DEV: Copying tuples from a dot selector works.

This commit is contained in:
Jeremy Wall 2019-08-20 20:51:46 -05:00
parent d1014d4b6e
commit 506036d888
3 changed files with 84 additions and 21 deletions

View File

@ -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)))),
])))),
])),
];
}

View File

@ -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<u8> = 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),

View File

@ -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<Value>, 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<Value>, Position), Error> {
match self.stack.pop() {
Some(v) => Ok(v),
Some(v) => {
self.last = Some(v.clone());
Ok(v)
}
None => unreachable!(),
}
}