Skip to content

Commit

Permalink
Merge #55
Browse files Browse the repository at this point in the history
55: More comparisons r=vext01 a=ltratt

This PR adds more comparisons to yksom: reference equality (1dca2bc) and various comparisons for doubles (82d35c5). Notice that the former commit means that we diverge slightly from SOM's current semantics (see SOM-st/SOM#23) although I think it's fair to say that @smarr thinks the approach we're taking in this PR is the right one (and if I've got that wrong, hopefully he'll shout!).

Co-authored-by: Laurence Tratt <[email protected]>
  • Loading branch information
bors[bot] and ltratt authored Oct 9, 2019
2 parents a745951 + 82d35c5 commit b1f477b
Show file tree
Hide file tree
Showing 14 changed files with 194 additions and 0 deletions.
46 changes: 46 additions & 0 deletions lang_tests/double10.som
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"
VM:
status: success
stdout:
false
true
true
true
false
true
false
false
false
true
true
false
true
true
true
false
"

double10 = (
run = (
(1.0 = 0) println.
(1.0 = 1) println.
(1.0 ~= 0) println.
(1.0 ~= 1) println.

(1.0 < 1) println.
(1.0 < 2) println.
(2.0 < 0) println.

(1.0 > 1) println.
(1.0 > 2) println.
(2.0 > 0) println.

(1.0 >= 1) println.
(1.0 >= 2) println.
(2.0 >= 0) println.

(1.0 <= 1) println.
(1.0 <= 2) println.
(2.0 <= 0) println.
)
)
29 changes: 29 additions & 0 deletions lang_tests/obj1.som
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"
VM:
status: success
stdout:
true
false
false
true
true
true
false
false
true
"

obj1 = (
run = (
(1 == 1) println.
(1 <> 1) println.
(1 ~= 1) println.
(1 <> 2) println.
(1 ~= 2) println.

(self == self) println.
(self <> self) println.
(self == 'a') println.
(self <> 'a') println.
)
)
22 changes: 22 additions & 0 deletions lang_tests/obj2.som
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"
VM:
status: success
stdout:
true
true
true
true
false
false
"

obj2 = (
run = (
(1 == 1) println.
(100 == 100) println.
((1 << 200) == (1 << 200)) println.
(1.0 == 1.0) println.
(1.0 == 1) println.
(1 == 1.0) println.
)
)
4 changes: 4 additions & 0 deletions lib/SOM/Double.som
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@ Double = (
* argument = primitive
= argument = primitive
< argument = primitive
> argument = ( ^(self >= argument) and: [ self <> argument ] )
>= argument = ( ^(self < argument) not )
<= argument = ( ^(self < argument) or: [ self = argument ] )
negative = ( ^self < 0.0 )
asString = primitive
)
2 changes: 2 additions & 0 deletions lib/SOM/False.som
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
False = Boolean (
asString = ( ^'false' )
not = ( ^true )
or: block = ( ^block value )
and: block = ( ^false )
ifTrue: block = ( ^nil )
ifFalse: block = ( ^block value )
)
5 changes: 5 additions & 0 deletions lib/SOM/Object.som
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ Object = nil (
class = primitive
asString = ( ^'instance of ' concatenate: (self class asString) )

= other = ( ^self == other )
<> argument = ( ^(self = argument) not )
== other = primitive
~= other = (^ (self == other) not )

print = ( self asString print )
println = (
self print.
Expand Down
2 changes: 2 additions & 0 deletions lib/SOM/True.som
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
True = Boolean (
asString = ( ^'true' )
not = ( ^false )
or: block = ( ^true )
and: block = ( ^block value )
ifTrue: block = ( ^block value )
ifFalse: block = ( ^nil )
)
4 changes: 4 additions & 0 deletions src/lib/compiler/ast_to_instrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ impl<'a> Compiler<'a> {
requires_args(1)?;
Ok(cobjects::MethodBody::Primitive(Primitive::Equals))
}
"==" => {
requires_args(1)?;
Ok(cobjects::MethodBody::Primitive(Primitive::RefEquals))
}
"~=" => {
requires_args(1)?;
Ok(cobjects::MethodBody::Primitive(Primitive::NotEquals))
Expand Down
1 change: 1 addition & 0 deletions src/lib/compiler/instrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub enum Primitive {
New,
PrintNewline,
PrintString,
RefEquals,
Restart,
Shl,
Sub,
Expand Down
4 changes: 4 additions & 0 deletions src/lib/vm/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,10 @@ impl VM {
self.stack_push(stry!(rcv.not_equals(self, self.stack_pop())));
SendReturn::Val
}
Primitive::RefEquals => {
self.stack_push(stry!(rcv.ref_equals(self, self.stack_pop())));
SendReturn::Val
}
Primitive::Restart => unreachable!(),
Primitive::PrintNewline => {
println!();
Expand Down
45 changes: 45 additions & 0 deletions src/lib/vm/objects/double.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,51 @@ impl Obj for Double {
}))
}
}

fn ref_equals(&self, vm: &VM, other: Val) -> Result<Val, Box<VMError>> {
let b = if let Some(rhs) = other.try_downcast::<Double>(vm) {
self.val == rhs.double()
} else {
false
};
Ok(Val::from_bool(vm, b))
}

fn equals(&self, vm: &VM, other: Val) -> Result<Val, Box<VMError>> {
let b = if let Some(rhs) = other.as_isize(vm) {
self.val == (rhs as f64)
} else if let Some(rhs) = other.try_downcast::<Double>(vm) {
self.val == rhs.double()
} else if let Some(rhs) = other.try_downcast::<ArbInt>(vm) {
match rhs.bigint().to_f64() {
Some(i) => self.val == i,
None => false,
}
} else {
false
};

Ok(Val::from_bool(vm, b))
}

fn less_than(&self, vm: &VM, other: Val) -> Result<Val, Box<VMError>> {
let b = if let Some(rhs) = other.as_isize(vm) {
self.val < (rhs as f64)
} else if let Some(rhs) = other.try_downcast::<Double>(vm) {
self.val < rhs.double()
} else if let Some(rhs) = other.try_downcast::<ArbInt>(vm) {
match rhs.bigint().to_f64() {
Some(i) => self.val < i,
None => false,
}
} else {
return Err(Box::new(VMError::NotANumber {
got: other.dyn_objtype(vm),
}));
};

Ok(Val::from_bool(vm, b))
}
}

