diff options
author | Vincent Ambo <mail@tazj.in> | 2021-01-17T09·13+0300 |
---|---|---|
committer | tazjin <mail@tazj.in> | 2021-01-17T09·34+0000 |
commit | f8b3e2a100fdb28cad24948703439d2964c31580 (patch) | |
tree | fdd7b13f4a359532f6acaa183d78e7d777f5c32d /users/tazjin/rlox/src/resolver.rs | |
parent | 052f8976bb3273d16fb0e1c4643de5abcaf0f135 (diff) |
refactor(tazjin/rlox): Move treewalk interpreter into subdirectory r/2120
Change-Id: I9163f75db5a1ff75e1b1f81bad78fd9d8ddb104a Reviewed-on: https://cl.tvl.fyi/c/depot/+/2409 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
Diffstat (limited to 'users/tazjin/rlox/src/resolver.rs')
-rw-r--r-- | users/tazjin/rlox/src/resolver.rs | 199 |
1 files changed, 0 insertions, 199 deletions
diff --git a/users/tazjin/rlox/src/resolver.rs b/users/tazjin/rlox/src/resolver.rs deleted file mode 100644 index 5e15d386c73f..000000000000 --- a/users/tazjin/rlox/src/resolver.rs +++ /dev/null @@ -1,199 +0,0 @@ -// Resolves variable access to their specific instances in the -// environment chain. -// -// https://craftinginterpreters.com/resolving-and-binding.html - -use std::collections::HashMap; -use std::rc::Rc; - -use crate::errors::{Error, ErrorKind}; -use crate::parser::{self, Expr, Statement}; -use crate::scanner::Token; - -#[derive(Default)] -struct Resolver<'a> { - scopes: Vec<HashMap<&'a str, bool>>, -} - -impl<'a> Resolver<'a> { - // AST traversal - fn resolve(&mut self, program: &'a mut parser::Block) -> Result<(), Error> { - self.begin_scope(); - for stmt in program { - self.resolve_stmt(stmt)?; - } - self.end_scope(); - - Ok(()) - } - - fn resolve_stmt(&mut self, stmt: &'a mut Statement) -> Result<(), Error> { - match stmt { - Statement::Expr(expr) => self.resolve_expr(expr), - Statement::Print(expr) => self.resolve_expr(expr), - Statement::Var(var) => self.resolve_var(var), - Statement::Return(ret) => self.resolve_expr(&mut ret.value), - Statement::Block(block) => self.resolve(block), - - Statement::If(if_stmt) => { - self.resolve_expr(&mut if_stmt.condition)?; - self.resolve_stmt(&mut if_stmt.then_branch)?; - - if let Some(branch) = if_stmt.else_branch.as_mut() { - self.resolve_stmt(branch)?; - } - - Ok(()) - } - - Statement::While(while_stmt) => { - self.resolve_expr(&mut while_stmt.condition)?; - self.resolve_stmt(&mut while_stmt.body) - } - - Statement::Function(func) => match Rc::get_mut(func) { - Some(func) => self.resolve_function(func), - // The resolver does not clone references, so unless - // the interpreter is called before the resolver this - // case should never happen. - None => { - return Err(Error { - line: 0, - kind: ErrorKind::InternalError( - "multiple function references before interpretation".into(), - ), - }) - } - }, - } - } - - fn resolve_var(&mut self, var: &'a mut parser::Var) -> Result<(), Error> { - self.declare(&var.name.lexeme); - - if let Some(init) = &mut var.initialiser { - self.resolve_expr(init)?; - } - - self.define(&var.name.lexeme); - - Ok(()) - } - - fn resolve_function(&mut self, func: &'a mut parser::Function) -> Result<(), Error> { - self.declare(&func.name.lexeme); - self.define(&func.name.lexeme); - - self.begin_scope(); - - for param in &func.params { - self.declare(¶m.lexeme); - self.define(¶m.lexeme); - } - - for stmt in &mut func.body { - self.resolve_stmt(stmt)?; - } - - self.end_scope(); - - Ok(()) - } - - fn resolve_expr(&mut self, expr: &'a mut Expr) -> Result<(), Error> { - match expr { - Expr::Variable(var) => self.resolve_variable(var), - Expr::Assign(assign) => self.resolve_assign(assign), - Expr::Grouping(grouping) => self.resolve_expr(&mut grouping.0), - Expr::Call(call) => self.resolve_call(call), - Expr::Literal(_) => Ok(()), - Expr::Unary(unary) => self.resolve_expr(&mut unary.right), - - Expr::Logical(log) => { - self.resolve_expr(&mut log.left)?; - self.resolve_expr(&mut log.right) - } - - Expr::Binary(binary) => { - self.resolve_expr(&mut binary.left)?; - self.resolve_expr(&mut binary.right) - } - } - } - - fn resolve_variable(&mut self, var: &'a mut parser::Variable) -> Result<(), Error> { - if let Some(scope) = self.scopes.last_mut() { - if let Some(false) = scope.get(var.name.lexeme.as_str()) { - return Err(Error { - line: var.name.line, - kind: ErrorKind::StaticError( - "can't read local variable in its own initialiser".into(), - ), - }); - } - } - - var.depth = self.resolve_local(&var.name); - Ok(()) - } - - fn resolve_assign(&mut self, assign: &'a mut parser::Assign) -> Result<(), Error> { - self.resolve_expr(&mut assign.value)?; - assign.depth = self.resolve_local(&assign.name); - Ok(()) - } - - fn resolve_local(&mut self, name: &'a Token) -> Option<usize> { - for (c, scope) in self.scopes.iter().rev().enumerate() { - if scope.contains_key(name.lexeme.as_str()) { - return Some(c); - } - } - - None - } - - fn resolve_call(&mut self, call: &'a mut parser::Call) -> Result<(), Error> { - self.resolve_expr(&mut call.callee)?; - - for arg in call.args.iter_mut() { - self.resolve_expr(arg)?; - } - - Ok(()) - } - - // Internal helpers - - fn declare(&mut self, name: &'a str) { - if let Some(scope) = self.scopes.last_mut() { - scope.insert(&name, false); - } - } - - fn define(&mut self, name: &'a str) { - if let Some(scope) = self.scopes.last_mut() { - scope.insert(&name, true); - } - } - - fn begin_scope(&mut self) { - self.scopes.push(Default::default()); - } - - fn end_scope(&mut self) { - self.scopes.pop(); - } -} - -pub fn resolve(globals: &[String], block: &mut parser::Block) -> Result<(), Error> { - let mut resolver: Resolver = Default::default(); - - // Scope for static globals only starts, never ends. - resolver.begin_scope(); - for global in globals { - resolver.define(global); - } - - resolver.resolve(block) -} |