Skip to content

Commit

Permalink
Report errors on invalid super usage in resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
froth committed Apr 18, 2024
1 parent 02d9594 commit d3e5e4c
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 12 deletions.
28 changes: 17 additions & 11 deletions src/resolver/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::sync::Arc;

use miette::{NamedSource, SourceSpan};

use super::{resolution_error::ResolutionError, Resolver, Result};
use super::{resolution_error::ResolutionError, ClassType, Resolver, Result};
use crate::ast::{
expr::{Expr, ExprType::*},
name::NameExpr,
Expand Down Expand Up @@ -73,15 +73,21 @@ impl Resolver {
location: SourceSpan,
src: &Arc<NamedSource<String>>,
) -> Result<()> {
// if self.current_class.is_none() {
// Err(ResolutionError::InvalidThis {
// src: src.clone(),
// location,
// })
// } else {
let name_expr = NameExpr::super_name(location, src.clone());
self.resolve_local(&name_expr);
Ok(())
// }
use ResolutionError::*;
match self.current_class {
None => Err(SuperOutsideClass {
src: src.clone(),
location,
}),
Some(ClassType::Class) => Err(SuperWithoutSuperclass {
src: src.clone(),
location,
}),
Some(ClassType::Subclass) => {
let name_expr = NameExpr::super_name(location, src.clone());
self.resolve_local(&name_expr);
Ok(())
}
}
}
}
1 change: 1 addition & 0 deletions src/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ enum FunctionType {
#[derive(Debug)]
enum ClassType {
Class,
Subclass,
}

type Result<T> = std::result::Result<T, ResolutionError>;
Expand Down
16 changes: 16 additions & 0 deletions src/resolver/resolution_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,20 @@ pub enum ResolutionError {
#[label("here")]
location: SourceSpan,
},

#[error("Can't use 'super' outside of a class.")]
SuperOutsideClass {
#[source_code]
src: Arc<NamedSource<String>>,
#[label("here")]
location: SourceSpan,
},

#[error("Can't use 'super' in a class with no superclass")]
SuperWithoutSuperclass {
#[source_code]
src: Arc<NamedSource<String>>,
#[label("here")]
location: SourceSpan,
},
}
7 changes: 6 additions & 1 deletion src/resolver/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,12 @@ impl Resolver {
methods: &[Function],
superclass: &Option<NameExpr>,
) -> Result<()> {
let enclosing_class = std::mem::replace(&mut self.current_class, Some(ClassType::Class));
let class_type = if superclass.is_some() {
ClassType::Subclass
} else {
ClassType::Class
};
let enclosing_class = std::mem::replace(&mut self.current_class, Some(class_type));
self.declare(name);
self.define(name);

Expand Down
22 changes: 22 additions & 0 deletions tests/resolver_errors/super_outside_of_class.lox
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error
super.a();
----
----
{
"causes": [],
"filename": "tests/resolver_errors/super_outside_of_class.lox",
"labels": [
{
"label": "here",
"span": {
"length": 7,
"offset": 0
}
}
],
"message": "Can't use 'super' outside of a class.",
"related": [],
"severity": "error"
}
----
---- (no newline)
26 changes: 26 additions & 0 deletions tests/resolver_errors/super_without_superclass.lox
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
error
class A {
method() {
super.x();
}
}
----
----
{
"causes": [],
"filename": "tests/resolver_errors/super_without_superclass.lox",
"labels": [
{
"label": "here",
"span": {
"length": 7,
"offset": 33
}
}
],
"message": "Can't use 'super' in a class with no superclass",
"related": [],
"severity": "error"
}
----
---- (no newline)

0 comments on commit d3e5e4c

Please sign in to comment.