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 hooks
Runtime(Hook), Runtime(Hook),
Render, Render,
// The self lookup for tuples.
PushSelf,
PopSelf,
} }
use super::ir::Val; use super::ir::Val;

View File

@ -220,10 +220,7 @@ fn tuple_ops() {
("foo".to_owned(), Rc::new(P(Int(2)))), ("foo".to_owned(), Rc::new(P(Int(2)))),
])), ])),
vec![ vec![
InitTuple, // Override tuple Sym("tpl".to_owned()),
Val(Str("foo".to_owned())),
Val(Int(2)),
Field,
InitTuple, // Target tuple InitTuple, // Target tuple
Sym("bar".to_owned()), Sym("bar".to_owned()),
Val(Str("ux".to_owned())), Val(Str("ux".to_owned())),
@ -233,6 +230,13 @@ fn tuple_ops() {
Val(Str("foo".to_owned())), Val(Str("foo".to_owned())),
Val(Int(1)), Val(Int(1)),
Field, 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 Cp, // Do the tuple copy operation
] => C(Tuple(vec![ ] => C(Tuple(vec![
("bar".to_owned(), Rc::new(P(Str("quux".to_owned())))), ("bar".to_owned(), Rc::new(P(Str("quux".to_owned())))),
@ -400,10 +404,6 @@ fn function_definition_and_call() {
fn module_call() { fn module_call() {
assert_cases![ assert_cases![
vec![ 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 Sym("m".to_owned()), // 4 // binding name for module
InitTuple, // 5 // Module tuple bindings InitTuple, // 5 // Module tuple bindings
Sym("one".to_owned()), // 6 Sym("one".to_owned()), // 6
@ -422,15 +422,15 @@ fn module_call() {
Return, // 19 // end the module Return, // 19 // end the module
Bind, // 20 // bind module to the binding name Bind, // 20 // bind module to the binding name
DeRef("m".to_owned()), // 21 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 Cp, // 22 // Call the module
] => C(Tuple(vec![ ] => C(Tuple(vec![
("foo".to_owned(), Rc::new(P(Int(11)))), ("foo".to_owned(), Rc::new(P(Int(11)))),
])), ])),
vec![ 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 Sym("m".to_owned()), // 4 // binding name for module
InitTuple, // 5 // Module tuple bindings InitTuple, // 5 // Module tuple bindings
Sym("one".to_owned()), // 6 Sym("one".to_owned()), // 6
@ -450,6 +450,10 @@ fn module_call() {
Return, // 20 // end the module Return, // 20 // end the module
Bind, // 21 // bind module to the binding name Bind, // 21 // bind module to the binding name
DeRef("m".to_owned()), // 22 DeRef("m".to_owned()), // 22
InitTuple, // 0 // override tuple
Sym("one".to_owned()), // 1
Val(Int(11)), // 2
Field, // 3
Cp, // 23 Cp, // 23
] => P(Int(1)), ] => P(Int(1)),
]; ];
@ -737,6 +741,11 @@ fn tuple_copies() {
assert_parse_cases![ assert_parse_cases![
"let tpl = { v = 1, }; tpl{};" => C(Tuple(vec![("v".to_owned(), Rc::new(P(Int(1))))])), "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))))])), "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); ops.push(Op::FCall, func_pos);
} }
Expression::Copy(def) => { 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()); ops.push(Op::InitTuple, def.pos.clone());
for (t, e) in def.fields { for (t, e) in def.fields {
ops.push(Op::Sym(t.fragment), t.pos.clone()); ops.push(Op::Sym(t.fragment), t.pos.clone());
Self::translate_expr(e, &mut ops, root); Self::translate_expr(e, &mut ops, root);
ops.push(Op::Field, t.pos.clone()); ops.push(Op::Field, t.pos.clone());
} }
Self::translate_value(def.selector, &mut ops, root); ops.push(Op::Cp, def.pos.clone());
ops.push(Op::Cp, def.pos); ops.push(Op::PopSelf, def.pos);
} }
Expression::Debug(def) => { Expression::Debug(def) => {
let mut buffer: Vec<u8> = Vec::new(); let mut buffer: Vec<u8> = Vec::new();

View File

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