DEV: Self references in tuples.

This commit is contained in:
Jeremy Wall 2019-08-20 19:36:07 -05:00
parent b024d23110
commit d1014d4b6e
4 changed files with 58 additions and 16 deletions

View File

@ -211,6 +211,9 @@ pub enum Op {
// Runtime hooks
Runtime(Hook),
Render,
// The self lookup for tuples.
PushSelf,
PopSelf,
}
use super::ir::Val;

View File

@ -220,10 +220,7 @@ fn tuple_ops() {
("foo".to_owned(), Rc::new(P(Int(2)))),
])),
vec![
InitTuple, // Override tuple
Val(Str("foo".to_owned())),
Val(Int(2)),
Field,
Sym("tpl".to_owned()),
InitTuple, // Target tuple
Sym("bar".to_owned()),
Val(Str("ux".to_owned())),
@ -233,6 +230,13 @@ fn tuple_ops() {
Val(Str("foo".to_owned())),
Val(Int(1)),
Field,
Bind,
DeRef("tpl".to_owned()),
InitTuple,
// Begin the field overrides
Val(Str("foo".to_owned())),
Val(Int(2)),
Field,
Cp, // Do the tuple copy operation
] => C(Tuple(vec![
("bar".to_owned(), Rc::new(P(Str("quux".to_owned())))),
@ -400,10 +404,6 @@ fn function_definition_and_call() {
fn module_call() {
assert_cases![
vec![
InitTuple, // 0 // override tuple
Sym("one".to_owned()), // 1
Val(Int(11)), // 2
Field, // 3
Sym("m".to_owned()), // 4 // binding name for module
InitTuple, // 5 // Module tuple bindings
Sym("one".to_owned()), // 6
@ -422,15 +422,15 @@ fn module_call() {
Return, // 19 // end the module
Bind, // 20 // bind module to the binding name
DeRef("m".to_owned()), // 21
InitTuple, // 0 // override tuple
Sym("one".to_owned()), // 1
Val(Int(11)), // 2
Field, // 3
Cp, // 22 // Call the module
] => C(Tuple(vec![
("foo".to_owned(), Rc::new(P(Int(11)))),
])),
vec![
InitTuple, // 0 // override tuple
Sym("one".to_owned()), // 1
Val(Int(11)), // 2
Field, // 3
Sym("m".to_owned()), // 4 // binding name for module
InitTuple, // 5 // Module tuple bindings
Sym("one".to_owned()), // 6
@ -450,6 +450,10 @@ fn module_call() {
Return, // 20 // end the module
Bind, // 21 // bind module to the binding name
DeRef("m".to_owned()), // 22
InitTuple, // 0 // override tuple
Sym("one".to_owned()), // 1
Val(Int(11)), // 2
Field, // 3
Cp, // 23
] => P(Int(1)),
];
@ -737,6 +741,11 @@ 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))))])),
// Tests for Self lookups
"let tpl = { v = 1, w = 2}; tpl{v=self.w};" => C(Tuple(vec![
("v".to_owned(), Rc::new(P(Int(2)))),
("w".to_owned(), Rc::new(P(Int(2)))),
])),
];
}

View File

@ -442,14 +442,16 @@ impl AST {
ops.push(Op::FCall, func_pos);
}
Expression::Copy(def) => {
Self::translate_value(def.selector, &mut ops, root);
ops.push(Op::PushSelf, def.pos.clone());
ops.push(Op::InitTuple, def.pos.clone());
for (t, e) in def.fields {
ops.push(Op::Sym(t.fragment), t.pos.clone());
Self::translate_expr(e, &mut ops, root);
ops.push(Op::Field, t.pos.clone());
}
Self::translate_value(def.selector, &mut ops, root);
ops.push(Op::Cp, def.pos);
ops.push(Op::Cp, def.pos.clone());
ops.push(Op::PopSelf, def.pos);
}
Expression::Debug(def) => {
let mut buffer: Vec<u8> = Vec::new();

View File

@ -39,6 +39,7 @@ where
ops: OpPointer,
pub env: Rc<RefCell<Environment<O, E>>>,
pub last: Option<(Rc<Value>, Position)>,
self_stack: Vec<(Rc<Value>, Position)>,
}
impl<'a, O, E> VM<O, E>
@ -58,6 +59,7 @@ where
ops: ops,
env: env,
last: None,
self_stack: Vec::new(),
}
}
@ -69,6 +71,7 @@ where
ops: self.ops.clone(),
env: self.env.clone(),
last: self.last,
self_stack: self.self_stack,
}
}
@ -144,6 +147,8 @@ where
Op::Typ => self.op_typ()?,
Op::Runtime(h) => self.op_runtime(h, pos)?,
Op::Render => self.op_render()?,
Op::PushSelf => self.op_push_self()?,
Op::PopSelf => self.op_pop_self()?,
};
}
Ok(())
@ -574,6 +579,20 @@ where
Ok(())
}
fn op_push_self(&mut self) -> Result<(), Error> {
// We'll need a self stack.
let (val, pos) = self.pop()?;
self.self_stack.push((val.clone(), pos.clone()));
self.push(val.clone(), pos)?;
Ok(())
}
fn op_pop_self(&mut self) -> Result<(), Error> {
// We'll need a self stack.
self.self_stack.pop();
Ok(())
}
fn op_bind(&mut self, strict: bool) -> Result<(), Error> {
// pop val off stack.
let (val, val_pos) = self.pop()?;
@ -671,10 +690,10 @@ where
}
fn op_copy(&mut self, pos: Position) -> Result<(), Error> {
// get next value. It should be a Module or Tuple.
let (tgt, tgt_pos) = dbg!(self.pop()?);
// This value should always be a tuple
let (override_val, _) = dbg!(self.pop()?);
// get targett value. It should be a Module or Tuple.
let (tgt, tgt_pos) = dbg!(self.pop()?);
let overrides = if let &C(Tuple(ref oflds)) = override_val.as_ref() {
oflds.clone()
} else {
@ -782,6 +801,15 @@ where
name: &str,
pos: &Position,
) -> Result<(Rc<Value>, Position), Error> {
if name == "self" {
if let Some((val, pos)) = self.self_stack.last() {
return Ok((val.clone(), pos.clone()));
}
return Err(dbg!(Error::new(
format!("No such binding {}", name),
pos.clone()
)));
}
match self.symbols.get(name) {
Some((ref v, ref pos)) => Ok((v.clone(), pos.clone())),
None => Err(dbg!(Error::new(