[fine] Support assignment to member, loops with iterators

Hmm it's starting to look like something.
This commit is contained in:
John Doty 2024-02-07 01:57:41 -08:00
parent 3415b1a3f6
commit 239e859eaf
7 changed files with 360 additions and 171 deletions

View file

@ -1,3 +1,4 @@
use std::cell::RefCell;
use std::rc::Rc;
use crate::compiler::{Export, Function, Instruction, Module};
@ -48,17 +49,17 @@ type Result<T> = std::result::Result<T, VMErrorCode>;
pub struct Object {
name: Rc<str>,
class_id: i64,
values: Box<[StackValue]>,
values: RefCell<Box<[StackValue]>>,
}
impl Object {
pub fn get_slot(&self, index: usize) -> Result<StackValue> {
match self.values.get(index) {
match self.values.borrow().get(index) {
Some(v) => Ok(v.clone()),
None => Err(VMErrorCode::SlotOutOfRange(
index,
self.name.clone(),
self.values.len(),
self.values.borrow().len(),
)),
}
}
@ -76,6 +77,43 @@ pub enum StackValue {
Object(Rc<Object>),
}
impl StackValue {
pub fn is_object(&self, id: i64) -> bool {
match self {
StackValue::Object(o) => o.class_id == id,
_ => false,
}
}
pub fn is_float(&self) -> bool {
match self {
StackValue::Float(_) => true,
_ => false,
}
}
pub fn is_nothing(&self) -> bool {
match self {
StackValue::Nothing => true,
_ => false,
}
}
pub fn is_bool(&self) -> bool {
match self {
StackValue::Bool(_) => true,
_ => false,
}
}
pub fn is_string(&self) -> bool {
match self {
StackValue::String(_) => true,
_ => false,
}
}
}
enum FuncValue {
Function(Rc<Function>),
ExternFunction(usize),
@ -387,6 +425,11 @@ fn eval_one(
let v = f.pop_value()?;
c.set_global(i, v)?;
}
Instruction::StoreSlot(i) => {
let o = f.pop_object()?;
let v = f.pop_value()?;
o.values.borrow_mut()[i] = v;
}
Instruction::LoadFunction(i) => {
let v = c.get_function(i)?;
f.push_function(v);
@ -477,7 +520,7 @@ fn eval_one(
let object = Object {
name,
class_id,
values: values.into(),
values: RefCell::new(values.into()),
};
f.push_object(object.into());
@ -488,16 +531,27 @@ fn eval_one(
}
Instruction::IsClass(id) => {
let value = f.pop_value()?;
match value {
StackValue::Object(o) => {
f.push_bool(o.class_id == id);
}
_ => f.push_bool(false),
}
f.push_bool(value.is_object(id));
}
Instruction::PushInt(v) => {
f.push_int(v);
}
Instruction::IsBool => {
let v = f.pop_value()?;
f.push_bool(v.is_bool());
}
Instruction::IsFloat => {
let v = f.pop_value()?;
f.push_bool(v.is_float());
}
Instruction::IsString => {
let v = f.pop_value()?;
f.push_bool(v.is_string());
}
Instruction::IsNothing => {
let v = f.pop_value()?;
f.push_bool(v.is_nothing());
}
}
Ok(Flow::Continue)