From 7277510a7202e8d6fc3ac29fa0cd3091d893fffe Mon Sep 17 00:00:00 2001 From: James Harton Date: Thu, 14 Feb 2019 19:08:40 +1300 Subject: [PATCH] Scope stuff. --- huia-compiler/src/context.rs | 26 ++++++++++++++------------ huia-compiler/src/scope.rs | 8 ++++---- huia-parser/src/ast/constant.rs | 4 ++-- huia-parser/src/ast/term.rs | 9 +++++++++ huia-parser/src/grammar.pest | 3 ++- 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/huia-compiler/src/context.rs b/huia-compiler/src/context.rs index 878b709..3108050 100644 --- a/huia-compiler/src/context.rs +++ b/huia-compiler/src/context.rs @@ -3,16 +3,17 @@ use crate::symbol::Symbol; pub struct Context { current_pos: usize, + globals: Scope, scope_stack: Vec, } impl Context { pub fn globals(&self) -> &Scope { - &self.scope_stack[0] + &self.globals } pub fn globals_mut(&mut self) -> &mut Scope { - &mut self.scope_stack[0] + &mut self.globals } pub fn scope(&self) -> &Scope { @@ -39,12 +40,12 @@ impl Context { } } - pub fn find_symbol(&self, identifier: &str) -> Option<&Symbol> { + pub fn reference(&self, identifier: &str) -> Option<&Symbol> { let mut pos = self.scope_stack.len(); while pos > 0 { pos -= 1; if self.scope_stack[pos].has_symbol(identifier) { - return self.scope_stack[pos].get(identifier); + return self.scope_stack[pos].reference(identifier); } } None @@ -55,6 +56,7 @@ impl Default for Context { fn default() -> Context { Context { current_pos: 0, + globals: Scope::default(), scope_stack: vec![Scope::default()], } } @@ -70,7 +72,7 @@ mod test { let symbol = Symbol::r#type("MartyMcFly"); assert!(context.globals().is_empty()); - context.globals_mut().add(symbol); + context.globals_mut().define(symbol); assert!(!context.globals().is_empty()); } @@ -80,7 +82,7 @@ mod test { let symbol = Symbol::local("marty"); assert!(context.scope().is_empty()); - context.scope_mut().add(symbol); + context.scope_mut().define(symbol); assert!(!context.scope().is_empty()); } @@ -90,10 +92,10 @@ mod test { let symbol0 = Symbol::local("marty"); let symbol1 = Symbol::local("doc"); - context.scope_mut().add(symbol0); + context.scope_mut().define(symbol0); assert!(context.scope().has_symbol("marty")); context.push_scope(); - context.scope_mut().add(symbol1); + context.scope_mut().define(symbol1); assert!(context.scope().has_symbol("doc")); assert!(!context.scope().has_symbol("marty")); context.pop_scope(); @@ -102,14 +104,14 @@ mod test { } #[test] - fn find_symbol() { + fn reference() { let mut context = Context::default(); let symbol0 = Symbol::local("marty"); let symbol1 = Symbol::local("doc"); - context.scope_mut().add(symbol0); + context.scope_mut().define(symbol0); context.push_scope(); - context.scope_mut().add(symbol1); - assert!(context.find_symbol("marty").is_some()); + context.scope_mut().define(symbol1); + assert!(context.reference("marty").is_some()); } } diff --git a/huia-compiler/src/scope.rs b/huia-compiler/src/scope.rs index e6efdec..b1fca4c 100644 --- a/huia-compiler/src/scope.rs +++ b/huia-compiler/src/scope.rs @@ -6,11 +6,11 @@ pub struct Scope { } impl Scope { - pub fn add(&mut self, symbol: Symbol) { + pub fn define(&mut self, symbol: Symbol) { self.symbols.insert(symbol.identifier().to_string(), symbol); } - pub fn get(&self, identifier: &str) -> Option<&Symbol> { + pub fn reference(&self, identifier: &str) -> Option<&Symbol> { self.symbols.get(identifier) } @@ -41,8 +41,8 @@ mod test { let symbol = Symbol::local("marty"); assert!(scope.is_empty()); assert!(!scope.has_symbol("marty")); - scope.add(symbol.clone()); + scope.define(symbol.clone()); assert!(scope.has_symbol("marty")); - assert_eq!(scope.get("marty").unwrap(), &symbol); + assert_eq!(scope.reference("marty").unwrap(), &symbol); } } diff --git a/huia-parser/src/ast/constant.rs b/huia-parser/src/ast/constant.rs index d90bffa..f8c2415 100644 --- a/huia-parser/src/ast/constant.rs +++ b/huia-parser/src/ast/constant.rs @@ -56,11 +56,11 @@ mod test { #[test] fn it_parses() { - let pair = Grammar::parse(Rule::constant, "MartyMcFly") + let pair = Grammar::parse(Rule::constant, "Marty.McFly") .unwrap() .next() .unwrap(); let constant = Constant::from(pair); - assert_eq!(constant.value(), "MartyMcFly"); + assert_eq!(constant.value(), "Marty.McFly"); } } diff --git a/huia-parser/src/ast/term.rs b/huia-parser/src/ast/term.rs index 7d79b10..9c373ee 100644 --- a/huia-parser/src/ast/term.rs +++ b/huia-parser/src/ast/term.rs @@ -646,6 +646,15 @@ mod test { assert_eq!(arguments.len(), 0); } + #[test] + fn test_method_call_on_constant() { + let terms = Term::input("My.Greeter.hello()").unwrap(); + let (method_name, receiver, arguments) = terms[0].method_call().unwrap(); + assert_eq!(method_name.value_ref(), "hello"); + assert_eq!(receiver.constant().unwrap().value_ref(), "My.Greeter"); + assert_eq!(arguments.len(), 0); + } + #[test] fn test_string() { let terms = Term::input("\"Marty McFly\"").unwrap(); diff --git a/huia-parser/src/grammar.pest b/huia-parser/src/grammar.pest index 4afd3f7..71359b2 100644 --- a/huia-parser/src/grammar.pest +++ b/huia-parser/src/grammar.pest @@ -44,7 +44,8 @@ array = { "[" ~ (expression ~ ("," ~ expression)*)? ~ "]" } atom = @{ ":" ~ ident } -constant = @{ 'A'..'Z' ~ ('a'..'z' | 'A'..'Z' | "_")* } +constant = @{ constant_name ~ ("." ~ constant_name)* } +constant_name = @{ 'A'..'Z' ~ ('a'..'z' | 'A'..'Z' | "_")* } float = ${ float_characteristic ~ "." ~ float_mantissa } float_characteristic = { "0" | (('1'..'9') ~ ('0'..'9' | "_")*) }