aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java12
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/FieldValue.java56
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java22
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/ObjectInterpreterValue.java2
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java2
-rw-r--r--src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java26
6 files changed, 80 insertions, 40 deletions
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java b/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java
index 3a4443f..63c1bbe 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java
@@ -41,7 +41,7 @@ public class ConcreteType {
}
public Builder<T> field(String name, TypeName type) {
- fields.put(name, new FieldValue(name, type));
+ fields.put(name, new FieldValue(false, name, type));
return this;
}
@@ -92,7 +92,10 @@ public class ConcreteType {
}
public static ConcreteType fromNode(ClassNode classNode) {
- Map<String, FieldValue> fields = classNode.getFields().stream().collect(toMap(field -> field.getName(), field -> new FieldValue(field.getName(), field.getType())));
+ Map<String, FieldValue> fields = classNode.getFields().stream()
+ .collect(toMap(
+ field -> field.getName(),
+ field -> new FieldValue(field.isStatic(), field.getName(), field.getType())));
MethodValue constructor = new MethodValue(getArgumentTypes(classNode.getConstructor().getArguments()), (environment, arguments) -> Executor.callMethod(environment, classNode.getConstructor(), Optional.of(arguments.getReceiver()), arguments.getPositionalArguments()));
Map<MethodSignature, MethodValue> methods = classNode.getMethods()
.stream()
@@ -158,8 +161,9 @@ public class ConcreteType {
return superTypes;
}
- public Optional<FieldValue> getField(String fieldName) {
- return Optional.ofNullable(fields.get(fieldName));
+ public Optional<FieldValue> getField(boolean isStatic, String fieldName) {
+ return Optional.ofNullable(fields.get(fieldName))
+ .filter(field -> field.isStatic() == isStatic);
}
public List<StatementNode> getStaticConstructor() {
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/FieldValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/FieldValue.java
index 4ee1c95..90a6099 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/FieldValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/FieldValue.java
@@ -3,14 +3,20 @@ package org.zwobble.couscous.interpreter.values;
import org.zwobble.couscous.ast.TypeName;
public final class FieldValue {
+ private final boolean isStatic;
private final String name;
private final TypeName type;
- public FieldValue(final String name, final TypeName type) {
+ public FieldValue(final boolean isStatic, final String name, final TypeName type) {
+ this.isStatic = isStatic;
this.name = name;
this.type = type;
}
+ public boolean isStatic() {
+ return isStatic;
+ }
+
public String getName() {
return this.name;
}
@@ -19,33 +25,33 @@ public final class FieldValue {
return this.type;
}
- @java.lang.Override
- public boolean equals(final java.lang.Object o) {
- if (o == this) return true;
- if (!(o instanceof FieldValue)) return false;
- final FieldValue other = (FieldValue)o;
- final java.lang.Object this$name = this.getName();
- final java.lang.Object other$name = other.getName();
- if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
- final java.lang.Object this$type = this.getType();
- final java.lang.Object other$type = other.getType();
- if (this$type == null ? other$type != null : !this$type.equals(other$type)) return false;
- return true;
+ @Override
+ public String toString() {
+ return "FieldValue(" +
+ "isStatic=" + isStatic +
+ ", name='" + name + '\'' +
+ ", type=" + type +
+ ')';
}
- @java.lang.Override
- public int hashCode() {
- final int PRIME = 59;
- int result = 1;
- final java.lang.Object $name = this.getName();
- result = result * PRIME + ($name == null ? 43 : $name.hashCode());
- final java.lang.Object $type = this.getType();
- result = result * PRIME + ($type == null ? 43 : $type.hashCode());
- return result;
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ FieldValue that = (FieldValue) o;
+
+ if (isStatic != that.isStatic) return false;
+ if (!name.equals(that.name)) return false;
+ return type.equals(that.type);
+
}
- @java.lang.Override
- public java.lang.String toString() {
- return "FieldValue(name=" + this.getName() + ", type=" + this.getType() + ")";
+ @Override
+ public int hashCode() {
+ int result = (isStatic ? 1 : 0);
+ result = 31 * result + name.hashCode();
+ result = 31 * result + type.hashCode();
+ return result;
}
} \ No newline at end of file
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java
index fc082a5..df33d60 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java
@@ -8,18 +8,26 @@ import java.util.HashMap;
import java.util.Map;
public class InterpreterFields {
- // TODO: distinguish static and non-static fields
+ public static InterpreterFields forClass(ConcreteType type) {
+ return new InterpreterFields(true, type);
+ }
+
+ public static InterpreterFields forInstanceOf(ConcreteType type) {
+ return new InterpreterFields(false, type);
+ }
+ private final boolean isStatic;
private final ConcreteType type;
private final Map<String, InterpreterValue> fields;
- public InterpreterFields(ConcreteType type) {
+ private InterpreterFields(boolean isStatic, ConcreteType type) {
+ this.isStatic = isStatic;
this.type = type;
this.fields = new HashMap<>();
}
public InterpreterValue getField(String fieldName) {
- type.getField(fieldName).orElseThrow(() -> new NoSuchField(fieldName));
+ getFieldDefinition(fieldName);
if (fields.containsKey(fieldName)) {
return fields.get(fieldName);
} else {
@@ -28,9 +36,13 @@ public class InterpreterFields {
}
public void setField(String fieldName, InterpreterValue value) {
- FieldValue field = type.getField(fieldName)
- .orElseThrow(() -> new NoSuchField(fieldName));
+ FieldValue field = getFieldDefinition(fieldName);
InterpreterTypes.checkIsInstance(field.getType(), value);
fields.put(fieldName, value);
}
+
+ private FieldValue getFieldDefinition(String fieldName) {
+ return type.getField(isStatic, fieldName)
+ .orElseThrow(() -> new NoSuchField(fieldName));
+ }
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/ObjectInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/ObjectInterpreterValue.java
index e46ae45..e15c01d 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/ObjectInterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/ObjectInterpreterValue.java
@@ -10,7 +10,7 @@ public class ObjectInterpreterValue implements InterpreterValue {
public ObjectInterpreterValue(ConcreteType type) {
this.type = type;
- this.fields = new InterpreterFields(type);
+ this.fields = InterpreterFields.forInstanceOf(type);
}
@Override
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java
index 9844e33..2595623 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java
@@ -12,7 +12,7 @@ public class StaticReceiverValue implements ReceiverValue {
public StaticReceiverValue(ConcreteType type) {
this.type = type;
- this.fields = new InterpreterFields(type);
+ this.fields = InterpreterFields.forClass(type);
}
@Override
diff --git a/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java
index 98f4e22..b2b572d 100644
--- a/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java
@@ -2,10 +2,7 @@ package org.zwobble.couscous.tests.interpreter;
import com.google.common.collect.ImmutableMap;
import org.junit.Test;
-import org.zwobble.couscous.ast.ClassNode;
-import org.zwobble.couscous.ast.ExpressionNode;
-import org.zwobble.couscous.ast.FormalArgumentNode;
-import org.zwobble.couscous.ast.MethodSignature;
+import org.zwobble.couscous.ast.*;
import org.zwobble.couscous.interpreter.Environment;
import org.zwobble.couscous.interpreter.JavaProject;
import org.zwobble.couscous.interpreter.MapBackedProject;
@@ -171,6 +168,27 @@ public class EvaluatorTests extends BackendEvalTests {
assertEquals(new NoSuchField("value"), exception);
}
+
+ @Test
+ public void cannotSetValueOfInstanceFieldAsThoughItIsAStaticField() {
+ TypeName type = TypeName.of("com.example.Example");
+ ClassNode classNode = ClassNode.builder(type)
+ .field("value", IntegerValue.REF)
+ .constructor(constructor -> constructor
+ .statement(assignStatement(
+ fieldAccess(type, "value", IntegerValue.REF),
+ literal(42))))
+ .build();
+
+ NoSuchField exception = assertThrows(NoSuchField.class,
+ () -> evalExpression(
+ list(classNode),
+ constructorCall(
+ classNode.getName(),
+ list())));
+
+ assertEquals(new NoSuchField("value"), exception);
+ }
@Test
public void cannotSetValueOfFieldWithWrongType() {