mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
DEV: Copying tuples from a dot selector works.
This commit is contained in:
parent
d1014d4b6e
commit
506036d888
@ -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{};" => 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
|
// 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)))),
|
("v".to_owned(), Rc::new(P(Int(2)))),
|
||||||
("w".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)))),
|
||||||
|
])))),
|
||||||
])),
|
])),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
use std::path::Path;
|
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::ast::{FuncOpDef, TemplatePart};
|
||||||
use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser};
|
use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser};
|
||||||
use crate::build::opcode::Primitive;
|
use crate::build::opcode::Primitive;
|
||||||
@ -202,7 +202,45 @@ impl AST {
|
|||||||
Self::translate_expr(*def.left, &mut ops, root);
|
Self::translate_expr(*def.left, &mut ops, root);
|
||||||
// Symbols on the right side should be converted to strings to satisfy
|
// Symbols on the right side should be converted to strings to satisfy
|
||||||
// the Index operation contract.
|
// 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)) => {
|
Expression::Simple(Value::Symbol(name)) => {
|
||||||
Self::translate_expr(
|
Self::translate_expr(
|
||||||
Expression::Simple(Value::Str(name)),
|
Expression::Simple(Value::Str(name)),
|
||||||
@ -443,15 +481,7 @@ impl AST {
|
|||||||
}
|
}
|
||||||
Expression::Copy(def) => {
|
Expression::Copy(def) => {
|
||||||
Self::translate_value(def.selector, &mut ops, root);
|
Self::translate_value(def.selector, &mut ops, root);
|
||||||
ops.push(Op::PushSelf, def.pos.clone());
|
Self::translate_copy(ops, def.fields, def.pos, root);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
Expression::Debug(def) => {
|
Expression::Debug(def) => {
|
||||||
let mut buffer: Vec<u8> = Vec::new();
|
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) {
|
fn translate_value(value: Value, mut ops: &mut PositionMap, root: &Path) {
|
||||||
match value {
|
match value {
|
||||||
Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val)), i.pos),
|
Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val)), i.pos),
|
||||||
|
@ -88,7 +88,7 @@ where
|
|||||||
|
|
||||||
pub fn run(&mut self) -> Result<(), Error> {
|
pub fn run(&mut self) -> Result<(), Error> {
|
||||||
loop {
|
loop {
|
||||||
let op = if let Some(op) = dbg!(self.ops.next()) {
|
let op = if let Some(op) = self.ops.next() {
|
||||||
op.clone()
|
op.clone()
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@ -142,7 +142,7 @@ where
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
Op::Pop => {
|
Op::Pop => {
|
||||||
self.last = Some(self.pop()?);
|
self.pop()?;
|
||||||
}
|
}
|
||||||
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)?,
|
||||||
@ -582,7 +582,7 @@ where
|
|||||||
fn op_push_self(&mut self) -> Result<(), Error> {
|
fn op_push_self(&mut self) -> Result<(), Error> {
|
||||||
// We'll need a self stack.
|
// We'll need a self stack.
|
||||||
let (val, pos) = self.pop()?;
|
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)?;
|
self.push(val.clone(), pos)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -803,7 +803,7 @@ where
|
|||||||
) -> Result<(Rc<Value>, Position), Error> {
|
) -> Result<(Rc<Value>, Position), Error> {
|
||||||
if name == "self" {
|
if name == "self" {
|
||||||
if let Some((val, pos)) = self.self_stack.last() {
|
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(
|
return Err(dbg!(Error::new(
|
||||||
format!("No such binding {}", name),
|
format!("No such binding {}", name),
|
||||||
@ -812,16 +812,22 @@ where
|
|||||||
}
|
}
|
||||||
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 => {
|
||||||
format!("No such binding {}", name),
|
// TODO(jwall): Look in the last item?
|
||||||
pos.clone()
|
return Err(dbg!(Error::new(
|
||||||
))),
|
format!("No such binding {}", name),
|
||||||
|
pos.clone()
|
||||||
|
)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop(&mut self) -> Result<(Rc<Value>, Position), Error> {
|
pub fn pop(&mut self) -> Result<(Rc<Value>, Position), Error> {
|
||||||
match self.stack.pop() {
|
match self.stack.pop() {
|
||||||
Some(v) => Ok(v),
|
Some(v) => {
|
||||||
|
self.last = Some(v.clone());
|
||||||
|
Ok(v)
|
||||||
|
}
|
||||||
None => unreachable!(),
|
None => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user