Handle function definition before use
And some other ReducedAST - Evaluation niceties
This commit is contained in:
parent
6d93c758a2
commit
8d6fea942f
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
println(a(4))
|
||||
println(sua(4))
|
||||
|
||||
fn sua(x): Int {
|
||||
x + 10
|
||||
|
Loading…
Reference in New Issue
Block a user