Initial commit

This commit is contained in:
JOLIMAITRE Matthieu 2022-05-25 08:09:48 +03:00
commit 70f1f90cc7
12 changed files with 1455 additions and 0 deletions

155
src/execution_tree/mod.rs Normal file
View file

@ -0,0 +1,155 @@
use std::collections::HashMap;
use crate::value::Value;
#[derive(Debug)]
pub struct Program {
pub main_scope_id: Id,
pub scopes: HashMap<Id, Scope>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Id(u64); // u64::MAX = 18_446_744_073_709_551_615
impl Id {
pub fn zero() -> Self {
Self(0)
}
pub fn next(self) -> Self {
let Self(id) = self;
Self(id + 1)
}
}
#[derive(Debug)]
pub struct Expr(Box<ExprInner>);
impl Expr {
pub fn inner(&self) -> &ExprInner {
&self.0
}
pub fn new_scope(scope_id: Id) -> Self {
Self(Box::new(ExprInner::Scope(scope_id)))
}
pub fn new_literal(literal: Literal) -> Self {
Self(Box::new(ExprInner::Literal(literal)))
}
pub fn new_variable_definition(variable_definition: VarDef) -> Self {
Self(Box::new(ExprInner::VarDef(variable_definition)))
}
pub fn new_variable_assignment(variable_assignment: VarAssign) -> Self {
Self(Box::new(ExprInner::VarAssign(variable_assignment)))
}
pub fn new_variable_call(variable_call: VarCall) -> Self {
Self(Box::new(ExprInner::VarCall(variable_call)))
}
pub fn new_function_definition(function_definition: FnDef) -> Self {
Self(Box::new(ExprInner::FnDef(function_definition)))
}
pub fn new_function_call(function_call: FnCall) -> Self {
Self(Box::new(ExprInner::FnCall(function_call)))
}
pub fn new_function_return(function_return: FnRet) -> Self {
Self(Box::new(ExprInner::FnRet(function_return)))
}
pub fn new_loop(loop_: Loop) -> Self {
Self(Box::new(ExprInner::Loop(loop_)))
}
pub fn new_loop_break(loop_break: LoopBr) -> Self {
Self(Box::new(ExprInner::LoopBr(loop_break)))
}
pub fn new_condition(condition: Cond) -> Self {
Self(Box::new(ExprInner::Cond(condition)))
}
}
#[derive(Debug)]
pub enum ExprInner {
Scope(Id),
Literal(Literal),
VarDef(VarDef),
VarAssign(VarAssign),
VarCall(VarCall),
FnDef(FnDef),
FnCall(FnCall),
FnRet(FnRet),
Loop(Loop),
LoopBr(LoopBr),
Cond(Cond),
}
#[derive(Debug)]
pub struct Scope {
pub scope_id: Id,
pub parent_scope_id: Option<Id>,
pub local_variables: Vec<Id>,
pub expressions: Vec<Expr>,
}
#[derive(Debug)]
pub struct Literal(pub Value);
#[derive(Debug)]
pub struct VarDef {
pub variable_id: Id,
pub value: Expr,
}
#[derive(Debug)]
pub struct VarAssign {
pub variable_id: Id,
pub value: Expr,
}
#[derive(Debug)]
pub struct VarCall {
pub variable_id: Id,
}
#[derive(Debug)]
pub struct FnDef {
pub parameter_ids: Vec<Id>,
pub body_scope_id: Id,
}
#[derive(Debug)]
pub struct FnCall {
pub variable_id: Id,
pub arguments: Vec<Expr>,
}
#[derive(Debug)]
pub struct FnRet {
pub value: Expr,
pub function_scope_id: Id,
}
#[derive(Debug)]
pub struct Loop {
pub body_scope_id: Id,
}
#[derive(Debug)]
pub struct LoopBr {
pub value: Expr,
pub loop_scope_id: Id,
}
#[derive(Debug)]
pub struct Cond {
pub condition: Expr,
pub arm_true: Expr,
pub arm_false: Option<Expr>,
}
pub mod parser;

View file

@ -0,0 +1,447 @@
use std::{collections::HashMap, rc::Rc, sync::Mutex};
use crate::{
execution_tree::{self, Id},
syntax_tree,
value::Value,
};
pub struct ParserBuilder {
prelude: Vec<(String, Value)>,
}
impl ParserBuilder {
fn new() -> Self {
let prelude = Vec::new();
Self { prelude }
}
pub fn prelude(&mut self, name: String, value: Value) {
self.prelude.push((name, value));
}
}
pub struct Parser {
scopes: HashMap<Id, execution_tree::Scope>,
}
impl Parser {
pub fn parse<F>(ast: syntax_tree::Program, builder: F) -> execution_tree::Program
where
F: FnOnce(&mut ParserBuilder),
{
let syntax_tree::Program { mut body } = ast;
let mut parser = Self {
scopes: HashMap::new(),
};
let parser_scope = ParserScope::new_root();
let mut parser_builder = ParserBuilder::new();
builder(&mut parser_builder);
for (name, value) in parser_builder.prelude.into_iter().rev() {
let value = syntax_tree::Expr::new_literal(value);
let expression = syntax_tree::Expr::new_variable_definition(name, value);
body.instructions.insert(0, expression);
}
let body_scope_id = parser.parse_ast_scope(body, &parser_scope);
let Self { scopes } = parser;
execution_tree::Program {
main_scope_id: body_scope_id,
scopes,
}
}
pub fn parse_ast_scope(
&mut self,
ast_scope: syntax_tree::Scope,
parser_scope: &ParserScope,
) -> execution_tree::Id {
let syntax_tree::Scope { instructions } = ast_scope;
let scope_id = parser_scope.get_current_id();
let parent_scope_id = parser_scope.get_parent_id();
let expressions = instructions
.into_iter()
.map(|expression| self.parse_expression(expression, &parser_scope))
.collect();
let local_variables = parser_scope.local_variable_ids();
let scope = execution_tree::Scope {
parent_scope_id,
scope_id,
expressions,
local_variables,
};
self.scopes.insert(scope_id, scope);
scope_id
}
pub fn parse_expression(
&mut self,
expression: syntax_tree::Expr,
parser_scope: &ParserScope,
) -> execution_tree::Expr {
let inner = expression.into_inner();
match inner {
syntax_tree::ExprInner::Scope(scope) => {
let parser_scope = parser_scope.make_child_common();
let scope = self.parse_ast_scope(scope, &parser_scope);
execution_tree::Expr::new_scope(scope)
}
syntax_tree::ExprInner::Literal(literal) => {
let literal = self.parse_literal(literal);
execution_tree::Expr::new_literal(literal)
}
syntax_tree::ExprInner::VarDef(variable_definition) => {
let variable_definition =
self.parse_variable_definition(variable_definition, parser_scope);
execution_tree::Expr::new_variable_definition(variable_definition)
}
syntax_tree::ExprInner::VarAssign(variable_assignment) => {
let variable_assignment =
self.parse_variable_assignment(variable_assignment, parser_scope);
execution_tree::Expr::new_variable_assignment(variable_assignment)
}
syntax_tree::ExprInner::VarCall(variable_call) => {
let variable_call = self.parse_variable_call(variable_call, parser_scope);
execution_tree::Expr::new_variable_call(variable_call)
}
syntax_tree::ExprInner::FnDef(function_definition) => {
let function_definition =
self.parse_function_definition(function_definition, parser_scope);
execution_tree::Expr::new_function_definition(function_definition)
}
syntax_tree::ExprInner::FnCall(function_call) => {
let function_call = self.parse_function_call(function_call, parser_scope);
execution_tree::Expr::new_function_call(function_call)
}
syntax_tree::ExprInner::FnRet(function_return) => {
let function_return = self.parse_function_return(function_return, parser_scope);
execution_tree::Expr::new_function_return(function_return)
}
syntax_tree::ExprInner::Loop(loop_) => {
let loop_ = self.parse_loop(loop_, parser_scope);
execution_tree::Expr::new_loop(loop_)
}
syntax_tree::ExprInner::LoopBr(loop_break) => {
let loop_break = self.parse_loop_break(loop_break, parser_scope);
execution_tree::Expr::new_loop_break(loop_break)
}
syntax_tree::ExprInner::Cond(condition) => {
let condition = self.parse_condition(condition, parser_scope);
execution_tree::Expr::new_condition(condition)
}
}
}
pub fn parse_literal(&mut self, literal: syntax_tree::Literal) -> execution_tree::Literal {
let syntax_tree::Literal(value) = literal;
execution_tree::Literal(value)
}
pub fn parse_variable_definition(
&mut self,
variable_definition: syntax_tree::VarDef,
parser_scope: &ParserScope,
) -> execution_tree::VarDef {
let syntax_tree::VarDef { name, value } = variable_definition;
let value = self.parse_expression(value, parser_scope);
let variable_id = parser_scope.add_name(name);
execution_tree::VarDef { value, variable_id }
}
pub fn parse_variable_assignment(
&mut self,
variable_assignment: syntax_tree::VarAssign,
parser_scope: &ParserScope,
) -> execution_tree::VarAssign {
let syntax_tree::VarAssign { name, value } = variable_assignment;
let value = self.parse_expression(value, parser_scope);
let variable_id = parser_scope
.get_variable_id(&name)
.expect("assignment to undefined variable");
execution_tree::VarAssign { value, variable_id }
}
pub fn parse_variable_call(
&mut self,
variable_call: syntax_tree::VarCall,
parser_scope: &ParserScope,
) -> execution_tree::VarCall {
let syntax_tree::VarCall { name } = variable_call;
let variable_id = parser_scope
.get_variable_id(&name)
.expect("call of undefined variable");
execution_tree::VarCall { variable_id }
}
pub fn parse_function_definition(
&mut self,
function_definition: syntax_tree::FnDef,
parser_scope: &ParserScope,
) -> execution_tree::FnDef {
let syntax_tree::FnDef {
body,
parameter_names,
} = function_definition;
let parser_scope = parser_scope.make_child_common();
let parameter_ids = parameter_names
.into_iter()
.map(|name| parser_scope.add_name(name))
.collect();
let body_scope_id = self.parse_ast_scope(body, &parser_scope);
execution_tree::FnDef {
body_scope_id,
parameter_ids,
}
}
pub fn parse_function_call(
&mut self,
function_call: syntax_tree::FnCall,
parser_scope: &ParserScope,
) -> execution_tree::FnCall {
let syntax_tree::FnCall { name, arguments } = function_call;
let variable_id = parser_scope
.get_variable_id(&name)
.expect("call of undeclared function");
let parameters = arguments
.into_iter()
.map(|argument| self.parse_expression(argument, parser_scope))
.collect();
execution_tree::FnCall {
arguments: parameters,
variable_id,
}
}
pub fn parse_function_return(
&mut self,
function_return: syntax_tree::FnRet,
parser_scope: &ParserScope,
) -> execution_tree::FnRet {
let syntax_tree::FnRet { value } = function_return;
let value = self.parse_expression(value, parser_scope);
let function_scope_id = parser_scope
.get_current_function_id()
.expect("returning outside a function");
execution_tree::FnRet {
value,
function_scope_id,
}
}
pub fn parse_loop(
&mut self,
loop_: syntax_tree::Loop,
parser_scope: &ParserScope,
) -> execution_tree::Loop {
let syntax_tree::Loop { body } = loop_;
let parser_scope = parser_scope.make_child_loop();
let body_scope_id = self.parse_ast_scope(body, &parser_scope);
execution_tree::Loop { body_scope_id }
}
pub fn parse_loop_break(
&mut self,
loop_break: syntax_tree::LoopBr,
parser_scope: &ParserScope,
) -> execution_tree::LoopBr {
let syntax_tree::LoopBr { value } = loop_break;
let value = self.parse_expression(value, parser_scope);
let loop_scope_id = parser_scope
.get_current_loop_id()
.expect("breaking outside a loop");
execution_tree::LoopBr {
value,
loop_scope_id,
}
}
pub fn parse_condition(
&mut self,
condition: syntax_tree::Cond,
parser_scope: &ParserScope,
) -> execution_tree::Cond {
let syntax_tree::Cond {
condition,
arm_true,
arm_false,
} = condition;
let condition = self.parse_expression(condition, parser_scope);
let arm_true = self.parse_expression(arm_true, parser_scope);
let arm_false = arm_false.map(|arm_false| self.parse_expression(arm_false, parser_scope));
execution_tree::Cond {
condition,
arm_true,
arm_false,
}
}
}
#[derive(Debug, Clone)]
struct ParserScopeVariables {
parent_scope: Option<Rc<Mutex<ParserScopeVariables>>>,
local_variables: HashMap<String, Id>,
}
impl ParserScopeVariables {
pub fn get_id(&self, name: &str) -> Option<Id> {
self.get_id_in_local(name)
.or_else(|| self.get_id_in_parents(name))
}
fn get_id_in_local(&self, name: &str) -> Option<Id> {
self.local_variables.get(name).cloned()
}
fn get_id_in_parents(&self, name: &str) -> Option<Id> {
self.parent_scope
.as_ref()
.and_then(|parent| parent.lock().unwrap().get_id(name))
}
fn local_variable_ids(&self) -> Vec<Id> {
self.local_variables.values().cloned().collect()
}
fn add_name(&mut self, name: String, id: Id) {
let _dropped = self.local_variables.insert(name, id);
}
}
/// Clonable, shareable.
#[derive(Debug, Clone)]
pub struct ParserScope {
variables: Rc<Mutex<ParserScopeVariables>>,
next_global_id: Rc<Mutex<Id>>,
current_id: Id,
parent_id: Option<Id>,
current_function_scope_id: Option<Id>,
current_loop_scope_id: Option<Id>,
}
impl ParserScope {
pub fn new_root() -> Self {
let current_id = Id::zero();
let next_global_id = current_id.next();
let variables = ParserScopeVariables {
local_variables: HashMap::new(),
parent_scope: None,
};
Self {
parent_id: None,
current_id,
next_global_id: Rc::new(Mutex::new(next_global_id)),
variables: Rc::new(Mutex::new(variables)),
current_function_scope_id: None,
current_loop_scope_id: None,
}
}
pub fn make_child_common(&self) -> Self {
let variables = ParserScopeVariables {
local_variables: HashMap::new(),
parent_scope: Some(self.variables.clone()),
};
Self {
parent_id: Some(self.get_current_id()),
next_global_id: self.next_global_id.clone(),
variables: Rc::new(Mutex::new(variables)),
current_id: self.request_new_id(),
current_function_scope_id: self.get_current_function_id(),
current_loop_scope_id: self.get_current_loop_id(),
}
}
pub fn make_child_function(&self) -> Self {
let variables = ParserScopeVariables {
local_variables: HashMap::new(),
parent_scope: Some(self.variables.clone()),
};
let current_id = self.request_new_id();
Self {
parent_id: Some(self.get_current_id()),
next_global_id: self.next_global_id.clone(),
variables: Rc::new(Mutex::new(variables)),
current_id,
current_function_scope_id: Some(current_id.clone()),
current_loop_scope_id: None,
}
}
pub fn make_child_loop(&self) -> Self {
let variables = ParserScopeVariables {
local_variables: HashMap::new(),
parent_scope: Some(self.variables.clone()),
};
let current_id = self.request_new_id();
Self {
parent_id: Some(self.get_current_id()),
next_global_id: self.next_global_id.clone(),
variables: Rc::new(Mutex::new(variables)),
current_id,
current_function_scope_id: self.get_current_function_id(),
current_loop_scope_id: Some(current_id.clone()),
}
}
pub fn get_current_id(&self) -> Id {
self.current_id.clone()
}
pub fn get_current_function_id(&self) -> Option<Id> {
self.current_function_scope_id.clone()
}
pub fn get_current_loop_id(&self) -> Option<Id> {
self.current_loop_scope_id.clone()
}
pub fn get_parent_id(&self) -> Option<Id> {
self.parent_id.clone()
}
pub fn get_variable_id(&self, name: &str) -> Option<Id> {
self.variables.lock().unwrap().get_id(name)
}
fn request_new_id(&self) -> Id {
let mut next_id_ref = self.next_global_id.lock().unwrap();
let id = *next_id_ref;
*next_id_ref = id.next();
id
}
pub fn add_name(&self, name: String) -> Id {
let new_id = self.request_new_id();
self.variables.lock().unwrap().add_name(name, new_id);
new_id
}
pub fn add_anonymous(&self) -> Id {
self.request_new_id()
}
pub fn local_variable_ids(&self) -> Vec<Id> {
self.variables.lock().unwrap().local_variable_ids()
}
}

39
src/main.rs Normal file
View file

@ -0,0 +1,39 @@
pub mod execution_tree;
pub mod prelude;
pub mod runtime;
pub mod syntax_tree;
pub mod value;
fn main() {
println!("Hello, world!");
}
#[test]
fn it_works() {
use crate::execution_tree::parser::Parser;
use crate::prelude::std_prelude;
use crate::runtime::Runtime;
use crate::syntax_tree::*;
let ast = Program {
body: Scope::new(vec![
Expr::new_variable_definition("a", Expr::new_literal(3.0)),
Expr::new_variable_assignment("a", Expr::new_literal(6.0)),
Expr::new_variable_definition(
"my_print",
Expr::new_function_definition(
vec!["to_print"],
Scope::new(vec![
Expr::new_variable_definition("a", Expr::new_variable_call("to_print")),
Expr::new_function_call("print", vec![Expr::new_variable_call("a")]),
]),
),
),
Expr::new_function_call("my_print", vec!["hello, PROUT".into()]),
Expr::new_function_call("print", vec![Expr::new_variable_call("a")]),
]),
};
let exec = Parser::parse(ast, |builder| std_prelude(builder));
println!("\n\n\n-- running: --");
let _result = Runtime::new().execute(&exec);
}

14
src/prelude.rs Normal file
View file

@ -0,0 +1,14 @@
use crate::{
execution_tree::parser::ParserBuilder,
value::{function::Function, Value},
};
pub fn std_prelude(builder: &mut ParserBuilder) {
builder.prelude("print".into(), Function::new_native(1, print).into())
}
fn print(args: Vec<Value>) -> Value {
let to_print = args.get(0).unwrap();
println!("{to_print:?}");
Value::Bool(true)
}

434
src/runtime.rs Normal file
View file

@ -0,0 +1,434 @@
use std::collections::HashMap;
use crate::{
execution_tree::{
Cond, Expr, ExprInner, FnCall, FnDef, FnRet, Id, Literal, Loop, LoopBr, Program, Scope,
VarAssign, VarCall, VarDef,
},
value::{
function::{
ConstructedFunctionExecutor, Function, FunctionExecutor, NativeFunctionExecutor,
},
Value,
},
};
pub struct FrameBuilder {
variables: HashMap<Id, Value>,
}
impl FrameBuilder {
fn new() -> Self {
let variables = HashMap::new();
Self { variables }
}
pub fn variable(&mut self, variable_id: &Id, default: Value) {
self.variables.insert(variable_id.clone(), default);
}
}
pub struct Frame {
scope_id: Id,
variables: HashMap<Id, Value>,
}
impl Frame {
/// Puts all variable of that scope in the new frame
pub fn new<F>(scope: &Scope, builder: F) -> Self
where
F: FnOnce(&mut FrameBuilder),
{
let Scope {
scope_id,
local_variables,
..
} = scope;
let mut frame_builder = FrameBuilder::new();
for variable in local_variables {
frame_builder.variable(variable, Value::None);
}
builder(&mut frame_builder);
let FrameBuilder { variables } = frame_builder;
let scope_id = scope_id.clone();
Self {
scope_id,
variables,
}
}
}
pub struct Stack {
frames: Vec<Frame>,
}
impl Stack {
pub fn new() -> Self {
let frames = Vec::new();
Self { frames }
}
pub fn push_frame(&mut self, frame: Frame) {
self.frames.push(frame);
}
pub fn pop_frame(&mut self) {
let _dropped = self.frames.pop();
}
pub fn get(&self, variable_id: &Id) -> Option<&Value> {
self.frames.iter().rev().find_map(|frame| {
frame
.variables
.iter()
.find(|(id, _value)| **id == *variable_id)
.map(|(_id, value)| value)
})
}
pub fn get_mut(&mut self, variable_id: &Id) -> Option<&mut Value> {
self.frames.iter_mut().rev().find_map(|frame| {
frame
.variables
.iter_mut()
.find(|(id, _value)| **id == *variable_id)
.map(|(_id, value)| value)
})
}
}
pub struct ShortCircuit {
value: Value,
destination_scope_id: Id,
}
pub enum ExecReturn {
Value(Value),
ShortCircuit(ShortCircuit),
}
impl ExecReturn {
pub fn new_value(value: Value) -> Self {
Self::Value(value)
}
pub fn new_short_circuit(value: Value, destination_scope_id: Id) -> Self {
Self::ShortCircuit(ShortCircuit {
destination_scope_id,
value,
})
}
pub fn into_value(self) -> Option<Value> {
if let Self::Value(value) = self {
Some(value)
} else {
None
}
}
pub fn into_shortcircuit(self) -> Option<ShortCircuit> {
if let Self::ShortCircuit(short_circuit) = self {
Some(short_circuit)
} else {
None
}
}
}
impl Into<ExecReturn> for Value {
fn into(self) -> ExecReturn {
ExecReturn::new_value(self)
}
}
pub struct Runtime {
stack: Stack,
}
impl Runtime {
pub fn new() -> Self {
let stack = Stack::new();
Self { stack }
}
pub fn execute(&mut self, program: &Program) -> Value {
self.execute_scope(&program.main_scope_id, program, |_| ())
.into_value()
.unwrap()
}
pub fn execute_scope<F>(
&mut self,
scope_id: &Id,
program: &Program,
frame_builder: F,
) -> ExecReturn
where
F: FnOnce(&mut FrameBuilder),
{
let scope = program.scopes.get(&scope_id).unwrap();
let Scope {
parent_scope_id: _,
expressions,
..
} = scope;
let frame = Frame::new(scope, |builder| frame_builder(builder));
self.stack.push_frame(frame);
let mut last_expression = Value::None;
for expression in expressions {
let returned = self.execute_expression(expression, program);
match returned {
ExecReturn::ShortCircuit(short_circuit) => {
self.stack.pop_frame();
return ExecReturn::ShortCircuit(short_circuit);
}
ExecReturn::Value(value) => {
last_expression = value;
}
}
}
self.stack.pop_frame();
last_expression.into()
}
pub fn execute_expression(&mut self, expression: &Expr, program: &Program) -> ExecReturn {
match expression.inner() {
ExprInner::Scope(scope_id) => self.execute_scope(scope_id, program, |_| ()),
ExprInner::Literal(literal) => self.execute_literal(literal),
ExprInner::VarDef(variable_definition) => {
self.execute_variable_definition(variable_definition, program)
}
ExprInner::VarAssign(variable_assignment) => {
self.execute_variable_assignment(variable_assignment, program)
}
ExprInner::VarCall(variable_call) => self.execute_variable_call(variable_call),
ExprInner::FnDef(function_definition) => {
self.execute_function_definition(function_definition)
}
ExprInner::FnCall(function_call) => {
self.execute_function_call(function_call, program).into()
}
ExprInner::FnRet(function_return) => {
self.execute_function_return(function_return, program)
}
ExprInner::Loop(loop_) => self.execute_loop(loop_, program),
ExprInner::LoopBr(loop_break) => self.execute_loop_break(loop_break, program),
ExprInner::Cond(condition) => self.execute_condition(condition, program),
}
}
pub fn execute_literal(&self, literal: &Literal) -> ExecReturn {
let Literal(value) = literal;
ExecReturn::new_value(value.clone())
}
pub fn execute_variable_definition(
&mut self,
variable_definition: &VarDef,
program: &Program,
) -> ExecReturn {
let VarDef { variable_id, value } = variable_definition;
let value = match self.execute_expression(value, program) {
ExecReturn::ShortCircuit(short_circuit) => {
return ExecReturn::ShortCircuit(short_circuit);
}
ExecReturn::Value(value) => value,
};
let variable = self.stack.get_mut(variable_id).unwrap();
*variable = value.clone();
value.into()
}
pub fn execute_variable_assignment(
&mut self,
variable_assignment: &VarAssign,
program: &Program,
) -> ExecReturn {
let VarAssign { variable_id, value } = variable_assignment;
let value = match self.execute_expression(value, program) {
ExecReturn::Value(value) => value,
ExecReturn::ShortCircuit(short_circuit) => {
return ExecReturn::ShortCircuit(short_circuit);
}
};
let variable = self.stack.get_mut(variable_id).unwrap();
*variable = value.clone();
value.into()
}
pub fn execute_variable_call(&mut self, variable_call: &VarCall) -> ExecReturn {
let VarCall { variable_id } = variable_call;
let variable = self.stack.get(variable_id).unwrap();
variable.clone().into()
}
pub fn execute_function_definition(&mut self, function_definition: &FnDef) -> ExecReturn {
let FnDef {
parameter_ids: argument_ids,
body_scope_id,
} = function_definition;
let value = Function::new_constructed(argument_ids.clone(), body_scope_id.clone());
let value = Value::Function(value);
value.into()
}
pub fn execute_function_call(
&mut self,
function_call: &FnCall,
program: &Program,
) -> ExecReturn {
let FnCall {
variable_id,
arguments,
} = function_call;
let mut collector = Vec::new();
for argument in arguments {
match self.execute_expression(argument, program) {
ExecReturn::Value(value) => collector.push(value),
ExecReturn::ShortCircuit(short_circuit) => {
return ExecReturn::ShortCircuit(short_circuit)
}
}
}
let arguments = collector;
let function = self
.stack
.get(variable_id)
.unwrap()
.as_function()
.expect("calling a non-function variable")
.clone();
match function.executor() {
FunctionExecutor::Constructed(executor) => self
.execute_constructed_function(arguments, executor, program)
.into(),
FunctionExecutor::Native(executor) => {
self.execute_native_function(arguments, executor).into()
}
}
}
pub fn execute_constructed_function(
&mut self,
arguments: Vec<Value>,
executor: &ConstructedFunctionExecutor,
program: &Program,
) -> Value {
let ConstructedFunctionExecutor {
parameter_ids,
body_scope_id,
} = executor;
let returned = self.execute_scope(body_scope_id, program, |builder| {
for (id, argument) in parameter_ids.iter().zip(arguments.into_iter()) {
builder.variable(id, argument)
}
});
match returned {
ExecReturn::Value(value) => value,
ExecReturn::ShortCircuit(ShortCircuit {
value,
destination_scope_id: _,
}) => value,
}
}
pub fn execute_native_function(
&mut self,
arguments: Vec<Value>,
executor: &NativeFunctionExecutor,
) -> Value {
(executor.closure)(arguments)
}
pub fn execute_function_return(
&mut self,
function_return: &FnRet,
program: &Program,
) -> ExecReturn {
let FnRet {
value,
function_scope_id,
} = function_return;
let value = match self.execute_expression(value, program) {
ExecReturn::Value(value) => value,
ExecReturn::ShortCircuit(ShortCircuit {
value,
destination_scope_id: _,
}) => value,
};
ExecReturn::new_short_circuit(value, function_scope_id.clone())
}
pub fn execute_loop(&mut self, loop_: &Loop, program: &Program) -> ExecReturn {
let Loop { body_scope_id } = loop_;
loop {
let value = self.execute_scope(body_scope_id, program, |_| ());
match value {
ExecReturn::ShortCircuit(ShortCircuit {
value,
destination_scope_id,
}) if destination_scope_id == *body_scope_id => return value.into(),
ExecReturn::ShortCircuit(short_circuit) => {
return ExecReturn::ShortCircuit(short_circuit)
}
_ => (),
}
}
}
pub fn execute_loop_break(&mut self, loop_break: &LoopBr, program: &Program) -> ExecReturn {
let LoopBr {
value,
loop_scope_id,
} = loop_break;
let value = match self.execute_expression(value, program) {
ExecReturn::Value(value) => value,
ExecReturn::ShortCircuit(short_circuit) => {
return ExecReturn::ShortCircuit(short_circuit)
}
};
ExecReturn::new_short_circuit(value, loop_scope_id.clone())
}
pub fn execute_condition(&mut self, condition: &Cond, program: &Program) -> ExecReturn {
let Cond {
condition,
arm_true,
arm_false,
} = condition;
let value = match self.execute_expression(condition, program) {
ExecReturn::Value(value) => value,
ExecReturn::ShortCircuit(short_circuit) => {
return ExecReturn::ShortCircuit(short_circuit)
}
};
if let Value::Bool(boolean) = value {
if boolean {
self.execute_expression(arm_true, program)
} else {
arm_false
.as_ref()
.map(|arm_false| self.execute_expression(arm_false, program))
.unwrap_or(Value::Bool(false).into())
}
} else {
panic!("non-boolean in condition");
}
}
}

43
src/sequencing.rs Normal file
View file

@ -0,0 +1,43 @@
/*
use std::collections::HashMap;
use crate::{abstract_tree::Id, value::Value};
pub struct Program {
statements: Vec<Statement>,
state: State,
}
pub enum Statement {
Label(Label),
VarAssign(VarAssign),
FnCall(FnCall),
Branch(Branch),
}
pub struct VarAssign {
variable:
}
pub struct FnCall {}
pub struct State {
variables: HashMap<Id, Vec<Value>>,
next_instruction_index: usize,
}
impl Statement {
pub fn run(&self, state: &mut State) {}
}
pub mod parser {
pub struct Parser;
impl Parser {
pub fn parse() {
//
}
}
}
*/

166
src/syntax_tree.rs Normal file
View file

@ -0,0 +1,166 @@
use crate::value::Value;
#[derive(Debug)]
pub struct Program {
pub body: Scope,
}
#[derive(Debug)]
pub struct Expr(pub Box<ExprInner>);
impl Expr {
pub fn inner(&self) -> &ExprInner {
let Self(inner) = self;
inner
}
pub fn into_inner(self) -> ExprInner {
let Self(inner) = self;
*inner
}
pub fn new_scope(instructions: Vec<Expr>) -> Self {
Self(Box::new(ExprInner::Scope(Scope { instructions })))
}
pub fn new_literal<V: Into<Value>>(value: V) -> Self {
Self(Box::new(ExprInner::Literal(Literal(value.into()))))
}
pub fn new_variable_definition<S: ToString>(name: S, value: Expr) -> Self {
let name = name.to_string();
Self(Box::new(ExprInner::VarDef(VarDef { name, value })))
}
pub fn new_variable_assignment<S: ToString>(name: S, value: Expr) -> Self {
let name = name.to_string();
Self(Box::new(ExprInner::VarAssign(VarAssign { name, value })))
}
pub fn new_variable_call<S: ToString>(name: S) -> Self {
let name = name.to_string();
Self(Box::new(ExprInner::VarCall(VarCall { name })))
}
pub fn new_function_definition<S: ToString>(parameter_names: Vec<S>, body: Scope) -> Self {
let parameter_names = parameter_names.into_iter().map(|s| s.to_string()).collect();
Self(Box::new(ExprInner::FnDef(FnDef {
body,
parameter_names,
})))
}
pub fn new_function_call<S: ToString>(name: S, arguments: Vec<Expr>) -> Self {
let name = name.to_string();
Self(Box::new(ExprInner::FnCall(FnCall { name, arguments })))
}
pub fn new_function_return(value: Expr) -> Self {
Self(Box::new(ExprInner::FnRet(FnRet { value })))
}
pub fn new_loop(body: Scope) -> Self {
Self(Box::new(ExprInner::Loop(Loop { body })))
}
pub fn new_loop_break(value: Expr) -> Self {
Self(Box::new(ExprInner::LoopBr(LoopBr { value })))
}
pub fn new_condition(condition: Expr, arm_true: Expr, arm_false: Option<Expr>) -> Self {
Self(Box::new(ExprInner::Cond(Cond {
condition,
arm_true,
arm_false,
})))
}
}
impl<T> From<T> for Expr
where
T: Into<Value>,
{
fn from(input: T) -> Self {
Self::new_literal(input.into())
}
}
#[derive(Debug)]
pub enum ExprInner {
Scope(Scope),
Literal(Literal),
VarDef(VarDef),
VarAssign(VarAssign),
VarCall(VarCall),
FnDef(FnDef),
FnCall(FnCall),
FnRet(FnRet),
Loop(Loop),
LoopBr(LoopBr),
Cond(Cond),
}
#[derive(Debug)]
pub struct Scope {
pub instructions: Vec<Expr>,
}
impl Scope {
pub fn new(instructions: Vec<Expr>) -> Self {
Self { instructions }
}
}
#[derive(Debug)]
pub struct Literal(pub Value);
#[derive(Debug)]
pub struct VarDef {
pub name: String,
pub value: Expr,
}
#[derive(Debug)]
pub struct VarAssign {
pub name: String,
pub value: Expr,
}
#[derive(Debug)]
pub struct VarCall {
pub name: String,
}
#[derive(Debug)]
pub struct FnDef {
pub parameter_names: Vec<String>,
pub body: Scope,
}
#[derive(Debug)]
pub struct FnCall {
pub name: String,
pub arguments: Vec<Expr>,
}
#[derive(Debug)]
pub struct FnRet {
pub value: Expr,
}
#[derive(Debug)]
pub struct Loop {
pub body: Scope,
}
#[derive(Debug)]
pub struct LoopBr {
pub value: Expr,
}
#[derive(Debug)]
pub struct Cond {
pub condition: Expr,
pub arm_true: Expr,
pub arm_false: Option<Expr>,
}

114
src/value.rs Normal file
View file

@ -0,0 +1,114 @@
use std::collections::HashMap;
use self::function::Function;
pub mod function {
use crate::execution_tree::{Expr, Id};
use super::Value;
#[derive(Debug, Clone)]
pub struct ConstructedFunctionExecutor {
pub parameter_ids: Vec<Id>,
pub body_scope_id: Id,
}
#[derive(Debug, Clone)]
pub struct NativeFunctionExecutor {
pub closure: fn(Vec<Value>) -> Value,
}
#[derive(Debug, Clone)]
pub enum FunctionExecutor {
Constructed(ConstructedFunctionExecutor),
Native(NativeFunctionExecutor),
}
#[derive(Debug, Clone)]
pub struct Function {
pub argument_count: usize,
pub executor: FunctionExecutor,
}
impl Function {
pub fn new_constructed(argument_ids: Vec<Id>, body_scope_id: Id) -> Self {
let argument_count = argument_ids.len();
let executor = FunctionExecutor::Constructed(ConstructedFunctionExecutor {
parameter_ids: argument_ids,
body_scope_id,
});
Self {
argument_count,
executor,
}
}
pub fn new_native(argument_count: usize, closure: fn(Vec<Value>) -> Value) -> Self {
let executor = FunctionExecutor::Native(NativeFunctionExecutor { closure });
Self {
argument_count,
executor,
}
}
pub fn executor(&self) -> &FunctionExecutor {
&self.executor
}
}
impl Into<Value> for Function {
fn into(self) -> Value {
Value::Function(self)
}
}
}
#[derive(Debug, Clone)]
pub enum Value {
None,
Bool(bool),
Number(f64),
String(String),
Object(HashMap<String, Value>),
Function(Function),
}
impl Value {
pub fn as_function(&self) -> Option<&Function> {
match self {
Self::Function(function) => Some(function),
_ => None,
}
}
}
impl From<bool> for Value {
fn from(value: bool) -> Self {
Self::Bool(value)
}
}
impl From<f64> for Value {
fn from(value: f64) -> Self {
Self::Number(value)
}
}
impl From<String> for Value {
fn from(value: String) -> Self {
Self::String(value)
}
}
impl From<&str> for Value {
fn from(value: &str) -> Self {
value.to_string().into()
}
}
impl<T> From<Option<T>> for Value
where
T: Into<Value>,
{
fn from(value: Option<T>) -> Self {
value.map_or(Value::None, |v| v.into())
}
}