diff options
Diffstat (limited to '')
7 files changed, 78 insertions, 25 deletions
diff --git a/evaluator/src/main/java/lv/enes/orang/evaluator/Array.java b/evaluator/src/main/java/lv/enes/orang/evaluator/Array.java index ab0d896..265bbd9 100644 --- a/evaluator/src/main/java/lv/enes/orang/evaluator/Array.java +++ b/evaluator/src/main/java/lv/enes/orang/evaluator/Array.java | |||
| @@ -46,7 +46,7 @@ public record Array(List<Value> items) implements Value { | |||
| 46 | newItems.addAll(rhsi); | 46 | newItems.addAll(rhsi); |
| 47 | return new Array(Collections.unmodifiableList(newItems)); | 47 | return new Array(Collections.unmodifiableList(newItems)); |
| 48 | } else { | 48 | } else { |
| 49 | throw new OrangRuntimeException(STR."add not implemented for Array and \{rhs.typeName()}"); | 49 | return Value.super.add(rhs); |
| 50 | } | 50 | } |
| 51 | } | 51 | } |
| 52 | 52 | ||
| @@ -58,7 +58,7 @@ public record Array(List<Value> items) implements Value { | |||
| 58 | } | 58 | } |
| 59 | return items.get(i); | 59 | return items.get(i); |
| 60 | } else { | 60 | } else { |
| 61 | throw new OrangRuntimeException(STR."array access not implemented for Array and \{idx.typeName()}"); | 61 | return Value.super.arrayAccess(idx); |
| 62 | } | 62 | } |
| 63 | } | 63 | } |
| 64 | 64 | ||
| @@ -71,7 +71,7 @@ public record Array(List<Value> items) implements Value { | |||
| 71 | } | 71 | } |
| 72 | return new Array(Collections.unmodifiableList(newItems)); | 72 | return new Array(Collections.unmodifiableList(newItems)); |
| 73 | } else { | 73 | } else { |
| 74 | throw new OrangRuntimeException(STR."multiply not implemented for Array and \{rhs.typeName()}"); | 74 | return Value.super.multiply(rhs); |
| 75 | } | 75 | } |
| 76 | } | 76 | } |
| 77 | } | 77 | } |
diff --git a/evaluator/src/main/java/lv/enes/orang/evaluator/Evaluator.java b/evaluator/src/main/java/lv/enes/orang/evaluator/Evaluator.java index 69c03e8..8fd61e8 100644 --- a/evaluator/src/main/java/lv/enes/orang/evaluator/Evaluator.java +++ b/evaluator/src/main/java/lv/enes/orang/evaluator/Evaluator.java | |||
| @@ -120,6 +120,17 @@ public record Evaluator(Map<String, Value> scope, Value lastResult) implements E | |||
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | @Override | 122 | @Override |
| 123 | public Value visitMap(MapExpression expr) throws OrangRuntimeException { | ||
| 124 | var map = new HashMap<Value, Value>(); | ||
| 125 | for (var entry : expr.entries()) { | ||
| 126 | var from = visit(entry.from()); | ||
| 127 | var to = visit(entry.to()); | ||
| 128 | map.put(from, to); | ||
| 129 | } | ||
| 130 | return new OrangMap(Collections.unmodifiableMap(map)); | ||
| 131 | } | ||
| 132 | |||
| 133 | @Override | ||
| 123 | public Evaluator visitProgram(Program prog) throws OrangRuntimeException { | 134 | public Evaluator visitProgram(Program prog) throws OrangRuntimeException { |
| 124 | var evaluator = this; | 135 | var evaluator = this; |
| 125 | for (var statement : prog.statements()) { | 136 | for (var statement : prog.statements()) { |
diff --git a/evaluator/src/main/java/lv/enes/orang/evaluator/OrangBoolean.java b/evaluator/src/main/java/lv/enes/orang/evaluator/OrangBoolean.java index 3564a9c..46c887c 100644 --- a/evaluator/src/main/java/lv/enes/orang/evaluator/OrangBoolean.java +++ b/evaluator/src/main/java/lv/enes/orang/evaluator/OrangBoolean.java | |||
| @@ -5,8 +5,8 @@ import lv.enes.orang.core.OrangRuntimeException; | |||
| 5 | 5 | ||
| 6 | @EqualsAndHashCode | 6 | @EqualsAndHashCode |
| 7 | public final class OrangBoolean implements Value { | 7 | public final class OrangBoolean implements Value { |
| 8 | public final static OrangBoolean TRUE = new OrangBoolean(true); | 8 | public static final OrangBoolean TRUE = new OrangBoolean(true); |
| 9 | public final static OrangBoolean FALSE = new OrangBoolean(false); | 9 | public static final OrangBoolean FALSE = new OrangBoolean(false); |
| 10 | 10 | ||
| 11 | private final boolean value; | 11 | private final boolean value; |
| 12 | 12 | ||
| @@ -45,11 +45,11 @@ public final class OrangBoolean implements Value { | |||
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | @Override | 47 | @Override |
| 48 | public OrangBoolean or(Value rhs) throws OrangRuntimeException { | 48 | public Value or(Value rhs) throws OrangRuntimeException { |
| 49 | if (rhs instanceof OrangBoolean rhsb) { | 49 | if (rhs instanceof OrangBoolean rhsb) { |
| 50 | return new OrangBoolean(value || rhsb.value); | 50 | return new OrangBoolean(value || rhsb.value); |
| 51 | } else { | 51 | } else { |
| 52 | throw new OrangRuntimeException(STR."or is not implemented for Boolean and \{rhs.typeName()}"); | 52 | return Value.super.or(rhs); |
| 53 | } | 53 | } |
| 54 | } | 54 | } |
| 55 | } | 55 | } |
diff --git a/evaluator/src/main/java/lv/enes/orang/evaluator/OrangInteger.java b/evaluator/src/main/java/lv/enes/orang/evaluator/OrangInteger.java index 90de0b5..872fce2 100644 --- a/evaluator/src/main/java/lv/enes/orang/evaluator/OrangInteger.java +++ b/evaluator/src/main/java/lv/enes/orang/evaluator/OrangInteger.java | |||
| @@ -24,47 +24,47 @@ public record OrangInteger(int value) implements Value { | |||
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | @Override | 26 | @Override |
| 27 | public OrangInteger add(Value rhs) throws OrangRuntimeException { | 27 | public Value add(Value rhs) throws OrangRuntimeException { |
| 28 | if (rhs instanceof OrangInteger(int rhsi)) { | 28 | if (rhs instanceof OrangInteger(int rhsi)) { |
| 29 | return new OrangInteger(value + rhsi); | 29 | return new OrangInteger(value + rhsi); |
| 30 | } else { | 30 | } else { |
| 31 | throw new OrangRuntimeException(STR."add is not implemented for Integer and \{rhs.typeName()}"); | 31 | return Value.super.add(rhs); |
| 32 | } | 32 | } |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | @Override | 35 | @Override |
| 36 | public OrangInteger divide(Value rhs) throws OrangRuntimeException { | 36 | public Value divide(Value rhs) throws OrangRuntimeException { |
| 37 | if (rhs instanceof OrangInteger(int rhsi)) { | 37 | if (rhs instanceof OrangInteger(int rhsi)) { |
| 38 | return new OrangInteger(value / rhsi); | 38 | return new OrangInteger(value / rhsi); |
| 39 | } else { | 39 | } else { |
| 40 | throw new OrangRuntimeException(STR."divide is not implemented for Integer and \{rhs.typeName()}"); | 40 | return Value.super.divide(rhs); |
| 41 | } | 41 | } |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | @Override | 44 | @Override |
| 45 | public OrangInteger multiply(Value rhs) throws OrangRuntimeException { | 45 | public Value multiply(Value rhs) throws OrangRuntimeException { |
| 46 | if (rhs instanceof OrangInteger(int rhsi)) { | 46 | if (rhs instanceof OrangInteger(int rhsi)) { |
| 47 | return new OrangInteger(value * rhsi); | 47 | return new OrangInteger(value * rhsi); |
| 48 | } else { | 48 | } else { |
| 49 | throw new OrangRuntimeException(STR."multiply is not implemented for Integer and \{rhs.typeName()}"); | 49 | return Value.super.multiply(rhs); |
| 50 | } | 50 | } |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | @Override | 53 | @Override |
| 54 | public OrangInteger subtract(Value rhs) throws OrangRuntimeException { | 54 | public Value subtract(Value rhs) throws OrangRuntimeException { |
| 55 | if (rhs instanceof OrangInteger(int rhsi)) { | 55 | if (rhs instanceof OrangInteger(int rhsi)) { |
| 56 | return new OrangInteger(value - rhsi); | 56 | return new OrangInteger(value - rhsi); |
| 57 | } else { | 57 | } else { |
| 58 | throw new OrangRuntimeException(STR."subtract is not implemented for Integer and \{rhs.typeName()}"); | 58 | return Value.super.subtract(rhs); |
| 59 | } | 59 | } |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | @Override | 62 | @Override |
| 63 | public OrangBoolean greaterThan(Value rhs) throws OrangRuntimeException { | 63 | public Value greaterThan(Value rhs) throws OrangRuntimeException { |
| 64 | if (rhs instanceof OrangInteger(int rhsi)) { | 64 | if (rhs instanceof OrangInteger(int rhsi)) { |
| 65 | return OrangBoolean.of(value > rhsi); | 65 | return OrangBoolean.of(value > rhsi); |
| 66 | } else { | 66 | } else { |
| 67 | throw new OrangRuntimeException(STR."greaterThan is not implemented for Integer and \{rhs.typeName()}"); | 67 | return Value.super.greaterThan(rhs); |
| 68 | } | 68 | } |
| 69 | } | 69 | } |
| 70 | } | 70 | } |
diff --git a/evaluator/src/main/java/lv/enes/orang/evaluator/OrangMap.java b/evaluator/src/main/java/lv/enes/orang/evaluator/OrangMap.java new file mode 100644 index 0000000..27f9f35 --- /dev/null +++ b/evaluator/src/main/java/lv/enes/orang/evaluator/OrangMap.java | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | package lv.enes.orang.evaluator; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangRuntimeException; | ||
| 4 | |||
| 5 | import java.util.HashMap; | ||
| 6 | import java.util.Map; | ||
| 7 | |||
| 8 | public record OrangMap(Map<Value, Value> map) implements Value { | ||
| 9 | @Override | ||
| 10 | public String typeName() { | ||
| 11 | return "Map"; | ||
| 12 | } | ||
| 13 | |||
| 14 | @Override | ||
| 15 | public String stringify() { | ||
| 16 | var sb = new StringBuilder("{ "); | ||
| 17 | for (var entry : map.entrySet()) { | ||
| 18 | sb.append(entry.getKey().stringify()).append(" -> ").append(entry.getValue().stringify()).append(", "); | ||
| 19 | } | ||
| 20 | return sb.append("}").toString(); | ||
| 21 | } | ||
| 22 | |||
| 23 | @Override | ||
| 24 | public Value add(Value rhs) throws OrangRuntimeException { | ||
| 25 | if (rhs instanceof OrangMap(var rhsm)) { | ||
| 26 | var newMap = new HashMap<>(map); | ||
| 27 | newMap.putAll(rhsm); | ||
| 28 | return new OrangMap(newMap); | ||
| 29 | } else { | ||
| 30 | return Value.super.add(rhs); | ||
| 31 | } | ||
| 32 | } | ||
| 33 | |||
| 34 | @Override | ||
| 35 | public Value arrayAccess(Value idx) throws OrangRuntimeException { | ||
| 36 | if (map.containsKey(idx)) { | ||
| 37 | return map.get(idx); | ||
| 38 | } else { | ||
| 39 | throw new OrangRuntimeException(STR."No value associated with key \{idx.stringify()} in \{stringify()}"); | ||
| 40 | } | ||
| 41 | } | ||
| 42 | } | ||
diff --git a/evaluator/src/main/java/lv/enes/orang/evaluator/OrangString.java b/evaluator/src/main/java/lv/enes/orang/evaluator/OrangString.java index 5c38842..fe03c1f 100644 --- a/evaluator/src/main/java/lv/enes/orang/evaluator/OrangString.java +++ b/evaluator/src/main/java/lv/enes/orang/evaluator/OrangString.java | |||
| @@ -30,11 +30,11 @@ public record OrangString(String value) implements Value { | |||
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | @Override | 32 | @Override |
| 33 | public OrangString add(Value rhs) throws OrangRuntimeException { | 33 | public Value add(Value rhs) throws OrangRuntimeException { |
| 34 | if (rhs instanceof OrangString(String rhss)) { | 34 | if (rhs instanceof OrangString(String rhss)) { |
| 35 | return new OrangString(value + rhss); | 35 | return new OrangString(value + rhss); |
| 36 | } else { | 36 | } else { |
| 37 | throw new OrangRuntimeException(STR."add is not implemented for Integer and \{rhs.typeName()}"); | 37 | return Value.super.add(rhs); |
| 38 | } | 38 | } |
| 39 | } | 39 | } |
| 40 | 40 | ||
| @@ -43,7 +43,7 @@ public record OrangString(String value) implements Value { | |||
| 43 | if (rhs instanceof OrangInteger(var repeat)) { | 43 | if (rhs instanceof OrangInteger(var repeat)) { |
| 44 | return new OrangString(value.repeat(Math.max(0, repeat))); | 44 | return new OrangString(value.repeat(Math.max(0, repeat))); |
| 45 | } else { | 45 | } else { |
| 46 | throw new OrangRuntimeException(STR."multiply not implemented for Array and \{rhs.typeName()}"); | 46 | return Value.super.multiply(rhs); |
| 47 | } | 47 | } |
| 48 | } | 48 | } |
| 49 | } | 49 | } |
diff --git a/evaluator/src/main/java/lv/enes/orang/evaluator/Value.java b/evaluator/src/main/java/lv/enes/orang/evaluator/Value.java index 35af35b..da44a19 100644 --- a/evaluator/src/main/java/lv/enes/orang/evaluator/Value.java +++ b/evaluator/src/main/java/lv/enes/orang/evaluator/Value.java | |||
| @@ -3,7 +3,7 @@ package lv.enes.orang.evaluator; | |||
| 3 | import lv.enes.orang.core.OrangRuntimeException; | 3 | import lv.enes.orang.core.OrangRuntimeException; |
| 4 | 4 | ||
| 5 | public sealed interface Value | 5 | public sealed interface Value |
| 6 | permits Array, BuiltinFunction, Function, OrangBoolean, OrangInteger, OrangString, | 6 | permits Array, BuiltinFunction, Function, OrangBoolean, OrangInteger, OrangMap, OrangString, |
| 7 | PartialBuiltinFunction, PartialFunction, Tuple, Undefined { | 7 | PartialBuiltinFunction, PartialFunction, Tuple, Undefined { |
| 8 | String typeName(); | 8 | String typeName(); |
| 9 | String stringify(); | 9 | String stringify(); |
| @@ -56,19 +56,19 @@ public sealed interface Value | |||
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | 58 | ||
| 59 | default OrangBoolean greaterThan(Value rhs) throws OrangRuntimeException { | 59 | default Value greaterThan(Value rhs) throws OrangRuntimeException { |
| 60 | throw new OrangRuntimeException(STR."greater than is not implemented for \{typeName()} and \{rhs.typeName()}"); | 60 | throw new OrangRuntimeException(STR."greater than is not implemented for \{typeName()} and \{rhs.typeName()}"); |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | default OrangBoolean greaterThanOrEqual(Value rhs) throws OrangRuntimeException { | 63 | default Value greaterThanOrEqual(Value rhs) throws OrangRuntimeException { |
| 64 | return greaterThan(rhs).or(orangEquals(rhs)); | 64 | return greaterThan(rhs).or(orangEquals(rhs)); |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | default OrangBoolean lessThan(Value rhs) throws OrangRuntimeException { | 67 | default Value lessThan(Value rhs) throws OrangRuntimeException { |
| 68 | return greaterThanOrEqual(rhs).not(); | 68 | return greaterThanOrEqual(rhs).not(); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | default OrangBoolean lessThanOrEqual(Value rhs) throws OrangRuntimeException { | 71 | default Value lessThanOrEqual(Value rhs) throws OrangRuntimeException { |
| 72 | return greaterThan(rhs).not(); | 72 | return greaterThan(rhs).not(); |
| 73 | } | 73 | } |
| 74 | 74 | ||