Handle function definition before use

And some other ReducedAST - Evaluation niceties
This commit is contained in:
greg 2018-05-13 17:24:21 -07:00
parent 6d93c758a2
commit 8d6fea942f
3 changed files with 35 additions and 6 deletions

View File

@ -8,12 +8,17 @@ pub struct ReducedAST(pub Vec<Stmt>);
#[derive(Debug, Clone)]
pub enum Stmt {
PreBinding {
name: Rc<String>,
func: Func,
},
Binding {
name: Rc<String>,
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)
}
}

View File

@ -318,6 +318,12 @@ impl Expr {
impl<'a> State<'a> {
pub fn evaluate(&mut self, ast: ReducedAST, repl: bool) -> Vec<Result<String, String>> {
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<Option<Expr>> {
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<String>) -> EvalResult<Expr> {
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 {

View File

@ -1,5 +1,5 @@
println(a(4))
println(sua(4))
fn sua(x): Int {
x + 10