support code generation through () blocks

This commit is contained in:
2024-10-25 20:55:07 -04:00
parent d29fa2b9b0
commit a28dedb1ea
5 changed files with 654 additions and 475 deletions

View File

@@ -1,4 +1,3 @@
use std::cell::RefCell;
use crate::parser::ParseTree;
use crate::executor::{Executor, RuntimeError};
use crate::{Type, Object, Value};
@@ -16,11 +15,13 @@ impl Display for FunctionType {
}
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
pub struct Function {
pub(crate) name: Option<String>,
name: Option<String>,
t: FunctionType,
arg_names: Vec<String>,
globals: Option<HashMap<String, Arc<Mutex<Object>>>>,
locals: Option<HashMap<String, Arc<Mutex<Object>>>>,
arg_names: Option<Vec<String>>,
body: Box<ParseTree>,
}
@@ -29,7 +30,9 @@ impl Function {
Self {
name: None,
t,
arg_names,
globals: None,
locals: None,
arg_names: Some(arg_names),
body
}
}
@@ -38,11 +41,97 @@ impl Function {
Self {
name: Some(name.to_string()),
t,
arg_names,
globals: None,
locals: None,
arg_names: Some(arg_names),
body
}
}
pub(crate) fn _generated(t: FunctionType, body: Box<ParseTree>) -> Self {
Self {
name: None,
t,
globals: None,
locals: None,
arg_names: None,
body,
}
}
pub(crate) fn locals(mut self, locals: HashMap<String, Arc<Mutex<Object>>>) -> Self {
self.locals = Some(locals);
self
}
pub(crate) fn globals(mut self, globals: HashMap<String, Arc<Mutex<Object>>>) -> Self {
self.globals = Some(globals);
self
}
fn _replace_locals(mut self) -> Self {
fn replace_locals_(body: Box<ParseTree>, args: &Vec<String>) -> Box<ParseTree> {
match *body {
ParseTree::Operator(op, a) =>
Box::new(ParseTree::Operator(
op,
a.into_iter().map(|x| *replace_locals_(Box::new(x), args)).collect())),
ParseTree::Equ(name, body, scope) =>
Box::new(ParseTree::Equ(
name,
replace_locals_(body, args),
replace_locals_(scope, args))),
ParseTree::LazyEqu(name, body, scope) =>
Box::new(ParseTree::LazyEqu(
name,
replace_locals_(body, args),
replace_locals_(scope, args))),
ParseTree::FunctionDefinition(func, scope) =>
Box::new(ParseTree::FunctionDefinition(func, replace_locals_(scope, args))),
ParseTree::LambdaDefinition(_) => body,
ParseTree::FunctionCall(ref func, ref a) =>
if let Some(idx) = args.into_iter().position(|r| *r == *func) {
Box::new(ParseTree::_FunctionCallLocal(
idx,
a.into_iter().map(|x| *replace_locals_(Box::new(x.clone()), args)).collect()))
} else {
Box::new(ParseTree::FunctionCall(
func.clone(),
a.into_iter().map(|x| *replace_locals_(Box::new(x.clone()), args)).collect()))
}
ParseTree::Variable(ref var) => {
if let Some(idx) = args.into_iter().position(|r| *r == *var) {
Box::new(ParseTree::_Local(idx))
} else {
body
}
},
ParseTree::If(cond, branch) =>
Box::new(ParseTree::If(replace_locals_(cond, args),
replace_locals_(branch, args))),
ParseTree::IfElse(cond, t, f) =>
Box::new(ParseTree::IfElse(replace_locals_(cond, args),
replace_locals_(t, args),
replace_locals_(f, args))),
ParseTree::_FunctionCallLocal(_, _) => body,
ParseTree::_Local(_) => body,
ParseTree::Value(_) => body,
ParseTree::Nop => body,
ParseTree::Export(_) => body,
ParseTree::NonCall(ref var) => if let Some(idx) =
args.into_iter().position(|r| *r == *var) {
Box::new(ParseTree::_Local(idx))
} else {
body
}
ParseTree::GeneratedFunction(_) => todo!(),
}
}
self.body = replace_locals_(self.body, &self.arg_names.take().unwrap());
self
}
pub(crate) fn name(&self) -> Option<&str> {
self.name.as_ref().map(|x| x.as_str())
}
@@ -51,26 +140,25 @@ impl Function {
self.t.clone()
}
pub(crate) fn call(&mut self,
mut globals: HashMap<String, Arc<Mutex<Object>>>,
locals: HashMap<String, Arc<Mutex<Object>>>,
args: Vec<Object>) -> Result<Value, RuntimeError>
{
pub(crate) fn call(&mut self, args: Vec<Arc<Mutex<Object>>>) -> Result<Value, RuntimeError> {
let mut tree = vec![Ok(*self.body.clone())].into_iter();
let g = globals.clone();
let mut globals = self.globals.clone().unwrap();
let locals = self.locals.clone().unwrap();
let mut exec = Executor::new(&mut tree, &mut globals)
.locals(locals.clone());
for (obj, name) in std::iter::zip(args.into_iter(), self.arg_names.clone().into_iter()) {
exec = exec.add_local(name.clone(), Arc::new(Mutex::new(obj)));
if let Some(names) = self.arg_names.clone() {
for (obj, name) in std::iter::zip(args.clone().into_iter(), names.into_iter()) {
exec = exec.add_local(name, obj);
}
}
if let Some(name) = self.name().map(|x| x.to_string()) {
exec = exec.add_local(name, Arc::new(Mutex::new(Object::function(self.clone(), g, locals))));
if let Some(name) = self.clone().name().map(|x| x.to_string()) {
exec = exec.add_local(name, Arc::new(Mutex::new(Object::function(self.clone(), self.globals.clone().unwrap(), locals))));
}
exec.next().unwrap()
exec.exec(self.body.clone())
}
}