summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java11
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/errors/WrongNumberOfTypeLevelArgsError.java23
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerConstructedTypeTests.java45
3 files changed, 77 insertions, 2 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
index a12677e..2d496e5 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
@@ -393,14 +393,21 @@ public class TypeChecker {
TypeCheckerNamespaceContext context
) {
var typedReceiver = typeCheckTypeLevelExpression(untyped.receiver(), context);
+ // TODO: check this properly
var receiver = (TypeConstructor<SimpleNativeType>) typedReceiver.value();
+ if (untyped.args().size() != receiver.params().size()) {
+ throw new WrongNumberOfTypeLevelArgsError(
+ receiver.params().size(),
+ untyped.args().size(),
+ untyped.source()
+ );
+ }
+
var args = untyped.args().stream()
.map(untypedArg -> typeCheckMetaType(untypedArg, context).value())
.toList();
- // TODO: check number of args
-
var constructedType = new ConstructedNativeType(receiver, args);
return new TypedConstructedTypeNode(
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/errors/WrongNumberOfTypeLevelArgsError.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/errors/WrongNumberOfTypeLevelArgsError.java
new file mode 100644
index 0000000..86f57f2
--- /dev/null
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/errors/WrongNumberOfTypeLevelArgsError.java
@@ -0,0 +1,23 @@
+package org.zwobble.hobgoblin.compiler.typechecker.errors;
+
+import org.zwobble.hobgoblin.compiler.errors.SourceError;
+import org.zwobble.hobgoblin.compiler.sources.Source;
+
+public class WrongNumberOfTypeLevelArgsError extends SourceError {
+ private final int expectedArgCount;
+ private final int actualArgCount;
+
+ public WrongNumberOfTypeLevelArgsError(int expectedArgCount, int actualArgCount, Source source) {
+ super("expected " + expectedArgCount + " type-level args, but got " + actualArgCount, source);
+ this.expectedArgCount = expectedArgCount;
+ this.actualArgCount = actualArgCount;
+ }
+
+ public int expectedArgCount() {
+ return expectedArgCount;
+ }
+
+ public int actualArgCount() {
+ return actualArgCount;
+ }
+}
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerConstructedTypeTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerConstructedTypeTests.java
index fa511ba..09c0f8c 100644
--- a/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerConstructedTypeTests.java
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerConstructedTypeTests.java
@@ -3,10 +3,12 @@ package org.zwobble.hobgoblin.compiler.typechecker;
import org.junit.jupiter.api.Test;
import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedArb;
import org.zwobble.hobgoblin.compiler.sources.NullSource;
+import org.zwobble.hobgoblin.compiler.typechecker.errors.WrongNumberOfTypeLevelArgsError;
import org.zwobble.hobgoblin.compiler.types.*;
import java.util.List;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.zwobble.hobgoblin.compiler.ast.typed.TypedNodeMatchers.isTypedConstructedTypeNode;
import static org.zwobble.precisely.AssertThat.assertThat;
import static org.zwobble.precisely.Matchers.equalTo;
@@ -31,4 +33,47 @@ public class TypeCheckerConstructedTypeTests {
equalTo(new ConstructedNativeType(listTypeConstructor, List.of(int32Type)))
));
}
+
+ @Test
+ public void whenThereAreTooFewArgsThenErrorIsThrown() {
+ var untyped = UntypedArb.constructedType(
+ UntypedArb.typeLevelReference("List"),
+ List.of()
+ );
+ var context = TypeCheckerContextArb.namespaceContext();
+ var listType = SimpleNativeType.builtin("List");
+ var listTypeConstructor = new TypeConstructor<>(List.of(new TypeParam("T")), listType);
+ context.declare("List", new TypeLevelValueType(listTypeConstructor), NullSource.INSTANCE);
+
+ var error = assertThrows(
+ WrongNumberOfTypeLevelArgsError.class,
+ () -> TypeChecker.typeCheckTypeLevelExpression(untyped, context)
+ );
+
+ assertThat(error.expectedArgCount(), equalTo(1));
+ assertThat(error.actualArgCount(), equalTo(0));
+ }
+
+ @Test
+ public void whenThereAreTooManyArgsThenErrorIsThrown() {
+ var untyped = UntypedArb.constructedType(
+ UntypedArb.typeLevelReference("List"),
+ List.of(
+ UntypedArb.typeLevelReference("Int32"),
+ UntypedArb.typeLevelReference("Int64")
+ )
+ );
+ var context = TypeCheckerContextArb.namespaceContext();
+ var listType = SimpleNativeType.builtin("List");
+ var listTypeConstructor = new TypeConstructor<>(List.of(new TypeParam("T")), listType);
+ context.declare("List", new TypeLevelValueType(listTypeConstructor), NullSource.INSTANCE);
+
+ var error = assertThrows(
+ WrongNumberOfTypeLevelArgsError.class,
+ () -> TypeChecker.typeCheckTypeLevelExpression(untyped, context)
+ );
+
+ assertThat(error.expectedArgCount(), equalTo(1));
+ assertThat(error.actualArgCount(), equalTo(2));
+ }
}