From 73e08209d065bfdf8489fda4166ea66cba7c7667 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Sat, 17 Oct 2026 01:07:08 +0200 Subject: [PATCH 1/7] Make sure Class>>#fields returns a copy Signed-off-by: Stefan Marr --- integration-tests.yml | 4 ---- src/som/primitives/ClassPrimitives.java | 2 +- src/som/vmobjects/SArray.java | 6 ++++++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/integration-tests.yml b/integration-tests.yml index 717ce12..25c1d0c 100644 --- a/integration-tests.yml +++ b/integration-tests.yml @@ -116,10 +116,6 @@ failing_as_unspecified: - Tests/test_literals_limit_2.som - Tests/unknown_field_write.som - # This should be specified so that the "set" of fields cannot be changed reflectively - # they obtained array can be changed, but it is expected to have no effect. - - Tests/mutate_fields.som - unsupported: [] diff --git a/src/som/primitives/ClassPrimitives.java b/src/som/primitives/ClassPrimitives.java index 1879d6b..5e32d43 100644 --- a/src/som/primitives/ClassPrimitives.java +++ b/src/som/primitives/ClassPrimitives.java @@ -71,7 +71,7 @@ public void invoke(final Frame frame, final Interpreter interpreter) { @Override public void invoke(final Frame frame, final Interpreter interpreter) { SClass self = (SClass) frame.pop(); - frame.push(self.getInstanceFields()); + frame.push(self.getInstanceFields().copy(universe)); } }); diff --git a/src/som/vmobjects/SArray.java b/src/som/vmobjects/SArray.java index bf836c7..92a7e6f 100644 --- a/src/som/vmobjects/SArray.java +++ b/src/som/vmobjects/SArray.java @@ -64,6 +64,12 @@ public SArray copyAndExtendWith(SAbstractObject value, final Universe universe) return result; } + public SArray copy(final Universe universe) { + SArray result = universe.newArray(getNumberOfIndexableFields()); + copyIndexableFieldsTo(result); + return result; + } + protected void copyIndexableFieldsTo(SArray destination) { // Copy all indexable fields from this array to the destination array for (int i = 0; i < getNumberOfIndexableFields(); i++) { From d9abd77dea6991b9adac082471bd564c7fd28751 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Sun, 18 Oct 2026 22:37:11 +0200 Subject: [PATCH 2/7] Fix rounding semantics Signed-off-by: Stefan Marr --- integration-tests.yml | 10 ---------- src/som/primitives/DoublePrimitives.java | 3 +-- src/som/vmobjects/SBigInteger.java | 4 ++++ src/som/vmobjects/SDouble.java | 14 +++++++------- src/som/vmobjects/SNumber.java | 7 +++++++ 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/integration-tests.yml b/integration-tests.yml index 25c1d0c..acb1e00 100644 --- a/integration-tests.yml +++ b/integration-tests.yml @@ -21,7 +21,6 @@ failing_as_unspecified: # I think IEEE allows for infinities here, and we probably want that - Tests/double3.som - - Tests/double4.som - Tests/double5.som - Tests/double6.som - Tests/double7.som @@ -30,16 +29,11 @@ failing_as_unspecified: - Tests/double11.som - Tests/double13.som - # Java seems to do some rounding in the transition, but it's also requiring bigints - - Tests/double_asinteger.som - - - Tests/double_double_div_err.som - Tests/double_double_div_zero_err1.som - Tests/double_double_div_zero_err2.som - Tests/double_double_div_zero_err3.som - Tests/double_double_div_zero_err4.som - - Tests/double_modulus.som - Tests/double_modulus_err.som - Tests/exit_double.som @@ -49,8 +43,6 @@ failing_as_unspecified: - Tests/fromstring_double_err.som - Tests/fromstring_err.som - - Tests/hashcode2.som - - Tests/inst_var_at_bad_idx.som - Tests/inst_var_at_put_bad_idx.som @@ -83,7 +75,6 @@ failing_as_unspecified: - Tests/int_double_div_err.som - Tests/int_double_div_zero_err.som - - Tests/int_modulus.som - Tests/int_modulus_err.som - Tests/load_string.som @@ -102,7 +93,6 @@ failing_as_unspecified: - Tests/remainder_zero.som - Tests/round.som - - Tests/shift_right.som - Tests/shift_right_too_big.som - Tests/shift_right_type_err.som diff --git a/src/som/primitives/DoublePrimitives.java b/src/som/primitives/DoublePrimitives.java index 2898e01..57baafb 100644 --- a/src/som/primitives/DoublePrimitives.java +++ b/src/som/primitives/DoublePrimitives.java @@ -133,8 +133,7 @@ public void invoke(final Frame frame, final Interpreter interpreter) { @Override public void invoke(final Frame frame, final Interpreter interpreter) { SDouble rcvr = (SDouble) frame.pop(); - long result = Math.round(rcvr.getEmbeddedDouble()); - frame.push(universe.newInteger(result)); + frame.push(rcvr.primRound(universe)); } }); diff --git a/src/som/vmobjects/SBigInteger.java b/src/som/vmobjects/SBigInteger.java index 423b8ca..521596a 100644 --- a/src/som/vmobjects/SBigInteger.java +++ b/src/som/vmobjects/SBigInteger.java @@ -133,6 +133,10 @@ public SNumber primDoubleDivide(final SNumber right, final Universe universe) { @Override public SNumber primIntegerDivide(final SNumber right, final Universe universe) { + if (right instanceof SDouble d) { + return fitIntoInteger( + embeddedBiginteger.doubleValue() / d.getEmbeddedDouble(), universe); + } BigInteger r = asBigInteger(right); BigInteger result = embeddedBiginteger.divide(r); return asSNumber(result, universe); diff --git a/src/som/vmobjects/SDouble.java b/src/som/vmobjects/SDouble.java index aec9044..a812e3e 100644 --- a/src/som/vmobjects/SDouble.java +++ b/src/som/vmobjects/SDouble.java @@ -26,9 +26,6 @@ import som.vm.Universe; -import java.math.BigDecimal; -import java.math.BigInteger; - public final class SDouble extends SNumber { @@ -77,11 +74,14 @@ public SDouble primAsDouble(final Universe universe) { } public SNumber primAsInteger(final Universe universe) { - if (embeddedDouble > Long.MAX_VALUE || embeddedDouble < Long.MIN_VALUE) { - BigInteger bigInteger = BigDecimal.valueOf(embeddedDouble).toBigInteger(); - return universe.newBigInteger(bigInteger); + return fitIntoInteger(embeddedDouble, universe); + } + + public SNumber primRound(final Universe universe) { + if (embeddedDouble >= Long.MAX_VALUE || embeddedDouble < Long.MIN_VALUE) { + return fitIntoInteger(embeddedDouble, universe); } - return universe.newInteger((long) embeddedDouble); + return universe.newInteger(Math.round(embeddedDouble)); } @Override diff --git a/src/som/vmobjects/SNumber.java b/src/som/vmobjects/SNumber.java index ee8084e..81eaf64 100644 --- a/src/som/vmobjects/SNumber.java +++ b/src/som/vmobjects/SNumber.java @@ -43,6 +43,13 @@ protected final SNumber intOrBigInt(final double value, final Universe universe) } } + protected static SNumber fitIntoInteger(final double value, final Universe universe) { + if (value >= Long.MAX_VALUE || value < Long.MIN_VALUE) { + return universe.newBigInteger(new BigDecimal(value).toBigInteger()); + } + return universe.newInteger((long) value); + } + protected final SObject asSBoolean(final boolean result, final Universe universe) { if (result) { return universe.trueObject; From f7ffe2eb000ddddc3f3f486e80edcd3c6c3056ef Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Sun, 18 Oct 2026 22:37:55 +0200 Subject: [PATCH 3/7] Remove round.som from integration-tests.yml Signed-off-by: Stefan Marr --- integration-tests.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/integration-tests.yml b/integration-tests.yml index acb1e00..3f33095 100644 --- a/integration-tests.yml +++ b/integration-tests.yml @@ -91,7 +91,6 @@ failing_as_unspecified: - Tests/perform_witharguments_wrong.som - Tests/remainder_zero.som - - Tests/round.som - Tests/shift_right_too_big.som - Tests/shift_right_type_err.som From 507f93d525c476c30b34fc9628f8c54c5dcc173f Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Thu, 22 Oct 2026 21:25:45 +0200 Subject: [PATCH 4/7] Add primShiftRight for SBigInteger Signed-off-by: Stefan Marr --- src/som/primitives/IntegerPrimitives.java | 5 ++--- src/som/vmobjects/SBigInteger.java | 6 ++++++ src/som/vmobjects/SDouble.java | 5 +++++ src/som/vmobjects/SInteger.java | 6 ++++++ src/som/vmobjects/SNumber.java | 3 +++ 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/som/primitives/IntegerPrimitives.java b/src/som/primitives/IntegerPrimitives.java index be37d1b..9fca1ca 100644 --- a/src/som/primitives/IntegerPrimitives.java +++ b/src/som/primitives/IntegerPrimitives.java @@ -219,9 +219,8 @@ public void invoke(final Frame frame, final Interpreter interpreter) { @Override public void invoke(final Frame frame, final Interpreter interpreter) { SInteger right = (SInteger) frame.pop(); - SInteger rcvr = (SInteger) frame.pop(); - frame.push( - universe.newInteger(rcvr.getEmbeddedInteger() >>> right.getEmbeddedInteger())); + SNumber rcvr = (SNumber) frame.pop(); + frame.push(rcvr.primShiftRight(right, universe)); } }); diff --git a/src/som/vmobjects/SBigInteger.java b/src/som/vmobjects/SBigInteger.java index 521596a..489936c 100644 --- a/src/som/vmobjects/SBigInteger.java +++ b/src/som/vmobjects/SBigInteger.java @@ -198,6 +198,12 @@ public SNumber primLeftShift(final SNumber right, final Universe universe) { return universe.newBigInteger(embeddedBiginteger.shiftLeft(r.intValue())); } + @Override + public SNumber primShiftRight(final SInteger right, final Universe universe) { + return asSNumber(embeddedBiginteger.shiftRight((int) right.getEmbeddedInteger()), + universe); + } + @Override public SNumber primBitXor(final SNumber right, final Universe universe) { BigInteger r = asBigInteger(right); diff --git a/src/som/vmobjects/SDouble.java b/src/som/vmobjects/SDouble.java index a812e3e..6e4fdcf 100644 --- a/src/som/vmobjects/SDouble.java +++ b/src/som/vmobjects/SDouble.java @@ -139,6 +139,11 @@ public SNumber primLeftShift(final SNumber right, final Universe universe) { throw new RuntimeException("Not supported for doubles"); } + @Override + public SNumber primShiftRight(final SInteger right, final Universe universe) { + throw new RuntimeException("Not supported for doubles"); + } + @Override public SObject primEqual(final SAbstractObject right, final Universe universe) { if (!(right instanceof SNumber)) { diff --git a/src/som/vmobjects/SInteger.java b/src/som/vmobjects/SInteger.java index 60826b0..3756320 100644 --- a/src/som/vmobjects/SInteger.java +++ b/src/som/vmobjects/SInteger.java @@ -264,6 +264,12 @@ public SNumber primLeftShift(final SNumber right, final Universe universe) { return universe.newInteger(result); } + @Override + public SNumber primShiftRight(final SInteger right, final Universe universe) { + return universe.newInteger( + embeddedInteger >>> right.getEmbeddedInteger()); + } + @Override public SObject primEqual(final SAbstractObject right, final Universe universe) { boolean result; diff --git a/src/som/vmobjects/SNumber.java b/src/som/vmobjects/SNumber.java index 81eaf64..e860825 100644 --- a/src/som/vmobjects/SNumber.java +++ b/src/som/vmobjects/SNumber.java @@ -1,6 +1,7 @@ package som.vmobjects; import java.math.BigDecimal; +import java.math.BigInteger; import som.vm.Universe; @@ -30,6 +31,8 @@ public abstract class SNumber extends SAbstractObject { public abstract SNumber primLeftShift(SNumber right, Universe universe); + public abstract SNumber primShiftRight(SInteger right, Universe universe); + public abstract SObject primEqual(SAbstractObject right, Universe universe); public abstract SObject primLessThan(SNumber right, Universe universe); From 120b9a6d0726bdeae92b2e844c1c210c09c9f15f Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Thu, 22 Oct 2026 21:41:40 +0200 Subject: [PATCH 5/7] Fix modulo implementation Signed-off-by: Stefan Marr --- src/som/vmobjects/SBigInteger.java | 13 ++++--------- src/som/vmobjects/SInteger.java | 8 ++------ src/som/vmobjects/SNumber.java | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/som/vmobjects/SBigInteger.java b/src/som/vmobjects/SBigInteger.java index 489936c..b0ec5f4 100644 --- a/src/som/vmobjects/SBigInteger.java +++ b/src/som/vmobjects/SBigInteger.java @@ -64,14 +64,6 @@ public SNumber primAsDouble(final Universe universe) { return universe.newDouble(embeddedBiginteger.doubleValue()); } - private SNumber asSNumber(final BigInteger result, final Universe universe) { - if (result.bitLength() >= Long.SIZE) { - return universe.newBigInteger(result); - } else { - return universe.newInteger(result.longValue()); - } - } - private BigInteger asBigInteger(final SNumber right) { BigInteger r; if (right instanceof SInteger r1) { @@ -144,8 +136,11 @@ public SNumber primIntegerDivide(final SNumber right, final Universe universe) { @Override public SNumber primModulo(final SNumber right, final Universe universe) { + if (right instanceof SDouble d) { + return universe.newDouble(embeddedBiginteger.doubleValue() % d.getEmbeddedDouble()); + } BigInteger r = asBigInteger(right); - BigInteger result = embeddedBiginteger.mod(r); + BigInteger result = floorMod(embeddedBiginteger, r); return asSNumber(result, universe); } diff --git a/src/som/vmobjects/SInteger.java b/src/som/vmobjects/SInteger.java index 3756320..b4bb69e 100644 --- a/src/som/vmobjects/SInteger.java +++ b/src/som/vmobjects/SInteger.java @@ -196,13 +196,9 @@ public SNumber primIntegerDivide(final SNumber right, final Universe universe) { @Override public SNumber primModulo(final SNumber right, final Universe universe) { if (right instanceof SBigInteger) { - // Note: modulo semantics of SOM differ from Java, with respect to - // negative operands, but BigInteger doesn't support a negative - // second operand, so, we should get an exception, which we can - // properly handle once an application actually needs it. - BigInteger result = BigInteger.valueOf(embeddedInteger).mod( + BigInteger result = floorMod(BigInteger.valueOf(embeddedInteger), ((SBigInteger) right).getEmbeddedBiginteger()); - return universe.newBigInteger(result); + return asSNumber(result, universe); } else if (right instanceof SDouble) { double result = embeddedInteger % ((SDouble) right).getEmbeddedDouble(); return universe.newDouble(result); diff --git a/src/som/vmobjects/SNumber.java b/src/som/vmobjects/SNumber.java index e860825..6b6f397 100644 --- a/src/som/vmobjects/SNumber.java +++ b/src/som/vmobjects/SNumber.java @@ -53,6 +53,22 @@ protected static SNumber fitIntoInteger(final double value, final Universe unive return universe.newInteger((long) value); } + public static SNumber asSNumber(final BigInteger result, final Universe universe) { + if (result.bitLength() >= Long.SIZE) { + return universe.newBigInteger(result); + } else { + return universe.newInteger(result.longValue()); + } + } + + protected static BigInteger floorMod(final BigInteger left, final BigInteger right) { + BigInteger result = left.remainder(right); + if (result.signum() != 0 && result.signum() != right.signum()) { + result = result.add(right); + } + return result; + } + protected final SObject asSBoolean(final boolean result, final Universe universe) { if (result) { return universe.trueObject; From c96cc218e7d657bbeeda2cf115f01cf27cc59fd7 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Thu, 22 Oct 2026 21:56:27 +0200 Subject: [PATCH 6/7] Add hashcode to SDouble Signed-off-by: Stefan Marr --- src/som/vmobjects/SDouble.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/som/vmobjects/SDouble.java b/src/som/vmobjects/SDouble.java index 6e4fdcf..b652512 100644 --- a/src/som/vmobjects/SDouble.java +++ b/src/som/vmobjects/SDouble.java @@ -40,6 +40,17 @@ public double getEmbeddedDouble() { return embeddedDouble; } + @Override + public int hashCode() { + return Double.hashCode(embeddedDouble); + } + + @Override + public boolean equals(final Object o) { + return o instanceof SDouble d + && Double.compare(embeddedDouble, d.embeddedDouble) == 0; + } + @Override public String toString() { return super.toString() + "(" + embeddedDouble + ")"; From 063f2bd443d2dbbd67488bc9fdeeb9349426b04a Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Thu, 22 Oct 2026 21:58:29 +0200 Subject: [PATCH 7/7] Update core-lib and adapt to tests of version 4 Signed-off-by: Stefan Marr --- core-lib | 2 +- integration-tests.yml | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/core-lib b/core-lib index c67b309..12ddd9b 160000 --- a/core-lib +++ b/core-lib @@ -1 +1 @@ -Subproject commit c67b309fdb6c41ec0c31a414f86dd3cb53cabb32 +Subproject commit 12ddd9b8544de968c0d437c9dbdbe2f589872c4a diff --git a/integration-tests.yml b/integration-tests.yml index 3f33095..db581d8 100644 --- a/integration-tests.yml +++ b/integration-tests.yml @@ -1,5 +1,6 @@ known_failures: [] +version: 4 failing_as_unspecified: - Tests/arbint_double_div_err.som @@ -9,6 +10,7 @@ failing_as_unspecified: - Tests/array_at_idx2_err.som - Tests/array_at_idx_err.som - Tests/array_at_negative_idx_err.som + - Tests/array_at_put_idx_err.som - Tests/array_at_put_idx0_err.som - Tests/array_at_put_idx2_err.som - Tests/call2.som @@ -105,6 +107,13 @@ failing_as_unspecified: - Tests/test_literals_limit_2.som - Tests/unknown_field_write.som + - Tests/parse_errors/duplicate_name_arg.som + - Tests/parse_errors/duplicate_name_arg_local.som + - Tests/parse_errors/duplicate_name_local.som + - Tests/parse_errors/duplicate_name_method.som + - Tests/parse_errors/instance_fields_overlap2.som + - Tests/unknown_field_write2.som + unsupported: []