diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-11-07 16:41:51 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-11-07 16:41:51 +0000 |
| commit | 188006a7a103106924fd7e16edb1cafb352eb78c (patch) | |
| tree | ca04a8b711c020f1bbd3c5517dfee939c8afe39d /src | |
| parent | c22e9652e8a2904829bc7d5586074f38ded966f3 (diff) | |
Add (unsound) basic type-checking for resume statements
Diffstat (limited to 'src')
8 files changed, 52 insertions, 13 deletions
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionStatementNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionStatementNode.java index 57a585a0..a79437ec 100644 --- a/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionStatementNode.java +++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionStatementNode.java @@ -1,5 +1,5 @@ package org.shedlang.compiler.ast.typed; -public sealed interface TypedFunctionStatementNode extends TypedNode permits TypedWhileNode, TypedAssignNode, TypedBlockReturnNode, TypedExpressionStatementNode, TypedFunctionReturnNode { +public sealed interface TypedFunctionStatementNode extends TypedNode permits TypedAssignNode, TypedBlockReturnNode, TypedExpressionStatementNode, TypedFunctionReturnNode, TypedResumeNode, TypedWhileNode { TypedFunctionStatementBehaviour behaviour(); } diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedResumeNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedResumeNode.java new file mode 100644 index 00000000..6511d3b6 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedResumeNode.java @@ -0,0 +1,13 @@ +package org.shedlang.compiler.ast.typed; + +import org.shedlang.compiler.sources.Source; + +public record TypedResumeNode( + TypedExpressionNode expression, + Source source +) implements TypedFunctionStatementNode { + @Override + public TypedFunctionStatementBehaviour behaviour() { + return TypedFunctionStatementBehaviour.TERMINATE; + } +} diff --git a/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java b/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java index 8564a66d..0d467c0d 100644 --- a/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java +++ b/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java @@ -314,6 +314,9 @@ public class StackCompiler { case TypedFunctionReturnNode functionReturn -> compileFunctionReturn(functionReturn, context); + case TypedResumeNode resume -> + throw new UnsupportedOperationException("TODO"); + case TypedWhileNode while_ -> compileWhile(while_, context); }; diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index 8dbf0927..5e1fc6e2 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -611,7 +611,10 @@ public class TypeChecker { returnType = implicitLowerBound.type(); } case ReturnTypeState.ImplicitUnknown implicitUnknown -> { - throw new UnsupportedOperationException("TODO"); + // If we've reached this point, then there are no returns + // statements, nor a block return, so this function must never + // return. + returnType = Types.BOTTOM; } case ReturnTypeState.NotInFunction notInFunction -> { // TODO: better error @@ -945,7 +948,7 @@ public class TypeChecker { typeCheckAssign(assign, context); case UntypedResumeNode resume -> - throw new UnsupportedOperationException("TODO"); + typeCheckResume(resume, context); case UntypedBlockReturnNode blockReturn -> typeCheckBlockReturn(blockReturn, context); @@ -1274,6 +1277,18 @@ public class TypeChecker { }); } + private static TypeCheckerResult<TypedResumeNode> typeCheckResume( + UntypedResumeNode untyped, + TypeCheckerContext context + ) { + context = typeCheckFunctionReturnValue(Types.UNIT, untyped.source(), context); + + return context.toResult(new TypedResumeNode( + new TypedUnitLiteralNode(untyped.source()), + untyped.source() + )); + } + private static TypeCheckerResult<TypedStringLiteralNode> typeCheckStringLiteral( UntypedStringLiteralNode untyped, TypeCheckerContext context 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 ec392e5c..1c0cad87 100644 --- a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java +++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java @@ -250,6 +250,15 @@ public class TypedNodeMatchers { ); } + public static Matcher<TypedFunctionStatementNode> isTypedResumeNode( + Matcher<TypedExpressionNode> expression + ) { + return instanceOf( + TypedResumeNode.class, + has("expression", x -> x.expression(), expression) + ); + } + public static Matcher<TypedExpressionNode> isTypedStringAddNode( Matcher<TypedExpressionNode> left, Matcher<TypedExpressionNode> right @@ -361,7 +370,7 @@ public class TypedNodeMatchers { return isTypedTypeLevelReferenceNode(name, equalTo(value)); } - public static Matcher<TypedExpressionNode> isTypedUnitNode() { + public static Matcher<TypedExpressionNode> isTypedUnitLiteralNode() { return instanceOf(TypedUnitLiteralNode.class); } diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionReturnTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionReturnTests.java index 32908c34..da130bcc 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionReturnTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionReturnTests.java @@ -37,7 +37,7 @@ public class TypeCheckerFunctionReturnTests { var typed = TypeChecker.typeCheckFunctionStatement(untyped, context); - assertThat(typed.value(), isTypedFunctionReturnNode(isTypedUnitNode())); + assertThat(typed.value(), isTypedFunctionReturnNode(isTypedUnitLiteralNode())); } @Test diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java index d48eaf79..cffae60a 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java @@ -232,8 +232,7 @@ public class TypeCheckerTryTests { .addHandlerField( UntypedFunctionDefinitionNode.builder() .addPositionalParam("x", Untyped.typeLevelReference("String")) - // TODO: support type-checking resume - //.addStatement(Untyped.resume()) + .addStatement(Untyped.resume()) .withName("mark") .build() ) @@ -279,8 +278,7 @@ public class TypeCheckerTryTests { .withHandledEffect(Untyped.typeLevelReference(handledEffect.name())) .addHandlerField( UntypedFunctionDefinitionNode.builder() - // TODO: support type-checking resume - //.addStatement(Untyped.resume()) + .addStatement(Untyped.resume()) .withName("mark") .build() ) @@ -294,7 +292,6 @@ public class TypeCheckerTryTests { ) .enterFunction( P.map( - Map.entry("String", Variable.defined(Types.metaType(Types.STRING), VariableType.CONSTANT)), Map.entry(handledEffect.name(), Variable.defined(Types.effectType(handledEffect), VariableType.CONSTANT)) ), Effects.NONE, @@ -309,7 +306,9 @@ public class TypeCheckerTryTests { .withHandlerFields(isSequence( isTypedFunctionDefinitionNode() .withName("mark") - .withBodyBlock(isTypedBlockNode(isSequence())) + .withBodyBlock(isTypedBlockNode(isSequence( + isTypedResumeNode(isTypedUnitLiteralNode()) + ))) )) ); } diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerUnitLiteralTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerUnitLiteralTests.java index 07f57003..21e35974 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerUnitLiteralTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerUnitLiteralTests.java @@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test; import org.shedlang.compiler.ast.untyped.Untyped; import org.shedlang.compiler.types.Types; -import static org.shedlang.compiler.ast.typed.TypedNodeMatchers.isTypedUnitNode; +import static org.shedlang.compiler.ast.typed.TypedNodeMatchers.isTypedUnitLiteralNode; import static org.shedlang.compiler.typechecker.TypeCheckerTesting.typeCheckExpression; import static org.zwobble.precisely.AssertThat.assertThat; import static org.zwobble.precisely.Matchers.equalTo; @@ -16,7 +16,7 @@ public class TypeCheckerUnitLiteralTests { var typed = typeCheckExpression(untyped, TypeCheckerContext.EMPTY); - assertThat(typed.value(), isTypedUnitNode()); + assertThat(typed.value(), isTypedUnitLiteralNode()); assertThat(typed.value().type(), equalTo(Types.UNIT)); } } |
