mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
DEV: Indexing operation.
This commit is contained in:
parent
a50eb46c5e
commit
102f0f5ae1
@ -109,6 +109,7 @@ pub enum Op {
|
|||||||
// - And(usize)
|
// - And(usize)
|
||||||
// - Or(usize)
|
// - Or(usize)
|
||||||
// Spacer operation, Does nothing.
|
// Spacer operation, Does nothing.
|
||||||
|
Index, // indexing operation
|
||||||
Noop,
|
Noop,
|
||||||
// Pending Computation
|
// Pending Computation
|
||||||
InitThunk(i32), // Basically just used for module return expressions
|
InitThunk(i32), // Basically just used for module return expressions
|
||||||
@ -167,7 +168,7 @@ impl<'a> VM {
|
|||||||
let idx = self.ops.idx()?;
|
let idx = self.ops.idx()?;
|
||||||
match op {
|
match op {
|
||||||
Op::Val(p) => self.push(dbg!(P(p.clone())))?,
|
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::DeRef(s) => self.op_deref(s.clone())?,
|
||||||
Op::Add => self.op_add()?,
|
Op::Add => self.op_add()?,
|
||||||
Op::Sub => self.op_sub()?,
|
Op::Sub => self.op_sub()?,
|
||||||
@ -185,6 +186,7 @@ impl<'a> VM {
|
|||||||
Op::InitTuple => self.push(C(Tuple(Vec::new())))?,
|
Op::InitTuple => self.push(C(Tuple(Vec::new())))?,
|
||||||
Op::Field => self.op_field()?,
|
Op::Field => self.op_field()?,
|
||||||
Op::Element => self.op_element()?,
|
Op::Element => self.op_element()?,
|
||||||
|
Op::Index => self.op_index()?,
|
||||||
Op::Cp => self.op_copy()?,
|
Op::Cp => self.op_copy()?,
|
||||||
//TODO(jwall): Should this take a user provided message?
|
//TODO(jwall): Should this take a user provided message?
|
||||||
Op::Bang => return dbg!(Err(Error {})),
|
Op::Bang => return dbg!(Err(Error {})),
|
||||||
@ -495,19 +497,73 @@ impl<'a> VM {
|
|||||||
Ok(())
|
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> {
|
fn op_copy(&mut self) -> Result<(), Error> {
|
||||||
// TODO Use Cow pointers for this?
|
// TODO Use Cow pointers for this?
|
||||||
// get next value. It should be a Module.
|
// get next value. It should be a Module or Tuple.
|
||||||
let tgt = self.pop()?;
|
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 {
|
match tgt {
|
||||||
C(Tuple(mut flds)) => {
|
C(Tuple(mut flds)) => {
|
||||||
let overrides = self.pop()?;
|
for (name, val) in overrides {
|
||||||
if let C(Tuple(oflds)) = overrides {
|
dbg!(self.merge_field_into_tuple(&mut flds, name, val))?;
|
||||||
for (name, val) in oflds {
|
|
||||||
self.merge_field_into_tuple(&mut flds, name, val)?;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return dbg!(Err(Error {}));
|
|
||||||
}
|
}
|
||||||
// Put the copy on the Stack
|
// Put the copy on the Stack
|
||||||
self.push(C(Tuple(flds)))?;
|
self.push(C(Tuple(flds)))?;
|
||||||
@ -517,17 +573,19 @@ impl<'a> VM {
|
|||||||
result_ptr,
|
result_ptr,
|
||||||
mut flds,
|
mut flds,
|
||||||
}) => {
|
}) => {
|
||||||
let overrides = dbg!(self.pop()?);
|
//let this = M(Module {
|
||||||
if let C(Tuple(oflds)) = overrides {
|
// ptr: ptr.clone(),
|
||||||
for (name, val) in oflds {
|
// result_ptr: result_ptr.clone(),
|
||||||
self.merge_field_into_tuple(&mut flds, name, val)?;
|
// flds: flds.clone(),
|
||||||
}
|
//});
|
||||||
} else {
|
for (name, val) in overrides {
|
||||||
return dbg!(Err(Error {}));
|
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);
|
let mut vm = Self::with_pointer(ptr);
|
||||||
vm.push(S("mod".to_owned()))?;
|
vm.push(S("mod".to_owned()))?;
|
||||||
vm.push(C(Tuple(flds)))?;
|
vm.push(C(Tuple(dbg!(flds))))?;
|
||||||
vm.run()?;
|
vm.run()?;
|
||||||
let mut flds = Vec::new();
|
let mut flds = Vec::new();
|
||||||
if let Some(ptr) = dbg!(result_ptr) {
|
if let Some(ptr) = dbg!(result_ptr) {
|
||||||
|
@ -16,11 +16,11 @@ use std::rc::Rc;
|
|||||||
use super::scope::Stack;
|
use super::scope::Stack;
|
||||||
use super::Composite::{List, Tuple};
|
use super::Composite::{List, Tuple};
|
||||||
use super::Op::{
|
use super::Op::{
|
||||||
Add, Bang, Bind, Cp, DeRef, Div, Element, Equal, FCall, Field, Func, InitList, InitThunk,
|
Add, Bang, Bind, Cp, DeRef, Div, Element, Equal, FCall, Field, Func, Index, InitList,
|
||||||
InitTuple, Jump, JumpIfFalse, JumpIfTrue, Module, Mul, Noop, Pop, Return, SelectJump, Sub, Sym,
|
InitThunk, InitTuple, Jump, JumpIfFalse, JumpIfTrue, Module, Mul, Noop, Pop, Return,
|
||||||
Val,
|
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::Value::{C, P};
|
||||||
use super::VM;
|
use super::VM;
|
||||||
|
|
||||||
@ -356,22 +356,24 @@ fn test_module_call() {
|
|||||||
Sym("two".to_owned()), // 9
|
Sym("two".to_owned()), // 9
|
||||||
Val(Int(2)), // 10
|
Val(Int(2)), // 10
|
||||||
Field, // 11
|
Field, // 11
|
||||||
Module(17), // 12 // Module definition
|
Module(17), // 12 // Module body definition
|
||||||
Bind, // 13
|
Bind, // 13 // bind the mod tuple
|
||||||
Sym("foo".to_owned()), // 14
|
Sym("foo".to_owned()), // 14
|
||||||
DeRef("mod".to_owned()), // 15
|
DeRef("mod".to_owned()), // 15
|
||||||
Bind, // 16 // bind mod tuple to foo
|
Bind, // 16 // bind mod tuple to foo
|
||||||
Return, // 17 // end the module
|
Return, // 17 // end the module
|
||||||
Bind, // 18 // bind module to the binding name
|
Bind, // 18 // bind module to the binding name
|
||||||
DeRef("m".to_owned()), // 19
|
DeRef("m".to_owned()), // 19
|
||||||
Cp, // 20
|
Cp, // 20 // Call the module
|
||||||
] => C(Tuple(vec![(
|
] => C(Tuple(vec![
|
||||||
"foo".to_owned(),
|
(
|
||||||
C(Tuple(vec![
|
"foo".to_owned(),
|
||||||
("one".to_owned(), P(Int(11))),
|
C(Tuple(vec![
|
||||||
("two".to_owned(), P(Int(2))),
|
("one".to_owned(), P(Int(11))),
|
||||||
])),
|
("two".to_owned(), P(Int(2))),
|
||||||
)])),
|
]))
|
||||||
|
),
|
||||||
|
])),
|
||||||
vec![
|
vec![
|
||||||
InitTuple, // 0 // override tuple
|
InitTuple, // 0 // override tuple
|
||||||
Sym("one".to_owned()), // 1
|
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]
|
#[test]
|
||||||
fn test_scope_stacks() {
|
fn test_scope_stacks() {
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user