From 8d6fea942f691297c80b1aa03efbc17533f7248b Mon Sep 17 00:00:00 2001 From: greg Date: Sun, 13 May 2018 17:24:21 -0700 Subject: [PATCH] Handle function definition before use And some other ReducedAST - Evaluation niceties --- schala-lang/src/ast_reducing.rs | 16 +++++++++++----- schala-lang/src/eval.rs | 23 +++++++++++++++++++++++ source_files/schala/test.schala | 2 +- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/schala-lang/src/ast_reducing.rs b/schala-lang/src/ast_reducing.rs index 4ccf8d6..21f1a00 100644 --- a/schala-lang/src/ast_reducing.rs +++ b/schala-lang/src/ast_reducing.rs @@ -8,12 +8,17 @@ pub struct ReducedAST(pub Vec); #[derive(Debug, Clone)] pub enum Stmt { + PreBinding { + name: Rc, + func: Func, + }, Binding { name: Rc, constant: bool, expr: Expr, }, Expr(Expr), + Noop, } #[derive(Debug, Clone)] @@ -111,17 +116,18 @@ impl Expression { impl Declaration { fn reduce(&self) -> Stmt { use self::Declaration::*; + use ::parsing::Signature; match self { Binding {name, constant, expr } => Stmt::Binding { name: name.clone(), constant: *constant, expr: expr.reduce() }, - FuncDecl(::parsing::Signature { name, params, .. }, statements) => Stmt::Binding { + FuncDecl(Signature { name, params, .. }, statements) => Stmt::PreBinding { name: name.clone(), - constant: true, - expr: Expr::Func(Func::UserDefined { - name: None, + func: Func::UserDefined { + name: Some(name.clone()), params: params.iter().map(|param| param.0.clone()).collect(), body: statements.iter().map(|stmt| stmt.reduce()).collect(), - }) + } }, + TypeDecl(_,_) => Stmt::Noop, _ => Stmt::Expr(Expr::UnimplementedSigilValue) } } diff --git a/schala-lang/src/eval.rs b/schala-lang/src/eval.rs index 6273e84..f9dd7c3 100644 --- a/schala-lang/src/eval.rs +++ b/schala-lang/src/eval.rs @@ -318,6 +318,12 @@ impl Expr { impl<'a> State<'a> { pub fn evaluate(&mut self, ast: ReducedAST, repl: bool) -> Vec> { let mut acc = vec![]; + + // handle prebindings + for statement in ast.0.iter() { + self.prebinding(statement); + } + for statement in ast.0 { match self.statement(statement) { Ok(Some(ref output)) if repl => acc.push(Ok(output.to_repl())), @@ -331,6 +337,20 @@ impl<'a> State<'a> { acc } + fn prebinding(&mut self, stmt: &Stmt) { + match stmt { + Stmt::PreBinding { name, func } => { + let v_entry = ValueEntry::Binding { constant: true, val: Expr::Func(func.clone()) }; + self.values.insert(name.clone(), v_entry); + }, + Stmt::Expr(_expr) => { + //TODO have this support things like nested function defs + + }, + _ => () + } + } + fn statement(&mut self, stmt: Stmt) -> EvalResult> { match stmt { Stmt::Binding { name, constant, expr } => { @@ -339,6 +359,7 @@ impl<'a> State<'a> { Ok(None) }, Stmt::Expr(expr) => Ok(Some(self.expression(expr)?)), + Stmt::PreBinding {..} | Stmt::Noop => Ok(None), } } @@ -471,6 +492,8 @@ impl<'a> State<'a> { fn value(&mut self, name: Rc) -> EvalResult { use self::ValueEntry::*; + //TODO add a layer of indirection here to talk to the symbol table first, and only then look up + //in the values table match self.values.lookup(&name) { None => return Err(format!("Value {} not found", *name)), Some(lookup) => match lookup { diff --git a/source_files/schala/test.schala b/source_files/schala/test.schala index eab6109..0780446 100644 --- a/source_files/schala/test.schala +++ b/source_files/schala/test.schala @@ -1,5 +1,5 @@ -println(a(4)) +println(sua(4)) fn sua(x): Int { x + 10