Split up src/obj.rs
* common macros are in their own private module * functions are in their own obj::function module Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -8,6 +8,7 @@ use common_macros::hash_map;
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
|
use crate::obj::function::UserFunctionInst;
|
||||||
use crate::obj::*;
|
use crate::obj::*;
|
||||||
use crate::token::TokenKind;
|
use crate::token::TokenKind;
|
||||||
use crate::vm::*;
|
use crate::vm::*;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::obj::{ObjP, UserFunctionInst};
|
use crate::obj::function::UserFunctionInst;
|
||||||
|
use crate::obj::ObjP;
|
||||||
use crate::vm::{Chunk, JumpOpArg, Op};
|
use crate::vm::{Chunk, JumpOpArg, Op};
|
||||||
|
|
||||||
type Row = (String, String, &'static str, String, String);
|
type Row = (String, String, &'static str, String, String);
|
||||||
|
|||||||
293
src/obj.rs
293
src/obj.rs
@@ -1,15 +1,20 @@
|
|||||||
// TODO obj.rs - remove the warning suppression
|
// TODO obj.rs - remove the warning suppression
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
mod macros;
|
||||||
|
// Leave this comment here - macros must come first
|
||||||
|
pub mod function;
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::{self, Debug, Display};
|
use std::fmt::{self, Debug, Display};
|
||||||
use std::ptr;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use gc::{Finalize, Gc, GcCell, Trace};
|
use gc::{Finalize, Gc, GcCell, Trace};
|
||||||
|
|
||||||
use crate::vm::{Argc, Chunk, Frame, Vm};
|
use crate::obj::function::*;
|
||||||
|
use crate::obj::macros::*;
|
||||||
|
use crate::vm::{Argc, Chunk, Vm};
|
||||||
|
|
||||||
pub type Ptr<T> = Gc<GcCell<T>>;
|
pub type Ptr<T> = Gc<GcCell<T>>;
|
||||||
pub type ObjP = Ptr<dyn Obj>;
|
pub type ObjP = Ptr<dyn Obj>;
|
||||||
@@ -459,47 +464,6 @@ impl Obj for BaseObjInst {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_base_obj {
|
|
||||||
($base_name:ident) => {
|
|
||||||
fn instantiate(&mut self, ty: ObjP) {
|
|
||||||
self.$base_name.instantiate(ty);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_instantiated(&self) -> bool {
|
|
||||||
self.$base_name.is_instantiated()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn attrs(&self) -> &Attrs {
|
|
||||||
self.$base_name.attrs()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn attrs_mut(&mut self) -> &mut Attrs {
|
|
||||||
self.$base_name.attrs_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
};
|
|
||||||
() => {
|
|
||||||
impl_base_obj! { base }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_create {
|
|
||||||
($($arg:ident : $ty:ty),* $(,)?) => {
|
|
||||||
pub fn create(ty: ObjP $(, $arg : $ty )*) -> ObjP {
|
|
||||||
let ptr = make_ptr(Self::new($($arg),*));
|
|
||||||
ptr.borrow_mut().instantiate(ty);
|
|
||||||
ptr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// ObjInst
|
// ObjInst
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -861,249 +825,6 @@ impl Obj for NilInst {
|
|||||||
impl_base_obj!();
|
impl_base_obj!();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// BuiltinFunctionInst
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
pub type BuiltinFunctionPtr = fn(vm: &mut Vm, args: Vec<ObjP>) -> ObjP;
|
|
||||||
|
|
||||||
#[derive(Debug, Trace)]
|
|
||||||
pub struct BuiltinFunctionInst {
|
|
||||||
base: BaseObjInst,
|
|
||||||
name: String,
|
|
||||||
#[unsafe_ignore_trace]
|
|
||||||
function: BuiltinFunctionPtr,
|
|
||||||
arity: Argc,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BuiltinFunctionInst {
|
|
||||||
pub fn new(name: impl ToString, function: BuiltinFunctionPtr, arity: Argc) -> Self {
|
|
||||||
Self {
|
|
||||||
base: Default::default(),
|
|
||||||
name: name.to_string(),
|
|
||||||
function,
|
|
||||||
arity,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_create!(
|
|
||||||
name: impl ToString,
|
|
||||||
function: BuiltinFunctionPtr,
|
|
||||||
arity: Argc,
|
|
||||||
);
|
|
||||||
|
|
||||||
pub fn name(&self) -> &String {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Finalize for BuiltinFunctionInst {
|
|
||||||
fn finalize(&self) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for BuiltinFunctionInst {
|
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(
|
|
||||||
fmt,
|
|
||||||
"<BuiltinFunction {}/{} at 0x{:x}>",
|
|
||||||
self.name(),
|
|
||||||
self.arity().unwrap(),
|
|
||||||
self.function as *const BuiltinFunctionPtr as usize
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Obj for BuiltinFunctionInst {
|
|
||||||
fn arity(&self) -> Option<Argc> {
|
|
||||||
Some(self.arity)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&self, vm: &mut Vm, argc: Argc) {
|
|
||||||
// args
|
|
||||||
let mut args = Vec::with_capacity(argc as usize);
|
|
||||||
for _ in 0..argc {
|
|
||||||
args.push(vm.pop());
|
|
||||||
}
|
|
||||||
args.reverse();
|
|
||||||
// callee (self)
|
|
||||||
vm.pop();
|
|
||||||
let result = (self.function)(vm, args);
|
|
||||||
vm.push(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn equals(&self, other: &dyn Obj) -> bool {
|
|
||||||
// TODO BuiltinFunctionInst::equals : need something more robust than checking addr_eq,
|
|
||||||
// maybe check the self_binding pointer too?
|
|
||||||
if let Some(other) = other.as_any().downcast_ref::<BuiltinFunctionInst>() {
|
|
||||||
ptr::addr_eq(self, other)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_base_obj!();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// UserFunctionInst
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Trace)]
|
|
||||||
pub struct UserFunctionInst {
|
|
||||||
base: BaseObjInst,
|
|
||||||
#[unsafe_ignore_trace]
|
|
||||||
name: Rc<String>,
|
|
||||||
#[unsafe_ignore_trace]
|
|
||||||
chunk: Rc<Chunk>,
|
|
||||||
arity: Argc,
|
|
||||||
captures: Vec<ObjP>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UserFunctionInst {
|
|
||||||
pub fn new(chunk: Chunk, arity: Argc) -> Self {
|
|
||||||
Self {
|
|
||||||
base: Default::default(),
|
|
||||||
name: Rc::new("(anonymous)".to_string()),
|
|
||||||
chunk: Rc::new(chunk),
|
|
||||||
arity,
|
|
||||||
captures: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_create!(chunk: Chunk, arity: Argc);
|
|
||||||
|
|
||||||
pub fn name(&self) -> &String {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_name(&mut self, name: Rc<String>) {
|
|
||||||
self.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn chunk(&self) -> &Chunk {
|
|
||||||
&self.chunk
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_capture(&mut self, value: ObjP) {
|
|
||||||
self.captures.push(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Finalize for UserFunctionInst {
|
|
||||||
fn finalize(&self) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for UserFunctionInst {
|
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(
|
|
||||||
fmt,
|
|
||||||
"<UserFunction {}/{} at 0x{:x}>",
|
|
||||||
self.name(),
|
|
||||||
self.arity().unwrap(),
|
|
||||||
self as *const _ as usize
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Obj for UserFunctionInst {
|
|
||||||
fn arity(&self) -> Option<Argc> {
|
|
||||||
Some(self.arity)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&self, vm: &mut Vm, argc: Argc) {
|
|
||||||
assert_eq!(argc, self.arity, "argc must match arity");
|
|
||||||
let new_frame = Frame {
|
|
||||||
name: Rc::clone(&self.name),
|
|
||||||
chunk: Rc::clone(&self.chunk),
|
|
||||||
ip: 0,
|
|
||||||
stack_base: vm.stack().len() - (argc as usize),
|
|
||||||
};
|
|
||||||
vm.push_frame(new_frame);
|
|
||||||
for capture in &self.captures {
|
|
||||||
vm.push(Ptr::clone(&capture));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn equals(&self, other: &dyn Obj) -> bool {
|
|
||||||
if let Some(other) = other.as_any().downcast_ref::<UserFunctionInst>() {
|
|
||||||
// TODO UserFunctionInst::equals : need something more robust than checking addr_eq.
|
|
||||||
ptr::addr_eq(self, other)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_base_obj!();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// MethodInst
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#[derive(Debug, Trace)]
|
|
||||||
pub struct MethodInst {
|
|
||||||
base: BaseObjInst,
|
|
||||||
self_binding: ObjP,
|
|
||||||
function: ObjP,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MethodInst {
|
|
||||||
pub fn new(self_binding: ObjP, function: ObjP) -> Self {
|
|
||||||
Self {
|
|
||||||
base: Default::default(),
|
|
||||||
self_binding,
|
|
||||||
function,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create(ty: ObjP, self_binding: ObjP, function: ObjP) -> ObjP {
|
|
||||||
let ptr = make_ptr(Self::new(self_binding, function));
|
|
||||||
ptr.borrow_mut().instantiate(ty.clone());
|
|
||||||
ptr
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn self_binding(&self) -> &ObjP {
|
|
||||||
&self.self_binding
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Finalize for MethodInst {
|
|
||||||
fn finalize(&self) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for MethodInst {
|
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(fmt, "{}", self.function.borrow())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Obj for MethodInst {
|
|
||||||
fn arity(&self) -> Option<Argc> {
|
|
||||||
// Subtract one from the arity - this is because the VM uses arity() to check against the
|
|
||||||
// number of arguments passed.
|
|
||||||
self.function.borrow().arity().map(|arity| arity - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&self, vm: &mut Vm, mut argc: Argc) {
|
|
||||||
let self_pos = vm.stack().len() - (argc as usize);
|
|
||||||
vm.stack_mut().insert(self_pos, self.self_binding.clone());
|
|
||||||
argc += 1;
|
|
||||||
|
|
||||||
self.function.borrow().call(vm, argc)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn equals(&self, other: &dyn Obj) -> bool {
|
|
||||||
if let Some(other) = other.as_any().downcast_ref::<MethodInst>() {
|
|
||||||
ptr::addr_eq(&*self.self_binding, &*other.self_binding)
|
|
||||||
&& ptr::addr_eq(&*self.function, &*other.function)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_base_obj!();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Tests
|
// Tests
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
252
src/obj/function.rs
Normal file
252
src/obj/function.rs
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
use std::fmt::{self, Debug, Display};
|
||||||
|
use std::ptr;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use gc::{Finalize, Trace};
|
||||||
|
|
||||||
|
use crate::obj::macros::*;
|
||||||
|
use crate::obj::{make_ptr, BaseObjInst, Obj, ObjP};
|
||||||
|
use crate::vm::{Argc, Chunk, Frame, Vm};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// BuiltinFunctionInst
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
pub type BuiltinFunctionPtr = fn(vm: &mut Vm, args: Vec<ObjP>) -> ObjP;
|
||||||
|
|
||||||
|
#[derive(Debug, Trace)]
|
||||||
|
pub struct BuiltinFunctionInst {
|
||||||
|
base: BaseObjInst,
|
||||||
|
name: String,
|
||||||
|
#[unsafe_ignore_trace]
|
||||||
|
function: BuiltinFunctionPtr,
|
||||||
|
arity: Argc,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuiltinFunctionInst {
|
||||||
|
pub fn new(name: impl ToString, function: BuiltinFunctionPtr, arity: Argc) -> Self {
|
||||||
|
Self {
|
||||||
|
base: Default::default(),
|
||||||
|
name: name.to_string(),
|
||||||
|
function,
|
||||||
|
arity,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_create!(
|
||||||
|
name: impl ToString,
|
||||||
|
function: BuiltinFunctionPtr,
|
||||||
|
arity: Argc,
|
||||||
|
);
|
||||||
|
|
||||||
|
pub fn name(&self) -> &String {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Finalize for BuiltinFunctionInst {
|
||||||
|
fn finalize(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for BuiltinFunctionInst {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
fmt,
|
||||||
|
"<BuiltinFunction {}/{} at 0x{:x}>",
|
||||||
|
self.name(),
|
||||||
|
self.arity().unwrap(),
|
||||||
|
self.function as *const BuiltinFunctionPtr as usize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Obj for BuiltinFunctionInst {
|
||||||
|
fn arity(&self) -> Option<Argc> {
|
||||||
|
Some(self.arity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&self, vm: &mut Vm, argc: Argc) {
|
||||||
|
// args
|
||||||
|
let mut args = Vec::with_capacity(argc as usize);
|
||||||
|
for _ in 0..argc {
|
||||||
|
args.push(vm.pop());
|
||||||
|
}
|
||||||
|
args.reverse();
|
||||||
|
// callee (self)
|
||||||
|
vm.pop();
|
||||||
|
let result = (self.function)(vm, args);
|
||||||
|
vm.push(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn equals(&self, other: &dyn Obj) -> bool {
|
||||||
|
// TODO BuiltinFunctionInst::equals : need something more robust than checking addr_eq,
|
||||||
|
// maybe check the self_binding pointer too?
|
||||||
|
if let Some(other) = other.as_any().downcast_ref::<BuiltinFunctionInst>() {
|
||||||
|
ptr::addr_eq(self, other)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_base_obj!();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// UserFunctionInst
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Trace)]
|
||||||
|
pub struct UserFunctionInst {
|
||||||
|
base: BaseObjInst,
|
||||||
|
#[unsafe_ignore_trace]
|
||||||
|
name: Rc<String>,
|
||||||
|
#[unsafe_ignore_trace]
|
||||||
|
chunk: Rc<Chunk>,
|
||||||
|
arity: Argc,
|
||||||
|
captures: Vec<ObjP>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UserFunctionInst {
|
||||||
|
pub fn new(chunk: Chunk, arity: Argc) -> Self {
|
||||||
|
Self {
|
||||||
|
base: Default::default(),
|
||||||
|
name: Rc::new("(anonymous)".to_string()),
|
||||||
|
chunk: Rc::new(chunk),
|
||||||
|
arity,
|
||||||
|
captures: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_create!(chunk: Chunk, arity: Argc);
|
||||||
|
|
||||||
|
pub fn name(&self) -> &String {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_name(&mut self, name: Rc<String>) {
|
||||||
|
self.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chunk(&self) -> &Chunk {
|
||||||
|
&self.chunk
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_capture(&mut self, value: ObjP) {
|
||||||
|
self.captures.push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Finalize for UserFunctionInst {
|
||||||
|
fn finalize(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for UserFunctionInst {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
fmt,
|
||||||
|
"<UserFunction {}/{} at 0x{:x}>",
|
||||||
|
self.name(),
|
||||||
|
self.arity().unwrap(),
|
||||||
|
self as *const _ as usize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Obj for UserFunctionInst {
|
||||||
|
fn arity(&self) -> Option<Argc> {
|
||||||
|
Some(self.arity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&self, vm: &mut Vm, argc: Argc) {
|
||||||
|
assert_eq!(argc, self.arity, "argc must match arity");
|
||||||
|
let new_frame = Frame {
|
||||||
|
name: Rc::clone(&self.name),
|
||||||
|
chunk: Rc::clone(&self.chunk),
|
||||||
|
ip: 0,
|
||||||
|
stack_base: vm.stack().len() - (argc as usize),
|
||||||
|
};
|
||||||
|
vm.push_frame(new_frame);
|
||||||
|
for capture in &self.captures {
|
||||||
|
vm.push(capture.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn equals(&self, other: &dyn Obj) -> bool {
|
||||||
|
if let Some(other) = other.as_any().downcast_ref::<UserFunctionInst>() {
|
||||||
|
// TODO UserFunctionInst::equals : need something more robust than checking addr_eq.
|
||||||
|
ptr::addr_eq(self, other)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_base_obj!();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// MethodInst
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[derive(Debug, Trace)]
|
||||||
|
pub struct MethodInst {
|
||||||
|
base: BaseObjInst,
|
||||||
|
self_binding: ObjP,
|
||||||
|
function: ObjP,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MethodInst {
|
||||||
|
pub fn new(self_binding: ObjP, function: ObjP) -> Self {
|
||||||
|
Self {
|
||||||
|
base: Default::default(),
|
||||||
|
self_binding,
|
||||||
|
function,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create(ty: ObjP, self_binding: ObjP, function: ObjP) -> ObjP {
|
||||||
|
let ptr = make_ptr(Self::new(self_binding, function));
|
||||||
|
ptr.borrow_mut().instantiate(ty.clone());
|
||||||
|
ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn self_binding(&self) -> &ObjP {
|
||||||
|
&self.self_binding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Finalize for MethodInst {
|
||||||
|
fn finalize(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for MethodInst {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(fmt, "{}", self.function.borrow())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Obj for MethodInst {
|
||||||
|
fn arity(&self) -> Option<Argc> {
|
||||||
|
// Subtract one from the arity - this is because the VM uses arity() to check against the
|
||||||
|
// number of arguments passed.
|
||||||
|
self.function.borrow().arity().map(|arity| arity - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&self, vm: &mut Vm, mut argc: Argc) {
|
||||||
|
let self_pos = vm.stack().len() - (argc as usize);
|
||||||
|
vm.stack_mut().insert(self_pos, self.self_binding.clone());
|
||||||
|
argc += 1;
|
||||||
|
|
||||||
|
self.function.borrow().call(vm, argc)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn equals(&self, other: &dyn Obj) -> bool {
|
||||||
|
if let Some(other) = other.as_any().downcast_ref::<MethodInst>() {
|
||||||
|
ptr::addr_eq(&*self.self_binding, &*other.self_binding)
|
||||||
|
&& ptr::addr_eq(&*self.function, &*other.function)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_base_obj!();
|
||||||
|
}
|
||||||
43
src/obj/macros.rs
Normal file
43
src/obj/macros.rs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
macro_rules! impl_base_obj {
|
||||||
|
($base_name:ident) => {
|
||||||
|
fn instantiate(&mut self, ty: $crate::obj::ObjP) {
|
||||||
|
self.$base_name.instantiate(ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_instantiated(&self) -> bool {
|
||||||
|
self.$base_name.is_instantiated()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attrs(&self) -> &$crate::obj::Attrs {
|
||||||
|
self.$base_name.attrs()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attrs_mut(&mut self) -> &mut $crate::obj::Attrs {
|
||||||
|
self.$base_name.attrs_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
};
|
||||||
|
() => {
|
||||||
|
impl_base_obj! { base }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_create {
|
||||||
|
($($arg:ident : $ty:ty),* $(,)?) => {
|
||||||
|
pub fn create(ty: $crate::obj::ObjP $(, $arg : $ty )*) -> $crate::obj::ObjP {
|
||||||
|
let ptr = make_ptr(Self::new($($arg),*));
|
||||||
|
ptr.borrow_mut().instantiate(ty);
|
||||||
|
ptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use impl_base_obj;
|
||||||
|
pub(crate) use impl_create;
|
||||||
Reference in New Issue
Block a user