diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-07-03 12:40:22 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-07-03 12:40:22 +0100 |
| commit | c08dc7894a1b78a59fdd0372f3090c46b20b5b7d (patch) | |
| tree | b2c6e1983c8c385398458ee6e65b6ac135ad8793 /src/main/java | |
| parent | 28b744b0039e381e197f46cea0e5e87ac4b8bab2 (diff) | |
Extract EnvironmentBuilder
Diffstat (limited to 'src/main/java')
3 files changed, 43 insertions, 16 deletions
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedParamsNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedParamsNode.java index f2601644..f7273497 100644 --- a/src/main/java/org/shedlang/compiler/ast/typed/TypedParamsNode.java +++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedParamsNode.java @@ -3,6 +3,7 @@ package org.shedlang.compiler.ast.typed; import org.shedlang.compiler.sources.Source; import java.util.List; +import java.util.stream.Collectors; import java.util.stream.Stream; public record TypedParamsNode( @@ -10,7 +11,8 @@ public record TypedParamsNode( List<TypedParamNode> named, Source source ) implements TypedNode { - public Stream<TypedParamNode> all() { - return Stream.concat(positional.stream(), named.stream()); + public Iterable<TypedParamNode> all() { + return Stream.concat(positional.stream(), named.stream()) + .collect(Collectors.toList()); } } diff --git a/src/main/java/org/shedlang/compiler/typechecker/EnvironmentBuilder.java b/src/main/java/org/shedlang/compiler/typechecker/EnvironmentBuilder.java new file mode 100644 index 00000000..4ac46d2a --- /dev/null +++ b/src/main/java/org/shedlang/compiler/typechecker/EnvironmentBuilder.java @@ -0,0 +1,27 @@ +package org.shedlang.compiler.typechecker; + +import org.pcollections.Empty; +import org.pcollections.PMap; +import org.shedlang.compiler.sources.Source; +import org.shedlang.compiler.typechecker.errors.DuplicateVariableName; + +public class EnvironmentBuilder { + public static final EnvironmentBuilder EMPTY = new EnvironmentBuilder(Empty.map()); + + private PMap<String, TypeCheckerContext.Variable> environment; + + private EnvironmentBuilder(PMap<String, TypeCheckerContext.Variable> environment) { + this.environment = environment; + } + + public EnvironmentBuilder add(String name, TypeCheckerContext.Variable variable, Source source) { + if (environment.containsKey(name)) { + throw new DuplicateVariableName(name, source); + } + return new EnvironmentBuilder(environment.plus(name, variable)); + } + + public PMap<String, TypeCheckerContext.Variable> build() { + return environment; + } +} diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index bf09b84b..e7688898 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -259,30 +259,28 @@ public class TypeChecker { var typedReturnType = typeCheckTypeLevelExpression(TypeSets.META_TYPE, untyped.returnType(), context); + var bodyEnvironment = EnvironmentBuilder.EMPTY; // TODO: check for duplicate param names - var bodyEnvironment = typedParams.all() - .map(param -> Map.entry( + + for (var param : typedParams.all()) { + bodyEnvironment = bodyEnvironment.add( param.name(), - TypeCheckerContext.defined(param.type().value()) - )) - .collect(PCollectors.toMap()); + TypeCheckerContext.defined(param.type().value()), + param.source() + ); + } for (var statement : untyped.body()) { for (var targetVariable : targetVariables(statement)) { - if (bodyEnvironment.containsKey(targetVariable.name())) { - throw new DuplicateVariableName( - targetVariable.name(), - targetVariable.source() - ); - } - bodyEnvironment = bodyEnvironment.plus( + bodyEnvironment = bodyEnvironment.add( targetVariable.name(), - TypeCheckerContext.undefined() + TypeCheckerContext.undefined(), + targetVariable.source() ); } } - var bodyContext = context.enterFunction(bodyEnvironment, typedEffect.map(e -> e.value()).orElse(Effects.NONE)); + var bodyContext = context.enterFunction(bodyEnvironment.build(), typedEffect.map(e -> e.value()).orElse(Effects.NONE)); var bodyResult = bodyContext.mapWithContext( untyped.body(), |
