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 {
|
pub struct Context {
|
||||||
current_pos: usize,
|
current_pos: usize,
|
||||||
|
globals: Scope,
|
||||||
scope_stack: Vec<Scope>,
|
scope_stack: Vec<Scope>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub fn globals(&self) -> &Scope {
|
pub fn globals(&self) -> &Scope {
|
||||||
&self.scope_stack[0]
|
&self.globals
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn globals_mut(&mut self) -> &mut Scope {
|
pub fn globals_mut(&mut self) -> &mut Scope {
|
||||||
&mut self.scope_stack[0]
|
&mut self.globals
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scope(&self) -> &Scope {
|
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();
|
let mut pos = self.scope_stack.len();
|
||||||
while pos > 0 {
|
while pos > 0 {
|
||||||
pos -= 1;
|
pos -= 1;
|
||||||
if self.scope_stack[pos].has_symbol(identifier) {
|
if self.scope_stack[pos].has_symbol(identifier) {
|
||||||
return self.scope_stack[pos].get(identifier);
|
return self.scope_stack[pos].reference(identifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
@ -55,6 +56,7 @@ impl Default for Context {
|
||||||
fn default() -> Context {
|
fn default() -> Context {
|
||||||
Context {
|
Context {
|
||||||
current_pos: 0,
|
current_pos: 0,
|
||||||
|
globals: Scope::default(),
|
||||||
scope_stack: vec![Scope::default()],
|
scope_stack: vec![Scope::default()],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,7 +72,7 @@ mod test {
|
||||||
let symbol = Symbol::r#type("MartyMcFly");
|
let symbol = Symbol::r#type("MartyMcFly");
|
||||||
|
|
||||||
assert!(context.globals().is_empty());
|
assert!(context.globals().is_empty());
|
||||||
context.globals_mut().add(symbol);
|
context.globals_mut().define(symbol);
|
||||||
assert!(!context.globals().is_empty());
|
assert!(!context.globals().is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +82,7 @@ mod test {
|
||||||
let symbol = Symbol::local("marty");
|
let symbol = Symbol::local("marty");
|
||||||
|
|
||||||
assert!(context.scope().is_empty());
|
assert!(context.scope().is_empty());
|
||||||
context.scope_mut().add(symbol);
|
context.scope_mut().define(symbol);
|
||||||
assert!(!context.scope().is_empty());
|
assert!(!context.scope().is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,10 +92,10 @@ mod test {
|
||||||
let symbol0 = Symbol::local("marty");
|
let symbol0 = Symbol::local("marty");
|
||||||
let symbol1 = Symbol::local("doc");
|
let symbol1 = Symbol::local("doc");
|
||||||
|
|
||||||
context.scope_mut().add(symbol0);
|
context.scope_mut().define(symbol0);
|
||||||
assert!(context.scope().has_symbol("marty"));
|
assert!(context.scope().has_symbol("marty"));
|
||||||
context.push_scope();
|
context.push_scope();
|
||||||
context.scope_mut().add(symbol1);
|
context.scope_mut().define(symbol1);
|
||||||
assert!(context.scope().has_symbol("doc"));
|
assert!(context.scope().has_symbol("doc"));
|
||||||
assert!(!context.scope().has_symbol("marty"));
|
assert!(!context.scope().has_symbol("marty"));
|
||||||
context.pop_scope();
|
context.pop_scope();
|
||||||
|
@ -102,14 +104,14 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn find_symbol() {
|
fn reference() {
|
||||||
let mut context = Context::default();
|
let mut context = Context::default();
|
||||||
let symbol0 = Symbol::local("marty");
|
let symbol0 = Symbol::local("marty");
|
||||||
let symbol1 = Symbol::local("doc");
|
let symbol1 = Symbol::local("doc");
|
||||||
|
|
||||||
context.scope_mut().add(symbol0);
|
context.scope_mut().define(symbol0);
|
||||||
context.push_scope();
|
context.push_scope();
|
||||||
context.scope_mut().add(symbol1);
|
context.scope_mut().define(symbol1);
|
||||||
assert!(context.find_symbol("marty").is_some());
|
assert!(context.reference("marty").is_some());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,11 @@ pub struct Scope {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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);
|
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)
|
self.symbols.get(identifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@ mod test {
|
||||||
let symbol = Symbol::local("marty");
|
let symbol = Symbol::local("marty");
|
||||||
assert!(scope.is_empty());
|
assert!(scope.is_empty());
|
||||||
assert!(!scope.has_symbol("marty"));
|
assert!(!scope.has_symbol("marty"));
|
||||||
scope.add(symbol.clone());
|
scope.define(symbol.clone());
|
||||||
assert!(scope.has_symbol("marty"));
|
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]
|
#[test]
|
||||||
fn it_parses() {
|
fn it_parses() {
|
||||||
let pair = Grammar::parse(Rule::constant, "MartyMcFly")
|
let pair = Grammar::parse(Rule::constant, "Marty.McFly")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.next()
|
.next()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let constant = Constant::from(pair);
|
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);
|
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]
|
#[test]
|
||||||
fn test_string() {
|
fn test_string() {
|
||||||
let terms = Term::input("\"Marty McFly\"").unwrap();
|
let terms = Term::input("\"Marty McFly\"").unwrap();
|
||||||
|
|
|
@ -44,7 +44,8 @@ array = { "[" ~ (expression ~ ("," ~ expression)*)? ~ "]" }
|
||||||
|
|
||||||
atom = @{ ":" ~ ident }
|
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 = ${ float_characteristic ~ "." ~ float_mantissa }
|
||||||
float_characteristic = { "0" | (('1'..'9') ~ ('0'..'9' | "_")*) }
|
float_characteristic = { "0" | (('1'..'9') ~ ('0'..'9' | "_")*) }
|
||||||
|
|
Reference in a new issue