Skip to content

Commit

Permalink
Report an error in resolver when trying to return from top-level
Browse files Browse the repository at this point in the history
  • Loading branch information
froth committed Mar 15, 2024
1 parent 9b2065a commit 4f65ea3
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 6 deletions.
28 changes: 25 additions & 3 deletions src/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ use self::resolution_error::ResolutionError;
pub struct Resolver {
locals: HashMap<NameExpr, usize>,
scopes: Vec<HashMap<Name, bool>>,
current_function: Option<FunctionType>,
}

#[derive(Debug)]
enum FunctionType {
Function,
}

type Result<T> = std::result::Result<T, ResolutionError>;
Expand Down Expand Up @@ -45,9 +51,18 @@ impl Resolver {
} => {
self.declare(name);
self.define(name);
self.resolve_function(parameters, body)
self.resolve_function(parameters, body, FunctionType::Function)
}
Return(expr) => {
if self.current_function.is_none() {
Err(ResolutionError::InvalidReturn {
src: statement.src.clone(),
location: statement.location,
})
} else {
expr.iter().try_for_each(|e| self.resolve_expr(e))
}
}
Return(expr) => expr.iter().try_for_each(|e| self.resolve_expr(e)),
Block(statements) => self.resolve_block(statements),
If {
condition,
Expand All @@ -72,14 +87,21 @@ impl Resolver {
Ok(())
}

fn resolve_function(&mut self, parameters: &[Name], body: &[Stmt]) -> Result<()> {
fn resolve_function(
&mut self,
parameters: &[Name],
body: &[Stmt],
function_type: FunctionType,
) -> Result<()> {
let enclosing_function = std::mem::replace(&mut self.current_function, Some(function_type));
self.begin_scope();
parameters.iter().for_each(|p| {
self.declare(p);
self.define(p);
});
self.resolve_statements(body)?;
self.end_scope();
self.current_function = enclosing_function;
Ok(())
}

Expand Down
7 changes: 7 additions & 0 deletions src/resolver/resolution_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,11 @@ pub enum ResolutionError {
#[label("here")]
location: SourceSpan,
},
#[error("Can't return from top-level code")]
InvalidReturn {
#[source_code]
src: Arc<NamedSource<String>>,
#[label("here")]
location: SourceSpan,
},
}
2 changes: 1 addition & 1 deletion tests/closure.lox
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ counter();
counter();
----
1
2
2
2 changes: 1 addition & 1 deletion tests/resolver_errors/recursive_var.lox
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ var a = 1;
"severity": "error"
}
----
---- (no newline)
---- (no newline)
22 changes: 22 additions & 0 deletions tests/resolver_errors/return_from_top.lox
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error
return 1;
----
----
{
"causes": [],
"filename": "tests/resolver_errors/return_from_top.lox",
"labels": [
{
"label": "here",
"span": {
"length": 9,
"offset": 0
}
}
],
"message": "Can't return from top-level code",
"related": [],
"severity": "error"
}
----
---- (no newline)
2 changes: 1 addition & 1 deletion tests/static_scope.lox
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ var a = "global";
}
----
global
global
global

0 comments on commit 4f65ea3

Please sign in to comment.