@@ -4,6 +4,7 @@ use crate::common::diagnostics::sinks::Diagnostics;
44use crate :: syntax:: * ;
55
66pub 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}
0 commit comments