From d1014d4b6e9f6bf0b9abd76d53a86ad953bfb4e4 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Tue, 20 Aug 2019 19:36:07 -0500 Subject: [PATCH] DEV: Self references in tuples. --- src/build/opcode/mod.rs | 3 +++ src/build/opcode/test.rs | 33 +++++++++++++++++++++------------ src/build/opcode/translate.rs | 6 ++++-- src/build/opcode/vm.rs | 32 ++++++++++++++++++++++++++++++-- 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/build/opcode/mod.rs b/src/build/opcode/mod.rs index 3cad9d6..38ba37b 100644 --- a/src/build/opcode/mod.rs +++ b/src/build/opcode/mod.rs @@ -211,6 +211,9 @@ pub enum Op { // Runtime hooks Runtime(Hook), Render, + // The self lookup for tuples. + PushSelf, + PopSelf, } use super::ir::Val; diff --git a/src/build/opcode/test.rs b/src/build/opcode/test.rs index a0be83c..70e9241 100644 --- a/src/build/opcode/test.rs +++ b/src/build/opcode/test.rs @@ -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)))), + ])), ]; } diff --git a/src/build/opcode/translate.rs b/src/build/opcode/translate.rs index 5b3e5e1..cc59789 100644 --- a/src/build/opcode/translate.rs +++ b/src/build/opcode/translate.rs @@ -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 = Vec::new(); diff --git a/src/build/opcode/vm.rs b/src/build/opcode/vm.rs index adf9e20..7a13fec 100644 --- a/src/build/opcode/vm.rs +++ b/src/build/opcode/vm.rs @@ -39,6 +39,7 @@ where ops: OpPointer, pub env: Rc>>, pub last: Option<(Rc, Position)>, + self_stack: Vec<(Rc, Position)>, } impl<'a, O, E> VM @@ -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, 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(