Skip to content

Commit 1fe8ffc

Browse files
small fixes and interpreter update
working on an iPad is difficult...
1 parent eb1798a commit 1fe8ffc

3 files changed

Lines changed: 31 additions & 8 deletions

File tree

src/interpreter.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::common::diagnostics::sinks::Diagnostics;
44
use crate::syntax::*;
55

66
pub struct Env<'a> {
7+
parent: Option<&'a Env<'a>>
78
vars: HashMap<&'a str, f64>,
89
}
910

@@ -18,7 +19,7 @@ pub fn interpret_program<'a>(src: &'a str) -> (HashMap<&'a str, f64>, Vec<EvalEr
1819
let mut diagnostics = Diagnostics::empty();
1920
let ast = parse(src, &mut diagnostics);
2021

21-
let mut env = Env { vars: HashMap::new() };
22+
let mut env = Env { parent: None, vars: HashMap::new() };
2223
let mut errors = Vec::new();
2324

2425
for stmt in &ast.stmts {
@@ -51,10 +52,21 @@ fn eval_expr<'a>(expr: &Expr<'a>, env: &Env<'a>) -> Result<f64, EvalError> {
5152
match &expr.kind {
5253
ExprKind::Number { value, .. } => Ok(*value),
5354

54-
ExprKind::Identifier { name } => env.vars
55-
.get(name)
56-
.copied()
57-
.ok_or(EvalError::UnknownVariable(name.to_string(), expr.span)),
55+
ExprKind::Identifier { name } => {
56+
let mut current = env;
57+
loop {
58+
let found = current.vars.get(name).copied();
59+
60+
if let Some(val) = found {
61+
return Ok(val)
62+
}
63+
64+
match current.parent {
65+
Some(p) => current = p,
66+
None => return Err(EvalError::UnknownVariable(name.to_string(), expr.span)),
67+
}
68+
}
69+
}
5870

5971
ExprKind::BinaryOp { op, left, right } => {
6072
let l = eval_expr(left, env)?;
@@ -68,6 +80,16 @@ fn eval_expr<'a>(expr: &Expr<'a>, env: &Env<'a>) -> Result<f64, EvalError> {
6880
}
6981
}
7082

83+
ExprKind::Block { stmts, tail_expr } => {
84+
let mut inner_env = Env { parent: Some(env), vars: HashMap::new() };
85+
86+
for stmt in stmts {
87+
eval_stmt(&mut inner_env, stmt)?;
88+
}
89+
90+
tail_expr.map(|expr| eval_expr(&inner_env, expr)).unwrap_or(Ok(0.0))
91+
}
92+
7193
ExprKind::Error => Err(EvalError::InvalidExpression(expr.span)),
7294
}
7395
}

src/semantics/resolver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ impl<'d, D: DiagnosticSink> Resolver<'d, D> {
230230
.map(|stmt| self.resolve_stmt(stmt))
231231
.collect();
232232

233-
let resolved_expr = tail_expr.map(|expr| self.resolve_expr(expr));
233+
let resolved_expr = tail_expr.map(|expr| Box::new(self.resolve_expr(*expr)));
234234

235235
self.current_scope = outer;
236236
r::ExprKind::Block { stmts: resolved_stmts, tail_expr: resolved_expr }

src/syntax/parser.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,9 @@ impl<'a, 'd, D: DiagnosticSink> Parser<'a, 'd, D> {
344344

345345
let tail_expr = match stmts.pop() {
346346
Some(Stmt { kind: StmtKind::Expr(expr), span }) if expr.span != span => Some(Box::new(expr)),
347-
other => { stmts.push(other); None }
348-
}
347+
Some(other) => { stmts.push(other); None }
348+
_ => None,
349+
};
349350

350351
Expr {
351352
kind: ExprKind::Block { stmts, tail_expr },

0 commit comments

Comments
 (0)