From 05606c768b55f7dc9689eba586d347e0cec78a16 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Tue, 9 Jun 2020 08:10:31 +0100 Subject: [PATCH] Implement the 'as32Bit[Un]signedValue' primitives. Java SOM crashes on big integers, so I have defined what I believe to be appropriate semantics for them which appears to be not to perform sign extension in the conversion. For example: ((1 << 60) - 1) as32BitUnsignedValue in Java SOM returns 4294967295, which is bigger than a signed 32 bit can represent. This commit preserves that behaviour. --- lang_tests/to32bits.som | 43 +++++++++++++++++++++++++++++++++++++++++ src/lib/vm/core.rs | 30 ++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 lang_tests/to32bits.som diff --git a/lang_tests/to32bits.som b/lang_tests/to32bits.som new file mode 100644 index 00000000..c982409a --- /dev/null +++ b/lang_tests/to32bits.som @@ -0,0 +1,43 @@ +" +VM: + status: success + stdout: + 0 + 1 + 4294967295 + 4294967295 + 0 + 4294967295 + 0 + 4294967295 + 0 + 1 + -1 + -1 + 0 + -1 + 0 + -1 +" + +to32bits = ( + run = ( + 0 as32BitUnsignedValue println. + 1 as32BitUnsignedValue println. + -1 as32BitUnsignedValue println. + 4294967295 as32BitUnsignedValue println. + (1 << 60) as32BitUnsignedValue println. + ((1 << 60) - 1) as32BitUnsignedValue println. + (1 << 200) as32BitUnsignedValue println. + ((1 << 200) - 1) as32BitUnsignedValue println. + + 0 as32BitSignedValue println. + 1 as32BitSignedValue println. + -1 as32BitSignedValue println. + 4294967295 as32BitSignedValue println. + (1 << 60) as32BitSignedValue println. + ((1 << 60) - 1) as32BitSignedValue println. + (1 << 200) as32BitSignedValue println. + ((1 << 200) - 1) as32BitSignedValue println. + ) +) diff --git a/src/lib/vm/core.rs b/src/lib/vm/core.rs index 75ddbeec..9b3d60fd 100644 --- a/src/lib/vm/core.rs +++ b/src/lib/vm/core.rs @@ -636,8 +636,34 @@ impl VM { self.stack.push(v); SendReturn::Val } - Primitive::As32BitSignedValue => todo!(), - Primitive::As32BitUnsignedValue => todo!(), + Primitive::As32BitSignedValue => { + let i = if let Some(i) = rcv.as_isize(self) { + i as i32 as isize + } else { + rcv.downcast::(self) + .unwrap() + .bigint() + .to_u32_digits() + .1[0] as i32 as isize + }; + let v = Val::from_isize(self, i as isize); + self.stack.push(v); + SendReturn::Val + } + Primitive::As32BitUnsignedValue => { + let i = if let Some(i) = rcv.as_isize(self) { + i as u32 + } else { + rcv.downcast::(self) + .unwrap() + .bigint() + .to_u32_digits() + .1[0] as u32 + }; + let v = Val::from_isize(self, i as isize); + self.stack.push(v); + SendReturn::Val + } Primitive::At => { let rcv_tobj = stry!(rcv.tobj(self)); let arr = stry!(rcv_tobj.to_array());