Add Method type for objects

* Methods are wrappers created with an owner and a function, which
  passes the owner as the first argument when the function is called.
* Fix a small bug in the VM where the pc was being set at the wrong
  time

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-10-08 16:10:10 -07:00
parent c3121a176c
commit c738c52455
4 changed files with 90 additions and 15 deletions

View File

@@ -1,4 +1,5 @@
use crate::obj::prelude::*;
use crate::obj::{prelude::*, reserved::*};
use once_cell::sync::Lazy;
use shredder::Scan;
use std::fmt::{Debug, Formatter, self};
@@ -13,14 +14,18 @@ pub struct Int {
impl Int {
pub fn new_obj(value: i64) -> ObjRef<Self> {
// TODO : vtable for Int
let obj_ref = ObjRef::new(Self {
value,
vtable: Default::default(),
attrs: Default::default(),
});
obj_ref
// TODO : cache int values
self_referring_obj! {
Self {
value,
vtable: Default::default(),
attrs: Default::default(),
},
vtable: |obj_ref: ObjRef| vtable! {
// TODO needs Method type so this function is given an argument when called
STR_MEMBER_NAME.sym => Method::new_obj(obj_ref.clone(), INT_STR_FUN.clone()),
}
}
}
pub fn value(&self) -> i64 {
@@ -37,3 +42,15 @@ impl Debug for Int {
.finish()
}
}
static INT_STR_FUN: Lazy<NativeFunRef> = Lazy::new(|| {
NativeFun::new_obj(|_callee, vm, args| {
read_obj!(let int_obj = &args[0]);
if let Some(int_obj) = std::any::Any::downcast_ref::<Int>(int_obj.as_any()) {
vm.push(Str::new_obj(int_obj.value.to_string()));
} else {
panic!("{:?} is not an int", int_obj)
}
crate::vm::signal::Signal::Return
})
});