diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-07-19 14:44:13 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-07-19 14:44:13 +0100 |
| commit | 813d4b15f404ace15684a474404ae88563d27579 (patch) | |
| tree | ad9b22af77fe7f96f2e2a5b3bd9b65026a7e7700 /src/main/java | |
| parent | b2aab81fd37cc37ca96ec17d6bf2a92e77f35819 (diff) | |
Bodge together proper checks for dependencies between statements
Diffstat (limited to 'src/main/java')
| -rw-r--r-- | src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index 73bd8eb7..0584509e 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -4,6 +4,7 @@ import org.pcollections.PVector; import org.shedlang.compiler.ast.typed.*; import org.shedlang.compiler.ast.untyped.*; import org.shedlang.compiler.sources.Source; +import org.shedlang.compiler.sources.Sources; import org.shedlang.compiler.typechecker.errors.*; import org.shedlang.compiler.typechecker.typesets.TypeSetTypeLevelValue; import org.shedlang.compiler.typechecker.typesets.TypeSets; @@ -12,6 +13,7 @@ import org.shedlang.compiler.util.P; import org.shedlang.compiler.util.PCollectors; import java.util.*; +import java.util.stream.Collectors; import java.util.stream.Stream; public class TypeChecker { @@ -84,7 +86,7 @@ public class TypeChecker { variables; case UntypedValNode val -> - declaredVariables(val.target(), variables); + declaredVariables(val, variables); }; } @@ -97,10 +99,17 @@ public class TypeChecker { variables.plus(functionDefinition); case UntypedValNode val -> - declaredVariables(val.target(), variables); + declaredVariables(val, variables); }; } + static PVector<UntypedVariableDeclarationNode> declaredVariables( + UntypedValNode statement, + PVector<UntypedVariableDeclarationNode> variables + ) { + return declaredVariables(statement.target(), variables); + } + private static PVector<UntypedVariableDeclarationNode> declaredVariables( UntypedTargetNode target, PVector<UntypedVariableDeclarationNode> variables @@ -628,6 +637,12 @@ public class TypeChecker { context = typeCheckSteps.declareFunctions(context); } + var dependencies = new ArrayList<Set<String>>(); + var variableNames = untyped.body().stream() + .flatMap(untypedStatement -> declaredVariables(untypedStatement, P.vector()).stream()) + .map(declaration -> declaration.name()) + .collect(Collectors.toSet()); + for (var typeCheckSteps : typeCheckStepSets) { context = context.enterFreeVariableCapture(); @@ -640,6 +655,65 @@ public class TypeChecker { context = freeVariablesResult.context(); typedBody.add(typedStatement); + + var freeVariableNames = freeVariables.stream() + .filter(freeVariable -> variableNames.contains(freeVariable.name())) + .map(freeVariable -> freeVariable.name()) + .collect(Collectors.toSet()); + dependencies.add(freeVariableNames); + } + + var deferredDependencies = new HashMap<String, Set<String>>(); + for (var i = 0; i < untyped.body().size(); i++) { + var untypedStatement = untyped.body().get(i); + if (untypedStatement instanceof UntypedFunctionDefinitionNode functionDefinition) { + var freeVariables = dependencies.get(i); + deferredDependencies.put(functionDefinition.name(), freeVariables); + } + } + + var state = new Object() { + HashSet<String> defined = new HashSet<>(); + + void define(String name) { + defined.add(name); + } + + void require(String name) { + if (defined.contains(name)) { + return; + } + + var freeVariables = deferredDependencies.get(name); + + if (freeVariables == null) { + // TODO: fix source + throw new ReferenceBeforeDefinitionError(name, Sources.NULL); + } + + for (var dependency : freeVariables) { + require(dependency); + } + } + }; + + for (var i = 0; i < untyped.body().size(); i++) { + var untypedStatement = untyped.body().get(i); + var freeVariables = dependencies.get(i); + + switch (untypedStatement) { + case UntypedFunctionDefinitionNode functionDefinition -> { + } + case UntypedValNode val -> { + for (var freeVariable : freeVariables) { + state.require(freeVariable); + } + + for (var declaredVariable : declaredVariables(val, P.vector())) { + state.define(declaredVariable.name()); + } + } + } } var fieldTypes = typedBody.stream() |