impl StaticObjType for Double {
Expand Down
9 changes: 9 additions & 0 deletions src/lib/vm/objects/integers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,15 @@ impl Obj for ArbInt {
}
}

fn ref_equals(&self, vm: &VM, other: Val) -> Result<Val, Box<VMError>> {
let b = if let Some(rhs) = other.try_downcast::<ArbInt>(vm) {
self.val == rhs.val
} else {
false
};
Ok(Val::from_bool(vm, b))
}

fn equals(&self, vm: &VM, other: Val) -> Result<Val, Box<VMError>> {
let b = if other.dyn_objtype(vm) == ObjType::Int {
debug_assert!(self.val != BigInt::from_isize(other.as_isize(vm).unwrap()).unwrap());
Expand Down
12 changes: 12 additions & 0 deletions src/lib/vm/objects/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,18 @@ pub trait Obj: std::fmt::Debug + abgc::GcLayout {
unimplemented!();
}

/// Is this `Val` reference equality equal to `other`? Only number types are likely to want to
/// override this.
fn ref_equals(&self, vm: &VM, other: Val) -> Result<Val, Box<VMError>> {
let other_tobj = other.tobj(vm)?;
let other_data =
unsafe { std::mem::transmute::<&dyn Obj, (*const u8, usize)>(&**other_tobj).0 };
Ok(Val::from_bool(
vm,
(self as *const _ as *const u8) == other_data,
))
}

/// Does this `Val` equal `other`?
fn equals(&self, _: &VM, _: Val) -> Result<Val, Box<VMError>> {
unimplemented!();
Expand Down
9 changes: 9 additions & 0 deletions src/lib/vm/val.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,15 @@ impl Val {
ValKind::GCBOX => self.tobj(vm).unwrap().to_strval(vm),
}
}

/// Is this `Val` reference equal to `other`? Notice that for integers (but not Doubles)
/// "reference equal" is equivalent to "equals".
pub fn ref_equals(&self, vm: &VM, other: Val) -> Result<Val, Box<VMError>> {
match self.valkind() {
ValKind::INT => self.equals(vm, other),
ValKind::GCBOX => self.tobj(vm)?.ref_equals(vm, other),
}
}
}

macro_rules! binop_all {
Expand Down

0 comments on commit b1f477b

Please sign in to comment.