diff --git a/praxiscore-script/src/main/java/org/praxislive/script/commands/ArrayCmds.java b/praxiscore-script/src/main/java/org/praxislive/script/commands/ArrayCmds.java index 30772f3d..76cae971 100644 --- a/praxiscore-script/src/main/java/org/praxislive/script/commands/ArrayCmds.java +++ b/praxiscore-script/src/main/java/org/praxislive/script/commands/ArrayCmds.java @@ -25,6 +25,7 @@ import java.util.Map; import org.praxislive.core.Value; import org.praxislive.core.types.PArray; +import org.praxislive.core.types.PNumber; import org.praxislive.script.Command; import org.praxislive.script.Env; import org.praxislive.script.InlineCommand; @@ -35,23 +36,118 @@ */ class ArrayCmds { - private final static Array ARRAY = new Array(); + private static final Array ARRAY = new Array(); + private static final ArrayGet ARRAY_GET = new ArrayGet(); + private static final ArrayJoin ARRAY_JOIN = new ArrayJoin(); + private static final ArrayRange ARRAY_RANGE = new ArrayRange(); + private static final ArraySize ARRAY_SIZE = new ArraySize(); private ArrayCmds() { } static void install(Map commands) { commands.put("array", ARRAY); + commands.put("array-get", ARRAY_GET); + commands.put("array-join", ARRAY_JOIN); + commands.put("array-range", ARRAY_RANGE); + commands.put("array-size", ARRAY_SIZE); } private static class Array implements InlineCommand { @Override public List process(Env context, Namespace namespace, List args) throws Exception { + if (args.isEmpty()) { + return List.of(PArray.EMPTY); + } PArray ar = args.stream().collect(PArray.collector()); return List.of(ar); } } + private static class ArrayGet implements InlineCommand { + + @Override + public List process(Env context, Namespace namespace, List args) throws Exception { + if (args.size() != 2) { + throw new IllegalArgumentException("Incorrect number of arguments"); + } + + PArray array = PArray.from(args.get(0)) + .orElseThrow(() -> new IllegalArgumentException("First argument is not an array")); + + int index = PNumber + .from(args.get(1)) + .orElseThrow(() -> new IllegalArgumentException("Second argument is not a number")) + .toIntValue(); + + return List.of(array.get(index)); + } + + } + + private static class ArrayJoin implements InlineCommand { + + @Override + public List process(Env context, Namespace namespace, List args) throws Exception { + PArray result = args.stream() + .flatMap(v -> PArray.from(v).stream()) + .flatMap(PArray::stream) + .collect(PArray.collector()); + return List.of(result); + } + + } + + private static class ArrayRange implements InlineCommand { + + @Override + public List process(Env context, Namespace namespace, List args) throws Exception { + if (args.size() < 2 || args.size() > 3) { + throw new IllegalArgumentException("Incorrect number of arguments"); + } + + PArray array = PArray.from(args.get(0)) + .orElseThrow(() -> new IllegalArgumentException("First argument is not an array")); + + int from, to; + if (args.size() == 2) { + from = 0; + to = PNumber + .from(args.get(1)) + .orElseThrow(() -> new IllegalArgumentException("Second argument is not a number")) + .toIntValue(); + } else { + from = PNumber + .from(args.get(1)) + .orElseThrow(() -> new IllegalArgumentException("Second argument is not a number")) + .toIntValue(); + to = PNumber + .from(args.get(2)) + .orElseThrow(() -> new IllegalArgumentException("Third argument is not a number")) + .toIntValue(); + } + + return List.of(PArray.of(array.asList().subList(from, to))); + } + + } + + private static class ArraySize implements InlineCommand { + + @Override + public List process(Env context, Namespace namespace, List args) throws Exception { + if (args.size() != 1) { + throw new IllegalArgumentException("Incorrect number of arguments"); + } + + PArray array = PArray.from(args.get(0)) + .orElseThrow(() -> new IllegalArgumentException("Argument is not an array")); + + return List.of(PNumber.of(array.size())); + } + + } + } diff --git a/praxiscore-script/src/main/java/org/praxislive/script/commands/BaseCmds.java b/praxiscore-script/src/main/java/org/praxislive/script/commands/BaseCmds.java index d0bc15df..2c659376 100644 --- a/praxiscore-script/src/main/java/org/praxislive/script/commands/BaseCmds.java +++ b/praxiscore-script/src/main/java/org/praxislive/script/commands/BaseCmds.java @@ -40,14 +40,19 @@ class BaseCmds { private static final System.Logger LOG = System.getLogger(BaseCmds.class.getName()); + + private static final Constant CONSTANT = new Constant(); private static final Set SET = new Set(); + private static final Var VAR = new Var(); private static final Echo ECHO = new Echo(); private BaseCmds() { } static void install(Map commands) { + commands.put("constant", CONSTANT); commands.put("set", SET); + commands.put("var", VAR); commands.put("echo", ECHO); } @@ -72,6 +77,36 @@ public List process(Env context, Namespace namespace, List args) t } } + private static class Constant implements InlineCommand { + + @Override + public List process(Env context, Namespace namespace, List args) throws Exception { + if (args.size() != 2) { + throw new Exception(); + } + String varName = args.get(0).toString(); + Value val = args.get(1); + namespace.createConstant(varName, val); + return List.of(val); + + } + } + + private static class Var implements InlineCommand { + + @Override + public List process(Env context, Namespace namespace, List args) throws Exception { + if (args.size() != 2) { + throw new Exception(); + } + String varName = args.get(0).toString(); + Value val = args.get(1); + namespace.createVariable(varName, val); + return List.of(val); + + } + } + private static class Echo implements InlineCommand { @Override diff --git a/praxiscore-script/src/main/java/org/praxislive/script/commands/CoreCommandsInstaller.java b/praxiscore-script/src/main/java/org/praxislive/script/commands/CoreCommandsInstaller.java index eff593ed..305c555b 100644 --- a/praxiscore-script/src/main/java/org/praxislive/script/commands/CoreCommandsInstaller.java +++ b/praxiscore-script/src/main/java/org/praxislive/script/commands/CoreCommandsInstaller.java @@ -39,6 +39,7 @@ public void install(Map commands) { AtCmds.install(commands); ConnectionCmds.install(commands); FileCmds.install(commands); + MapCmds.install(commands); ScriptCmds.install(commands); } diff --git a/praxiscore-script/src/main/java/org/praxislive/script/commands/MapCmds.java b/praxiscore-script/src/main/java/org/praxislive/script/commands/MapCmds.java new file mode 100644 index 00000000..83078165 --- /dev/null +++ b/praxiscore-script/src/main/java/org/praxislive/script/commands/MapCmds.java @@ -0,0 +1,136 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2024 Neil C Smith. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this work; if not, see http://www.gnu.org/licenses/ + * + * + * Please visit https://www.praxislive.org if you need additional information or + * have any questions. + */ +package org.praxislive.script.commands; + +import java.util.List; +import java.util.Map; +import org.praxislive.core.Value; +import org.praxislive.core.types.PArray; +import org.praxislive.core.types.PMap; +import org.praxislive.core.types.PNumber; +import org.praxislive.core.types.PString; +import org.praxislive.script.Command; +import org.praxislive.script.Env; +import org.praxislive.script.InlineCommand; +import org.praxislive.script.Namespace; + +/** + * + */ +class MapCmds { + + private static final CreateMap MAP = new CreateMap(); + private static final MapGet MAP_GET = new MapGet(); + private static final MapKeys MAP_KEYS = new MapKeys(); + private static final MapSize MAP_SIZE = new MapSize(); + + private MapCmds() { + } + + static void install(Map commands) { + commands.put("map", MAP); + commands.put("map-get", MAP_GET); + commands.put("map-keys", MAP_KEYS); + commands.put("map-size", MAP_SIZE); + } + + private static class CreateMap implements InlineCommand { + + @Override + public List process(Env context, Namespace namespace, List args) throws Exception { + if (args.isEmpty()) { + return List.of(PMap.EMPTY); + } + + int size = args.size(); + if (size % 2 != 0) { + throw new IllegalArgumentException("Map requires an even number of arguments"); + } + + var builder = PMap.builder(); + for (int i = 0; i < size; i += 2) { + builder.put(args.get(i).toString(), args.get(i + 1)); + } + + return List.of(builder.build()); + } + + } + + private static class MapGet implements InlineCommand { + + @Override + public List process(Env context, Namespace namespace, List args) throws Exception { + if (args.size() != 2) { + throw new IllegalArgumentException("Incorrect number of arguments"); + } + + PMap map = PMap.from(args.get(0)) + .orElseThrow(() -> new IllegalArgumentException("Argument is not a map")); + String key = args.get(1).toString(); + + Value result = map.get(key); + if (result == null) { + throw new IllegalArgumentException("Unknown map key"); + } + return List.of(result); + } + + } + + private static class MapKeys implements InlineCommand { + + @Override + public List process(Env context, Namespace namespace, List args) throws Exception { + if (args.size() != 1) { + throw new IllegalArgumentException("Incorrect number of arguments"); + } + + PMap map = PMap.from(args.get(0)) + .orElseThrow(() -> new IllegalArgumentException("Argument is not a map")); + + PArray result = map.keys().stream() + .map(PString::of) + .collect(PArray.collector()); + + return List.of(result); + } + + } + + private static class MapSize implements InlineCommand { + + @Override + public List process(Env context, Namespace namespace, List args) throws Exception { + if (args.size() != 1) { + throw new IllegalArgumentException("Incorrect number of arguments"); + } + + PMap map = PMap.from(args.get(0)) + .orElseThrow(() -> new IllegalArgumentException("Argument is not a map")); + + return List.of(PNumber.of(map.size())); + } + + } + +} diff --git a/praxiscore-script/src/test/java/org/praxislive/script/DefaultScriptServiceTest.java b/praxiscore-script/src/test/java/org/praxislive/script/DefaultScriptServiceTest.java index f445cbe3..3309aa6e 100644 --- a/praxiscore-script/src/test/java/org/praxislive/script/DefaultScriptServiceTest.java +++ b/praxiscore-script/src/test/java/org/praxislive/script/DefaultScriptServiceTest.java @@ -128,12 +128,13 @@ public void testEvalInline() throws Exception { logTest("testEvalInline"); String script = """ eval --inline { - set X 42 + var X 42 /hub.value $X } + set X [echo $X $X] /hub.value $X eval { - set Y 84 + var Y 84 /hub.value $Y } /hub.value $Y @@ -143,7 +144,7 @@ public void testEvalInline() throws Exception { hub.start(); hub.send("/script.eval", "/hub.result", script); - for (String expected : new String[]{"42", "42", "84"}) { + for (String expected : new String[]{"42", "4242", "84"}) { Call call = hub.poll(); logCall("Value received", call); assertEquals("/hub.value", call.to().toString()); diff --git a/praxiscore-script/src/test/java/org/praxislive/script/commands/ArrayCmdsTest.java b/praxiscore-script/src/test/java/org/praxislive/script/commands/ArrayCmdsTest.java new file mode 100644 index 00000000..9ef5749e --- /dev/null +++ b/praxiscore-script/src/test/java/org/praxislive/script/commands/ArrayCmdsTest.java @@ -0,0 +1,206 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2024 Neil C Smith. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this work; if not, see http://www.gnu.org/licenses/ + * + * + * Please visit https://www.praxislive.org if you need additional information or + * have any questions. + */ +package org.praxislive.script.commands; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.praxislive.core.ControlAddress; +import org.praxislive.core.Value; +import org.praxislive.core.types.PArray; +import org.praxislive.core.types.PBoolean; +import org.praxislive.core.types.PNumber; +import org.praxislive.core.types.PString; +import org.praxislive.script.Command; +import org.praxislive.script.InlineCommand; + +import static org.junit.jupiter.api.Assertions.*; +import static org.praxislive.script.commands.Utils.*; + +/** + * + */ +public class ArrayCmdsTest { + + private static final int V0 = 42; + private static final boolean V1 = true; + private static final String V2 = "FOO"; + private static final PArray V3 = PArray.of( + ControlAddress.of("/root.info"), + ControlAddress.of("/root.meta") + ); + + private static final Map CMDS; + + static { + CMDS = new HashMap<>(); + ArrayCmds.install(CMDS); + } + + @Test + public void testArrayCommand() throws Exception { + logTest("testArrayCommand"); + InlineCommand array = (InlineCommand) CMDS.get("array"); + List values = List.of( + Value.ofObject(V0), + Value.ofObject(V1), + Value.ofObject(V2), + Value.ofObject(V3) + ); + List resultList = array.process(env(), namespace(), values); + logResult("Command result of array", resultList); + assertEquals(1, resultList.size()); + PArray result = PArray.from(resultList.get(0)).orElseThrow(); + assertEquals(4, result.size()); + assertEquals(V0, PNumber.from(result.get(0)).orElseThrow().toIntValue()); + assertEquals(V1, PBoolean.from(result.get(1)).orElseThrow().value()); + assertEquals(V2, PString.from(result.get(2)).orElseThrow().value()); + assertEquals(V3, result.get(3)); + + resultList = array.process(env(), namespace(), List.of()); + logResult("Command result of array no-args", resultList); + assertEquals(1, resultList.size()); + result = PArray.from(resultList.get(0)).orElseThrow(); + assertSame(PArray.EMPTY, result); + } + + @Test + public void testArrayGetCommand() throws Exception { + logTest("testArrayGetCommand"); + InlineCommand arrayGet = (InlineCommand) CMDS.get("array-get"); + PArray array = Stream.of(V0, V1, V2, V3) + .map(Value::ofObject) + .collect(PArray.collector()); + + List resultList = arrayGet.process(env(), namespace(), + List.of(array, PNumber.of(2))); + logResult("Command result of array-get 2", resultList); + assertEquals(1, resultList.size()); + Value result = resultList.get(0); + assertEquals(V2, result.toString()); + resultList = arrayGet.process(env(), namespace(), + List.of(array, PNumber.of(5))); + logResult("Command result of array-get 5", resultList); + assertEquals(1, resultList.size()); + result = resultList.get(0); + assertEquals(V1, PBoolean.from(result).orElseThrow().value()); + resultList = arrayGet.process(env(), namespace(), + List.of(array, PNumber.of(-1))); + logResult("Command result of array-get -1", resultList); + assertEquals(1, resultList.size()); + result = resultList.get(0); + assertEquals(V3, result); + + resultList = arrayGet.process(env(), namespace(), + List.of(PArray.EMPTY, PNumber.of(-1))); + logResult("Command result of array-get -1 on empty array", resultList); + assertEquals(1, resultList.size()); + result = resultList.get(0); + assertSame(PArray.EMPTY, result); + + assertThrows(IllegalArgumentException.class, () -> { + List noResult = arrayGet.process(env(), namespace(), List.of(PNumber.ONE)); + }); + + } + + @Test + public void testArrayJoinCommand() throws Exception { + logTest("testArrayJoinCommand"); + InlineCommand arrayJoin = (InlineCommand) CMDS.get("array-join"); + PArray array1 = Stream.of(V0, V1, V2, V3) + .map(Value::ofObject) + .collect(PArray.collector()); + PArray array2 = Stream.of(V3, V2, V1, V0) + .map(Value::ofObject) + .collect(PArray.collector()); + List resultList = arrayJoin.process(env(), namespace(), + List.of(array1, array2)); + logResult("Command result of array-join", resultList); + assertEquals(1, resultList.size()); + PArray result = PArray.from(resultList.get(0)).orElseThrow(); + assertEquals(8, result.size()); + PArray expected = Stream.of(V0, V1, V2, V3, V3, V2, V1, V0) + .map(Value::ofObject) + .collect(PArray.collector()); + assertEquals(expected, result); + + resultList = arrayJoin.process(env(), namespace(), List.of(array1, PArray.EMPTY)); + logResult("Command result of array-join empty with empty", resultList); + result = PArray.from(resultList.get(0)).orElseThrow(); + assertEquals(array1, result); + + } + + @Test + public void testArrayRangeCommand() throws Exception { + logTest("testArrayRangeCommand"); + InlineCommand arrayRange = (InlineCommand) CMDS.get("array-range"); + PArray array = Stream.of(V0, V1, V2, V3) + .map(Value::ofObject) + .collect(PArray.collector()); + List resultList = arrayRange.process(env(), namespace(), + List.of(array, PNumber.of(3))); + logResult("Command result of array-range 3", resultList); + assertEquals(1, resultList.size()); + PArray result = PArray.from(resultList.get(0)).orElseThrow(); + assertEquals(3, result.size()); + PArray expected = Stream.of(V0, V1, V2) + .map(Value::ofObject) + .collect(PArray.collector()); + assertEquals(expected, result); + resultList = arrayRange.process(env(), namespace(), + List.of(array, PNumber.of(1), PNumber.of(3))); + logResult("Command result of array-range 1 3", resultList); + assertEquals(1, resultList.size()); + result = PArray.from(resultList.get(0)).orElseThrow(); + assertEquals(2, result.size()); + expected = Stream.of(V1, V2) + .map(Value::ofObject) + .collect(PArray.collector()); + assertEquals(expected, result); + + assertThrows(IndexOutOfBoundsException.class, () -> { + List failResult = arrayRange.process(env(), namespace(), + List.of(array, PNumber.of(1), PNumber.of(5))); + }); + + } + + @Test + public void testArraySizeCommand() throws Exception { + logTest("testArraySizeCommand"); + InlineCommand arraySize = (InlineCommand) CMDS.get("array-size"); + PArray array = Stream.of(V0, V1, V2, V3) + .map(Value::ofObject) + .collect(PArray.collector()); + List resultList = arraySize.process(env(), namespace(), + List.of(array)); + logResult("Command result of array-size", resultList); + assertEquals(1, resultList.size()); + int result = PNumber.from(resultList.get(0)).orElseThrow().toIntValue(); + assertEquals(4, result); + } + +} diff --git a/praxiscore-script/src/test/java/org/praxislive/script/commands/MapCmdsTest.java b/praxiscore-script/src/test/java/org/praxislive/script/commands/MapCmdsTest.java new file mode 100644 index 00000000..7dce7264 --- /dev/null +++ b/praxiscore-script/src/test/java/org/praxislive/script/commands/MapCmdsTest.java @@ -0,0 +1,150 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2024 Neil C Smith. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this work; if not, see http://www.gnu.org/licenses/ + * + * + * Please visit https://www.praxislive.org if you need additional information or + * have any questions. + */ +package org.praxislive.script.commands; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.praxislive.core.ControlAddress; +import org.praxislive.core.Value; +import org.praxislive.core.types.PArray; +import org.praxislive.core.types.PBoolean; +import org.praxislive.core.types.PMap; +import org.praxislive.core.types.PNumber; +import org.praxislive.core.types.PString; +import org.praxislive.script.Command; +import org.praxislive.script.InlineCommand; + +import static org.junit.jupiter.api.Assertions.*; +import static org.praxislive.script.commands.Utils.*; + +/** + * + */ +public class MapCmdsTest { + + private static final String K1 = "Key1"; + private static final String K2 = "Key2"; + private static final String K3 = "Key3"; + private static final String K4 = "Key4"; + + private static final int V1 = 42; + private static final boolean V2 = true; + private static final String V3 = "FOO"; + private static final PArray V4 = PArray.of( + ControlAddress.of("/root.info"), + ControlAddress.of("/root.meta") + ); + + private static final PMap BASE_MAP = PMap.of( + K1, V1, K2, V2, K3, V3, K4, V4 + ); + + private static final Map CMDS; + + static { + CMDS = new HashMap<>(); + MapCmds.install(CMDS); + } + + @Test + public void testMapCommand() throws Exception { + logTest("testMapCommand"); + InlineCommand map = (InlineCommand) CMDS.get("map"); + List resultList = map.process(env(), namespace(), + List.of( + PString.of(K1), Value.ofObject(V1), + PString.of(K2), Value.ofObject(V2), + PString.of(K3), Value.ofObject(V3), + PString.of(K4), Value.ofObject(V4) + )); + logResult("Command result of map", resultList); + assertEquals(1, resultList.size()); + PMap result = PMap.from(resultList.get(0)).orElseThrow(); + assertEquals(BASE_MAP, result); + + resultList = map.process(env(), namespace(), List.of()); + logResult("Command result of map-empty", resultList); + assertEquals(1, resultList.size()); + result = PMap.from(resultList.get(0)).orElseThrow(); + assertSame(PMap.EMPTY, result); + + assertThrows(IllegalArgumentException.class, () -> { + List failResult = map.process(env(), namespace(), + List.of( + PString.of(K1), Value.ofObject(V1), + PString.of(K2), Value.ofObject(V2), + PString.of(K3), Value.ofObject(V3), + PString.of(K4) + )); + }); + + } + + @Test + public void testMapGetCommand() throws Exception { + logTest("testMapGetCommand"); + InlineCommand mapGet = (InlineCommand) CMDS.get("map-get"); + List resultList = mapGet.process(env(), namespace(), + List.of(BASE_MAP, PString.of(K3))); + logResult("Command result of map-get key3", resultList); + assertEquals(1, resultList.size()); + assertEquals(V3, resultList.get(0).toString()); + + assertThrows(IllegalArgumentException.class, () -> { + List failResult = mapGet.process(env(), namespace(), + List.of(PMap.EMPTY, PString.of(K3))); + }); + + } + + @Test + public void testMapKeysCommand() throws Exception { + logTest("testMapKeysCommand"); + InlineCommand mapKeys = (InlineCommand) CMDS.get("map-keys"); + List resultList = mapKeys.process(env(), namespace(), List.of(BASE_MAP)); + logResult("Command result of map-keys", resultList); + assertEquals(1, resultList.size()); + PArray result = PArray.from(resultList.get(0)).orElseThrow(); + PArray expected = PArray.of( + PString.of(K1), + PString.of(K2), + PString.of(K3), + PString.of(K4) + ); + assertEquals(expected, result); + } + + @Test + public void testMapSizeCommand() throws Exception { + logTest("testMapSizeCommand"); + InlineCommand mapSize = (InlineCommand) CMDS.get("map-size"); + List resultList = mapSize.process(env(), namespace(), List.of(BASE_MAP)); + logResult("Command result of map-size", resultList); + assertEquals(1, resultList.size()); + int result = PNumber.from(resultList.get(0)).orElseThrow().toIntValue(); + assertEquals(BASE_MAP.size(), result); + } + +} diff --git a/praxiscore-script/src/test/java/org/praxislive/script/commands/Utils.java b/praxiscore-script/src/test/java/org/praxislive/script/commands/Utils.java new file mode 100644 index 00000000..079801ca --- /dev/null +++ b/praxiscore-script/src/test/java/org/praxislive/script/commands/Utils.java @@ -0,0 +1,143 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2024 Neil C Smith. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * version 3 for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this work; if not, see http://www.gnu.org/licenses/ + * + * + * Please visit https://www.praxislive.org if you need additional information or + * have any questions. + */ +package org.praxislive.script.commands; + +import java.util.HashMap; +import java.util.Map; +import org.praxislive.core.ControlAddress; +import org.praxislive.core.Lookup; +import org.praxislive.core.PacketRouter; +import org.praxislive.script.Command; +import org.praxislive.script.Env; +import org.praxislive.script.Namespace; +import org.praxislive.script.Variable; + +/** + * + */ +class Utils { + + private static final boolean VERBOSE = Boolean.getBoolean("praxis.test.verbose"); + + private Utils() { + } + + static Env env() { + return new EmptyEnv(); + } + + static Namespace namespace() { + return new NS(); + } + + static void logTest(String testName) { + if (VERBOSE) { + System.out.println(); + System.out.println(testName); + System.out.println("=================="); + } + } + + static void logResult(String description, Object value) { + if (VERBOSE) { + System.out.println(description); + System.out.println(value); + } + } + + private static class EmptyEnv implements Env { + + @Override + public ControlAddress getAddress() { + return ControlAddress.of("/dev.null"); + } + + @Override + public Lookup getLookup() { + return Lookup.EMPTY; + } + + @Override + public PacketRouter getPacketRouter() { + return p -> { + }; + } + + @Override + public long getTime() { + return System.nanoTime(); + } + + } + + private static class NS implements Namespace { + + private final NS parent; + private final Map variables; + private final Map commands; + + private NS() { + this(null); + } + + private NS(NS parent) { + this.parent = parent; + variables = new HashMap<>(); + commands = Map.of(); + } + + @Override + public Variable getVariable(String id) { + Variable var = variables.get(id); + if (var == null && parent != null) { + return parent.getVariable(id); + } else { + return var; + } + } + + @Override + public void addVariable(String id, Variable var) { + if (variables.containsKey(id)) { + throw new IllegalArgumentException(); + } + variables.put(id, var); + } + + @Override + public Command getCommand(String id) { + return commands.get(id); + } + + @Override + public void addCommand(String id, Command cmd) { + throw new UnsupportedOperationException(); + } + + @Override + public Namespace createChild() { + return new NS(this); + } + + } + +}