DEV: List indexing works.

This commit is contained in:
Jeremy Wall 2019-08-02 18:55:18 -05:00
parent 40fc6fe15f
commit c792d758d7
3 changed files with 69 additions and 27 deletions

View File

@ -453,11 +453,9 @@ fn index_operation() {
Val(Int(1)), Val(Int(1)),
Field, Field,
Field, Field,
InitList,
Val(Str("foo".to_owned())), Val(Str("foo".to_owned())),
Element, Index,
Val(Str("bar".to_owned())), Val(Str("bar".to_owned())),
Element,
Index, Index,
] => P(Int(1)), ] => P(Int(1)),
vec![ vec![
@ -466,9 +464,7 @@ fn index_operation() {
Element, Element,
Val(Str("bar".to_owned())), Val(Str("bar".to_owned())),
Element, Element,
InitList,
Val(Int(0)), Val(Int(0)),
Element,
Index, Index,
] => P(Str("foo".to_owned())), ] => P(Str("foo".to_owned())),
vec![ vec![
@ -480,11 +476,9 @@ fn index_operation() {
Val(Str("bar".to_owned())), Val(Str("bar".to_owned())),
Element, Element,
Field, Field,
InitList,
Val(Str("field".to_owned())), Val(Str("field".to_owned())),
Element, Index,
Val(Int(0)), Val(Int(0)),
Element,
Index, Index,
] => P(Str("foo".to_owned())), ] => P(Str("foo".to_owned())),
]; ];
@ -612,6 +606,27 @@ fn simple_binary_expr() {
) )
} }
#[test]
fn dot_expressions() {
let mut ops = vec![
Sym("foo".to_owned()),
InitList,
Val(Int(0)),
Element,
Val(Int(1)),
Element,
Val(Int(2)),
Element,
Bind,
];
let stmts = parse(OffsetStrIter::from(dbg!("foo.0;")), None).unwrap();
ops.append(&mut translate::AST::translate(stmts));
let ops = Rc::new(ops);
let mut vm = VM::new("foo.ucg", ops.clone());
vm.run().unwrap();
}
#[test] #[test]
fn simple_not_expr() { fn simple_not_expr() {
assert_parse_cases!( assert_parse_cases!(

View File

@ -136,9 +136,26 @@ impl AST {
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops);
ops.push(Op::Mod); ops.push(Op::Mod);
} }
BinaryExprType::IN | BinaryExprType::DOT => { BinaryExprType::IN => {
unimplemented!("Binary expressions are not implmented yet") unimplemented!("Binary expressions are not implmented yet")
// TODO }
BinaryExprType::DOT => {
// Dot expressions expect the left side to be pushed first
Self::translate_expr(*def.left, &mut ops);
// Symbols on the right side should be converted to strings to satisfy
// the Index operation contract.
match *def.right {
Expression::Simple(Value::Symbol(name)) => {
Self::translate_expr(
Expression::Simple(Value::Str(name)),
&mut ops,
);
}
expr => {
Self::translate_expr(expr, &mut ops);
}
}
ops.push(Op::Index);
} }
}; };
} }
@ -171,7 +188,9 @@ impl AST {
Value::Str(s) => ops.push(Op::Val(Primitive::Str(s.val))), Value::Str(s) => ops.push(Op::Val(Primitive::Str(s.val))),
Value::Empty(_pos) => ops.push(Op::Val(Primitive::Empty)), Value::Empty(_pos) => ops.push(Op::Val(Primitive::Empty)),
Value::Boolean(b) => ops.push(Op::Val(Primitive::Bool(b.val))), Value::Boolean(b) => ops.push(Op::Val(Primitive::Bool(b.val))),
Value::Symbol(s) => ops.push(Op::Sym(s.val)), Value::Symbol(s) => {
ops.push(Op::DeRef(s.val));
}
Value::Tuple(_flds) => unimplemented!("Select expression are not implmented yet"), Value::Tuple(_flds) => unimplemented!("Select expression are not implmented yet"),
Value::List(_els) => unimplemented!("Select expression are not implmented yet"), Value::List(_els) => unimplemented!("Select expression are not implmented yet"),
} }

View File

@ -541,25 +541,33 @@ impl<'a> VM {
} }
fn op_index(&mut self) -> Result<(), Error> { fn op_index(&mut self) -> Result<(), Error> {
let path_val = self.pop()?; // left and then right
let path = if let &C(List(ref elems)) = path_val.as_ref() { let right = dbg!(self.pop()?);
elems.clone() let left = dbg!(self.pop()?);
} else { match right.as_ref() {
return Err(dbg!(Error {})); &P(Int(i)) => {
}; if let &C(List(ref elems)) = left.as_ref() {
let target_val = self.pop()?; if i < (elems.len() as i64) && i >= 0 {
match target_val.as_ref() { self.push(elems[i as usize].clone())?;
&P(_) | &S(_) | &T(_) | &F(_) | &M(_) => return Err(dbg!(Error {})), return Ok(());
_ => { }
let mut out = target_val.clone();
for p in path {
let tgt = self.find_in_value(&p, &out)?;
out = tgt;
} }
self.push(out)?; }
&P(Str(ref s)) => {
if let &C(Tuple(ref flds)) = left.as_ref() {
for &(ref key, ref val) in flds.iter() {
if key == s {
self.push(val.clone())?;
return Ok(());
}
}
}
}
_ => {
// noop
} }
}; };
Ok(()) return Err(dbg!(Error {}));
} }
fn op_copy(&mut self) -> Result<(), Error> { fn op_copy(&mut self) -> Result<(), Error> {