Scope stuff.

This commit is contained in:
James Harton 2019-02-14 19:08:40 +13:00
parent 447c54ce35
commit 7277510a72
5 changed files with 31 additions and 19 deletions

View file

@ -3,16 +3,17 @@ use crate::symbol::Symbol;
pub struct Context {
current_pos: usize,
globals: Scope,
scope_stack: Vec<Scope>,
}
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());
}
}

View file

@ -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);
}
}

View file

@ -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");
}
}

View file

@ -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();

View file

@ -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' | "_")*) }