Scope stuff.
This commit is contained in:
parent
447c54ce35
commit
7277510a72
5 changed files with 31 additions and 19 deletions
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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' | "_")*) }
|
||||
|
|
Reference in a new issue