Skip to content

Commit a56e735

Browse files
committed
Implemented widening conversions on basic type comparison
1 parent 8645f2b commit a56e735

5 files changed

Lines changed: 58 additions & 24 deletions

File tree

CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/CompileErrors.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ public static CompileError ambiguousType(List<TypeID> candidates) {
2424
return new CompileError(CompileExceptionCode.INFERENCE_AMBIGUOUS, "Type inference ambiguity, possible types: " + possibleTypes);
2525
}
2626

27+
public static CompileError cannotCompare(TypeID a, TypeID b) {
28+
return new CompileError(CompileExceptionCode.CANNOT_COMPARE, "Cannot compare " + a + " and " + b);
29+
}
30+
2731
public static CompileError ambiguousComparison(TypeID a, TypeID b) {
2832
return new CompileError(CompileExceptionCode.AMBIGUOUS_COMPARISON, "Ambiguous comparison, not sure to compare as " + a + " or " + b);
2933
}

CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/builtin/BasicTypeMembers.java

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.openzen.zenscript.codemodel.OperatorType;
66
import org.openzen.zenscript.codemodel.compilation.CastedEval;
77
import org.openzen.zenscript.codemodel.compilation.CastedExpression;
8+
import org.openzen.zenscript.codemodel.compilation.CompileErrors;
89
import org.openzen.zenscript.codemodel.expression.CompareExpression;
910
import org.openzen.zenscript.codemodel.expression.Expression;
1011
import org.openzen.zenscript.codemodel.identifiers.MethodID;
@@ -14,6 +15,8 @@
1415
import org.openzen.zenscript.codemodel.type.TypeID;
1516
import org.openzen.zenscript.codemodel.type.member.MemberSet;
1617

