From 9993f60f036824c6c5c437591148b4cd8ef2dc50 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sat, 4 Nov 2023 15:12:52 +0000 Subject: Create effect type when type checking effect definition node --- .../ast/typed/TypedEffectDefinitionNode.java | 10 +++++++ .../ast/typed/TypedNamespaceStatementNode.java | 2 +- .../ast/untyped/UntypedEffectDefinitionNode.java | 33 ++++++++++++++++++++++ .../shedlang/compiler/stackir/StackCompiler.java | 6 ++++ .../shedlang/compiler/typechecker/TypeChecker.java | 31 +++++++++++++++++++- .../CannotDefineEffectOutsideOfNamespaceError.java | 10 +++++++ .../java/org/shedlang/compiler/types/Effects.java | 7 +++++ 7 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/shedlang/compiler/ast/typed/TypedEffectDefinitionNode.java create mode 100644 src/main/java/org/shedlang/compiler/typechecker/errors/CannotDefineEffectOutsideOfNamespaceError.java (limited to 'src/main/java') diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedEffectDefinitionNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedEffectDefinitionNode.java new file mode 100644 index 00000000..1e858885 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedEffectDefinitionNode.java @@ -0,0 +1,10 @@ +package org.shedlang.compiler.ast.typed; + +import org.shedlang.compiler.sources.Source; +import org.shedlang.compiler.types.UserDefinedEffect; + +public record TypedEffectDefinitionNode( + UserDefinedEffect effect, + Source source +) implements TypedNamespaceStatementNode { +} diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedNamespaceStatementNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedNamespaceStatementNode.java index 654e073d..79c69548 100644 --- a/src/main/java/org/shedlang/compiler/ast/typed/TypedNamespaceStatementNode.java +++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedNamespaceStatementNode.java @@ -1,4 +1,4 @@ package org.shedlang.compiler.ast.typed; -public sealed interface TypedNamespaceStatementNode extends TypedNode permits TypedAssignNode, TypedFunctionDefinitionNode, TypedStructDefinitionNode, TypedSumTypeDefinitionNode { +public sealed interface TypedNamespaceStatementNode extends TypedNode permits TypedAssignNode, TypedEffectDefinitionNode, TypedFunctionDefinitionNode, TypedStructDefinitionNode, TypedSumTypeDefinitionNode { } diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedEffectDefinitionNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedEffectDefinitionNode.java index 48e6fdf0..5731aefe 100644 --- a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedEffectDefinitionNode.java +++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedEffectDefinitionNode.java @@ -1,7 +1,10 @@ package org.shedlang.compiler.ast.untyped; +import org.pcollections.PVector; import org.shedlang.compiler.sources.Source; +import org.shedlang.compiler.sources.Sources; import org.shedlang.compiler.types.Visibility; +import org.shedlang.compiler.util.P; import java.util.List; @@ -11,4 +14,34 @@ public record UntypedEffectDefinitionNode( List functions, Source source ) implements UntypedNamespaceStatementNode, UntypedVariableDeclarationNode { + public static Builder builder() { + return new Builder( + "E", + Visibility.PRIVATE, + P.vector() + ); + } + + public record Builder( + String name, + Visibility visibility, + PVector functions + ) { + public UntypedEffectDefinitionNode build() { + return new UntypedEffectDefinitionNode( + name, + visibility, + functions, + Sources.NULL + ); + } + + public Builder withName(String name) { + return new Builder( + name, + this.visibility, + this.functions + ); + } + } } diff --git a/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java b/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java index ecb32acd..7080cde2 100644 --- a/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java +++ b/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java @@ -407,6 +407,9 @@ public class StackCompiler { case TypedAssignNode assign -> 1; + case TypedEffectDefinitionNode effectDefinition -> + 0; + case TypedFunctionDefinitionNode functionDefinition -> 1; @@ -440,6 +443,9 @@ public class StackCompiler { case TypedAssignNode assign -> compileAssign(assign, context); + case TypedEffectDefinitionNode effectDefinition -> + throw new UnsupportedOperationException("TODO"); + case TypedFunctionDefinitionNode functionDefinition -> compileFunctionDefinition(functionDefinition, context); diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index b115f529..5c104fe1 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -388,6 +388,35 @@ public class TypeChecker { return typeCheckTypeLevelExpression(TypeSets.EFFECT, untyped, context); } + private static TypeCheckSteps typeCheckStepsEffectDefinition( + UntypedEffectDefinitionNode untyped + ) { + return new TypeCheckSteps() { + @Override + public TypeCheckerContext declareTypes(TypeCheckerContext context) { + var namespaceName = context.namespaceName() + .orElseThrow(() -> new CannotDefineEffectOutsideOfNamespaceError(untyped.source())); + + var effect = new UserDefinedEffect(namespaceName, untyped.name()); + + return context + .addLexicalState(untyped.name(), effect) + .declareVariableType( + untyped.name(), + Types.effectType(effect), + untyped.source() + ); + } + + @Override + public TypeCheckerResult finish(TypeCheckerContext context) { + var effect = context.getLexicalState(UserDefinedEffect.class, untyped.name()); + + return context.toResult(new TypedEffectDefinitionNode(effect, untyped.source())); + } + }; + } + public static TypeCheckerResult typeCheckExpression( UntypedExpressionNode untyped, Optional hint, @@ -1148,7 +1177,7 @@ public class TypeChecker { typeCheckStepsAssign(assign); case UntypedEffectDefinitionNode effectDefinition -> - throw new UnsupportedOperationException("TODO"); + typeCheckStepsEffectDefinition(effectDefinition); case UntypedFunctionDefinitionNode functionDefinition -> typeCheckStepsFunctionDefinition(functionDefinition); diff --git a/src/main/java/org/shedlang/compiler/typechecker/errors/CannotDefineEffectOutsideOfNamespaceError.java b/src/main/java/org/shedlang/compiler/typechecker/errors/CannotDefineEffectOutsideOfNamespaceError.java new file mode 100644 index 00000000..1777afbe --- /dev/null +++ b/src/main/java/org/shedlang/compiler/typechecker/errors/CannotDefineEffectOutsideOfNamespaceError.java @@ -0,0 +1,10 @@ +package org.shedlang.compiler.typechecker.errors; + +import org.shedlang.compiler.errors.InternalCompilerError; +import org.shedlang.compiler.sources.Source; + +public class CannotDefineEffectOutsideOfNamespaceError extends InternalCompilerError { + public CannotDefineEffectOutsideOfNamespaceError(Source source) { + super("Cannot define effect outside of namespace", source); + } +} diff --git a/src/main/java/org/shedlang/compiler/types/Effects.java b/src/main/java/org/shedlang/compiler/types/Effects.java index c894a58b..206574d7 100644 --- a/src/main/java/org/shedlang/compiler/types/Effects.java +++ b/src/main/java/org/shedlang/compiler/types/Effects.java @@ -7,4 +7,11 @@ public class Effects { public static final Effect NONE = NoneEffect.INSTANCE; public static final Effect IO = IoEffect.INSTANCE; + + public static UserDefinedEffect userDefined( + NamespaceName namespaceName, + String name + ) { + return new UserDefinedEffect(namespaceName, name); + } } -- cgit v1.2.3