diff options
| author | Michael Williamson <mike@zwobble.org> | 2024-03-03 09:34:44 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2024-03-03 09:34:44 +0000 |
| commit | ec7c801a8dbad307b76b0a18f819da3ea06bb16e (patch) | |
| tree | ac3643832d6622ccf430b97e2928d416d958c802 /src/main/java | |
| parent | 925916777a52ffa2f0cf94c761b3a4616fe17019 (diff) | |
Support calling functions with explicit type-level args
Diffstat (limited to 'src/main/java')
| -rw-r--r-- | src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java | 56 | ||||
| -rw-r--r-- | src/main/java/org/shedlang/compiler/types/FunctionType.java | 2 |
2 files changed, 50 insertions, 8 deletions
diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index 223323d3..c51758bb 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -376,23 +376,39 @@ public class TypeChecker { var contextForReceiver = context; var receiverType = untyped.typeLevelArgs() .map(untypedTypeLevelArgNodes -> { - var typeLevelArgs = untypedTypeLevelArgNodes.stream() - .map(argNode -> typeCheckTypeExpression(argNode, contextForReceiver).value()) - .toList(); + Type specificReceiverType; if ( typedReceiver.type() instanceof TypeLevelValueType initialReceiverType && initialReceiverType.value() instanceof TypeConstructor<?> typeConstructor ) { - // TODO: check args - return typeCheckCallReceiverType( - Types.metaType(Types.constructedType(typeConstructor, typeLevelArgs)), - typedReceiver.source(), + var typeLevelArgs = typeCheckTypeLevelArgs( + untypedTypeLevelArgNodes, + typeConstructor.params(), + contextForReceiver + ); + specificReceiverType = Types.metaType( + Types.constructedType(typeConstructor, typeLevelArgs) + ); + } else if ( + typedReceiver.type() instanceof FunctionType initialReceiverType && + initialReceiverType.typeLevelParams().isPresent() + ) { + var typeLevelArgs = typeCheckTypeLevelArgs( + untypedTypeLevelArgNodes, + initialReceiverType.typeLevelParams().get(), contextForReceiver ); + specificReceiverType = initialReceiverType.applyTypeLevelArgs(typeLevelArgs); } else { throw new IllegalArgumentException("TODO"); } + + return typeCheckCallReceiverType( + specificReceiverType, + typedReceiver.source(), + contextForReceiver + ); }) .orElseGet(() -> typeCheckCallReceiverType(typedReceiver, contextForReceiver)); @@ -1864,6 +1880,32 @@ public class TypeChecker { return new TypedTupleTypeNode(tupleType, untyped.source()); } + private static ArrayList<TypeLevelValue> typeCheckTypeLevelArgs( + List<UntypedTypeLevelExpressionNode> untyped, + List<TypeLevelParam> typeLevelParams, + TypeCheckerContext context + ) { + var typeLevelArgs = new ArrayList<TypeLevelValue>(); + + // TODO: check length + // TODO: check arg is appropriate for param + + for (var paramIndex = 0; paramIndex < typeLevelParams.size(); paramIndex++) { + var typeLevelParam = typeLevelParams.get(paramIndex); + var argNode = untyped.get(paramIndex); + + var typeLevelArg = switch (typeLevelParam) { + case EffectParam effectParam -> + typeCheckEffect(argNode, context).value(); + case TypeParam typeParam -> + typeCheckTypeExpression(argNode, context).value(); + }; + typeLevelArgs.add(typeLevelArg); + } + + return typeLevelArgs; + } + private static TypedTypeLevelExpressionNode<TypeLevelValue> typeCheckTypeLevelReference( UntypedTypeLevelReferenceNode untyped, TypeCheckerContext context diff --git a/src/main/java/org/shedlang/compiler/types/FunctionType.java b/src/main/java/org/shedlang/compiler/types/FunctionType.java index 14a885f7..9c992e55 100644 --- a/src/main/java/org/shedlang/compiler/types/FunctionType.java +++ b/src/main/java/org/shedlang/compiler/types/FunctionType.java @@ -78,7 +78,7 @@ public record FunctionType( ); } - public FunctionType applyTypeLevelArgs(List<TypeLevelArg> typeArgs) { + public FunctionType applyTypeLevelArgs(List<? extends TypeLevelValue> typeArgs) { var typeSubstitutionMap = TypeSubstitutionMap.from( this.typeLevelParams.orElseThrow(), typeArgs |
