aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-10-29 18:02:04 +0000
committerMichael Williamson <mike@zwobble.org>2023-10-29 18:02:04 +0000
commit9d15f1601242707953864e687a261932a6bf84ea (patch)
treec2470b56785e6243e05af24d87c8458cf628fdbb /src/main/java
parentd19e7debea80e9216923935ef03c8607d7c1d9ec (diff)
Support inferring return type from single return statement
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionBodyNode.java5
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionDefinitionNode.java1
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionExpressionNode.java1
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java28
4 files changed, 29 insertions, 6 deletions
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionBodyNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionBodyNode.java
index 415d4502..01225d71 100644
--- a/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionBodyNode.java
+++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionBodyNode.java
@@ -8,6 +8,7 @@ import java.util.List;
public record TypedFunctionBodyNode(
FreeVariables freeVariables,
TypedBlockNode block,
+ Type type,
Source source
) implements TypedNode {
public List<String> boundVariableNames() {
@@ -17,8 +18,4 @@ public record TypedFunctionBodyNode(
public TypedFunctionStatementBehaviour behaviour() {
return block.behaviour();
}
-
- public Type type() {
- return block.type();
- }
}
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionDefinitionNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionDefinitionNode.java
index 889b4fee..eb664e71 100644
--- a/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionDefinitionNode.java
+++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionDefinitionNode.java
@@ -41,6 +41,7 @@ public record TypedFunctionDefinitionNode(
new TypedFunctionBodyNode(
freeVariables.build(),
new TypedBlockNode(body, boundVariableNames, Sources.NULL),
+ Types.UNIT,
Sources.NULL
),
type,
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionExpressionNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionExpressionNode.java
index 401f4009..e11c35d0 100644
--- a/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionExpressionNode.java
+++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionExpressionNode.java
@@ -37,6 +37,7 @@ public record TypedFunctionExpressionNode(
new TypedFunctionBodyNode(
freeVariables.build(),
new TypedBlockNode(body, boundVariableNames, Sources.NULL),
+ Types.UNIT,
Sources.NULL
),
type,
diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
index a68cc23c..b444a3a5 100644
--- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
@@ -498,7 +498,10 @@ public class TypeChecker {
var typedBody = bodyResult.value();
context = bodyResult.context();
+ Type returnType;
if (explicitReturnType.isPresent()) {
+ returnType = explicitReturnType.get();
+
switch (typedBody.behaviour()) {
case TypedFunctionStatementBehaviour.BlockReturn blockReturn -> {
if (!isSubType(blockReturn.type(), explicitReturnType.get(), context)) {
@@ -529,12 +532,16 @@ public class TypeChecker {
case TypedFunctionStatementBehaviour.Continue continue_ -> {
switch (context.returnTypeState()) {
case ReturnTypeState.Explicit explicit -> {
- throw new UnsupportedOperationException("TODO");
+ // TODO: better error
+ throw new IllegalStateException();
}
case ReturnTypeState.ImplicitUnknown implicitUnknown -> {
// No explicit returns.
+ returnType = Types.UNIT;
}
case ReturnTypeState.ImplicitLowerBound implicitLowerBound -> {
+ returnType = implicitLowerBound.type();
+
checkIsSubType(
Types.UNIT,
implicitLowerBound.type(),
@@ -549,7 +556,23 @@ public class TypeChecker {
}
}
case TypedFunctionStatementBehaviour.Terminate terminate -> {
- throw new UnsupportedOperationException("TODO");
+ switch (context.returnTypeState()) {
+ case ReturnTypeState.Explicit explicit -> {
+ // TODO: better error
+ throw new IllegalStateException();
+ }
+ case ReturnTypeState.ImplicitUnknown implicitUnknown -> {
+ // TODO: better error
+ throw new IllegalStateException();
+ }
+ case ReturnTypeState.ImplicitLowerBound implicitLowerBound -> {
+ returnType = implicitLowerBound.type();
+ }
+ case ReturnTypeState.NotInFunction notInFunction -> {
+ // TODO: better error
+ throw new IllegalStateException();
+ }
+ }
}
}
}
@@ -562,6 +585,7 @@ public class TypeChecker {
var typed = new TypedFunctionBodyNode(
freeVariables,
typedBody,
+ returnType,
typedBody.source()
);