diff options
| author | Michael Williamson <mike@zwobble.org> | 2024-03-03 10:27:42 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2024-03-03 10:27:42 +0000 |
| commit | f48ecd33ee4430abe7ebb85652554d37d8dea29b (patch) | |
| tree | 938632a0b72cd176f5f9945307a8d1b18b07e733 /src | |
| parent | ec7c801a8dbad307b76b0a18f819da3ea06bb16e (diff) | |
Check number of type-level arguments
Diffstat (limited to 'src')
3 files changed, 65 insertions, 1 deletions
diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index c51758bb..d9a52038 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -385,6 +385,7 @@ public class TypeChecker { var typeLevelArgs = typeCheckTypeLevelArgs( untypedTypeLevelArgNodes, typeConstructor.params(), + untyped.source(), contextForReceiver ); specificReceiverType = Types.metaType( @@ -397,6 +398,7 @@ public class TypeChecker { var typeLevelArgs = typeCheckTypeLevelArgs( untypedTypeLevelArgNodes, initialReceiverType.typeLevelParams().get(), + untyped.source(), contextForReceiver ); specificReceiverType = initialReceiverType.applyTypeLevelArgs(typeLevelArgs); @@ -1883,11 +1885,19 @@ public class TypeChecker { private static ArrayList<TypeLevelValue> typeCheckTypeLevelArgs( List<UntypedTypeLevelExpressionNode> untyped, List<TypeLevelParam> typeLevelParams, + Source source, TypeCheckerContext context ) { + if (untyped.size() != typeLevelParams.size()) { + throw new WrongNumberOfTypeLevelArgsError( + typeLevelParams.size(), + untyped.size(), + source + ); + } + var typeLevelArgs = new ArrayList<TypeLevelValue>(); - // TODO: check length // TODO: check arg is appropriate for param for (var paramIndex = 0; paramIndex < typeLevelParams.size(); paramIndex++) { diff --git a/src/main/java/org/shedlang/compiler/typechecker/errors/WrongNumberOfTypeLevelArgsError.java b/src/main/java/org/shedlang/compiler/typechecker/errors/WrongNumberOfTypeLevelArgsError.java new file mode 100644 index 00000000..9af86c37 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/typechecker/errors/WrongNumberOfTypeLevelArgsError.java @@ -0,0 +1,23 @@ +package org.shedlang.compiler.typechecker.errors; + +import org.shedlang.compiler.errors.SourceError; +import org.shedlang.compiler.sources.Source; + +public class WrongNumberOfTypeLevelArgsError extends SourceError { + private final int expected; + private final int actual; + + public WrongNumberOfTypeLevelArgsError(int expected, int actual, Source source) { + super("Expected " + expected + " type-level arguments but got " + actual, source); + this.expected = expected; + this.actual = actual; + } + + public int expected() { + return expected; + } + + public int actual() { + return actual; + } +} diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerCallTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerCallTests.java index 21a3e718..3027304e 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerCallTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerCallTests.java @@ -632,4 +632,35 @@ public class TypeCheckerCallTests { .withHasEffects(true) ); } + + @Test + public void whenReceiverIsCalledWithWrongNumberOfTypeLevelArgsThenErrorIsThrown() { + var untyped = UntypedCallNode.builder() + .withReceiver(Untyped.reference("identity")) + .withTypeLevelArgs(List.of( + Untyped.typeLevelReference("Int"), + Untyped.typeLevelReference("Int") + )) + .addPositionalArg(Untyped.intLiteral(42)) + .build(); + var context = TypeCheckerContext.EMPTY + .enterGlobal(P.map( + Map.entry( + "identity", + FunctionType.builder() + .withTypeLevelParams(List.of( + TypeParam.forFunction(NamespaceName.of("Example"), "identity", "T") + )) + .addPositionalParam(TypeParam.forFunction(NamespaceName.of("Example"), "identity", "T")) + .withReturnType(TypeParam.forFunction(NamespaceName.of("Example"), "identity", "T")) + .build() + ), + Map.entry("Int", Types.metaType(Types.INT)) + )); + + var error = assertThrows(WrongNumberOfTypeLevelArgsError.class, () -> typeCheckExpression(untyped, context)); + + assertThat(error.expected(), equalTo(1)); + assertThat(error.actual(), equalTo(2)); + } } |
