Resolver - Refactored entering/exiting scopes
This commit is contained in:
parent
6dceae73a0
commit
8d65c288a3
1 changed files with 15 additions and 23 deletions
|
@ -55,14 +55,16 @@ struct ResolverState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResolverState {
|
impl ResolverState {
|
||||||
/// Enter a new scope.
|
/// Execute some function with a new scope. The scope will be disposed
|
||||||
fn begin_scope(&mut self) {
|
/// of after the function has been executed.
|
||||||
|
fn with_scope<F>(&mut self, f: F) -> ResolverResult
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut Self) -> ResolverResult,
|
||||||
|
{
|
||||||
self.scopes.push(HashMap::new());
|
self.scopes.push(HashMap::new());
|
||||||
}
|
let result = f(self);
|
||||||
|
|
||||||
/// End the current scope.
|
|
||||||
fn end_scope(&mut self) {
|
|
||||||
self.scopes.pop();
|
self.scopes.pop();
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to declare a symbol. If the scope already contains a declaration
|
/// Try to declare a symbol. If the scope already contains a declaration
|
||||||
|
@ -156,18 +158,13 @@ fn resolve_function(
|
||||||
params: &[Token],
|
params: &[Token],
|
||||||
body: &Vec<ast::StmtNode>,
|
body: &Vec<ast::StmtNode>,
|
||||||
) -> ResolverResult {
|
) -> ResolverResult {
|
||||||
rs.begin_scope();
|
|
||||||
for param in params {
|
for param in params {
|
||||||
rs.declare(param, SymKind::Variable)?;
|
rs.declare(param, SymKind::Variable)?;
|
||||||
rs.define(param);
|
rs.define(param);
|
||||||
}
|
}
|
||||||
// Unlike the original Lox, function arguments and function bodies do
|
// Unlike the original Lox, function arguments and function bodies do
|
||||||
// not use the same environment.
|
// not use the same environment.
|
||||||
rs.begin_scope();
|
rs.with_scope(|rs| body.resolve(rs))
|
||||||
let result = body.resolve(rs);
|
|
||||||
rs.end_scope();
|
|
||||||
rs.end_scope();
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper trait used to visit the various AST nodes with the resolver.
|
/// Helper trait used to visit the various AST nodes with the resolver.
|
||||||
|
@ -194,12 +191,7 @@ impl VarResolver for Vec<ast::StmtNode> {
|
||||||
impl VarResolver for ast::StmtNode {
|
impl VarResolver for ast::StmtNode {
|
||||||
fn resolve(&self, rs: &mut ResolverState) -> ResolverResult {
|
fn resolve(&self, rs: &mut ResolverState) -> ResolverResult {
|
||||||
match self {
|
match self {
|
||||||
ast::StmtNode::Block(stmts) => {
|
ast::StmtNode::Block(stmts) => rs.with_scope(|rs| stmts.resolve(rs)),
|
||||||
rs.begin_scope();
|
|
||||||
let result = stmts.resolve(rs);
|
|
||||||
rs.end_scope();
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
ast::StmtNode::VarDecl(name, None) => {
|
ast::StmtNode::VarDecl(name, None) => {
|
||||||
rs.declare(name, SymKind::Variable)?;
|
rs.declare(name, SymKind::Variable)?;
|
||||||
|
@ -215,7 +207,7 @@ impl VarResolver for ast::StmtNode {
|
||||||
ast::StmtNode::FunDecl { name, params, body } => {
|
ast::StmtNode::FunDecl { name, params, body } => {
|
||||||
rs.declare(name, SymKind::Function)?;
|
rs.declare(name, SymKind::Function)?;
|
||||||
rs.define(name);
|
rs.define(name);
|
||||||
resolve_function(rs, params, body)
|
rs.with_scope(|rs| resolve_function(rs, params, body))
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::StmtNode::If {
|
ast::StmtNode::If {
|
||||||
|
@ -270,16 +262,16 @@ impl VarResolver for ast::StmtNode {
|
||||||
impl VarResolver for ast::ExprNode {
|
impl VarResolver for ast::ExprNode {
|
||||||
fn resolve(&self, rs: &mut ResolverState) -> ResolverResult {
|
fn resolve(&self, rs: &mut ResolverState) -> ResolverResult {
|
||||||
match self {
|
match self {
|
||||||
ast::ExprNode::Variable { name, id } => {
|
ast::ExprNode::Variable { name, id } => rs.resolve_local(id, name, false),
|
||||||
rs.resolve_local(id, name, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
ast::ExprNode::Assignment { name, value, id } => {
|
ast::ExprNode::Assignment { name, value, id } => {
|
||||||
value.resolve(rs)?;
|
value.resolve(rs)?;
|
||||||
rs.resolve_local(id, name, true)
|
rs.resolve_local(id, name, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprNode::Lambda { params, body } => resolve_function(rs, params, body),
|
ast::ExprNode::Lambda { params, body } => {
|
||||||
|
rs.with_scope(|rs| resolve_function(rs, params, body))
|
||||||
|
}
|
||||||
|
|
||||||
ast::ExprNode::Logical {
|
ast::ExprNode::Logical {
|
||||||
left,
|
left,
|
||||||
|
|
Loading…
Reference in a new issue