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.
use crate::obj::function::{BuiltinFunctionInst, FunctionResult, FunctionState};
use crate::obj::function::{BuiltinFunction, FunctionResult, FunctionState};
use crate::obj::*;
use crate::vm::Vm;
@@ -7,7 +7,7 @@ pub fn init_global_builtins() {
macro_rules! builtins {
($($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|
builtins.insert(
stringify!($builtin).to_string(),
@@ -50,7 +50,7 @@ pub(crate) fn println(vm: &mut Vm, state: FunctionState) -> FunctionResult {
}
FunctionState::Resume(0) => {
println!("{}", vm.frame_stack()[0].borrow());
NilInst::create().into()
Nil::create().into()
}
_ => unreachable!(),
}
@@ -69,17 +69,17 @@ pub(crate) fn print(vm: &mut Vm, state: FunctionState) -> FunctionResult {
}
FunctionState::Resume(0) => {
print!("{}", vm.frame_stack()[0].borrow());
NilInst::create().into()
Nil::create().into()
}
_ => unreachable!(),
}
}
////////////////////////////////////////////////////////////////////////////////
// BaseObjInst implementations
// BaseObj implementations
////////////////////////////////////////////////////////////////////////////////
impl BaseObjInst {
impl BaseObj {
//
// Common functions
//
@@ -103,11 +103,11 @@ impl BaseObjInst {
pub(crate) fn to_repr(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
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 {
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 rhs = vm.frame_stack()[1].borrow();
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 {
let lhs = vm.frame_stack()[0].borrow();
let rhs = vm.frame_stack()[1].borrow();
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 {
@@ -145,7 +145,7 @@ impl BaseObjInst {
}
FunctionState::Resume(0) => {
let result = !vm.peek().borrow().is_truthy();
BoolInst::create(result).into()
Bool::create(result).into()
}
_ => {
unreachable!()
@@ -157,7 +157,7 @@ impl BaseObjInst {
let lhs = vm.frame_stack()[0].borrow();
let rhs = vm.frame_stack()[1].borrow();
let equals = lhs.equals(&*rhs);
BoolInst::create(equals).into()
Bool::create(equals).into()
}
pub(crate) fn not(vm: &mut Vm, state: FunctionState) -> FunctionResult {
@@ -173,7 +173,7 @@ impl BaseObjInst {
}
FunctionState::Resume(0) => {
let value = vm.peek().borrow().is_truthy();
BoolInst::create(!value).into()
Bool::create(!value).into()
}
_ => unreachable!(),
}
@@ -185,7 +185,7 @@ impl BaseObjInst {
pub(crate) fn not_implemented_un(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
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
// BLOCKED-ON: exceptions
todo!(
@@ -196,7 +196,7 @@ impl BaseObjInst {
}
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
// BLOCKED-ON: exceptions
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 {
// top item of the stack should just be ourselves, so return immediately
FunctionResult::Return
}
pub(crate) fn to_repr(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let escaped: String =
with_obj_downcast(vm.frame_stack()[0].clone(), |str_inst: &StrInst| {
str_inst.str_value().as_str().escape_default().collect()
});
StrInst::create(format!("'{}'", escaped)).into()
let escaped: String = with_obj_downcast(vm.frame_stack()[0].clone(), |str_inst: &Str| {
str_inst.str_value().as_str().escape_default().collect()
});
Str::create(format!("'{}'", escaped)).into()
}
pub(crate) fn to_int(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
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()
});
match parsed {
Ok(int) => IntInst::create(int).into(),
// TODO StrInst::to_int - throw an exception when we fail to parse an integer
Ok(int) => Int::create(int).into(),
// TODO Str::to_int - throw an exception when we fail to parse an integer
// BLOCKED-ON - exceptions
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 {
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()
});
match parsed {
Ok(float) => FloatInst::create(float).into(),
// TODO StrInst::to_int - throw an exception when we fail to parse an integer
Ok(float) => Float::create(float).into(),
// TODO Str::to_int - throw an exception when we fail to parse an integer
// BLOCKED-ON - exceptions
Err(e) => todo!("error parsing string to a float: {}", e),
}
}
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
});
IntInst::create(len).into()
Int::create(len).into()
}
pub(crate) fn add(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let lhs = vm.frame_stack()[0].clone();
let rhs = vm.frame_stack()[1].clone();
if !obj_is_inst::<StrInst>(&rhs) {
// TODO StrInst::add - throw an exception when the RHS is not a string
if !obj_is_inst::<Str>(&rhs) {
// TODO Str::add - throw an exception when the RHS is not a string
// BLOCKED-ON: exceptions
todo!(
"can only concatenate Str, got {} instead",
rhs.borrow().type_name()
rhs.borrow().ty_name()
)
}
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 {
let lhs = vm.frame_stack()[0].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()
} 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
todo!(
"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 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 {
@@ -299,18 +298,18 @@ macro_rules! int_bin_op_math {
let lhs = vm.frame_stack()[0].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>() {
IntInst::create(lhs_value $op int_inst.int_value())
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<FloatInst>() {
FloatInst::create(lhs_value as f64 $op float_inst.float_value())
let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<Int>() {
Int::create(lhs_value $op int_inst.int_value())
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<Float>() {
Float::create(lhs_value as f64 $op float_inst.float_value())
} 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
todo!(
concat!("cannot use '", stringify!($op), "' operator with Int and {}"),
rhs.borrow().type_name()
rhs.borrow().ty_name()
)
};
result.into()
@@ -324,18 +323,18 @@ macro_rules! int_bin_op_logical {
let lhs = vm.frame_stack()[0].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>() {
BoolInst::create(lhs_value $op int_inst.int_value())
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<FloatInst>() {
BoolInst::create((lhs_value as f64) $op float_inst.float_value())
let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<Int>() {
Bool::create(lhs_value $op int_inst.int_value())
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<Float>() {
Bool::create((lhs_value as f64) $op float_inst.float_value())
} 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
todo!(
concat!("cannot use '", stringify!($op), "' operator with Int and {}"),
rhs.borrow().type_name()
rhs.borrow().ty_name()
)
};
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 {
FunctionResult::Return
}
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);
FloatInst::create(int_value as f64).into()
let int_value = with_obj_downcast(vm.frame_stack()[0].clone(), Int::int_value);
Float::create(int_value as f64).into()
}
int_bin_op_math!(add, +);
@@ -361,28 +360,28 @@ impl IntInst {
let lhs = vm.frame_stack()[0].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>() {
IntInst::create(lhs_value * int_inst.int_value())
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<FloatInst>() {
FloatInst::create(lhs_value as f64 * float_inst.float_value())
} else if let Some(str_inst) = rhs.borrow().as_any().downcast_ref::<StrInst>() {
// TODO IntInst::mul - maybe convert this to just call Str.mul with arguments reversed?
let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<Int>() {
Int::create(lhs_value * int_inst.int_value())
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<Float>() {
Float::create(lhs_value as f64 * float_inst.float_value())
} else if let Some(str_inst) = rhs.borrow().as_any().downcast_ref::<Str>() {
// TODO Int::mul - maybe convert this to just call Str.mul with arguments reversed?
// 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 {
// 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
todo!(
"cannot use '*' operator with Int and {}",
rhs.borrow().type_name()
rhs.borrow().ty_name()
)
};
result.into()
}
// TODO IntInst::div - handle divide by zero
// TODO Int::div - handle divide by zero
// BLOCKED-ON: exceptions
// NOTE - we will probably need to get rid of the macro here to handle that :(
int_bin_op_math!(div, /);
@@ -397,19 +396,19 @@ impl IntInst {
pub(crate) fn pos(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let lhs = vm.frame_stack()[0].clone();
let value = with_obj_downcast(lhs, IntInst::int_value);
IntInst::create(value.abs()).into()
let value = with_obj_downcast(lhs, Int::int_value);
Int::create(value.abs()).into()
}
pub(crate) fn neg(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let lhs = vm.frame_stack()[0].clone();
let value = with_obj_downcast(lhs, IntInst::int_value);
IntInst::create(-value).into()
let value = with_obj_downcast(lhs, Int::int_value);
Int::create(-value).into()
}
}
////////////////////////////////////////////////////////////////////////////////
// FloatInst implementations
// Float implementations
////////////////////////////////////////////////////////////////////////////////
macro_rules! float_bin_op_math {
@@ -418,18 +417,18 @@ macro_rules! float_bin_op_math {
let lhs = vm.frame_stack()[0].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>() {
FloatInst::create(lhs_value $op int_inst.int_value() as f64)
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<FloatInst>() {
FloatInst::create(lhs_value $op float_inst.float_value())
let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<Int>() {
Float::create(lhs_value $op int_inst.int_value() as f64)
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<Float>() {
Float::create(lhs_value $op float_inst.float_value())
} 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
todo!(
concat!("cannot use '", stringify!($op), "' operator with Float and {}"),
rhs.borrow().type_name()
rhs.borrow().ty_name()
)
};
result.into()
@@ -443,18 +442,18 @@ macro_rules! float_bin_op_logical {
let lhs = vm.frame_stack()[0].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>() {
BoolInst::create(lhs_value $op int_inst.int_value() as f64)
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<FloatInst>() {
BoolInst::create(lhs_value $op float_inst.float_value())
let result = if let Some(int_inst) = rhs.borrow().as_any().downcast_ref::<Int>() {
Bool::create(lhs_value $op int_inst.int_value() as f64)
} else if let Some(float_inst) = rhs.borrow().as_any().downcast_ref::<Float>() {
Bool::create(lhs_value $op float_inst.float_value())
} 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
todo!(
concat!("cannot use '", stringify!($op), "' operator with Float and {}"),
rhs.borrow().type_name()
rhs.borrow().ty_name()
)
};
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 {
let float_value = with_obj_downcast(vm.frame_stack()[0].clone(), FloatInst::float_value);
IntInst::create(float_value as i64).into()
let float_value = with_obj_downcast(vm.frame_stack()[0].clone(), Float::float_value);
Int::create(float_value as i64).into()
}
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 {
let lhs = vm.frame_stack()[0].clone();
let value = with_obj_downcast(lhs, FloatInst::float_value);
FloatInst::create(value.abs()).into()
let value = with_obj_downcast(lhs, Float::float_value);
Float::create(value.abs()).into()
}
pub(crate) fn neg(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let lhs = vm.frame_stack()[0].clone();
let value = with_obj_downcast(lhs, FloatInst::float_value);
FloatInst::create(-value).into()
let value = with_obj_downcast(lhs, Float::float_value);
Float::create(-value).into()
}
}

View File

@@ -8,7 +8,7 @@ use common_macros::hash_map;
use thiserror::Error;
use crate::ast::*;
use crate::obj::function::UserFunctionInst;
use crate::obj::function::UserFunction;
use crate::obj::*;
use crate::token::TokenKind;
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
// want to be 100% sure instead of 99%.
let obj = self.constants.last().unwrap().as_ref();
if let Some(fun) = obj
.borrow_mut()
.as_any_mut()
.downcast_mut::<UserFunctionInst>()
{
if let Some(fun) = obj.borrow_mut().as_any_mut().downcast_mut::<UserFunction>() {
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<()> {
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.emit(stmt_line_number(stmt), Op::SetAttr(name));
Ok(())
@@ -697,7 +693,7 @@ impl StmtVisitor for Compiler {
if let Some(expr) = &stmt.expr {
self.compile_expr(expr)?;
} 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::Return);
@@ -707,7 +703,7 @@ impl StmtVisitor for Compiler {
// condition
self.compile_expr(&stmt.condition)?;
// 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::Call(0));
let condition_patch_index = self.chunk().code.len();
@@ -779,7 +775,7 @@ impl ExprVisitor for Compiler {
let mut exit_patch_index = 0;
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::Call(0));
exit_patch_index = self.chunk().code.len();
@@ -793,14 +789,14 @@ impl ExprVisitor for Compiler {
let name = OP_NAMES
.get(&expr.op.kind)
.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.compile_expr(&expr.rhs)?;
// convert RHS to a bool if we're doing AND or OR
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::Call(0));
}
@@ -838,7 +834,7 @@ impl ExprVisitor for Compiler {
});
self.compile_expr(&expr.expr)?;
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::Call(0));
Ok(())
@@ -862,7 +858,7 @@ impl ExprVisitor for Compiler {
fn visit_get_expr(&mut self, expr: &GetExpr) -> Result<()> {
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));
Ok(())
}
@@ -888,29 +884,28 @@ impl ExprVisitor for Compiler {
}
TokenKind::Number => {
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") {
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") {
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 {
IntInst::create(expr.token.text.parse().unwrap())
Int::create(expr.token.text.parse().unwrap())
};
let constant_id = self.insert_constant(obj)?;
self.emit(expr_line_number(expr), Op::PushConstant(constant_id));
}
TokenKind::String => {
let constant_id =
self.insert_constant(StrInst::create(unescape(&expr.token.text)))?;
let constant_id = self.insert_constant(Str::create(unescape(&expr.token.text)))?;
self.emit(expr_line_number(expr), Op::PushConstant(constant_id));
}
TokenKind::True | TokenKind::False => {
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));
}
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));
}
_ => unreachable!(),
@@ -968,7 +963,7 @@ impl ExprVisitor for Compiler {
}
// 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::Return);
@@ -976,7 +971,7 @@ impl ExprVisitor for Compiler {
// create the function
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
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::vm::{Chunk, JumpOpArg, Op};
@@ -151,11 +151,7 @@ pub fn disassemble(chunk: &Chunk, constants: &Vec<ObjP>, globals: &Vec<String>)
disassemble_chunk(chunk, constants, globals);
for constant in constants {
if let Some(fun) = constant
.borrow()
.as_any()
.downcast_ref::<UserFunctionInst>()
{
if let Some(fun) = constant.borrow().as_any().downcast_ref::<UserFunction>() {
println!();
println!(
"== {} starting on line {}",

View File

@@ -18,7 +18,7 @@ use crate::obj::macros::*;
use crate::vm::{Argc, Vm};
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>;
// 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.
pub fn with_obj_downcast<T, Out>(ptr: ObjP, closure: impl FnOnce(&T) -> Out) -> Out
where
T: Obj + 'static,
T: Object + 'static,
{
let borrowed = ptr.borrow();
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.
pub fn with_obj_downcast_mut<T, Out>(ptr: ObjP, closure: impl FnOnce(&mut T) -> Out) -> Out
where
T: Obj + 'static,
T: Object + 'static,
{
let mut borrowed = ptr.borrow_mut();
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
where
T: Obj + 'static,
T: Object + 'static,
{
let borrowed = ptr.borrow();
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 {
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)
}
}
@@ -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()));
)*
@@ -97,16 +97,16 @@ pub fn init_types() {
// setting up these fundamental types.
$({
let base_type = $base_type.clone();
$name.borrow_mut().set_attr("__type__", base_type);
with_obj_downcast_mut($name.clone(), |type_inst: &mut TypeInst| { type_inst.base.is_instantiated = true; });
$name.borrow_mut().set_attr("__ty__", base_type);
with_obj_downcast_mut($name.clone(), |ty: &mut Ty| { ty.base.is_instantiated = true; });
})*
$({
$(
let vtable_name = stringify!($vtable_name);
let vtable_value = $vtable_value;
with_obj_downcast_mut($name.clone(), |type_inst: &mut TypeInst| {
type_inst.vtable.insert(vtable_name.to_string(), vtable_value);
with_obj_downcast_mut($name.clone(), |ty: &mut Ty| {
ty.vtable.insert(vtable_name.to_string(), vtable_value);
});
)*
})*
@@ -115,82 +115,82 @@ pub fn init_types() {
types! {
// base type
base_type: Type,
base_type: Ty,
// type definitions
Type {
Ty {
// Conversion methods
to_str => BuiltinFunctionInst::create("to_str", BaseObjInst::to_str, 1),
to_repr => BuiltinFunctionInst::create("to_repr", BaseObjInst::to_repr, 1),
to_bool => BuiltinFunctionInst::create("to_bool", BaseObjInst::to_bool, 1),
to_int => BuiltinFunctionInst::create("to_int", BaseObjInst::not_implemented_un, 1),
to_float => BuiltinFunctionInst::create("to_float", BaseObjInst::not_implemented_un, 1),
len => BuiltinFunctionInst::create("len", BaseObjInst::not_implemented_un, 1),
to_str => BuiltinFunction::create("to_str", BaseObj::to_str, 1),
to_repr => BuiltinFunction::create("to_repr", BaseObj::to_repr, 1),
to_bool => BuiltinFunction::create("to_bool", BaseObj::to_bool, 1),
to_int => BuiltinFunction::create("to_int", BaseObj::not_implemented_un, 1),
to_float => BuiltinFunction::create("to_float", BaseObj::not_implemented_un, 1),
len => BuiltinFunction::create("len", BaseObj::not_implemented_un, 1),
// Operators
__add__ => BuiltinFunctionInst::create("__add__", BaseObjInst::not_implemented_bin, 2),
__sub__ => BuiltinFunctionInst::create("__sub__", BaseObjInst::not_implemented_bin, 2),
__mul__ => BuiltinFunctionInst::create("__mul__", BaseObjInst::not_implemented_bin, 2),
__div__ => BuiltinFunctionInst::create("__div__", BaseObjInst::not_implemented_bin, 2),
__and__ => BuiltinFunctionInst::create("__and__", BaseObjInst::and, 2),
__or__ => BuiltinFunctionInst::create("__or__", BaseObjInst::or, 2),
__ne__ => BuiltinFunctionInst::create("__ne__", BaseObjInst::ne, 2),
__eq__ => BuiltinFunctionInst::create("__eq__", BaseObjInst::eq, 2),
__gt__ => BuiltinFunctionInst::create("__gt__", BaseObjInst::not_implemented_bin, 2),
__ge__ => BuiltinFunctionInst::create("__ge__", BaseObjInst::not_implemented_bin, 2),
__lt__ => BuiltinFunctionInst::create("__lt__", BaseObjInst::not_implemented_bin, 2),
__le__ => BuiltinFunctionInst::create("__le__", BaseObjInst::not_implemented_bin, 2),
__pos__ => BuiltinFunctionInst::create("__pos__", BaseObjInst::not_implemented_un, 1),
__neg__ => BuiltinFunctionInst::create("__neg__", BaseObjInst::not_implemented_un, 1),
__not__ => BuiltinFunctionInst::create("__not__", BaseObjInst::not, 1),
__add__ => BuiltinFunction::create("__add__", BaseObj::not_implemented_bin, 2),
__sub__ => BuiltinFunction::create("__sub__", BaseObj::not_implemented_bin, 2),
__mul__ => BuiltinFunction::create("__mul__", BaseObj::not_implemented_bin, 2),
__div__ => BuiltinFunction::create("__div__", BaseObj::not_implemented_bin, 2),
__and__ => BuiltinFunction::create("__and__", BaseObj::and, 2),
__or__ => BuiltinFunction::create("__or__", BaseObj::or, 2),
__ne__ => BuiltinFunction::create("__ne__", BaseObj::ne, 2),
__eq__ => BuiltinFunction::create("__eq__", BaseObj::eq, 2),
__gt__ => BuiltinFunction::create("__gt__", BaseObj::not_implemented_bin, 2),
__ge__ => BuiltinFunction::create("__ge__", BaseObj::not_implemented_bin, 2),
__lt__ => BuiltinFunction::create("__lt__", BaseObj::not_implemented_bin, 2),
__le__ => BuiltinFunction::create("__le__", BaseObj::not_implemented_bin, 2),
__pos__ => BuiltinFunction::create("__pos__", BaseObj::not_implemented_un, 1),
__neg__ => BuiltinFunction::create("__neg__", BaseObj::not_implemented_un, 1),
__not__ => BuiltinFunction::create("__not__", BaseObj::not, 1),
},
Obj { },
Object { },
Str {
// Conversion methods
to_str => BuiltinFunctionInst::create("to_str", StrInst::to_str, 1),
to_repr => BuiltinFunctionInst::create("to_repr", StrInst::to_repr, 1),
to_int => BuiltinFunctionInst::create("to_int", StrInst::to_int, 1),
to_float => BuiltinFunctionInst::create("to_float", StrInst::to_float, 1),
len => BuiltinFunctionInst::create("len", StrInst::len, 1),
to_str => BuiltinFunction::create("to_str", Str::to_str, 1),
to_repr => BuiltinFunction::create("to_repr", Str::to_repr, 1),
to_int => BuiltinFunction::create("to_int", Str::to_int, 1),
to_float => BuiltinFunction::create("to_float", Str::to_float, 1),
len => BuiltinFunction::create("len", Str::len, 1),
// Operators
__add__ => BuiltinFunctionInst::create("__add__", StrInst::add, 2),
__mul__ => BuiltinFunctionInst::create("__mul__", StrInst::mul, 2),
__add__ => BuiltinFunction::create("__add__", Str::add, 2),
__mul__ => BuiltinFunction::create("__mul__", Str::mul, 2),
// .lower, .upper, .slice, etc
},
Int {
// Conversion methods
to_int => BuiltinFunctionInst::create("to_int", IntInst::to_int, 1),
to_float => BuiltinFunctionInst::create("to_float", IntInst::to_float, 1),
to_int => BuiltinFunction::create("to_int", Int::to_int, 1),
to_float => BuiltinFunction::create("to_float", Int::to_float, 1),
// Operators
__add__ => BuiltinFunctionInst::create("__add__", IntInst::add, 2),
__sub__ => BuiltinFunctionInst::create("__sub__", IntInst::sub, 2),
__mul__ => BuiltinFunctionInst::create("__mul__", IntInst::mul, 2),
__div__ => BuiltinFunctionInst::create("__div__", IntInst::div, 2),
//__eq__ => BuiltinFunctionInst::create("__eq__", IntInst::eq, 2),
__gt__ => BuiltinFunctionInst::create("__gt__", IntInst::gt, 2),
__ge__ => BuiltinFunctionInst::create("__ge__", IntInst::ge, 2),
__lt__ => BuiltinFunctionInst::create("__lt__", IntInst::lt, 2),
__le__ => BuiltinFunctionInst::create("__le__", IntInst::le, 2),
__pos__ => BuiltinFunctionInst::create("__pos__", IntInst::pos, 1),
__neg__ => BuiltinFunctionInst::create("__neg__", IntInst::neg, 1),
__add__ => BuiltinFunction::create("__add__", Int::add, 2),
__sub__ => BuiltinFunction::create("__sub__", Int::sub, 2),
__mul__ => BuiltinFunction::create("__mul__", Int::mul, 2),
__div__ => BuiltinFunction::create("__div__", Int::div, 2),
//__eq__ => BuiltinFunction::create("__eq__", Int::eq, 2),
__gt__ => BuiltinFunction::create("__gt__", Int::gt, 2),
__ge__ => BuiltinFunction::create("__ge__", Int::ge, 2),
__lt__ => BuiltinFunction::create("__lt__", Int::lt, 2),
__le__ => BuiltinFunction::create("__le__", Int::le, 2),
__pos__ => BuiltinFunction::create("__pos__", Int::pos, 1),
__neg__ => BuiltinFunction::create("__neg__", Int::neg, 1),
},
Float {
// Conversion methods
to_int => BuiltinFunctionInst::create("to_int", FloatInst::to_int, 1),
to_float => BuiltinFunctionInst::create("to_float", FloatInst::to_float, 1),
to_int => BuiltinFunction::create("to_int", Float::to_int, 1),
to_float => BuiltinFunction::create("to_float", Float::to_float, 1),
// Operators
__add__ => BuiltinFunctionInst::create("__add__", FloatInst::add, 2),
__sub__ => BuiltinFunctionInst::create("__sub__", FloatInst::sub, 2),
__mul__ => BuiltinFunctionInst::create("__mul__", FloatInst::mul, 2),
__div__ => BuiltinFunctionInst::create("__div__", FloatInst::div, 2),
__gt__ => BuiltinFunctionInst::create("__gt__", FloatInst::gt, 2),
__ge__ => BuiltinFunctionInst::create("__ge__", FloatInst::ge, 2),
__lt__ => BuiltinFunctionInst::create("__lt__", FloatInst::lt, 2),
__le__ => BuiltinFunctionInst::create("__le__", FloatInst::le, 2),
__pos__ => BuiltinFunctionInst::create("__pos__", FloatInst::pos, 1),
__neg__ => BuiltinFunctionInst::create("__neg__", FloatInst::neg, 1),
__add__ => BuiltinFunction::create("__add__", Float::add, 2),
__sub__ => BuiltinFunction::create("__sub__", Float::sub, 2),
__mul__ => BuiltinFunction::create("__mul__", Float::mul, 2),
__div__ => BuiltinFunction::create("__div__", Float::div, 2),
__gt__ => BuiltinFunction::create("__gt__", Float::gt, 2),
__ge__ => BuiltinFunction::create("__ge__", Float::ge, 2),
__lt__ => BuiltinFunction::create("__lt__", Float::lt, 2),
__le__ => BuiltinFunction::create("__le__", Float::le, 2),
__pos__ => BuiltinFunction::create("__pos__", Float::pos, 1),
__neg__ => BuiltinFunction::create("__neg__", Float::neg, 1),
},
Bool { },
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
/// 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)))
}
////////////////////////////////////////////////////////////////////////////////
// Obj
// Object
////////////////////////////////////////////////////////////////////////////////
pub trait Obj: Debug + Display + Any + Trace {
pub trait Object: Debug + Display + Any + Trace {
fn instantiate(&mut self);
fn is_instantiated(&self) -> bool;
@@ -235,45 +235,42 @@ pub trait Obj: Debug + Display + Any + Trace {
return attr;
}
let mut type_inst = self.type_inst();
let mut ty = self.ty();
loop {
let vtable_entry =
with_obj_downcast_mut(type_inst.clone(), |type_inst: &mut TypeInst| {
type_inst.vtable.get(name).cloned()
})
.map(|vtable_entry| {
let ptr = if obj_is_inst::<BuiltinFunctionInst>(&vtable_entry)
|| obj_is_inst::<UserFunctionInst>(&vtable_entry)
{
MethodInst::create(self_ptr.clone(), vtable_entry)
} else {
vtable_entry
};
// TODO Obj::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
// floating around.
//self.set_attr(name, ptr.clone());
ptr
});
with_obj_downcast_mut(ty.clone(), |ty: &mut Ty| ty.vtable.get(name).cloned()).map(
|vtable_entry| {
let ptr = if obj_is_inst::<BuiltinFunction>(&vtable_entry)
|| obj_is_inst::<UserFunction>(&vtable_entry)
{
Method::create(self_ptr.clone(), vtable_entry)
} else {
vtable_entry
};
// 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
// floating around.
//self.set_attr(name, ptr.clone());
ptr
},
);
if vtable_entry.is_some() {
return vtable_entry;
}
let type_inst_copy = type_inst.borrow().type_inst();
if type_inst.borrow().equals(&*type_inst_copy.borrow()) {
let ty_copy = ty.borrow().ty();
if ty.borrow().equals(&*ty_copy.borrow()) {
return None;
}
type_inst = type_inst_copy;
ty = ty_copy;
}
}
fn type_inst(&self) -> ObjP {
self.get_attr("__type__").expect("no __type__")
fn ty(&self) -> ObjP {
self.get_attr("__ty__").expect("no __ty__")
}
fn type_name(&self) -> Rc<String> {
with_obj_downcast(self.type_inst(), |type_inst: &TypeInst| {
Rc::clone(&type_inst.name)
})
fn ty_name(&self) -> Rc<String> {
with_obj_downcast(self.ty(), |ty: &Ty| Rc::clone(&ty.name))
}
fn arity(&self) -> Option<Argc> {
@@ -281,7 +278,7 @@ pub trait Obj: Debug + Display + Any + Trace {
}
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
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
}
fn equals(&self, other: &dyn Obj) -> bool;
fn equals(&self, other: &dyn Object) -> bool;
fn as_any(&self) -> &dyn Any;
@@ -298,16 +295,16 @@ pub trait Obj: Debug + Display + Any + Trace {
}
////////////////////////////////////////////////////////////////////////////////
// BaseObjInst
// BaseObj
////////////////////////////////////////////////////////////////////////////////
#[derive(Default, Debug, Trace, Finalize)]
pub(crate) struct BaseObjInst {
pub(crate) struct BaseObj {
attrs: Attrs,
is_instantiated: bool,
}
impl Clone for BaseObjInst {
impl Clone for BaseObj {
fn clone(&self) -> Self {
Self {
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 {
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) {
self.is_instantiated = true;
}
@@ -339,8 +336,8 @@ impl Obj for BaseObjInst {
&mut self.attrs
}
fn equals(&self, other: &dyn Obj) -> bool {
if let Some(other) = other.as_any().downcast_ref::<BaseObjInst>() {
fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<BaseObj>() {
// compare all attrs
self.attrs.iter().all(|(k1, v1)| {
other
@@ -364,15 +361,15 @@ impl Obj for BaseObjInst {
}
////////////////////////////////////////////////////////////////////////////////
// ObjInst
// Obj
////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Trace, Finalize)]
pub struct ObjInst {
base: BaseObjInst,
pub struct Obj {
base: BaseObj,
}
impl ObjInst {
impl Obj {
pub fn new() -> Self {
Self {
base: Default::default(),
@@ -382,37 +379,37 @@ impl ObjInst {
impl_create!();
}
impl Display for ObjInst {
impl Display for Obj {
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 {
fn equals(&self, other: &dyn Obj) -> bool {
if let Some(other) = other.as_any().downcast_ref::<ObjInst>() {
impl Object for Obj {
fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<Obj>() {
self.base.equals(&other.base)
} else {
false
}
}
impl_base_obj!(Obj);
impl_base_obj!(Object);
}
////////////////////////////////////////////////////////////////////////////////
// TypeInst
// Ty
////////////////////////////////////////////////////////////////////////////////
#[derive(Trace, Finalize)]
pub struct TypeInst {
base: BaseObjInst,
pub struct Ty {
base: BaseObj,
#[unsafe_ignore_trace]
name: Rc<String>,
vtable: HashMap<String, ObjP>,
}
impl TypeInst {
impl Ty {
pub fn new(name: impl ToString) -> Self {
Self {
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 {
write!(
fmt,
"<Type {} at {:x}>",
"<Ty {} at {:x}>",
self.name,
(self as *const _ as usize)
)
}
}
impl Display for TypeInst {
impl Display for Ty {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(
fmt,
"<Type {} at {:x}>",
"<Ty {} at {:x}>",
self.name,
(self as *const _ as usize)
)
}
}
impl Obj for TypeInst {
fn equals(&self, other: &dyn Obj) -> bool {
if let Some(other) = other.as_any().downcast_ref::<TypeInst>() {
// TODO TypeInst::equals : something more robust than this
// Types 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
// to go through attributes to specially exclude to the __type__ attribute if it points
impl Object for Ty {
fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<Ty>() {
// TODO Ty::equals : something more robust than this
// Tys should hold equality if they have the same name
// 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 __ty__ attribute if it points
// to ourself.
// How do we detect that it's pointing to ourself? I suppose pointers are the way
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)]
pub struct StrInst {
base: BaseObjInst,
pub struct Str {
base: BaseObj,
#[unsafe_ignore_trace]
str_value: Rc<String>,
}
impl StrInst {
impl Str {
pub fn new(str_value: impl ToString) -> Self {
Self {
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 {
write!(fmt, "{}", self.str_value)
}
}
impl Obj for StrInst {
impl Object for Str {
fn is_truthy(&self) -> bool {
!self.str_value.is_empty()
}
fn equals(&self, other: &dyn Obj) -> bool {
if let Some(other) = other.as_any().downcast_ref::<StrInst>() {
fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<Str>() {
self.str_value == other.str_value
} else {
false
@@ -517,16 +514,16 @@ impl Obj for StrInst {
}
////////////////////////////////////////////////////////////////////////////////
// IntInst
// Int
////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Trace, Finalize)]
pub struct IntInst {
base: BaseObjInst,
pub struct Int {
base: BaseObj,
int_value: i64,
}
impl IntInst {
impl Int {
pub fn new(int_value: i64) -> Self {
Self {
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 {
write!(fmt, "{}", self.int_value)
}
}
impl Obj for IntInst {
impl Object for Int {
fn is_truthy(&self) -> bool {
self.int_value != 0
}
fn equals(&self, other: &dyn Obj) -> bool {
if let Some(other) = other.as_any().downcast_ref::<IntInst>() {
fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<Int>() {
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
} else {
false
@@ -566,16 +563,16 @@ impl Obj for IntInst {
}
////////////////////////////////////////////////////////////////////////////////
// FloatInst
// Float
////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Trace, Finalize)]
pub struct FloatInst {
base: BaseObjInst,
pub struct Float {
base: BaseObj,
float_value: f64,
}
impl FloatInst {
impl Float {
pub fn new(float_value: f64) -> Self {
Self {
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 {
// we want to force the .0 if it's a whole number
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 {
self.float_value != 0.0
}
fn equals(&self, other: &dyn Obj) -> bool {
if let Some(other) = other.as_any().downcast_ref::<FloatInst>() {
fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<Float>() {
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
} else {
false
@@ -620,16 +617,16 @@ impl Obj for FloatInst {
}
////////////////////////////////////////////////////////////////////////////////
// BoolInst
// Bool
////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Trace, Finalize)]
pub struct BoolInst {
base: BaseObjInst,
pub struct Bool {
base: BaseObj,
bool_value: bool,
}
impl BoolInst {
impl Bool {
pub fn new(bool_value: bool) -> Self {
Self {
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 {
write!(fmt, "{}", self.bool_value)
}
}
impl Obj for BoolInst {
impl Object for Bool {
fn is_truthy(&self) -> bool {
self.bool_value
}
fn equals(&self, other: &dyn Obj) -> bool {
if let Some(other) = other.as_any().downcast_ref::<BoolInst>() {
fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<Bool>() {
self.bool_value == other.bool_value
} else {
false
@@ -667,15 +664,15 @@ impl Obj for BoolInst {
}
////////////////////////////////////////////////////////////////////////////////
// NilInst
// Nil
////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Default, Trace, Finalize)]
pub struct NilInst {
base: BaseObjInst,
pub struct Nil {
base: BaseObj,
}
impl NilInst {
impl Nil {
pub fn new() -> Self {
Default::default()
}
@@ -683,19 +680,19 @@ impl NilInst {
impl_create!();
}
impl Display for NilInst {
impl Display for Nil {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "nil")
}
}
impl Obj for NilInst {
impl Object for Nil {
fn is_truthy(&self) -> bool {
false
}
fn equals(&self, other: &dyn Obj) -> bool {
other.as_any().downcast_ref::<NilInst>().is_some()
fn equals(&self, other: &dyn Object) -> bool {
other.as_any().downcast_ref::<Nil>().is_some()
}
impl_base_obj!(Nil);
@@ -709,49 +706,49 @@ impl Obj for NilInst {
fn test_new_objects() {
init_types();
let type_value = TypeInst::create("Type");
assert_eq!(&*type_value.borrow().type_name(), "Type");
let type_value = Ty::create("Ty");
assert_eq!(&*type_value.borrow().ty_name(), "Ty");
let str_value = StrInst::create("asdfasdfasdfasdfasdf");
assert_eq!(&*str_value.borrow().type_name(), "Str");
let str_value = Str::create("asdfasdfasdfasdfasdf");
assert_eq!(&*str_value.borrow().ty_name(), "Str");
let int_value = IntInst::create(1234);
assert_eq!(&*int_value.borrow().type_name(), "Int");
let int_value = Int::create(1234);
assert_eq!(&*int_value.borrow().ty_name(), "Int");
let float_value = FloatInst::create(1234.5678);
assert_eq!(&*float_value.borrow().type_name(), "Float");
let float_value = Float::create(1234.5678);
assert_eq!(&*float_value.borrow().ty_name(), "Float");
let nil_value = NilInst::create();
assert_eq!(&*nil_value.borrow().type_name(), "Nil");
let nil_value = Nil::create();
assert_eq!(&*nil_value.borrow().ty_name(), "Nil");
}
#[test]
fn test_obj_equals() {
init_types();
let int1 = IntInst::create(1234);
let int2 = IntInst::create(1234);
let int1 = Int::create(1234);
let int2 = Int::create(1234);
assert!(int1.borrow().equals(&*int2.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!(float1.borrow().equals(&*int2.borrow()));
// self-equality
let str1 = StrInst::create("1234");
let str1 = Str::create("1234");
assert!(str1.borrow().equals(&*str1.borrow()));
let str2 = StrInst::create("1234");
let str2 = Str::create("1234");
assert!(str1.borrow().equals(&*str2.borrow()));
assert!(str2.borrow().equals(&*str1.borrow()));
assert!(!str1.borrow().equals(&*float1.borrow()));
assert!(!str1.borrow().equals(&*int1.borrow()));
let obj1 = ObjInst::create();
let obj2 = ObjInst::create();
let obj1 = Obj::create();
let obj2 = Obj::create();
assert!(obj1.borrow().equals(&*obj2.borrow()));
// these objects aren't equal anymore
@@ -766,14 +763,14 @@ fn test_obj_equals() {
#[test]
fn test_obj_vtable() {
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");
assert!(to_string_ptr.is_some());
let to_string_ptr = to_string_ptr.unwrap();
assert!(obj_is_inst::<MethodInst>(&to_string_ptr));
with_obj_downcast(to_string_ptr.clone(), |method: &MethodInst| {
assert!(obj_is_inst::<Method>(&to_string_ptr));
with_obj_downcast(to_string_ptr.clone(), |method: &Method| {
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()
let method_to_string_ptr = method_to_string_ptr.unwrap();
assert!(obj_is_inst::<MethodInst>(&method_to_string_ptr));
with_obj_downcast(method_to_string_ptr.clone(), |method: &MethodInst| {
assert!(obj_is_inst::<Method>(&method_to_string_ptr));
with_obj_downcast(method_to_string_ptr.clone(), |method: &Method| {
assert!(method
.self_binding()
.borrow()

View File

@@ -5,7 +5,7 @@ use std::rc::Rc;
use gc::{Finalize, Trace};
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};
////////////////////////////////////////////////////////////////////////////////
@@ -49,14 +49,14 @@ pub enum FunctionState {
}
////////////////////////////////////////////////////////////////////////////////
// BuiltinFunctionInst
// BuiltinFunction
////////////////////////////////////////////////////////////////////////////////
pub type BuiltinFunctionPtr = fn(vm: &mut Vm, function_state: FunctionState) -> FunctionResult;
#[derive(Debug, Trace, Finalize)]
pub struct BuiltinFunctionInst {
base: BaseObjInst,
pub struct BuiltinFunction {
base: BaseObj,
#[unsafe_ignore_trace]
name: Rc<String>,
#[unsafe_ignore_trace]
@@ -64,7 +64,7 @@ pub struct BuiltinFunctionInst {
arity: Argc,
}
impl BuiltinFunctionInst {
impl BuiltinFunction {
pub fn new(name: impl ToString, function: BuiltinFunctionPtr, arity: Argc) -> Self {
Self {
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 {
write!(
fmt,
@@ -97,7 +97,7 @@ impl Display for BuiltinFunctionInst {
}
}
impl Obj for BuiltinFunctionInst {
impl Object for BuiltinFunction {
fn arity(&self) -> Option<Argc> {
Some(self.arity)
}
@@ -111,10 +111,10 @@ impl Obj for BuiltinFunctionInst {
vm.push_frame(new_frame);
}
fn equals(&self, other: &dyn Obj) -> bool {
// TODO BuiltinFunctionInst::equals : need something more robust than checking addr_eq,
fn equals(&self, other: &dyn Object) -> bool {
// TODO BuiltinFunction::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>() {
if let Some(other) = other.as_any().downcast_ref::<BuiltinFunction>() {
ptr::addr_eq(self, other)
} else {
false
@@ -125,12 +125,12 @@ impl Obj for BuiltinFunctionInst {
}
////////////////////////////////////////////////////////////////////////////////
// UserFunctionInst
// UserFunction
////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Clone, Trace, Finalize)]
pub struct UserFunctionInst {
base: BaseObjInst,
pub struct UserFunction {
base: BaseObj,
#[unsafe_ignore_trace]
name: Rc<String>,
#[unsafe_ignore_trace]
@@ -139,7 +139,7 @@ pub struct UserFunctionInst {
captures: Vec<ObjP>,
}
impl UserFunctionInst {
impl UserFunction {
pub fn new(chunk: Chunk, arity: Argc) -> Self {
Self {
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 {
write!(
fmt,
@@ -181,7 +181,7 @@ impl Display for UserFunctionInst {
}
}
impl Obj for UserFunctionInst {
impl Object for UserFunction {
fn arity(&self) -> Option<Argc> {
Some(self.arity)
}
@@ -199,9 +199,9 @@ impl Obj for UserFunctionInst {
}
}
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.
fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<UserFunction>() {
// TODO UserFunction::equals : need something more robust than checking addr_eq.
ptr::addr_eq(self, other)
} else {
false
@@ -212,19 +212,19 @@ impl Obj for UserFunctionInst {
}
////////////////////////////////////////////////////////////////////////////////
// MethodInst
// Method
////////////////////////////////////////////////////////////////////////////////
#[derive(Trace, Finalize)]
pub struct MethodInst {
base: BaseObjInst,
pub struct Method {
base: BaseObj,
self_binding: ObjP,
function: ObjP,
}
impl Debug for MethodInst {
impl Debug for Method {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("MethodInst")
fmt.debug_struct("Method")
.field("base", &self.base)
.field("self_binding", &format!("{}", self.self_binding.borrow()))
.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 {
Self {
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 {
write!(fmt, "{}", self.function.borrow())
}
}
impl Obj for MethodInst {
impl Object for Method {
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.
@@ -273,8 +273,8 @@ impl Obj for MethodInst {
self.function.borrow().call(vm, argc)
}
fn equals(&self, other: &dyn Obj) -> bool {
if let Some(other) = other.as_any().downcast_ref::<MethodInst>() {
fn equals(&self, other: &dyn Object) -> bool {
if let Some(other) = other.as_any().downcast_ref::<Method>() {
ptr::addr_eq(&*self.self_binding, &*other.self_binding)
&& ptr::addr_eq(&*self.function, &*other.function)
} else {

View File

@@ -7,7 +7,7 @@ macro_rules! impl_base_obj {
.expect(concat!("no ", stringify!($type_name)))
.clone()
});
self.set_attr("__type__", ty);
self.set_attr("__ty__", ty);
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.
pub fn new(chunk: Rc<Chunk>, constants: Vec<ObjP>, global_names: Vec<String>) -> Self {
// 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 register_global = |name: &str, value: ObjP| {
@@ -290,7 +290,7 @@ impl Vm {
// need both declarations to borrow cell value
let name_obj = Ptr::clone(&self.constants[constant_id as usize]);
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 value = owner.borrow_mut().get_vtable_attr(owner.clone(), &name);
if let Some(value) = value {
@@ -309,7 +309,7 @@ impl Vm {
Op::SetAttr(constant_id) => {
let name_obj = Ptr::clone(&self.constants[constant_id as usize]);
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 target = self.pop();
@@ -378,10 +378,9 @@ impl Vm {
// constants, we want to deep-clone this object so we don't alter any live
// objects.
// 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 mut fun: UserFunctionInst =
with_obj_downcast(fun_ptr, UserFunctionInst::clone);
let mut fun: UserFunction = with_obj_downcast(fun_ptr, UserFunction::clone);
let frame_index = self.frames.len() - (depth as usize) - 1;
let stack_base = self.frames[frame_index].stack_base;
let value = Ptr::clone(&self.stack[stack_base + (slot as usize)]);