diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-06-09 18:15:27 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-06-09 18:15:27 +0100 |
| commit | 92bcb4b11954348daa759eb967d2b15c12744dc5 (patch) | |
| tree | 99c02a547451d45bc46a9494e0de00913ecafc18 /src/main/java | |
| parent | f8174b842a7b2fdab34146c543dade8f92e45b1d (diff) | |
Type check references
Diffstat (limited to 'src/main/java')
6 files changed, 101 insertions, 4 deletions
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java index f7ce02dc..73ad8991 100644 --- a/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java +++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedExpressionNode.java @@ -3,7 +3,7 @@ package org.shedlang.compiler.ast.typed; import org.shedlang.compiler.sources.Source; import org.shedlang.compiler.types.Type; -public sealed interface TypedExpressionNode permits TypedStringLiteralNode { +public sealed interface TypedExpressionNode permits TypedReferenceNode, TypedStringLiteralNode { Source source(); Type type(); } diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedReferenceNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedReferenceNode.java new file mode 100644 index 00000000..767cf814 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedReferenceNode.java @@ -0,0 +1,11 @@ +package org.shedlang.compiler.ast.typed; + +import org.shedlang.compiler.sources.Source; +import org.shedlang.compiler.types.Type; + +public record TypedReferenceNode( + String name, + Type type, + Source source +) implements TypedExpressionNode { +} diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index d37eb347..a030f117 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -1,6 +1,7 @@ package org.shedlang.compiler.typechecker; import org.shedlang.compiler.ast.typed.TypedExpressionNode; +import org.shedlang.compiler.ast.typed.TypedReferenceNode; import org.shedlang.compiler.ast.typed.TypedStringLiteralNode; import org.shedlang.compiler.ast.untyped.UntypedCallNode; import org.shedlang.compiler.ast.untyped.UntypedExpressionNode; @@ -17,13 +18,39 @@ public class TypeChecker { ) { return switch (untyped) { case UntypedStringLiteralNode untypedStringLiteral -> - new TypedStringLiteralNode(untypedStringLiteral.value(), untypedStringLiteral.source()); + typeCheckStringLiteral(untypedStringLiteral); case UntypedCallNode untypedCall -> throw new UnsupportedOperationException("TODO"); case UntypedReferenceNode untypedReference -> - throw new UnsupportedOperationException("TODO"); + typeCheckReference(untypedReference, context); }; } + + private static TypedReferenceNode typeCheckReference( + UntypedReferenceNode untyped, + TypeCheckerContext context + ) { + var type = context.environment(untyped.name()); + + if (type.isEmpty()) { + throw new UnknownVariableError(untyped.name(), untyped.source()); + } + + return new TypedReferenceNode( + untyped.name(), + type.get(), + untyped.source() + ); + } + + private static TypedStringLiteralNode typeCheckStringLiteral( + UntypedStringLiteralNode untypedStringLiteral + ) { + return new TypedStringLiteralNode( + untypedStringLiteral.value(), + untypedStringLiteral.source() + ); + } } diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java index 261e3e95..c130b0d3 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java @@ -1,5 +1,27 @@ package org.shedlang.compiler.typechecker; +import org.pcollections.Empty; +import org.pcollections.PMap; +import org.shedlang.compiler.types.Type; + +import java.util.Optional; + public class TypeCheckerContext { - public static final TypeCheckerContext EMPTY = new TypeCheckerContext(); + public static final TypeCheckerContext EMPTY = new TypeCheckerContext( + Empty.map() + ); + + private final PMap<String, Type> environment; + + public TypeCheckerContext(PMap<String, Type> environment) { + this.environment = environment; + } + + public TypeCheckerContext enter(PMap<String, Type> environment) { + return new TypeCheckerContext(this.environment.plusAll(environment)); + } + + public Optional<Type> environment(String name) { + return Optional.ofNullable(environment.get(name)); + } } diff --git a/src/main/java/org/shedlang/compiler/typechecker/UnknownVariableError.java b/src/main/java/org/shedlang/compiler/typechecker/UnknownVariableError.java new file mode 100644 index 00000000..91ab3fae --- /dev/null +++ b/src/main/java/org/shedlang/compiler/typechecker/UnknownVariableError.java @@ -0,0 +1,17 @@ +package org.shedlang.compiler.typechecker; + +import org.shedlang.compiler.errors.SourceError; +import org.shedlang.compiler.sources.Source; + +public class UnknownVariableError extends SourceError { + private final String variableName; + + public UnknownVariableError(String variableName, Source source) { + super("Unknown variable: " + variableName, source); + this.variableName = variableName; + } + + public String variableName() { + return variableName; + } +} diff --git a/src/main/java/org/shedlang/compiler/util/P.java b/src/main/java/org/shedlang/compiler/util/P.java new file mode 100644 index 00000000..7ce8232c --- /dev/null +++ b/src/main/java/org/shedlang/compiler/util/P.java @@ -0,0 +1,20 @@ +package org.shedlang.compiler.util; + +import org.pcollections.HashTreePMap; +import org.pcollections.PMap; + +import java.util.Map; + +public class P { + private P() { + } + + @SafeVarargs + public static <K, V> PMap<K, V> map(Map.Entry<K, V>... entries) { + var map = HashTreePMap.<K, V>empty(); + for (var entry : entries) { + map = map.plus(entry.getKey(), entry.getValue()); + } + return map; + } +} |
