aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-11-07 16:41:51 +0000
committerMichael Williamson <mike@zwobble.org>2023-11-07 16:41:51 +0000
commit188006a7a103106924fd7e16edb1cafb352eb78c (patch)
treeca04a8b711c020f1bbd3c5517dfee939c8afe39d /src
parentc22e9652e8a2904829bc7d5586074f38ded966f3 (diff)
Add (unsound) basic type-checking for resume statements
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionStatementNode.java2
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedResumeNode.java13
-rw-r--r--src/main/java/org/shedlang/compiler/stackir/StackCompiler.java3
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java19
-rw-r--r--src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java11
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionReturnTests.java2
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerTryTests.java11
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerUnitLiteralTests.java4
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));
}
}