From 9d15f1601242707953864e687a261932a6bf84ea Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 29 Oct 2023 18:02:04 +0000 Subject: Support inferring return type from single return statement --- .../compiler/ast/typed/TypedFunctionBodyNode.java | 5 +--- .../ast/typed/TypedFunctionDefinitionNode.java | 1 + .../ast/typed/TypedFunctionExpressionNode.java | 1 + .../shedlang/compiler/typechecker/TypeChecker.java | 28 ++++++++++++++++++++-- 4 files changed, 29 insertions(+), 6 deletions(-) (limited to 'src/main/java') 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 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() ); -- cgit v1.2.3