18+
import java.util.Optional;
19+
1720
public class BasicTypeMembers {
1821
private static final MemberSet NO_MEMBERS = new MemberSet();
1922
private static final MethodID CONSTRUCTOR = MethodID.operator(OperatorType.CONSTRUCTOR);
@@ -549,7 +552,7 @@ private static MemberSet getString() {
549552
private static void setup(MemberSet.Builder builder, BasicTypeID type) {
550553
for (BuiltinMethodSymbol method : BuiltinMethodSymbol.values()) {
551554
if (method.getDefiningType().equals(type) && method.getID().equals(COMPARE)) {
552-
comparator(builder, method, method.getHeader().getParameterType(false, 0));
555+
comparator(builder);
553556
}/* else if (method.getID().equals(CONSTRUCTOR)) {
554557
builder.constructor(new MethodInstance(method));
555558
} else if (method.getDefiningType() == type) {
@@ -583,23 +586,46 @@ private static void setup(MemberSet.Builder builder, BasicTypeID type) {
583586
}
584587
}
585588

586-
private static void comparator(MemberSet.Builder builder, BuiltinMethodSymbol method, TypeID ofType) {
587-
MethodInstance comparator = new MethodInstance(method);
589+
private static void comparator(MemberSet.Builder builder) {
588590
builder.comparator(((compiler, position, left, right, type) -> {
589-
CastedExpression casted = right.cast(CastedEval.implicit(compiler, position, ofType));
590-
if (casted.isFailed())
591-
return casted;
592-
593-
Expression value = new CompareExpression(
594-
position,
595-
left,
596-
casted.value,
597-
comparator,
598-
type);
599-
return new CastedExpression(casted.level, value);
591+
Expression rightCompiled = right.eval();
592+
Optional<TypeID> union = compiler.union(left.type, rightCompiled.type);
593+
return union.map(typeID -> {
594+
CastedEval cast = new CastedEval(compiler, left.position, typeID, false, false);
595+
Expression castedLeft = cast.of(left).value;
596+
Expression castedRight = cast.of(rightCompiled).value;
597+
Expression value = new CompareExpression(
598+
position,
599+
castedLeft,
600+
castedRight,
601+
new MethodInstance(getComparator((BasicTypeID) typeID)),
602+
type);
603+
return new CastedExpression(CastedExpression.Level.EXACT, value);
604+
}).orElseGet(() -> {
605+
return new CastedExpression(CastedExpression.Level.INVALID, compiler.at(position).invalid(CompileErrors.cannotCompare(left.type, rightCompiled.type)));
606+
});
600607
}));
601608
}
602609

610+
private static BuiltinMethodSymbol getComparator(BasicTypeID type) {
611+
switch (type) {
612+
case BYTE: return BuiltinMethodSymbol.BYTE_COMPARE;
613+
case SBYTE: return BuiltinMethodSymbol.SBYTE_COMPARE;
614+
case SHORT: return BuiltinMethodSymbol.SHORT_COMPARE;
615+
case USHORT: return BuiltinMethodSymbol.USHORT_COMPARE;
616+
case INT: return BuiltinMethodSymbol.INT_COMPARE;
617+
case UINT: return BuiltinMethodSymbol.UINT_COMPARE;
618+
case LONG: return BuiltinMethodSymbol.LONG_COMPARE;
619+
case ULONG: return BuiltinMethodSymbol.ULONG_COMPARE;
620+
case USIZE: return BuiltinMethodSymbol.USIZE_COMPARE;
621+
case FLOAT: return BuiltinMethodSymbol.FLOAT_COMPARE;
622+
case DOUBLE: return BuiltinMethodSymbol.DOUBLE_COMPARE;
623+
case CHAR: return BuiltinMethodSymbol.CHAR_COMPARE;
624+
case STRING: return BuiltinMethodSymbol.STRING_COMPARE;
625+
default: throw new IllegalArgumentException("No comparator for " + type);
626+
}
627+
}
628+
603629
private static MethodInstance[] getWideningMethodInstances(BuiltinMethodSymbol method) {
604630
FunctionHeader original = method.getHeader();
605631
if (original.parameters.length != 1)

Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionConditional.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,16 @@ public Compiling(
4949

5050
@Override
5151
public Expression eval() {
52-
Expression condition = this.condition.cast(cast(BasicTypeID.BOOL)).value;
52+
CastedExpression condition = this.condition.cast(cast(BasicTypeID.BOOL));
53+
if (condition.isFailed())
54+
return condition.value;
55+
5356
Expression ifThen = this.ifThen.eval();
5457
Expression ifElse = this.ifElse.eval();
5558
return compiler.union(ifThen.type, ifElse.type)
5659
.map(t -> {
5760
CastedEval cast = cast(t);
58-
return compiler.at(position).ternary(condition, cast.of(ifThen).value, cast.of(ifElse).value);
61+
return compiler.at(position).ternary(condition.value, cast.of(ifThen).value, cast.of(ifElse).value);
5962
})
6063
.orElseGet(() -> compiler.at(position).invalid(CompileErrors.noIntersectionBetweenTypes(ifThen.type, ifElse.type)));
6164
}

ScriptingEngineTester/src/main/resources/zencode-tests/operators/compare-1.zc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
#output: true
33
#output: true
44
#output: true
5-
#output: false
6-
7-
println("" + ((3 < 5) ? "true" : "false"));
8-
println("" + ((3 < (5 as usize)) ? "true" : "false"));
9-
println("" + ((3 < 5.0) ? "true" : "false"));
10-
println("" + ((3 < 5.0f) ? "true" : "false"));
11-
println("" + (3 < 0x40 ? "true" : "false"));
5+
#output: true
6+
#output: true
127

13-
println("" + ((-5 < (3 as usize)) ? "true" : "false")); //What does this return?
8+
println("" + ((3 < 5)));
9+
println("" + ((3 < (5 as usize))));
10+
println("" + ((3 < 5.0)));
11+
println("" + ((3 < 5.0f)));
12+
println("" + (3 < 0x40));
13+
println("" + ((-5 < (3 as usize)))); // interpreted as int

Shared/src/main/java/org/openzen/zencode/shared/CompileExceptionCode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public enum CompileExceptionCode {
7575
INVALID_ARRAY_TYPE,
7676
INFERENCE_AMBIGUOUS,
7777
AMBIGUOUS_COMPARISON,
78+
CANNOT_COMPARE,
7879
NOT_AN_EXPRESSION,
7980
INCOMPLETE_HEADER,
8081
INCOMPLETE_IMPLEMENTATION,

0 commit comments

Comments
 (0)