From 506036d8884f88ff29661dc2be382e790bfca3a7 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Tue, 20 Aug 2019 20:51:46 -0500 Subject: [PATCH] DEV: Copying tuples from a dot selector works. --- src/build/opcode/test.rs | 17 +++++++++- src/build/opcode/translate.rs | 64 +++++++++++++++++++++++++++++------ src/build/opcode/vm.rs | 24 ++++++++----- 3 files changed, 84 insertions(+), 21 deletions(-) diff --git a/src/build/opcode/test.rs b/src/build/opcode/test.rs index 70e9241..8f7d36d 100644 --- a/src/build/opcode/test.rs +++ b/src/build/opcode/test.rs @@ -742,9 +742,24 @@ fn tuple_copies() { "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![ + "let tpl = { v = 1, w = 2}; tpl{v=self.w, x=self.v};" => C(Tuple(vec![ ("v".to_owned(), Rc::new(P(Int(2)))), ("w".to_owned(), Rc::new(P(Int(2)))), + ("x".to_owned(), Rc::new(P(Int(1)))), + ])), + // the deep copy case identity copy + "let tpl = { v = 1, inner = { w = 2 }}; tpl{inner=self.inner{}};" => C(Tuple(vec![ + ("v".to_owned(), Rc::new(P(Int(1)))), + ("inner".to_owned(), Rc::new(C(Tuple(vec![ + ("w".to_owned(), Rc::new(P(Int(2)))), + ])))), + ])), + // the deep copy case modifications + "let tpl = { v = 1, inner = { w = 2 }}; tpl{inner=self.inner{w=3}};" => C(Tuple(vec![ + ("v".to_owned(), Rc::new(P(Int(1)))), + ("inner".to_owned(), Rc::new(C(Tuple(vec![ + ("w".to_owned(), Rc::new(P(Int(3)))), + ])))), ])), ]; } diff --git a/src/build/opcode/translate.rs b/src/build/opcode/translate.rs index cc59789..05d13eb 100644 --- a/src/build/opcode/translate.rs +++ b/src/build/opcode/translate.rs @@ -13,7 +13,7 @@ // limitations under the License. use std::path::Path; -use crate::ast::{BinaryExprType, Expression, FormatArgs, Position, Statement, Value}; +use crate::ast::{Token, BinaryExprType, Expression, FormatArgs, Position, Statement, Value}; use crate::ast::{FuncOpDef, TemplatePart}; use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser}; use crate::build::opcode::Primitive; @@ -202,7 +202,45 @@ impl AST { Self::translate_expr(*def.left, &mut ops, root); // Symbols on the right side should be converted to strings to satisfy // the Index operation contract. - match *def.right { + match dbg!(*def.right) { + Expression::Copy(copy_def) => { + // first handle the selector + match copy_def.selector { + Value::Str(sym) | Value::Symbol(sym) => { + ops.push(Op::Val(Primitive::Str(sym.val)), sym.pos); + } + Value::Int(sym) => { + ops.push(Op::Val(Primitive::Int(sym.val)), sym.pos); + } + _ => { + unreachable!() + } + } + ops.push(Op::Index, copy_def.pos.clone()); + Self::translate_copy(ops, copy_def.fields, copy_def.pos, root); + return; + } + Expression::Call(call_def) => { + // first push our arguments. + for e in call_def.arglist { + Self::translate_expr(e, &mut ops, root); + } + // then handle the selector + let func_pos = call_def.funcref.pos().clone(); + match call_def.funcref { + Value::Str(sym) | Value::Symbol(sym) => { + ops.push(Op::Val(Primitive::Str(sym.val)), sym.pos); + } + Value::Int(sym) => { + ops.push(Op::Val(Primitive::Int(sym.val)), sym.pos); + } + _ => { + unreachable!() + } + } + ops.push(Op::FCall, func_pos); + return; + } Expression::Simple(Value::Symbol(name)) => { Self::translate_expr( Expression::Simple(Value::Str(name)), @@ -443,15 +481,7 @@ impl AST { } 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()); - } - ops.push(Op::Cp, def.pos.clone()); - ops.push(Op::PopSelf, def.pos); + Self::translate_copy(ops, def.fields, def.pos, root); } Expression::Debug(def) => { let mut buffer: Vec = Vec::new(); @@ -499,6 +529,18 @@ impl AST { } } + fn translate_copy(mut ops: &mut PositionMap, flds: Vec<(Token, Expression)>, pos: Position, root: &Path) { + ops.push(Op::PushSelf, pos.clone()); + ops.push(Op::InitTuple, pos.clone()); + for (t, e) in flds { + ops.push(Op::Sym(t.fragment), t.pos.clone()); + Self::translate_expr(e, &mut ops, root); + ops.push(Op::Field, t.pos.clone()); + } + ops.push(Op::Cp, pos.clone()); + ops.push(Op::PopSelf, pos); + } + fn translate_value(value: Value, mut ops: &mut PositionMap, root: &Path) { match value { Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val)), i.pos), diff --git a/src/build/opcode/vm.rs b/src/build/opcode/vm.rs index 7a13fec..37fcfd0 100644 --- a/src/build/opcode/vm.rs +++ b/src/build/opcode/vm.rs @@ -88,7 +88,7 @@ where pub fn run(&mut self) -> Result<(), Error> { loop { - let op = if let Some(op) = dbg!(self.ops.next()) { + let op = if let Some(op) = self.ops.next() { op.clone() } else { break; @@ -142,7 +142,7 @@ where return Ok(()); } Op::Pop => { - self.last = Some(self.pop()?); + self.pop()?; } Op::Typ => self.op_typ()?, Op::Runtime(h) => self.op_runtime(h, pos)?, @@ -582,7 +582,7 @@ where 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.self_stack.push((dbg!(val.clone()), pos.clone())); self.push(val.clone(), pos)?; Ok(()) } @@ -803,7 +803,7 @@ where ) -> Result<(Rc, Position), Error> { if name == "self" { if let Some((val, pos)) = self.self_stack.last() { - return Ok((val.clone(), pos.clone())); + return Ok((dbg!(val.clone()), pos.clone())); } return Err(dbg!(Error::new( format!("No such binding {}", name), @@ -812,16 +812,22 @@ where } match self.symbols.get(name) { Some((ref v, ref pos)) => Ok((v.clone(), pos.clone())), - None => Err(dbg!(Error::new( - format!("No such binding {}", name), - pos.clone() - ))), + None => { + // TODO(jwall): Look in the last item? + return Err(dbg!(Error::new( + format!("No such binding {}", name), + pos.clone() + ))); + } } } pub fn pop(&mut self) -> Result<(Rc, Position), Error> { match self.stack.pop() { - Some(v) => Ok(v), + Some(v) => { + self.last = Some(v.clone()); + Ok(v) + } None => unreachable!(), } }