aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-06-10 11:00:22 +0100
committerMichael Williamson <mike@zwobble.org>2023-06-10 11:01:18 +0100
commit74b2aa135e2bf1af1ef65476aa03406eaaddd2ab (patch)
treec558aa52c7735b52bda18eded51b325111f57aa3 /src
parent677a2627c238c511b33f7586f97197f5cf3ced5b (diff)
Add incomplete type checking for calls
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedArgsNode.java12
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedCallNode.java13
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java5
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedNamedArgNode.java10
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedNode.java7
-rw-r--r--src/main/java/org/shedlang/compiler/stackir/StackCompiler.java3
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java29
-rw-r--r--src/test/java/org/shedlang/compiler/ast/typed/TypedArgsNodeMatcher.java36
-rw-r--r--src/test/java/org/shedlang/compiler/ast/typed/TypedCallNodeMatcher.java46
-rw-r--r--src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java18
-rw-r--r--src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java25
-rw-r--r--src/test/java/org/shedlang/compiler/ast/untyped/UntypedArgsNodeMatcher.java7
-rw-r--r--src/test/java/org/shedlang/compiler/ast/untyped/UntypedCallNodeMatcher.java7
-rw-r--r--src/test/java/org/shedlang/compiler/ast/untyped/UntypedFunctionDefinitionNodeMatcher.java7
-rw-r--r--src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java6
-rw-r--r--src/test/java/org/shedlang/compiler/testing/MatcherBuilder.java5
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerCallTests.java68
17 files changed, 283 insertions, 21 deletions
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedArgsNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedArgsNode.java
new file mode 100644
index 00000000..473fa197
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedArgsNode.java
@@ -0,0 +1,12 @@
+package org.shedlang.compiler.ast.typed;
+
+import org.shedlang.compiler.sources.Source;
+
+import java.util.List;
+
+public record TypedArgsNode(
+ List<TypedExpressionNode> positional,
+ List<TypedNamedArgNode> named,
+ Source source
+) implements TypedNode {
+}
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedCallNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedCallNode.java
new file mode 100644
index 00000000..188436f4
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedCallNode.java
@@ -0,0 +1,13 @@
+package org.shedlang.compiler.ast.typed;
+
+import org.shedlang.compiler.sources.Source;
+import org.shedlang.compiler.types.Type;
+
+public record TypedCallNode(
+ TypedExpressionNode receiver,
+ TypedArgsNode args,
+ boolean hasEffects,
+ Type type,
+ Source source
+) implements TypedExpressionNode {
+}
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 5ec6216b..0c61b3b2 100644
--- a/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java
+++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java
@@ -1,9 +1,8 @@
package org.shedlang.compiler.ast.typed;
-import org.shedlang.compiler.sources.Source;
import org.shedlang.compiler.types.Type;
-public sealed interface TypedExpressionNode permits TypedBoolLiteralNode, TypedIntLiteralNode, TypedReferenceNode, TypedStringLiteralNode {
- Source source();
+public sealed interface TypedExpressionNode
+ permits TypedBoolLiteralNode, TypedCallNode, TypedIntLiteralNode, TypedReferenceNode, TypedStringLiteralNode {
Type type();
}
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedNamedArgNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedNamedArgNode.java
new file mode 100644
index 00000000..c29f3c04
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedNamedArgNode.java
@@ -0,0 +1,10 @@
+package org.shedlang.compiler.ast.typed;
+
+import org.shedlang.compiler.sources.Source;
+
+public record TypedNamedArgNode(
+ String name,
+ TypedExpressionNode expression,
+ Source source
+) implements TypedNode {
+}
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedNode.java
new file mode 100644
index 00000000..d38c6017
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedNode.java
@@ -0,0 +1,7 @@
+package org.shedlang.compiler.ast.typed;
+
+import org.shedlang.compiler.sources.Source;
+
+public interface TypedNode {
+ Source source();
+}
diff --git a/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java b/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java
index 8a268c4c..1d6b0a88 100644
--- a/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java
+++ b/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java
@@ -18,6 +18,9 @@ public class StackCompiler {
case TypedBoolLiteralNode typedBoolLiteralNode ->
compileBoolLiteral(typedBoolLiteralNode);
+ case TypedCallNode typedCallNode ->
+ throw new UnsupportedOperationException("TODO");
+
case TypedIntLiteralNode typedIntLiteralNode ->
compileIntLiteral(typedIntLiteralNode);
diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
index 73d3b9b6..850929c3 100644
--- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
@@ -2,11 +2,22 @@ package org.shedlang.compiler.typechecker;
import org.shedlang.compiler.ast.typed.*;
import org.shedlang.compiler.ast.untyped.*;
+import org.shedlang.compiler.types.FunctionType;
+
+import java.util.List;
public class TypeChecker {
private TypeChecker() {
}
+ private static TypedArgsNode typeCheckArgs(UntypedArgsNode args, TypeCheckerContext context) {
+ var typedPositional = args.positional().stream()
+ .map(arg -> typeCheckExpression(arg, context))
+ .toList();
+
+ return new TypedArgsNode(typedPositional, List.of(), args.source());
+ }
+
public static TypedExpressionNode typeCheckBoolLiteral(
UntypedBoolLiteralNode untyped
) {
@@ -16,6 +27,22 @@ public class TypeChecker {
);
}
+ private static TypedExpressionNode typeCheckCall(
+ UntypedCallNode untyped,
+ TypeCheckerContext context
+ ) {
+ var typedReceiver = typeCheckExpression(untyped.receiver(), context);
+ var receiverType = (FunctionType) typedReceiver.type();
+
+ return new TypedCallNode(
+ typedReceiver,
+ typeCheckArgs(untyped.args(), context),
+ false,
+ receiverType.returnType(),
+ untyped.source()
+ );
+ }
+
public static TypedExpressionNode typeCheckExpression(
UntypedExpressionNode untyped,
TypeCheckerContext context
@@ -25,7 +52,7 @@ public class TypeChecker {
typeCheckBoolLiteral(untypedBoolLiteral);
case UntypedCallNode untypedCall ->
- throw new UnsupportedOperationException("TODO");
+ typeCheckCall(untypedCall, context);
case UntypedIntLiteralNode untypedIntLiteral ->
typeCheckIntLiteral(untypedIntLiteral);
diff --git a/src/test/java/org/shedlang/compiler/ast/typed/TypedArgsNodeMatcher.java b/src/test/java/org/shedlang/compiler/ast/typed/TypedArgsNodeMatcher.java
new file mode 100644
index 00000000..05037526
--- /dev/null
+++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedArgsNodeMatcher.java
@@ -0,0 +1,36 @@
+package org.shedlang.compiler.ast.typed;
+
+import org.pcollections.Empty;
+import org.pcollections.PVector;
+import org.shedlang.compiler.testing.MatcherBuilder;
+import org.zwobble.precisely.Matcher;
+
+import static org.zwobble.precisely.Matchers.has;
+
+public class TypedArgsNodeMatcher extends MatcherBuilder<TypedArgsNode, TypedArgsNode, TypedArgsNodeMatcher> {
+ public static TypedArgsNodeMatcher empty() {
+ return new TypedArgsNodeMatcher(Empty.vector());
+ }
+
+ public TypedArgsNodeMatcher(PVector<Matcher<? super TypedArgsNode>> submatchers) {
+ super(submatchers);
+ }
+
+ @Override
+ protected Class<TypedArgsNode> expectedType() {
+ return TypedArgsNode.class;
+ }
+
+ @Override
+ protected TypedArgsNodeMatcher create(PVector<Matcher<? super TypedArgsNode>> submatchers) {
+ return new TypedArgsNodeMatcher(submatchers);
+ }
+
+ public TypedArgsNodeMatcher withPositional(Matcher<? super Iterable<TypedExpressionNode>> positional) {
+ return with(has("positional", x -> x.positional(), positional));
+ }
+
+ public TypedArgsNodeMatcher withNamed(Matcher<? super Iterable<TypedNamedArgNode>> named) {
+ return with(has("named", x -> x.named(), named));
+ }
+}
diff --git a/src/test/java/org/shedlang/compiler/ast/typed/TypedCallNodeMatcher.java b/src/test/java/org/shedlang/compiler/ast/typed/TypedCallNodeMatcher.java
new file mode 100644
index 00000000..5512d9c8
--- /dev/null
+++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedCallNodeMatcher.java
@@ -0,0 +1,46 @@
+package org.shedlang.compiler.ast.typed;
+
+import org.pcollections.Empty;
+import org.pcollections.PVector;
+import org.shedlang.compiler.testing.MatcherBuilder;
+import org.shedlang.compiler.types.Type;
+import org.zwobble.precisely.Matcher;
+
+import static org.zwobble.precisely.Matchers.equalTo;
+import static org.zwobble.precisely.Matchers.has;
+
+public class TypedCallNodeMatcher extends MatcherBuilder<TypedExpressionNode, TypedCallNode, TypedCallNodeMatcher> {
+ public static TypedCallNodeMatcher empty() {
+ return new TypedCallNodeMatcher(Empty.vector());
+ }
+
+ public TypedCallNodeMatcher(PVector<Matcher<? super TypedCallNode>> submatchers) {
+ super(submatchers);
+ }
+
+ @Override
+ protected Class<TypedCallNode> expectedType() {
+ return TypedCallNode.class;
+ }
+
+ @Override
+ protected TypedCallNodeMatcher create(PVector<Matcher<? super TypedCallNode>> submatchers) {
+ return new TypedCallNodeMatcher(submatchers);
+ }
+
+ public TypedCallNodeMatcher withArgs(Matcher<TypedArgsNode> args) {
+ return with(has("args", x -> x.args(), args));
+ }
+
+ public TypedCallNodeMatcher withHasEffects(boolean hasEffects) {
+ return with(has("hasEffects", x -> x.hasEffects(), equalTo(hasEffects)));
+ }
+
+ public TypedCallNodeMatcher withReceiver(Matcher<TypedExpressionNode> receiver) {
+ return with(has("receiver", x -> x.receiver(), receiver));
+ }
+
+ public TypedCallNodeMatcher withType(Type type) {
+ return with(has("type", x -> x.type(), equalTo(type)));
+ }
+}
diff --git a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java
index 7716b76a..acf61900 100644
--- a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java
+++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java
@@ -11,6 +11,10 @@ public class TypedNodeMatchers {
private TypedNodeMatchers() {
}
+ public static TypedArgsNodeMatcher isTypedArgsNode() {
+ return TypedArgsNodeMatcher.empty();
+ }
+
public static Matcher<TypedExpressionNode> isTypedBoolLiteralNode(boolean value) {
return instanceOf(
TypedBoolLiteralNode.class,
@@ -18,6 +22,10 @@ public class TypedNodeMatchers {
);
}
+ public static TypedCallNodeMatcher isTypedCallNode() {
+ return TypedCallNodeMatcher.empty();
+ }
+
public static Matcher<TypedExpressionNode> isTypedIntLiteralNode(int value) {
return isTypedIntLiteralNode(BigInteger.valueOf(value));
}
@@ -29,6 +37,16 @@ public class TypedNodeMatchers {
);
}
+ public static Matcher<TypedNamedArgNode> isTypedNamedArgNode(
+ String name,
+ Matcher<TypedExpressionNode> expression
+ ) {
+ return allOf(
+ has("name", x -> x.name(), equalTo(name)),
+ has("expression", x -> x.expression(), expression)
+ );
+ }
+
public static Matcher<TypedExpressionNode> isTypedReferenceNode(String name, Type type) {
return instanceOf(
TypedReferenceNode.class,
diff --git a/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java b/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java
index 37778968..11e7b38f 100644
--- a/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java
+++ b/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java
@@ -3,6 +3,7 @@ package org.shedlang.compiler.ast.untyped;
import org.shedlang.compiler.sources.Sources;
import java.math.BigInteger;
+import java.util.List;
public class Untyped {
private Untyped() {
@@ -20,6 +21,10 @@ public class Untyped {
return new UntypedIntLiteralNode(value, Sources.NULL);
}
+ public static UntypedNamedArgNode namedArg(String name, UntypedExpressionNode expression) {
+ return new UntypedNamedArgNode(name, expression, Sources.NULL);
+ }
+
public static UntypedReferenceNode reference(String name) {
return new UntypedReferenceNode(name, Sources.NULL);
}
@@ -27,4 +32,24 @@ public class Untyped {
public static UntypedStringLiteralNode stringLiteral(String value) {
return new UntypedStringLiteralNode(value, Sources.NULL);
}
+
+ public static UntypedCallNode call(
+ UntypedExpressionNode receiver,
+ List<UntypedExpressionNode> positionalArgs
+ ) {
+ return call(receiver, positionalArgs, List.of());
+ }
+
+ public static UntypedCallNode call(
+ UntypedExpressionNode receiver,
+ List<UntypedExpressionNode> positionalArgs,
+ List<UntypedNamedArgNode> namedArgs
+ ) {
+ return new UntypedCallNode(
+ receiver,
+ new UntypedArgsNode(positionalArgs, namedArgs, Sources.NULL),
+ false,
+ Sources.NULL
+ );
+ }
}
diff --git a/src/test/java/org/shedlang/compiler/ast/untyped/UntypedArgsNodeMatcher.java b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedArgsNodeMatcher.java
index ce782c0d..da40138d 100644
--- a/src/test/java/org/shedlang/compiler/ast/untyped/UntypedArgsNodeMatcher.java
+++ b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedArgsNodeMatcher.java
@@ -1,5 +1,6 @@
package org.shedlang.compiler.ast.untyped;
+import org.pcollections.Empty;
import org.pcollections.PVector;
import org.shedlang.compiler.testing.MatcherBuilder;
import org.zwobble.precisely.Matcher;
@@ -7,8 +8,8 @@ import org.zwobble.precisely.Matcher;
import static org.zwobble.precisely.Matchers.has;
public class UntypedArgsNodeMatcher extends MatcherBuilder<UntypedArgsNode, UntypedArgsNode, UntypedArgsNodeMatcher> {
- public UntypedArgsNodeMatcher() {
- super();
+ public static UntypedArgsNodeMatcher empty() {
+ return new UntypedArgsNodeMatcher(Empty.vector());
}
public UntypedArgsNodeMatcher(PVector<Matcher<? super UntypedArgsNode>> submatchers) {
@@ -22,7 +23,7 @@ public class UntypedArgsNodeMatcher extends MatcherBuilder<UntypedArgsNode, Unty
@Override
protected UntypedArgsNodeMatcher create(PVector<Matcher<? super UntypedArgsNode>> submatchers) {
- return new UntypedArgsNodeMatcher();
+ return new UntypedArgsNodeMatcher(submatchers);
}
public UntypedArgsNodeMatcher withPositional(Matcher<? super Iterable<UntypedExpressionNode>> positional) {
diff --git a/src/test/java/org/shedlang/compiler/ast/untyped/UntypedCallNodeMatcher.java b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedCallNodeMatcher.java
index b9411fec..aeb020a3 100644
--- a/src/test/java/org/shedlang/compiler/ast/untyped/UntypedCallNodeMatcher.java
+++ b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedCallNodeMatcher.java
@@ -1,5 +1,6 @@
package org.shedlang.compiler.ast.untyped;
+import org.pcollections.Empty;
import org.pcollections.PVector;
import org.shedlang.compiler.testing.MatcherBuilder;
import org.zwobble.precisely.Matcher;
@@ -8,8 +9,8 @@ import static org.zwobble.precisely.Matchers.equalTo;
import static org.zwobble.precisely.Matchers.has;
public class UntypedCallNodeMatcher extends MatcherBuilder<UntypedExpressionNode, UntypedCallNode, UntypedCallNodeMatcher> {
- public UntypedCallNodeMatcher() {
- super();
+ public static UntypedCallNodeMatcher empty() {
+ return new UntypedCallNodeMatcher(Empty.vector());
}
public UntypedCallNodeMatcher(PVector<Matcher<? super UntypedCallNode>> submatchers) {
@@ -23,7 +24,7 @@ public class UntypedCallNodeMatcher extends MatcherBuilder<UntypedExpressionNode
@Override
protected UntypedCallNodeMatcher create(PVector<Matcher<? super UntypedCallNode>> submatchers) {
- return new UntypedCallNodeMatcher();
+ return new UntypedCallNodeMatcher(submatchers);
}
public UntypedCallNodeMatcher withArgs(Matcher<UntypedArgsNode> args) {
diff --git a/src/test/java/org/shedlang/compiler/ast/untyped/UntypedFunctionDefinitionNodeMatcher.java b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedFunctionDefinitionNodeMatcher.java
index e8a227c3..c88111df 100644
--- a/src/test/java/org/shedlang/compiler/ast/untyped/UntypedFunctionDefinitionNodeMatcher.java
+++ b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedFunctionDefinitionNodeMatcher.java
@@ -1,5 +1,6 @@
package org.shedlang.compiler.ast.untyped;
+import org.pcollections.Empty;
import org.pcollections.PVector;
import org.shedlang.compiler.testing.MatcherBuilder;
import org.zwobble.precisely.Matcher;
@@ -10,8 +11,8 @@ import static org.zwobble.precisely.Matchers.equalTo;
import static org.zwobble.precisely.Matchers.has;
public class UntypedFunctionDefinitionNodeMatcher extends MatcherBuilder<UntypedNamespaceStatementNode, UntypedFunctionDefinitionNode, UntypedFunctionDefinitionNodeMatcher> {
- public UntypedFunctionDefinitionNodeMatcher() {
- super();
+ public static UntypedFunctionDefinitionNodeMatcher empty() {
+ return new UntypedFunctionDefinitionNodeMatcher(Empty.vector());
}
public UntypedFunctionDefinitionNodeMatcher(PVector<Matcher<? super UntypedFunctionDefinitionNode>> submatchers) {
@@ -25,7 +26,7 @@ public class UntypedFunctionDefinitionNodeMatcher extends MatcherBuilder<Untyped
@Override
protected UntypedFunctionDefinitionNodeMatcher create(PVector<Matcher<? super UntypedFunctionDefinitionNode>> submatchers) {
- return new UntypedFunctionDefinitionNodeMatcher();
+ return new UntypedFunctionDefinitionNodeMatcher(submatchers);
}
public UntypedFunctionDefinitionNodeMatcher withBody(Matcher<Iterable<UntypedFunctionStatementNode>> body) {
diff --git a/src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java
index 04c56443..6c06e52a 100644
--- a/src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java
+++ b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java
@@ -9,11 +9,11 @@ public class UntypedNodeMatchers {
}
public static UntypedArgsNodeMatcher isUntypedArgsNode() {
- return new UntypedArgsNodeMatcher();
+ return UntypedArgsNodeMatcher.empty();
}
public static UntypedCallNodeMatcher isUntypedCallNode() {
- return new UntypedCallNodeMatcher();
+ return UntypedCallNodeMatcher.empty();
}
public static Matcher<UntypedFunctionStatementNode> isUntypedExpressionStatementNode(
@@ -26,7 +26,7 @@ public class UntypedNodeMatchers {
}
public static UntypedFunctionDefinitionNodeMatcher isUntypedFunctionDefinitionNode() {
- return new UntypedFunctionDefinitionNodeMatcher();
+ return UntypedFunctionDefinitionNodeMatcher.empty();
}
public static Matcher<UntypedNamedArgNode> isUntypedNamedArgNode(
diff --git a/src/test/java/org/shedlang/compiler/testing/MatcherBuilder.java b/src/test/java/org/shedlang/compiler/testing/MatcherBuilder.java
index 6736659f..984ba3da 100644
--- a/src/test/java/org/shedlang/compiler/testing/MatcherBuilder.java
+++ b/src/test/java/org/shedlang/compiler/testing/MatcherBuilder.java
@@ -1,6 +1,5 @@
package org.shedlang.compiler.testing;
-import org.pcollections.Empty;
import org.pcollections.PVector;
import org.zwobble.precisely.MatchResult;
import org.zwobble.precisely.Matcher;
@@ -11,10 +10,6 @@ import static org.zwobble.precisely.Matchers.instanceOf;
public abstract class MatcherBuilder<T, U, This> implements Matcher<T> {
private final PVector<Matcher<? super U>> submatchers;
- public MatcherBuilder() {
- this(Empty.vector());
- }
-
public MatcherBuilder(PVector<Matcher<? super U>> submatchers) {
this.submatchers = submatchers;
}
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerCallTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerCallTests.java
new file mode 100644
index 00000000..379368a1
--- /dev/null
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerCallTests.java
@@ -0,0 +1,68 @@
+package org.shedlang.compiler.typechecker;
+
+import org.junit.jupiter.api.Test;
+import org.shedlang.compiler.ast.untyped.Untyped;
+import org.shedlang.compiler.types.FunctionType;
+import org.shedlang.compiler.types.Types;
+import org.shedlang.compiler.util.P;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.shedlang.compiler.ast.typed.TypedNodeMatchers.*;
+import static org.zwobble.precisely.AssertThat.assertThat;
+import static org.zwobble.precisely.Matchers.isSequence;
+
+public class TypeCheckerCallTests {
+ @Test
+ public void canCallFunctionWithNoArgs() {
+ var untyped = Untyped.call(
+ Untyped.reference("f"),
+ List.of()
+ );
+ var functionType = FunctionType.builder()
+ .withReturnType(Types.STRING)
+ .build();
+ var context = TypeCheckerContext.EMPTY
+ .enter(P.map(Map.entry("f", functionType)));
+
+ var typed = TypeChecker.typeCheckExpression(untyped, context);
+
+ assertThat(
+ typed,
+ isTypedCallNode()
+ .withReceiver(isTypedReferenceNode("f", functionType))
+ .withArgs(isTypedArgsNode().withPositional(isSequence()).withNamed(isSequence()))
+ .withHasEffects(false)
+ .withType(Types.STRING)
+ );
+ }
+
+ @Test
+ public void positionalArgsAreTypedChecked() {
+ var untyped = Untyped.call(
+ Untyped.reference("f"),
+ List.of(
+ Untyped.stringLiteral("hello"),
+ Untyped.intLiteral(42)
+ )
+ );
+ var functionType = FunctionType.builder()
+ .addPositionalParam(Types.STRING)
+ .addPositionalParam(Types.INT)
+ .build();
+ var context = TypeCheckerContext.EMPTY
+ .enter(P.map(Map.entry("f", functionType)));
+
+ var typed = TypeChecker.typeCheckExpression(untyped, context);
+
+ assertThat(
+ typed,
+ isTypedCallNode()
+ .withArgs(isTypedArgsNode().withPositional(isSequence(
+ isTypedStringLiteralNode("hello"),
+ isTypedIntLiteralNode(42)
+ )))
+ );
+ }
+}