diff --git a/src/main/java/com/annimon/ownlang/lib/ArrayValue.java b/src/main/java/com/annimon/ownlang/lib/ArrayValue.java index 81a3448..cdd3b68 100644 --- a/src/main/java/com/annimon/ownlang/lib/ArrayValue.java +++ b/src/main/java/com/annimon/ownlang/lib/ArrayValue.java @@ -1,6 +1,7 @@ package com.annimon.ownlang.lib; import com.annimon.ownlang.exceptions.TypeException; +import com.annimon.ownlang.exceptions.UnknownPropertyException; import java.util.Arrays; import java.util.Iterator; import java.util.List; @@ -78,29 +79,45 @@ public class ArrayValue implements Value, Iterable { public int type() { return Types.ARRAY; } - + public int size() { return elements.length; } - + public Value get(int index) { return elements[index]; } - + + public Value get(Value index) { + final String prop = index.asString(); + switch (prop) { + // Properties + case "length": + return NumberValue.of(size()); + + // Functions + case "isEmpty": + return NumberValue.fromBoolean(size() == 0); + + default: + return get(index.asInt()); + } + } + public void set(int index, Value value) { elements[index] = value; } - + @Override public Object raw() { return elements; } - + @Override public int asInt() { throw new TypeException("Cannot cast array to integer"); } - + @Override public double asNumber() { throw new TypeException("Cannot cast array to number"); @@ -132,7 +149,7 @@ public class ArrayValue implements Value, Iterable { final ArrayValue other = (ArrayValue) obj; return Arrays.deepEquals(this.elements, other.elements); } - + @Override public int compareTo(Value o) { if (o.type() == Types.ARRAY) { diff --git a/src/main/java/com/annimon/ownlang/parser/ast/ContainerAccessExpression.java b/src/main/java/com/annimon/ownlang/parser/ast/ContainerAccessExpression.java index 27bb676..1d5e915 100644 --- a/src/main/java/com/annimon/ownlang/parser/ast/ContainerAccessExpression.java +++ b/src/main/java/com/annimon/ownlang/parser/ast/ContainerAccessExpression.java @@ -43,8 +43,7 @@ public final class ContainerAccessExpression implements Expression, Accessible { final Value lastIndex = lastIndex(); switch (container.type()) { case Types.ARRAY: - final int arrayIndex = lastIndex.asInt(); - return ((ArrayValue) container).get(arrayIndex); + return ((ArrayValue) container).get(lastIndex); case Types.MAP: return ((MapValue) container).get(lastIndex); diff --git a/src/test/java/com/annimon/ownlang/parser/ProgramsTest.java b/src/test/java/com/annimon/ownlang/parser/ProgramsTest.java index d142122..0fcab09 100644 --- a/src/test/java/com/annimon/ownlang/parser/ProgramsTest.java +++ b/src/test/java/com/annimon/ownlang/parser/ProgramsTest.java @@ -1,6 +1,7 @@ package com.annimon.ownlang.parser; import com.annimon.ownlang.Console; +import com.annimon.ownlang.lib.FunctionValue; import com.annimon.ownlang.lib.Functions; import com.annimon.ownlang.lib.NumberValue; import com.annimon.ownlang.lib.Variables; @@ -83,6 +84,15 @@ public class ProgramsTest { assertFalse(args[0].asInt() != 0); return NumberValue.ONE; }); + Functions.set("assertFail", (args) -> { + try { + ((FunctionValue) args[0]).getValue().execute(); + fail("Function should fail"); + } catch (Throwable thr) { + + } + return NumberValue.ONE; + }); } @Test diff --git a/src/test/resources/other/arrayFunctions.own b/src/test/resources/other/arrayFunctions.own new file mode 100644 index 0000000..da25e6a --- /dev/null +++ b/src/test/resources/other/arrayFunctions.own @@ -0,0 +1,26 @@ +def testSetUnknownKey() = assertFail(def() { + arr = [1, 2, 3] + arr.one = 1 + }) + +def testSetLengthProperty() = assertFail(def() { + arr = [1, 2, 3] + arr.length = 10 + }) + +def testGetLength() { + arr = [1, 2, 3] + assertEquals(3, arr.length) +} + +def testGetLengthInnerArray() { + arr = [[1, 2, 3], [1, 2, [3, 4, 5, 6]]] + assertEquals(2, arr.length) + assertEquals(3, arr[0].length) + assertEquals(4, arr[1][2].length) +} + +def testIsEmpty() { + arr = [1, 2, 3] + assertFalse(arr.isEmpty) +} \ No newline at end of file