diff --git a/src/main/java/com/annimon/ownlang/parser/ast/UseStatement.java b/src/main/java/com/annimon/ownlang/parser/ast/UseStatement.java index 7a40d23..568b63b 100644 --- a/src/main/java/com/annimon/ownlang/parser/ast/UseStatement.java +++ b/src/main/java/com/annimon/ownlang/parser/ast/UseStatement.java @@ -1,5 +1,9 @@ package com.annimon.ownlang.parser.ast; +import com.annimon.ownlang.exceptions.TypeException; +import com.annimon.ownlang.lib.ArrayValue; +import com.annimon.ownlang.lib.Types; +import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.modules.Module; import java.lang.reflect.Method; @@ -21,9 +25,24 @@ public final class UseStatement extends InterruptableNode implements Statement { @Override public void execute() { super.interruptionCheck(); + final Value value = expression.eval(); + switch (value.type()) { + case Types.ARRAY: + for (Value module : ((ArrayValue) value)) { + loadModule(module.asString()); + } + break; + case Types.STRING: + loadModule(value.asString()); + break; + default: + throw new TypeException("Array or string required"); + } + } + + private void loadModule(String name) { try { - final String moduleName = expression.eval().asString(); - final Module module = (Module) Class.forName(String.format(PACKAGE, moduleName, moduleName)).newInstance(); + final Module module = (Module) Class.forName(String.format(PACKAGE, name, name)).newInstance(); module.init(); } catch (Exception ex) { throw new RuntimeException(ex); @@ -31,14 +50,30 @@ public final class UseStatement extends InterruptableNode implements Statement { } public void loadConstants() { + final Value value = expression.eval(); + switch (value.type()) { + case Types.ARRAY: + for (Value module : ((ArrayValue) value)) { + loadConstants(module.asString()); + } + break; + case Types.STRING: + loadConstants(value.asString()); + break; + default: + throw new TypeException("Array or string required"); + } + } + + private void loadConstants(String moduleName) { try { - final String moduleName = expression.eval().asString(); final Class moduleClass = Class.forName(String.format(PACKAGE, moduleName, moduleName)); final Method method = moduleClass.getMethod(INIT_CONSTANTS_METHOD); if (method != null) { method.invoke(this); } } catch (Exception ex) { + // ignore } } diff --git a/src/main/java/com/annimon/ownlang/parser/linters/UseWithNonStringValueValidator.java b/src/main/java/com/annimon/ownlang/parser/linters/UseWithNonStringValueValidator.java index fa4745c..de1e51b 100644 --- a/src/main/java/com/annimon/ownlang/parser/linters/UseWithNonStringValueValidator.java +++ b/src/main/java/com/annimon/ownlang/parser/linters/UseWithNonStringValueValidator.java @@ -1,6 +1,7 @@ package com.annimon.ownlang.parser.linters; import com.annimon.ownlang.Console; +import com.annimon.ownlang.lib.ArrayValue; import com.annimon.ownlang.lib.Types; import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.parser.ast.*; @@ -23,9 +24,26 @@ public final class UseWithNonStringValueValidator extends LintVisitor { } final Value value = ((ValueExpression) st.expression).value; - if (value.type() != Types.STRING) { - Console.error(String.format( - "Warning: `use` with %s - %s, not string", Types.typeToString(value.type()), value.asString())); + switch (value.type()) { + case Types.STRING: + // ok + break; + case Types.ARRAY: + // ok, need additional check + for (Value module : ((ArrayValue) value)) { + if (module.type() != Types.STRING) { + warnWrongType(module); + } + } + break; + default: + warnWrongType(value); } } + + private void warnWrongType(Value value) { + Console.error(String.format( + "Warning: `use` with %s - %s, not string", + Types.typeToString(value.type()), value.asString())); + } } diff --git a/src/test/resources/modules/base64/base64.own b/src/test/resources/modules/base64/base64.own index 841dfdd..b9e11db 100644 --- a/src/test/resources/modules/base64/base64.own +++ b/src/test/resources/modules/base64/base64.own @@ -1,6 +1,4 @@ -use "base64" -use "functional" -use "types" +use ["base64", "functional", "types"] base64Example = [0x42, 0x61, 0x73, 0x65, 0x36, 0x34, 0x20, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65] base64Example_enc = [0x51, 0x6D, 0x46, 0x7A, 0x5A, 0x54, 0x59, 0x30, diff --git a/src/test/resources/modules/files/files.own b/src/test/resources/modules/files/files.own index f4591b8..4f9c7e3 100644 --- a/src/test/resources/modules/files/files.own +++ b/src/test/resources/modules/files/files.own @@ -1,5 +1,4 @@ -use "files" -use "types" +use ["files", "types"] def testFiles() { // writeLong diff --git a/src/test/resources/modules/functional/stream.own b/src/test/resources/modules/functional/stream.own index c3c5ae3..6268143 100644 --- a/src/test/resources/modules/functional/stream.own +++ b/src/test/resources/modules/functional/stream.own @@ -1,6 +1,4 @@ -use "std" -use "functional" -use "math" +use ["std", "functional", "math"] def testStream() { data = [1,2,3,4,5,6,7] diff --git a/src/test/resources/modules/java/classes.own b/src/test/resources/modules/java/classes.own index 04a8dd2..2ccb6ad 100644 --- a/src/test/resources/modules/java/classes.own +++ b/src/test/resources/modules/java/classes.own @@ -1,5 +1,4 @@ -use "std" -use "java" +use ["std", "java"] def testCheckNull() { assertTrue(isNull(null)) diff --git a/src/test/resources/modules/std/range.own b/src/test/resources/modules/std/range.own index d1e13fe..ae616db 100644 --- a/src/test/resources/modules/std/range.own +++ b/src/test/resources/modules/std/range.own @@ -1,6 +1,4 @@ -use "std" -use "types" -use "functional" +use ["std", "types", "functional"] def testRangeParams() { x = range(10) diff --git a/src/test/resources/modules/yaml/yamldecode.own b/src/test/resources/modules/yaml/yamldecode.own index 1cc2565..fc335af 100644 --- a/src/test/resources/modules/yaml/yamldecode.own +++ b/src/test/resources/modules/yaml/yamldecode.own @@ -1,24 +1,22 @@ -use "std" -use "yaml" -use "ounit" +use ["std", "yaml", "ounit"] x = yamldecode(" name: \"std\" scope: \"both\" desc: \"Contains common functions\" - desc_ru: \"Содержит вспомогательные функции общего назначения\" + desc_ru: \"Содержит вспомогательные функции общего назначения\" constants: [] functions: - name: \"arrayCombine\" args: \"keys, values\" desc: \"creates map by combining two arrays\" - desc_ru: \"создаёт объект на основе двух массивов\" + desc_ru: \"создаёт объект РЅР° РѕСЃРЅРѕРІРµ РґРІСѓС… массивов\" - name: \"typeof\" args: \"value\" desc: \"returns the type of value\" - desc_ru: \"возвращает тип переданного значения\" + desc_ru: \"возвращает тип переданного значения\" example: |- print typeof(1) // 1 (NUMBER) print typeof(\"text\") // 2 (STRING) @@ -30,4 +28,4 @@ assertEquals("both", x.scope) assertEquals(0, length(x.constants)) assertEquals(2, length(x.functions)) assertEquals("arrayCombine", x.functions[0].name) -assertEquals("возвращает тип переданного значения", x.functions[1].desc_ru) \ No newline at end of file +assertEquals("возвращает тип переданного значения", x.functions[1].desc_ru) \ No newline at end of file diff --git a/src/test/resources/modules/yaml/yamlencode.own b/src/test/resources/modules/yaml/yamlencode.own index a54e33d..cf2e465 100644 --- a/src/test/resources/modules/yaml/yamlencode.own +++ b/src/test/resources/modules/yaml/yamlencode.own @@ -1,6 +1,4 @@ -use "std" -use "yaml" -use "ounit" +use ["std", "yaml", "ounit"] yml = yamlencode({ "name": "Yaml Example",