From 96ebcff317d75c1f7f6dce210e72d112c672a331 Mon Sep 17 00:00:00 2001 From: kindlich Date: Sun, 18 Oct 2026 11:16:24 +0000 Subject: [PATCH 1/3] Fix expected output of division-by-zero tests 2.0 / 0 is Infinity under IEEE 754, not NaN (only 0.0 / 0.0 is NaN). Co-Authored-By: Claude Opus 5.5 --- .../resources/zencode_tests/expressions/mod_type_inference_1.zc | 2 +- .../resources/zencode_tests/expressions/mod_type_inference_2.zc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ScriptingEngineTester/src/main/resources/zencode_tests/expressions/mod_type_inference_1.zc b/ScriptingEngineTester/src/main/resources/zencode_tests/expressions/mod_type_inference_1.zc index 7bee657e..a2706f0a 100644 --- a/ScriptingEngineTester/src/main/resources/zencode_tests/expressions/mod_type_inference_1.zc +++ b/ScriptingEngineTester/src/main/resources/zencode_tests/expressions/mod_type_inference_1.zc @@ -1,3 +1,3 @@ -#output: NaN +#output: Infinity println(2.0 / 0); \ No newline at end of file diff --git a/ScriptingEngineTester/src/main/resources/zencode_tests/expressions/mod_type_inference_2.zc b/ScriptingEngineTester/src/main/resources/zencode_tests/expressions/mod_type_inference_2.zc index 3897fc3c..71f5e85b 100644 --- a/ScriptingEngineTester/src/main/resources/zencode_tests/expressions/mod_type_inference_2.zc +++ b/ScriptingEngineTester/src/main/resources/zencode_tests/expressions/mod_type_inference_2.zc @@ -1,3 +1,3 @@ -#output: NaN +#output: Infinity println(2.0 / 0.0f); \ No newline at end of file From 466190fcc6dad9f6e4851765305d60076e568888 Mon Sep 17 00:00:00 2001 From: kindlich Date: Sun, 18 Oct 2026 11:18:27 +0000 Subject: [PATCH 2/3] Make gradlew executable Co-Authored-By: Claude Opus 5.5 --- gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 gradlew diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 From ca73b274bbabba7f55a8705f8ba880fa91f9d55b Mon Sep 17 00:00:00 2001 From: kindlich Date: Sun, 18 Oct 2026 11:36:01 +0000 Subject: [PATCH 3/3] Fix double / int literal ambiguity: prefer the literal's natural type Unsuffixed int literals were an EXACT match for every integer type they fit into, so e.g. 2.0 / 0 matched nine operator overloads equally. Now only int (or long, if the value doesn't fit) is EXACT; other types are INFERRED, mirroring the float/double handling from 148a61e4. Co-Authored-By: Claude Opus 5.5 --- .../expression/ParsedExpressionInt.java | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionInt.java b/Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionInt.java index ab279a78..e1bc6f40 100644 --- a/Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionInt.java +++ b/Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionInt.java @@ -166,35 +166,42 @@ private CastedExpression asInt(CastedEval cast, BasicTypeID type) { long signed = negative ? -value : value; switch (type) { case SBYTE: - return castIfFits(cast, signed >= Byte.MIN_VALUE && signed <= Byte.MAX_VALUE, (position, value) -> new ConstantSByteExpression(position, value.byteValue())); + return castIfFits(cast, type, signed >= Byte.MIN_VALUE && signed <= Byte.MAX_VALUE, (position, value) -> new ConstantSByteExpression(position, value.byteValue())); case BYTE: - return castIfFits(cast, !negative && value <= 0xFF, (position, value) -> new ConstantByteExpression(position, value.intValue())); + return castIfFits(cast, type, !negative && value <= 0xFF, (position, value) -> new ConstantByteExpression(position, value.intValue())); case SHORT: - return castIfFits(cast, signed >= Short.MIN_VALUE && signed <= Short.MAX_VALUE, (position, value) -> new ConstantShortExpression(position, value.shortValue())); + return castIfFits(cast, type, signed >= Short.MIN_VALUE && signed <= Short.MAX_VALUE, (position, value) -> new ConstantShortExpression(position, value.shortValue())); case USHORT: - return castIfFits(cast, !negative && value <= 0xFFFF, (position, value) -> new ConstantUShortExpression(position, value.intValue())); + return castIfFits(cast, type, !negative && value <= 0xFFFF, (position, value) -> new ConstantUShortExpression(position, value.intValue())); case INT: - return castIfFits(cast, signed >= Integer.MIN_VALUE && signed <= Integer.MAX_VALUE, (position, value) -> new ConstantIntExpression(position, value.intValue())); + return castIfFits(cast, type, signed >= Integer.MIN_VALUE && signed <= Integer.MAX_VALUE, (position, value) -> new ConstantIntExpression(position, value.intValue())); case UINT: - return castIfFits(cast, !negative && value <= 0xFFFFFFFFL, (position, value) -> new ConstantUIntExpression(position, value.intValue())); + return castIfFits(cast, type, !negative && value <= 0xFFFFFFFFL, (position, value) -> new ConstantUIntExpression(position, value.intValue())); case USIZE: - return castIfFits(cast, !negative && value <= 0xFFFFFFFFL, ConstantUSizeExpression::new); + return castIfFits(cast, type, !negative && value <= 0xFFFFFFFFL, ConstantUSizeExpression::new); case LONG: - return cast.of(new ConstantLongExpression(position, value)); + return cast.of(levelFor(type), new ConstantLongExpression(position, value)); case ULONG: - return castIfFits(cast, !negative, ConstantULongExpression::new); + return castIfFits(cast, type, !negative, ConstantULongExpression::new); case FLOAT: - return cast.of(new ConstantFloatExpression(position, value)); + return cast.of(levelFor(type), new ConstantFloatExpression(position, value)); case DOUBLE: - return cast.of(new ConstantDoubleExpression(position, value)); + return cast.of(levelFor(type), new ConstantDoubleExpression(position, value)); } return cast.of(eval()); } - private CastedExpression castIfFits(CastedEval cast, boolean fits, BiFunction expr){ + // Only the literal's natural type (int, or long if it doesn't fit) is an exact match; + // any other numeric type it fits into is inferred, so that e.g. 2.0 / 0 prefers the int overload + private CastedExpression.Level levelFor(BasicTypeID type) { + BasicTypeID natural = value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE ? BasicTypeID.INT : BasicTypeID.LONG; + return type == natural ? CastedExpression.Level.EXACT : CastedExpression.Level.INFERRED; + } + + private CastedExpression castIfFits(CastedEval cast, BasicTypeID type, boolean fits, BiFunction expr){ if (fits) { - return cast.of(CastedExpression.Level.EXACT, expr.apply(this.position, this.value)); + return cast.of(levelFor(type), expr.apply(this.position, this.value)); } else if (cast.isExplicit()) { return cast.of(CastedExpression.Level.EXPLICIT, expr.apply(this.position, this.value)); }