DEV: Indexing operation.

This commit is contained in:
Jeremy Wall 2019-07-11 19:28:55 -05:00
parent a50eb46c5e
commit 102f0f5ae1
2 changed files with 140 additions and 32 deletions

View File

@ -109,6 +109,7 @@ pub enum Op {
// - And(usize)
// - Or(usize)
// Spacer operation, Does nothing.
Index, // indexing operation
Noop,
// Pending Computation
InitThunk(i32), // Basically just used for module return expressions
@ -167,7 +168,7 @@ impl<'a> VM {
let idx = self.ops.idx()?;
match op {
Op::Val(p) => self.push(dbg!(P(p.clone())))?,
Op::Sym(s) => self.push(S(s.clone()))?,
Op::Sym(s) => self.push(dbg!(S(s.clone())))?,
Op::DeRef(s) => self.op_deref(s.clone())?,
Op::Add => self.op_add()?,
Op::Sub => self.op_sub()?,
@ -185,6 +186,7 @@ impl<'a> VM {
Op::InitTuple => self.push(C(Tuple(Vec::new())))?,
Op::Field => self.op_field()?,
Op::Element => self.op_element()?,
Op::Index => self.op_index()?,
Op::Cp => self.op_copy()?,
//TODO(jwall): Should this take a user provided message?
Op::Bang => return dbg!(Err(Error {})),
@ -495,19 +497,73 @@ impl<'a> VM {
Ok(())
}
fn find_in_list(&self, index: Value, elems: Vec<Value>) -> Result<Value, Error> {
let idx = match index {
P(Int(i)) => i,
_ => return dbg!(Err(Error {})),
};
match elems.get(idx as usize) {
Some(v) => Ok(v.clone()),
None => Err(Error {}),
}
}
fn find_in_flds(&self, index: Value, flds: Vec<(String, Value)>) -> Result<Value, Error> {
let idx = match index {
S(p) => p,
P(Str(p)) => p,
_ => return dbg!(Err(Error {})),
};
for f in flds.iter() {
if idx == f.0 {
return Ok(f.1.clone());
}
}
Err(Error {})
}
fn find_in_value(&self, index: Value, target: Value) -> Result<Value, Error> {
match target {
C(Tuple(flds)) => self.find_in_flds(index, flds),
C(List(elements)) => self.find_in_list(index, elements),
_ => return Err(Error {}),
}
}
fn op_index(&mut self) -> Result<(), Error> {
let path = if let C(List(elems)) = self.pop()? {
elems
} else {
return dbg!(Err(Error {}));
};
match self.pop()? {
P(_) | S(_) | T(_) | F(_) | M(_) => return dbg!(Err(Error {})),
val => {
let mut out = val;
for p in path {
let tgt = self.find_in_value(p, out)?;
out = tgt;
}
self.push(out)?;
}
};
Ok(())
}
fn op_copy(&mut self) -> Result<(), Error> {
// TODO Use Cow pointers for this?
// get next value. It should be a Module.
let tgt = self.pop()?;
// get next value. It should be a Module or Tuple.
let tgt = dbg!(self.pop())?;
// This value should always be a tuple
let overrides = if let C(Tuple(oflds)) = self.pop()? {
oflds
} else {
return dbg!(Err(Error {}));
};
match tgt {
C(Tuple(mut flds)) => {
let overrides = self.pop()?;
if let C(Tuple(oflds)) = overrides {
for (name, val) in oflds {
self.merge_field_into_tuple(&mut flds, name, val)?;
}
} else {
return dbg!(Err(Error {}));
for (name, val) in overrides {
dbg!(self.merge_field_into_tuple(&mut flds, name, val))?;
}
// Put the copy on the Stack
self.push(C(Tuple(flds)))?;
@ -517,17 +573,19 @@ impl<'a> VM {
result_ptr,
mut flds,
}) => {
let overrides = dbg!(self.pop()?);
if let C(Tuple(oflds)) = overrides {
for (name, val) in oflds {
self.merge_field_into_tuple(&mut flds, name, val)?;
}
} else {
return dbg!(Err(Error {}));
//let this = M(Module {
// ptr: ptr.clone(),
// result_ptr: result_ptr.clone(),
// flds: flds.clone(),
//});
for (name, val) in overrides {
self.merge_field_into_tuple(&mut flds, name, val)?;
}
// FIXME(jwall): We need to populate the pkg key for modules.
//self.merge_field_into_tuple(&mut flds, "this".to_owned(), this)?;
let mut vm = Self::with_pointer(ptr);
vm.push(S("mod".to_owned()))?;
vm.push(C(Tuple(flds)))?;
vm.push(C(Tuple(dbg!(flds))))?;
vm.run()?;
let mut flds = Vec::new();
if let Some(ptr) = dbg!(result_ptr) {

View File

@ -16,11 +16,11 @@ use std::rc::Rc;
use super::scope::Stack;
use super::Composite::{List, Tuple};
use super::Op::{
Add, Bang, Bind, Cp, DeRef, Div, Element, Equal, FCall, Field, Func, InitList, InitThunk,
InitTuple, Jump, JumpIfFalse, JumpIfTrue, Module, Mul, Noop, Pop, Return, SelectJump, Sub, Sym,
Val,
Add, Bang, Bind, Cp, DeRef, Div, Element, Equal, FCall, Field, Func, Index, InitList,
InitThunk, InitTuple, Jump, JumpIfFalse, JumpIfTrue, Module, Mul, Noop, Pop, Return,
SelectJump, Sub, Sym, Val,
};
use super::Primitive::{Bool, Float, Int, Str};
use super::Primitive::{Bool, Empty, Float, Int, Str};
use super::Value::{C, P};
use super::VM;
@ -356,22 +356,24 @@ fn test_module_call() {
Sym("two".to_owned()), // 9
Val(Int(2)), // 10
Field, // 11
Module(17), // 12 // Module definition
Bind, // 13
Module(17), // 12 // Module body definition
Bind, // 13 // bind the mod tuple
Sym("foo".to_owned()), // 14
DeRef("mod".to_owned()), // 15
Bind, // 16 // bind mod tuple to foo
Return, // 17 // end the module
Bind, // 18 // bind module to the binding name
DeRef("m".to_owned()), // 19
Cp, // 20
] => C(Tuple(vec![(
"foo".to_owned(),
C(Tuple(vec![
("one".to_owned(), P(Int(11))),
("two".to_owned(), P(Int(2))),
])),
)])),
Cp, // 20 // Call the module
] => C(Tuple(vec![
(
"foo".to_owned(),
C(Tuple(vec![
("one".to_owned(), P(Int(11))),
("two".to_owned(), P(Int(2))),
]))
),
])),
vec![
InitTuple, // 0 // override tuple
Sym("one".to_owned()), // 1
@ -433,6 +435,54 @@ fn test_select_short_circuit() {
];
}
#[test]
fn test_index_operation() {
assert_cases![
vec![
InitTuple,
Sym("foo".to_owned()),
InitTuple,
Sym("bar".to_owned()),
Val(Int(1)),
Field,
Field,
InitList,
Val(Str("foo".to_owned())),
Element,
Val(Str("bar".to_owned())),
Element,
Index,
] => P(Int(1)),
vec![
InitList,
Val(Str("foo".to_owned())),
Element,
Val(Str("bar".to_owned())),
Element,
InitList,
Val(Int(0)),
Element,
Index,
] => P(Str("foo".to_owned())),
vec![
InitTuple,
Sym("field".to_owned()),
InitList,
Val(Str("foo".to_owned())),
Element,
Val(Str("bar".to_owned())),
Element,
Field,
InitList,
Val(Str("field".to_owned())),
Element,
Val(Int(0)),
Element,
Index,
] => P(Str("foo".to_owned())),
];
}
#[test]
fn test_scope_stacks() {
let mut stack = Stack::new();