aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-07-19 14:44:13 +0100
committerMichael Williamson <mike@zwobble.org>2023-07-19 14:44:13 +0100
commit813d4b15f404ace15684a474404ae88563d27579 (patch)
treead9b22af77fe7f96f2e2a5b3bd9b65026a7e7700 /src/main/java
parentb2aab81fd37cc37ca96ec17d6bf2a92e77f35819 (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.java78
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()