diff options
| author | Michael Williamson <mike@zwobble.org> | 2015-10-04 17:52:29 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2015-10-04 17:52:29 +0100 |
| commit | b74d68227dc7c05e24705e3064ef961f95b8b729 (patch) | |
| tree | 70601bc83d1105c6748a062bd6ffe41ecfe68acc /src/main/java/org/zwobble/couscous/interpreter/Environment.java | |
| parent | 8d2374ba254e637c22e6f1eaa58ccb54d814529f (diff) | |
Throw exception if assigning value of wrong type
Diffstat (limited to 'src/main/java/org/zwobble/couscous/interpreter/Environment.java')
| -rw-r--r-- | src/main/java/org/zwobble/couscous/interpreter/Environment.java | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Environment.java b/src/main/java/org/zwobble/couscous/interpreter/Environment.java index a24bf1c..27e337a 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/Environment.java +++ b/src/main/java/org/zwobble/couscous/interpreter/Environment.java @@ -1,6 +1,5 @@ package org.zwobble.couscous.interpreter; -import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -8,27 +7,36 @@ import org.zwobble.couscous.Project; import org.zwobble.couscous.ast.VariableNode; import org.zwobble.couscous.values.ConcreteType; import org.zwobble.couscous.values.InterpreterValue; +import org.zwobble.couscous.values.TypeReference; + +import static java.util.stream.Collectors.toMap; +import static org.zwobble.couscous.util.CousCousMaps.mapKeys; import lombok.val; public class Environment { - private final Map<Integer, Optional<InterpreterValue>> stackFrame; private final Project project; + private final Map<Integer, Optional<InterpreterValue>> stackFrameValues; + private final Map<Integer, TypeReference> stackFrameTypes; - public Environment(Project project, Map<Integer, Optional<InterpreterValue>> stackFrame) { + public Environment(Project project, Map<VariableNode, Optional<InterpreterValue>> stackFrame) { this.project = project; - this.stackFrame = new HashMap<>(stackFrame); + this.stackFrameValues = mapKeys(stackFrame, variable -> variable.getId()); + this.stackFrameTypes = stackFrame.keySet() + .stream() + .collect(toMap(variable -> variable.getId(), variable -> variable.getType())); } public InterpreterValue get(int variableId) { checkVariableIsInScope(variableId); - val value = stackFrame.get(variableId); + val value = stackFrameValues.get(variableId); return value.orElseThrow(() -> new UnboundVariable(variableId)); } public void put(int variableId, InterpreterValue value) { checkVariableIsInScope(variableId); - stackFrame.put(variableId, Optional.of(value)); + checkVariableType(variableId, value); + stackFrameValues.put(variableId, Optional.of(value)); } public void put(VariableNode variable, InterpreterValue value) { @@ -40,13 +48,21 @@ public class Environment { return project.findClass(className); } - public Environment withStackFrame(Map<Integer, Optional<InterpreterValue>> stackFrame) { + public Environment withStackFrame(Map<VariableNode, Optional<InterpreterValue>> stackFrame) { return new Environment(project, stackFrame); } private void checkVariableIsInScope(int variableId) { - if (!stackFrame.containsKey(variableId)) { + if (!stackFrameValues.containsKey(variableId)) { throw new VariableNotInScope(variableId); } } + + private void checkVariableType(int variableId, InterpreterValue value) { + val variableType = stackFrameTypes.get(variableId); + val valueType = value.getType().getReference(); + if (!variableType.equals(valueType)) { + throw new UnexpectedValueType(variableType, valueType); + } + } } |
