aboutsummaryrefslogtreecommitdiff
path: root/src/test/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2024-03-03 09:34:44 +0000
committerMichael Williamson <mike@zwobble.org>2024-03-03 09:34:44 +0000
commitec7c801a8dbad307b76b0a18f819da3ea06bb16e (patch)
treeac3643832d6622ccf430b97e2928d416d958c802 /src/test/java
parent925916777a52ffa2f0cf94c761b3a4616fe17019 (diff)
Support calling functions with explicit type-level args
Diffstat (limited to 'src/test/java')
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerCallTests.java119
1 files changed, 119 insertions, 0 deletions
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerCallTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerCallTests.java
index c7bbafaf..21a3e718 100644
--- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerCallTests.java
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerCallTests.java
@@ -467,6 +467,125 @@ public class TypeCheckerCallTests {
}
@Test
+ public void canCallGenericFunctionWithExplicitTypeArg() {
+ var untyped = UntypedCallNode.builder()
+ .withReceiver(Untyped.reference("identity"))
+ .withTypeLevelArgs(List.of(
+ 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 typed = typeCheckExpression(untyped, context);
+
+ assertThat(
+ typed.value(),
+ isTypedCallNode()
+ .withType(Types.INT)
+ );
+ }
+
+ @Test
+ public void canCallGenericFunctionWithImplicitTypeArg() {
+ var untyped = UntypedCallNode.builder()
+ .withReceiver(Untyped.reference("identity"))
+ .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 typed = typeCheckExpression(untyped, context);
+
+ assertThat(
+ typed.value(),
+ isTypedCallNode()
+ .withType(Types.INT)
+ );
+ }
+
+ @Test
+ public void canCallGenericFunctionWithExplicitEffectArg() {
+ var untyped = UntypedCallNode.builder()
+ .withReceiver(Untyped.reference("twice"))
+ .withHasEffects(true)
+ .withTypeLevelArgs(List.of(Untyped.typeLevelReference("Io")))
+ .addPositionalArg(Untyped.reference("f"))
+ .build();
+ var twiceType = FunctionType.builder()
+ .withTypeLevelParams(List.of(
+ EffectParam.forFunction(NamespaceName.of("Example"), "twice", "E")
+ ))
+ .addPositionalParam(
+ FunctionType.builder()
+ .withEffect(EffectParam.forFunction(NamespaceName.of("Example"), "twice", "E"))
+ .build()
+ )
+ .withEffect(EffectParam.forFunction(NamespaceName.of("Example"), "twice", "E"))
+ .build();
+ var context = TypeCheckerContext.EMPTY
+ .enterFunction(
+ P.map(
+ Map.entry(
+ "twice",
+ Variable.defined(twiceType, VariableType.VAL)
+ ),
+ Map.entry(
+ "f",
+ Variable.defined(
+ FunctionType.builder()
+ .withEffect(Effects.IO)
+ .build(),
+ VariableType.VAL
+ )
+ ),
+ Map.entry(
+ "Io",
+ Variable.defined(
+ Types.effectType(Effects.IO),
+ VariableType.CONSTANT
+ )
+ )
+ ),
+ Effects.IO,
+ Types.UNIT
+ );
+
+ var typed = typeCheckExpression(untyped, context);
+
+ assertThat(
+ typed.value(),
+ isTypedCallNode()
+ .withHasEffects(true)
+ );
+ }
+
+ @Test
public void canCallGenericFunctionWithImplicitEffectArg() {
var untyped = UntypedCallNode.builder()
.withReceiver(Untyped.reference("twice"))