DEV: Bindings store their location too.

This commit is contained in:
Jeremy Wall 2019-08-20 19:03:49 -05:00
parent e4c652b240
commit b024d23110
3 changed files with 27 additions and 12 deletions

View File

@ -14,11 +14,12 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::rc::Rc; use std::rc::Rc;
use crate::ast::Position;
use super::Value; use super::Value;
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
pub struct Stack { pub struct Stack {
curr: BTreeMap<String, Rc<Value>>, curr: BTreeMap<String, (Rc<Value>, Position)>,
} }
impl Stack { impl Stack {
@ -28,7 +29,7 @@ impl Stack {
} }
} }
pub fn get(&self, name: &str) -> Option<Rc<Value>> { pub fn get(&self, name: &str) -> Option<(Rc<Value>, Position)> {
self.curr.get(name).cloned() self.curr.get(name).cloned()
} }
@ -36,8 +37,8 @@ impl Stack {
self.curr.get(name).is_some() self.curr.get(name).is_some()
} }
pub fn add(&mut self, name: String, val: Rc<Value>) { pub fn add(&mut self, name: String, val: Rc<Value>, pos: Position) {
self.curr.insert(name, val); self.curr.insert(name, (val, pos));
} }
pub fn symbol_list(&self) -> Vec<&String> { pub fn symbol_list(&self) -> Vec<&String> {

View File

@ -140,7 +140,7 @@ fn bind_op() {
let mut vm = VM::new(Rc::new(map), env); let mut vm = VM::new(Rc::new(map), env);
vm.run().unwrap(); vm.run().unwrap();
let (name, result) = case.1; let (name, result) = case.1;
let v = vm.get_binding(name, &Position::new(0, 0, 0)).unwrap(); let (v, _) = vm.get_binding(name, &Position::new(0, 0, 0)).unwrap();
assert_eq!(&result, v.as_ref()); assert_eq!(&result, v.as_ref());
} }
} }
@ -400,7 +400,7 @@ fn function_definition_and_call() {
fn module_call() { fn module_call() {
assert_cases![ assert_cases![
vec![ vec![
InitTuple, // 0 // override tuple InitTuple, // 0 // override tuple
Sym("one".to_owned()), // 1 Sym("one".to_owned()), // 1
Val(Int(11)), // 2 Val(Int(11)), // 2
Field, // 3 Field, // 3
@ -732,6 +732,14 @@ fn simple_modules() {
]; ];
} }
#[test]
fn tuple_copies() {
assert_parse_cases![
"let tpl = { v = 1, }; tpl{};" => C(Tuple(vec![("v".to_owned(), Rc::new(P(Int(1))))])),
"let tpl = { v = 1, }; tpl{v=2};" => C(Tuple(vec![("v".to_owned(), Rc::new(P(Int(2))))])),
];
}
#[test] #[test]
fn simple_range() { fn simple_range() {
assert_parse_cases![ assert_parse_cases![

View File

@ -76,7 +76,8 @@ where
let mut flds = Vec::new(); let mut flds = Vec::new();
for sym in self.symbols.symbol_list() { for sym in self.symbols.symbol_list() {
if include_mod || sym != "mod" { if include_mod || sym != "mod" {
flds.push((sym.clone(), self.symbols.get(sym).unwrap().clone())); let (val, _) = self.symbols.get(sym).unwrap().clone();
flds.push((sym.clone(), val));
} }
} }
return C(Tuple(flds)); return C(Tuple(flds));
@ -169,7 +170,7 @@ where
} }
fn op_deref(&mut self, name: String, pos: &Position) -> Result<(), Error> { fn op_deref(&mut self, name: String, pos: &Position) -> Result<(), Error> {
let val = self.get_binding(&name, pos)?.clone(); let (val, _) = self.get_binding(&name, pos)?.clone();
self.push(val, pos.clone()) self.push(val, pos.clone())
} }
@ -686,7 +687,8 @@ where
self.merge_field_into_tuple(&mut flds, name, val)?; self.merge_field_into_tuple(&mut flds, name, val)?;
} }
// Put the copy on the Stack // Put the copy on the Stack
self.push(Rc::new(C(Tuple(flds))), tgt_pos)?; self.push(Rc::new(C(Tuple(flds))), tgt_pos.clone())?;
self.last = Some((tgt.clone(), tgt_pos));
} }
&M(Module { &M(Module {
ref ptr, ref ptr,
@ -771,13 +773,17 @@ where
pos.clone(), pos.clone(),
))); )));
} }
self.symbols.add(name, val); self.symbols.add(name, val, pos.clone());
Ok(()) Ok(())
} }
pub fn get_binding(&'a self, name: &str, pos: &Position) -> Result<Rc<Value>, Error> { pub fn get_binding(
&'a self,
name: &str,
pos: &Position,
) -> Result<(Rc<Value>, Position), Error> {
match self.symbols.get(name) { match self.symbols.get(name) {
Some(v) => Ok(v), Some((ref v, ref pos)) => Ok((v.clone(), pos.clone())),
None => Err(dbg!(Error::new( None => Err(dbg!(Error::new(
format!("No such binding {}", name), format!("No such binding {}", name),
pos.clone() pos.clone()