Big Object naming refactor

* trait Obj -> Object
* Remove *Inst suffix from all object types. ObjInst -> Obj, IntInst ->
  Int, etc
* Type -> Ty, type_inst() -> ty(), type_name() -> ty_name()

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2024-09-26 11:07:12 -07:00
parent 3a9bee0e35
commit 9d5d094c5b
7 changed files with 342 additions and 356 deletions

View File

@@ -1,5 +1,5 @@
//! Builtin functions. //! Builtin functions.
use crate::obj::function::{BuiltinFunctionInst, FunctionResult, FunctionState}; use crate::obj::function::{BuiltinFunction, FunctionResult, FunctionState};
use crate::obj::*; use crate::obj::*;
use crate::vm::Vm; use crate::vm::Vm;
@@ -7,7 +7,7 @@ pub fn init_global_builtins() {
macro_rules! builtins { macro_rules! builtins {
($($builtin:ident / $argc:expr),* $(,)?) => { ($($builtin:ident / $argc:expr),* $(,)?) => {
$({ $({
let builtin_function = BuiltinFunctionInst::create(stringify!($builtin), $builtin, $argc); let builtin_function = BuiltinFunction::create(stringify!($builtin), $builtin, $argc);
$crate::obj::BUILTINS.with_borrow_mut(|builtins| $crate::obj::BUILTINS.with_borrow_mut(|builtins|
builtins.insert( builtins.insert(
stringify!($builtin).to_string(), stringify!($builtin).to_string(),
@@ -50,7 +50,7 @@ pub(crate) fn println(vm: &mut Vm, state: FunctionState) -> FunctionResult {
} }
FunctionState::Resume(0) => { FunctionState::Resume(0) => {
println!("{}", vm.frame_stack()[0].borrow()); println!("{}", vm.frame_stack()[0].borrow());
NilInst::create().into() Nil::create().into()
} }
_ => unreachable!(), _ => unreachable!(),
} }
@@ -69,17 +69,17 @@ pub(crate) fn print(vm: &mut Vm, state: FunctionState) -> FunctionResult {
} }
FunctionState::Resume(0) => { FunctionState::Resume(0) => {
print!("{}", vm.frame_stack()[0].borrow()); print!("{}", vm.frame_stack()[0].borrow());
NilInst::create().into() Nil::create().into()
} }
_ => unreachable!(), _ => unreachable!(),
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// BaseObjInst implementations // BaseObj implementations
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
impl BaseObjInst { impl BaseObj {
// //
// Common functions // Common functions
// //
@@ -103,11 +103,11 @@ impl BaseObjInst {
pub(crate) fn to_repr(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn to_repr(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let str_value = format!("{}", vm.frame_stack()[0].borrow()); let str_value = format!("{}", vm.frame_stack()[0].borrow());
StrInst::create(str_value).into() Str::create(str_value).into()
} }
pub(crate) fn to_bool(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn to_bool(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
BoolInst::create(vm.frame_stack()[0].borrow().is_truthy()).into() Bool::create(vm.frame_stack()[0].borrow().is_truthy()).into()
} }
// //
@@ -118,14 +118,14 @@ impl BaseObjInst {
let lhs = vm.frame_stack()[0].borrow(); let lhs = vm.frame_stack()[0].borrow();
let rhs = vm.frame_stack()[1].borrow(); let rhs = vm.frame_stack()[1].borrow();
let result = lhs.is_truthy() && rhs.is_truthy(); let result = lhs.is_truthy() && rhs.is_truthy();
BoolInst::create(result).into() Bool::create(result).into()
} }
pub(crate) fn or(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn or(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let lhs = vm.frame_stack()[0].borrow(); let lhs = vm.frame_stack()[0].borrow();
let rhs = vm.frame_stack()[1].borrow(); let rhs = vm.frame_stack()[1].borrow();
let result = lhs.is_truthy() || rhs.is_truthy(); let result = lhs.is_truthy() || rhs.is_truthy();
BoolInst::create(result).into() Bool::create(result).into()
} }
pub(crate) fn ne(vm: &mut Vm, state: FunctionState) -> FunctionResult { pub(crate) fn ne(vm: &mut Vm, state: FunctionState) -> FunctionResult {
@@ -145,7 +145,7 @@ impl BaseObjInst {
} }
FunctionState::Resume(0) => { FunctionState::Resume(0) => {
let result = !vm.peek().borrow().is_truthy(); let result = !vm.peek().borrow().is_truthy();
BoolInst::create(result).into() Bool::create(result).into()
} }
_ => { _ => {
unreachable!() unreachable!()
@@ -157,7 +157,7 @@ impl BaseObjInst {
let lhs = vm.frame_stack()[0].borrow(); let lhs = vm.frame_stack()[0].borrow();
let rhs = vm.frame_stack()[1].borrow(); let rhs = vm.frame_stack()[1].borrow();
let equals = lhs.equals(&*rhs); let equals = lhs.equals(&*rhs);
BoolInst::create(equals).into() Bool::create(equals).into()
} }
pub(crate) fn not(vm: &mut Vm, state: FunctionState) -> FunctionResult { pub(crate) fn not(vm: &mut Vm, state: FunctionState) -> FunctionResult {
@@ -173,7 +173,7 @@ impl BaseObjInst {
} }
FunctionState::Resume(0) => { FunctionState::Resume(0) => {
let value = vm.peek().borrow().is_truthy(); let value = vm.peek().borrow().is_truthy();
BoolInst::create(!value).into() Bool::create(!value).into()
} }
_ => unreachable!(), _ => unreachable!(),
} }
@@ -185,7 +185,7 @@ impl BaseObjInst {
pub(crate) fn not_implemented_un(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn not_implemented_un(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let fname = &vm.frame().name; let fname = &vm.frame().name;
// TODO BaseObjInst::not_implemented_un - throw an exception of some kind for not // TODO BaseObj::not_implemented_un - throw an exception of some kind for not
// implemented/not available errors on unary operators // implemented/not available errors on unary operators
// BLOCKED-ON: exceptions // BLOCKED-ON: exceptions
todo!( todo!(
@@ -196,7 +196,7 @@ impl BaseObjInst {
} }
pub(crate) fn not_implemented_bin(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn not_implemented_bin(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
// TODO BaseObjInst::not_implemented_un - throw an exception of some kind for not // TODO BaseObj::not_implemented_un - throw an exception of some kind for not
// implemented/not available errors on unary operators // implemented/not available errors on unary operators
// BLOCKED-ON: exceptions // BLOCKED-ON: exceptions
let fname = &vm.frame().name; let fname = &vm.frame().name;
@@ -205,30 +205,29 @@ impl BaseObjInst {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// StrInst implementations // Str implementations
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
impl StrInst { impl Str {
pub(crate) fn to_str(_vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn to_str(_vm: &mut Vm, _state: FunctionState) -> FunctionResult {
// top item of the stack should just be ourselves, so return immediately // top item of the stack should just be ourselves, so return immediately
FunctionResult::Return FunctionResult::Return
} }
pub(crate) fn to_repr(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn to_repr(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let escaped: String = let escaped: String = with_obj_downcast(vm.frame_stack()[0].clone(), |str_inst: &Str| {
with_obj_downcast(vm.frame_stack()[0].clone(), |str_inst: &StrInst| {
str_inst.str_value().as_str().escape_default().collect() str_inst.str_value().as_str().escape_default().collect()
}); });
StrInst::create(format!("'{}'", escaped)).into() Str::create(format!("'{}'", escaped)).into()
} }
pub(crate) fn to_int(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn to_int(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let parsed: Result<i64, _> = let parsed: Result<i64, _> =
with_obj_downcast(vm.frame_stack()[0].clone(), |str_inst: &StrInst| { with_obj_downcast(vm.frame_stack()[0].clone(), |str_inst: &Str| {
str_inst.str_value().parse() str_inst.str_value().parse()
}); });
match parsed { match parsed {
Ok(int) => IntInst::create(int).into(), Ok(int) => Int::create(int).into(),
// TODO StrInst::to_int - throw an exception when we fail to parse an integer // TODO Str::to_int - throw an exception when we fail to parse an integer
// BLOCKED-ON - exceptions // BLOCKED-ON - exceptions
Err(e) => todo!("error parsing string to an integer: {}", e), Err(e) => todo!("error parsing string to an integer: {}", e),
} }
@@ -236,61 +235,61 @@ impl StrInst {
pub(crate) fn to_float(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn to_float(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let parsed: Result<f64, _> = let parsed: Result<f64, _> =
with_obj_downcast(vm.frame_stack()[0].clone(), |str_inst: &StrInst| { with_obj_downcast(vm.frame_stack()[0].clone(), |str_inst: &Str| {
str_inst.str_value().parse() str_inst.str_value().parse()
}); });
match parsed { match parsed {
Ok(float) => FloatInst::create(float).into(), Ok(float) => Float::create(float).into(),
// TODO StrInst::to_int - throw an exception when we fail to parse an integer // TODO Str::to_int - throw an exception when we fail to parse an integer
// BLOCKED-ON - exceptions // BLOCKED-ON - exceptions
Err(e) => todo!("error parsing string to a float: {}", e), Err(e) => todo!("error parsing string to a float: {}", e),
} }
} }
pub(crate) fn len(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn len(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let len = with_obj_downcast(vm.frame_stack()[0].clone(), |str_inst: &StrInst| { let len = with_obj_downcast(vm.frame_stack()[0].clone(), |str_inst: &Str| {
str_inst.str_value().len() as i64 str_inst.str_value().len() as i64
}); });
IntInst::create(len).into() Int::create(len).into()
} }
pub(crate) fn add(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn add(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let lhs = vm.frame_stack()[0].clone(); let lhs = vm.frame_stack()[0].clone();
let rhs = vm.frame_stack()[1].clone(); let rhs = vm.frame_stack()[1].clone();
if !obj_is_inst::<StrInst>(&rhs) { if !obj_is_inst::<Str>(&rhs) {
// TODO StrInst::add - throw an exception when the RHS is not a string // TODO Str::add - throw an exception when the RHS is not a string
// BLOCKED-ON: exceptions // BLOCKED-ON: exceptions
todo!( todo!(
"can only concatenate Str, got {} instead", "can only concatenate Str, got {} instead",
rhs.borrow().type_name() rhs.borrow().ty_name()
) )
} }
let new = format!("{}{}", lhs.borrow(), rhs.borrow()); let new = format!("{}{}", lhs.borrow(), rhs.borrow());
StrInst::create(new).into() Str::create(new).into()
} }
pub(crate) fn mul(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn mul(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let lhs = vm.frame_stack()[0].clone(); let lhs = vm.frame_stack()[0].clone();
let rhs = vm.frame_stack()[1].clone(); let rhs = vm.frame_stack()[1].clone();
let repeat_count = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<IntInst>() { let repeat_count = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<Int>() {
int_inst.int_value() int_inst.int_value()
} else { } else {
// TODO StrInst::mul - throw an exception when the RHS is not an int // TODO Str::mul - throw an exception when the RHS is not an int
// BLOCKED-ON: exceptions // BLOCKED-ON: exceptions
todo!( todo!(
"can only repeat Str with Int, got {} instead", "can only repeat Str with Int, got {} instead",
rhs.borrow().type_name() rhs.borrow().ty_name()
) )
}; };
let repeat_count = repeat_count.max(0) as usize; let repeat_count = repeat_count.max(0) as usize;
let new = format!("{}", lhs.borrow()).repeat(repeat_count); let new = format!("{}", lhs.borrow()).repeat(repeat_count);
StrInst::create(new).into() Str::create(new).into()
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// IntInst implementations // Int implementations
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
macro_rules! int_bin_op_math { macro_rules! int_bin_op_math {
@@ -299,18 +298,18 @@ macro_rules! int_bin_op_math {
let lhs = vm.frame_stack()[0].clone(); let lhs = vm.frame_stack()[0].clone();
let rhs = vm.frame_stack()[1].clone(); let rhs = vm.frame_stack()[1].clone();
let lhs_value = with_obj_downcast(lhs, IntInst::int_value); let lhs_value = with_obj_downcast(lhs, Int::int_value);
let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<IntInst>() { let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<Int>() {
IntInst::create(lhs_value $op int_inst.int_value()) Int::create(lhs_value $op int_inst.int_value())
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<FloatInst>() { } else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<Float>() {
FloatInst::create(lhs_value as f64 $op float_inst.float_value()) Float::create(lhs_value as f64 $op float_inst.float_value())
} else { } else {
// TODO IntInst arithmetic operator - throw an exception when RHS is not Int, Float // TODO Int arithmetic operator - throw an exception when RHS is not Int, Float
// BLOCKED-ON: exceptions // BLOCKED-ON: exceptions
todo!( todo!(
concat!("cannot use '", stringify!($op), "' operator with Int and {}"), concat!("cannot use '", stringify!($op), "' operator with Int and {}"),
rhs.borrow().type_name() rhs.borrow().ty_name()
) )
}; };
result.into() result.into()
@@ -324,18 +323,18 @@ macro_rules! int_bin_op_logical {
let lhs = vm.frame_stack()[0].clone(); let lhs = vm.frame_stack()[0].clone();
let rhs = vm.frame_stack()[1].clone(); let rhs = vm.frame_stack()[1].clone();
let lhs_value = with_obj_downcast(lhs, IntInst::int_value); let lhs_value = with_obj_downcast(lhs, Int::int_value);
let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<IntInst>() { let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<Int>() {
BoolInst::create(lhs_value $op int_inst.int_value()) Bool::create(lhs_value $op int_inst.int_value())
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<FloatInst>() { } else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<Float>() {
BoolInst::create((lhs_value as f64) $op float_inst.float_value()) Bool::create((lhs_value as f64) $op float_inst.float_value())
} else { } else {
// TODO IntInst logical operator - throw an exception when RHS is not Int, Float // TODO Int logical operator - throw an exception when RHS is not Int, Float
// BLOCKED-ON: exceptions // BLOCKED-ON: exceptions
todo!( todo!(
concat!("cannot use '", stringify!($op), "' operator with Int and {}"), concat!("cannot use '", stringify!($op), "' operator with Int and {}"),
rhs.borrow().type_name() rhs.borrow().ty_name()
) )
}; };
result.into() result.into()
@@ -343,14 +342,14 @@ macro_rules! int_bin_op_logical {
} }
} }
impl IntInst { impl Int {
pub(crate) fn to_int(_vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn to_int(_vm: &mut Vm, _state: FunctionState) -> FunctionResult {
FunctionResult::Return FunctionResult::Return
} }
pub(crate) fn to_float(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn to_float(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let int_value = with_obj_downcast(vm.frame_stack()[0].clone(), IntInst::int_value); let int_value = with_obj_downcast(vm.frame_stack()[0].clone(), Int::int_value);
FloatInst::create(int_value as f64).into() Float::create(int_value as f64).into()
} }
int_bin_op_math!(add, +); int_bin_op_math!(add, +);
@@ -361,28 +360,28 @@ impl IntInst {
let lhs = vm.frame_stack()[0].clone(); let lhs = vm.frame_stack()[0].clone();
let rhs = vm.frame_stack()[1].clone(); let rhs = vm.frame_stack()[1].clone();
let lhs_value = with_obj_downcast(lhs, IntInst::int_value); let lhs_value = with_obj_downcast(lhs, Int::int_value);
let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<IntInst>() { let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<Int>() {
IntInst::create(lhs_value * int_inst.int_value()) Int::create(lhs_value * int_inst.int_value())
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<FloatInst>() { } else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<Float>() {
FloatInst::create(lhs_value as f64 * float_inst.float_value()) Float::create(lhs_value as f64 * float_inst.float_value())
} else if let Some(str_inst) = rhs.borrow().as_any().downcast_ref::<StrInst>() { } else if let Some(str_inst) = rhs.borrow().as_any().downcast_ref::<Str>() {
// TODO IntInst::mul - maybe convert this to just call Str.mul with arguments reversed? // TODO Int::mul - maybe convert this to just call Str.mul with arguments reversed?
// Just so we have the same logic here // Just so we have the same logic here
StrInst::create(str_inst.str_value().repeat(lhs_value as usize)) Str::create(str_inst.str_value().repeat(lhs_value as usize))
} else { } else {
// TODO IntInst::mul - throw an exception when RHS is not Int, Float, Str // TODO Int::mul - throw an exception when RHS is not Int, Float, Str
// BLOCKED-ON: exceptions // BLOCKED-ON: exceptions
todo!( todo!(
"cannot use '*' operator with Int and {}", "cannot use '*' operator with Int and {}",
rhs.borrow().type_name() rhs.borrow().ty_name()
) )
}; };
result.into() result.into()
} }
// TODO IntInst::div - handle divide by zero // TODO Int::div - handle divide by zero
// BLOCKED-ON: exceptions // BLOCKED-ON: exceptions
// NOTE - we will probably need to get rid of the macro here to handle that :( // NOTE - we will probably need to get rid of the macro here to handle that :(
int_bin_op_math!(div, /); int_bin_op_math!(div, /);
@@ -397,19 +396,19 @@ impl IntInst {
pub(crate) fn pos(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn pos(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let lhs = vm.frame_stack()[0].clone(); let lhs = vm.frame_stack()[0].clone();
let value = with_obj_downcast(lhs, IntInst::int_value); let value = with_obj_downcast(lhs, Int::int_value);
IntInst::create(value.abs()).into() Int::create(value.abs()).into()
} }
pub(crate) fn neg(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn neg(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let lhs = vm.frame_stack()[0].clone(); let lhs = vm.frame_stack()[0].clone();
let value = with_obj_downcast(lhs, IntInst::int_value); let value = with_obj_downcast(lhs, Int::int_value);
IntInst::create(-value).into() Int::create(-value).into()
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// FloatInst implementations // Float implementations
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
macro_rules! float_bin_op_math { macro_rules! float_bin_op_math {
@@ -418,18 +417,18 @@ macro_rules! float_bin_op_math {
let lhs = vm.frame_stack()[0].clone(); let lhs = vm.frame_stack()[0].clone();
let rhs = vm.frame_stack()[1].clone(); let rhs = vm.frame_stack()[1].clone();
let lhs_value = with_obj_downcast(lhs, FloatInst::float_value); let lhs_value = with_obj_downcast(lhs, Float::float_value);
let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<IntInst>() { let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<Int>() {
FloatInst::create(lhs_value $op int_inst.int_value() as f64) Float::create(lhs_value $op int_inst.int_value() as f64)
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<FloatInst>() { } else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<Float>() {
FloatInst::create(lhs_value $op float_inst.float_value()) Float::create(lhs_value $op float_inst.float_value())
} else { } else {
// TODO IntInst arithmetic operator - throw an exception when RHS is not Int, Float // TODO Int arithmetic operator - throw an exception when RHS is not Int, Float
// BLOCKED-ON: exceptions // BLOCKED-ON: exceptions
todo!( todo!(
concat!("cannot use '", stringify!($op), "' operator with Float and {}"), concat!("cannot use '", stringify!($op), "' operator with Float and {}"),
rhs.borrow().type_name() rhs.borrow().ty_name()
) )
}; };
result.into() result.into()
@@ -443,18 +442,18 @@ macro_rules! float_bin_op_logical {
let lhs = vm.frame_stack()[0].clone(); let lhs = vm.frame_stack()[0].clone();
let rhs = vm.frame_stack()[1].clone(); let rhs = vm.frame_stack()[1].clone();
let lhs_value = with_obj_downcast(lhs, FloatInst::float_value); let lhs_value = with_obj_downcast(lhs, Float::float_value);
let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<IntInst>() { let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<Int>() {
BoolInst::create(lhs_value $op int_inst.int_value() as f64) Bool::create(lhs_value $op int_inst.int_value() as f64)
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<FloatInst>() { } else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<Float>() {
BoolInst::create(lhs_value $op float_inst.float_value()) Bool::create(lhs_value $op float_inst.float_value())
} else { } else {
// TODO IntInst logical operator - throw an exception when RHS is not Int, Float // TODO Int logical operator - throw an exception when RHS is not Int, Float
// BLOCKED-ON: exceptions // BLOCKED-ON: exceptions
todo!( todo!(
concat!("cannot use '", stringify!($op), "' operator with Float and {}"), concat!("cannot use '", stringify!($op), "' operator with Float and {}"),
rhs.borrow().type_name() rhs.borrow().ty_name()
) )
}; };
result.into() result.into()
@@ -462,10 +461,10 @@ macro_rules! float_bin_op_logical {
} }
} }
impl FloatInst { impl Float {
pub(crate) fn to_int(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn to_int(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let float_value = with_obj_downcast(vm.frame_stack()[0].clone(), FloatInst::float_value); let float_value = with_obj_downcast(vm.frame_stack()[0].clone(), Float::float_value);
IntInst::create(float_value as i64).into() Int::create(float_value as i64).into()
} }
pub(crate) fn to_float(_vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn to_float(_vm: &mut Vm, _state: FunctionState) -> FunctionResult {
@@ -487,13 +486,13 @@ impl FloatInst {
pub(crate) fn pos(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn pos(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let lhs = vm.frame_stack()[0].clone(); let lhs = vm.frame_stack()[0].clone();
let value = with_obj_downcast(lhs, FloatInst::float_value); let value = with_obj_downcast(lhs, Float::float_value);
FloatInst::create(value.abs()).into() Float::create(value.abs()).into()
} }
pub(crate) fn neg(vm: &mut Vm, _state: FunctionState) -> FunctionResult { pub(crate) fn neg(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let lhs = vm.frame_stack()[0].clone(); let lhs = vm.frame_stack()[0].clone();
let value = with_obj_downcast(lhs, FloatInst::float_value); let value = with_obj_downcast(lhs, Float::float_value);
FloatInst::create(-value).into() Float::create(-value).into()
} }
} }

View File

@@ -8,7 +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::function::UserFunction;
use crate::obj::*; use crate::obj::*;
use crate::token::TokenKind; use crate::token::TokenKind;
use crate::vm::*; use crate::vm::*;
@@ -665,11 +665,7 @@ impl StmtVisitor for Compiler {
// object created, if it were a function object, will be what we're assigning it to, but I // object created, if it were a function object, will be what we're assigning it to, but I
// want to be 100% sure instead of 99%. // want to be 100% sure instead of 99%.
let obj = self.constants.last().unwrap().as_ref(); let obj = self.constants.last().unwrap().as_ref();
if let Some(fun) = obj if let Some(fun) = obj.borrow_mut().as_any_mut().downcast_mut::<UserFunction>() {
.borrow_mut()
.as_any_mut()
.downcast_mut::<UserFunctionInst>()
{
fun.set_name(Rc::new(name.to_string())); fun.set_name(Rc::new(name.to_string()));
} }
@@ -678,7 +674,7 @@ impl StmtVisitor for Compiler {
fn visit_set_stmt(&mut self, stmt: &SetStmt) -> Result<()> { fn visit_set_stmt(&mut self, stmt: &SetStmt) -> Result<()> {
self.compile_expr(&stmt.expr)?; self.compile_expr(&stmt.expr)?;
let name = self.insert_constant(StrInst::create(&stmt.name.text))?; let name = self.insert_constant(Str::create(&stmt.name.text))?;
self.compile_expr(&stmt.rhs)?; self.compile_expr(&stmt.rhs)?;
self.emit(stmt_line_number(stmt), Op::SetAttr(name)); self.emit(stmt_line_number(stmt), Op::SetAttr(name));
Ok(()) Ok(())
@@ -697,7 +693,7 @@ impl StmtVisitor for Compiler {
if let Some(expr) = &stmt.expr { if let Some(expr) = &stmt.expr {
self.compile_expr(expr)?; self.compile_expr(expr)?;
} else { } else {
let nil = self.insert_constant(NilInst::create())?; let nil = self.insert_constant(Nil::create())?;
self.emit(stmt_line_number(stmt), Op::PushConstant(nil)); self.emit(stmt_line_number(stmt), Op::PushConstant(nil));
} }
self.emit(stmt_line_number(stmt), Op::Return); self.emit(stmt_line_number(stmt), Op::Return);
@@ -707,7 +703,7 @@ impl StmtVisitor for Compiler {
// condition // condition
self.compile_expr(&stmt.condition)?; self.compile_expr(&stmt.condition)?;
// call obj.to_bool() // call obj.to_bool()
let bool_attr = self.insert_constant(StrInst::create("to_bool"))?; let bool_attr = self.insert_constant(Str::create("to_bool"))?;
self.emit(expr_line_number(&*stmt.condition), Op::GetAttr(bool_attr)); self.emit(expr_line_number(&*stmt.condition), Op::GetAttr(bool_attr));
self.emit(expr_line_number(&*stmt.condition), Op::Call(0)); self.emit(expr_line_number(&*stmt.condition), Op::Call(0));
let condition_patch_index = self.chunk().code.len(); let condition_patch_index = self.chunk().code.len();
@@ -779,7 +775,7 @@ impl ExprVisitor for Compiler {
let mut exit_patch_index = 0; let mut exit_patch_index = 0;
if let TokenKind::And | TokenKind::Or = expr.op.kind { if let TokenKind::And | TokenKind::Or = expr.op.kind {
let constant_id = self.insert_constant(StrInst::create("to_bool"))?; let constant_id = self.insert_constant(Str::create("to_bool"))?;
self.emit(expr_line_number(&*expr.lhs), Op::GetAttr(constant_id)); self.emit(expr_line_number(&*expr.lhs), Op::GetAttr(constant_id));
self.emit(expr_line_number(&*expr.lhs), Op::Call(0)); self.emit(expr_line_number(&*expr.lhs), Op::Call(0));
exit_patch_index = self.chunk().code.len(); exit_patch_index = self.chunk().code.len();
@@ -793,14 +789,14 @@ impl ExprVisitor for Compiler {
let name = OP_NAMES let name = OP_NAMES
.get(&expr.op.kind) .get(&expr.op.kind)
.expect("invalid binary operator"); .expect("invalid binary operator");
let constant_id = self.insert_constant(StrInst::create(name))?; let constant_id = self.insert_constant(Str::create(name))?;
self.emit(expr_line_number(expr), Op::GetAttr(constant_id)); self.emit(expr_line_number(expr), Op::GetAttr(constant_id));
self.compile_expr(&expr.rhs)?; self.compile_expr(&expr.rhs)?;
// convert RHS to a bool if we're doing AND or OR // convert RHS to a bool if we're doing AND or OR
if let TokenKind::And | TokenKind::Or = expr.op.kind { if let TokenKind::And | TokenKind::Or = expr.op.kind {
let constant_id = self.insert_constant(StrInst::create("to_bool"))?; let constant_id = self.insert_constant(Str::create("to_bool"))?;
self.emit(expr_line_number(&*expr.rhs), Op::GetAttr(constant_id)); self.emit(expr_line_number(&*expr.rhs), Op::GetAttr(constant_id));
self.emit(expr_line_number(&*expr.rhs), Op::Call(0)); self.emit(expr_line_number(&*expr.rhs), Op::Call(0));
} }
@@ -838,7 +834,7 @@ impl ExprVisitor for Compiler {
}); });
self.compile_expr(&expr.expr)?; self.compile_expr(&expr.expr)?;
let name = OP_NAMES.get(&expr.op.kind).expect("invalid unary operator"); let name = OP_NAMES.get(&expr.op.kind).expect("invalid unary operator");
let constant_id = self.insert_constant(StrInst::create(name))?; let constant_id = self.insert_constant(Str::create(name))?;
self.emit(expr_line_number(expr), Op::GetAttr(constant_id)); self.emit(expr_line_number(expr), Op::GetAttr(constant_id));
self.emit(expr_line_number(expr), Op::Call(0)); self.emit(expr_line_number(expr), Op::Call(0));
Ok(()) Ok(())
@@ -862,7 +858,7 @@ impl ExprVisitor for Compiler {
fn visit_get_expr(&mut self, expr: &GetExpr) -> Result<()> { fn visit_get_expr(&mut self, expr: &GetExpr) -> Result<()> {
self.compile_expr(&expr.expr)?; self.compile_expr(&expr.expr)?;
let constant_id = self.insert_constant(StrInst::create(&expr.name.text))?; let constant_id = self.insert_constant(Str::create(&expr.name.text))?;
self.emit(expr_line_number(expr), Op::GetAttr(constant_id)); self.emit(expr_line_number(expr), Op::GetAttr(constant_id));
Ok(()) Ok(())
} }
@@ -888,29 +884,28 @@ impl ExprVisitor for Compiler {
} }
TokenKind::Number => { TokenKind::Number => {
let obj = if expr.token.text.contains('.') { let obj = if expr.token.text.contains('.') {
FloatInst::create(expr.token.text.parse().unwrap()) Float::create(expr.token.text.parse().unwrap())
} else if expr.token.text.starts_with("0x") || expr.token.text.starts_with("0X") { } else if expr.token.text.starts_with("0x") || expr.token.text.starts_with("0X") {
IntInst::create(i64::from_str_radix(&expr.token.text[2..], 16).unwrap()) Int::create(i64::from_str_radix(&expr.token.text[2..], 16).unwrap())
} else if expr.token.text.starts_with("0b") || expr.token.text.starts_with("0B") { } else if expr.token.text.starts_with("0b") || expr.token.text.starts_with("0B") {
IntInst::create(i64::from_str_radix(&expr.token.text[2..], 2).unwrap()) Int::create(i64::from_str_radix(&expr.token.text[2..], 2).unwrap())
} else { } else {
IntInst::create(expr.token.text.parse().unwrap()) Int::create(expr.token.text.parse().unwrap())
}; };
let constant_id = self.insert_constant(obj)?; let constant_id = self.insert_constant(obj)?;
self.emit(expr_line_number(expr), Op::PushConstant(constant_id)); self.emit(expr_line_number(expr), Op::PushConstant(constant_id));
} }
TokenKind::String => { TokenKind::String => {
let constant_id = let constant_id = self.insert_constant(Str::create(unescape(&expr.token.text)))?;
self.insert_constant(StrInst::create(unescape(&expr.token.text)))?;
self.emit(expr_line_number(expr), Op::PushConstant(constant_id)); self.emit(expr_line_number(expr), Op::PushConstant(constant_id));
} }
TokenKind::True | TokenKind::False => { TokenKind::True | TokenKind::False => {
let constant_id = let constant_id =
self.insert_constant(BoolInst::create(expr.token.kind == TokenKind::True))?; self.insert_constant(Bool::create(expr.token.kind == TokenKind::True))?;
self.emit(expr_line_number(expr), Op::PushConstant(constant_id)); self.emit(expr_line_number(expr), Op::PushConstant(constant_id));
} }
TokenKind::Nil => { TokenKind::Nil => {
let constant_id = self.insert_constant(NilInst::create())?; let constant_id = self.insert_constant(Nil::create())?;
self.emit(expr_line_number(expr), Op::PushConstant(constant_id)); self.emit(expr_line_number(expr), Op::PushConstant(constant_id));
} }
_ => unreachable!(), _ => unreachable!(),
@@ -968,7 +963,7 @@ impl ExprVisitor for Compiler {
} }
// always end with a "return nil" // always end with a "return nil"
let nil = self.insert_constant(NilInst::create())?; let nil = self.insert_constant(Nil::create())?;
self.emit(end_line, Op::PushConstant(nil)); self.emit(end_line, Op::PushConstant(nil));
self.emit(end_line, Op::Return); self.emit(end_line, Op::Return);
@@ -976,7 +971,7 @@ impl ExprVisitor for Compiler {
// create the function // create the function
let chunk = self.chunks.pop().unwrap(); let chunk = self.chunks.pop().unwrap();
let fun = UserFunctionInst::create(chunk, expr.params.len() as Argc); let fun = UserFunction::create(chunk, expr.params.len() as Argc);
// register the function as a constant // register the function as a constant
let fun_constant = self.insert_constant(fun)?; let fun_constant = self.insert_constant(fun)?;

View File

@@ -1,4 +1,4 @@
use crate::obj::function::UserFunctionInst; use crate::obj::function::UserFunction;
use crate::obj::ObjP; use crate::obj::ObjP;
use crate::vm::{Chunk, JumpOpArg, Op}; use crate::vm::{Chunk, JumpOpArg, Op};
@@ -151,11 +151,7 @@ pub fn disassemble(chunk: &Chunk, constants: &Vec<ObjP>, globals: &Vec<String>)
disassemble_chunk(chunk, constants, globals); disassemble_chunk(chunk, constants, globals);
for constant in constants { for constant in constants {
if let Some(fun) = constant if let Some(fun) = constant.borrow().as_any().downcast_ref::<UserFunction>() {
.borrow()
.as_any()
.downcast_ref::<UserFunctionInst>()
{
println!(); println!();
println!( println!(
"== {} starting on line {}", "== {} starting on line {}",

View File

@@ -18,7 +18,7 @@ use crate::obj::macros::*;
use crate::vm::{Argc, Vm}; use crate::vm::{Argc, 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 Object>;
pub type Attrs = HashMap<String, ObjP>; pub type Attrs = HashMap<String, ObjP>;
// TODO obj::with_obj_downcast - optimize downcasts of "known" types with an unchecked downcast // TODO obj::with_obj_downcast - optimize downcasts of "known" types with an unchecked downcast
@@ -26,7 +26,7 @@ pub type Attrs = HashMap<String, ObjP>;
/// Downcast an object pointer to a concrete type, and do something with that object. /// Downcast an object pointer to a concrete type, and do something with that object.
pub fn with_obj_downcast<T, Out>(ptr: ObjP, closure: impl FnOnce(&T) -> Out) -> Out pub fn with_obj_downcast<T, Out>(ptr: ObjP, closure: impl FnOnce(&T) -> Out) -> Out
where where
T: Obj + 'static, T: Object + 'static,
{ {
let borrowed = ptr.borrow(); let borrowed = ptr.borrow();
if let Some(obj) = borrowed.as_any().downcast_ref::<T>() { if let Some(obj) = borrowed.as_any().downcast_ref::<T>() {
@@ -43,7 +43,7 @@ where
/// Downcast an object pointer to a concrete type, and do something with that object. /// Downcast an object pointer to a concrete type, and do something with that object.
pub fn with_obj_downcast_mut<T, Out>(ptr: ObjP, closure: impl FnOnce(&mut T) -> Out) -> Out pub fn with_obj_downcast_mut<T, Out>(ptr: ObjP, closure: impl FnOnce(&mut T) -> Out) -> Out
where where
T: Obj + 'static, T: Object + 'static,
{ {
let mut borrowed = ptr.borrow_mut(); let mut borrowed = ptr.borrow_mut();
if let Some(obj) = borrowed.as_any_mut().downcast_mut::<T>() { if let Some(obj) = borrowed.as_any_mut().downcast_mut::<T>() {
@@ -59,15 +59,15 @@ where
pub fn obj_is_inst<T>(ptr: &ObjP) -> bool pub fn obj_is_inst<T>(ptr: &ObjP) -> bool
where where
T: Obj + 'static, T: Object + 'static,
{ {
let borrowed = ptr.borrow(); let borrowed = ptr.borrow();
borrowed.as_any().downcast_ref::<T>().is_some() borrowed.as_any().downcast_ref::<T>().is_some()
} }
pub fn upcast_obj<T: Obj>(ptr: Ptr<T>) -> ObjP { pub fn upcast_obj<T: Object>(ptr: Ptr<T>) -> ObjP {
unsafe { unsafe {
let ptr = Ptr::into_raw(ptr) as *const GcCell<dyn Obj>; let ptr = Ptr::into_raw(ptr) as *const GcCell<dyn Object>;
Ptr::from_raw(ptr) Ptr::from_raw(ptr)
} }
} }
@@ -88,7 +88,7 @@ pub fn init_types() {
),* $(,)? ),* $(,)?
) => {{ ) => {{
$( $(
let $name = make_ptr(TypeInst::new(stringify!($name))); let $name = make_ptr(Ty::new(stringify!($name)));
BUILTINS.with_borrow_mut(|builtins| builtins.insert(stringify!($name).to_string(), $name.clone())); BUILTINS.with_borrow_mut(|builtins| builtins.insert(stringify!($name).to_string(), $name.clone()));
)* )*
@@ -97,16 +97,16 @@ pub fn init_types() {
// setting up these fundamental types. // setting up these fundamental types.
$({ $({
let base_type = $base_type.clone(); let base_type = $base_type.clone();
$name.borrow_mut().set_attr("__type__", base_type); $name.borrow_mut().set_attr("__ty__", base_type);
with_obj_downcast_mut($name.clone(), |type_inst: &mut TypeInst| { type_inst.base.is_instantiated = true; }); with_obj_downcast_mut($name.clone(), |ty: &mut Ty| { ty.base.is_instantiated = true; });
})* })*
$({ $({
$( $(
let vtable_name = stringify!($vtable_name); let vtable_name = stringify!($vtable_name);
let vtable_value = $vtable_value; let vtable_value = $vtable_value;
with_obj_downcast_mut($name.clone(), |type_inst: &mut TypeInst| { with_obj_downcast_mut($name.clone(), |ty: &mut Ty| {
type_inst.vtable.insert(vtable_name.to_string(), vtable_value); ty.vtable.insert(vtable_name.to_string(), vtable_value);
}); });
)* )*
})* })*
@@ -115,82 +115,82 @@ pub fn init_types() {
types! { types! {
// base type // base type
base_type: Type, base_type: Ty,
// type definitions // type definitions
Type { Ty {
// Conversion methods // Conversion methods
to_str => BuiltinFunctionInst::create("to_str", BaseObjInst::to_str, 1), to_str => BuiltinFunction::create("to_str", BaseObj::to_str, 1),
to_repr => BuiltinFunctionInst::create("to_repr", BaseObjInst::to_repr, 1), to_repr => BuiltinFunction::create("to_repr", BaseObj::to_repr, 1),
to_bool => BuiltinFunctionInst::create("to_bool", BaseObjInst::to_bool, 1), to_bool => BuiltinFunction::create("to_bool", BaseObj::to_bool, 1),
to_int => BuiltinFunctionInst::create("to_int", BaseObjInst::not_implemented_un, 1), to_int => BuiltinFunction::create("to_int", BaseObj::not_implemented_un, 1),
to_float => BuiltinFunctionInst::create("to_float", BaseObjInst::not_implemented_un, 1), to_float => BuiltinFunction::create("to_float", BaseObj::not_implemented_un, 1),
len => BuiltinFunctionInst::create("len", BaseObjInst::not_implemented_un, 1), len => BuiltinFunction::create("len", BaseObj::not_implemented_un, 1),
// Operators // Operators
__add__ => BuiltinFunctionInst::create("__add__", BaseObjInst::not_implemented_bin, 2), __add__ => BuiltinFunction::create("__add__", BaseObj::not_implemented_bin, 2),
__sub__ => BuiltinFunctionInst::create("__sub__", BaseObjInst::not_implemented_bin, 2), __sub__ => BuiltinFunction::create("__sub__", BaseObj::not_implemented_bin, 2),
__mul__ => BuiltinFunctionInst::create("__mul__", BaseObjInst::not_implemented_bin, 2), __mul__ => BuiltinFunction::create("__mul__", BaseObj::not_implemented_bin, 2),
__div__ => BuiltinFunctionInst::create("__div__", BaseObjInst::not_implemented_bin, 2), __div__ => BuiltinFunction::create("__div__", BaseObj::not_implemented_bin, 2),
__and__ => BuiltinFunctionInst::create("__and__", BaseObjInst::and, 2), __and__ => BuiltinFunction::create("__and__", BaseObj::and, 2),
__or__ => BuiltinFunctionInst::create("__or__", BaseObjInst::or, 2), __or__ => BuiltinFunction::create("__or__", BaseObj::or, 2),
__ne__ => BuiltinFunctionInst::create("__ne__", BaseObjInst::ne, 2), __ne__ => BuiltinFunction::create("__ne__", BaseObj::ne, 2),
__eq__ => BuiltinFunctionInst::create("__eq__", BaseObjInst::eq, 2), __eq__ => BuiltinFunction::create("__eq__", BaseObj::eq, 2),
__gt__ => BuiltinFunctionInst::create("__gt__", BaseObjInst::not_implemented_bin, 2), __gt__ => BuiltinFunction::create("__gt__", BaseObj::not_implemented_bin, 2),
__ge__ => BuiltinFunctionInst::create("__ge__", BaseObjInst::not_implemented_bin, 2), __ge__ => BuiltinFunction::create("__ge__", BaseObj::not_implemented_bin, 2),
__lt__ => BuiltinFunctionInst::create("__lt__", BaseObjInst::not_implemented_bin, 2), __lt__ => BuiltinFunction::create("__lt__", BaseObj::not_implemented_bin, 2),
__le__ => BuiltinFunctionInst::create("__le__", BaseObjInst::not_implemented_bin, 2), __le__ => BuiltinFunction::create("__le__", BaseObj::not_implemented_bin, 2),
__pos__ => BuiltinFunctionInst::create("__pos__", BaseObjInst::not_implemented_un, 1), __pos__ => BuiltinFunction::create("__pos__", BaseObj::not_implemented_un, 1),
__neg__ => BuiltinFunctionInst::create("__neg__", BaseObjInst::not_implemented_un, 1), __neg__ => BuiltinFunction::create("__neg__", BaseObj::not_implemented_un, 1),
__not__ => BuiltinFunctionInst::create("__not__", BaseObjInst::not, 1), __not__ => BuiltinFunction::create("__not__", BaseObj::not, 1),
}, },
Obj { }, Object { },
Str { Str {
// Conversion methods // Conversion methods
to_str => BuiltinFunctionInst::create("to_str", StrInst::to_str, 1), to_str => BuiltinFunction::create("to_str", Str::to_str, 1),
to_repr => BuiltinFunctionInst::create("to_repr", StrInst::to_repr, 1), to_repr => BuiltinFunction::create("to_repr", Str::to_repr, 1),
to_int => BuiltinFunctionInst::create("to_int", StrInst::to_int, 1), to_int => BuiltinFunction::create("to_int", Str::to_int, 1),
to_float => BuiltinFunctionInst::create("to_float", StrInst::to_float, 1), to_float => BuiltinFunction::create("to_float", Str::to_float, 1),
len => BuiltinFunctionInst::create("len", StrInst::len, 1), len => BuiltinFunction::create("len", Str::len, 1),
// Operators // Operators
__add__ => BuiltinFunctionInst::create("__add__", StrInst::add, 2), __add__ => BuiltinFunction::create("__add__", Str::add, 2),
__mul__ => BuiltinFunctionInst::create("__mul__", StrInst::mul, 2), __mul__ => BuiltinFunction::create("__mul__", Str::mul, 2),
// .lower, .upper, .slice, etc // .lower, .upper, .slice, etc
}, },
Int { Int {
// Conversion methods // Conversion methods
to_int => BuiltinFunctionInst::create("to_int", IntInst::to_int, 1), to_int => BuiltinFunction::create("to_int", Int::to_int, 1),
to_float => BuiltinFunctionInst::create("to_float", IntInst::to_float, 1), to_float => BuiltinFunction::create("to_float", Int::to_float, 1),
// Operators // Operators
__add__ => BuiltinFunctionInst::create("__add__", IntInst::add, 2), __add__ => BuiltinFunction::create("__add__", Int::add, 2),
__sub__ => BuiltinFunctionInst::create("__sub__", IntInst::sub, 2), __sub__ => BuiltinFunction::create("__sub__", Int::sub, 2),
__mul__ => BuiltinFunctionInst::create("__mul__", IntInst::mul, 2), __mul__ => BuiltinFunction::create("__mul__", Int::mul, 2),
__div__ => BuiltinFunctionInst::create("__div__", IntInst::div, 2), __div__ => BuiltinFunction::create("__div__", Int::div, 2),
//__eq__ => BuiltinFunctionInst::create("__eq__", IntInst::eq, 2), //__eq__ => BuiltinFunction::create("__eq__", Int::eq, 2),
__gt__ => BuiltinFunctionInst::create("__gt__", IntInst::gt, 2), __gt__ => BuiltinFunction::create("__gt__", Int::gt, 2),
__ge__ => BuiltinFunctionInst::create("__ge__", IntInst::ge, 2), __ge__ => BuiltinFunction::create("__ge__", Int::ge, 2),
__lt__ => BuiltinFunctionInst::create("__lt__", IntInst::lt, 2), __lt__ => BuiltinFunction::create("__lt__", Int::lt, 2),
__le__ => BuiltinFunctionInst::create("__le__", IntInst::le, 2), __le__ => BuiltinFunction::create("__le__", Int::le, 2),
__pos__ => BuiltinFunctionInst::create("__pos__", IntInst::pos, 1), __pos__ => BuiltinFunction::create("__pos__", Int::pos, 1),
__neg__ => BuiltinFunctionInst::create("__neg__", IntInst::neg, 1), __neg__ => BuiltinFunction::create("__neg__", Int::neg, 1),
}, },
Float { Float {
// Conversion methods // Conversion methods
to_int => BuiltinFunctionInst::create("to_int", FloatInst::to_int, 1), to_int => BuiltinFunction::create("to_int", Float::to_int, 1),
to_float => BuiltinFunctionInst::create("to_float", FloatInst::to_float, 1), to_float => BuiltinFunction::create("to_float", Float::to_float, 1),
// Operators // Operators
__add__ => BuiltinFunctionInst::create("__add__", FloatInst::add, 2), __add__ => BuiltinFunction::create("__add__", Float::add, 2),
__sub__ => BuiltinFunctionInst::create("__sub__", FloatInst::sub, 2), __sub__ => BuiltinFunction::create("__sub__", Float::sub, 2),
__mul__ => BuiltinFunctionInst::create("__mul__", FloatInst::mul, 2), __mul__ => BuiltinFunction::create("__mul__", Float::mul, 2),
__div__ => BuiltinFunctionInst::create("__div__", FloatInst::div, 2), __div__ => BuiltinFunction::create("__div__", Float::div, 2),
__gt__ => BuiltinFunctionInst::create("__gt__", FloatInst::gt, 2), __gt__ => BuiltinFunction::create("__gt__", Float::gt, 2),
__ge__ => BuiltinFunctionInst::create("__ge__", FloatInst::ge, 2), __ge__ => BuiltinFunction::create("__ge__", Float::ge, 2),
__lt__ => BuiltinFunctionInst::create("__lt__", FloatInst::lt, 2), __lt__ => BuiltinFunction::create("__lt__", Float::lt, 2),
__le__ => BuiltinFunctionInst::create("__le__", FloatInst::le, 2), __le__ => BuiltinFunction::create("__le__", Float::le, 2),
__pos__ => BuiltinFunctionInst::create("__pos__", FloatInst::pos, 1), __pos__ => BuiltinFunction::create("__pos__", Float::pos, 1),
__neg__ => BuiltinFunctionInst::create("__neg__", FloatInst::neg, 1), __neg__ => BuiltinFunction::create("__neg__", Float::neg, 1),
}, },
Bool { }, Bool { },
Nil { }, Nil { },
@@ -205,15 +205,15 @@ pub fn init_types() {
/// ///
/// I would implement this as a `From<T>` but it doesn't seem to work for a foreign type, and I'm /// I would implement this as a `From<T>` but it doesn't seem to work for a foreign type, and I'm
/// not sure why. /// not sure why.
pub fn make_ptr<T: Obj>(obj: T) -> ObjP { pub fn make_ptr<T: Object>(obj: T) -> ObjP {
upcast_obj(Ptr::new(GcCell::new(obj))) upcast_obj(Ptr::new(GcCell::new(obj)))
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Obj // Object
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
pub trait Obj: Debug + Display + Any + Trace { pub trait Object: Debug + Display + Any + Trace {
fn instantiate(&mut self); fn instantiate(&mut self);
fn is_instantiated(&self) -> bool; fn is_instantiated(&self) -> bool;
@@ -235,45 +235,42 @@ pub trait Obj: Debug + Display + Any + Trace {
return attr; return attr;
} }
let mut type_inst = self.type_inst(); let mut ty = self.ty();
loop { loop {
let vtable_entry = let vtable_entry =
with_obj_downcast_mut(type_inst.clone(), |type_inst: &mut TypeInst| { with_obj_downcast_mut(ty.clone(), |ty: &mut Ty| ty.vtable.get(name).cloned()).map(
type_inst.vtable.get(name).cloned() |vtable_entry| {
}) let ptr = if obj_is_inst::<BuiltinFunction>(&vtable_entry)
.map(|vtable_entry| { || obj_is_inst::<UserFunction>(&vtable_entry)
let ptr = if obj_is_inst::<BuiltinFunctionInst>(&vtable_entry)
|| obj_is_inst::<UserFunctionInst>(&vtable_entry)
{ {
MethodInst::create(self_ptr.clone(), vtable_entry) Method::create(self_ptr.clone(), vtable_entry)
} else { } else {
vtable_entry vtable_entry
}; };
// TODO Obj::get_attr - cache the vtable result somehow? we aren't caching for // TODO Object::get_attr - cache the vtable result somehow? we aren't caching for
// speed, but rather so we don't have a million different method objects // speed, but rather so we don't have a million different method objects
// floating around. // floating around.
//self.set_attr(name, ptr.clone()); //self.set_attr(name, ptr.clone());
ptr ptr
}); },
);
if vtable_entry.is_some() { if vtable_entry.is_some() {
return vtable_entry; return vtable_entry;
} }
let type_inst_copy = type_inst.borrow().type_inst(); let ty_copy = ty.borrow().ty();
if type_inst.borrow().equals(&*type_inst_copy.borrow()) { if ty.borrow().equals(&*ty_copy.borrow()) {
return None; return None;
} }
type_inst = type_inst_copy; ty = ty_copy;
} }
} }
fn type_inst(&self) -> ObjP { fn ty(&self) -> ObjP {
self.get_attr("__type__").expect("no __type__") self.get_attr("__ty__").expect("no __ty__")
} }
fn type_name(&self) -> Rc<String> { fn ty_name(&self) -> Rc<String> {
with_obj_downcast(self.type_inst(), |type_inst: &TypeInst| { with_obj_downcast(self.ty(), |ty: &Ty| Rc::clone(&ty.name))
Rc::clone(&type_inst.name)
})
} }
fn arity(&self) -> Option<Argc> { fn arity(&self) -> Option<Argc> {
@@ -281,7 +278,7 @@ pub trait Obj: Debug + Display + Any + Trace {
} }
fn call(&self, _vm: &mut Vm, _argc: Argc) { fn call(&self, _vm: &mut Vm, _argc: Argc) {
// TODO Obj::call - need to handle "this object cannot be called" errors // TODO Object::call - need to handle "this object cannot be called" errors
// BLOCKED-ON: exceptions // BLOCKED-ON: exceptions
todo!("Raise some kind of not implemented/not callable error for non-callable objects") todo!("Raise some kind of not implemented/not callable error for non-callable objects")
} }
@@ -290,7 +287,7 @@ pub trait Obj: Debug + Display + Any + Trace {
true true
} }
fn equals(&self, other: &dyn Obj) -> bool; fn equals(&self, other: &dyn Object) -> bool;
fn as_any(&self) -> &dyn Any; fn as_any(&self) -> &dyn Any;
@@ -298,16 +295,16 @@ pub trait Obj: Debug + Display + Any + Trace {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// BaseObjInst // BaseObj
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[derive(Default, Debug, Trace, Finalize)] #[derive(Default, Debug, Trace, Finalize)]
pub(crate) struct BaseObjInst { pub(crate) struct BaseObj {
attrs: Attrs, attrs: Attrs,
is_instantiated: bool, is_instantiated: bool,
} }
impl Clone for BaseObjInst { impl Clone for BaseObj {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
attrs: self.attrs.clone(), attrs: self.attrs.clone(),
@@ -316,13 +313,13 @@ impl Clone for BaseObjInst {
} }
} }
impl Display for BaseObjInst { impl Display for BaseObj {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "<BaseObjInst at {:x}>", (self as *const _ as usize)) write!(fmt, "<BaseObj at {:x}>", (self as *const _ as usize))
} }
} }
impl Obj for BaseObjInst { impl Object for BaseObj {
fn instantiate(&mut self) { fn instantiate(&mut self) {
self.is_instantiated = true; self.is_instantiated = true;
} }
@@ -339,8 +336,8 @@ impl Obj for BaseObjInst {
&mut self.attrs &mut self.attrs
} }
fn equals(&self, other: &dyn Obj) -> bool { fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<BaseObjInst>() { if let Some(other) = other.as_any().downcast_ref::<BaseObj>() {
// compare all attrs // compare all attrs
self.attrs.iter().all(|(k1, v1)| { self.attrs.iter().all(|(k1, v1)| {
other other
@@ -364,15 +361,15 @@ impl Obj for BaseObjInst {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// ObjInst // Obj
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Trace, Finalize)] #[derive(Debug, Trace, Finalize)]
pub struct ObjInst { pub struct Obj {
base: BaseObjInst, base: BaseObj,
} }
impl ObjInst { impl Obj {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
base: Default::default(), base: Default::default(),
@@ -382,37 +379,37 @@ impl ObjInst {
impl_create!(); impl_create!();
} }
impl Display for ObjInst { impl Display for Obj {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "<ObjInst at {:x}>", (self as *const _ as usize)) write!(fmt, "<Obj at {:x}>", (self as *const _ as usize))
} }
} }
impl Obj for ObjInst { impl Object for Obj {
fn equals(&self, other: &dyn Obj) -> bool { fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<ObjInst>() { if let Some(other) = other.as_any().downcast_ref::<Obj>() {
self.base.equals(&other.base) self.base.equals(&other.base)
} else { } else {
false false
} }
} }
impl_base_obj!(Obj); impl_base_obj!(Object);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// TypeInst // Ty
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[derive(Trace, Finalize)] #[derive(Trace, Finalize)]
pub struct TypeInst { pub struct Ty {
base: BaseObjInst, base: BaseObj,
#[unsafe_ignore_trace] #[unsafe_ignore_trace]
name: Rc<String>, name: Rc<String>,
vtable: HashMap<String, ObjP>, vtable: HashMap<String, ObjP>,
} }
impl TypeInst { impl Ty {
pub fn new(name: impl ToString) -> Self { pub fn new(name: impl ToString) -> Self {
Self { Self {
name: Rc::new(name.to_string()), name: Rc::new(name.to_string()),
@@ -428,35 +425,35 @@ impl TypeInst {
} }
} }
impl Debug for TypeInst { impl Debug for Ty {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
fmt, fmt,
"<Type {} at {:x}>", "<Ty {} at {:x}>",
self.name, self.name,
(self as *const _ as usize) (self as *const _ as usize)
) )
} }
} }
impl Display for TypeInst { impl Display for Ty {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
fmt, fmt,
"<Type {} at {:x}>", "<Ty {} at {:x}>",
self.name, self.name,
(self as *const _ as usize) (self as *const _ as usize)
) )
} }
} }
impl Obj for TypeInst { impl Object for Ty {
fn equals(&self, other: &dyn Obj) -> bool { fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<TypeInst>() { if let Some(other) = other.as_any().downcast_ref::<Ty>() {
// TODO TypeInst::equals : something more robust than this // TODO Ty::equals : something more robust than this
// Types should hold equality if they have the same name // Tys should hold equality if they have the same name
// the problem is that Type.get_attr("__type__") is going to return itself, so we have // the problem is that Ty.get_attr("__ty__") is going to return itself, so we have
// to go through attributes to specially exclude to the __type__ attribute if it points // to go through attributes to specially exclude to the __ty__ attribute if it points
// to ourself. // to ourself.
// How do we detect that it's pointing to ourself? I suppose pointers are the way // How do we detect that it's pointing to ourself? I suppose pointers are the way
self.name == other.name self.name == other.name
@@ -465,21 +462,21 @@ impl Obj for TypeInst {
} }
} }
impl_base_obj!(Type); impl_base_obj!(Ty);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// StrInst // Str
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Trace, Finalize)] #[derive(Debug, Trace, Finalize)]
pub struct StrInst { pub struct Str {
base: BaseObjInst, base: BaseObj,
#[unsafe_ignore_trace] #[unsafe_ignore_trace]
str_value: Rc<String>, str_value: Rc<String>,
} }
impl StrInst { impl Str {
pub fn new(str_value: impl ToString) -> Self { pub fn new(str_value: impl ToString) -> Self {
Self { Self {
base: Default::default(), base: Default::default(),
@@ -494,19 +491,19 @@ impl StrInst {
} }
} }
impl Display for StrInst { impl Display for Str {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", self.str_value) write!(fmt, "{}", self.str_value)
} }
} }
impl Obj for StrInst { impl Object for Str {
fn is_truthy(&self) -> bool { fn is_truthy(&self) -> bool {
!self.str_value.is_empty() !self.str_value.is_empty()
} }
fn equals(&self, other: &dyn Obj) -> bool { fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<StrInst>() { if let Some(other) = other.as_any().downcast_ref::<Str>() {
self.str_value == other.str_value self.str_value == other.str_value
} else { } else {
false false
@@ -517,16 +514,16 @@ impl Obj for StrInst {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// IntInst // Int
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Trace, Finalize)] #[derive(Debug, Trace, Finalize)]
pub struct IntInst { pub struct Int {
base: BaseObjInst, base: BaseObj,
int_value: i64, int_value: i64,
} }
impl IntInst { impl Int {
pub fn new(int_value: i64) -> Self { pub fn new(int_value: i64) -> Self {
Self { Self {
int_value, int_value,
@@ -541,21 +538,21 @@ impl IntInst {
} }
} }
impl Display for IntInst { impl Display for Int {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", self.int_value) write!(fmt, "{}", self.int_value)
} }
} }
impl Obj for IntInst { impl Object for Int {
fn is_truthy(&self) -> bool { fn is_truthy(&self) -> bool {
self.int_value != 0 self.int_value != 0
} }
fn equals(&self, other: &dyn Obj) -> bool { fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<IntInst>() { if let Some(other) = other.as_any().downcast_ref::<Int>() {
self.int_value == other.int_value self.int_value == other.int_value
} else if let Some(other) = other.as_any().downcast_ref::<FloatInst>() { } else if let Some(other) = other.as_any().downcast_ref::<Float>() {
self.int_value as f64 == other.float_value self.int_value as f64 == other.float_value
} else { } else {
false false
@@ -566,16 +563,16 @@ impl Obj for IntInst {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// FloatInst // Float
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Trace, Finalize)] #[derive(Debug, Trace, Finalize)]
pub struct FloatInst { pub struct Float {
base: BaseObjInst, base: BaseObj,
float_value: f64, float_value: f64,
} }
impl FloatInst { impl Float {
pub fn new(float_value: f64) -> Self { pub fn new(float_value: f64) -> Self {
Self { Self {
float_value, float_value,
@@ -590,7 +587,7 @@ impl FloatInst {
} }
} }
impl Display for FloatInst { impl Display for Float {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
// we want to force the .0 if it's a whole number // we want to force the .0 if it's a whole number
if self.float_value == self.float_value.floor() { if self.float_value == self.float_value.floor() {
@@ -601,15 +598,15 @@ impl Display for FloatInst {
} }
} }
impl Obj for FloatInst { impl Object for Float {
fn is_truthy(&self) -> bool { fn is_truthy(&self) -> bool {
self.float_value != 0.0 self.float_value != 0.0
} }
fn equals(&self, other: &dyn Obj) -> bool { fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<FloatInst>() { if let Some(other) = other.as_any().downcast_ref::<Float>() {
self.float_value == other.float_value self.float_value == other.float_value
} else if let Some(other) = other.as_any().downcast_ref::<IntInst>() { } else if let Some(other) = other.as_any().downcast_ref::<Int>() {
self.float_value == other.int_value as f64 self.float_value == other.int_value as f64
} else { } else {
false false
@@ -620,16 +617,16 @@ impl Obj for FloatInst {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// BoolInst // Bool
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Trace, Finalize)] #[derive(Debug, Trace, Finalize)]
pub struct BoolInst { pub struct Bool {
base: BaseObjInst, base: BaseObj,
bool_value: bool, bool_value: bool,
} }
impl BoolInst { impl Bool {
pub fn new(bool_value: bool) -> Self { pub fn new(bool_value: bool) -> Self {
Self { Self {
bool_value, bool_value,
@@ -644,19 +641,19 @@ impl BoolInst {
} }
} }
impl Display for BoolInst { impl Display for Bool {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", self.bool_value) write!(fmt, "{}", self.bool_value)
} }
} }
impl Obj for BoolInst { impl Object for Bool {
fn is_truthy(&self) -> bool { fn is_truthy(&self) -> bool {
self.bool_value self.bool_value
} }
fn equals(&self, other: &dyn Obj) -> bool { fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<BoolInst>() { if let Some(other) = other.as_any().downcast_ref::<Bool>() {
self.bool_value == other.bool_value self.bool_value == other.bool_value
} else { } else {
false false
@@ -667,15 +664,15 @@ impl Obj for BoolInst {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// NilInst // Nil
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Default, Trace, Finalize)] #[derive(Debug, Default, Trace, Finalize)]
pub struct NilInst { pub struct Nil {
base: BaseObjInst, base: BaseObj,
} }
impl NilInst { impl Nil {
pub fn new() -> Self { pub fn new() -> Self {
Default::default() Default::default()
} }
@@ -683,19 +680,19 @@ impl NilInst {
impl_create!(); impl_create!();
} }
impl Display for NilInst { impl Display for Nil {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "nil") write!(fmt, "nil")
} }
} }
impl Obj for NilInst { impl Object for Nil {
fn is_truthy(&self) -> bool { fn is_truthy(&self) -> bool {
false false
} }
fn equals(&self, other: &dyn Obj) -> bool { fn equals(&self, other: &dyn Object) -> bool {
other.as_any().downcast_ref::<NilInst>().is_some() other.as_any().downcast_ref::<Nil>().is_some()
} }
impl_base_obj!(Nil); impl_base_obj!(Nil);
@@ -709,49 +706,49 @@ impl Obj for NilInst {
fn test_new_objects() { fn test_new_objects() {
init_types(); init_types();
let type_value = TypeInst::create("Type"); let type_value = Ty::create("Ty");
assert_eq!(&*type_value.borrow().type_name(), "Type"); assert_eq!(&*type_value.borrow().ty_name(), "Ty");
let str_value = StrInst::create("asdfasdfasdfasdfasdf"); let str_value = Str::create("asdfasdfasdfasdfasdf");
assert_eq!(&*str_value.borrow().type_name(), "Str"); assert_eq!(&*str_value.borrow().ty_name(), "Str");
let int_value = IntInst::create(1234); let int_value = Int::create(1234);
assert_eq!(&*int_value.borrow().type_name(), "Int"); assert_eq!(&*int_value.borrow().ty_name(), "Int");
let float_value = FloatInst::create(1234.5678); let float_value = Float::create(1234.5678);
assert_eq!(&*float_value.borrow().type_name(), "Float"); assert_eq!(&*float_value.borrow().ty_name(), "Float");
let nil_value = NilInst::create(); let nil_value = Nil::create();
assert_eq!(&*nil_value.borrow().type_name(), "Nil"); assert_eq!(&*nil_value.borrow().ty_name(), "Nil");
} }
#[test] #[test]
fn test_obj_equals() { fn test_obj_equals() {
init_types(); init_types();
let int1 = IntInst::create(1234); let int1 = Int::create(1234);
let int2 = IntInst::create(1234); let int2 = Int::create(1234);
assert!(int1.borrow().equals(&*int2.borrow())); assert!(int1.borrow().equals(&*int2.borrow()));
assert!(int2.borrow().equals(&*int1.borrow())); assert!(int2.borrow().equals(&*int1.borrow()));
let float1 = FloatInst::create(1234.0); let float1 = Float::create(1234.0);
assert!(int1.borrow().equals(&*float1.borrow())); assert!(int1.borrow().equals(&*float1.borrow()));
assert!(float1.borrow().equals(&*int2.borrow())); assert!(float1.borrow().equals(&*int2.borrow()));
// self-equality // self-equality
let str1 = StrInst::create("1234"); let str1 = Str::create("1234");
assert!(str1.borrow().equals(&*str1.borrow())); assert!(str1.borrow().equals(&*str1.borrow()));
let str2 = StrInst::create("1234"); let str2 = Str::create("1234");
assert!(str1.borrow().equals(&*str2.borrow())); assert!(str1.borrow().equals(&*str2.borrow()));
assert!(str2.borrow().equals(&*str1.borrow())); assert!(str2.borrow().equals(&*str1.borrow()));
assert!(!str1.borrow().equals(&*float1.borrow())); assert!(!str1.borrow().equals(&*float1.borrow()));
assert!(!str1.borrow().equals(&*int1.borrow())); assert!(!str1.borrow().equals(&*int1.borrow()));
let obj1 = ObjInst::create(); let obj1 = Obj::create();
let obj2 = ObjInst::create(); let obj2 = Obj::create();
assert!(obj1.borrow().equals(&*obj2.borrow())); assert!(obj1.borrow().equals(&*obj2.borrow()));
// these objects aren't equal anymore // these objects aren't equal anymore
@@ -766,14 +763,14 @@ fn test_obj_equals() {
#[test] #[test]
fn test_obj_vtable() { fn test_obj_vtable() {
init_types(); init_types();
let str1 = StrInst::create("asdfasdfasdf"); let str1 = Str::create("asdfasdfasdf");
let to_string_ptr = str1.borrow_mut().get_vtable_attr(str1.clone(), "to_str"); let to_string_ptr = str1.borrow_mut().get_vtable_attr(str1.clone(), "to_str");
assert!(to_string_ptr.is_some()); assert!(to_string_ptr.is_some());
let to_string_ptr = to_string_ptr.unwrap(); let to_string_ptr = to_string_ptr.unwrap();
assert!(obj_is_inst::<MethodInst>(&to_string_ptr)); assert!(obj_is_inst::<Method>(&to_string_ptr));
with_obj_downcast(to_string_ptr.clone(), |method: &MethodInst| { with_obj_downcast(to_string_ptr.clone(), |method: &Method| {
assert!(method.self_binding().borrow().equals(&*str1.borrow())); assert!(method.self_binding().borrow().equals(&*str1.borrow()));
}); });
@@ -785,8 +782,8 @@ fn test_obj_vtable() {
// this is like doing "asdfasdfasdf".to_string().to_string() // this is like doing "asdfasdfasdf".to_string().to_string()
let method_to_string_ptr = method_to_string_ptr.unwrap(); let method_to_string_ptr = method_to_string_ptr.unwrap();
assert!(obj_is_inst::<MethodInst>(&method_to_string_ptr)); assert!(obj_is_inst::<Method>(&method_to_string_ptr));
with_obj_downcast(method_to_string_ptr.clone(), |method: &MethodInst| { with_obj_downcast(method_to_string_ptr.clone(), |method: &Method| {
assert!(method assert!(method
.self_binding() .self_binding()
.borrow() .borrow()

View File

@@ -5,7 +5,7 @@ use std::rc::Rc;
use gc::{Finalize, Trace}; use gc::{Finalize, Trace};
use crate::obj::macros::*; use crate::obj::macros::*;
use crate::obj::{make_ptr, BaseObjInst, Obj, ObjP}; use crate::obj::{make_ptr, BaseObj, ObjP, Object};
use crate::vm::{Argc, Chunk, Frame, Function, Vm}; use crate::vm::{Argc, Chunk, Frame, Function, Vm};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -49,14 +49,14 @@ pub enum FunctionState {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// BuiltinFunctionInst // BuiltinFunction
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
pub type BuiltinFunctionPtr = fn(vm: &mut Vm, function_state: FunctionState) -> FunctionResult; pub type BuiltinFunctionPtr = fn(vm: &mut Vm, function_state: FunctionState) -> FunctionResult;
#[derive(Debug, Trace, Finalize)] #[derive(Debug, Trace, Finalize)]
pub struct BuiltinFunctionInst { pub struct BuiltinFunction {
base: BaseObjInst, base: BaseObj,
#[unsafe_ignore_trace] #[unsafe_ignore_trace]
name: Rc<String>, name: Rc<String>,
#[unsafe_ignore_trace] #[unsafe_ignore_trace]
@@ -64,7 +64,7 @@ pub struct BuiltinFunctionInst {
arity: Argc, arity: Argc,
} }
impl BuiltinFunctionInst { impl BuiltinFunction {
pub fn new(name: impl ToString, function: BuiltinFunctionPtr, arity: Argc) -> Self { pub fn new(name: impl ToString, function: BuiltinFunctionPtr, arity: Argc) -> Self {
Self { Self {
base: Default::default(), base: Default::default(),
@@ -85,7 +85,7 @@ impl BuiltinFunctionInst {
} }
} }
impl Display for BuiltinFunctionInst { impl Display for BuiltinFunction {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
fmt, fmt,
@@ -97,7 +97,7 @@ impl Display for BuiltinFunctionInst {
} }
} }
impl Obj for BuiltinFunctionInst { impl Object for BuiltinFunction {
fn arity(&self) -> Option<Argc> { fn arity(&self) -> Option<Argc> {
Some(self.arity) Some(self.arity)
} }
@@ -111,10 +111,10 @@ impl Obj for BuiltinFunctionInst {
vm.push_frame(new_frame); vm.push_frame(new_frame);
} }
fn equals(&self, other: &dyn Obj) -> bool { fn equals(&self, other: &dyn Object) -> bool {
// TODO BuiltinFunctionInst::equals : need something more robust than checking addr_eq, // TODO BuiltinFunction::equals : need something more robust than checking addr_eq,
// maybe check the self_binding pointer too? // maybe check the self_binding pointer too?
if let Some(other) = other.as_any().downcast_ref::<BuiltinFunctionInst>() { if let Some(other) = other.as_any().downcast_ref::<BuiltinFunction>() {
ptr::addr_eq(self, other) ptr::addr_eq(self, other)
} else { } else {
false false
@@ -125,12 +125,12 @@ impl Obj for BuiltinFunctionInst {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// UserFunctionInst // UserFunction
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Clone, Trace, Finalize)] #[derive(Debug, Clone, Trace, Finalize)]
pub struct UserFunctionInst { pub struct UserFunction {
base: BaseObjInst, base: BaseObj,
#[unsafe_ignore_trace] #[unsafe_ignore_trace]
name: Rc<String>, name: Rc<String>,
#[unsafe_ignore_trace] #[unsafe_ignore_trace]
@@ -139,7 +139,7 @@ pub struct UserFunctionInst {
captures: Vec<ObjP>, captures: Vec<ObjP>,
} }
impl UserFunctionInst { impl UserFunction {
pub fn new(chunk: Chunk, arity: Argc) -> Self { pub fn new(chunk: Chunk, arity: Argc) -> Self {
Self { Self {
base: Default::default(), base: Default::default(),
@@ -169,7 +169,7 @@ impl UserFunctionInst {
} }
} }
impl Display for UserFunctionInst { impl Display for UserFunction {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
fmt, fmt,
@@ -181,7 +181,7 @@ impl Display for UserFunctionInst {
} }
} }
impl Obj for UserFunctionInst { impl Object for UserFunction {
fn arity(&self) -> Option<Argc> { fn arity(&self) -> Option<Argc> {
Some(self.arity) Some(self.arity)
} }
@@ -199,9 +199,9 @@ impl Obj for UserFunctionInst {
} }
} }
fn equals(&self, other: &dyn Obj) -> bool { fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<UserFunctionInst>() { if let Some(other) = other.as_any().downcast_ref::<UserFunction>() {
// TODO UserFunctionInst::equals : need something more robust than checking addr_eq. // TODO UserFunction::equals : need something more robust than checking addr_eq.
ptr::addr_eq(self, other) ptr::addr_eq(self, other)
} else { } else {
false false
@@ -212,19 +212,19 @@ impl Obj for UserFunctionInst {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// MethodInst // Method
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[derive(Trace, Finalize)] #[derive(Trace, Finalize)]
pub struct MethodInst { pub struct Method {
base: BaseObjInst, base: BaseObj,
self_binding: ObjP, self_binding: ObjP,
function: ObjP, function: ObjP,
} }
impl Debug for MethodInst { impl Debug for Method {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("MethodInst") fmt.debug_struct("Method")
.field("base", &self.base) .field("base", &self.base)
.field("self_binding", &format!("{}", self.self_binding.borrow())) .field("self_binding", &format!("{}", self.self_binding.borrow()))
.field("function", &self.function) .field("function", &self.function)
@@ -232,7 +232,7 @@ impl Debug for MethodInst {
} }
} }
impl MethodInst { impl Method {
pub fn new(self_binding: ObjP, function: ObjP) -> Self { pub fn new(self_binding: ObjP, function: ObjP) -> Self {
Self { Self {
base: Default::default(), base: Default::default(),
@@ -252,13 +252,13 @@ impl MethodInst {
} }
} }
impl Display for MethodInst { impl Display for Method {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", self.function.borrow()) write!(fmt, "{}", self.function.borrow())
} }
} }
impl Obj for MethodInst { impl Object for Method {
fn arity(&self) -> Option<Argc> { fn arity(&self) -> Option<Argc> {
// Subtract one from the arity - this is because the VM uses arity() to check against the // Subtract one from the arity - this is because the VM uses arity() to check against the
// number of arguments passed. // number of arguments passed.
@@ -273,8 +273,8 @@ impl Obj for MethodInst {
self.function.borrow().call(vm, argc) self.function.borrow().call(vm, argc)
} }
fn equals(&self, other: &dyn Obj) -> bool { fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<MethodInst>() { if let Some(other) = other.as_any().downcast_ref::<Method>() {
ptr::addr_eq(&*self.self_binding, &*other.self_binding) ptr::addr_eq(&*self.self_binding, &*other.self_binding)
&& ptr::addr_eq(&*self.function, &*other.function) && ptr::addr_eq(&*self.function, &*other.function)
} else { } else {

View File

@@ -7,7 +7,7 @@ macro_rules! impl_base_obj {
.expect(concat!("no ", stringify!($type_name))) .expect(concat!("no ", stringify!($type_name)))
.clone() .clone()
}); });
self.set_attr("__type__", ty); self.set_attr("__ty__", ty);
self.$base_name.instantiate(); self.$base_name.instantiate();
} }

View File

@@ -98,7 +98,7 @@ impl Vm {
/// Create a new virtual machine with the given chunk, constants, and global names. /// Create a new virtual machine with the given chunk, constants, and global names.
pub fn new(chunk: Rc<Chunk>, constants: Vec<ObjP>, global_names: Vec<String>) -> Self { pub fn new(chunk: Rc<Chunk>, constants: Vec<ObjP>, global_names: Vec<String>) -> Self {
// set up globals // set up globals
let nil = NilInst::create(); let nil = Nil::create();
let mut globals: Vec<_> = global_names.iter().map(|_| ObjP::clone(&nil)).collect(); let mut globals: Vec<_> = global_names.iter().map(|_| ObjP::clone(&nil)).collect();
let mut register_global = |name: &str, value: ObjP| { let mut register_global = |name: &str, value: ObjP| {
@@ -290,7 +290,7 @@ impl Vm {
// need both declarations to borrow cell value // need both declarations to borrow cell value
let name_obj = Ptr::clone(&self.constants[constant_id as usize]); let name_obj = Ptr::clone(&self.constants[constant_id as usize]);
let name = let name =
with_obj_downcast(name_obj, |name: &StrInst| Rc::clone(&name.str_value())); with_obj_downcast(name_obj, |name: &Str| Rc::clone(&name.str_value()));
let owner = self.pop(); let owner = self.pop();
let value = owner.borrow_mut().get_vtable_attr(owner.clone(), &name); let value = owner.borrow_mut().get_vtable_attr(owner.clone(), &name);
if let Some(value) = value { if let Some(value) = value {
@@ -309,7 +309,7 @@ impl Vm {
Op::SetAttr(constant_id) => { Op::SetAttr(constant_id) => {
let name_obj = Ptr::clone(&self.constants[constant_id as usize]); let name_obj = Ptr::clone(&self.constants[constant_id as usize]);
let name = let name =
with_obj_downcast(name_obj, |name: &StrInst| Rc::clone(&name.str_value())); with_obj_downcast(name_obj, |name: &Str| Rc::clone(&name.str_value()));
let value = self.pop(); let value = self.pop();
let target = self.pop(); let target = self.pop();
@@ -378,10 +378,9 @@ impl Vm {
// constants, we want to deep-clone this object so we don't alter any live // constants, we want to deep-clone this object so we don't alter any live
// objects. // objects.
// there is some room for optimization here so we aren't cloning the entire // there is some room for optimization here so we aren't cloning the entire
// UserFunctionInst for every individual capture in a function. // UserFunction for every individual capture in a function.
let fun_ptr = self.pop(); let fun_ptr = self.pop();
let mut fun: UserFunctionInst = let mut fun: UserFunction = with_obj_downcast(fun_ptr, UserFunction::clone);
with_obj_downcast(fun_ptr, UserFunctionInst::clone);
let frame_index = self.frames.len() - (depth as usize) - 1; let frame_index = self.frames.len() - (depth as usize) - 1;
let stack_base = self.frames[frame_index].stack_base; let stack_base = self.frames[frame_index].stack_base;
let value = Ptr::clone(&self.stack[stack_base + (slot as usize)]); let value = Ptr::clone(&self.stack[stack_base + (slot as usize)]);