aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-07-17 22:49:34 +0100
committerMichael Williamson <mike@zwobble.org>2023-07-17 22:49:34 +0100
commitdbcedbdd60d5bf9be5536699e83272879afa81eb (patch)
tree910d5e926c5264e4371510c2c97c6bc34cc4a6ce /src/main/java
parentecbe7b4a85c23ba0520d5ff6e2682efd889848e9 (diff)
Check that variable is declared and defined in same scope
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java27
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java6
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/errors/CannotDefineVariableDeclaredInOuterScopeError.java17
3 files changed, 39 insertions, 11 deletions
diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
index 391d8e0c..8758ad6a 100644
--- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
@@ -226,19 +226,16 @@ public class TypeChecker {
UntypedBlockNode untyped,
TypeCheckerContext context
) {
- // TODO: get environment and pass to enterBlock()
- var bodyContext = context.enterBlock(P.map());
-
- var typedStatementsResult = bodyContext.mapWithContext(
+ var typedStatementsResult = context.mapWithContext(
untyped.statements(),
TypeChecker::typeCheckFunctionStatement
);
var typedStatements = typedStatementsResult.value();
- bodyContext = typedStatementsResult.context();
+ context = typedStatementsResult.context();
var typed = new TypedBlockNode(typedStatements, untyped.source());
- return context.exit(bodyContext).toResult(typed);
+ return context.toResult(typed);
}
private static TypeCheckerResult<TypedFunctionStatementNode> typeCheckBlockReturn(
@@ -320,9 +317,14 @@ public class TypeChecker {
checkExpressionType(typedCondition, Types.BOOL, context);
- var typedBodyResult = typeCheckBlock(conditionalBranch.body(), context);
+ // TODO: get environment and pass to enterBlock()
+ var bodyContext = context.enterBlock(P.map());
+
+ var typedBodyResult = typeCheckBlock(conditionalBranch.body(), bodyContext);
var typedBody = typedBodyResult.value();
- context = typedBodyResult.context();
+ bodyContext = typedBodyResult.context();
+
+ context = context.exit(bodyContext);
return context.toResult(new TypedConditionalBranchNode(
typedCondition,
@@ -506,9 +508,14 @@ public class TypeChecker {
var typedConditionalBranches = typedConditionalBranchesResult.value();
context = typedConditionalBranchesResult.context();
- var typedElseBodyResult = typeCheckBlock(untyped.elseBody(), context);
+ // TODO: get environment and pass to enterBlock()
+ var bodyContext = context.enterBlock(P.map());
+
+ var typedElseBodyResult = typeCheckBlock(untyped.elseBody(), bodyContext);
var typedElseBody = typedElseBodyResult.value();
- context = typedElseBodyResult.context();
+ bodyContext = typedElseBodyResult.context();
+
+ context = context.exit(bodyContext);
var branchTypes = Stream.concat(
typedConditionalBranches.stream()
diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java
index 6f626725..2a5423db 100644
--- a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java
+++ b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java
@@ -4,6 +4,7 @@ import org.pcollections.Empty;
import org.pcollections.PMap;
import org.shedlang.compiler.ast.typed.FreeVariables;
import org.shedlang.compiler.sources.Source;
+import org.shedlang.compiler.typechecker.errors.CannotDefineVariableDeclaredInOuterScopeError;
import org.shedlang.compiler.typechecker.errors.UnknownVariableError;
import org.shedlang.compiler.typechecker.errors.VariableIsAlreadyDefinedError;
import org.shedlang.compiler.types.*;
@@ -142,7 +143,10 @@ public class TypeCheckerContext {
throw new VariableIsAlreadyDefinedError(name, source);
}
case Variable.Undefined undefined -> {
- // TODO: check is declared in this scope
+ if (!this.boundVariables.contains(name)) {
+ throw new CannotDefineVariableDeclaredInOuterScopeError(name, source);
+ }
+
return new TypeCheckerContext(
this.environment.plus(name, new Variable.Defined(type)),
this.effect,
diff --git a/src/main/java/org/shedlang/compiler/typechecker/errors/CannotDefineVariableDeclaredInOuterScopeError.java b/src/main/java/org/shedlang/compiler/typechecker/errors/CannotDefineVariableDeclaredInOuterScopeError.java
new file mode 100644
index 00000000..7002c637
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/typechecker/errors/CannotDefineVariableDeclaredInOuterScopeError.java
@@ -0,0 +1,17 @@
+package org.shedlang.compiler.typechecker.errors;
+
+import org.shedlang.compiler.errors.SourceError;
+import org.shedlang.compiler.sources.Source;
+
+public class CannotDefineVariableDeclaredInOuterScopeError extends SourceError {
+ private final String variableName;
+
+ public CannotDefineVariableDeclaredInOuterScopeError(String variableName, Source source) {
+ super("Cannot define variable declared in outer scope: " + variableName, source);
+ this.variableName = variableName;
+ }
+
+ public String variableName() {
+ return variableName;
+ }
+}