aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/zwobble/couscous/interpreter/Environment.java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2015-10-04 17:52:29 +0100
committerMichael Williamson <mike@zwobble.org>2015-10-04 17:52:29 +0100
commitb74d68227dc7c05e24705e3064ef961f95b8b729 (patch)
tree70601bc83d1105c6748a062bd6ffe41ecfe68acc /src/main/java/org/zwobble/couscous/interpreter/Environment.java
parent8d2374ba254e637c22e6f1eaa58ccb54d814529f (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.java32
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);
+ }
+ }
}