From 7cabca2987d33fff13913fbeb50e6b52ac05a972 Mon Sep 17 00:00:00 2001 From: greg Date: Tue, 15 Oct 2019 23:59:37 -0700 Subject: [PATCH] Got all tests passing with visitor scope-resolver --- schala-lang/language/src/ast/walker.rs | 23 +- schala-lang/language/src/eval/test.rs | 2 +- schala-lang/language/src/scope_resolution.rs | 213 +++++-------------- 3 files changed, 70 insertions(+), 168 deletions(-) diff --git a/schala-lang/language/src/ast/walker.rs b/schala-lang/language/src/ast/walker.rs index d54cc05..a17406d 100644 --- a/schala-lang/language/src/ast/walker.rs +++ b/schala-lang/language/src/ast/walker.rs @@ -48,6 +48,7 @@ fn declaration(v: &mut V, decl: &Declaration) { Binding { name, constant, type_anno, expr } => { v.binding(name, *constant, type_anno.as_ref(), expr); v.type_annotation(type_anno.as_ref()); + v.expression(&expr); expression(v, &expr); }, Impl { type_name, interface_name, block } => { @@ -76,6 +77,7 @@ fn expression(v: &mut V, expression: &Expression) { fn call(v: &mut V, f: &Expression, args: &Vec) { v.expression(f); + expression(v, f); for arg in args.iter() { v.invocation_argument(arg); invocation_argument(v, arg); @@ -114,6 +116,7 @@ fn named_struct(v: &mut V, n: &QualifiedName, fields: &Vec<(Rc(v: &mut V, params: &Vec, type_anno: Option<&TypeIdentifier>, body: &Block) { for param in params { v.formal_param(param); + formal_param(v, param); } v.type_annotation(type_anno); v.block(body); @@ -121,7 +124,10 @@ fn lambda(v: &mut V, params: &Vec, type_anno: Option } fn formal_param(v: &mut V, param: &FormalParam) { - param.default.as_ref().map(|p| v.expression(p)); + param.default.as_ref().map(|p| { + v.expression(p); + expression(v, p); + }); v.type_annotation(param.anno.as_ref()); } @@ -220,6 +226,12 @@ fn condition_arm(v: &mut V, arm: &ConditionArm) { }, _ => () } + arm.guard.as_ref().map(|guard| { + v.expression(guard); + expression(v, guard); + }); + v.block(&arm.body); + walk_block(v, &arm.body); } fn walk_pattern(v: &mut V, pat: &Pattern) { @@ -231,18 +243,23 @@ fn walk_pattern(v: &mut V, pat: &Pattern) { walk_pattern(v, pat); } }, - TupleStruct(_, patterns) => { + TupleStruct(qualified_name, patterns) => { + v.qualified_name(qualified_name); for pat in patterns { v.pattern(pat); walk_pattern(v, pat); } }, - Record(_, name_and_patterns) => { + Record(qualified_name, name_and_patterns) => { + v.qualified_name(qualified_name); for (_, pat) in name_and_patterns { v.pattern(pat); walk_pattern(v, pat); } }, + VarOrName(qualified_name) => { + v.qualified_name(qualified_name); + }, _ => () } } diff --git a/schala-lang/language/src/eval/test.rs b/schala-lang/language/src/eval/test.rs index 526ca75..5d18933 100644 --- a/schala-lang/language/src/eval/test.rs +++ b/schala-lang/language/src/eval/test.rs @@ -69,7 +69,7 @@ fn scopes() { test_in_fresh_env!(scope_ok, "10"); let scope_ok = r#" let a = 20 - fn haha() { + fn queque() { let a = 10 a } diff --git a/schala-lang/language/src/scope_resolution.rs b/schala-lang/language/src/scope_resolution.rs index a42d25b..d3d7f64 100644 --- a/schala-lang/language/src/scope_resolution.rs +++ b/schala-lang/language/src/scope_resolution.rs @@ -10,26 +10,71 @@ type NameScopeStack<'t> = ScopeStack<'t, Rc, FQSNPrefix>; pub struct ScopeResolver<'a> { symbol_table: &'a mut SymbolTable, name_scope_stack: ScopeStack<'a, Rc, FQSNPrefix>, + errors: Vec<()>, } impl<'a> ASTVisitor for ScopeResolver<'a> { fn ast(&mut self, _ast: &AST) { println!("VISITING AST!!!"); } + + fn import(&mut self, import_spec: &ImportSpecifier) { + let ImportSpecifier { ref path_components, ref imported_names, .. } = &import_spec; + match imported_names { + ImportedNames::All => unimplemented!(), + ImportedNames::LastOfPath => { + let name = path_components.last().unwrap(); //TODO handle better + let fqsn_prefix = path_components.iter().map(|c| ScopeSegment { + name: c.clone(), kind: ScopeSegmentKind::Type + }).collect(); + self.name_scope_stack.insert(name.clone(), fqsn_prefix); + } + ImportedNames::List(ref names) => { + let fqsn_prefix: FQSNPrefix = path_components.iter().map(|c| ScopeSegment { + name: c.clone(), kind: ScopeSegmentKind::Type + }).collect(); + for name in names.iter() { + self.name_scope_stack.insert(name.clone(), fqsn_prefix.clone()); + } + } + }; + } + + fn qualified_name(&mut self, qualified_name: &QualifiedName) { + let fqsn = self.lookup_name_in_scope(&qualified_name); + let ref id = qualified_name.id; + self.symbol_table.map_id_to_fqsn(id, fqsn); + } + + fn named_struct(&mut self, name: &QualifiedName, _fields: &Vec<(Rc, Expression)>) { + let ref id = name.id; + let fqsn = self.lookup_name_in_scope(&name); + self.symbol_table.map_id_to_fqsn(id, fqsn); + } + + fn pattern(&mut self, pat: &Pattern) { + use Pattern::*; + match pat { + Ignored => (), + TuplePattern(patterns) => (), + Literal(_) => (), + TupleStruct(name, _) => self.qualified_name_in_pattern(name), + Record(name, _) => self.qualified_name_in_pattern(name), + VarOrName(name) => self.qualified_name_in_pattern(name), + }; + } } impl<'a> ScopeResolver<'a> { pub fn new(symbol_table: &'a mut SymbolTable) -> ScopeResolver { let name_scope_stack = ScopeStack::new(None); - ScopeResolver { symbol_table, name_scope_stack } + ScopeResolver { symbol_table, name_scope_stack, errors: vec![] } } pub fn resolve(&mut self, ast: &mut AST) -> Result<(), String> { walk_ast(self, ast); - self.block(&mut ast.statements)?; - Ok(()) + Ok(()) //TODO make this error meaningful } - //TODO this is incomplete fn lookup_name_in_scope(&self, sym_name: &QualifiedName) -> FullyQualifiedSymbolName { let QualifiedName { components: vec, .. } = sym_name; @@ -45,166 +90,6 @@ impl<'a> ScopeResolver<'a> { FullyQualifiedSymbolName(new_vec) } - fn import(&mut self, import_spec: &ImportSpecifier) -> Result<(), String> { - let ImportSpecifier { ref path_components, ref imported_names, .. } = &import_spec; - match imported_names { - ImportedNames::All => unimplemented!(), - ImportedNames::LastOfPath => { - let name = path_components.last().unwrap(); //TODO handle better - let fqsn_prefix = path_components.iter().map(|c| ScopeSegment { - name: c.clone(), kind: ScopeSegmentKind::Type - }).collect(); - self.name_scope_stack.insert(name.clone(), fqsn_prefix); - () - } - ImportedNames::List(ref names) => { - let fqsn_prefix: FQSNPrefix = path_components.iter().map(|c| ScopeSegment { - name: c.clone(), kind: ScopeSegmentKind::Type - }).collect(); - for name in names.iter() { - self.name_scope_stack.insert(name.clone(), fqsn_prefix.clone()); - } - } - }; - Ok(()) - } - - fn decl(&mut self, decl: &Declaration) -> Result<(), String> { - use Declaration::*; - match decl { - Binding { expr, .. } => self.expr(expr), - FuncDecl(_, block) => self.block(block), - _ => Ok(()), - } - } - fn block(&mut self, block: &Block) -> Result<(), String> { - for statement in block.iter() { - match statement.kind { - StatementKind::Declaration(ref decl) => self.decl(decl), - StatementKind::Expression(ref expr) => self.expr(expr), - StatementKind::Import(ref spec) => self.import(spec), - }?; - } - Ok(()) - } - - fn expr(&mut self, expr: &Expression) -> Result<(), String> { - use ExpressionKind::*; - match &expr.kind { - ExpressionKind::Value(qualified_name) => { - let fqsn = self.lookup_name_in_scope(&qualified_name); - let ref id = qualified_name.id; - self.symbol_table.map_id_to_fqsn(id, fqsn); - }, - NamedStruct { name, .. } => { - let ref id = name.id; - let fqsn = self.lookup_name_in_scope(&name); - self.symbol_table.map_id_to_fqsn(id, fqsn); - }, - BinExp(_, ref lhs, ref rhs) => { - self.expr(lhs)?; - self.expr(rhs)?; - }, - PrefixExp(_, ref arg) => { - self.expr(arg)?; - }, - TupleLiteral(exprs) => { - for expr in exprs.iter() { - self.expr(expr)?; - } - }, - Call { f, arguments } => { - self.expr(&f)?; - for arg in arguments.iter() { - self.invoc(arg)?; - } - }, - IfExpression { discriminator, body } => { - match discriminator { - None => (), - Some(ref expr) => self.expr(expr)? - }; - self.if_expr_body(body)?; - }, - Lambda { params, body, .. } => { - self.block(&body)?; - for param in params.iter() { - if let Some(ref expr) = param.default { - self.expr(expr)?; - } - } - }, - _ => () - }; - Ok(()) - } - - fn invoc(&mut self, invoc: &InvocationArgument) -> Result<(), String> { - use InvocationArgument::*; - match invoc { - Positional(expr) => self.expr(expr), - Keyword { expr, .. } => self.expr(expr), - _ => Ok(()) - } - } - - fn if_expr_body(&mut self, body: &IfExpressionBody) -> Result<(), String> { - use IfExpressionBody::*; - match body { - SimpleConditional { then_case, else_case } => { - self.block(then_case)?; - if let Some(block) = else_case { - self.block(block)?; - } - }, - SimplePatternMatch { pattern, then_case, else_case } => { - self.pattern(pattern)?; - self.block(then_case)?; - if let Some(block) = else_case { - self.block(block)?; - } - }, - CondList(conditions) => { - for arm in conditions.iter() { - if let Condition::Pattern(ref pat) = arm.condition { - self.pattern(pat)?; - } - self.block(&arm.body)?; - } - }, - } - Ok(()) - } - - fn pattern(&mut self, pat: &Pattern) -> Result<(), String> { - use Pattern::*; - match pat { - Ignored => (), - TuplePattern(patterns) => { - for pat in patterns { - self.pattern(pat)?; - } - }, - Literal(_) => (), - TupleStruct(name, patterns) => { - self.qualified_name_in_pattern(name); - for pat in patterns { - self.pattern(pat)?; - } - }, - Record(name, key_patterns) => { - self.qualified_name_in_pattern(name); - for (_, pat) in key_patterns { - self.pattern(pat)?; - } - }, - VarOrName(name) => { - self.qualified_name_in_pattern(name); - }, - }; - Ok(()) - } - /// this might be a variable or a pattern. if a variable, set to none fn qualified_name_in_pattern(&mut self, qualified_name: &QualifiedName) { let ref id = qualified_name.id;