diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-07-17 22:49:34 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-07-17 22:49:34 +0100 |
| commit | dbcedbdd60d5bf9be5536699e83272879afa81eb (patch) | |
| tree | 910d5e926c5264e4371510c2c97c6bc34cc4a6ce /src/main/java | |
| parent | ecbe7b4a85c23ba0520d5ff6e2682efd889848e9 (diff) | |
Check that variable is declared and defined in same scope
Diffstat (limited to 'src/main/java')
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; + } +} |
