diff --git a/sample-initial.amo b/sample-initial.amo index 474c32c..b919038 100644 --- a/sample-initial.amo +++ b/sample-initial.amo @@ -1,5 +1,31 @@ main: Int -main = 1 + distance_squared 4 3 +main = nth_prime 77 -distance_squared: Int, Int -> Int -distance_squared a b = a * a + b * b +nth_prime: Int -> Int +nth_prime n = + if n == 1 + then 2 + else nth_prime_helper (n - 1) 3 + +nth_prime_helper: Int, Int -> Int +nth_prime_helper remaining_primes next_to_try = + if is_prime next_to_try + then + if remaining_primes < 2 + then next_to_try + else nth_prime_helper (remaining_primes - 1) (next_to_try + 2) + else nth_prime_helper remaining_primes (next_to_try + 2) + +is_prime: Int -> Int +is_prime x = + if x % 2 == 0 + then 0 + else is_prime_helper x 3 + +is_prime_helper: Int, Int -> Int +is_prime_helper x try = + if try * try > x + then 1 + else if x % try == 0 + then 0 + else is_prime_helper x (try + 2) diff --git a/src/ir/expr.rs b/src/ir/expr.rs index c35f658..8a9f531 100644 --- a/src/ir/expr.rs +++ b/src/ir/expr.rs @@ -252,19 +252,25 @@ pub fn get_last_ident(exprs: &LinkedList) -> Option { pub fn evaluate(exprs: LinkedList, bindings: &ValueBindings) -> evaluation::Result { let bindings = bindings.nested_scope(); - let (all_bindings, last_ident) = exprs.into_iter() - .filter(Expr::isnt_noop) - .try_fold( - (bindings, None), - |(bindings, _last_ident), expr| { - let last_value = expr.evaluate(&bindings)?; - Ok((bindings.bind(&expr.identifier, last_value.clone()), Some(expr.identifier))) - })?; - last_ident.ok_or(EvaluateError::EvaluatingZeroLengthExpr) - .and_then( - |ident| - all_bindings.lookup(&ident) - .cloned() - .ok_or(EvaluateError::UndefinedValue(ident)) - ) + 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 { + let (all_bindings, last_ident) = exprs.into_iter() + .filter(Expr::isnt_noop) + .try_fold( + (bindings, None), + |(bindings, _last_ident), expr| { + let last_value = expr.evaluate(&bindings)?; + Ok((bindings.bind(&expr.identifier, last_value.clone()), Some(expr.identifier))) + })?; + last_ident.ok_or(EvaluateError::EvaluatingZeroLengthExpr) + .and_then( + |ident| + all_bindings.lookup(&ident) + .cloned() + .ok_or(EvaluateError::UndefinedValue(ident)) + ) + } }