Resolver - Superclass environments

This commit is contained in:
Emmanuel BENOîT 2023-01-16 07:26:34 +01:00
parent d6f03f1429
commit 1a39e40325

View file

@ -38,7 +38,7 @@ enum SymKind {
Variable, Variable,
Function, Function,
Class, Class,
This, Special,
} }
/// The type of a scope /// The type of a scope
@ -168,17 +168,17 @@ impl<'a> ResolverState<'a> {
} }
} }
/// Declare and define the "this" value for the current scope. /// Declare and define a special symbol (e.g. this) for the current scope.
fn define_this(&mut self) { fn define_special(&mut self, name: &str) {
assert!(!self.scopes.is_empty()); assert!(!self.scopes.is_empty());
let idx = self.scopes.len() - 1; let idx = self.scopes.len() - 1;
let scope = &mut self.scopes[idx]; let scope = &mut self.scopes[idx];
assert!(!scope.symbols.contains_key("this")); assert!(!scope.symbols.contains_key(name));
scope.symbols.insert( scope.symbols.insert(
"this".to_owned(), name.to_owned(),
SymInfo { SymInfo {
decl: None, decl: None,
kind: SymKind::This, kind: SymKind::Special,
state: SymState::Defined, state: SymState::Defined,
}, },
); );
@ -312,16 +312,30 @@ where
/// Process all method definitions in a class. /// Process all method definitions in a class.
fn resolve_class<'a, 'b>( fn resolve_class<'a, 'b>(
rs: &mut ResolverState<'a>, rs: &mut ResolverState<'a>,
has_superclass: bool,
methods: &'b [ClassMemberDecl], methods: &'b [ClassMemberDecl],
) -> ResolverResult ) -> ResolverResult
where where
'b: 'a, 'b: 'a,
{ {
let mut uniqueness = HashSet::new(); let mut uniqueness = HashSet::new();
rs.define_this(); let mut rc = |rs: &mut ResolverState<'a>| {
rs.define_special("this");
methods methods
.iter() .iter()
.try_for_each(|member| resolve_class_member(rs, member, &mut uniqueness)) .try_for_each(|member| resolve_class_member(rs, member, &mut uniqueness))
};
if has_superclass {
rs.with_scope(
|rs| {
rs.define_special("super");
rc(rs)
},
rs.current_type(),
)
} else {
rc(rs)
}
} }
/// Helper trait used to visit the various AST nodes with the resolver. /// Helper trait used to visit the various AST nodes with the resolver.
@ -387,7 +401,10 @@ impl VarResolver for StmtNode {
rs.resolve_use(superclass)?; rs.resolve_use(superclass)?;
} }
rs.define(&decl.name); rs.define(&decl.name);
rs.with_scope(|rs| resolve_class(rs, &decl.members), rs.current_type()) rs.with_scope(
|rs| resolve_class(rs, decl.superclass.is_some(), &decl.members),
rs.current_type(),
)
} }
StmtNode::If { StmtNode::If {