diff --git a/sample-initial.amo b/sample-initial.amo index b919038..a8e3a18 100644 --- a/sample-initial.amo +++ b/sample-initial.amo @@ -1,5 +1,8 @@ +cool_number: Into +cool_number = 1312 + main: Int -main = nth_prime 77 +main = nth_prime cool_number nth_prime: Int -> Int nth_prime n = diff --git a/src/ir/expr.rs b/src/ir/expr.rs index 8e42848..3e7f2e6 100644 --- a/src/ir/expr.rs +++ b/src/ir/expr.rs @@ -183,7 +183,17 @@ impl Expr { } Operation::VariantUnion => todo!(), Operation::FunctionType => todo!(), - Operation::NoOp => ExprEvalResult::Succeeded(Value::Int(0)), + Operation::NoOp => { + // Look up the value, if it's a zero-arg function, evaluate it + let apparent_value = + bindings.lookup(&self.identifier) + .ok_or_else(|| EvaluateError::UndefinedValue(self.identifier.clone()))?; + match apparent_value { + Value::Function(args, exprs) if args.is_empty() => + ExprEvalResult::EvaluateThis(exprs, LinkedList::new()), + val => ExprEvalResult::Succeeded(val.clone()), + } + } Operation::Conditional(cases) => { let mut arguments = arguments; let value = @@ -280,11 +290,7 @@ pub fn get_last_ident(exprs: &LinkedList) -> Option { } pub fn evaluate(mut exprs: LinkedList, mut bindings: ValueBindings) -> evaluation::Result { loop { return - if exprs.iter().all(|e| !e.isnt_noop()) { - bindings.lookup(&exprs.back().ok_or(EvaluateError::EvaluatingZeroLengthExpr)?.identifier) - .ok_or_else(|| EvaluateError::UndefinedValue(exprs.back().unwrap().identifier.clone())) - .cloned() - } else if exprs.len() == 1 { + if exprs.len() == 1 { let instr = exprs.back().unwrap(); let res = instr.evaluate(&bindings); match res { @@ -303,25 +309,19 @@ pub fn evaluate(mut exprs: LinkedList, mut bindings: ValueBindings) -> eva } } else { let first_instruction = exprs.pop_front().ok_or(EvaluateError::EvaluatingZeroLengthExpr)?; - if first_instruction.isnt_noop() { - let res = first_instruction.evaluate(&bindings); - let res_value = match res { - ExprEvalResult::Succeeded(v) => v, - ExprEvalResult::EvaluateThis(code, new_bindings) => { - let local_scope = bindings.nested_scope() - .bind_all(new_bindings); - evaluate(code.clone(), local_scope)? - }, - ExprEvalResult::Failed(e) => return Err(e), - }; + let res = first_instruction.evaluate(&bindings); + let res_value = match res { + ExprEvalResult::Succeeded(v) => v, + ExprEvalResult::EvaluateThis(code, new_bindings) => { + let local_scope = bindings.nested_scope() + .bind_all(new_bindings); + evaluate(code.clone(), local_scope)? + }, + ExprEvalResult::Failed(e) => return Err(e), + }; - exprs = exprs; - bindings = bindings.bind(&first_instruction.identifier, res_value); - continue; // Tail-recursive "call" - } else { - exprs = exprs; - bindings = bindings; - continue; // Tail-recursive "call" - } + exprs = exprs; + bindings = bindings.bind(&first_instruction.identifier, res_value); + continue; // Tail-recursive "call" } }}