diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-06-10 11:17:03 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-06-10 11:17:14 +0100 |
| commit | 646c5b9673ffbbc691db246ca8a253cb3e6ea8a1 (patch) | |
| tree | c8e9cab7e3c9893994f8c7bce845bf14f66b6e37 /src/main/java | |
| parent | 482c93fe786d63dd8263bde262acc76467021169 (diff) | |
Check positional arg type matches param type
Diffstat (limited to 'src/main/java')
7 files changed, 98 insertions, 5 deletions
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java index 0c61b3b2..4bb9cb8e 100644 --- a/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java +++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java @@ -3,6 +3,7 @@ package org.shedlang.compiler.ast.typed; import org.shedlang.compiler.types.Type; public sealed interface TypedExpressionNode + extends TypedNode permits TypedBoolLiteralNode, TypedCallNode, TypedIntLiteralNode, TypedReferenceNode, TypedStringLiteralNode { Type type(); } diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index d4704a4e..ebfdc0d5 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -2,18 +2,38 @@ package org.shedlang.compiler.typechecker; import org.shedlang.compiler.ast.typed.*; import org.shedlang.compiler.ast.untyped.*; +import org.shedlang.compiler.typechecker.typesets.TypeSets; import org.shedlang.compiler.types.FunctionType; +import org.shedlang.compiler.types.Type; public class TypeChecker { private TypeChecker() { } - private static TypedArgsNode typeCheckArgs(UntypedArgsNode args, TypeCheckerContext context) { - var typedPositional = args.positional().stream() + private static void checkIsSubType(TypedExpressionNode expression, Type expectedType, TypeCheckerContext context) { + if (!isSubType(expression.type(), expectedType, context)) { + throw new UnexpectedTypeError( + TypeSets.type(expectedType), + expression.type(), + expression.source() + ); + } + } + + private static boolean isSubType(Type subType, Type superType, TypeCheckerContext context) { + return subType.equals(superType); + } + + private static TypedArgsNode typeCheckArgs( + UntypedArgsNode args, + TypeCheckerContext context, + FunctionType receiverType + ) { + var typedPositionalArgs = args.positional().stream() .map(arg -> typeCheckExpression(arg, context)) .toList(); - var typedNamed = args.named().stream() + var typedNamedArgs = args.named().stream() .map(arg -> new TypedNamedArgNode( arg.name(), typeCheckExpression(arg.expression(), context), @@ -21,7 +41,14 @@ public class TypeChecker { )) .toList(); - return new TypedArgsNode(typedPositional, typedNamed, args.source()); + for (var i = 0; i < typedPositionalArgs.size(); i++) { + var typedArg = typedPositionalArgs.get(i); + var paramType = receiverType.positionalParams().get(i); + + checkIsSubType(typedArg, paramType, context); + } + + return new TypedArgsNode(typedPositionalArgs, typedNamedArgs, args.source()); } public static TypedExpressionNode typeCheckBoolLiteral( @@ -42,7 +69,7 @@ public class TypeChecker { return new TypedCallNode( typedReceiver, - typeCheckArgs(untyped.args(), context), + typeCheckArgs(untyped.args(), context, receiverType), false, receiverType.returnType(), untyped.source() diff --git a/src/main/java/org/shedlang/compiler/typechecker/UnexpectedTypeError.java b/src/main/java/org/shedlang/compiler/typechecker/UnexpectedTypeError.java new file mode 100644 index 00000000..51cc6652 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/typechecker/UnexpectedTypeError.java @@ -0,0 +1,25 @@ +package org.shedlang.compiler.typechecker; + +import org.shedlang.compiler.errors.SourceError; +import org.shedlang.compiler.sources.Source; +import org.shedlang.compiler.typechecker.typesets.TypeSet; +import org.shedlang.compiler.types.Type; + +public class UnexpectedTypeError extends SourceError { + private final TypeSet expected; + private final Type actual; + + public UnexpectedTypeError(TypeSet expected, Type actual, Source source) { + super("Expected " + expected.describe() + " but was " + actual.describe(), source); + this.expected = expected; + this.actual = actual; + } + + public TypeSet expected() { + return expected; + } + + public Type actual() { + return actual; + } +} diff --git a/src/main/java/org/shedlang/compiler/typechecker/typesets/TypeSet.java b/src/main/java/org/shedlang/compiler/typechecker/typesets/TypeSet.java new file mode 100644 index 00000000..79cb0433 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/typechecker/typesets/TypeSet.java @@ -0,0 +1,5 @@ +package org.shedlang.compiler.typechecker.typesets; + +public sealed interface TypeSet permits TypeSetFunction, TypeSetType { + String describe(); +} diff --git a/src/main/java/org/shedlang/compiler/typechecker/typesets/TypeSetFunction.java b/src/main/java/org/shedlang/compiler/typechecker/typesets/TypeSetFunction.java new file mode 100644 index 00000000..127c0e71 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/typechecker/typesets/TypeSetFunction.java @@ -0,0 +1,13 @@ +package org.shedlang.compiler.typechecker.typesets; + +public final class TypeSetFunction implements TypeSet { + static final TypeSetFunction INSTANCE = new TypeSetFunction(); + + private TypeSetFunction() { + } + + @Override + public String describe() { + return "function"; + } +} diff --git a/src/main/java/org/shedlang/compiler/typechecker/typesets/TypeSetType.java b/src/main/java/org/shedlang/compiler/typechecker/typesets/TypeSetType.java new file mode 100644 index 00000000..f067351a --- /dev/null +++ b/src/main/java/org/shedlang/compiler/typechecker/typesets/TypeSetType.java @@ -0,0 +1,10 @@ +package org.shedlang.compiler.typechecker.typesets; + +import org.shedlang.compiler.types.Type; + +public record TypeSetType(Type type) implements TypeSet { + @Override + public String describe() { + return type.describe(); + } +} diff --git a/src/main/java/org/shedlang/compiler/typechecker/typesets/TypeSets.java b/src/main/java/org/shedlang/compiler/typechecker/typesets/TypeSets.java new file mode 100644 index 00000000..4f5f1848 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/typechecker/typesets/TypeSets.java @@ -0,0 +1,12 @@ +package org.shedlang.compiler.typechecker.typesets; + +import org.shedlang.compiler.types.Type; + +public class TypeSets { + private TypeSets() { + } + + public static TypeSet type(Type type) { + return new TypeSetType(type); + } +} |
