Skip to content

Commit

Permalink
Implemented widening conversions on basic type comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
stanhebben committed Feb 23, 2024
1 parent 8645f2b commit a56e735
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public static CompileError ambiguousType(List<TypeID> candidates) {
return new CompileError(CompileExceptionCode.INFERENCE_AMBIGUOUS, "Type inference ambiguity, possible types: " + possibleTypes);
}

public static CompileError cannotCompare(TypeID a, TypeID b) {
return new CompileError(CompileExceptionCode.CANNOT_COMPARE, "Cannot compare " + a + " and " + b);
}

public static CompileError ambiguousComparison(TypeID a, TypeID b) {
return new CompileError(CompileExceptionCode.AMBIGUOUS_COMPARISON, "Ambiguous comparison, not sure to compare as " + a + " or " + b);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.openzen.zenscript.codemodel.OperatorType;
import org.openzen.zenscript.codemodel.compilation.CastedEval;
import org.openzen.zenscript.codemodel.compilation.CastedExpression;
import org.openzen.zenscript.codemodel.compilation.CompileErrors;
import org.openzen.zenscript.codemodel.expression.CompareExpression;
import org.openzen.zenscript.codemodel.expression.Expression;
import org.openzen.zenscript.codemodel.identifiers.MethodID;
Expand All @@ -14,6 +15,8 @@
import org.openzen.zenscript.codemodel.type.TypeID;
import org.openzen.zenscript.codemodel.type.member.MemberSet;

import java.util.Optional;

public class BasicTypeMembers {
private static final MemberSet NO_MEMBERS = new MemberSet();
private static final MethodID CONSTRUCTOR = MethodID.operator(OperatorType.CONSTRUCTOR);
Expand Down Expand Up @@ -549,7 +552,7 @@ private static MemberSet getString() {
private static void setup(MemberSet.Builder builder, BasicTypeID type) {
for (BuiltinMethodSymbol method : BuiltinMethodSymbol.values()) {
if (method.getDefiningType().equals(type) && method.getID().equals(COMPARE)) {
comparator(builder, method, method.getHeader().getParameterType(false, 0));
comparator(builder);
}/* else if (method.getID().equals(CONSTRUCTOR)) {
builder.constructor(new MethodInstance(method));
} else if (method.getDefiningType() == type) {
Expand Down Expand Up @@ -583,23 +586,46 @@ private static void setup(MemberSet.Builder builder, BasicTypeID type) {
}
}

private static void comparator(MemberSet.Builder builder, BuiltinMethodSymbol method, TypeID ofType) {
MethodInstance comparator = new MethodInstance(method);
private static void comparator(MemberSet.Builder builder) {
builder.comparator(((compiler, position, left, right, type) -> {
CastedExpression casted = right.cast(CastedEval.implicit(compiler, position, ofType));
if (casted.isFailed())
return casted;

Expression value = new CompareExpression(
position,
left,
casted.value,
comparator,
type);
return new CastedExpression(casted.level, value);
Expression rightCompiled = right.eval();
Optional<TypeID> union = compiler.union(left.type, rightCompiled.type);
return union.map(typeID -> {
CastedEval cast = new CastedEval(compiler, left.position, typeID, false, false);
Expression castedLeft = cast.of(left).value;
Expression castedRight = cast.of(rightCompiled).value;
Expression value = new CompareExpression(
position,
castedLeft,
castedRight,
new MethodInstance(getComparator((BasicTypeID) typeID)),
type);
return new CastedExpression(CastedExpression.Level.EXACT, value);
}).orElseGet(() -> {
return new CastedExpression(CastedExpression.Level.INVALID, compiler.at(position).invalid(CompileErrors.cannotCompare(left.type, rightCompiled.type)));
});
}));
}

private static BuiltinMethodSymbol getComparator(BasicTypeID type) {
switch (type) {
case BYTE: return BuiltinMethodSymbol.BYTE_COMPARE;
case SBYTE: return BuiltinMethodSymbol.SBYTE_COMPARE;
case SHORT: return BuiltinMethodSymbol.SHORT_COMPARE;
case USHORT: return BuiltinMethodSymbol.USHORT_COMPARE;
case INT: return BuiltinMethodSymbol.INT_COMPARE;
case UINT: return BuiltinMethodSymbol.UINT_COMPARE;
case LONG: return BuiltinMethodSymbol.LONG_COMPARE;
case ULONG: return BuiltinMethodSymbol.ULONG_COMPARE;
case USIZE: return BuiltinMethodSymbol.USIZE_COMPARE;
case FLOAT: return BuiltinMethodSymbol.FLOAT_COMPARE;
case DOUBLE: return BuiltinMethodSymbol.DOUBLE_COMPARE;
case CHAR: return BuiltinMethodSymbol.CHAR_COMPARE;
case STRING: return BuiltinMethodSymbol.STRING_COMPARE;
default: throw new IllegalArgumentException("No comparator for " + type);
}
}

private static MethodInstance[] getWideningMethodInstances(BuiltinMethodSymbol method) {
FunctionHeader original = method.getHeader();
if (original.parameters.length != 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,16 @@ public Compiling(

@Override
public Expression eval() {
Expression condition = this.condition.cast(cast(BasicTypeID.BOOL)).value;
CastedExpression condition = this.condition.cast(cast(BasicTypeID.BOOL));
if (condition.isFailed())
return condition.value;

Expression ifThen = this.ifThen.eval();
Expression ifElse = this.ifElse.eval();
return compiler.union(ifThen.type, ifElse.type)
.map(t -> {
CastedEval cast = cast(t);
return compiler.at(position).ternary(condition, cast.of(ifThen).value, cast.of(ifElse).value);
return compiler.at(position).ternary(condition.value, cast.of(ifThen).value, cast.of(ifElse).value);
})
.orElseGet(() -> compiler.at(position).invalid(CompileErrors.noIntersectionBetweenTypes(ifThen.type, ifElse.type)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
#output: true
#output: true
#output: true
#output: false

println("" + ((3 < 5) ? "true" : "false"));
println("" + ((3 < (5 as usize)) ? "true" : "false"));
println("" + ((3 < 5.0) ? "true" : "false"));
println("" + ((3 < 5.0f) ? "true" : "false"));
println("" + (3 < 0x40 ? "true" : "false"));
#output: true
#output: true

println("" + ((-5 < (3 as usize)) ? "true" : "false")); //What does this return?
println("" + ((3 < 5)));
println("" + ((3 < (5 as usize))));
println("" + ((3 < 5.0)));
println("" + ((3 < 5.0f)));
println("" + (3 < 0x40));
println("" + ((-5 < (3 as usize)))); // interpreted as int
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public enum CompileExceptionCode {
INVALID_ARRAY_TYPE,
INFERENCE_AMBIGUOUS,
AMBIGUOUS_COMPARISON,
CANNOT_COMPARE,
NOT_AN_EXPRESSION,
INCOMPLETE_HEADER,
INCOMPLETE_IMPLEMENTATION,
Expand Down

0 comments on commit a56e735

Please sign in to comment.