Add FloatInst method implementations and tests
FloatInst should be fully implemented now and have a suite of tests to make sure those methods are doing what they should be. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
102
src/builtins.rs
102
src/builtins.rs
@@ -267,7 +267,7 @@ impl StrInst {
|
||||
// IntInst implementations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! bin_op_math {
|
||||
macro_rules! int_bin_op_math {
|
||||
($function:ident, $op:tt) => {
|
||||
pub(crate) fn $function(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
|
||||
let lhs = vm.frame_stack()[0].clone();
|
||||
@@ -292,7 +292,7 @@ macro_rules! bin_op_math {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! bin_op_logical {
|
||||
macro_rules! int_bin_op_logical {
|
||||
($function:ident, $op:tt) => {
|
||||
pub(crate) fn $function(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
|
||||
let lhs = vm.frame_stack()[0].clone();
|
||||
@@ -318,8 +318,8 @@ macro_rules! bin_op_logical {
|
||||
}
|
||||
|
||||
impl IntInst {
|
||||
bin_op_math!(add, +);
|
||||
bin_op_math!(sub, -);
|
||||
int_bin_op_math!(add, +);
|
||||
int_bin_op_math!(sub, -);
|
||||
|
||||
pub(crate) fn mul(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
|
||||
// can't bin_op_math this one because it needs the string case
|
||||
@@ -350,12 +350,15 @@ impl IntInst {
|
||||
// TODO IntInst::div - handle divide by zero
|
||||
// BLOCKED-ON: exceptions
|
||||
// NOTE - we will probably need to get rid of the macro here to handle that :(
|
||||
bin_op_math!(div, /);
|
||||
int_bin_op_math!(div, /);
|
||||
|
||||
bin_op_logical!(gt, >);
|
||||
bin_op_logical!(ge, >=);
|
||||
bin_op_logical!(lt, <);
|
||||
bin_op_logical!(le, <=);
|
||||
// __eq__ will use the default .equals implementation
|
||||
//int_bin_op_logical!(eq, ==);
|
||||
// __ne__ will call __eq__ and negate it
|
||||
int_bin_op_logical!(gt, >);
|
||||
int_bin_op_logical!(ge, >=);
|
||||
int_bin_op_logical!(lt, <);
|
||||
int_bin_op_logical!(le, <=);
|
||||
|
||||
pub(crate) fn pos(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
|
||||
let lhs = vm.frame_stack()[0].clone();
|
||||
@@ -369,3 +372,84 @@ impl IntInst {
|
||||
IntInst::create(-value).into()
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FloatInst implementations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! float_bin_op_math {
|
||||
($function:ident, $op:tt) => {
|
||||
pub(crate) fn $function(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
|
||||
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 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())
|
||||
} else {
|
||||
// TODO IntInst 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()
|
||||
)
|
||||
};
|
||||
result.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! float_bin_op_logical {
|
||||
($function:ident, $op:tt) => {
|
||||
pub(crate) fn $function(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
|
||||
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 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())
|
||||
} else {
|
||||
// TODO IntInst 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()
|
||||
)
|
||||
};
|
||||
result.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FloatInst {
|
||||
float_bin_op_math!(add, +);
|
||||
float_bin_op_math!(sub, -);
|
||||
float_bin_op_math!(mul, *);
|
||||
float_bin_op_math!(div, /);
|
||||
|
||||
// __eq__ will use the default .equals implementation
|
||||
//int_bin_op_logical!(eq, ==);
|
||||
// __ne__ will call __eq__ and negate it
|
||||
float_bin_op_logical!(gt, >);
|
||||
float_bin_op_logical!(ge, >=);
|
||||
float_bin_op_logical!(lt, <);
|
||||
float_bin_op_logical!(le, <=);
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
22
src/obj.rs
22
src/obj.rs
@@ -156,6 +156,7 @@ pub fn init_types() {
|
||||
__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),
|
||||
@@ -163,7 +164,19 @@ pub fn init_types() {
|
||||
__pos__ => BuiltinFunctionInst::create("__pos__", IntInst::pos, 1),
|
||||
__neg__ => BuiltinFunctionInst::create("__neg__", IntInst::neg, 1),
|
||||
},
|
||||
Float { },
|
||||
Float {
|
||||
__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),
|
||||
},
|
||||
Bool { },
|
||||
Nil { },
|
||||
BuiltinFunction { },
|
||||
@@ -588,7 +601,12 @@ impl Finalize for FloatInst {
|
||||
|
||||
impl Display for FloatInst {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{}", self.float_value)
|
||||
// we want to force the .0 if it's a whole number
|
||||
if self.float_value == self.float_value.floor() {
|
||||
write!(fmt, "{}.0", self.float_value)
|
||||
} else {
|
||||
write!(fmt, "{}", self.float_value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user