diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-07-02 12:19:46 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-07-02 12:19:46 +0100 |
| commit | 71a8ca11b03331a92bb271cbd1fbcb877e587300 (patch) | |
| tree | 3a73642a3285bca6b0049656ba8d421f548c4bfb /src/main/java | |
| parent | 1f86ef817b64e5e78ed92dd767fa38306c7662b5 (diff) | |
Check call to function with effect is marked with effects
Diffstat (limited to 'src/main/java')
8 files changed, 49 insertions, 6 deletions
diff --git a/src/main/java/org/shedlang/compiler/ShedCompiler.java b/src/main/java/org/shedlang/compiler/ShedCompiler.java index bf26436e..d727aea5 100644 --- a/src/main/java/org/shedlang/compiler/ShedCompiler.java +++ b/src/main/java/org/shedlang/compiler/ShedCompiler.java @@ -42,6 +42,7 @@ public class ShedCompiler { Map.entry("print", new FunctionType( List.of(Types.STRING), List.of(), + Effects.IO, Types.UNIT )) )) @@ -52,6 +53,7 @@ public class ShedCompiler { Map.entry("print", new FunctionType( List.of(Types.STRING), List.of(), + Effects.IO, Types.UNIT )) )); 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 417b9ad6..42783224 100644 --- a/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionDefinitionNode.java +++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionDefinitionNode.java @@ -42,6 +42,7 @@ public record TypedFunctionDefinitionNode( params.named().stream() .map(param -> new NamedParam(param.name(), param.type().value())) .toList(), + effect.map(e -> e.value()).orElse(Effects.NONE), returnType.value() ), source diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index 770b7063..4d2b7326 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -142,6 +142,10 @@ public class TypeChecker { var typedArgs = argsResult.value(); context = argsResult.context(); + if (!receiverType.effect().equals(Effects.NONE) && !untyped.hasEffects()) { + throw new CallIsMissingEffectsError(receiverType.effect(), untyped.source()); + } + return context.toResult(new TypedCallNode( typedReceiver, typedArgs, diff --git a/src/main/java/org/shedlang/compiler/typechecker/errors/CallIsMissingEffectsError.java b/src/main/java/org/shedlang/compiler/typechecker/errors/CallIsMissingEffectsError.java new file mode 100644 index 00000000..083d9a03 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/typechecker/errors/CallIsMissingEffectsError.java @@ -0,0 +1,18 @@ +package org.shedlang.compiler.typechecker.errors; + +import org.shedlang.compiler.errors.SourceError; +import org.shedlang.compiler.sources.Source; +import org.shedlang.compiler.types.Effect; + +public class CallIsMissingEffectsError extends SourceError { + private final Effect effect; + + public CallIsMissingEffectsError(Effect effect, Source source) { + super("Function has effect, but call is missing effect: " + effect.describe(), source); + this.effect = effect; + } + + public Effect effect() { + return effect; + } +} diff --git a/src/main/java/org/shedlang/compiler/types/Effect.java b/src/main/java/org/shedlang/compiler/types/Effect.java index 257a3847..7e8bc203 100644 --- a/src/main/java/org/shedlang/compiler/types/Effect.java +++ b/src/main/java/org/shedlang/compiler/types/Effect.java @@ -1,4 +1,4 @@ package org.shedlang.compiler.types; -public sealed interface Effect extends TypeLevelValue permits IoEffect { +public sealed interface Effect extends TypeLevelValue permits IoEffect, NoneEffect { } diff --git a/src/main/java/org/shedlang/compiler/types/Effects.java b/src/main/java/org/shedlang/compiler/types/Effects.java index 820d31c5..c894a58b 100644 --- a/src/main/java/org/shedlang/compiler/types/Effects.java +++ b/src/main/java/org/shedlang/compiler/types/Effects.java @@ -4,5 +4,7 @@ public class Effects { private Effects() { } + public static final Effect NONE = NoneEffect.INSTANCE; + public static final Effect IO = IoEffect.INSTANCE; } diff --git a/src/main/java/org/shedlang/compiler/types/FunctionType.java b/src/main/java/org/shedlang/compiler/types/FunctionType.java index 22d3487b..e40439f7 100644 --- a/src/main/java/org/shedlang/compiler/types/FunctionType.java +++ b/src/main/java/org/shedlang/compiler/types/FunctionType.java @@ -8,10 +8,11 @@ import java.util.List; public record FunctionType( List<Type> positionalParams, List<NamedParam> namedParams, + Effect effect, Type returnType ) implements Type { public static Builder builder() { - return new Builder(Empty.vector(), Empty.vector(), Types.UNIT); + return new Builder(Empty.vector(), Empty.vector(), Effects.NONE, Types.UNIT); } @Override @@ -23,23 +24,28 @@ public record FunctionType( public record Builder( PVector<Type> positionalParams, PVector<NamedParam> namedParams, + Effect effect, Type returnType ) { public FunctionType build() { - return new FunctionType(positionalParams, namedParams, returnType); + return new FunctionType(positionalParams, namedParams, effect, returnType); } public Builder addNamedParam(String name, Type type) { var namedParam = new NamedParam(name, type); - return new Builder(positionalParams, namedParams.plus(namedParam), returnType); + return new Builder(positionalParams, namedParams.plus(namedParam), effect, returnType); } public Builder addPositionalParam(Type type) { - return new Builder(positionalParams.plus(type), namedParams, returnType); + return new Builder(positionalParams.plus(type), namedParams, effect, returnType); + } + + public Builder withEffect(Effect effect) { + return new Builder(positionalParams, namedParams, effect, returnType); } public Builder withReturnType(Type returnType) { - return new Builder(positionalParams, namedParams, returnType); + return new Builder(positionalParams, namedParams, effect, returnType); } } } diff --git a/src/main/java/org/shedlang/compiler/types/NoneEffect.java b/src/main/java/org/shedlang/compiler/types/NoneEffect.java new file mode 100644 index 00000000..e6fe5f95 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/types/NoneEffect.java @@ -0,0 +1,10 @@ +package org.shedlang.compiler.types; + +public record NoneEffect() implements Effect { + static final NoneEffect INSTANCE = new NoneEffect(); + + @Override + public String describe() { + return "None"; + } +} |
