diff --git a/src/main/java/com/annimon/ownlang/modules/std/std.java b/src/main/java/com/annimon/ownlang/modules/std/std.java index a8618db..470be66 100644 --- a/src/main/java/com/annimon/ownlang/modules/std/std.java +++ b/src/main/java/com/annimon/ownlang/modules/std/std.java @@ -55,6 +55,7 @@ public final class std implements Module { Functions.set("arrayKeyExists", new std_arrayKeyExists()); Functions.set("arrayKeys", new std_arrayKeys()); Functions.set("arrayValues", new std_arrayValues()); + Functions.set("arraySplice", new std_arraySplice()); Functions.set("range", new std_range()); } } diff --git a/src/main/java/com/annimon/ownlang/modules/std/std_arraySplice.java b/src/main/java/com/annimon/ownlang/modules/std/std_arraySplice.java new file mode 100644 index 0000000..f16f04f --- /dev/null +++ b/src/main/java/com/annimon/ownlang/modules/std/std_arraySplice.java @@ -0,0 +1,45 @@ +package com.annimon.ownlang.modules.std; + +import com.annimon.ownlang.exceptions.TypeException; +import com.annimon.ownlang.lib.Arguments; +import com.annimon.ownlang.lib.ArrayValue; +import com.annimon.ownlang.lib.Function; +import com.annimon.ownlang.lib.Types; +import com.annimon.ownlang.lib.Value; + +public final class std_arraySplice implements Function { + + @Override + public Value execute(Value... args) { + Arguments.checkRange(2, 4, args.length); + if (args[0].type() != Types.ARRAY) { + throw new TypeException("Array expected at first argument"); + } + final Value[] input = ((ArrayValue) args[0]).getCopyElements(); + final int size = input.length; + + int start = args[1].asInt(); + if (start < 0) start = size - Math.abs(start); + start = Math.max(0, Math.min(size, start)); + + final int deleteCount = (args.length >= 3) + ? Math.max(0, Math.min(size - start, args[2].asInt())) // [0..size - start) + : (size - start); + + final Value[] additions; + if (args.length != 4) { + additions = new Value[0]; + } else if (args[3].type() == Types.ARRAY) { + additions = ((ArrayValue) args[3]).getCopyElements(); + } else { + throw new TypeException("Array expected at fourth argument"); + } + + Value[] result = new Value[start + (size - start - deleteCount) + additions.length]; + System.arraycopy(input, 0, result, 0, start); // [0, start) + System.arraycopy(additions, 0, result, start, additions.length); // insert new + System.arraycopy(input, start + deleteCount, result, start + additions.length, size - start - deleteCount); + return new ArrayValue(result); + } + +} diff --git a/src/test/resources/modules/std/arraySplice.own b/src/test/resources/modules/std/arraySplice.own new file mode 100644 index 0000000..0ec3d50 --- /dev/null +++ b/src/test/resources/modules/std/arraySplice.own @@ -0,0 +1,107 @@ +use "std" + +def testArraySpliceFromStart() { + arr = [1,2,3,4,5] + assertEquals([1, 2], arraySplice(arr, 2)) +} + +def testArraySpliceFromStartAndInsert() { + arr = [1,2,3,4,5] + assertEquals([1, 2, 6,7,8], arraySplice(arr, 2, 3, [6,7,8])) +} + +def testArraySpliceRemoveOneElementByIndex() { + arr = [1,2,3,4,5] + assertEquals([1, 2, 4, 5], arraySplice(arr, 2, 1)) +} + +def testArraySpliceRemoveOneElementByIndexAndInsert() { + arr = [1,2,3,4,5] + assertEquals([1, 2, 6,7,8, 4, 5], arraySplice(arr, 2, 1, [6,7,8])) +} + +def testArraySpliceReplaceFirstElement() { + arr = [1,2,3,4,5] + assertEquals([6,7,8, 2, 3, 4, 5], arraySplice(arr, 0, 1, [6,7,8])) +} + +def testArraySpliceInsertAtStart() { + arr = [1,2,3,4,5] + assertEquals([6,7,8, 1, 2, 3, 4, 5], arraySplice(arr, 0, 0, [6,7,8])) +} + +def testArraySpliceReplaceAll() { + arr = [1,2,3,4,5] + assertEquals([6,7,8], arraySplice(arr, 0, 5, [6,7,8])) +} + +def testArraySpliceRemoveMoreThanSizeAtTheEnd() { + arr = [1,2,3,4,5] + assertEquals([1, 2, 3], arraySplice(arr, 3, 4)) +} + +def testArraySpliceRemoveMoreThanSizeAtTheEndAndInsert() { + arr = [1,2,3,4,5] + assertEquals([1, 2, 3, 6,7,8], arraySplice(arr, 3, 4, [6,7,8])) +} + +def testArraySpliceRemoveMoreThanSize() { + arr = [1,2,3,4,5] + assertEquals([], arraySplice(arr, 0, 15)) +} + +def testArraySpliceRemoveMoreThanSizeAndInsert() { + arr = [1,2,3,4,5] + assertEquals([1,2], arraySplice(arr, 0, 15, [1,2])) +} + +def testArraySpliceStartMoreThanSize() { + arr = [1,2,3,4,5] + assertEquals([1,2,3,4,5], arraySplice(arr, 15)) +} + +def testArraySpliceStartAndRemoveMoreThanSize() { + arr = [1,2,3,4,5] + assertEquals([1,2,3,4,5], arraySplice(arr, 15, 15)) +} + +def testArraySpliceStartAndRemoveMoreThanSizeAndInsert() { + arr = [1,2,3,4,5] + assertEquals([1,2,3,4,5,1], arraySplice(arr, 15, 15, [1])) +} + +def testArraySpliceFromJSExamples1() { + arr = ["angel", "clown", "mandarin", "surgeon"] + res = ["angel", "clown", "drum", "mandarin", "surgeon"] + assertEquals(res, arraySplice(arr, 2, 0, ["drum"])) +} + +def testArraySpliceFromJSExamples2() { + arr = ["angel", "clown", "drum", "mandarin", "surgeon"] + res = ["angel", "clown", "drum", "surgeon"] + assertEquals(res, arraySplice(arr, 3, 1)) +} + +def testArraySpliceFromJSExamples3() { + arr = ["angel", "clown", "drum", "surgeon"] + res = ["angel", "clown", "trumpet", "surgeon"] + assertEquals(res, arraySplice(arr, 2, 1, ["trumpet"])) +} + +def testArraySpliceFromJSExamples4() { + arr = ["angel", "clown", "trumpet", "surgeon"] + res = ["parrot", "anemone", "blue", "trumpet", "surgeon"] + assertEquals(res, arraySplice(arr, 0, 2, ["parrot", "anemone", "blue"])) +} + +def testArraySpliceFromJSExamples5() { + arr = ["parrot", "anemone", "blue", "trumpet", "surgeon"] + res = ["parrot", "anemone", "surgeon"] + assertEquals(res, arraySplice(arr, length(arr) - 3, 2)) +} + +def testArraySpliceFromJSExamples6() { + arr = ["angel", "clown", "mandarin", "surgeon"] + res = ["angel", "clown", "surgeon"] + assertEquals(res, arraySplice(arr, -2, 1)) +} \ No newline at end of file