diff --git a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/CompileErrors.java b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/CompileErrors.java index 9be71d644..0271d223d 100644 --- a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/CompileErrors.java +++ b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/CompileErrors.java @@ -24,6 +24,10 @@ public static CompileError ambiguousType(List candidates) { return new CompileError(CompileExceptionCode.INFERENCE_AMBIGUOUS, "Type inference ambiguity, possible types: " + possibleTypes); } + public static CompileError ambiguousComparison(TypeID a, TypeID b) { + return new CompileError(CompileExceptionCode.AMBIGUOUS_COMPARISON, "Ambiguous comparison, not sure to compare as " + a + " or " + b); + } + public static CompileError noMemberInType(TypeID type, String name) { return new CompileError(CompileExceptionCode.NO_SUCH_MEMBER, "No member " + name + " in type " + type); } diff --git a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/ResolvedType.java b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/ResolvedType.java index 1fab00ebc..526d1b242 100644 --- a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/ResolvedType.java +++ b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/ResolvedType.java @@ -10,6 +10,7 @@ import org.openzen.zenscript.codemodel.identifiers.instances.IteratorInstance; import org.openzen.zenscript.codemodel.type.TypeID; +import java.util.List; import java.util.Optional; public interface ResolvedType { @@ -66,7 +67,7 @@ default boolean canCastImplicitlyTo(TypeID target) { Optional findSwitchMember(String name); - Optional compare(TypeID typeId); + List comparators(); Optional findIterator(int variables); @@ -100,7 +101,7 @@ interface StaticField { @FunctionalInterface interface Comparator { - Expression compare( + CastedExpression compare( ExpressionCompiler compiler, CodePosition position, Expression left, diff --git a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/builtin/BasicTypeMembers.java b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/builtin/BasicTypeMembers.java index 636225ded..668e24cc6 100644 --- a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/builtin/BasicTypeMembers.java +++ b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/builtin/BasicTypeMembers.java @@ -4,7 +4,9 @@ import org.openzen.zenscript.codemodel.FunctionParameter; 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.expression.CompareExpression; +import org.openzen.zenscript.codemodel.expression.Expression; import org.openzen.zenscript.codemodel.identifiers.MethodID; import org.openzen.zenscript.codemodel.identifiers.instances.FieldInstance; import org.openzen.zenscript.codemodel.identifiers.instances.MethodInstance; @@ -583,12 +585,19 @@ 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); - builder.comparator(ofType, ((compiler, position, left, right, type) -> new CompareExpression( - position, - left, - right.cast(CastedEval.implicit(compiler, position, ofType)).value, - comparator, - type))); + 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); + })); } private static MethodInstance[] getWideningMethodInstances(BuiltinMethodSymbol method) { diff --git a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/builtin/BuiltinMethodSymbol.java b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/builtin/BuiltinMethodSymbol.java index 455fe3143..8b5c07ee2 100644 --- a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/builtin/BuiltinMethodSymbol.java +++ b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/builtin/BuiltinMethodSymbol.java @@ -21,10 +21,10 @@ import static org.openzen.zenscript.codemodel.type.BasicTypeID.*; public enum BuiltinMethodSymbol implements MethodSymbol { - BOOL_NOT(BOOL, NOT, BOOL, BOOL), - BOOL_AND(BOOL, AND, BOOL, BOOL, BOOL), - BOOL_OR(BOOL, OR, BOOL, BOOL, BOOL), - BOOL_XOR(BOOL, XOR, BOOL, BOOL, BOOL), + BOOL_NOT(BOOL, NOT, BOOL), + BOOL_AND(BOOL, AND, false, BOOL, BOOL), + BOOL_OR(BOOL, OR, false, BOOL, BOOL), + BOOL_XOR(BOOL, XOR, false, BOOL, BOOL), BOOL_ADD_STRING(BOOL, ADD, false, STRING, STRING), BOOL_CAT_STRING(BOOL, CAT, STRING, STRING), BOOL_EQUALS(BOOL, EQUALS, BOOL, BOOL, BOOL), diff --git a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/ExpandedResolvedType.java b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/ExpandedResolvedType.java index debf30321..9548f144d 100644 --- a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/ExpandedResolvedType.java +++ b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/ExpandedResolvedType.java @@ -182,8 +182,8 @@ public Optional findSwitchMember(String name) { } @Override - public Optional compare(TypeID typeId) { - return base.compare(typeId); + public List comparators() { + return base.comparators(); } @Override diff --git a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/MemberSet.java b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/MemberSet.java index 1d5b05553..fe45a4f35 100644 --- a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/MemberSet.java +++ b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/MemberSet.java @@ -26,7 +26,7 @@ public static Builder create() { private final Map switchMembers = new HashMap<>(); private final Map innerTypes = new HashMap<>(); private final List iterators = new ArrayList<>(); - private final Map comparators = new HashMap<>(); + private final List comparators = new ArrayList<>(); @Override public StaticCallable getConstructor() { @@ -125,8 +125,8 @@ public Optional findSwitchMember(String name) { } @Override - public Optional compare(TypeID typeId) { - return Optional.ofNullable(comparators.get(typeId)); + public List comparators() { + return comparators; } @Override @@ -200,8 +200,8 @@ public Builder inner(TypeSymbol type) { return this; } - public Builder comparator(TypeID typeId, Comparator comparator) { - target.comparators.put(typeId, comparator); + public Builder comparator(Comparator comparator) { + target.comparators.add(comparator); return this; } diff --git a/JavaIntegration/src/main/java/org/openzen/zencode/java/module/JavaNativeTypeMembers.java b/JavaIntegration/src/main/java/org/openzen/zencode/java/module/JavaNativeTypeMembers.java index 2a478e161..3eec48800 100644 --- a/JavaIntegration/src/main/java/org/openzen/zencode/java/module/JavaNativeTypeMembers.java +++ b/JavaIntegration/src/main/java/org/openzen/zencode/java/module/JavaNativeTypeMembers.java @@ -10,6 +10,7 @@ import org.openzen.zenscript.codemodel.identifiers.instances.IteratorInstance; import org.openzen.zenscript.codemodel.type.TypeID; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -117,8 +118,8 @@ public Optional findSwitchMember(String name) { } @Override - public Optional compare(TypeID typeId) { - return Optional.empty(); + public List comparators() { + return Collections.emptyList(); } @Override diff --git a/Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionCompare.java b/Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionCompare.java index 5f84b579b..63e671ece 100644 --- a/Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionCompare.java +++ b/Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionCompare.java @@ -1,5 +1,6 @@ package org.openzen.zenscript.parser.expression; +import org.openzen.zencode.shared.CompileError; import org.openzen.zenscript.codemodel.compilation.expression.AbstractCompilingExpression; import org.openzen.zencode.shared.CodePosition; import org.openzen.zenscript.codemodel.CompareType; @@ -65,11 +66,25 @@ public Expression eval() { return notEquals.get().call(compiler, position, left, TypeID.NONE, right); } } - return resolved.compare(right.eval().type) + CastedExpression result = resolved.comparators() + .stream() .map(comparator -> comparator.compare(compiler, position, left, right, this.type)) - .orElseGet(() -> compiler.at(position).invalid( + .reduce((a, b) -> { + if (a.isFailed()) return b; + if (b.isFailed()) return a; + + if (a.level.compareTo(b.level) == 0) { + return new CastedExpression(a.level, compiler.at(position).invalid(CompileErrors.ambiguousComparison(a.value.type, b.value.type))); + } else if (a.level.compareTo(b.level) > 0) { + return a; + } else { + return b; + } + }) + .orElseGet(() -> CastedExpression.invalid(compiler.at(position).invalid( CompileErrors.noOperatorInType(left.type, OperatorType.COMPARE), //TODO Make error message more descriptive and include target type. - BasicTypeID.BOOL)); + BasicTypeID.BOOL))); + return result.value; } @Override diff --git a/Shared/src/main/java/org/openzen/zencode/shared/CompileExceptionCode.java b/Shared/src/main/java/org/openzen/zencode/shared/CompileExceptionCode.java index c67dd3f90..d53cb07c2 100644 --- a/Shared/src/main/java/org/openzen/zencode/shared/CompileExceptionCode.java +++ b/Shared/src/main/java/org/openzen/zencode/shared/CompileExceptionCode.java @@ -74,6 +74,7 @@ public enum CompileExceptionCode { INVALID_TYPE_ARGUMENTS, INVALID_ARRAY_TYPE, INFERENCE_AMBIGUOUS, + AMBIGUOUS_COMPARISON, NOT_AN_EXPRESSION, INCOMPLETE_HEADER, INCOMPLETE_IMPLEMENTATION, diff --git a/StdLibs b/StdLibs index 08927818c..043fb7d02 160000 --- a/StdLibs +++ b/StdLibs @@ -1 +1 @@ -Subproject commit 08927818c710ae6e68c5a6dae675873622062d84 +Subproject commit 043fb7d02fe7ce8c8b1d6b4a3abcceca5db8f45f