From 7754c9deb867a955cd4a53818b2cb723bd92b3ad Mon Sep 17 00:00:00 2001 From: Pilow Date: Thu, 29 Aug 2019 13:06:16 +0200 Subject: [PATCH 001/319] [compilation] Improve java compilation process and errors Signed-off-by: Pilow --- .../leekscript/compiler/JavaCompiler.java | 123 +++++++++++------- .../java/leekscript/compiler/LeekScript.java | 12 +- .../compiler/LeekScriptException.java | 11 +- 3 files changed, 82 insertions(+), 64 deletions(-) diff --git a/src/main/java/leekscript/compiler/JavaCompiler.java b/src/main/java/leekscript/compiler/JavaCompiler.java index 5b226da5..fb39eaac 100644 --- a/src/main/java/leekscript/compiler/JavaCompiler.java +++ b/src/main/java/leekscript/compiler/JavaCompiler.java @@ -1,8 +1,10 @@ package leekscript.compiler; +import java.io.BufferedReader; import java.io.File; +import java.io.IOException; import java.io.InputStream; -import java.util.Arrays; +import java.io.InputStreamReader; public class JavaCompiler { @@ -13,23 +15,6 @@ public class JavaCompiler { private final File mInput; private int mStatus = 0; - private static class Worker extends Thread { - private final Process process; - private Integer exit; - - private Worker(Process process) { - this.process = process; - } - - public void run() { - try { - exit = process.waitFor(); - } catch (InterruptedException ignore) { - return; - } - } - } - public JavaCompiler(File input) { mInput = input; } @@ -43,45 +28,35 @@ public void compile(String jar) throws Exception { return; } - Process process = Runtime.getRuntime().exec(new String[] { "javac", "-encoding", "utf8", "-nowarn", "-classpath", jar, mInput.getAbsolutePath() }); + String[] args = new String[] { "javac", "-encoding", "utf8", "-classpath", jar, mInput.getPath() }; + // System.out.println(String.join(" ", args)); + ProcessBuilder pb = new ProcessBuilder(args); + Worker worker = new Worker(pb); + Process process = worker.begin(); + + Gobbler outGobbler = new Gobbler(process.getInputStream()); + Gobbler errGobbler = new Gobbler(process.getErrorStream()); + Thread outThread = new Thread(outGobbler); + Thread errThread = new Thread(errGobbler); + outThread.start(); + errThread.start(); - Worker worker = new Worker(process); - worker.start(); try { - worker.join(10000); if (worker.exit == null) { throw new CompilationException("too_long_java"); } - - // new - // File(System.getProperty("user.dir"))); - boolean error = false; - InputStream iin = process.getErrorStream(); - if (iin != null) { - byte[] e = new byte[128]; - int nb; - StringBuilder sb = new StringBuilder(); - while ((nb = iin.read(e)) > 0) { - sb.append(new String(Arrays.copyOf(e, nb))); - } - if (sb.length() > 0) - throw new CompilationException(sb.toString()); - } - iin = process.getInputStream(); - if (iin != null) { - byte[] e = new byte[128]; - int nb; - while ((nb = iin.read(e)) > 0) { - System.out.println(new String(Arrays.copyOf(e, nb))); - } - } + outThread.join(); + errThread.join(); process.waitFor(); - if (process.exitValue() != 0) - error = true; - if (!error) + String error = errGobbler.getOuput(); + if (error.length() > 0) { + mStatus = END; + throw new CompilationException(error); + } + if (process.exitValue() == 0) { mStatus = END; - + } } catch (InterruptedException ex) { worker.interrupt(); Thread.currentThread().interrupt(); @@ -94,4 +69,54 @@ public void compile(String jar) throws Exception { public static int getStatus() { return 0; } + + public static class Worker extends Thread { + private final ProcessBuilder pb; + private Process p; + public Integer exit; + public Worker(ProcessBuilder pb) { + this.pb = pb; + } + public Process begin() { + try { + p = pb.start(); + } catch (IOException e) { + e.printStackTrace(); + } + super.start(); + return p; + } + public void run() { + try { + exit = p.waitFor(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static class Gobbler implements Runnable { + private BufferedReader reader; + private StringBuilder output; + public Gobbler(InputStream inputStream) { + this.reader = new BufferedReader(new InputStreamReader(inputStream)); + } + public void run() { + String line; + output = new StringBuilder(); + try { + while ((line = reader.readLine()) != null) { + // Limit the length of the line to 500 characters + output.append(line.substring(0, Math.min(line.length(), 500)) + "\n"); + } + reader.close(); + } catch (IOException e) { + System.err.println("ERROR: " + e.getMessage()); + e.printStackTrace(); + } + } + public String getOuput() { + return this.output.toString(); + } + } } diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 10ce5b69..62fe5e2f 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -150,16 +150,8 @@ private static AI compile(AIFile ai, String AIClass, String jar, boolean noca try { compiler.compile(jar); status = JavaCompiler.getStatus(); - } catch (CompilationException e) { - - error = e.getMessage(); - // ErrorManager.registerCompilationError(ai, e.getMessage()); - status = JavaCompiler.ERROR; - } catch (Exception e) { - - // ErrorManager.exception(e, ai.getId()); - ErrorManager.exception(e); + error = e.getMessage(); status = JavaCompiler.ERROR; } if (status == JavaCompiler.ERROR) { @@ -183,6 +175,6 @@ public static void throwException(String error) throws LeekScriptException { throw new LeekScriptException(LeekScriptException.CODE_TOO_LARGE); } } - throw new LeekScriptException(LeekScriptException.CANT_COMPILE); + throw new LeekScriptException(LeekScriptException.CANT_COMPILE, error); } } \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/LeekScriptException.java b/src/main/java/leekscript/compiler/LeekScriptException.java index 1fb49e96..f241ce18 100644 --- a/src/main/java/leekscript/compiler/LeekScriptException.java +++ b/src/main/java/leekscript/compiler/LeekScriptException.java @@ -9,22 +9,23 @@ public class LeekScriptException extends Exception { public final static int CODE_TOO_LARGE_FUNCTION = 2; private final int mType; - private String mFunction = null; + private String mMessage = null; public LeekScriptException(int type) { mType = type; } - public LeekScriptException(int type, String function) { + public LeekScriptException(int type, String message) { mType = type; - mFunction = function; + mMessage = message; } public int getType() { return mType; } - public String getFunction() { - return mFunction; + @Override + public String getMessage() { + return mMessage; } } From 8c130128feade6ae1b530349f7c7c0372da63cc3 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 30 Aug 2019 13:52:17 +0200 Subject: [PATCH 002/319] [error] Improve error data to fix a bug with too long string --- src/main/java/leekscript/compiler/JavaWriter.java | 6 +++--- src/main/java/leekscript/runner/AI.java | 7 +++++-- src/test/java/test/TestAI.java | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/leekscript/compiler/JavaWriter.java b/src/main/java/leekscript/compiler/JavaWriter.java index d53cab26..f669f384 100644 --- a/src/main/java/leekscript/compiler/JavaWriter.java +++ b/src/main/java/leekscript/compiler/JavaWriter.java @@ -72,16 +72,16 @@ else if (string.charAt(i + 1) == 't') } public void writeErrorFunction(IACompiler comp, String ai) { - mCode.append("protected String getErrorString(){ return \"["); + mCode.append("protected String[] getErrorString(){ return new String[]{"); boolean first = true; for (Line l : mLines) { if (!first) mCode.append(","); else first = false; - mCode.append("[").append(l.mJavaLine).append(",\\\"").append(escape(l.mAI.getPath())).append("\\\",").append(l.mCodeLine).append("]"); + mCode.append("\"[").append(l.mJavaLine).append(",\\\"").append(escape(l.mAI.getPath())).append("\\\",").append(l.mCodeLine).append("]\""); } - mCode.append("]\";}\n protected String getAItring(){ return \""); + mCode.append("};}\n protected String getAItring(){ return \""); mCode.append(escape(ai)); mCode.append("\";}"); } diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 35a26eec..66e6b0c5 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -73,7 +73,10 @@ public String getErrorMessage(Throwable e) { protected String getErrorLocalisation(int line) { if (mErrorObject == null) { - mErrorObject = JSONArray.parseArray(getErrorString()); + mErrorObject = new JSONArray(); + for (String error : getErrorString()) { + mErrorObject.add(JSON.parseArray(error)); + } thisObject = getAItring(); } int value = 0; @@ -325,7 +328,7 @@ else if (type == AILog.STANDARD) logs.addSystemLog(type, getErrorMessage(elements), key, parameters); } - protected abstract String getErrorString(); + protected abstract String[] getErrorString(); protected abstract String getAItring(); diff --git a/src/test/java/test/TestAI.java b/src/test/java/test/TestAI.java index e5ceeca1..0ba0c97f 100644 --- a/src/test/java/test/TestAI.java +++ b/src/test/java/test/TestAI.java @@ -9,7 +9,7 @@ public TestAI() throws Exception { } @Override - protected String getErrorString() { + protected String[] getErrorString() { // TODO Auto-generated method stub return null; } From b7d1ec8a8bfc06055a0db52bc78d4654694abe37 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 1 Sep 2019 02:02:43 +0200 Subject: [PATCH 003/319] [functions] Simplify functions operations loading and usage --- .../java/leekscript/functions/Function.java | 30 ---------------- .../java/leekscript/functions/Functions.java | 36 +++---------------- .../java/leekscript/runner/ILeekFunction.java | 1 + .../java/leekscript/runner/LeekFunctions.java | 22 +++++------- 4 files changed, 13 insertions(+), 76 deletions(-) delete mode 100644 src/main/java/leekscript/functions/Function.java diff --git a/src/main/java/leekscript/functions/Function.java b/src/main/java/leekscript/functions/Function.java deleted file mode 100644 index aee31092..00000000 --- a/src/main/java/leekscript/functions/Function.java +++ /dev/null @@ -1,30 +0,0 @@ -package leekscript.functions; - -public class Function { - - private final String mName; - private final int mArgumentCount; - private final int mOperations; - - public Function(String name, int argumentcount, String operations) { - mName = name; - mArgumentCount = argumentcount; - int nb = -1; - try { - nb = Integer.parseInt(operations); - } catch (Exception e) {} - mOperations = nb; - } - - public String getName() { - return mName; - } - - public int countArguments() { - return mArgumentCount; - } - - public int getOperations() { - return mOperations; - } -} diff --git a/src/main/java/leekscript/functions/Functions.java b/src/main/java/leekscript/functions/Functions.java index cd1301f8..b6c62dd1 100644 --- a/src/main/java/leekscript/functions/Functions.java +++ b/src/main/java/leekscript/functions/Functions.java @@ -1,20 +1,18 @@ package leekscript.functions; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.TreeMap; import com.alibaba.fastjson.JSONObject; +import leekscript.runner.LeekFunctions; + public class Functions { - private static boolean sReady = false; - private static List sFunctions = new ArrayList(); private static Map sVariableOperations = new TreeMap(); - public static void addFunction(Function function) { - sFunctions.add(function); + public static void addFunctionOperations(String function, int operations) { + LeekFunctions.getValue(function).setOperations(operations); } public static void addVariableOperations(String name, String variableOperations) { @@ -24,30 +22,4 @@ public static void addVariableOperations(String name, String variableOperations) public static VariableOperations getVariableOperations(String name) { return sVariableOperations.get(name); } - - public static boolean isReady() { - - return sReady; - } - - public static void setReady(boolean ready) { - sReady = ready; - } - - public static Function getFunction(String name, int params) { - for (Function f : sFunctions) { - if (f.getName().equals(name) && f.countArguments() == params) - return f; - } - return null; - } - - public static Integer getOperations(String name) { - for (Function f : sFunctions) { - if (f.getName().equals(name)) { - return f.getOperations(); - } - } - return 1; - } } diff --git a/src/main/java/leekscript/runner/ILeekFunction.java b/src/main/java/leekscript/runner/ILeekFunction.java index f3d5b2ae..86979fe9 100644 --- a/src/main/java/leekscript/runner/ILeekFunction.java +++ b/src/main/java/leekscript/runner/ILeekFunction.java @@ -3,6 +3,7 @@ import leekscript.runner.values.AbstractLeekValue; public interface ILeekFunction { + abstract public void setOperations(int operations); abstract public int getArguments(); abstract public int getArgumentsMin(); abstract public boolean isExtra(); diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index bec06e55..903b09af 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -1301,7 +1301,7 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu private int mArguments; private int mArgumentsMin; - private Integer mOperations = null; + private int mOperations = 1; protected VariableOperations mVariableOperations = null; public static final int DOUBLE = 1; @@ -1365,15 +1365,6 @@ public boolean isExtra() { } public int getOperations() { - if (mOperations == null) { - if (!Functions.isReady()) { - return 0; - } - mOperations = Functions.getOperations(this.name()); - if (mOperations <= 0) { - mOperations = 1; - } - } return mOperations; } @@ -1385,10 +1376,9 @@ public boolean hasVariableOperations() { } public static ILeekFunction getValue(String name) { - for (LeekFunctions func : LeekFunctions.values()) { - if (func.name().equals(name)) - return func; - } + try { + return LeekFunctions.valueOf(name); + } catch (Exception e) {} if (extraFunctions != null) { try { Class extra = Class.forName(extraFunctions); @@ -1431,6 +1421,10 @@ public int cost() { return 1; } + public void setOperations(int operations) { + mOperations = operations; + } + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { leekIA.addOperations(getOperations()); } From 190d8b79f16a8c0dee158262d18267efe48794cb Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 1 Sep 2019 02:51:36 +0200 Subject: [PATCH 004/319] [function] Merge addFunctionOperations and addVariableOperations --- src/main/java/leekscript/functions/Functions.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/leekscript/functions/Functions.java b/src/main/java/leekscript/functions/Functions.java index b6c62dd1..8c951b4d 100644 --- a/src/main/java/leekscript/functions/Functions.java +++ b/src/main/java/leekscript/functions/Functions.java @@ -11,12 +11,11 @@ public class Functions { private static Map sVariableOperations = new TreeMap(); - public static void addFunctionOperations(String function, int operations) { - LeekFunctions.getValue(function).setOperations(operations); - } - - public static void addVariableOperations(String name, String variableOperations) { - sVariableOperations.put(name, new VariableOperations(JSONObject.parseObject(variableOperations))); + public static void addFunctionOperations(String function, int operations, String variableOperations) { + LeekFunctions.getValue(function).setOperations(Math.max(1, operations)); + if (variableOperations != null) { + sVariableOperations.put(function, new VariableOperations(JSONObject.parseObject(variableOperations))); + } } public static VariableOperations getVariableOperations(String name) { From 600b840c20cc0d1c0480c19093207b0bf93e35b1 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 1 Sep 2019 03:14:19 +0200 Subject: [PATCH 005/319] [functions] Add a null check --- src/main/java/leekscript/functions/Functions.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/functions/Functions.java b/src/main/java/leekscript/functions/Functions.java index 8c951b4d..226ceb66 100644 --- a/src/main/java/leekscript/functions/Functions.java +++ b/src/main/java/leekscript/functions/Functions.java @@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONObject; +import leekscript.runner.ILeekFunction; import leekscript.runner.LeekFunctions; public class Functions { @@ -12,7 +13,10 @@ public class Functions { private static Map sVariableOperations = new TreeMap(); public static void addFunctionOperations(String function, int operations, String variableOperations) { - LeekFunctions.getValue(function).setOperations(Math.max(1, operations)); + ILeekFunction f = LeekFunctions.getValue(function); + if (f != null) { + f.setOperations(Math.max(1, operations)); + } if (variableOperations != null) { sVariableOperations.put(function, new VariableOperations(JSONObject.parseObject(variableOperations))); } From 7e9ef938d063ded89215b952a0cf73a2a5f061c3 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 1 Sep 2019 15:20:09 +0200 Subject: [PATCH 006/319] [aifile] Add an id attribute to AIFile (used by Leek Wars generator) --- src/main/java/leekscript/compiler/AIFile.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/AIFile.java b/src/main/java/leekscript/compiler/AIFile.java index 3d51b043..cc78074d 100644 --- a/src/main/java/leekscript/compiler/AIFile.java +++ b/src/main/java/leekscript/compiler/AIFile.java @@ -8,12 +8,25 @@ public class AIFile { private String code; private C context; private String javaClassName; - + private int id; + public AIFile(String path, String code, C context) { this.path = path; this.code = code; this.context = context; } + public AIFile(String path, String code, C context, int id) { + this.path = path; + this.code = code; + this.context = context; + this.id = id; + } + public int getId() { + return id; + } + public void setId(int id) { + this.id = id; + } public String getCode() { return code; } From cd0f85e527888705b4e011f08a46748e42c11137 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 1 Sep 2019 15:20:32 +0200 Subject: [PATCH 007/319] [aicompiler] Use AI ids for analyze results --- src/main/java/leekscript/compiler/IACompiler.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index 993795d9..09ec06c2 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -21,7 +21,7 @@ public void addError(AIFile ia_context, int line, int pos, String word, Strin mErrors = true; JSONArray error = new JSONArray(); error.add(0); - error.add(ia_context); + error.add(ia_context.getId()); error.add(line); error.add(pos); error.add(word); @@ -35,7 +35,7 @@ public void addError(AIFile ia_context, String informations) { mErrors = true; JSONArray error = new JSONArray(); error.add(1); - error.add(ia_context); + error.add(ia_context.getId()); error.add(informations); mInformations.add(error); } @@ -43,7 +43,7 @@ public void addError(AIFile ia_context, String informations) { public void addInformations(AIFile ia_context, int level) { JSONArray error = new JSONArray(); error.add(2); - error.add(ia_context); + error.add(ia_context.getId()); error.add(level); mInformations.add(error); } From b4e7169bc628d4d38fd92e3a69a3a172e16400a5 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 1 Sep 2019 15:20:52 +0200 Subject: [PATCH 008/319] [iacompiler] Add an analyze method to simply check the validity of an AI --- .../java/leekscript/compiler/IACompiler.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index 09ec06c2..1ae9c771 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -48,6 +48,24 @@ public void addInformations(AIFile ia_context, int level) { mInformations.add(error); } + public String analyze(AIFile ai) throws LeekCompilerException { + try { + // On lance la compilation du code de l'IA + WordParser parser = new WordParser(ai); + // Si on est là c'est qu'on a une liste de words correcte, on peut commencer à lire + MainLeekBlock main = new MainLeekBlock(this, ai); + WordCompiler compiler = new WordCompiler(parser, main, ai); + compiler.readCode(); + // On sauvegarde les dépendances + addInformations(ai, main.getMinLevel()); + } catch (LeekCompilerException e) { + addError(e.getIA(), e.getLine(), e.getChar(), e.getWord(), e.getError(), e.getParameters()); + } catch (Exception e) { + addError(ai, e.getMessage()); + } + return mInformations.toJSONString(); + } + public String compile(AIFile ai, String AIClass) throws LeekCompilerException { JavaWriter writer = new JavaWriter(true); try { From ec697b5f0d1b5578d4a2fc354cefdff96a28e3ae Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 1 Sep 2019 18:54:24 +0200 Subject: [PATCH 009/319] [git] Ignore .vscode folder --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 17da52f3..463c1dc9 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ build/ .project /ai/ /bin/ +.vscode/ \ No newline at end of file From 93a0183cfba471417a52f50e9b093c4d09428cf3 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 2 Sep 2019 20:47:49 +0200 Subject: [PATCH 010/319] [resolver] Add method to create a default context --- .../java/leekscript/compiler/resolver/FileSystemResolver.java | 4 ++++ src/main/java/leekscript/compiler/resolver/Resolver.java | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index 5060fa94..bebc4be3 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -30,4 +30,8 @@ public AIFile resolve(String path, ResolverContext basecontex return null; } } + + public ResolverContext createContext(int parameter) { + return new FileSystemContext(Paths.get(".").toFile()); + } } diff --git a/src/main/java/leekscript/compiler/resolver/Resolver.java b/src/main/java/leekscript/compiler/resolver/Resolver.java index 41af7612..2bbee7bd 100644 --- a/src/main/java/leekscript/compiler/resolver/Resolver.java +++ b/src/main/java/leekscript/compiler/resolver/Resolver.java @@ -20,4 +20,6 @@ public Result(String code, C context) { * @return The result with the AI's code and context, or null if not found */ abstract public AIFile resolve(String path, ResolverContext context); + + public abstract ResolverContext createContext(int parameter); } From 200a24cf441dbbac8ea1d6e688a0baa979cfea71 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 2 Sep 2019 20:48:18 +0200 Subject: [PATCH 011/319] [leekscript] Add a compileFileContext method --- src/main/java/leekscript/compiler/LeekScript.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 62fe5e2f..ff6c4e02 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -10,6 +10,7 @@ import leekscript.compiler.resolver.FileSystemContext; import leekscript.compiler.resolver.FileSystemResolver; import leekscript.compiler.resolver.Resolver; +import leekscript.compiler.resolver.ResolverContext; import leekscript.runner.AI; import leekscript.runner.values.AbstractLeekValue; import leekscript.runner.values.ArrayLeekValue; @@ -50,6 +51,16 @@ public static AI compileFile(String filepath, String AIClass, String jar, boolea } return null; } + + public static AI compileFileContext(String filepath, String AIClass, String jar, ResolverContext context, boolean nocache) throws LeekScriptException, LeekCompilerException { + AIFile ai = getResolver().resolve(filepath, context); + if (ai != null) { + int id = (filepath + "_" + ai.getCode()).hashCode() & 0xfffffff; + ai.setJavaClassName("IA_" + id); + return compile(ai, AIClass, jar, nocache); + } + return null; + } public static AI compileSnippet(String snippet, String AIClass, String jar) throws LeekScriptException, LeekCompilerException { AIFile ai = new AIFile("", snippet, null); From 0804ac90d8ec20117b00444f8754b3abfdfa1ddd Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 2 Sep 2019 22:16:42 +0200 Subject: [PATCH 012/319] [test] Update test --- src/test/java/test/TestWithFile.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/java/test/TestWithFile.java b/src/test/java/test/TestWithFile.java index 0cdbaa20..11eeae2f 100644 --- a/src/test/java/test/TestWithFile.java +++ b/src/test/java/test/TestWithFile.java @@ -39,6 +39,10 @@ class CustomContext extends ResolverContext {} public AIFile resolve(String path, ResolverContext context) { return new AIFile(path, "return 'generated';", new CustomContext()); } + @Override + public ResolverContext createContext(int parameter) { + return null; + } }); assertEquals("generated", LeekScript.runFile("whatever")); LeekScript.resetResolver(); From 2562134e8b33d6f4dac8a141f4044590e6600c33 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 2 Sep 2019 22:43:34 +0200 Subject: [PATCH 013/319] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 145aa13a..58f60a5b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # LeekScript v1 First version of LeekScript language, built in Java. +Used in the [generator-v1](https://github.com/leek-wars/leekscript-v1) project. ### Build and run tests ``` From b554bec075877bce4c4315ebce842c78a91d2de6 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 2 Sep 2019 22:44:37 +0200 Subject: [PATCH 014/319] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 58f60a5b..76e1d9ca 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # LeekScript v1 First version of LeekScript language, built in Java. -Used in the [generator-v1](https://github.com/leek-wars/leekscript-v1) project. +Used in the [generator-v1](https://github.com/leek-wars/leek-wars-generator-v1) project. ### Build and run tests ``` From 1e4ba6983df88c58404444a34349bd1d3f2fc696 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 2 Sep 2019 22:45:33 +0200 Subject: [PATCH 015/319] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76e1d9ca..6f15540c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # LeekScript v1 First version of LeekScript language, built in Java. -Used in the [generator-v1](https://github.com/leek-wars/leek-wars-generator-v1) project. +Used in the [leek-wars-generator-v1](https://github.com/leek-wars/leek-wars-generator-v1) project. ### Build and run tests ``` From cbf8ec37377c788c94d660457c10f4b4efd77b7f Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 3 Sep 2019 21:14:31 +0200 Subject: [PATCH 016/319] [build] Remove useless dependency --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index de59f128..194c2d10 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,6 @@ repositories { } dependencies { - compile 'org.slf4j:slf4j-api:1.7.21' testCompile 'junit:junit:4.12' compile group: 'com.alibaba', name: 'fastjson', version: '1.1.25' } From 29bdc8f8f942050828e3ef7da28e49aab4b88e22 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 27 Oct 2019 14:28:40 +0100 Subject: [PATCH 017/319] [include] Fix include system --- .../compiler/bloc/MainLeekBlock.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 261c7a3a..3f91405e 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -25,11 +25,12 @@ public class MainLeekBlock extends AbstractLeekBlock { private int mAnonymousId = 1; private int mFunctionId = 1; - private final ArrayList mIncluded = new ArrayList(); + private final ArrayList mIncluded = new ArrayList(); private int mCounter = 0; private int mCountInstruction = 0; private final IACompiler mCompiler; + private String mAIName; @Override public int getCount() { @@ -39,7 +40,8 @@ public int getCount() { public MainLeekBlock(IACompiler compiler, AIFile ai) { super(null, null, 0, null); // On ajoute l'IA pour pas pouvoir l'include - mIncluded.add(ai.getPath()); + mIncluded.add(ai.getId()); + mAIName = ai.getPath(); mCompiler = compiler; mCompiler.setCurrentAI(ai); } @@ -69,14 +71,14 @@ public void setMinLevel(int min_level) { } public boolean includeAI(String path) throws Exception { - if (mIncluded.contains(path)) { - return true; - } AIFile ai = LeekScript.getResolver().resolve(path, mCompiler.getCurrentAI().getContext()); if (ai == null) { return false; } - mIncluded.add(ai.getPath()); + if (mIncluded.contains(ai.getId())) { + return true; + } + mIncluded.add(ai.getId()); AIFile previousAI = mCompiler.getCurrentAI(); mCompiler.setCurrentAI(ai); WordParser words = new WordParser(ai); @@ -191,7 +193,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { writer.addLine("return LeekValueManager.NULL;"); writer.addLine("}"); - writer.writeErrorFunction(mCompiler, mIncluded.get(0)); + writer.writeErrorFunction(mCompiler, mAIName); printFunctionInformations(writer); if (mRedefinedFunctions.size() > 0) { @@ -272,16 +274,16 @@ public void printFunctionInformations(JavaWriter writer) { */ /* * public abstract int userFunctionCount(int id); - * + * * public abstract boolean[] userFunctionReference(int id); - * + * * public abstract AbstractLeekValue userFunctionExecute(int id, * AbstractLeekValue[] value); - * + * * public abstract int anonymousFunctionCount(int id); - * + * * public abstract boolean[] anonymousFunctionReference(int id); - * + * * public abstract AbstractLeekValue anonymousFunctionExecute(int id, * AbstractLeekValue[] value); */ From 9db3a96624f0e3222610fc73b3b62f1765b0f352 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 28 Oct 2019 19:00:05 +0100 Subject: [PATCH 018/319] [build] Update build.gradle to build a jar properly --- build.gradle | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/build.gradle b/build.gradle index 194c2d10..fde2821e 100644 --- a/build.gradle +++ b/build.gradle @@ -9,6 +9,16 @@ test { jar.baseName = 'leekscript' libsDirName = '..' +jar { + baseName = 'leekscript' + manifest { + attributes "Main-Class": "leekscript.TopLevel" + } + from { + configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } + } +} + repositories { jcenter() } From 75dafa856f2d7a6cfbba4f69c75227d7ffc3a61e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Mon, 28 Oct 2019 19:05:17 +0100 Subject: [PATCH 019/319] Update README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 6f15540c..adcdb338 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,14 @@ First version of LeekScript language, built in Java. Used in the [leek-wars-generator-v1](https://github.com/leek-wars/leek-wars-generator-v1) project. +### Build +``` +gradle jar +``` +### Run a console +``` +java -jar leekscript.jar +``` ### Build and run tests ``` gradle jar test From a74d16600dd1e47a503038ba9deac58ab49249d4 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 29 Oct 2019 22:11:51 +0100 Subject: [PATCH 020/319] [afilei] Generate a id from full path hash code to get a better unique id --- src/main/java/leekscript/compiler/AIFile.java | 10 +---- .../java/leekscript/compiler/IACompiler.java | 7 ++-- .../java/leekscript/compiler/LeekScript.java | 41 ++++++++----------- .../compiler/resolver/FileSystemResolver.java | 11 ++--- 4 files changed, 29 insertions(+), 40 deletions(-) diff --git a/src/main/java/leekscript/compiler/AIFile.java b/src/main/java/leekscript/compiler/AIFile.java index cc78074d..afb7de01 100644 --- a/src/main/java/leekscript/compiler/AIFile.java +++ b/src/main/java/leekscript/compiler/AIFile.java @@ -3,17 +3,17 @@ import leekscript.compiler.resolver.ResolverContext; public class AIFile { - + private String path; private String code; private C context; - private String javaClassName; private int id; public AIFile(String path, String code, C context) { this.path = path; this.code = code; this.context = context; + this.id = (context + "/" + path).hashCode() & 0xfffffff; } public AIFile(String path, String code, C context, int id) { this.path = path; @@ -39,12 +39,6 @@ public C getContext() { public void setContext(C context) { this.context = context; } - public String getJavaClassName() { - return javaClassName; - } - public void setJavaClassName(String javaClassName) { - this.javaClassName = javaClassName; - } public String getPath() { return path; } diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index 1ae9c771..3f422f19 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -66,7 +66,7 @@ public String analyze(AIFile ai) throws LeekCompilerException { return mInformations.toJSONString(); } - public String compile(AIFile ai, String AIClass) throws LeekCompilerException { + public String compile(AIFile ai, String javaClassName, String AIClass) throws LeekCompilerException { JavaWriter writer = new JavaWriter(true); try { // On lance la compilation du code de l'IA @@ -76,8 +76,7 @@ public String compile(AIFile ai, String AIClass) throws LeekCompilerException WordCompiler compiler = new WordCompiler(parser, main, ai); compiler.readCode(); - compiler.writeJava(ai.getJavaClassName(), writer, AIClass); - + compiler.writeJava(javaClassName, writer, AIClass); // On sauvegarde les dépendances addInformations(ai, main.getMinLevel()); @@ -98,7 +97,7 @@ public String getInformations() { public boolean hasError() { return mErrors; } - + public AIFile getCurrentAI() { return mCurrentAI; } diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index ff6c4e02..002f9fbd 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -16,13 +16,13 @@ import leekscript.runner.values.ArrayLeekValue; public class LeekScript { - + private final static String IA_PATH = "ai/"; private static long id = 1; - + private static Resolver defaultResolver = new FileSystemResolver(); private static Resolver customResolver = null; - + private static RandomGenerator defaultRandomGenerator = new RandomGenerator() { private Random random = new Random(); @Override @@ -41,12 +41,10 @@ public double getDouble() { } }; private static RandomGenerator customRandomGenerator = null; - + public static AI compileFile(String filepath, String AIClass, String jar, boolean nocache) throws LeekScriptException, LeekCompilerException { AIFile ai = getResolver().resolve(filepath, null); if (ai != null) { - int id = (filepath + "_" + ai.getCode()).hashCode() & 0xfffffff; - ai.setJavaClassName("IA_" + id); return compile(ai, AIClass, jar, nocache); } return null; @@ -55,19 +53,16 @@ public static AI compileFile(String filepath, String AIClass, String jar, boolea public static AI compileFileContext(String filepath, String AIClass, String jar, ResolverContext context, boolean nocache) throws LeekScriptException, LeekCompilerException { AIFile ai = getResolver().resolve(filepath, context); if (ai != null) { - int id = (filepath + "_" + ai.getCode()).hashCode() & 0xfffffff; - ai.setJavaClassName("IA_" + id); return compile(ai, AIClass, jar, nocache); } return null; } - + public static AI compileSnippet(String snippet, String AIClass, String jar) throws LeekScriptException, LeekCompilerException { - AIFile ai = new AIFile("", snippet, null); - ai.setJavaClassName("IA_" + id++); + AIFile ai = new AIFile("", snippet, null); return compile(ai, AIClass, jar, false); } - + public static boolean testScript(String leek, String script, AbstractLeekValue s, String AIClass, String jar, boolean nocache) throws Exception { AI ai = LeekScript.compileSnippet(script, AIClass, jar); AbstractLeekValue v = ai.runIA(); @@ -86,25 +81,25 @@ public static boolean testScript(String leek, String script, AbstractLeekValue s System.out.println(v.getString(ai) + " -- " + s.getString(ai)); return false; } - + public static AbstractLeekValue runScript(String script, boolean nocache) throws Exception { return LeekScript.compileSnippet(script, "AI", "leekscript.jar").runIA(); } - + public static boolean testScript(String script, AbstractLeekValue s) throws Exception { AI ai = LeekScript.compileSnippet(script, "AI", "leekscript.jar"); AbstractLeekValue v = ai.runIA(); System.out.println(v.getString(ai)); return v.equals(ai, s); } - + public static String runFile(String filename) throws Exception { AI ai = LeekScript.compileFile(filename, "AI", "leekscript.jar", true); AbstractLeekValue v = ai.runIA(); System.out.println(v.getString(ai)); return v.getString(ai); } - + public static void setResolver(Resolver resolver) { customResolver = resolver; } @@ -114,7 +109,7 @@ public static void resetResolver() { public static Resolver getResolver() { return customResolver != null ? customResolver : defaultResolver; } - + public static void setRandomGenerator(RandomGenerator generator) { customRandomGenerator = generator; } @@ -125,11 +120,11 @@ public static RandomGenerator getRandom() { private static AI compile(AIFile ai, String AIClass, String jar, boolean nocache) throws LeekScriptException, LeekCompilerException { new File(IA_PATH).mkdir(); - String javaClassName = ai.getJavaClassName(); + String javaClassName = "AI_" + ai.getId(); String error = ""; File compiled = new File(IA_PATH + javaClassName + ".class"); File java = new File(IA_PATH + javaClassName + ".java"); - + if (!compiled.exists() || nocache) { // On commence par la conversion LS->Java if (ai.getCode().isEmpty()) { // Pas de code du tout... @@ -137,8 +132,8 @@ private static AI compile(AIFile ai, String AIClass, String jar, boolean noca return null; } // On compile l'IA - String compiledJava = new IACompiler().compile(ai, AIClass); - + String compiledJava = new IACompiler().compile(ai, javaClassName, AIClass); + if (compiledJava.isEmpty()) { System.out.println("No java generated!"); return null; // Rien ne compile @@ -153,11 +148,11 @@ private static AI compile(AIFile ai, String AIClass, String jar, boolean noca System.out.println("Failed to compiled AI: " + ai.getPath()); return null; } - + // On va compiler le java maintenant JavaCompiler compiler = new JavaCompiler(java); int status = JavaCompiler.INIT; - + try { compiler.compile(jar); status = JavaCompiler.getStatus(); diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index bebc4be3..0b84fd03 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -13,19 +13,20 @@ public class FileSystemResolver implements Resolver { @Override public AIFile resolve(String path, ResolverContext basecontext) { - + FileSystemContext context = (FileSystemContext) basecontext; if (context == null) { context = new FileSystemContext(Paths.get(".").toFile()); } try { Path resolvedPath = context.getFolder().toPath().resolve(path).normalize(); - + String code = new String(Files.readAllBytes(resolvedPath), StandardCharsets.UTF_8); - + FileSystemContext newContext = new FileSystemContext(resolvedPath.getParent().toFile()); - return new AIFile(path, code, newContext); - + + return new AIFile(path, code, newContext, resolvedPath.hashCode() & 0xfffffff); + } catch (IOException e) { return null; } From fa6feca8367c90884f3bf6695662791d7af94d51 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 29 Oct 2019 22:11:51 +0100 Subject: [PATCH 021/319] [ai] Write the number of instructions inside the AI code --- .../leekscript/compiler/bloc/MainLeekBlock.java | 5 ++++- src/main/java/leekscript/runner/AI.java | 13 +++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 3f91405e..b4ca9f80 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -168,7 +168,10 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { writer.addLine("import leekscript.runner.*;"); writer.addLine("import leekscript.runner.values.*;"); writer.addLine("public class " + className + " extends " + AIClass + " {"); - writer.addLine("public " + className + "() throws Exception{ super(); }"); + writer.addLine("public " + className + "() throws Exception {"); + writer.addLine("super();"); + writer.addLine("mInstructions = " + mInstructions.size() + ";"); + writer.addLine("}"); // Variables globales for (String global : mGobales) { writer.addLine("private VariableLeekValue globale_" + global + " = null;"); diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 66e6b0c5..c3c728c2 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -16,7 +16,7 @@ import com.alibaba.fastjson.JSONArray; public abstract class AI { - + public static final int ERROR_LOG_COST = 1000; public final static int MAX_MEMORY = 100000; @@ -29,16 +29,21 @@ public abstract class AI { protected AILog logs; protected AI mUAI; + protected int mInstructions; public AI() { mUAI = this; logs = new AILog(); } + public int getInstructions() { + return mInstructions; + } + public long getOperations() { return mOperations; } - + public AILog getLogs() { return logs; } @@ -95,7 +100,7 @@ protected String getErrorLocalisation(int line) { } return ""; } - + public AbstractLeekValue color(AbstractLeekValue red, AbstractLeekValue green, AbstractLeekValue blue) throws LeekRunException { @@ -327,7 +332,7 @@ else if (type == AILog.STANDARD) logs.addSystemLog(type, getErrorMessage(elements), key, parameters); } - + protected abstract String[] getErrorString(); protected abstract String getAItring(); From 730eb2f2169a9fa17e719511d2c273f4e314ebe8 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 29 Oct 2019 22:11:51 +0100 Subject: [PATCH 022/319] [ailoader] Fix a warning --- src/main/java/leekscript/compiler/IALoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/IALoader.java b/src/main/java/leekscript/compiler/IALoader.java index 3f51cd59..37c597f1 100644 --- a/src/main/java/leekscript/compiler/IALoader.java +++ b/src/main/java/leekscript/compiler/IALoader.java @@ -23,7 +23,7 @@ public static AI loadAI(String file, String classname) { if (loader != null) { Class c = loader.loadClass(classname); - return (AI) c.newInstance(); + return (AI) c.getDeclaredConstructor().newInstance(); } } catch (Exception e) { ErrorManager.exception(e); From a85279c125248bd04cac36e848edc4b72cfee2be Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 29 Oct 2019 23:27:02 +0100 Subject: [PATCH 023/319] [compilation] Add timestamps to AIFile to recompile if AI is modified --- src/main/java/leekscript/compiler/AIFile.java | 14 ++++++++------ src/main/java/leekscript/compiler/LeekScript.java | 4 ++-- .../compiler/resolver/FileSystemResolver.java | 4 +++- src/test/java/test/TestWithFile.java | 2 +- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/leekscript/compiler/AIFile.java b/src/main/java/leekscript/compiler/AIFile.java index afb7de01..6d411fb4 100644 --- a/src/main/java/leekscript/compiler/AIFile.java +++ b/src/main/java/leekscript/compiler/AIFile.java @@ -8,17 +8,16 @@ public class AIFile { private String code; private C context; private int id; + private long timestamp; - public AIFile(String path, String code, C context) { - this.path = path; - this.code = code; - this.context = context; - this.id = (context + "/" + path).hashCode() & 0xfffffff; + public AIFile(String path, String code, long timestamp, C context) { + this(path, code, timestamp, context, (context + "/" + path).hashCode() & 0xfffffff); } - public AIFile(String path, String code, C context, int id) { + public AIFile(String path, String code, long timestamp, C context, int id) { this.path = path; this.code = code; this.context = context; + this.timestamp = timestamp; this.id = id; } public int getId() { @@ -45,4 +44,7 @@ public String getPath() { public void setPath(String path) { this.path = path; } + public long getTimestamp() { + return this.timestamp; + } } diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 002f9fbd..56a19a45 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -59,7 +59,7 @@ public static AI compileFileContext(String filepath, String AIClass, String jar, } public static AI compileSnippet(String snippet, String AIClass, String jar) throws LeekScriptException, LeekCompilerException { - AIFile ai = new AIFile("", snippet, null); + AIFile ai = new AIFile("", snippet, System.currentTimeMillis(), null); return compile(ai, AIClass, jar, false); } @@ -125,7 +125,7 @@ private static AI compile(AIFile ai, String AIClass, String jar, boolean noca File compiled = new File(IA_PATH + javaClassName + ".class"); File java = new File(IA_PATH + javaClassName + ".java"); - if (!compiled.exists() || nocache) { + if (!compiled.exists() || compiled.lastModified() < ai.getTimestamp() || nocache) { // On commence par la conversion LS->Java if (ai.getCode().isEmpty()) { // Pas de code du tout... System.out.println("No code!"); diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index 0b84fd03..3d9161a8 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -25,7 +25,9 @@ public AIFile resolve(String path, ResolverContext basecontex FileSystemContext newContext = new FileSystemContext(resolvedPath.getParent().toFile()); - return new AIFile(path, code, newContext, resolvedPath.hashCode() & 0xfffffff); + long timestamp = resolvedPath.toFile().lastModified(); + + return new AIFile(path, code, timestamp, newContext, resolvedPath.hashCode() & 0xfffffff); } catch (IOException e) { return null; diff --git a/src/test/java/test/TestWithFile.java b/src/test/java/test/TestWithFile.java index 11eeae2f..5c237b5e 100644 --- a/src/test/java/test/TestWithFile.java +++ b/src/test/java/test/TestWithFile.java @@ -37,7 +37,7 @@ class CustomContext extends ResolverContext {} LeekScript.setResolver(new Resolver() { @Override public AIFile resolve(String path, ResolverContext context) { - return new AIFile(path, "return 'generated';", new CustomContext()); + return new AIFile(path, "return 'generated';", System.currentTimeMillis(), new CustomContext()); } @Override public ResolverContext createContext(int parameter) { From 29437fe7ffc774536937dac165fdbe7e63260607 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 29 Oct 2019 23:58:12 +0100 Subject: [PATCH 024/319] [ai] Add init() method and call it at creation of the AI --- src/main/java/leekscript/runner/AI.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index c3c728c2..16a37a7f 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -31,11 +31,15 @@ public abstract class AI { protected AI mUAI; protected int mInstructions; - public AI() { + public AI() throws Exception { mUAI = this; logs = new AILog(); + init(); } + // Method that can be overriden in each AI + protected void init() throws Exception {} + public int getInstructions() { return mInstructions; } From c5b65d3113dc8b14485cad652772bc8e011ccaa2 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 29 Oct 2019 23:58:12 +0100 Subject: [PATCH 025/319] [function] Fix redefined functions class name --- src/main/java/leekscript/compiler/bloc/MainLeekBlock.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index b4ca9f80..d2dd82f4 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -12,6 +12,7 @@ import leekscript.compiler.WordCompiler; import leekscript.compiler.WordParser; import leekscript.compiler.instruction.LeekInstruction; +import leekscript.runner.LeekFunctions; public class MainLeekBlock extends AbstractLeekBlock { @@ -200,7 +201,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { printFunctionInformations(writer); if (mRedefinedFunctions.size() > 0) { - writer.addCode("protected void init() throws Exception{"); + writer.addCode("protected void init() throws Exception {\n"); for (String redefined : mRedefinedFunctions) { FunctionBlock user_function = getUserFunction(redefined); writer.addCode("rfunction_"); @@ -211,7 +212,8 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { writer.addCode(String.valueOf(user_function.getId())); writer.addCode(")"); } else { - writer.addCode("new FunctionLeekValue(LeekFunctions."); + String namespace = LeekFunctions.getNamespace(redefined); + writer.addCode("new FunctionLeekValue(" + namespace + "."); writer.addCode(redefined); writer.addCode(")"); } From b5df164192e5efed491ce49f9d78f3030ef2ba90 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 1 Nov 2019 23:16:59 +0100 Subject: [PATCH 026/319] [resolver] Add another parameter to resolver API --- .../java/leekscript/compiler/resolver/FileSystemResolver.java | 2 +- src/main/java/leekscript/compiler/resolver/Resolver.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index 3d9161a8..344177ae 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -34,7 +34,7 @@ public AIFile resolve(String path, ResolverContext basecontex } } - public ResolverContext createContext(int parameter) { + public ResolverContext createContext(int parameter1, int parameter2) { return new FileSystemContext(Paths.get(".").toFile()); } } diff --git a/src/main/java/leekscript/compiler/resolver/Resolver.java b/src/main/java/leekscript/compiler/resolver/Resolver.java index 2bbee7bd..8d627f68 100644 --- a/src/main/java/leekscript/compiler/resolver/Resolver.java +++ b/src/main/java/leekscript/compiler/resolver/Resolver.java @@ -21,5 +21,5 @@ public Result(String code, C context) { */ abstract public AIFile resolve(String path, ResolverContext context); - public abstract ResolverContext createContext(int parameter); + public abstract ResolverContext createContext(int parameter1, int parameter2); } From a6e59fbbfef3e114f46703851a6b4055b2445874 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 6 Nov 2019 19:47:27 +0100 Subject: [PATCH 027/319] [test] Fix Resolver createContext arguments --- src/test/java/test/TestWithFile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/test/TestWithFile.java b/src/test/java/test/TestWithFile.java index 5c237b5e..8eb392b7 100644 --- a/src/test/java/test/TestWithFile.java +++ b/src/test/java/test/TestWithFile.java @@ -40,7 +40,7 @@ public AIFile resolve(String path, ResolverContext context) { return new AIFile(path, "return 'generated';", System.currentTimeMillis(), new CustomContext()); } @Override - public ResolverContext createContext(int parameter) { + public ResolverContext createContext(int parameter1, int parameter2) { return null; } }); From e657de53e47a61d8253f14724f057f75356e6bf4 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 6 Nov 2019 21:30:58 +0100 Subject: [PATCH 028/319] [compiler] Add included AI to result --- src/main/java/leekscript/compiler/IACompiler.java | 15 +++++++++++++-- .../leekscript/compiler/bloc/MainLeekBlock.java | 5 +++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index 3f422f19..42236b3e 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -4,6 +4,9 @@ import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.exceptions.LeekCompilerException; +import java.util.ArrayList; +import java.util.List; + import com.alibaba.fastjson.JSONArray; /** @@ -11,6 +14,11 @@ */ public class IACompiler { + public static class AnalyzeResult { + public String informations; + public List includedAIs = new ArrayList<>(); + } + private final JSONArray mInformations = new JSONArray(); private boolean mErrors = false; private AIFile mCurrentAI; @@ -48,7 +56,8 @@ public void addInformations(AIFile ia_context, int level) { mInformations.add(error); } - public String analyze(AIFile ai) throws LeekCompilerException { + public AnalyzeResult analyze(AIFile ai) throws LeekCompilerException { + AnalyzeResult result = new AnalyzeResult(); try { // On lance la compilation du code de l'IA WordParser parser = new WordParser(ai); @@ -58,12 +67,14 @@ public String analyze(AIFile ai) throws LeekCompilerException { compiler.readCode(); // On sauvegarde les dépendances addInformations(ai, main.getMinLevel()); + result.includedAIs = main.getIncludedAIs(); } catch (LeekCompilerException e) { addError(e.getIA(), e.getLine(), e.getChar(), e.getWord(), e.getError(), e.getParameters()); } catch (Exception e) { addError(ai, e.getMessage()); } - return mInformations.toJSONString(); + result.informations = mInformations.toJSONString(); + return result; } public String compile(AIFile ai, String javaClassName, String AIClass) throws LeekCompilerException { diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index d2dd82f4..7d8d85c8 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -293,4 +294,8 @@ public void printFunctionInformations(JavaWriter writer) { * AbstractLeekValue[] value); */ } + + public List getIncludedAIs() { + return mIncluded; + } } From f7172b23f111d18b27fd986beaf4607bf6430ca0 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 17 Nov 2019 13:30:11 +0100 Subject: [PATCH 029/319] [compilation] Don't delete java file if error --- src/main/java/leekscript/compiler/LeekScript.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 56a19a45..d758fd3c 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -161,7 +161,6 @@ private static AI compile(AIFile ai, String AIClass, String jar, boolean noca status = JavaCompiler.ERROR; } if (status == JavaCompiler.ERROR) { - java.delete(); throwException(error); } } From de32caff62196a9a3e32e691dd70770ffa69e7bf Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 5 Feb 2020 20:11:25 +0100 Subject: [PATCH 030/319] [resolver] Fix file system resolver when folder is current folder --- .../leekscript/compiler/resolver/FileSystemResolver.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index 344177ae..cdf9c09e 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -23,7 +23,10 @@ public AIFile resolve(String path, ResolverContext basecontex String code = new String(Files.readAllBytes(resolvedPath), StandardCharsets.UTF_8); - FileSystemContext newContext = new FileSystemContext(resolvedPath.getParent().toFile()); + Path parent = resolvedPath.getParent(); + if (parent == null) parent = Paths.get("."); + + FileSystemContext newContext = new FileSystemContext(parent.toFile()); long timestamp = resolvedPath.toFile().lastModified(); From f2b1fb7645ba0b37c29f34d8148bd0c4d8000f13 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 5 Feb 2020 20:12:17 +0100 Subject: [PATCH 031/319] [top-level] Add ability to run a leekscript file --- src/main/java/leekscript/TopLevel.java | 46 ++++++++++++++++++++------ 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/main/java/leekscript/TopLevel.java b/src/main/java/leekscript/TopLevel.java index d498536a..38f1279c 100644 --- a/src/main/java/leekscript/TopLevel.java +++ b/src/main/java/leekscript/TopLevel.java @@ -1,6 +1,7 @@ package leekscript; import java.util.Scanner; +import java.io.File; import leekscript.compiler.LeekScript; import leekscript.runner.AI; @@ -12,35 +13,60 @@ public static void main(String[] args) { if (args.length < 1) { Scanner input = new Scanner(System.in); System.out.print(">>> "); - String code; while ((code = input.nextLine()) != null) { - execute(code); + executeSnippet(code); System.out.print(">>> "); } input.close(); } else { - String code = args[0]; - execute(code); + + File file = new File(args[0]); + if (file.exists()) { + executeFile(file); + } else { + executeSnippet(args[0]); + } } } - - private static void execute(String code) { + + private static void executeSnippet(String code) { try { long ct = System.currentTimeMillis(); AI ai = LeekScript.compileSnippet(code, "AI", "leekscript.jar"); long compileTime = System.currentTimeMillis() - ct; - + + long et = System.currentTimeMillis(); + AbstractLeekValue v = ai.runIA(); + long executionTime = System.currentTimeMillis() - et; + + String result = v.getString(ai); + long ops = ai.getOperations(); + + System.out.println(result); + System.out.println("(" + ops + " ops, " + compileTime + "ms + " + executionTime + "ms)"); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static void executeFile(File file) { + try { + long ct = System.currentTimeMillis(); + AI ai = LeekScript.compileFile(file.getPath(), "AI", "leekscript.jar", false); + long compileTime = System.currentTimeMillis() - ct; + long et = System.currentTimeMillis(); AbstractLeekValue v = ai.runIA(); long executionTime = System.currentTimeMillis() - et; - + String result = v.getString(ai); long ops = ai.getOperations(); - + System.out.println(result); System.out.println("(" + ops + " ops, " + compileTime + "ms + " + executionTime + "ms)"); - + } catch (Exception e) { e.printStackTrace(); } From 2ed40c0b824bb8058aa95bcc96e0c327bd91c657 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 5 Feb 2020 20:12:28 +0100 Subject: [PATCH 032/319] [ai] Fix error file name --- src/main/java/leekscript/runner/AI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 16a37a7f..8fe98e55 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -99,7 +99,7 @@ protected String getErrorLocalisation(int line) { JSONArray l = mErrorObject.getJSONArray(value); if (l != null && l.size() >= 3) { String ai_name = thisObject != null ? thisObject : ""; - return "(IA : " + ai_name + ", line : " + l.getString(2) + ")"; + return "(IA : " + l.getString(1) + ", line : " + l.getString(2) + ")"; } } return ""; From abf5ae16823e2517a853555bd9a5735b69396e2c Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 15 Feb 2020 09:10:16 +0100 Subject: [PATCH 033/319] [leekscript] Fix typos --- .../java/leekscript/compiler/WordParser.java | 2 +- .../java/leekscript/runner/LeekRunException.java | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index 9fafa314..082631c4 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -7,7 +7,7 @@ public class WordParser { /** * Son but est de convertir le LeekCode en un "bytecode" plus rapide à - * éxécuter Il doit aussi trouver les erreurs dans le LeekCode + * exécuter Il doit aussi trouver les erreurs dans le LeekCode */ /** diff --git a/src/main/java/leekscript/runner/LeekRunException.java b/src/main/java/leekscript/runner/LeekRunException.java index e43ffb17..fadd8b4f 100644 --- a/src/main/java/leekscript/runner/LeekRunException.java +++ b/src/main/java/leekscript/runner/LeekRunException.java @@ -30,21 +30,21 @@ public int getError() { public String getMessage() { switch (mError) { case TOO_MUCH_OPERATIONS: - return "Erreur d'execution : Trop d'opérations éxécutées pour ce tour"; + return "Erreur d'exécution : Trop d'opérations exécutées pour ce tour"; case ARRAY_EMPTY: - return "Erreur d'execution : Tableau vide"; + return "Erreur d'exécution : Tableau vide"; case INVALID_INDEX: - return "Erreur d'execution : Indice invalide"; + return "Erreur d'exécution : Indice invalide"; case UNKNOWN_FUNCTION: - return "Erreur d'execution : Fonction inconnue"; + return "Erreur d'exécution : Fonction inconnue"; case INVALID_OPERATOR: - return "Erreur d'execution : Impossible d'utiliser cet opérateur"; + return "Erreur d'exécution : Impossible d'utiliser cet opérateur"; case INVALID_LEVEL: - return "Erreur d'execution : Niveau invalide"; + return "Erreur d'exécution : Niveau invalide"; case OUT_OF_MEMORY: - return "Erreur d'execution : Trop de RAM utilisée"; + return "Erreur d'exécution : Trop de RAM utilisée"; } - return "Erreur d'éxécution"; + return "Erreur d'exécution"; } } From 7c9fdff2709677f3e9d5e2fb3c11b539557ca7ed Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 15 Feb 2020 09:43:30 +0100 Subject: [PATCH 034/319] [ai] Remove useless variable --- src/main/java/leekscript/runner/AI.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 8fe98e55..b55eebaf 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -98,7 +98,6 @@ protected String getErrorLocalisation(int line) { if (mErrorObject.size() > value) { JSONArray l = mErrorObject.getJSONArray(value); if (l != null && l.size() >= 3) { - String ai_name = thisObject != null ? thisObject : ""; return "(IA : " + l.getString(1) + ", line : " + l.getString(2) + ")"; } } From 027b74cd3ccd846c5227a1d00df6556784619516 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 8 Mar 2020 23:36:58 +0100 Subject: [PATCH 035/319] [compiler] Remove redundant implements --- src/main/java/leekscript/compiler/bloc/ConditionalBloc.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java b/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java index 67a49783..a6075b1b 100644 --- a/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java +++ b/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java @@ -3,9 +3,8 @@ import leekscript.compiler.AIFile; import leekscript.compiler.JavaWriter; import leekscript.compiler.expression.AbstractExpression; -import leekscript.compiler.instruction.LeekInstruction; -public class ConditionalBloc extends AbstractLeekBlock implements LeekInstruction { +public class ConditionalBloc extends AbstractLeekBlock { private ConditionalBloc mParentCondition = null; private AbstractExpression mCondition = null; From cb65f5cf50e281e49b48a5ce2660aa445c421c0a Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 8 Mar 2020 23:39:59 +0100 Subject: [PATCH 036/319] [function] Change cost of insert function --- src/main/java/leekscript/runner/LeekFunctions.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 903b09af..9359b9b0 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -633,10 +633,7 @@ public int[] parameters() { @Override public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { - if (parameters[2].getInt(leekIA) >= 0 && parameters[2].getInt(leekIA) < parameters[0].getArray().size()) { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[1].getInt(leekIA) + 1) : 1); - } else - leekIA.addOperations(1); + leekIA.addOperations(1 + (parameters[0].getArray().getSize() - parameters[2].getInt(leekIA)) * 4); } }, push(2) { From e68a0e744661bbc45fca50e6607d89aceb384759 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 8 Mar 2020 23:40:07 +0100 Subject: [PATCH 037/319] [test] Remove todos --- src/test/java/test/TestAI.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/test/java/test/TestAI.java b/src/test/java/test/TestAI.java index 0ba0c97f..495c2493 100644 --- a/src/test/java/test/TestAI.java +++ b/src/test/java/test/TestAI.java @@ -10,49 +10,41 @@ public TestAI() throws Exception { @Override protected String[] getErrorString() { - // TODO Auto-generated method stub return null; } @Override protected String getAItring() { - // TODO Auto-generated method stub return null; } @Override public AbstractLeekValue runIA() throws Exception { - // TODO Auto-generated method stub return null; } @Override public int userFunctionCount(int id) { - // TODO Auto-generated method stub return 0; } @Override public boolean[] userFunctionReference(int id) { - // TODO Auto-generated method stub return null; } @Override public AbstractLeekValue userFunctionExecute(int id, AbstractLeekValue[] value) throws Exception { - // TODO Auto-generated method stub return null; } @Override public int anonymousFunctionCount(int id) { - // TODO Auto-generated method stub return 0; } @Override public boolean[] anonymousFunctionReference(int id) { - // TODO Auto-generated method stub return null; } From 3956f5df941ee978622090a0d70ef7c1027bc991 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 26 Jun 2020 20:38:25 +0200 Subject: [PATCH 038/319] [compilation] Add another check on compiled file and more timeout --- src/main/java/leekscript/compiler/JavaCompiler.java | 4 ++-- src/main/java/leekscript/compiler/LeekScript.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/compiler/JavaCompiler.java b/src/main/java/leekscript/compiler/JavaCompiler.java index fb39eaac..f201c07c 100644 --- a/src/main/java/leekscript/compiler/JavaCompiler.java +++ b/src/main/java/leekscript/compiler/JavaCompiler.java @@ -7,7 +7,7 @@ import java.io.InputStreamReader; public class JavaCompiler { - + public final static int INIT = 0; public final static int RUNNING = 1; public final static int END = 2; @@ -42,7 +42,7 @@ public void compile(String jar) throws Exception { errThread.start(); try { - worker.join(10000); + worker.join(20000); if (worker.exit == null) { throw new CompilationException("too_long_java"); } diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index d758fd3c..bfea69bd 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -125,7 +125,7 @@ private static AI compile(AIFile ai, String AIClass, String jar, boolean noca File compiled = new File(IA_PATH + javaClassName + ".class"); File java = new File(IA_PATH + javaClassName + ".java"); - if (!compiled.exists() || compiled.lastModified() < ai.getTimestamp() || nocache) { + if (!compiled.exists() || compiled.length() == 0 || compiled.lastModified() < ai.getTimestamp() || nocache) { // On commence par la conversion LS->Java if (ai.getCode().isEmpty()) { // Pas de code du tout... System.out.println("No code!"); From 481c5b8bbe3c03008e1e73df9dfc09fb1ec5d3e4 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 14 Aug 2020 20:11:53 +0200 Subject: [PATCH 039/319] [string] Use multi-line instruction for better error information --- .../java/leekscript/runner/values/StringLeekValue.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/runner/values/StringLeekValue.java b/src/main/java/leekscript/runner/values/StringLeekValue.java index e5f954f4..22a4c65e 100644 --- a/src/main/java/leekscript/runner/values/StringLeekValue.java +++ b/src/main/java/leekscript/runner/values/StringLeekValue.java @@ -4,7 +4,7 @@ import leekscript.runner.LeekRunException; public class StringLeekValue extends AbstractLeekValue { - + private String mValue; public StringLeekValue(String value) { @@ -92,7 +92,10 @@ public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { return getBoolean() == comp.getBoolean(); } else if (comp.getType() == STRING) { String s = comp.getString(ai); - ai.addOperations(Math.min(s.length(), mValue.length())); + ai.addOperations(Math.min( + s.length(), + mValue.length() + )); return mValue.equals(s); } else if (comp.getType() == ARRAY) { return comp.equals(ai, this); From a9e2fafaa64ce79081d233841b0f5d5d311a365b Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 14 Aug 2020 20:12:05 +0200 Subject: [PATCH 040/319] [leekscript] Force UTF-8 charset --- src/main/java/leekscript/compiler/LeekScript.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index bfea69bd..457e8355 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -2,6 +2,7 @@ import java.io.File; import java.io.FileOutputStream; +import java.nio.charset.StandardCharsets; import java.util.Random; import leekscript.ErrorManager; @@ -141,7 +142,7 @@ private static AI compile(AIFile ai, String AIClass, String jar, boolean noca // Si on a maintenant du code java try { FileOutputStream output = new FileOutputStream(java); - output.write(compiledJava.getBytes()); + output.write(compiledJava.getBytes(StandardCharsets.UTF_8)); output.close(); } catch (Exception e) { ErrorManager.exception(e); From b258ddd6f986edcd5ea0f5a0999abf69e26cf27d Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 14 Aug 2020 20:12:42 +0200 Subject: [PATCH 041/319] [compiler] Return a JSONArray instead of a string in analyze --- src/main/java/leekscript/compiler/IACompiler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index 42236b3e..11a402ce 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -15,7 +15,7 @@ public class IACompiler { public static class AnalyzeResult { - public String informations; + public JSONArray informations; public List includedAIs = new ArrayList<>(); } @@ -73,7 +73,7 @@ public AnalyzeResult analyze(AIFile ai) throws LeekCompilerException { } catch (Exception e) { addError(ai, e.getMessage()); } - result.informations = mInformations.toJSONString(); + result.informations = mInformations; return result; } From 0b1bdd5d050cb6b387040e78e6c39ef1e00709a1 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 3 Oct 2020 12:42:28 +0200 Subject: [PATCH 042/319] [log] Remove leek wars specific constants --- src/main/java/leekscript/AILog.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/leekscript/AILog.java b/src/main/java/leekscript/AILog.java index 1cbce144..4a95ff93 100644 --- a/src/main/java/leekscript/AILog.java +++ b/src/main/java/leekscript/AILog.java @@ -9,12 +9,10 @@ public class AILog { public final static int STANDARD = 1; public final static int WARNING = 2; public final static int ERROR = 3; - public final static int MARK = 4; - public final static int PAUSE = 5; public final static int SSTANDARD = 6; public final static int SWARNING = 7; public final static int SERROR = 8; - + // Clés public static final String DEPRECATED_FUNCTION = "deprecated_function"; public static final String UNKNOWN_FUNCTION = "unknown_function"; @@ -28,7 +26,7 @@ public class AILog { public static final String CODE_TOO_LARGE = "code_too_large"; public static final String CODE_TOO_LARGE_FUNCTION = "code_too_large_function"; public static final String NUMBER_OF_OPERATIONS = "number_of_operations"; - + public interface Stream { public void write(JSONArray a); } @@ -47,7 +45,7 @@ public void write(JSONArray a) { } public void addSystemLog(int type, String trace, String key, String[] parameters) { - + int paramSize = 0; if (parameters != null) { for (String p : parameters) { @@ -66,7 +64,7 @@ public void addSystemLog(int type, String trace, String key, String[] parameters obj.add(key); if (parameters != null) obj.add(parameters); - + stream.write(obj); } From d6148867fb64fcc11ecc0811b7cc02392be32490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Sat, 3 Oct 2020 12:43:43 +0200 Subject: [PATCH 043/319] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index adcdb338..79ed40d8 100644 --- a/README.md +++ b/README.md @@ -17,4 +17,4 @@ gradle jar test ``` ### Credits -Developed by Dawyde © 2012-2019 +Developed by Dawyde © 2012-2020 From 5b27c841c754fcd6a6a31df801dda6c47dbc724b Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 17 Oct 2020 13:52:53 +0200 Subject: [PATCH 044/319] [javawriter] Fix string escape for error information --- .../java/leekscript/compiler/JavaWriter.java | 39 +++++++------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/src/main/java/leekscript/compiler/JavaWriter.java b/src/main/java/leekscript/compiler/JavaWriter.java index f669f384..e514c8a9 100644 --- a/src/main/java/leekscript/compiler/JavaWriter.java +++ b/src/main/java/leekscript/compiler/JavaWriter.java @@ -2,6 +2,9 @@ import java.util.ArrayList; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; + public class JavaWriter { private final StringBuilder mCode; private int mLine; @@ -50,40 +53,26 @@ public String getJavaCode() { return mCode.toString(); } - public String escape(String string) { - String str = ""; - for (int i = 0; i < string.length(); i++) { - if (string.charAt(i) == '\n') - str += "\\n"; - else if (string.charAt(i) == '"') - str += "\\\""; - else if (string.charAt(i) == '\\') { - if (string.charAt(i + 1) == 'n') - str += "\\"; - else if (string.charAt(i + 1) == 't') - str += "\\"; - else - str += "\\\\"; - } - else - str += string.charAt(i); - } - return str; - } - public void writeErrorFunction(IACompiler comp, String ai) { mCode.append("protected String[] getErrorString(){ return new String[]{"); + + String aiJson = JSON.toJSONString(ai); + boolean first = true; for (Line l : mLines) { if (!first) mCode.append(","); else first = false; - mCode.append("\"[").append(l.mJavaLine).append(",\\\"").append(escape(l.mAI.getPath())).append("\\\",").append(l.mCodeLine).append("]\""); + JSONArray array = new JSONArray(); + array.add(l.mJavaLine); + array.add(l.mAI.getPath()); + array.add(l.mCodeLine); + mCode.append(JSON.toJSONString(array.toJSONString())); } - mCode.append("};}\n protected String getAItring(){ return \""); - mCode.append(escape(ai)); - mCode.append("\";}"); + mCode.append("};}\nprotected String getAItring(){ return "); + mCode.append(aiJson); + mCode.append(";}\n"); } public void addCounter(int id) { From af20821a5256c7345c0d1d6781f1437f1d3064f0 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 17 Oct 2020 13:59:21 +0200 Subject: [PATCH 045/319] [random] Put a randomGenerator in the AI instead of a static one --- .../java/leekscript/compiler/LeekScript.java | 11 ++-- src/main/java/leekscript/runner/AI.java | 7 +++ .../java/leekscript/runner/LeekFunctions.java | 51 +++++++++---------- 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 457e8355..d5db642d 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -26,22 +26,24 @@ public class LeekScript { private static RandomGenerator defaultRandomGenerator = new RandomGenerator() { private Random random = new Random(); + @Override public void seed(long seed) { random.setSeed(seed); } + @Override public int getInt(int min, int max) { if (max - min + 1 <= 0) return 0; return min + random.nextInt(max - min + 1); } + @Override public double getDouble() { return random.nextDouble(); } }; - private static RandomGenerator customRandomGenerator = null; public static AI compileFile(String filepath, String AIClass, String jar, boolean nocache) throws LeekScriptException, LeekCompilerException { AIFile ai = getResolver().resolve(filepath, null); @@ -104,18 +106,17 @@ public static String runFile(String filename) throws Exception { public static void setResolver(Resolver resolver) { customResolver = resolver; } + public static void resetResolver() { customResolver = null; } + public static Resolver getResolver() { return customResolver != null ? customResolver : defaultResolver; } - public static void setRandomGenerator(RandomGenerator generator) { - customRandomGenerator = generator; - } public static RandomGenerator getRandom() { - return customRandomGenerator != null ? customRandomGenerator : defaultRandomGenerator; + return defaultRandomGenerator; } private static AI compile(AIFile ai, String AIClass, String jar, boolean nocache) throws LeekScriptException, LeekCompilerException { diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index b55eebaf..70068b3d 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -1,6 +1,7 @@ package leekscript.runner; import leekscript.AILog; +import leekscript.compiler.RandomGenerator; import leekscript.runner.PhpArray.Element; import leekscript.runner.values.AbstractLeekValue; import leekscript.runner.values.ArrayLeekValue; @@ -30,10 +31,12 @@ public abstract class AI { protected AILog logs; protected AI mUAI; protected int mInstructions; + protected RandomGenerator randomGenerator; public AI() throws Exception { mUAI = this; logs = new AILog(); + randomGenerator = LeekScript.getRandom(); init(); } @@ -351,4 +354,8 @@ else if (type == AILog.STANDARD) public abstract int anonymousFunctionCount(int id); public abstract boolean[] anonymousFunctionReference(int id); + + public RandomGenerator getRandom() { + return randomGenerator; + } } diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 9359b9b0..b9381366 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -3,7 +3,6 @@ import java.util.regex.Pattern; import leekscript.AILog; -import leekscript.compiler.LeekScript; import leekscript.functions.Functions; import leekscript.functions.VariableOperations; import leekscript.runner.values.AbstractLeekValue; @@ -251,7 +250,7 @@ public int[] parameters() { rand(0) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { - return new DoubleLeekValue(LeekScript.getRandom().getDouble()); + return new DoubleLeekValue(leekIA.getRandom().getDouble()); } }, randInt(2) { @@ -260,9 +259,9 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu int nb = parameters[0].getInt(leekIA); int nb1 = parameters[1].getInt(leekIA); if (nb > nb1) - return LeekValueManager.getLeekIntValue(LeekScript.getRandom().getInt(nb1, nb - 1)); + return LeekValueManager.getLeekIntValue(leekIA.getRandom().getInt(nb1, nb - 1)); else - return LeekValueManager.getLeekIntValue(LeekScript.getRandom().getInt(nb, nb1 - 1)); + return LeekValueManager.getLeekIntValue(leekIA.getRandom().getInt(nb, nb1 - 1)); } @Override @@ -273,7 +272,7 @@ public int[] parameters() { randFloat(2) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { - return new DoubleLeekValue(parameters[0].getDouble(leekIA) + LeekScript.getRandom().getDouble() * (parameters[1].getDouble(leekIA) - parameters[0].getDouble(leekIA))); + return new DoubleLeekValue(parameters[0].getDouble(leekIA) + leekIA.getRandom().getDouble() * (parameters[1].getDouble(leekIA) - parameters[0].getDouble(leekIA))); } @Override @@ -374,7 +373,7 @@ public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue p public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { return new StringLeekValue(parameters[0].getString(leekIA) .replaceAll(Pattern.quote(parameters[1] - .getString(leekIA)), + .getString(leekIA)), parameters[2].getString(leekIA))); } @@ -385,7 +384,7 @@ public int[] parameters() { @Override public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { - leekIA.addOperations(hasVariableOperations() ? + leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations( parameters[0].getString(leekIA).length()) : 1); } @@ -443,7 +442,7 @@ public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue p leekIA.addOperations( hasVariableOperations() ? mVariableOperations.getOperations( - (int) (parameters[0].getString(leekIA).length() + (int) (parameters[0].getString(leekIA).length() * Math.log(parameters[1].getString(leekIA).length() + 1))) : 1); if (retour.isArray()) @@ -463,7 +462,7 @@ public int[] parameters() { @Override public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { - leekIA.addOperations(hasVariableOperations() ? + leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(retour.getString(leekIA).length()) : 1); } }, @@ -480,7 +479,7 @@ public int[] parameters() { @Override public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { - leekIA.addOperations(hasVariableOperations() + leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(retour.getString(leekIA).length()) : 1); } }, @@ -500,7 +499,7 @@ public int[] parameters() { @Override public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { if (parameters[0].getString(leekIA).length() > parameters[1].getString(leekIA).length()) { - leekIA.addOperations(hasVariableOperations() ? + leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations((parameters[1].getString(leekIA).length())) : 1); } else leekIA.addOperations(1); @@ -521,7 +520,7 @@ public int[] parameters() { @Override public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { if (parameters[0].getString(leekIA).length() > parameters[1].getString(leekIA).length()) { - leekIA.addOperations(hasVariableOperations() ? + leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations((parameters[1].getString(leekIA).length())) : 1); } else leekIA.addOperations(1); @@ -543,9 +542,9 @@ public int[] parameters() { } @Override public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { - leekIA.addOperations(hasVariableOperations() ? + leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations( - (int) (parameters[0].getString(leekIA).length() + (int) (parameters[0].getString(leekIA).length() * Math.log(parameters[1].getString(leekIA).length() + 1))) : 1); } }, @@ -706,7 +705,7 @@ public int[] parameters() { @Override public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { - leekIA.addOperations(hasVariableOperations() ? + leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, @@ -1269,7 +1268,7 @@ public int[] parameters() { return new int[] { NUMBER }; } }, - + typeOf(1) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { @@ -1293,7 +1292,7 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu return LeekValueManager.getLeekIntValue((int) leekIA.getOperations()); } }; - + private static String extraFunctions = null; private int mArguments; @@ -1319,23 +1318,23 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu mArgumentsMin = arguments; mArguments = arguments_max; } - + public static void setExtraFunctions(String extraFunctions) { LeekFunctions.extraFunctions = extraFunctions; } - + public static int isFunction(String name) { ILeekFunction f = getValue(name); if (f == null) return -1; return f.getArguments(); } - + public static boolean isExtraFunction(String name) { ILeekFunction f = getValue(name); return f != null && f.isExtra(); } - + public static String getNamespace(String name) { return isExtraFunction(name) ? extraFunctions : "LeekFunctions"; } @@ -1350,12 +1349,12 @@ public String getNamespace() { return "LeekFunctions"; } - + @Override public int getArgumentsMin() { return mArgumentsMin; } - + @Override public boolean isExtra() { return false; @@ -1387,11 +1386,11 @@ public static ILeekFunction getValue(String name) { } catch (ClassNotFoundException e) { e.printStackTrace(); } - + } return null; } - + public static Object[] getExtraFunctions() { if (extraFunctions != null) { try { @@ -1400,7 +1399,7 @@ public static Object[] getExtraFunctions() { } catch (ClassNotFoundException e) { return new Object[] {}; } - + } return new Object[] {}; } From 1e72a2eb47c5c225bdd4dd4b1678ea8aef947793 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 17 Oct 2020 13:59:46 +0200 Subject: [PATCH 046/319] [ai] Change error string --- src/main/java/leekscript/runner/AI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 70068b3d..1c233a56 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -101,7 +101,7 @@ protected String getErrorLocalisation(int line) { if (mErrorObject.size() > value) { JSONArray l = mErrorObject.getJSONArray(value); if (l != null && l.size() >= 3) { - return "(IA : " + l.getString(1) + ", line : " + l.getString(2) + ")"; + return "AI " + l.getString(1) + ", line " + l.getString(2) + " ▶ "; } } return ""; From cd4f823041f9d51d2cdad77b1b03ba46c4b07f24 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 17 Oct 2020 14:10:29 +0200 Subject: [PATCH 047/319] [log] Add errors --- src/main/java/leekscript/AILog.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/leekscript/AILog.java b/src/main/java/leekscript/AILog.java index 4a95ff93..6849d0a5 100644 --- a/src/main/java/leekscript/AILog.java +++ b/src/main/java/leekscript/AILog.java @@ -19,6 +19,8 @@ public class AILog { public static final String DIVISION_BY_ZERO = "division_by_zero"; public static final String CAN_NOT_EXECUTE_VALUE = "can_not_execute_value"; public static final String CAN_NOT_EXECUTE_WITH_ARGUMENTS = "can_not_execute_with_arguments"; + public static final String NO_AI_EQUIPPED = "no_ai_equipped"; + public static final String INVALID_AI = "invalid_ai"; public static final String CAN_NOT_COMPILE_AI = "can_not_compile_ai"; public static final String AI_DISABLED = "ai_disabled"; public static final String AI_INTERRUPTED = "ai_interrupted"; From 402d133988c6e9cf23bbab04b245f55409af27a0 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 17 Oct 2020 14:13:50 +0200 Subject: [PATCH 048/319] [ai] Add id in AIs --- .../java/leekscript/compiler/LeekScript.java | 4 +++- src/main/java/leekscript/runner/AI.java | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index d5db642d..46f47a60 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -166,7 +166,9 @@ private static AI compile(AIFile ai, String AIClass, String jar, boolean noca throwException(error); } } - return IALoader.loadAI(IA_PATH, javaClassName); + AI ai = IALoader.loadAI(IA_PATH, javaClassName); + ai.setId(file.getId()); + return ai; } public static void throwException(String error) throws LeekScriptException { diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 1c233a56..58432e36 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -1,6 +1,7 @@ package leekscript.runner; import leekscript.AILog; +import leekscript.compiler.LeekScript; import leekscript.compiler.RandomGenerator; import leekscript.runner.PhpArray.Element; import leekscript.runner.values.AbstractLeekValue; @@ -28,16 +29,27 @@ public abstract class AI { protected JSONArray mErrorObject = null; protected String thisObject = null; + protected int id; protected AILog logs; protected AI mUAI; protected int mInstructions; protected RandomGenerator randomGenerator; - public AI() throws Exception { + public AI() { mUAI = this; logs = new AILog(); randomGenerator = LeekScript.getRandom(); - init(); + try { + init(); + } catch (Exception e) {} + } + + public void setId(int id) { + this.id = id; + } + + public int getId() { + return id; } // Method that can be overriden in each AI @@ -107,8 +119,6 @@ protected String getErrorLocalisation(int line) { return ""; } - - public AbstractLeekValue color(AbstractLeekValue red, AbstractLeekValue green, AbstractLeekValue blue) throws LeekRunException { return LeekValueManager.getLeekIntValue(((red.getInt(this) & 255) << 16) | ((green.getInt(this) & 255) << 8) | (blue.getInt(this) & 255)); } From 93bb73509ffa92af1c45fef2648bb9a83acc6568 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 17 Oct 2020 14:29:45 +0200 Subject: [PATCH 049/319] [resolver] Throw a FileNotFoundException instead of returning null --- .../java/leekscript/compiler/LeekScript.java | 49 ++++++------------- .../compiler/resolver/FileSystemResolver.java | 5 +- .../compiler/resolver/Resolver.java | 11 +++-- 3 files changed, 26 insertions(+), 39 deletions(-) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 46f47a60..dc321f08 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -2,10 +2,10 @@ import java.io.File; import java.io.FileOutputStream; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Random; -import leekscript.ErrorManager; import leekscript.LSException; import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.resolver.FileSystemContext; @@ -45,23 +45,17 @@ public double getDouble() { } }; - public static AI compileFile(String filepath, String AIClass, String jar, boolean nocache) throws LeekScriptException, LeekCompilerException { + public static AI compileFile(String filepath, String AIClass, String jar, boolean nocache) throws LeekScriptException, LeekCompilerException, IOException { AIFile ai = getResolver().resolve(filepath, null); - if (ai != null) { - return compile(ai, AIClass, jar, nocache); - } - return null; + return compile(ai, AIClass, jar, nocache); } - public static AI compileFileContext(String filepath, String AIClass, String jar, ResolverContext context, boolean nocache) throws LeekScriptException, LeekCompilerException { + public static AI compileFileContext(String filepath, String AIClass, String jar, ResolverContext context, boolean nocache) throws LeekScriptException, LeekCompilerException, IOException { AIFile ai = getResolver().resolve(filepath, context); - if (ai != null) { - return compile(ai, AIClass, jar, nocache); - } - return null; + return compile(ai, AIClass, jar, nocache); } - public static AI compileSnippet(String snippet, String AIClass, String jar) throws LeekScriptException, LeekCompilerException { + public static AI compileSnippet(String snippet, String AIClass, String jar) throws LeekScriptException, LeekCompilerException, IOException { AIFile ai = new AIFile("", snippet, System.currentTimeMillis(), null); return compile(ai, AIClass, jar, false); } @@ -119,37 +113,26 @@ public static RandomGenerator getRandom() { return defaultRandomGenerator; } - private static AI compile(AIFile ai, String AIClass, String jar, boolean nocache) throws LeekScriptException, LeekCompilerException { + public static AI compile(AIFile file, String AIClass, String jar, boolean nocache) throws LeekScriptException, LeekCompilerException, IOException { new File(IA_PATH).mkdir(); - String javaClassName = "AI_" + ai.getId(); + String javaClassName = "AI_" + file.getId(); String error = ""; File compiled = new File(IA_PATH + javaClassName + ".class"); File java = new File(IA_PATH + javaClassName + ".java"); - if (!compiled.exists() || compiled.length() == 0 || compiled.lastModified() < ai.getTimestamp() || nocache) { + if (!compiled.exists() || compiled.length() == 0 || compiled.lastModified() < file.getTimestamp() || nocache) { + // On commence par la conversion LS->Java - if (ai.getCode().isEmpty()) { // Pas de code du tout... - System.out.println("No code!"); - return null; - } - // On compile l'IA - String compiledJava = new IACompiler().compile(ai, javaClassName, AIClass); + String compiledJava = new IACompiler().compile(file, javaClassName, AIClass); - if (compiledJava.isEmpty()) { - System.out.println("No java generated!"); - return null; // Rien ne compile + if (compiledJava.isEmpty()) { // Rien ne compile, pas normal + throw new LeekScriptException(LeekScriptException.CANT_COMPILE, "No java generated!"); } // Si on a maintenant du code java - try { - FileOutputStream output = new FileOutputStream(java); - output.write(compiledJava.getBytes(StandardCharsets.UTF_8)); - output.close(); - } catch (Exception e) { - ErrorManager.exception(e); - System.out.println("Failed to compiled AI: " + ai.getPath()); - return null; - } + FileOutputStream output = new FileOutputStream(java); + output.write(compiledJava.getBytes(StandardCharsets.UTF_8)); + output.close(); // On va compiler le java maintenant JavaCompiler compiler = new JavaCompiler(java); diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index cdf9c09e..47bfccf6 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -1,5 +1,6 @@ package leekscript.compiler.resolver; +import java.io.FileNotFoundException; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -12,7 +13,7 @@ public class FileSystemResolver implements Resolver { @Override - public AIFile resolve(String path, ResolverContext basecontext) { + public AIFile resolve(String path, ResolverContext basecontext) throws FileNotFoundException { FileSystemContext context = (FileSystemContext) basecontext; if (context == null) { @@ -33,7 +34,7 @@ public AIFile resolve(String path, ResolverContext basecontex return new AIFile(path, code, timestamp, newContext, resolvedPath.hashCode() & 0xfffffff); } catch (IOException e) { - return null; + throw new FileNotFoundException(); } } diff --git a/src/main/java/leekscript/compiler/resolver/Resolver.java b/src/main/java/leekscript/compiler/resolver/Resolver.java index 8d627f68..a276bc98 100644 --- a/src/main/java/leekscript/compiler/resolver/Resolver.java +++ b/src/main/java/leekscript/compiler/resolver/Resolver.java @@ -1,9 +1,11 @@ package leekscript.compiler.resolver; +import java.io.FileNotFoundException; + import leekscript.compiler.AIFile; public interface Resolver { - + public class Result { public final String code; public final C context; @@ -12,14 +14,15 @@ public Result(String code, C context) { this.context = context; } } - + /** * Resolve a AI by path, like 'library.leek' or '../../test.leek' * @param path AI path * @param context The AI's context or null to initialize it from default - * @return The result with the AI's code and context, or null if not found + * @return The result with the AI's code and context + * @throws FileNotFoundException if the AI is not found */ - abstract public AIFile resolve(String path, ResolverContext context); + abstract public AIFile resolve(String path, ResolverContext context) throws FileNotFoundException; public abstract ResolverContext createContext(int parameter1, int parameter2); } From 52db4d5ada235b41e40951ab76b3a78bc26d0796 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 17 Oct 2020 14:30:06 +0200 Subject: [PATCH 050/319] [compiler] Add a success flag to analyzer result --- src/main/java/leekscript/compiler/IACompiler.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index 11a402ce..a658e462 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -17,6 +17,7 @@ public class IACompiler { public static class AnalyzeResult { public JSONArray informations; public List includedAIs = new ArrayList<>(); + public boolean success; } private final JSONArray mInformations = new JSONArray(); @@ -68,10 +69,13 @@ public AnalyzeResult analyze(AIFile ai) throws LeekCompilerException { // On sauvegarde les dépendances addInformations(ai, main.getMinLevel()); result.includedAIs = main.getIncludedAIs(); + result.success = true; } catch (LeekCompilerException e) { addError(e.getIA(), e.getLine(), e.getChar(), e.getWord(), e.getError(), e.getParameters()); + result.success = false; } catch (Exception e) { addError(ai, e.getMessage()); + result.success = false; } result.informations = mInformations; return result; From dd448d2a1aafefead09450cbb6226d4f86b76140 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 7 Nov 2020 13:27:52 +0100 Subject: [PATCH 051/319] [foreach] Implement for (@key : @var in array) foreach --- .../leekscript/compiler/WordCompiler.java | 16 +++++++++++++-- .../compiler/bloc/ForeachBlock.java | 10 ++++++++-- .../compiler/bloc/ForeachKeyBlock.java | 20 +++++++++++++++---- .../leekscript/runner/LeekOperations.java | 8 ++++---- .../runner/values/AbstractLeekValue.java | 5 ++++- .../runner/values/ArrayLeekValue.java | 8 ++++++++ .../runner/values/VariableLeekValue.java | 5 +++++ 7 files changed, 59 insertions(+), 13 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index a75a1af6..683075d1 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -327,6 +327,12 @@ private void forBlock() throws Exception { isDeclaration = true; mCompiler.skipWord(); } + // Référence ? + boolean reference1 = false; + if (mCompiler.getWord().getWord().equals("@")) { + reference1 = true; + mCompiler.skipWord(); + } // On récupère ensuite le nom de la variable if (mCompiler.getWord().getType() != WordParser.T_STRING) throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.VARIABLE_NAME_EXPECTED); @@ -353,6 +359,12 @@ private void forBlock() throws Exception { isValueDeclaration = true; mCompiler.skipWord(); } + // Référence ? + boolean reference2 = false; + if (mCompiler.getWord().getWord().equals("@")) { + reference2 = true; + mCompiler.skipWord(); + } // On récupère ensuite le nom de la variable accueillant la valeur if (mCompiler.getWord().getType() != WordParser.T_STRING) throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.VARIABLE_NAME_EXPECTED); @@ -371,7 +383,7 @@ private void forBlock() throws Exception { throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.KEYWORD_IN_EXPECTED); // On déclare notre bloc foreach et on entre dedans - ForeachKeyBlock block = new ForeachKeyBlock(mCurentBlock, mMain, isDeclaration, isValueDeclaration, mLine, mAI); + ForeachKeyBlock block = new ForeachKeyBlock(mCurentBlock, mMain, isDeclaration, isValueDeclaration, mLine, mAI, reference1, reference2); mCurentBlock.addInstruction(block); mCurentBlock = block; @@ -387,7 +399,7 @@ private void forBlock() throws Exception { // array) mCompiler.skipWord(); - ForeachBlock block = new ForeachBlock(mCurentBlock, mMain, isDeclaration, mLine, mAI); + ForeachBlock block = new ForeachBlock(mCurentBlock, mMain, isDeclaration, mLine, mAI, reference1); mCurentBlock.addInstruction(block); mCurentBlock = block; diff --git a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java index 849d3bad..47a07a59 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java @@ -9,10 +9,12 @@ public class ForeachBlock extends AbstractLeekBlock { private String mIterator; private AbstractExpression mArray; private boolean mIsDeclaration = false; + private boolean mReference = false; - public ForeachBlock(AbstractLeekBlock parent, MainLeekBlock main, boolean isDeclaration, int line, AIFile ai) { + public ForeachBlock(AbstractLeekBlock parent, MainLeekBlock main, boolean isDeclaration, int line, AIFile ai, boolean reference) { super(parent, main, line, ai); mIsDeclaration = isDeclaration; + mReference = reference; } public void setIterator(String iterator, boolean declaration) { @@ -43,7 +45,11 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine("if(" + ar + ".isArray()){"); if(mIsDeclaration) writer.addLine("final VariableLeekValue " + iterator_name + " = new VariableLeekValue(mUAI, LeekValueManager.NULL);"); else writer.addLine(iterator_name + ".set(mUAI, LeekValueManager.NULL);"); - writer.addLine("for(AbstractLeekValue " + var + " : " + ar + ".getArray()){ " + iterator_name + ".set(mUAI, " + var + ".getValue());"); + if (mReference) { + writer.addLine("for(AbstractLeekValue " + var + " : " + ar + ".getArray()){ " + iterator_name + ".setRef(mUAI, " + var + ");"); + } else { + writer.addLine("for(AbstractLeekValue " + var + " : " + ar + ".getArray()){ " + iterator_name + ".set(mUAI, " + var + ".getValue());"); + } writer.addCounter(1); super.writeJavaCode(mainblock, writer); diff --git a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java index bb89d7d8..404dc46d 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java @@ -12,11 +12,15 @@ public class ForeachKeyBlock extends AbstractLeekBlock { private String mKeyIterator = null; private boolean mIsKeyDeclaration = false; + private boolean mKeyReference = false; + private boolean mValueReference = false; - public ForeachKeyBlock(AbstractLeekBlock parent, MainLeekBlock main, boolean isKeyDeclaration, boolean isValueDeclaration, int line, AIFile ai) { + public ForeachKeyBlock(AbstractLeekBlock parent, MainLeekBlock main, boolean isKeyDeclaration, boolean isValueDeclaration, int line, AIFile ai, boolean keyReference, boolean valueReference) { super(parent, main, line, ai); mIsDeclaration = isValueDeclaration; mIsKeyDeclaration = isKeyDeclaration; + mKeyReference = keyReference; + mValueReference = valueReference; } public void setValueIterator(String iterator, boolean declaration) { @@ -58,13 +62,21 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { //Valeur if(mIsDeclaration) sb.append("final VariableLeekValue ").append(val_iterator).append(" = new VariableLeekValue(mUAI, LeekValueManager.NULL);"); else sb.append(val_iterator).append(".set(mUAI, LeekValueManager.NULL);"); - //On fait le parcour + //On fait le parcours //Déclaration de la variable sb.append("ArrayLeekValue.ArrayIterator ").append(var).append("=").append(ar).append(".getArray().getArrayIterator();"); sb.append("while(!").append(var).append(".ended()){"); //Maj des variables - sb.append(key_iterator).append(".set(mUAI, ").append(var).append(".getKey(mUAI));"); - sb.append(val_iterator).append(".set(mUAI, ").append(var).append(".getValue(mUAI));"); + if (mKeyReference) { + sb.append(key_iterator).append(".setRef(mUAI, ").append(var).append(".getKeyRef());"); + } else { + sb.append(key_iterator).append(".set(mUAI, ").append(var).append(".getKeyRef());"); + } + if (mValueReference) { + sb.append(val_iterator).append(".setRef(mUAI, ").append(var).append(".getValueRef());"); + } else { + sb.append(val_iterator).append(".set(mUAI, ").append(var).append(".getValueRef());"); + } sb.append(var).append(".next();"); writer.addCounter(1); diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index a3e1e365..d91b6357 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -29,9 +29,9 @@ public static AbstractLeekValue add(AI ai, AbstractLeekValue v1, // Concatenate arrays if (v1 instanceof ArrayLeekValue && v2 instanceof ArrayLeekValue) { - + ai.addOperations(1 + (v1.getArray().size() + v2.getArray().size()) * 2); - + ArrayLeekValue retour = new ArrayLeekValue(); ArrayIterator iterator = v1.getArray().getArrayIterator(); @@ -109,7 +109,7 @@ public static AbstractLeekValue multiply(AI ai, AbstractLeekValue v1, AbstractLe } public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws Exception { - + ai.addOperations(AbstractLeekValue.DIV_COST); v1 = v1.getValue(); @@ -133,7 +133,7 @@ public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeek } public static AbstractLeekValue modulus(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws Exception { - + ai.addOperations(AbstractLeekValue.MOD_COST); v1 = v1.getValue(); v2 = v2.getValue(); diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index b606ee63..0b183126 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -12,7 +12,7 @@ public abstract class AbstractLeekValue { public final static int NULL = 4; public final static int STRING = 5; public final static int FUNCTION = 6; - + public final static int ADD_COST = 1; public final static int MUL_COST = 5; public final static int DIV_COST = 5; @@ -84,6 +84,9 @@ public AbstractLeekValue opposite(AI ai) throws Exception { public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunException, Exception { return this; } + public AbstractLeekValue setRef(AI ai, AbstractLeekValue value) throws LeekRunException, Exception { + return this; + } public int getArgumentsCount(AI ai) throws Exception { return -1; diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index ad8b45e1..1cf69ab8 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -38,6 +38,10 @@ public AbstractLeekValue getKey(AI ai) throws Exception { return LeekOperations.clone(ai, mElement.key()); } + public AbstractLeekValue getKeyRef() throws Exception { + return mElement.key(); + } + public Object key() { return mElement.keyObject(); } @@ -46,6 +50,10 @@ public AbstractLeekValue getValue(AI ai) throws Exception { return LeekOperations.clone(ai, mElement.value()); } + public AbstractLeekValue getValueRef() throws Exception { + return mElement.value(); + } + public AbstractLeekValue getKeyReference() throws Exception { return mElement.key(); } diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index ae4d611e..67c8f6ec 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -78,6 +78,11 @@ public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws Exception { return mValue = LeekOperations.clone(ai, value.getValue()); } + @Override + public AbstractLeekValue setRef(AI ai, AbstractLeekValue value) throws Exception { + return mValue = value.getValue(); + } + @Override public AbstractLeekValue increment(AI ai) throws Exception { mValue = mValue.getValue(); From 3bcfb7eb725c163b7b64180d33113dcff514d838 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 7 Nov 2020 13:28:01 +0100 Subject: [PATCH 052/319] [file] Add getTimestamp method --- src/main/java/leekscript/compiler/AIFile.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/leekscript/compiler/AIFile.java b/src/main/java/leekscript/compiler/AIFile.java index 6d411fb4..a8c69706 100644 --- a/src/main/java/leekscript/compiler/AIFile.java +++ b/src/main/java/leekscript/compiler/AIFile.java @@ -47,4 +47,7 @@ public void setPath(String path) { public long getTimestamp() { return this.timestamp; } + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } } From 427f3dd0530c08a1d7e70f99780e8e6c5e948fa3 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 7 Nov 2020 13:28:13 +0100 Subject: [PATCH 053/319] [value] Add getStringOrNullValue utility method --- src/main/java/leekscript/runner/LeekValueManager.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index 57cd699e..756342d7 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -85,6 +85,14 @@ public static AbstractLeekValue getLeekIntValue(AI ai, int nb, AbstractLeekValue return mValue; } + public static AbstractLeekValue getStringOrNullValue(String string) { + if (string == null) { + return LeekValueManager.NULL; + } else { + return new StringLeekValue(string); + } + } + public static AbstractLeekValue getLeekBooleanValue(boolean b) { return b ? TRUE : FALSE; } From a607325a1cb56f8883aa69b01783d9d1a062fabd Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 14 Nov 2020 15:13:08 +0100 Subject: [PATCH 054/319] [leekscript] Add ~ operator (bit not) --- src/main/java/leekscript/compiler/WordParser.java | 6 +++--- .../java/leekscript/compiler/expression/LeekExpression.java | 4 ++++ src/main/java/leekscript/compiler/expression/Operators.java | 4 ++++ .../java/leekscript/runner/values/AbstractLeekValue.java | 4 ++++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index 082631c4..a23b752a 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -12,9 +12,9 @@ public class WordParser { /** * Instructions byte(0) (0-255) byte => instruction - * + * * 1 : Etiquette SmallInt (2) : numéro d'étiquette - * + * * 2 : SetVariable StringUTF : nom variable */ @@ -169,7 +169,7 @@ else if(c == '.'){ throw new LeekCompilerException(mAI, line_counter, char_counter, word, LeekCompilerException.INVALID_CHAR); } } - else if(c == '@' || c == '+' || c == '=' || c == '<' || c == '>' || c == '|' || c == '&' || c == '-' || c == '/' || c == '*' || c == '%' || c == '!' || c == '?' || c == '^'){ + else if(c == '@' || c == '+' || c == '=' || c == '<' || c == '>' || c == '|' || c == '&' || c == '-' || c == '/' || c == '*' || c == '%' || c == '!' || c == '?' || c == '^' || c == '~'){ if(type == T_VAR_STRING){ word += c; } diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index dcc6c012..c48f79a0 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -578,6 +578,10 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { mExpression2.writeJavaCode(mainblock, writer); writer.addCode(".not(mUAI)"); return; + case Operators.BITNOT: + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(".bnot(mUAI)"); + return; case Operators.UNARY_MINUS: mExpression2.writeJavaCode(mainblock, writer); writer.addCode(".opposite(mUAI)"); diff --git a/src/main/java/leekscript/compiler/expression/Operators.java b/src/main/java/leekscript/compiler/expression/Operators.java index 12f70109..8b6cfae7 100644 --- a/src/main/java/leekscript/compiler/expression/Operators.java +++ b/src/main/java/leekscript/compiler/expression/Operators.java @@ -47,6 +47,7 @@ public class Operators { public final static int PRE_INCREMENT = 44; public final static int PRE_DECREMENT = 45; public final static int REFERENCE = 46; + public final static int BITNOT = 47; public final static int getOperator(String operator) { if(operator.equals("[")) return CROCHET; @@ -82,6 +83,7 @@ public final static int getOperator(String operator) { if(operator.equals("^")) return BITXOR; if(operator.equals("&")) return BITAND; if(operator.equals("|")) return BITOR; + if(operator.equals("~")) return BITNOT; if(operator.equals("<<")) return SHIFT_LEFT; if(operator.equals(">>")) return SHIFT_RIGHT; if(operator.equals(">>>")) return ROTATE_RIGHT; @@ -107,6 +109,7 @@ public static int getPriority(int operator) { case UNARY_MINUS: return 14; case NOT: + case BITNOT: return 13; case POWER: return 12; @@ -170,6 +173,7 @@ public static boolean isUnaryPrefix(int operator) { case PRE_INCREMENT: case PRE_DECREMENT: case REFERENCE: + case BITNOT: return true; } return false; diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 0b183126..cd6abb6d 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -77,6 +77,10 @@ public AbstractLeekValue not(AI ai) { return LeekValueManager.getLeekBooleanValue(!getBoolean()); } + public AbstractLeekValue bnot(AI ai) throws Exception { + return LeekValueManager.getLeekIntValue(~getInt(ai)); + } + public AbstractLeekValue opposite(AI ai) throws Exception { return LeekValueManager.getLeekIntValue(-getInt(ai)); } From 755c1cbf0688dc6f12cdd344c6c1c4f9e7bc6376 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 18 Dec 2020 20:02:14 +0100 Subject: [PATCH 055/319] [array] Fix operation counting --- src/main/java/leekscript/runner/AI.java | 4 +++ src/main/java/leekscript/runner/PhpArray.java | 34 +++++++++---------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 58432e36..a3325f81 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -74,6 +74,10 @@ public void addOperations(int nb) throws LeekRunException { } } + public void addOperationsNoCheck(int nb) throws LeekRunException { + mOperations += nb; + } + public void resetCounter() { mOperations = 0; } diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index ef07bc6e..7744c60f 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -202,11 +202,11 @@ public void setValue(AI ai, AbstractLeekValue v) throws Exception { private Element[] mTable = null; public PhpArray() {} - + public PhpArray(AI ai, int capacity) throws LeekRunException { initTable(ai, capacity); } - + public PhpArray(AI ai, PhpArray phpArray) throws Exception { if (phpArray.size() > 0) { initTable(ai, phpArray.size()); @@ -217,19 +217,19 @@ public PhpArray(AI ai, PhpArray phpArray) throws Exception { } } } - + private void initTable(AI ai, int capacity) throws LeekRunException { - ai.addOperations(capacity / 5); + ai.addOperationsNoCheck(capacity / 5); this.capacity = capacity; mTable = new Element[capacity]; } - + private void growCapacity(AI ai) throws Exception { if (capacity == MAX_CAPACITY) return; - + capacity = Math.min(capacity * 2, MAX_CAPACITY); - + // Copy in a new array PhpArray newArray = new PhpArray(ai, capacity); Element e = mHead; @@ -289,7 +289,7 @@ public boolean containsKey(AI ai, Object key) throws LeekRunException { * @param value * Valeur à rechercher * @return True si la valeur existe dans le tableau - * @throws LeekRunException + * @throws LeekRunException */ public boolean contains(AI ai, AbstractLeekValue value) throws LeekRunException { Element e = mHead; @@ -308,7 +308,7 @@ public boolean contains(AI ai, AbstractLeekValue value) throws LeekRunException * Valeur à rechercher * @param pos * @return Clé associée à la valeur ou null si la valeur n'existe pas - * @throws LeekRunException + * @throws LeekRunException */ public AbstractLeekValue search(AI ai, AbstractLeekValue value, int pos) throws LeekRunException { Element e = mHead; @@ -650,7 +650,7 @@ public void insert(AI ai, int position, AbstractLeekValue value) throws Exceptio // On réindexe reindex(ai); - + mSize++; if (mSize > capacity) { growCapacity(ai); @@ -664,7 +664,7 @@ public void reindex(AI ai) throws LeekRunException { // Réindexer le tableau (Change l'index de toutes les valeurs // numériques) int new_index = 0; - + Element e = mHead; while (e != null) { if (e.numeric) { @@ -716,7 +716,7 @@ private Element createElement(AI ai, Object key, AbstractLeekValue value) throws // On ajoute la taille de la clé int keySize = 1; - + e.value = new PhpArrayVariableLeekValue(this, ai, value, keySize); if (key instanceof Integer) { // On met à jour l'index suivant @@ -730,7 +730,7 @@ private Element createElement(AI ai, Object key, AbstractLeekValue value) throws addToHashMap(ai, e); int operations = ArrayLeekValue.ARRAY_CELL_CREATE_OPERATIONS + (int) Math.sqrt(mSize) / 3; - ai.addOperations(operations); + ai.addOperationsNoCheck(operations); return e; } @@ -789,7 +789,7 @@ private Element getElement(AI ai, Object key) throws LeekRunException { return null; // empty array } int operations = ArrayLeekValue.ARRAY_CELL_ACCESS_OPERATIONS; - ai.addOperations(operations); + ai.addOperationsNoCheck(operations); int hash = getHash(key); int index = getIndex(hash); @@ -870,9 +870,9 @@ public Iterator reversedIterator() { } public boolean equals(AI ai, PhpArray array) throws LeekRunException { - + ai.addOperations(1); - + // On commence par vérifier la taille if (mSize != array.mSize) return false; @@ -880,7 +880,7 @@ public boolean equals(AI ai, PhpArray array) throws LeekRunException { return true; ai.addOperations(mSize); - + Element e1 = mHead; Element e2 = array.mHead; // On va comparer chaque élément 1 à 1 From 6f9527dbbbb203cfcb10e8d39c2ea7545f0a13d4 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 22 Jan 2021 23:54:12 +0100 Subject: [PATCH 056/319] [include] Fix missing file management --- .../compiler/bloc/MainLeekBlock.java | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 7d8d85c8..e33bbc6e 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -1,5 +1,6 @@ package leekscript.compiler.bloc; +import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -73,21 +74,22 @@ public void setMinLevel(int min_level) { } public boolean includeAI(String path) throws Exception { - AIFile ai = LeekScript.getResolver().resolve(path, mCompiler.getCurrentAI().getContext()); - if (ai == null) { - return false; - } - if (mIncluded.contains(ai.getId())) { + try { + AIFile ai = LeekScript.getResolver().resolve(path, mCompiler.getCurrentAI().getContext()); + if (mIncluded.contains(ai.getId())) { + return true; + } + mIncluded.add(ai.getId()); + AIFile previousAI = mCompiler.getCurrentAI(); + mCompiler.setCurrentAI(ai); + WordParser words = new WordParser(ai); + WordCompiler compiler = new WordCompiler(words, this, ai); + compiler.readCode(); + mCompiler.setCurrentAI(previousAI); return true; + } catch (FileNotFoundException e) { + return false; } - mIncluded.add(ai.getId()); - AIFile previousAI = mCompiler.getCurrentAI(); - mCompiler.setCurrentAI(ai); - WordParser words = new WordParser(ai); - WordCompiler compiler = new WordCompiler(words, this, ai); - compiler.readCode(); - mCompiler.setCurrentAI(previousAI); - return true; } public boolean hasUserFunction(String name, boolean use_declarations) { From e289b8c9279ec3498a709b687269564208e48dfe Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 14 Feb 2021 15:54:59 +0100 Subject: [PATCH 057/319] [log] Escape tabs directly --- src/main/java/leekscript/AILog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/AILog.java b/src/main/java/leekscript/AILog.java index 6849d0a5..548388a0 100644 --- a/src/main/java/leekscript/AILog.java +++ b/src/main/java/leekscript/AILog.java @@ -71,7 +71,7 @@ public void addSystemLog(int type, String trace, String key, String[] parameters } public void addLog(int type, String message) { - + message = message.replaceAll("\t", " "); addLog(type, message, 0); } From 3daf418a50edbcf3e80d4116a5d5a8c810041484 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 13 Feb 2021 11:39:24 +0100 Subject: [PATCH 058/319] [error] Return the full stacktrace in error messages --- src/main/java/leekscript/runner/AI.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index a3325f81..ebc119d8 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -87,12 +87,13 @@ protected NullLeekValue nothing(AbstractLeekValue obj) throws Exception { } public String getErrorMessage(StackTraceElement[] elements) { + StringBuilder sb = new StringBuilder(); for (StackTraceElement element : elements) { if (element.getMethodName().equals("runIA") || element.getMethodName().startsWith("user_function_")) { - return getErrorLocalisation(element.getLineNumber()); + sb.append(getErrorLocalisation(element.getLineNumber())).append("\n"); } } - return ""; + return sb.toString(); } public String getErrorMessage(Throwable e) { @@ -117,7 +118,7 @@ protected String getErrorLocalisation(int line) { if (mErrorObject.size() > value) { JSONArray l = mErrorObject.getJSONArray(value); if (l != null && l.size() >= 3) { - return "AI " + l.getString(1) + ", line " + l.getString(2) + " ▶ "; + return "\t▶ AI " + l.getString(1) + ", line " + l.getString(2); } } return ""; From 3440c65a2d7a1cae5a366c7c0276f12f3cf9da44 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 13 Feb 2021 11:35:09 +0100 Subject: [PATCH 059/319] [ai] Add version --- src/main/java/leekscript/compiler/AIFile.java | 11 ++++++++--- src/main/java/leekscript/compiler/IACompiler.java | 8 ++++---- src/main/java/leekscript/compiler/LeekScript.java | 2 +- src/main/java/leekscript/compiler/WordCompiler.java | 8 +++++++- src/main/java/leekscript/compiler/WordParser.java | 4 +++- .../compiler/resolver/FileSystemResolver.java | 2 +- src/main/java/leekscript/runner/AI.java | 2 ++ 7 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/main/java/leekscript/compiler/AIFile.java b/src/main/java/leekscript/compiler/AIFile.java index a8c69706..838dce42 100644 --- a/src/main/java/leekscript/compiler/AIFile.java +++ b/src/main/java/leekscript/compiler/AIFile.java @@ -9,15 +9,17 @@ public class AIFile { private C context; private int id; private long timestamp; + private int version; - public AIFile(String path, String code, long timestamp, C context) { - this(path, code, timestamp, context, (context + "/" + path).hashCode() & 0xfffffff); + public AIFile(String path, String code, long timestamp, int version, C context) { + this(path, code, timestamp, version, context, (context + "/" + path).hashCode() & 0xfffffff); } - public AIFile(String path, String code, long timestamp, C context, int id) { + public AIFile(String path, String code, long timestamp, int version, C context, int id) { this.path = path; this.code = code; this.context = context; this.timestamp = timestamp; + this.version = version; this.id = id; } public int getId() { @@ -50,4 +52,7 @@ public long getTimestamp() { public void setTimestamp(long timestamp) { this.timestamp = timestamp; } + public int getVersion() { + return this.version; + } } diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index a658e462..0f2df5e8 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -61,10 +61,10 @@ public AnalyzeResult analyze(AIFile ai) throws LeekCompilerException { AnalyzeResult result = new AnalyzeResult(); try { // On lance la compilation du code de l'IA - WordParser parser = new WordParser(ai); + WordParser parser = new WordParser(ai, ai.getVersion()); // Si on est là c'est qu'on a une liste de words correcte, on peut commencer à lire MainLeekBlock main = new MainLeekBlock(this, ai); - WordCompiler compiler = new WordCompiler(parser, main, ai); + WordCompiler compiler = new WordCompiler(parser, main, ai, ai.getVersion()); compiler.readCode(); // On sauvegarde les dépendances addInformations(ai, main.getMinLevel()); @@ -85,10 +85,10 @@ public String compile(AIFile ai, String javaClassName, String AIClass) throws JavaWriter writer = new JavaWriter(true); try { // On lance la compilation du code de l'IA - WordParser parser = new WordParser(ai); + WordParser parser = new WordParser(ai, ai.getVersion()); // Si on est là c'est qu'on a une liste de words correcte, on peut commencer à lire MainLeekBlock main = new MainLeekBlock(this, ai); - WordCompiler compiler = new WordCompiler(parser, main, ai); + WordCompiler compiler = new WordCompiler(parser, main, ai, ai.getVersion()); compiler.readCode(); compiler.writeJava(javaClassName, writer, AIClass); diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index dc321f08..de310d7f 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -56,7 +56,7 @@ public static AI compileFileContext(String filepath, String AIClass, String jar, } public static AI compileSnippet(String snippet, String AIClass, String jar) throws LeekScriptException, LeekCompilerException, IOException { - AIFile ai = new AIFile("", snippet, System.currentTimeMillis(), null); + AIFile ai = new AIFile("", snippet, System.currentTimeMillis(), 11, null); return compile(ai, AIClass, jar, false); } diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 683075d1..ddfc92ea 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -46,12 +46,14 @@ public class WordCompiler { private final WordParser mCompiler; private int mLine; private AIFile mAI = null; + private final int version; - public WordCompiler(WordParser cmp, MainLeekBlock main, AIFile ai) { + public WordCompiler(WordParser cmp, MainLeekBlock main, AIFile ai, int version) { mCompiler = cmp; mMain = main; mCurentBlock = main; mAI = ai; + this.version = version; } public void readCode() throws Exception { @@ -908,4 +910,8 @@ public boolean isGlobalAvailable(String word) { public String getString() { return mMain.getCode(); } + + public int getVersion() { + return this.version; + } } diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index a23b752a..9b0dd231 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -44,10 +44,12 @@ public class WordParser { private int line_counter = 0; private int char_counter = 0; private final String code; + private int version; - public WordParser(AIFile ai) { + public WordParser(AIFile ai, int version) { mAI = ai; this.code = ai.getCode(); + this.version = version; } public void compile() throws LeekCompilerException { diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index 47bfccf6..9f8ee875 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -31,7 +31,7 @@ public AIFile resolve(String path, ResolverContext basecontex long timestamp = resolvedPath.toFile().lastModified(); - return new AIFile(path, code, timestamp, newContext, resolvedPath.hashCode() & 0xfffffff); + return new AIFile(path, code, timestamp, 11, newContext, resolvedPath.hashCode() & 0xfffffff); } catch (IOException e) { throw new FileNotFoundException(); diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index ebc119d8..f2b9b2a6 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -373,4 +373,6 @@ else if (type == AILog.STANDARD) public RandomGenerator getRandom() { return randomGenerator; } + + public abstract int getVersion(); } From e047a51c071a043e0c417158602167284d8cfcb6 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 14 Feb 2021 15:27:13 +0100 Subject: [PATCH 060/319] [include] Update --- src/main/java/leekscript/compiler/WordCompiler.java | 5 +++-- src/main/java/leekscript/compiler/WordParser.java | 2 +- src/main/java/leekscript/compiler/bloc/MainLeekBlock.java | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index ddfc92ea..e606c087 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -58,7 +58,7 @@ public WordCompiler(WordParser cmp, MainLeekBlock main, AIFile ai, int versio public void readCode() throws Exception { try { - mCompiler.compile(); + mCompiler.compile(this); // Receherche des fonctions utilisateur while (mCompiler.haveWords()) { if (mCompiler.getWord().getWord().equals("global")) { @@ -261,8 +261,9 @@ private void includeBlock() throws Exception { throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.AI_NAME_EXPECTED); String iaName = mCompiler.readWord().getWord(); - if (!mMain.includeAI(iaName)) + if (!mMain.includeAI(this, iaName)) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.AI_NOT_EXISTING, new String[] { iaName }); + } if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index 9b0dd231..6b8e792c 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -52,7 +52,7 @@ public WordParser(AIFile ai, int version) { this.version = version; } - public void compile() throws LeekCompilerException { + public void compile(WordCompiler compiler) throws LeekCompilerException { words.clear(); line_counter = 1; char_counter = 0; diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index e33bbc6e..83c45858 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -73,7 +73,7 @@ public void setMinLevel(int min_level) { this.mMinLevel = min_level; } - public boolean includeAI(String path) throws Exception { + public boolean includeAI(WordCompiler compiler, String path) throws Exception { try { AIFile ai = LeekScript.getResolver().resolve(path, mCompiler.getCurrentAI().getContext()); if (mIncluded.contains(ai.getId())) { @@ -82,9 +82,9 @@ public boolean includeAI(String path) throws Exception { mIncluded.add(ai.getId()); AIFile previousAI = mCompiler.getCurrentAI(); mCompiler.setCurrentAI(ai); - WordParser words = new WordParser(ai); - WordCompiler compiler = new WordCompiler(words, this, ai); - compiler.readCode(); + WordParser words = new WordParser(ai, compiler.getVersion()); + WordCompiler newCompiler = new WordCompiler(words, this, ai, compiler.getVersion()); + newCompiler.readCode(); mCompiler.setCurrentAI(previousAI); return true; } catch (FileNotFoundException e) { From 703bc7e91cf446dd7ba37455b1a0a0c3b89ede02 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 14 Feb 2021 21:47:36 +0100 Subject: [PATCH 061/319] [compiler] Remove jar option, replace it by current classpath --- src/main/java/leekscript/TopLevel.java | 2 +- .../java/leekscript/compiler/JavaCompiler.java | 5 +++-- .../java/leekscript/compiler/LeekScript.java | 16 ++++++++-------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/java/leekscript/TopLevel.java b/src/main/java/leekscript/TopLevel.java index 38f1279c..14c4b6f2 100644 --- a/src/main/java/leekscript/TopLevel.java +++ b/src/main/java/leekscript/TopLevel.java @@ -54,7 +54,7 @@ private static void executeSnippet(String code) { private static void executeFile(File file) { try { long ct = System.currentTimeMillis(); - AI ai = LeekScript.compileFile(file.getPath(), "AI", "leekscript.jar", false); + AI ai = LeekScript.compileFile(file.getPath(), "AI", false); long compileTime = System.currentTimeMillis() - ct; long et = System.currentTimeMillis(); diff --git a/src/main/java/leekscript/compiler/JavaCompiler.java b/src/main/java/leekscript/compiler/JavaCompiler.java index f201c07c..81605277 100644 --- a/src/main/java/leekscript/compiler/JavaCompiler.java +++ b/src/main/java/leekscript/compiler/JavaCompiler.java @@ -19,7 +19,7 @@ public JavaCompiler(File input) { mInput = input; } - public void compile(String jar) throws Exception { + public void compile() throws Exception { if (mStatus != INIT) return; mStatus = RUNNING; @@ -28,7 +28,8 @@ public void compile(String jar) throws Exception { return; } - String[] args = new String[] { "javac", "-encoding", "utf8", "-classpath", jar, mInput.getPath() }; + String classpath = JavaCompiler.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath(); + String[] args = new String[] { "javac", "-encoding", "utf8", "-classpath", classpath, mInput.getPath() }; // System.out.println(String.join(" ", args)); ProcessBuilder pb = new ProcessBuilder(args); Worker worker = new Worker(pb); diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index de310d7f..0c14f727 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -45,19 +45,19 @@ public double getDouble() { } }; - public static AI compileFile(String filepath, String AIClass, String jar, boolean nocache) throws LeekScriptException, LeekCompilerException, IOException { + public static AI compileFile(String filepath, String AIClass, boolean nocache) throws LeekScriptException, LeekCompilerException, IOException { AIFile ai = getResolver().resolve(filepath, null); - return compile(ai, AIClass, jar, nocache); + return compile(ai, AIClass, nocache); } - public static AI compileFileContext(String filepath, String AIClass, String jar, ResolverContext context, boolean nocache) throws LeekScriptException, LeekCompilerException, IOException { + public static AI compileFileContext(String filepath, String AIClass, ResolverContext context, boolean nocache) throws LeekScriptException, LeekCompilerException, IOException { AIFile ai = getResolver().resolve(filepath, context); - return compile(ai, AIClass, jar, nocache); + return compile(ai, AIClass, nocache); } public static AI compileSnippet(String snippet, String AIClass, String jar) throws LeekScriptException, LeekCompilerException, IOException { AIFile ai = new AIFile("", snippet, System.currentTimeMillis(), 11, null); - return compile(ai, AIClass, jar, false); + return compile(ai, AIClass, false); } public static boolean testScript(String leek, String script, AbstractLeekValue s, String AIClass, String jar, boolean nocache) throws Exception { @@ -91,7 +91,7 @@ public static boolean testScript(String script, AbstractLeekValue s) throws Exce } public static String runFile(String filename) throws Exception { - AI ai = LeekScript.compileFile(filename, "AI", "leekscript.jar", true); + AI ai = LeekScript.compileFile(filename, "AI", true); AbstractLeekValue v = ai.runIA(); System.out.println(v.getString(ai)); return v.getString(ai); @@ -113,7 +113,7 @@ public static RandomGenerator getRandom() { return defaultRandomGenerator; } - public static AI compile(AIFile file, String AIClass, String jar, boolean nocache) throws LeekScriptException, LeekCompilerException, IOException { + public static AI compile(AIFile file, String AIClass, boolean nocache) throws LeekScriptException, LeekCompilerException, IOException { new File(IA_PATH).mkdir(); String javaClassName = "AI_" + file.getId(); @@ -139,7 +139,7 @@ public static AI compile(AIFile file, String AIClass, String jar, boolean noc int status = JavaCompiler.INIT; try { - compiler.compile(jar); + compiler.compile(); status = JavaCompiler.getStatus(); } catch (Exception e) { error = e.getMessage(); From 1f6ab24d1c1fd691aced9b0615c0e5650e63fbc7 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 15 Feb 2021 13:11:41 +0100 Subject: [PATCH 062/319] [api] Remove jar, add missing versions --- src/main/java/leekscript/TopLevel.java | 2 +- .../java/leekscript/compiler/LeekScript.java | 10 +++++----- .../compiler/resolver/FileSystemResolver.java | 2 +- .../compiler/resolver/Resolver.java | 2 +- src/test/java/test/TestAI.java | 5 +++++ src/test/java/test/TestWithFile.java | 20 +++++++++---------- 6 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/main/java/leekscript/TopLevel.java b/src/main/java/leekscript/TopLevel.java index 14c4b6f2..29751ce4 100644 --- a/src/main/java/leekscript/TopLevel.java +++ b/src/main/java/leekscript/TopLevel.java @@ -33,7 +33,7 @@ public static void main(String[] args) { private static void executeSnippet(String code) { try { long ct = System.currentTimeMillis(); - AI ai = LeekScript.compileSnippet(code, "AI", "leekscript.jar"); + AI ai = LeekScript.compileSnippet(code, "AI"); long compileTime = System.currentTimeMillis() - ct; long et = System.currentTimeMillis(); diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 0c14f727..9fadc4e7 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -55,13 +55,13 @@ public static AI compileFileContext(String filepath, String AIClass, ResolverCon return compile(ai, AIClass, nocache); } - public static AI compileSnippet(String snippet, String AIClass, String jar) throws LeekScriptException, LeekCompilerException, IOException { + public static AI compileSnippet(String snippet, String AIClass) throws LeekScriptException, LeekCompilerException, IOException { AIFile ai = new AIFile("", snippet, System.currentTimeMillis(), 11, null); return compile(ai, AIClass, false); } - public static boolean testScript(String leek, String script, AbstractLeekValue s, String AIClass, String jar, boolean nocache) throws Exception { - AI ai = LeekScript.compileSnippet(script, AIClass, jar); + public static boolean testScript(String leek, String script, AbstractLeekValue s, String AIClass, boolean nocache) throws Exception { + AI ai = LeekScript.compileSnippet(script, AIClass); AbstractLeekValue v = ai.runIA(); if (v.equals(ai, s)) return true; @@ -80,11 +80,11 @@ public static boolean testScript(String leek, String script, AbstractLeekValue s } public static AbstractLeekValue runScript(String script, boolean nocache) throws Exception { - return LeekScript.compileSnippet(script, "AI", "leekscript.jar").runIA(); + return LeekScript.compileSnippet(script, "AI").runIA(); } public static boolean testScript(String script, AbstractLeekValue s) throws Exception { - AI ai = LeekScript.compileSnippet(script, "AI", "leekscript.jar"); + AI ai = LeekScript.compileSnippet(script, "AI"); AbstractLeekValue v = ai.runIA(); System.out.println(v.getString(ai)); return v.equals(ai, s); diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index 9f8ee875..0d4a7509 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -38,7 +38,7 @@ public AIFile resolve(String path, ResolverContext basecontex } } - public ResolverContext createContext(int parameter1, int parameter2) { + public ResolverContext createContext(int parameter1, int parameter2, int parameter3) { return new FileSystemContext(Paths.get(".").toFile()); } } diff --git a/src/main/java/leekscript/compiler/resolver/Resolver.java b/src/main/java/leekscript/compiler/resolver/Resolver.java index a276bc98..9dc07d39 100644 --- a/src/main/java/leekscript/compiler/resolver/Resolver.java +++ b/src/main/java/leekscript/compiler/resolver/Resolver.java @@ -24,5 +24,5 @@ public Result(String code, C context) { */ abstract public AIFile resolve(String path, ResolverContext context) throws FileNotFoundException; - public abstract ResolverContext createContext(int parameter1, int parameter2); + public abstract ResolverContext createContext(int parameter1, int parameter2, int parameter3); } diff --git a/src/test/java/test/TestAI.java b/src/test/java/test/TestAI.java index 495c2493..02d67fac 100644 --- a/src/test/java/test/TestAI.java +++ b/src/test/java/test/TestAI.java @@ -48,4 +48,9 @@ public boolean[] anonymousFunctionReference(int id) { return null; } + @Override + public int getVersion() { + return 11; + } + } diff --git a/src/test/java/test/TestWithFile.java b/src/test/java/test/TestWithFile.java index 8eb392b7..08919ec9 100644 --- a/src/test/java/test/TestWithFile.java +++ b/src/test/java/test/TestWithFile.java @@ -15,49 +15,49 @@ public class TestWithFile { public void testBasicFile() throws Exception { assertEquals("bonjour", LeekScript.runFile("test/ai/bonjour.leek")); } - + @Test public void testLargeFile() throws Exception { assertEquals("cent-vingt-trois millions quatre-cent-cinquante-six-mille-sept-cent-quatre-vingt-neuf", LeekScript.runFile("test/ai/french.leek")); } - + @Test public void testInclude() throws Exception { assertEquals("[a, b, KEY]", LeekScript.runFile("test/ai/array_keys.leek")); } - + @Test public void testIncludeMultiple() throws Exception { assertEquals("[a, b, KEY]", LeekScript.runFile("test/ai/include_multiple.leek")); } - + @Test public void testCustomResolver() throws Exception { - class CustomContext extends ResolverContext {} + class CustomContext extends ResolverContext {} LeekScript.setResolver(new Resolver() { @Override public AIFile resolve(String path, ResolverContext context) { - return new AIFile(path, "return 'generated';", System.currentTimeMillis(), new CustomContext()); + return new AIFile(path, "return 'generated';", System.currentTimeMillis(), 11, new CustomContext()); } @Override - public ResolverContext createContext(int parameter1, int parameter2) { + public ResolverContext createContext(int parameter1, int parameter2, int parameter3) { return null; } }); assertEquals("generated", LeekScript.runFile("whatever")); LeekScript.resetResolver(); } - + @Test public void testSubFolder() throws Exception { assertEquals("sub", LeekScript.runFile("test/ai/include_sub.leek")); } - + @Test public void testRelativePath() throws Exception { assertEquals("cent-vingt-trois millions quatre-cent-cinquante-six-mille-sept-cent-quatre-vingt-neuf", LeekScript.runFile("test/ai/subfolder/include_parent.leek")); } - + @Test public void testMultipleInclude() throws Exception { assertEquals("bonjour", LeekScript.runFile("test/ai/multiple_includes.leek")); From ff420be8b9eb466504cd85faf94c5f1ee6057a86 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 16 Feb 2021 00:24:24 +0100 Subject: [PATCH 063/319] [stacktrace] Limit to 50 elements --- src/main/java/leekscript/runner/AI.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index f2b9b2a6..09ea0566 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -88,9 +88,14 @@ protected NullLeekValue nothing(AbstractLeekValue obj) throws Exception { public String getErrorMessage(StackTraceElement[] elements) { StringBuilder sb = new StringBuilder(); + int count = 0; for (StackTraceElement element : elements) { if (element.getMethodName().equals("runIA") || element.getMethodName().startsWith("user_function_")) { sb.append(getErrorLocalisation(element.getLineNumber())).append("\n"); + if (count++ > 50) { + sb.append("[...]"); + break; + } } } return sb.toString(); From f6265834d8bc0e8d8840488dc8722951534fde69 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 19 Feb 2021 12:04:20 +0100 Subject: [PATCH 064/319] [insert] Use size() instead of getSize() --- src/main/java/leekscript/runner/LeekFunctions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index b9381366..c08b82be 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -632,7 +632,7 @@ public int[] parameters() { @Override public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { - leekIA.addOperations(1 + (parameters[0].getArray().getSize() - parameters[2].getInt(leekIA)) * 4); + leekIA.addOperations(1 + (parameters[0].getArray().size() - parameters[2].getInt(leekIA)) * 4); } }, push(2) { From 53e4a219cc6e8f670f2c290d2c3ee6386c6564db Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 23:41:10 +0100 Subject: [PATCH 065/319] [array] Seed shuffle function with a random generator number --- src/main/java/leekscript/runner/PhpArray.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 7744c60f..3fe3fd29 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -5,7 +5,9 @@ import java.util.Comparator; import java.util.Iterator; import java.util.List; +import java.util.Random; +import leekscript.compiler.LeekScript; import leekscript.runner.values.AbstractLeekValue; import leekscript.runner.values.ArrayLeekValue; import leekscript.runner.values.PhpArrayVariableLeekValue; @@ -389,7 +391,7 @@ public void sort(AI ai, int comparator) throws LeekRunException { } // Trie de la liste if (comparator == RANDOM) - Collections.shuffle(liste); + Collections.shuffle(liste, new Random(LeekScript.getRandom().getInt(0, Integer.MAX_VALUE))); else if (comparator == ASC_K || comparator == DESC_K) { Collections.sort(liste, new KeyComparator( (comparator == ASC_K) ? ElementComparator.SORT_ASC From ddf4b8950a1ef024fb1abf99860f20c87cd3f7ce Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 27 Feb 2021 19:20:43 +0100 Subject: [PATCH 066/319] [ternary] Add one operation --- .../java/leekscript/compiler/expression/LeekTernaire.java | 6 +++--- .../java/leekscript/runner/values/AbstractLeekValue.java | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekTernaire.java b/src/main/java/leekscript/compiler/expression/LeekTernaire.java index 29a05991..8682eb30 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTernaire.java +++ b/src/main/java/leekscript/compiler/expression/LeekTernaire.java @@ -73,13 +73,13 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { if(mCondition instanceof LeekExpression) mCondition = ((LeekExpression) mCondition).getAbstractExpression(); if(mExpression1 instanceof LeekExpression) mExpression1 = ((LeekExpression) mExpression1).getAbstractExpression(); if(mExpression2 instanceof LeekExpression) mExpression2 = ((LeekExpression) mExpression2).getAbstractExpression(); - if(!complete()) writer.addCode("/* " + getString() + " */"); + if (!complete()) writer.addCode("/* " + getString() + " */"); else{ writer.addCode("("); mCondition.writeJavaCode(mainblock, writer); - writer.addCode(".getBoolean()?("); + writer.addCode(".getBooleanTernary(mUAI) ? ("); mExpression1.writeJavaCode(mainblock, writer); - writer.addCode("):("); + writer.addCode(") : ("); mExpression2.writeJavaCode(mainblock, writer); writer.addCode("))"); } diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index cd6abb6d..2866cc71 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -41,6 +41,11 @@ public boolean getBoolean() { return false; } + public boolean getBooleanTernary(AI ai) throws LeekRunException { + ai.addOperations(1); + return getBoolean(); + } + public boolean isNumeric() { return false; } From 35d83178584db8827397542d6c76e6fef1010a58 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 27 Feb 2021 19:21:06 +0100 Subject: [PATCH 067/319] [array] Fix exception when growing capacity --- src/main/java/leekscript/runner/PhpArray.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 3fe3fd29..6d31838b 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -230,16 +230,16 @@ private void growCapacity(AI ai) throws Exception { if (capacity == MAX_CAPACITY) return; - capacity = Math.min(capacity * 2, MAX_CAPACITY); - // Copy in a new array - PhpArray newArray = new PhpArray(ai, capacity); + int new_capacity = Math.min(capacity * 2, MAX_CAPACITY); + PhpArray newArray = new PhpArray(ai, new_capacity); Element e = mHead; while (e != null) { newArray.set(ai, e.key, e.value.getValue()); e = e.next; } // Use the table of this new array + capacity = new_capacity; mTable = newArray.mTable; mHead = newArray.mHead; mEnd = newArray.mEnd; From 01cff1b373003968f73b7813f33b79f9b0d25492 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 6 Feb 2021 13:46:26 +0100 Subject: [PATCH 068/319] [exception] Fix exceptions and use var args for functions arguments --- .../compiler/bloc/AnonymousFunctionBlock.java | 2 +- .../compiler/bloc/FunctionBlock.java | 2 +- .../compiler/bloc/MainLeekBlock.java | 8 +- src/main/java/leekscript/runner/AI.java | 22 +- .../java/leekscript/runner/ILeekFunction.java | 4 +- .../runner/LeekAnonymousFunction.java | 2 +- .../java/leekscript/runner/LeekFunctions.java | 242 +++++++++--------- .../leekscript/runner/LeekOperations.java | 64 ++--- .../leekscript/runner/LeekValueManager.java | 4 +- src/main/java/leekscript/runner/PhpArray.java | 30 +-- .../runner/values/AbstractLeekValue.java | 52 ++-- .../runner/values/ArrayLeekValue.java | 36 +-- .../runner/values/BooleanLeekValue.java | 8 +- .../runner/values/FunctionLeekValue.java | 7 +- .../runner/values/IntLeekValue.java | 2 +- .../runner/values/NullLeekValue.java | 9 +- .../values/PhpArrayVariableLeekValue.java | 4 +- .../runner/values/ReferenceLeekValue.java | 42 +-- .../runner/values/VariableLeekValue.java | 46 ++-- src/test/java/test/TestAI.java | 4 +- 20 files changed, 287 insertions(+), 303 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java index 0166ec91..f5c8a59a 100644 --- a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java @@ -63,7 +63,7 @@ public void checkEndBlock() { public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { StringBuilder sb = new StringBuilder(); sb.append("new LeekAnonymousFunction() {"); - sb.append("public AbstractLeekValue run(AI mUAI, AbstractLeekValue[] values) throws Exception {"); + sb.append("public AbstractLeekValue run(AI mUAI, AbstractLeekValue... values) throws LeekRunException {"); for (int i = 0; i < mParameters.size(); i++) { sb.append("final VariableLeekValue user_").append(mParameters.get(i)).append(" = "); diff --git a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java index c0eab628..c71b3d38 100644 --- a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java @@ -82,7 +82,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { sb.append(", "); sb.append("AbstractLeekValue param_").append(mParameters.get(i)); } - sb.append(") throws Exception{"); + sb.append(") throws LeekRunException {"); for (int i = 0; i < mParameters.size(); i++) { sb.append("final VariableLeekValue user_").append(mParameters.get(i)).append(" = "); if (mReferences.get(i)) { diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 83c45858..98efd8bf 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -172,7 +172,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { writer.addLine("import leekscript.runner.*;"); writer.addLine("import leekscript.runner.values.*;"); writer.addLine("public class " + className + " extends " + AIClass + " {"); - writer.addLine("public " + className + "() throws Exception {"); + writer.addLine("public " + className + "() throws LeekRunException {"); writer.addLine("super();"); writer.addLine("mInstructions = " + mInstructions.size() + ";"); writer.addLine("}"); @@ -194,7 +194,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { * for(LeekInstruction instruction : mAnonymousFunctions){ * instruction.writeJavaCode(this, writer); } */ - writer.addLine("public AbstractLeekValue runIA() throws Exception{ resetCounter();"); + writer.addLine("public AbstractLeekValue runIA() throws LeekRunException { resetCounter();"); super.writeJavaCode(this, writer); if (mEndInstruction == 0) writer.addLine("return LeekValueManager.NULL;"); @@ -204,7 +204,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { printFunctionInformations(writer); if (mRedefinedFunctions.size() > 0) { - writer.addCode("protected void init() throws Exception {\n"); + writer.addCode("protected void init() throws LeekRunException {\n"); for (String redefined : mRedefinedFunctions) { FunctionBlock user_function = getUserFunction(redefined); writer.addCode("rfunction_"); @@ -243,7 +243,7 @@ public void printFunctionInformations(JavaWriter writer) { } writer.addLine("} return null; }"); // Execute - writer.addLine("public AbstractLeekValue userFunctionExecute(int id, AbstractLeekValue[] value) throws Exception{"); + writer.addLine("public AbstractLeekValue userFunctionExecute(int id, AbstractLeekValue[] value) throws LeekRunException {"); writer.addLine("switch(id){"); for (FunctionBlock f : mFunctions) { String params = ""; diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 09ea0566..ded47cda 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -82,7 +82,7 @@ public void resetCounter() { mOperations = 0; } - protected NullLeekValue nothing(AbstractLeekValue obj) throws Exception { + protected NullLeekValue nothing(AbstractLeekValue obj) throws LeekRunException { return LeekValueManager.NULL; } @@ -149,7 +149,7 @@ public int typeOf(AbstractLeekValue value) { return 0; } - public void arrayFlatten(ArrayLeekValue array, ArrayLeekValue retour, int depth) throws Exception { + public void arrayFlatten(ArrayLeekValue array, ArrayLeekValue retour, int depth) throws LeekRunException { for (AbstractLeekValue value : array) { if (value.getValue() instanceof ArrayLeekValue && depth > 0) { arrayFlatten(value.getArray(), retour, depth - 1); @@ -158,7 +158,7 @@ public void arrayFlatten(ArrayLeekValue array, ArrayLeekValue retour, int depth) } } - public AbstractLeekValue arrayFoldLeft(ArrayLeekValue array, AbstractLeekValue function, AbstractLeekValue start_value) throws Exception { + public AbstractLeekValue arrayFoldLeft(ArrayLeekValue array, AbstractLeekValue function, AbstractLeekValue start_value) throws LeekRunException { AbstractLeekValue result = LeekOperations.clone(this, start_value); // AbstractLeekValue prev = null; for (AbstractLeekValue value : array) { @@ -167,7 +167,7 @@ public AbstractLeekValue arrayFoldLeft(ArrayLeekValue array, AbstractLeekValue f return result; } - public AbstractLeekValue arrayFoldRight(ArrayLeekValue array, AbstractLeekValue function, AbstractLeekValue start_value) throws Exception { + public AbstractLeekValue arrayFoldRight(ArrayLeekValue array, AbstractLeekValue function, AbstractLeekValue start_value) throws LeekRunException { AbstractLeekValue result = LeekOperations.clone(this, start_value); // AbstractLeekValue prev = null; Iterator it = array.getReversedIterator(); @@ -177,7 +177,7 @@ public AbstractLeekValue arrayFoldRight(ArrayLeekValue array, AbstractLeekValue return result; } - public AbstractLeekValue arrayPartition(ArrayLeekValue array, AbstractLeekValue function) throws Exception { + public AbstractLeekValue arrayPartition(ArrayLeekValue array, AbstractLeekValue function) throws LeekRunException { ArrayLeekValue list1 = new ArrayLeekValue(); ArrayLeekValue list2 = new ArrayLeekValue(); int nb = function.getArgumentsCount(this); @@ -199,7 +199,7 @@ public AbstractLeekValue arrayPartition(ArrayLeekValue array, AbstractLeekValue return new ArrayLeekValue(this, new AbstractLeekValue[] { list1, list2 }, false); } - public ArrayLeekValue arrayMap(ArrayLeekValue array, AbstractLeekValue function) throws LeekRunException, Exception { + public ArrayLeekValue arrayMap(ArrayLeekValue array, AbstractLeekValue function) throws LeekRunException { ArrayLeekValue retour = new ArrayLeekValue(); ArrayIterator iterator = array.getArrayIterator(); int nb = function.getArgumentsCount(this); @@ -218,7 +218,7 @@ public ArrayLeekValue arrayMap(ArrayLeekValue array, AbstractLeekValue function) return retour; } - public ArrayLeekValue arrayFilter(ArrayLeekValue array, AbstractLeekValue function) throws LeekRunException, Exception { + public ArrayLeekValue arrayFilter(ArrayLeekValue array, AbstractLeekValue function) throws LeekRunException { ArrayLeekValue retour = new ArrayLeekValue(); ArrayIterator iterator = array.getArrayIterator(); int nb = function.getArgumentsCount(this); @@ -246,7 +246,7 @@ public ArrayLeekValue arrayFilter(ArrayLeekValue array, AbstractLeekValue functi return retour; } - public AbstractLeekValue arrayIter(ArrayLeekValue array, AbstractLeekValue function) throws LeekRunException, Exception { + public AbstractLeekValue arrayIter(ArrayLeekValue array, AbstractLeekValue function) throws LeekRunException { ArrayIterator iterator = array.getArrayIterator(); int nb = function.getArgumentsCount(this); if (nb != 1 && nb != 2) @@ -264,7 +264,7 @@ public AbstractLeekValue arrayIter(ArrayLeekValue array, AbstractLeekValue funct return LeekValueManager.NULL; } - public AbstractLeekValue arraySort(ArrayLeekValue origin, final AbstractLeekValue function) throws Exception { + public AbstractLeekValue arraySort(ArrayLeekValue origin, final AbstractLeekValue function) throws LeekRunException { try { int nb = function.getArgumentsCount(this); if (nb == 2) { @@ -363,13 +363,13 @@ else if (type == AILog.STANDARD) protected abstract String getAItring(); - public abstract AbstractLeekValue runIA() throws Exception; + public abstract AbstractLeekValue runIA() throws LeekRunException; public abstract int userFunctionCount(int id); public abstract boolean[] userFunctionReference(int id); - public abstract AbstractLeekValue userFunctionExecute(int id, AbstractLeekValue[] value) throws Exception; + public abstract AbstractLeekValue userFunctionExecute(int id, AbstractLeekValue[] value) throws LeekRunException; public abstract int anonymousFunctionCount(int id); diff --git a/src/main/java/leekscript/runner/ILeekFunction.java b/src/main/java/leekscript/runner/ILeekFunction.java index 86979fe9..a92ac29a 100644 --- a/src/main/java/leekscript/runner/ILeekFunction.java +++ b/src/main/java/leekscript/runner/ILeekFunction.java @@ -9,6 +9,6 @@ public interface ILeekFunction { abstract public boolean isExtra(); abstract public String getNamespace(); abstract public int[] parameters(); - abstract public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception; - abstract public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception; + abstract public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException; + abstract public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException; } diff --git a/src/main/java/leekscript/runner/LeekAnonymousFunction.java b/src/main/java/leekscript/runner/LeekAnonymousFunction.java index 92fa23fc..da1ddd91 100644 --- a/src/main/java/leekscript/runner/LeekAnonymousFunction.java +++ b/src/main/java/leekscript/runner/LeekAnonymousFunction.java @@ -4,5 +4,5 @@ public interface LeekAnonymousFunction { - public AbstractLeekValue run(AI ai, AbstractLeekValue[] values) throws Exception; + public AbstractLeekValue run(AI ai, AbstractLeekValue... values) throws LeekRunException; } diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index c08b82be..7226272e 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -18,7 +18,7 @@ public enum LeekFunctions implements ILeekFunction { // Fonctions mathématiques abs(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekDoubleValue(Math.abs(parameters[0].getDouble(leekIA))); } @@ -29,7 +29,7 @@ public int[] parameters() { }, min(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekDoubleValue(Math.min(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); } @@ -40,7 +40,7 @@ public int[] parameters() { }, max(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekDoubleValue(Math.max(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); } @@ -51,7 +51,7 @@ public int[] parameters() { }, cos(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(Math.cos(parameters[0].getDouble(leekIA))); } @@ -62,7 +62,7 @@ public int[] parameters() { }, sin(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(Math.sin(parameters[0].getDouble(leekIA))); } @@ -73,7 +73,7 @@ public int[] parameters() { }, tan(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(Math.tan(parameters[0].getDouble(leekIA))); } @@ -84,7 +84,7 @@ public int[] parameters() { }, toRadians(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(parameters[0].getDouble(leekIA) * Math.PI / 180); } @@ -95,7 +95,7 @@ public int[] parameters() { }, toDegrees(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(parameters[0].getDouble(leekIA) * 180 / Math.PI); } @@ -106,7 +106,7 @@ public int[] parameters() { }, acos(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(Math.acos(parameters[0].getDouble(leekIA))); } @@ -117,7 +117,7 @@ public int[] parameters() { }, asin(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(Math.asin(parameters[0].getDouble(leekIA))); } @@ -128,7 +128,7 @@ public int[] parameters() { }, atan(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(Math.atan(parameters[0].getDouble(leekIA))); } @@ -139,7 +139,7 @@ public int[] parameters() { }, atan2(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(Math.atan2(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); } @@ -150,7 +150,7 @@ public int[] parameters() { }, ceil(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekIntValue((int) Math.ceil(parameters[0].getDouble(leekIA))); } @@ -161,7 +161,7 @@ public int[] parameters() { }, floor(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekIntValue((int) Math.floor(parameters[0].getDouble(leekIA))); } @@ -172,7 +172,7 @@ public int[] parameters() { }, round(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekIntValue((int) Math.round(parameters[0].getDouble(leekIA))); } @@ -183,7 +183,7 @@ public int[] parameters() { }, sqrt(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekDoubleValue(Math.sqrt(parameters[0].getDouble(leekIA))); } @@ -194,7 +194,7 @@ public int[] parameters() { }, cbrt(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(Math.cbrt(parameters[0].getDouble(leekIA))); } @@ -205,7 +205,7 @@ public int[] parameters() { }, log(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(Math.log(parameters[0].getDouble(leekIA))); } @@ -216,7 +216,7 @@ public int[] parameters() { }, log10(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(Math.log10(parameters[0].getDouble(leekIA))); } @@ -227,7 +227,7 @@ public int[] parameters() { }, exp(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(Math.exp(parameters[0].getDouble(leekIA))); } @@ -238,7 +238,7 @@ public int[] parameters() { }, pow(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekDoubleValue(Math.pow(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); } @@ -249,13 +249,13 @@ public int[] parameters() { }, rand(0) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(leekIA.getRandom().getDouble()); } }, randInt(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { int nb = parameters[0].getInt(leekIA); int nb1 = parameters[1].getInt(leekIA); if (nb > nb1) @@ -271,7 +271,7 @@ public int[] parameters() { }, randFloat(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(parameters[0].getDouble(leekIA) + leekIA.getRandom().getDouble() * (parameters[1].getDouble(leekIA) - parameters[0].getDouble(leekIA))); } @@ -282,7 +282,7 @@ public int[] parameters() { }, hypot(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new DoubleLeekValue(Math.hypot(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); } @@ -293,7 +293,7 @@ public int[] parameters() { }, signum(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekIntValue((int) Math.signum(parameters[0].getDouble(leekIA))); } @@ -304,7 +304,7 @@ public int[] parameters() { }, string(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new StringLeekValue(parameters[0].getString(leekIA)); } }, @@ -312,7 +312,7 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu charAt(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { int pos = parameters[1].getInt(leekIA); String str = parameters[0].getString(leekIA); if (pos < 0 || pos >= str.length()) @@ -327,7 +327,7 @@ public int[] parameters() { }, length(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekIntValue(parameters[0].getString(leekIA).length()); } @@ -338,7 +338,7 @@ public int[] parameters() { }, substring(2, 3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { if (verifyParameters(new int[] { STRING, NUMBER, NUMBER }, parameters)) { String string = parameters[0].getString(leekIA); int index = parameters[1].getInt(leekIA); @@ -363,14 +363,14 @@ public int[] parameters() { return new int[] { STRING, NUMBER, -1 }; } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations( retour.getString(leekIA).length()) : 1); } }, replace(3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new StringLeekValue(parameters[0].getString(leekIA) .replaceAll(Pattern.quote(parameters[1] .getString(leekIA)), @@ -383,7 +383,7 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations( parameters[0].getString(leekIA).length()) : 1); @@ -392,7 +392,7 @@ public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue p indexOf(2, 3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { if (verifyParameters(new int[] { STRING, STRING, NUMBER }, parameters)) { return LeekValueManager.getLeekIntValue(parameters[0].getString(leekIA) .indexOf(parameters[1].getString(leekIA), parameters[2].getInt(leekIA))); @@ -408,13 +408,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations((parameters[0].getString(leekIA).length())) : 1); } }, split(2, 3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { if (verifyParameters(new int[] { STRING, STRING, NUMBER }, parameters)) { String[] elements = parameters[0].getString(leekIA) .split(parameters[1].getString(leekIA), parameters[2].getInt(leekIA)); @@ -438,7 +438,7 @@ public int[] parameters() { return new int[] { STRING, STRING, -1 }; } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations( hasVariableOperations() ? mVariableOperations.getOperations( @@ -451,7 +451,7 @@ public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue p }, toLower(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new StringLeekValue(parameters[0].getString(leekIA).toLowerCase()); } @@ -461,14 +461,14 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(retour.getString(leekIA).length()) : 1); } }, toUpper(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new StringLeekValue(parameters[0].getString(leekIA).toUpperCase()); } @@ -478,14 +478,14 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(retour.getString(leekIA).length()) : 1); } }, startsWith(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekBooleanValue( parameters[0].getString(leekIA) .startsWith(parameters[1].getString(leekIA))); @@ -497,7 +497,7 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { if (parameters[0].getString(leekIA).length() > parameters[1].getString(leekIA).length()) { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations((parameters[1].getString(leekIA).length())) : 1); @@ -507,7 +507,7 @@ public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue p }, endsWith(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekBooleanValue(parameters[0].getString(leekIA) .endsWith(parameters[1].getString(leekIA))); } @@ -518,7 +518,7 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { if (parameters[0].getString(leekIA).length() > parameters[1].getString(leekIA).length()) { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations((parameters[1].getString(leekIA).length())) : 1); @@ -528,7 +528,7 @@ public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue p }, contains(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { String haystack = parameters[0].getString(leekIA); String needle = parameters[1].getString(leekIA); if (needle.length() > haystack.length()) { @@ -541,7 +541,7 @@ public int[] parameters() { return new int[] { STRING, STRING }; } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations( (int) (parameters[0].getString(leekIA).length() @@ -550,7 +550,7 @@ public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue p }, number(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { if (parameters[0].getType() == AbstractLeekValue.NUMBER) return LeekOperations.clone(leekIA, parameters[0].getValue()); if (parameters[0].getType() != AbstractLeekValue.STRING) @@ -574,7 +574,7 @@ public int[] parameters() { // Fonctions array remove(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return parameters[0].getArray().remove(leekIA, parameters[1].getInt(leekIA)); } @@ -584,7 +584,7 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { if (parameters[1].getInt(leekIA) >= 0 && parameters[1].getInt(leekIA) < parameters[0].getArray().size()) { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[1].getInt(leekIA) + 1) : 1); } else @@ -593,7 +593,7 @@ public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue p }, count(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekIntValue(parameters[0].getArray().size()); } @@ -604,7 +604,7 @@ public int[] parameters() { }, join(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new StringLeekValue(parameters[0].getArray().join(leekIA, parameters[1].getString(leekIA))); } @@ -614,13 +614,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(retour.getString(leekIA).length() + 1) : 1); } }, insert(3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { parameters[0].getArray().insert(leekIA, LeekOperations.clone(leekIA, parameters[1]), parameters[2].getInt(leekIA)); return LeekValueManager.NULL; } @@ -631,13 +631,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(1 + (parameters[0].getArray().size() - parameters[2].getInt(leekIA)) * 4); } }, push(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { parameters[0].getArray().push(leekIA, LeekOperations.clone(leekIA, parameters[1])); return LeekValueManager.NULL; } @@ -649,7 +649,7 @@ public int[] parameters() { }, unshift(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { parameters[0].getArray().insert(leekIA, LeekOperations.clone(leekIA, parameters[1]), 0); return LeekValueManager.NULL; } @@ -661,7 +661,7 @@ public int[] parameters() { }, shift(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { if (parameters[0].getArray().size() > 0) { AbstractLeekValue v = parameters[0].getArray().start().getValue(); parameters[0].getArray().remove(leekIA, 0); @@ -677,7 +677,7 @@ public int[] parameters() { }, pop(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { if (parameters[0].getArray().size() > 0) { AbstractLeekValue v = parameters[0].getArray().end().getValue(); parameters[0].getArray().remove(leekIA, parameters[0].getArray().size() - 1); @@ -693,7 +693,7 @@ public int[] parameters() { }, removeElement(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { parameters[0].getArray().removeObject(leekIA, parameters[1]); return LeekValueManager.NULL; } @@ -704,14 +704,14 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, removeByKey(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { parameters[0].getArray().removeByKey(leekIA, parameters[1]); return LeekValueManager.NULL; } @@ -723,7 +723,7 @@ public int[] parameters() { }, removeKey(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { parameters[0].getArray().removeByKey(leekIA, parameters[1]); return LeekValueManager.NULL; } @@ -735,7 +735,7 @@ public int[] parameters() { }, sort(1, 2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { int type = LeekValueComparator.SortComparator.SORT_ASC; if (parameters[1].getBoolean()) type = LeekValueComparator.SortComparator.SORT_DESC; @@ -749,13 +749,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, assocSort(1, 2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { int type = PhpArray.ASC_A; if (parameters[1].getBoolean()) type = PhpArray.DESC_A; @@ -769,13 +769,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, keySort(1, 2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { int type = PhpArray.ASC_K; if (parameters[1].getBoolean()) @@ -790,13 +790,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, shuffle(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { parameters[0].getArray().shuffle(leekIA); return LeekValueManager.NULL; } @@ -807,13 +807,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, search(2, 3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { if (verifyParameters(new int[] { ARRAY, -1, NUMBER }, parameters)) { return parameters[0].getArray().search(leekIA, parameters[1], parameters[2].getInt(leekIA)); } else { @@ -827,13 +827,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, inArray(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekBooleanValue(parameters[0].getArray().contains(leekIA, parameters[1])); } @@ -843,13 +843,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, reverse(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { parameters[0].getArray().reverse(leekIA); return LeekValueManager.NULL; } @@ -860,13 +860,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, arrayMin(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { AbstractLeekValue max_c = null; LeekValueComparator.SortComparator comp = new LeekValueComparator.SortComparator(leekIA, LeekValueComparator.SortComparator.SORT_ASC); for (AbstractLeekValue val : parameters[0].getArray()) { @@ -888,7 +888,7 @@ public int[] parameters() { }, arrayMax(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { AbstractLeekValue min_c = null; LeekValueComparator.SortComparator mincomp = new LeekValueComparator.SortComparator(leekIA, LeekValueComparator.SortComparator.SORT_ASC); for (AbstractLeekValue val : parameters[0].getArray()) { @@ -909,13 +909,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, sum(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { double somme = 0; for (AbstractLeekValue val : parameters[0].getArray()) { somme += val.getDouble(leekIA); @@ -929,13 +929,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, average(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { double average = 0; for (AbstractLeekValue val : parameters[0].getArray()) { average += val.getDouble(leekIA); @@ -951,13 +951,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, fill(2, 3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { ArrayLeekValue array = parameters[0].getArray(); int size = array.size(); if (isType(parameters[2], NUMBER)) @@ -976,11 +976,11 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception {} + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException {} }, isEmpty(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekBooleanValue(parameters[0].getArray().size() == 0); } @@ -991,7 +991,7 @@ public int[] parameters() { }, subArray(3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { ArrayLeekValue array = parameters[0].getArray(); int start = parameters[1].getInt(leekIA); int end = parameters[2].getInt(leekIA); @@ -1015,11 +1015,11 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception {} + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException {} }, pushAll(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { ArrayLeekValue array = parameters[0].getArray(); ArrayLeekValue source = LeekOperations.clone(leekIA, parameters[1]).getArray(); for (AbstractLeekValue value : source) { @@ -1035,11 +1035,11 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception {} + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException {} }, assocReverse(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { parameters[0].getArray().assocReverse(); return LeekValueManager.NULL; } @@ -1050,13 +1050,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, arrayMap(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return leekIA.arrayMap(parameters[0].getArray(), parameters[1]); } @@ -1067,7 +1067,7 @@ public int[] parameters() { }, arrayFilter(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return leekIA.arrayFilter(parameters[0].getArray(), parameters[1]); } @@ -1078,7 +1078,7 @@ public int[] parameters() { }, arrayFlatten(1, 2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { int maxDepth = isType(parameters[1], NUMBER) ? parameters[1].getInt(leekIA) : 1; ArrayLeekValue retour = new ArrayLeekValue(); leekIA.arrayFlatten(parameters[0].getArray(), retour, maxDepth); @@ -1091,13 +1091,13 @@ public int[] parameters() { } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(retour.getArray().size() + 1) : 1); } }, arrayFoldLeft(2, 3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return leekIA.arrayFoldLeft(parameters[0].getArray(), parameters[1], parameters[2]); } @@ -1108,7 +1108,7 @@ public int[] parameters() { }, arrayFoldRight(2, 3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return leekIA.arrayFoldRight(parameters[0].getArray(), parameters[1], parameters[2]); } @@ -1119,7 +1119,7 @@ public int[] parameters() { }, arrayPartition(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return leekIA.arrayPartition(parameters[0].getArray(), parameters[1]); } @@ -1130,7 +1130,7 @@ public int[] parameters() { }, arrayIter(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return leekIA.arrayIter(parameters[0].getArray(), parameters[1]); } @@ -1141,7 +1141,7 @@ public int[] parameters() { }, arrayConcat(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekOperations.add(leekIA, parameters[0], parameters[1]); } @@ -1152,7 +1152,7 @@ public int[] parameters() { }, arraySort(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return leekIA.arraySort(parameters[0].getArray(), parameters[1]); } @@ -1163,7 +1163,7 @@ public int[] parameters() { }, debug(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { String p = parameters[0].getString(leekIA); leekIA.getLogs().addLog(AILog.STANDARD, p); leekIA.addOperations(p.length()); @@ -1172,7 +1172,7 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu }, debugW(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { String p = parameters[0].getString(leekIA); leekIA.getLogs().addLog(AILog.WARNING, p); leekIA.addOperations(p.length()); @@ -1181,7 +1181,7 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu }, debugE(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { String p = parameters[0].getString(leekIA); leekIA.getLogs().addLog(AILog.ERROR, p); leekIA.addOperations(p.length()); @@ -1190,7 +1190,7 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu }, debugC(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { String message = parameters[0].getString(leekIA); int color = parameters[1].getInt(leekIA); leekIA.getLogs().addLog(AILog.STANDARD, message, color); @@ -1200,13 +1200,13 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu }, jsonEncode(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return leekIA.jsonEncode(leekIA, parameters[0]); } }, jsonDecode(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return leekIA.jsonDecode(parameters[0].getString(leekIA)); } @@ -1217,13 +1217,13 @@ public int[] parameters() { }, getInstructionsCount(0) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekIntValue(0); } }, color(3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { leekIA.addOperations(AI.ERROR_LOG_COST); leekIA.addSystemLog(AILog.WARNING, AILog.DEPRECATED_FUNCTION, new String[] { "color", "getColor" }); return leekIA.color(parameters[0], parameters[1], parameters[2]); @@ -1231,13 +1231,13 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu }, getColor(3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return leekIA.color(parameters[0], parameters[1], parameters[2]); } }, getRed(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekIntValue(((parameters[0].getInt(leekIA)) >> 16) & 255); } @@ -1248,7 +1248,7 @@ public int[] parameters() { }, getGreen(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekIntValue(((parameters[0].getInt(leekIA)) >> 8) & 255); } @@ -1259,7 +1259,7 @@ public int[] parameters() { }, getBlue(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekIntValue(parameters[0].getInt(leekIA) & 255); } @@ -1271,13 +1271,13 @@ public int[] parameters() { typeOf(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekIntValue(leekIA.typeOf(parameters[0])); } }, trim(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return new StringLeekValue(parameters[0].getString(leekIA).trim()); } @@ -1288,7 +1288,7 @@ public int[] parameters() { }, getOperations(0) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws Exception { + public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekIntValue((int) leekIA.getOperations()); } }; @@ -1407,7 +1407,7 @@ public static Object[] getExtraFunctions() { /* * Lancer la fonction */ - public abstract AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue parameters[], int count) throws Exception; + public abstract AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue parameters[], int count) throws LeekRunException; public int[] parameters() { return null; @@ -1421,11 +1421,11 @@ public void setOperations(int operations) { mOperations = operations; } - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws Exception { + public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { leekIA.addOperations(getOperations()); } - public static AbstractLeekValue executeFunction(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], int count) throws Exception { + public static AbstractLeekValue executeFunction(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], int count) throws LeekRunException { // Vérification parametres int[] types = function.parameters(); diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index d91b6357..def84f3d 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -12,8 +12,7 @@ public class LeekOperations { - public static AbstractLeekValue add(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue add(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { v1 = v1.getValue(); v2 = v2.getValue(); @@ -61,7 +60,7 @@ public static AbstractLeekValue add(AI ai, AbstractLeekValue v1, return new StringLeekValue(v1_string + v2_string); } - public static AbstractLeekValue minus(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue minus(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); v1 = v1.getValue(); v2 = v2.getValue(); @@ -74,7 +73,7 @@ public static AbstractLeekValue minus(AI ai, AbstractLeekValue v1, AbstractLeekV throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public static AbstractLeekValue power(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue power(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(AbstractLeekValue.POW_COST); v1 = v1.getValue(); v2 = v2.getValue(); @@ -94,7 +93,7 @@ public static AbstractLeekValue power(AI ai, AbstractLeekValue v1, AbstractLeekV throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public static AbstractLeekValue multiply(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue multiply(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(AbstractLeekValue.MUL_COST); v1 = v1.getValue(); v2 = v2.getValue(); @@ -108,7 +107,7 @@ public static AbstractLeekValue multiply(AI ai, AbstractLeekValue v1, AbstractLe throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(AbstractLeekValue.DIV_COST); @@ -132,7 +131,7 @@ public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeek throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public static AbstractLeekValue modulus(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue modulus(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(AbstractLeekValue.MOD_COST); v1 = v1.getValue(); @@ -151,92 +150,77 @@ public static AbstractLeekValue modulus(AI ai, AbstractLeekValue v1, AbstractLee throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public static AbstractLeekValue and(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue and(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.getBoolean() && v2.getBoolean()); } - public static AbstractLeekValue or(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue or(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.getBoolean() || v2.getBoolean()); } - public static AbstractLeekValue bor(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue bor(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekIntValue(v1.getInt(ai) | v2.getInt(ai)); } - public static AbstractLeekValue band(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue band(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekIntValue(v1.getInt(ai) & v2.getInt(ai)); } - public static AbstractLeekValue bxor(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue bxor(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekIntValue(v1.getInt(ai) ^ v2.getInt(ai)); } - public static AbstractLeekValue bleft(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue bleft(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekIntValue(v1.getInt(ai) << v2.getInt(ai)); } - public static AbstractLeekValue bright(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue bright(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekIntValue(v1.getInt(ai) >> v2.getInt(ai)); } - public static AbstractLeekValue brotate(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue brotate(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekIntValue(v1.getInt(ai) >>> v2.getInt(ai)); } - public static AbstractLeekValue equals(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue equals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.equals(ai, v2)); } - public static AbstractLeekValue notequals(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue notequals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.notequals(ai, v2)); } - public static AbstractLeekValue less(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue less(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.less(ai, v2)); } - public static AbstractLeekValue more(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue more(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.more(ai, v2)); } - public static AbstractLeekValue lessequals(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue lessequals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.lessequals(ai, v2)); } - public static AbstractLeekValue moreequals(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue moreequals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.moreequals(ai, v2)); } - public static AbstractLeekValue clone(AI ai, AbstractLeekValue value) - throws Exception { + public static AbstractLeekValue clone(AI ai, AbstractLeekValue value) throws LeekRunException { value = value.getValue(); ai.addOperations(1); if (value instanceof StringLeekValue) @@ -258,14 +242,12 @@ else if (value instanceof ArrayLeekValue) { return LeekValueManager.NULL; } - public static AbstractLeekValue equals_equals(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue equals_equals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.getType() == v2.getType() && v1.equals(ai, v2)); } - public static AbstractLeekValue notequals_equals(AI ai, AbstractLeekValue v1, - AbstractLeekValue v2) throws Exception { + public static AbstractLeekValue notequals_equals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.getType() != v2.getType() || v1.notequals(ai, v2)); diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index 756342d7..f89a3bcd 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -97,7 +97,7 @@ public static AbstractLeekValue getLeekBooleanValue(boolean b) { return b ? TRUE : FALSE; } - public static AbstractLeekValue parseJSON(Object o, AI ai) throws Exception { + public static AbstractLeekValue parseJSON(Object o, AI ai) throws LeekRunException { if (o instanceof Boolean) { return new BooleanLeekValue((Boolean) o); @@ -109,7 +109,7 @@ public static AbstractLeekValue parseJSON(Object o, AI ai) throws Exception { return new IntLeekValue((Integer) o); } if (o instanceof BigInteger) { - throw new Exception(); + throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } if (o instanceof BigDecimal) { return new DoubleLeekValue(((BigDecimal) o).doubleValue()); diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 6d31838b..9dc72769 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -184,7 +184,7 @@ public AbstractLeekValue value() { return value.getValue(); } - public void setValue(AI ai, AbstractLeekValue v) throws Exception { + public void setValue(AI ai, AbstractLeekValue v) throws LeekRunException { value.set(ai, v.getValue()); } } @@ -209,7 +209,7 @@ public PhpArray(AI ai, int capacity) throws LeekRunException { initTable(ai, capacity); } - public PhpArray(AI ai, PhpArray phpArray) throws Exception { + public PhpArray(AI ai, PhpArray phpArray) throws LeekRunException { if (phpArray.size() > 0) { initTable(ai, phpArray.size()); Element e = phpArray.mHead; @@ -226,7 +226,7 @@ private void initTable(AI ai, int capacity) throws LeekRunException { mTable = new Element[capacity]; } - private void growCapacity(AI ai) throws Exception { + private void growCapacity(AI ai) throws LeekRunException { if (capacity == MAX_CAPACITY) return; @@ -422,9 +422,9 @@ else if (comparator == ASC_K || comparator == DESC_K) { * Trie le tableau * * @param comparator - * @throws Exception + * @throws LeekRunException */ - public void sort(AI ai, Comparator comparator) throws Exception { + public void sort(AI ai, Comparator comparator) throws LeekRunException { if (mSize == 0) return; @@ -548,9 +548,9 @@ public void removeObject(AI ai, AbstractLeekValue value) throws LeekRunException * * @param value * Element à ajouter - * @throws Exception + * @throws LeekRunException */ - public void push(AI ai, AbstractLeekValue value) throws Exception { + public void push(AI ai, AbstractLeekValue value) throws LeekRunException { Integer key = Integer.valueOf(mIndex); Element e = createElement(ai, key, value); pushElement(e); @@ -565,9 +565,9 @@ public void push(AI ai, AbstractLeekValue value) throws Exception { * * @param value * Element à ajouter - * @throws Exception + * @throws LeekRunException */ - public void unshift(AI ai, AbstractLeekValue value) throws Exception { + public void unshift(AI ai, AbstractLeekValue value) throws LeekRunException { Integer key = 0; Element e = createElement(ai, key, value); unshiftElement(e); @@ -585,9 +585,9 @@ public void unshift(AI ai, AbstractLeekValue value) throws Exception { * Clé (Integer, Double ou String) * @param value * Valeur - * @throws Exception + * @throws LeekRunException */ - public void set(AI ai, Object key, AbstractLeekValue value) throws Exception { + public void set(AI ai, Object key, AbstractLeekValue value) throws LeekRunException { Element e = getElement(ai, key); // Si l'élément n'existe pas on le crée @@ -603,7 +603,7 @@ public void set(AI ai, Object key, AbstractLeekValue value) throws Exception { } } - public AbstractLeekValue getOrCreate(AI ai, Object key) throws Exception { + public AbstractLeekValue getOrCreate(AI ai, Object key) throws LeekRunException { Element e = getElement(ai, key); if (e == null) { e = createElement(ai, key, LeekValueManager.NULL); @@ -617,7 +617,7 @@ public AbstractLeekValue getOrCreate(AI ai, Object key) throws Exception { return e.value; } - public void set(int key, AbstractLeekValue value) throws Exception { + public void set(int key, AbstractLeekValue value) throws LeekRunException { set(Integer.valueOf(key), value); } @@ -629,7 +629,7 @@ public AbstractLeekValue start() { return mHead == null ? LeekValueManager.NULL : mHead.value; } - public void insert(AI ai, int position, AbstractLeekValue value) throws Exception { + public void insert(AI ai, int position, AbstractLeekValue value) throws LeekRunException { if (position < 0) { return; } else if (position >= mSize) { @@ -710,7 +710,7 @@ private void pushElement(Element e) {// Ajouter un élément à la fin } } - private Element createElement(AI ai, Object key, AbstractLeekValue value) throws Exception { + private Element createElement(AI ai, Object key, AbstractLeekValue value) throws LeekRunException { // On crée l'élément Element e = new Element(); e.hash = key.hashCode(); diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 2866cc71..8fc2a711 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -62,15 +62,15 @@ public ArrayLeekValue getArray() { return null; } - public AbstractLeekValue get(AI ai, int value) throws LeekRunException, Exception { + public AbstractLeekValue get(AI ai, int value) throws LeekRunException { return LeekValueManager.NULL; } - public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunException { return LeekValueManager.NULL; } - public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws LeekRunException { return LeekValueManager.NULL; } @@ -82,22 +82,22 @@ public AbstractLeekValue not(AI ai) { return LeekValueManager.getLeekBooleanValue(!getBoolean()); } - public AbstractLeekValue bnot(AI ai) throws Exception { + public AbstractLeekValue bnot(AI ai) throws LeekRunException { return LeekValueManager.getLeekIntValue(~getInt(ai)); } - public AbstractLeekValue opposite(AI ai) throws Exception { + public AbstractLeekValue opposite(AI ai) throws LeekRunException { return LeekValueManager.getLeekIntValue(-getInt(ai)); } - public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunException, Exception { + public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunException { return this; } - public AbstractLeekValue setRef(AI ai, AbstractLeekValue value) throws LeekRunException, Exception { + public AbstractLeekValue setRef(AI ai, AbstractLeekValue value) throws LeekRunException { return this; } - public int getArgumentsCount(AI ai) throws Exception { + public int getArgumentsCount(AI ai) throws LeekRunException { return -1; } @@ -127,67 +127,67 @@ public boolean lessequals(AI ai, AbstractLeekValue comp) throws LeekRunException } // Fonctions pour L-Values - public AbstractLeekValue increment(AI ai) throws Exception { + public AbstractLeekValue increment(AI ai) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue decrement(AI ai) throws Exception { + public AbstractLeekValue decrement(AI ai) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue pre_increment(AI ai) throws Exception { + public AbstractLeekValue pre_increment(AI ai) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue pre_decrement(AI ai) throws Exception { + public AbstractLeekValue pre_decrement(AI ai) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue add(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue add(AI ai, AbstractLeekValue value) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue minus(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue minus(AI ai, AbstractLeekValue value) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue multiply(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue multiply(AI ai, AbstractLeekValue value) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue divide(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue divide(AI ai, AbstractLeekValue value) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue modulus(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue modulus(AI ai, AbstractLeekValue value) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue power(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue power(AI ai, AbstractLeekValue value) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue band(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue band(AI ai, AbstractLeekValue value) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue bor(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue bor(AI ai, AbstractLeekValue value) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue bxor(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue bxor(AI ai, AbstractLeekValue value) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue bleft(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue bleft(AI ai, AbstractLeekValue value) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue bright(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue bright(AI ai, AbstractLeekValue value) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public AbstractLeekValue brotate(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue brotate(AI ai, AbstractLeekValue value) throws LeekRunException { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } @@ -197,9 +197,9 @@ public boolean isReference() { return false; } - public abstract Object toJSON(AI ai) throws Exception; + public abstract Object toJSON(AI ai) throws LeekRunException; - public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue[] value) throws Exception { + public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... value) throws LeekRunException { // On ne peux pas exécuter ce type de variable ai.addOperations(AI.ERROR_LOG_COST); diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index 1cf69ab8..d0cae959 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -34,11 +34,11 @@ public void next() { mElement = mElement.next(); } - public AbstractLeekValue getKey(AI ai) throws Exception { + public AbstractLeekValue getKey(AI ai) throws LeekRunException { return LeekOperations.clone(ai, mElement.key()); } - public AbstractLeekValue getKeyRef() throws Exception { + public AbstractLeekValue getKeyRef() throws LeekRunException { return mElement.key(); } @@ -46,23 +46,23 @@ public Object key() { return mElement.keyObject(); } - public AbstractLeekValue getValue(AI ai) throws Exception { + public AbstractLeekValue getValue(AI ai) throws LeekRunException { return LeekOperations.clone(ai, mElement.value()); } - public AbstractLeekValue getValueRef() throws Exception { + public AbstractLeekValue getValueRef() throws LeekRunException { return mElement.value(); } - public AbstractLeekValue getKeyReference() throws Exception { + public AbstractLeekValue getKeyReference() throws LeekRunException { return mElement.key(); } - public AbstractLeekValue getValueReference() throws Exception { + public AbstractLeekValue getValueReference() throws LeekRunException { return mElement.value(); } - public void setValue(AI ai, VariableLeekValue value) throws Exception { + public void setValue(AI ai, VariableLeekValue value) throws LeekRunException { mElement.setValue(ai, value); } } @@ -71,11 +71,11 @@ public ArrayLeekValue() { mValues = new PhpArray(); } - public ArrayLeekValue(AI ai, AbstractLeekValue values[]) throws Exception { + public ArrayLeekValue(AI ai, AbstractLeekValue values[]) throws LeekRunException { this(ai, values, false); } - public ArrayLeekValue(AI ai, AbstractLeekValue values[], boolean isKeyValue) throws Exception { + public ArrayLeekValue(AI ai, AbstractLeekValue values[], boolean isKeyValue) throws LeekRunException { mValues = new PhpArray(ai, values.length); if (isKeyValue) { int i = 0; @@ -94,7 +94,7 @@ public ArrayLeekValue(AI ai, AbstractLeekValue values[], boolean isKeyValue) thr * public ArrayLeekValue() { mValues = new PhpArray(); } */ - public ArrayLeekValue(AI ai, ArrayLeekValue array) throws Exception { + public ArrayLeekValue(AI ai, ArrayLeekValue array) throws LeekRunException { mValues = new PhpArray(ai, array.mValues); } @@ -103,7 +103,7 @@ public int size() { } @Override - public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunException { Object key; value = value.getValue(); if (value instanceof StringLeekValue) @@ -114,7 +114,7 @@ public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws Exception { } @Override - public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws LeekRunException { Object key; value = value.getValue(); if (value instanceof StringLeekValue) { @@ -126,7 +126,7 @@ public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws Exce } @Override - public AbstractLeekValue get(AI ai, int value) throws Exception { + public AbstractLeekValue get(AI ai, int value) throws LeekRunException { return mValues.getOrCreate(ai, Integer.valueOf(value)); } @@ -171,7 +171,7 @@ public String join(AI ai, String sep) throws LeekRunException { return sb.toString(); } - public void insert(AI ai, AbstractLeekValue value, int pos) throws Exception { + public void insert(AI ai, AbstractLeekValue value, int pos) throws LeekRunException { mValues.insert(ai, pos, value); } @@ -202,7 +202,7 @@ public boolean contains(AI ai, AbstractLeekValue value) throws LeekRunException return mValues.contains(ai, value); } - public void push(AI ai, AbstractLeekValue m) throws Exception { + public void push(AI ai, AbstractLeekValue m) throws LeekRunException { mValues.push(ai, m); } @@ -259,7 +259,7 @@ public int getSize() throws LeekRunException { } @Override - public AbstractLeekValue add(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue add(AI ai, AbstractLeekValue value) throws LeekRunException { value = value.getValue(); if (value instanceof ArrayLeekValue) { // mValues.reindex(ai); @@ -283,7 +283,7 @@ public Iterator getReversedIterator() { return mValues.reversedIterator(); } - public void sort(AI ai, Comparator comparator) throws Exception { + public void sort(AI ai, Comparator comparator) throws LeekRunException { mValues.sort(ai, comparator); } @@ -292,7 +292,7 @@ public void setParent(PhpArrayVariableLeekValue parent) { } @Override - public Object toJSON(AI ai) throws Exception { + public Object toJSON(AI ai) throws LeekRunException { if (mValues.isAssociative()) { JSONObject o = new JSONObject(); diff --git a/src/main/java/leekscript/runner/values/BooleanLeekValue.java b/src/main/java/leekscript/runner/values/BooleanLeekValue.java index a96e2987..d9d0b5a8 100644 --- a/src/main/java/leekscript/runner/values/BooleanLeekValue.java +++ b/src/main/java/leekscript/runner/values/BooleanLeekValue.java @@ -43,22 +43,22 @@ public String getString(AI ai) { } @Override - public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { return LeekOperations.add(ai, this, val); } @Override - public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { return LeekOperations.multiply(ai, this, val); } @Override - public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { return LeekOperations.divide(ai, this, val); } @Override - public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { return LeekOperations.modulus(ai, this, val); } diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index 71780e96..5d3be91d 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -6,6 +6,7 @@ import leekscript.runner.LeekAnonymousFunction; import leekscript.runner.LeekFunctions; import leekscript.runner.LeekOperations; +import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; public class FunctionLeekValue extends AbstractLeekValue { @@ -59,7 +60,7 @@ public int getType() { return AbstractLeekValue.FUNCTION; } - private AbstractLeekValue[] copyValues(AI uai, AbstractLeekValue[] values, boolean[] references) throws Exception { + private AbstractLeekValue[] copyValues(AI uai, AbstractLeekValue[] values, boolean[] references) throws LeekRunException { AbstractLeekValue[] copy = new AbstractLeekValue[values.length]; for (int i = 0; i < values.length; i++) { if (!references[i]) @@ -79,7 +80,7 @@ private AbstractLeekValue[] prepareValues(AbstractLeekValue[] values, int count) } @Override - public int getArgumentsCount(AI ai) throws Exception { + public int getArgumentsCount(AI ai) throws LeekRunException { if (mType == LEEK_FUNCTION) return mFunction.getArguments(); else if (mType == USER_FUNCTION) @@ -90,7 +91,7 @@ else if (mType == ANONYMOUS_FUNCTION) } @Override - public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue[] values) throws Exception { + public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... values) throws LeekRunException { if (mType == LEEK_FUNCTION) { return LeekFunctions.executeFunction(ai, mFunction, prepareValues(values, mFunction.getArguments()), values.length); } diff --git a/src/main/java/leekscript/runner/values/IntLeekValue.java b/src/main/java/leekscript/runner/values/IntLeekValue.java index 98a44a3d..1257e0bb 100644 --- a/src/main/java/leekscript/runner/values/IntLeekValue.java +++ b/src/main/java/leekscript/runner/values/IntLeekValue.java @@ -163,7 +163,7 @@ public AbstractLeekValue brotate(AI ai, AbstractLeekValue value) throws LeekRunE } @Override - public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { ai.addOperations(DIV_COST); return LeekOperations.divide(ai, this, val); } diff --git a/src/main/java/leekscript/runner/values/NullLeekValue.java b/src/main/java/leekscript/runner/values/NullLeekValue.java index ab2ba1a7..a44d222c 100644 --- a/src/main/java/leekscript/runner/values/NullLeekValue.java +++ b/src/main/java/leekscript/runner/values/NullLeekValue.java @@ -2,6 +2,7 @@ import leekscript.runner.AI; import leekscript.runner.LeekOperations; +import leekscript.runner.LeekRunException; public class NullLeekValue extends AbstractLeekValue { @Override @@ -25,22 +26,22 @@ public String getString(AI ai) { } @Override - public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { return LeekOperations.add(ai, this, val); } @Override - public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { return LeekOperations.multiply(ai, this, val); } @Override - public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { return LeekOperations.divide(ai, this, val); } @Override - public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { return LeekOperations.modulus(ai, this, val); } diff --git a/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java b/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java index 78a6c501..cd935b49 100644 --- a/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java @@ -9,7 +9,7 @@ public class PhpArrayVariableLeekValue extends VariableLeekValue { private final PhpArray mArray; private int mTotalSize = 0; - public PhpArrayVariableLeekValue(PhpArray array, AI uai, AbstractLeekValue value, int keySize) throws Exception { + public PhpArrayVariableLeekValue(PhpArray array, AI uai, AbstractLeekValue value, int keySize) throws LeekRunException { super(uai, value.getValue()); mArray = array; mTotalSize = value.getSize(); @@ -20,7 +20,7 @@ public PhpArrayVariableLeekValue(PhpArray array, AI uai, AbstractLeekValue value } @Override - public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunException { value = value.getValue(); int size = value.getSize(); mArray.updateArraySize(size - mTotalSize); diff --git a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java b/src/main/java/leekscript/runner/values/ReferenceLeekValue.java index 442943c5..30a0ef58 100644 --- a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java +++ b/src/main/java/leekscript/runner/values/ReferenceLeekValue.java @@ -8,7 +8,7 @@ public class ReferenceLeekValue extends AbstractLeekValue { private AbstractLeekValue mValue; - public ReferenceLeekValue(AI uai, AbstractLeekValue value) throws Exception { + public ReferenceLeekValue(AI uai, AbstractLeekValue value) throws LeekRunException { if (!(value instanceof ReferenceLeekValue)) mValue = value; else @@ -62,27 +62,27 @@ public AbstractLeekValue getValue() { } @Override - public AbstractLeekValue increment(AI ai) throws Exception { + public AbstractLeekValue increment(AI ai) throws LeekRunException { return mValue.increment(ai); } @Override - public AbstractLeekValue decrement(AI ai) throws Exception { + public AbstractLeekValue decrement(AI ai) throws LeekRunException { return mValue.decrement(ai); } @Override - public AbstractLeekValue pre_increment(AI ai) throws Exception { + public AbstractLeekValue pre_increment(AI ai) throws LeekRunException { return mValue.pre_increment(ai); } @Override - public AbstractLeekValue pre_decrement(AI ai) throws Exception { + public AbstractLeekValue pre_decrement(AI ai) throws LeekRunException { return mValue.pre_decrement(ai); } @Override - public AbstractLeekValue opposite(AI ai) throws Exception { + public AbstractLeekValue opposite(AI ai) throws LeekRunException { return mValue.opposite(ai); } @@ -102,73 +102,73 @@ public boolean more(AI ai, AbstractLeekValue comp) throws LeekRunException { } @Override - public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.add(ai, val); } @Override - public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.minus(ai, val); } @Override - public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.multiply(ai, val); } @Override - public AbstractLeekValue power(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue power(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.power(ai, val); } @Override - public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.band(ai, val); } @Override - public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.bor(ai, val); } @Override - public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.bxor(ai, val); } @Override - public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.bleft(ai, val); } @Override - public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.bright(ai, val); } @Override - public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.brotate(ai, val); } @Override - public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.divide(ai, val); } @Override - public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.modulus(ai, val); } @@ -184,17 +184,17 @@ public boolean isReference() { } @Override - public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue[] values) throws Exception { + public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... values) throws LeekRunException { return mValue.executeFunction(ai, values); } @Override - public int getArgumentsCount(AI ai) throws Exception { + public int getArgumentsCount(AI ai) throws LeekRunException { return mValue.getArgumentsCount(ai); } @Override - public Object toJSON(AI ai) throws Exception { + public Object toJSON(AI ai) throws LeekRunException { return mValue.toJSON(ai); } } diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index 67c8f6ec..34849d2c 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -10,7 +10,7 @@ public class VariableLeekValue extends AbstractLeekValue { protected AbstractLeekValue mValue; protected AI mUAI = null; - public VariableLeekValue(AI uai, AbstractLeekValue value) throws Exception { + public VariableLeekValue(AI uai, AbstractLeekValue value) throws LeekRunException { mUAI = uai; mUAI.addOperations(1); if (!(value instanceof VariableLeekValue)) @@ -70,7 +70,7 @@ public AbstractLeekValue getValue() { } @Override - public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunException { ai.addOperations(1); if (value.isReference()) return mValue = value.getValue(); @@ -79,12 +79,12 @@ public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws Exception { } @Override - public AbstractLeekValue setRef(AI ai, AbstractLeekValue value) throws Exception { + public AbstractLeekValue setRef(AI ai, AbstractLeekValue value) throws LeekRunException { return mValue = value.getValue(); } @Override - public AbstractLeekValue increment(AI ai) throws Exception { + public AbstractLeekValue increment(AI ai) throws LeekRunException { mValue = mValue.getValue(); if (mValue instanceof IntLeekValue) { ai.addOperations(1); @@ -96,7 +96,7 @@ public AbstractLeekValue increment(AI ai) throws Exception { } @Override - public AbstractLeekValue decrement(AI ai) throws Exception { + public AbstractLeekValue decrement(AI ai) throws LeekRunException { mValue = mValue.getValue(); if (mValue instanceof IntLeekValue) { ai.addOperations(1); @@ -108,7 +108,7 @@ public AbstractLeekValue decrement(AI ai) throws Exception { } @Override - public AbstractLeekValue pre_increment(AI ai) throws Exception { + public AbstractLeekValue pre_increment(AI ai) throws LeekRunException { mValue = mValue.getValue(); if (mValue instanceof IntLeekValue) { ai.addOperations(1); @@ -119,7 +119,7 @@ public AbstractLeekValue pre_increment(AI ai) throws Exception { } @Override - public AbstractLeekValue pre_decrement(AI ai) throws Exception { + public AbstractLeekValue pre_decrement(AI ai) throws LeekRunException { mValue = mValue.getValue(); if (mValue instanceof IntLeekValue) { ai.addOperations(1); @@ -130,7 +130,7 @@ public AbstractLeekValue pre_decrement(AI ai) throws Exception { } @Override - public AbstractLeekValue opposite(AI ai) throws Exception { + public AbstractLeekValue opposite(AI ai) throws LeekRunException { return mValue.opposite(ai); } @@ -150,62 +150,62 @@ public boolean more(AI ai, AbstractLeekValue comp) throws LeekRunException { } @Override - public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.add(ai, val); } @Override - public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.minus(ai, val); } @Override - public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.multiply(ai, val); } @Override - public AbstractLeekValue power(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue power(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.power(ai, val); } @Override - public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.band(ai, val); } @Override - public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.bor(ai, val); } @Override - public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.bxor(ai, val); } @Override - public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.bleft(ai, val); } @Override - public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.bright(ai, val); } @Override - public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.brotate(ai, val); } @Override - public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.divide(ai, val); } @Override - public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws Exception { + public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { return mValue = mValue.modulus(ai, val); } @@ -220,17 +220,17 @@ public boolean isReference() { } @Override - public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue[] values) throws Exception { + public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... values) throws LeekRunException { return mValue.executeFunction(ai, values); } @Override - public int getArgumentsCount(AI ai) throws Exception { + public int getArgumentsCount(AI ai) throws LeekRunException { return mValue.getArgumentsCount(ai); } @Override - public Object toJSON(AI ai) throws Exception { + public Object toJSON(AI ai) throws LeekRunException { return mValue.toJSON(ai); } } diff --git a/src/test/java/test/TestAI.java b/src/test/java/test/TestAI.java index 02d67fac..d135a092 100644 --- a/src/test/java/test/TestAI.java +++ b/src/test/java/test/TestAI.java @@ -19,7 +19,7 @@ protected String getAItring() { } @Override - public AbstractLeekValue runIA() throws Exception { + public AbstractLeekValue runIA() throws LeekRunException { return null; } @@ -34,7 +34,7 @@ public boolean[] userFunctionReference(int id) { } @Override - public AbstractLeekValue userFunctionExecute(int id, AbstractLeekValue[] value) throws Exception { + public AbstractLeekValue userFunctionExecute(int id, AbstractLeekValue[] value) throws LeekRunException { return null; } From a6efd761dc66c00874bfc33fc6ae1b7c835a873d Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 13 Feb 2021 11:36:42 +0100 Subject: [PATCH 069/319] [string] Fix \\ escaping in LS 1.1 --- .../compiler/expression/LeekString.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekString.java b/src/main/java/leekscript/compiler/expression/LeekString.java index 4a2d50f8..c62fe133 100644 --- a/src/main/java/leekscript/compiler/expression/LeekString.java +++ b/src/main/java/leekscript/compiler/expression/LeekString.java @@ -31,13 +31,20 @@ public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionExc public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { String str = ""; int len = mString.length() - 1; - for(int i = 0; i < mString.length(); i++){ - if(mString.charAt(i) == '\n') str += "\\n"; - else if(mString.charAt(i) == '"') str += "\\\""; - else if(mString.charAt(i) == '\\'){ - if(len > i && mString.charAt(i + 1) == 'n') str += "\\"; - else if(len > i && mString.charAt(i + 1) == 't') str += "\\"; - else str += "\\\\"; + for (int i = 0; i < mString.length(); i++) { + if (mString.charAt(i) == '\n') str += "\\n"; + else if (mString.charAt(i) == '"') str += "\\\""; + else if (mString.charAt(i) == '\\') { + if (len > i && mString.charAt(i + 1) == 'n') str += "\\"; + else if (len > i && mString.charAt(i + 1) == 't') str += "\\"; + else { + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + str += "\\"; + } else { + // LeekScript 1.0 had a bug with "\\" strings producing 4 \ + str += "\\\\"; + } + } } else str += mString.charAt(i); } From 04c99af00d66bcc65fab12e32d5ddbd76f1f907d Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 13 Feb 2021 11:38:45 +0100 Subject: [PATCH 070/319] [operator] Fix ^= operator in LS 1.1 --- .../java/leekscript/compiler/WordCompiler.java | 4 ++-- .../leekscript/compiler/expression/Operators.java | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index e606c087..b84c4d13 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -666,7 +666,7 @@ public LeekExpression readExpression() throws Exception { retour.addFunction(function); } else if (word.getType() == WordParser.T_OPERATOR) { - int operator = Operators.getOperator(word.getWord()); + int operator = Operators.getOperator(word.getWord(), getVersion()); // Là c'est soit un opérateur (+ - ...) soit un suffix // unaire (++ -- ) sinon on sort de l'expression @@ -785,7 +785,7 @@ else if (LeekConstants.get(word.getWord()) != null) } else if (word.getType() == WordParser.T_OPERATOR) { // Si c'est un opérateur (il doit forcément être unaire et // de type préfix (! )) - int operator = Operators.getOperator(word.getWord()); + int operator = Operators.getOperator(word.getWord(), getVersion()); if (operator == Operators.MINUS) operator = Operators.UNARY_MINUS; else if (operator == Operators.DECREMENT) diff --git a/src/main/java/leekscript/compiler/expression/Operators.java b/src/main/java/leekscript/compiler/expression/Operators.java index 8b6cfae7..8fe53997 100644 --- a/src/main/java/leekscript/compiler/expression/Operators.java +++ b/src/main/java/leekscript/compiler/expression/Operators.java @@ -49,7 +49,7 @@ public class Operators { public final static int REFERENCE = 46; public final static int BITNOT = 47; - public final static int getOperator(String operator) { + public final static int getOperator(String operator, int version) { if(operator.equals("[")) return CROCHET; if(operator.equals("(")) return PARENTHESIS; if(operator.equals("++")) return INCREMENT; @@ -77,18 +77,24 @@ public final static int getOperator(String operator) { if(operator.equals("?")) return TERNAIRE; if(operator.equals(":")) return DOUBLE_POINT; if(operator.equals("**")) return POWER; - if(operator.equals("^=")) return POWERASSIGN; + if(operator.equals("**=")) return POWERASSIGN; if(operator.equals("===")) return EQUALS_EQUALS; if(operator.equals("!==")) return NOT_EQUALS_EQUALS; if(operator.equals("^")) return BITXOR; + if(operator.equals("^=")) { + if (version >= 11) { + return BITXOR_ASSIGN; + } else { + // In LeekScript 1.0, ^= was still power assignment + return POWERASSIGN; + } + } if(operator.equals("&")) return BITAND; if(operator.equals("|")) return BITOR; if(operator.equals("~")) return BITNOT; if(operator.equals("<<")) return SHIFT_LEFT; if(operator.equals(">>")) return SHIFT_RIGHT; if(operator.equals(">>>")) return ROTATE_RIGHT; - if(operator.equals("**=")) return POWERASSIGN; - if(operator.equals("^=")) return BITXOR_ASSIGN; if(operator.equals("&=")) return BITAND_ASSIGN; if(operator.equals("|=")) return BITOR_ASSIGN; if(operator.equals("<<=")) return SHIFT_LEFT_ASSIGN; From 5eb3cd2bb10c2c382bb7c422f75fb6f300949ade Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 13 Feb 2021 11:41:29 +0100 Subject: [PATCH 071/319] [function] Fix arrayFilter in LS 1.1 --- src/main/java/leekscript/runner/AI.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index ded47cda..b9fc3ecf 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -231,15 +231,21 @@ public ArrayLeekValue arrayFilter(ArrayLeekValue array, AbstractLeekValue functi if (nb == 1) { b = function.executeFunction(this, new AbstractLeekValue[] { value }).getBoolean(); iterator.setValue(this, value); - if (b) - retour.getOrCreate(this, iterator.getKey(this).getValue()).set(this, iterator.getValue(this).getValue()); - + if (b) { + if (getVersion() >= 11) + retour.push(this, iterator.getValue(this).getValue()); + else + // In LeekScript < 1.0, arrayFilter had a bug, the result array was not reindexed + retour.getOrCreate(this, iterator.getKey(this).getValue()).set(this, iterator.getValue(this).getValue()); + } } else { b = function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), value }).getBoolean(); iterator.setValue(this, value); if (b) - retour.getOrCreate(this, iterator.getKey(this).getValue()).set(this, iterator.getValue(this).getValue()); - + if (getVersion() >= 11) + retour.push(this, iterator.getValue(this).getValue()); + else + retour.getOrCreate(this, iterator.getKey(this).getValue()).set(this, iterator.getValue(this).getValue()); } iterator.next(); } From a1cf1d223a53861a629bf93992803248e879d0f7 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 14 Feb 2021 15:27:13 +0100 Subject: [PATCH 072/319] [include] Update --- src/main/java/leekscript/compiler/bloc/MainLeekBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 98efd8bf..6a58b013 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -73,7 +73,7 @@ public void setMinLevel(int min_level) { this.mMinLevel = min_level; } - public boolean includeAI(WordCompiler compiler, String path) throws Exception { + public boolean includeAI(WordCompiler compiler, String path) throws LeekCompilerException { try { AIFile ai = LeekScript.getResolver().resolve(path, mCompiler.getCurrentAI().getContext()); if (mIncluded.contains(ai.getId())) { From 5d641e1370dd95af2bfa2f1fd7e75f1f45ef2534 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 14 Feb 2021 20:25:20 +0100 Subject: [PATCH 073/319] [variable] Don't clone values all the time in 1.1, add clone function --- .../compiler/bloc/AnonymousFunctionBlock.java | 2 +- .../compiler/bloc/MainLeekBlock.java | 6 +++- .../runner/LeekAnonymousFunction.java | 2 +- .../java/leekscript/runner/LeekFunctions.java | 17 ++++++++-- .../leekscript/runner/LeekOperations.java | 27 ++++++++++++++-- src/main/java/leekscript/runner/PhpArray.java | 12 +++++-- .../runner/values/ArrayLeekValue.java | 20 ++++++++---- .../runner/values/FunctionLeekValue.java | 23 ++++++++++++-- .../runner/values/ReferenceLeekValue.java | 14 ++++++--- .../runner/values/VariableLeekValue.java | 31 ++++++++++++------- 10 files changed, 118 insertions(+), 36 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java index f5c8a59a..c88db95c 100644 --- a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java @@ -63,7 +63,7 @@ public void checkEndBlock() { public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { StringBuilder sb = new StringBuilder(); sb.append("new LeekAnonymousFunction() {"); - sb.append("public AbstractLeekValue run(AI mUAI, AbstractLeekValue... values) throws LeekRunException {"); + sb.append("public AbstractLeekValue run(AI mUAI, AbstractLeekValue thiz, AbstractLeekValue... values) throws LeekRunException {"); for (int i = 0; i < mParameters.size(); i++) { sb.append("final VariableLeekValue user_").append(mParameters.get(i)).append(" = "); diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 6a58b013..89493c42 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -73,7 +73,7 @@ public void setMinLevel(int min_level) { this.mMinLevel = min_level; } - public boolean includeAI(WordCompiler compiler, String path) throws LeekCompilerException { + public boolean includeAI(WordCompiler compiler, String path) throws Exception { try { AIFile ai = LeekScript.getResolver().resolve(path, mCompiler.getCurrentAI().getContext()); if (mIncluded.contains(ai.getId())) { @@ -300,4 +300,8 @@ public void printFunctionInformations(JavaWriter writer) { public List getIncludedAIs() { return mIncluded; } + + public IACompiler getCompiler() { + return mCompiler; + } } diff --git a/src/main/java/leekscript/runner/LeekAnonymousFunction.java b/src/main/java/leekscript/runner/LeekAnonymousFunction.java index da1ddd91..30f49dea 100644 --- a/src/main/java/leekscript/runner/LeekAnonymousFunction.java +++ b/src/main/java/leekscript/runner/LeekAnonymousFunction.java @@ -4,5 +4,5 @@ public interface LeekAnonymousFunction { - public AbstractLeekValue run(AI ai, AbstractLeekValue... values) throws LeekRunException; + public AbstractLeekValue run(AI ai, AbstractLeekValue thiz, AbstractLeekValue... values) throws LeekRunException; } diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 7226272e..919ac4d4 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -637,8 +637,12 @@ public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue p }, push(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - parameters[0].getArray().push(leekIA, LeekOperations.clone(leekIA, parameters[1])); + public AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { + if (ai.getVersion() >= 11) { + parameters[0].getArray().push(ai, LeekOperations.clonePrimitive(ai, parameters[1])); + } else { + parameters[0].getArray().push(ai, LeekOperations.clone(ai, parameters[1])); + } return LeekValueManager.NULL; } @@ -1291,7 +1295,14 @@ public int[] parameters() { public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { return LeekValueManager.getLeekIntValue((int) leekIA.getOperations()); } - }; + }, + clone(1, 2) { + @Override + public AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { + return LeekOperations.clone(ai, parameters[0], parameters[1].getInt(ai)); + } + } + ; private static String extraFunctions = null; diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index def84f3d..8757fa3f 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -220,7 +220,30 @@ public static AbstractLeekValue moreequals(AI ai, AbstractLeekValue v1, Abstract return LeekValueManager.getLeekBooleanValue(v1.moreequals(ai, v2)); } + public static AbstractLeekValue clonePrimitive(AI ai, AbstractLeekValue value) throws LeekRunException { + AbstractLeekValue v = value.getValue(); + if (v instanceof StringLeekValue) { + ai.addOperations(1); + return new StringLeekValue(v.getString(ai)); + } else if (v instanceof BooleanLeekValue) { + ai.addOperations(1); + return LeekValueManager.getLeekBooleanValue(v.getBoolean()); + } else if (v instanceof IntLeekValue) { + ai.addOperations(1); + return LeekValueManager.getLeekIntValue(v.getInt(ai)); + } else if (v instanceof DoubleLeekValue) { + ai.addOperations(1); + return new DoubleLeekValue(v.getDouble(ai)); + } else { + return value; + } + } + public static AbstractLeekValue clone(AI ai, AbstractLeekValue value) throws LeekRunException { + return clone(ai, value, 1); + } + + public static AbstractLeekValue clone(AI ai, AbstractLeekValue value, int level) throws LeekRunException { value = value.getValue(); ai.addOperations(1); if (value instanceof StringLeekValue) @@ -237,10 +260,10 @@ else if (value instanceof ArrayLeekValue) { if (value.getArray().size() > 0) { ai.addOperations(value.getArray().size() * (ArrayLeekValue.ARRAY_CELL_CREATE_OPERATIONS)); } - return new ArrayLeekValue(ai, value.getArray()); + return new ArrayLeekValue(ai, value.getArray(), level); } else return LeekValueManager.NULL; - } + } public static AbstractLeekValue equals_equals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 9dc72769..d74c675a 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -209,12 +209,20 @@ public PhpArray(AI ai, int capacity) throws LeekRunException { initTable(ai, capacity); } - public PhpArray(AI ai, PhpArray phpArray) throws LeekRunException { + public PhpArray(AI ai, PhpArray phpArray, int level) throws LeekRunException { if (phpArray.size() > 0) { initTable(ai, phpArray.size()); Element e = phpArray.mHead; while (e != null) { - set(ai, e.key, LeekOperations.clone(ai, e.value.getValue())); + if (ai.getVersion() >= 11) { + if (level == 0) { + set(ai, e.key, LeekOperations.clonePrimitive(ai, e.value.getValue())); + } else { + set(ai, e.key, LeekOperations.clone(ai, e.value.getValue(), level - 1)); + } + } else { + set(ai, e.key, LeekOperations.clone(ai, e.value.getValue())); + } e = e.next; } } diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index d0cae959..19ef335a 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -35,7 +35,11 @@ public void next() { } public AbstractLeekValue getKey(AI ai) throws LeekRunException { - return LeekOperations.clone(ai, mElement.key()); + if (ai.getVersion() >= 11) { + return LeekOperations.clonePrimitive(ai, mElement.key()); + } else { + return LeekOperations.clone(ai, mElement.key()); + } } public AbstractLeekValue getKeyRef() throws LeekRunException { @@ -47,7 +51,11 @@ public Object key() { } public AbstractLeekValue getValue(AI ai) throws LeekRunException { - return LeekOperations.clone(ai, mElement.value()); + if (ai.getVersion() >= 11) { + return LeekOperations.clonePrimitive(ai, mElement.value()); + } else { + return LeekOperations.clone(ai, mElement.value()); + } } public AbstractLeekValue getValueRef() throws LeekRunException { @@ -94,10 +102,11 @@ public ArrayLeekValue(AI ai, AbstractLeekValue values[], boolean isKeyValue) thr * public ArrayLeekValue() { mValues = new PhpArray(); } */ - public ArrayLeekValue(AI ai, ArrayLeekValue array) throws LeekRunException { - mValues = new PhpArray(ai, array.mValues); + public ArrayLeekValue(AI ai, ArrayLeekValue array, int level) throws LeekRunException { + mValues = new PhpArray(ai, array.mValues, level); } + public int size() { return mValues.size(); } @@ -234,8 +243,7 @@ public boolean getBoolean() { public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { if (comp.getType() == ARRAY) { return mValues.equals(ai, comp.getArray().mValues); - } else if (mValues.size() == 1) {// Si y'a un seul élément dans le - // tableau + } else if (mValues.size() == 1) { // Si y'a un seul élément dans le tableau return mValues.getHeadElement().value().equals(ai, comp); } else if (comp.getType() == BOOLEAN) { return comp.getBoolean() == getBoolean(); diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index 5d3be91d..f2520acf 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -71,6 +71,14 @@ private AbstractLeekValue[] copyValues(AI uai, AbstractLeekValue[] values, boole return copy; } + private AbstractLeekValue[] copyPrimitiveValues(AI uai, AbstractLeekValue[] values) throws LeekRunException { + AbstractLeekValue[] copy = new AbstractLeekValue[values.length]; + for (int i = 0; i < values.length; i++) { + copy[i] = LeekOperations.clonePrimitive(uai, values[i]); + } + return copy; + } + private AbstractLeekValue[] prepareValues(AbstractLeekValue[] values, int count) { AbstractLeekValue[] retour = new AbstractLeekValue[count]; for (int i = 0; i < count; i++) { @@ -101,8 +109,13 @@ else if (mType == USER_FUNCTION) { ai.addOperations(AI.ERROR_LOG_COST); ai.addSystemLog(AILog.ERROR, AILog.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { AbstractLeekValue.getParamString(values), String.valueOf(ai.userFunctionCount(mId)) }); } - else - return ai.userFunctionExecute(mId, copyValues(ai, values, ai.userFunctionReference(mId))); + else { + if (ai.getVersion() >= 11) { + return ai.userFunctionExecute(mId, copyPrimitiveValues(ai, values)); + } else { + return ai.userFunctionExecute(mId, copyValues(ai, values, ai.userFunctionReference(mId))); + } + } } else if (mType == ANONYMOUS_FUNCTION) { if (values.length != ai.anonymousFunctionCount(mId)) { @@ -112,7 +125,11 @@ else if (mType == ANONYMOUS_FUNCTION) { new String[] { AbstractLeekValue.getParamString(values), String.valueOf(ai.anonymousFunctionCount(mId)) }); } else - return mAnonymous.run(ai, copyValues(ai, values, ai.anonymousFunctionReference(mId))); + if (ai.getVersion() >= 11) { + return mAnonymous.run(ai, null, copyPrimitiveValues(ai, values)); + } else { + return mAnonymous.run(ai, null, copyValues(ai, values, ai.anonymousFunctionReference(mId))); + } } return LeekValueManager.NULL; diff --git a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java b/src/main/java/leekscript/runner/values/ReferenceLeekValue.java index 30a0ef58..d46fa53f 100644 --- a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java +++ b/src/main/java/leekscript/runner/values/ReferenceLeekValue.java @@ -8,11 +8,15 @@ public class ReferenceLeekValue extends AbstractLeekValue { private AbstractLeekValue mValue; - public ReferenceLeekValue(AI uai, AbstractLeekValue value) throws LeekRunException { - if (!(value instanceof ReferenceLeekValue)) - mValue = value; - else - mValue = LeekOperations.clone(uai, value.getValue()); + public ReferenceLeekValue(AI ai, AbstractLeekValue value) throws LeekRunException { + if (ai.getVersion() >= 11) { + mValue = value.getValue(); + } else { + if (!(value instanceof ReferenceLeekValue)) + mValue = value; + else + mValue = LeekOperations.clone(ai, value.getValue()); + } } @Override diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index 34849d2c..d9b99608 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -10,16 +10,19 @@ public class VariableLeekValue extends AbstractLeekValue { protected AbstractLeekValue mValue; protected AI mUAI = null; - public VariableLeekValue(AI uai, AbstractLeekValue value) throws LeekRunException { - mUAI = uai; - mUAI.addOperations(1); - if (!(value instanceof VariableLeekValue)) - mValue = value.getValue(); - else { - if (value.isReference()) + public VariableLeekValue(AI ai, AbstractLeekValue value) throws LeekRunException { + mUAI = ai; + ai.addOperations(1); + if (ai.getVersion() >= 11) { + mValue = LeekOperations.clonePrimitive(ai, value.getValue()); + } else { + if (!(value instanceof VariableLeekValue)) mValue = value.getValue(); else - mValue = LeekOperations.clone(uai, value.getValue()); + if (value.isReference()) + mValue = value.getValue(); + else + mValue = LeekOperations.clone(ai, value.getValue()); } } @@ -72,10 +75,14 @@ public AbstractLeekValue getValue() { @Override public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunException { ai.addOperations(1); - if (value.isReference()) - return mValue = value.getValue(); - else - return mValue = LeekOperations.clone(ai, value.getValue()); + if (ai.getVersion() >= 11) { + return mValue = LeekOperations.clonePrimitive(ai, value.getValue()); + } else { + if (value.isReference()) + return mValue = value.getValue(); + else + return mValue = LeekOperations.clone(ai, value.getValue()); + } } @Override From f6f701ab3a63ec2b39f5f0a2f4be35e9e1466399 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 15 Feb 2021 18:37:24 +0100 Subject: [PATCH 074/319] [value] Add isPrimitive methods --- .../java/leekscript/runner/values/AbstractLeekValue.java | 2 ++ src/main/java/leekscript/runner/values/ArrayLeekValue.java | 5 +++++ src/main/java/leekscript/runner/values/BooleanLeekValue.java | 5 +++++ src/main/java/leekscript/runner/values/DoubleLeekValue.java | 5 +++++ .../java/leekscript/runner/values/FunctionLeekValue.java | 5 +++++ src/main/java/leekscript/runner/values/IntLeekValue.java | 5 +++++ src/main/java/leekscript/runner/values/NullLeekValue.java | 5 +++++ .../java/leekscript/runner/values/ReferenceLeekValue.java | 5 +++++ src/main/java/leekscript/runner/values/StringLeekValue.java | 5 +++++ .../java/leekscript/runner/values/VariableLeekValue.java | 5 +++++ 10 files changed, 47 insertions(+) diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 8fc2a711..642b55ef 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -228,4 +228,6 @@ else if (parameters[j].getValue().getType() == NULL) } return ret; } + + public abstract boolean isPrimitive(); } diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index 19ef335a..c2f39335 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -318,4 +318,9 @@ public Object toJSON(AI ai) throws LeekRunException { return a; } } + + @Override + public boolean isPrimitive() { + return false; + } } diff --git a/src/main/java/leekscript/runner/values/BooleanLeekValue.java b/src/main/java/leekscript/runner/values/BooleanLeekValue.java index d9d0b5a8..462aec04 100644 --- a/src/main/java/leekscript/runner/values/BooleanLeekValue.java +++ b/src/main/java/leekscript/runner/values/BooleanLeekValue.java @@ -80,4 +80,9 @@ else if (comp.getType() == ARRAY) public Object toJSON(AI ai) { return mValue; } + + @Override + public boolean isPrimitive() { + return true; + } } diff --git a/src/main/java/leekscript/runner/values/DoubleLeekValue.java b/src/main/java/leekscript/runner/values/DoubleLeekValue.java index 02baae3b..58445da3 100644 --- a/src/main/java/leekscript/runner/values/DoubleLeekValue.java +++ b/src/main/java/leekscript/runner/values/DoubleLeekValue.java @@ -196,4 +196,9 @@ public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { public Object toJSON(AI ai) { return mValue; } + + @Override + public boolean isPrimitive() { + return true; + } } diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index f2520acf..be8e3d46 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -158,4 +158,9 @@ else if (mType == USER_FUNCTION) public Object toJSON(AI ai) { return ""; } + + @Override + public boolean isPrimitive() { + return false; + } } diff --git a/src/main/java/leekscript/runner/values/IntLeekValue.java b/src/main/java/leekscript/runner/values/IntLeekValue.java index 1257e0bb..ae4563e0 100644 --- a/src/main/java/leekscript/runner/values/IntLeekValue.java +++ b/src/main/java/leekscript/runner/values/IntLeekValue.java @@ -208,4 +208,9 @@ else if (comp.getType() == ARRAY) { public Object toJSON(AI ai) { return mValue; } + + @Override + public boolean isPrimitive() { + return true; + } } diff --git a/src/main/java/leekscript/runner/values/NullLeekValue.java b/src/main/java/leekscript/runner/values/NullLeekValue.java index a44d222c..86429c3f 100644 --- a/src/main/java/leekscript/runner/values/NullLeekValue.java +++ b/src/main/java/leekscript/runner/values/NullLeekValue.java @@ -59,4 +59,9 @@ public boolean equals(AI ai, AbstractLeekValue comp) { public Object toJSON(AI ai) { return null; } + + @Override + public boolean isPrimitive() { + return true; + } } diff --git a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java b/src/main/java/leekscript/runner/values/ReferenceLeekValue.java index d46fa53f..faad59c8 100644 --- a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java +++ b/src/main/java/leekscript/runner/values/ReferenceLeekValue.java @@ -201,4 +201,9 @@ public int getArgumentsCount(AI ai) throws LeekRunException { public Object toJSON(AI ai) throws LeekRunException { return mValue.toJSON(ai); } + + @Override + public boolean isPrimitive() { + return mValue.isPrimitive(); + } } diff --git a/src/main/java/leekscript/runner/values/StringLeekValue.java b/src/main/java/leekscript/runner/values/StringLeekValue.java index 22a4c65e..aebd0a84 100644 --- a/src/main/java/leekscript/runner/values/StringLeekValue.java +++ b/src/main/java/leekscript/runner/values/StringLeekValue.java @@ -107,4 +107,9 @@ public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { public Object toJSON(AI ai) { return mValue; } + + @Override + public boolean isPrimitive() { + return true; + } } diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index d9b99608..118fa5c1 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -240,4 +240,9 @@ public int getArgumentsCount(AI ai) throws LeekRunException { public Object toJSON(AI ai) throws LeekRunException { return mValue.toJSON(ai); } + + @Override + public boolean isPrimitive() { + return mValue.isPrimitive(); + } } From 12465a392e6e85ba669bf3db0d7d868a9274cae6 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 15 Feb 2021 19:08:37 +0100 Subject: [PATCH 075/319] [compiler] Add analyze, use tokens in AST, multiple errors --- .../leekscript/compiler/AnalyzeError.java | 64 ++++ .../java/leekscript/compiler/IACompiler.java | 51 +-- src/main/java/leekscript/compiler/IAWord.java | 13 + .../java/leekscript/compiler/JavaWriter.java | 5 + .../leekscript/compiler/WordCompiler.java | 321 +++++++++++------- .../compiler/bloc/AbstractLeekBlock.java | 51 ++- .../compiler/bloc/AnonymousFunctionBlock.java | 9 +- .../compiler/bloc/ConditionalBloc.java | 8 + .../compiler/bloc/DoWhileBlock.java | 8 + .../leekscript/compiler/bloc/ForBlock.java | 25 +- .../compiler/bloc/ForeachBlock.java | 24 +- .../compiler/bloc/ForeachKeyBlock.java | 24 +- .../compiler/bloc/FunctionBlock.java | 33 +- .../compiler/bloc/MainLeekBlock.java | 27 +- .../leekscript/compiler/bloc/WhileBlock.java | 8 + .../exceptions/LeekInstructionException.java | 13 - .../expression/AbstractExpression.java | 9 +- .../expression/LeekAnonymousFunction.java | 7 +- .../compiler/expression/LeekArray.java | 12 +- .../compiler/expression/LeekBoolean.java | 7 +- .../compiler/expression/LeekConstant.java | 9 +- .../compiler/expression/LeekExpression.java | 89 +++-- .../expression/LeekExpressionFunction.java | 51 ++- .../compiler/expression/LeekFunction.java | 51 ++- .../expression/LeekFunctionValue.java | 21 +- .../compiler/expression/LeekGlobal.java | 25 +- .../compiler/expression/LeekNull.java | 7 +- .../compiler/expression/LeekNumber.java | 7 +- .../compiler/expression/LeekObjectAccess.java | 75 ++++ .../compiler/expression/LeekParenthesis.java | 9 +- .../compiler/expression/LeekString.java | 8 +- .../compiler/expression/LeekTabularValue.java | 17 +- .../compiler/expression/LeekTernaire.java | 47 +-- .../compiler/expression/LeekVariable.java | 76 ++++- .../instruction/BlankInstruction.java | 5 + .../instruction/LeekBreakInstruction.java | 6 + .../instruction/LeekContinueInstruction.java | 6 + .../LeekExpressionInstruction.java | 6 + .../LeekGlobalDeclarationInstruction.java | 28 +- .../compiler/instruction/LeekInstruction.java | 3 + .../instruction/LeekReturnInstruction.java | 8 + .../LeekVariableDeclarationInstruction.java | 43 ++- src/main/java/leekscript/runner/PhpArray.java | 34 +- .../runner/values/AbstractLeekValue.java | 9 +- .../runner/values/ArrayLeekValue.java | 12 +- .../values/PhpArrayVariableLeekValue.java | 32 +- .../runner/values/VariableLeekValue.java | 6 +- 47 files changed, 1016 insertions(+), 393 deletions(-) create mode 100644 src/main/java/leekscript/compiler/AnalyzeError.java delete mode 100644 src/main/java/leekscript/compiler/exceptions/LeekInstructionException.java create mode 100644 src/main/java/leekscript/compiler/expression/LeekObjectAccess.java diff --git a/src/main/java/leekscript/compiler/AnalyzeError.java b/src/main/java/leekscript/compiler/AnalyzeError.java new file mode 100644 index 00000000..42934acd --- /dev/null +++ b/src/main/java/leekscript/compiler/AnalyzeError.java @@ -0,0 +1,64 @@ +package leekscript.compiler; + +import com.alibaba.fastjson.JSONArray; + +public class AnalyzeError implements Comparable { + + public static enum AnalyzeErrorLevel { + ERROR, // 0 + WARNING, // 1 + } + + // public String file; + // public int startLine; + // public int startCharacter; + // public int endLine; + // public int endCharacter; + public IAWord token; + public String error; + public AnalyzeErrorLevel level; + public String[] parameters; + + public AnalyzeError(IAWord token, AnalyzeErrorLevel level, String error) { + this(token, level, error, null); + } + public AnalyzeError(IAWord token, AnalyzeErrorLevel level, String error, String[] parameters) { + this.token = token; + this.error = error; + this.level = level; + this.parameters = parameters; + } + + public JSONArray toJSON() { + JSONArray array = new JSONArray(); + array.add(level.ordinal()); + array.add(token.getAI().getId()); + array.add(token.getLine()); + array.add(token.getCharacter()); + array.add(token.getWord()); + array.add(this.error); + if (parameters != null) { + array.add(parameters); + } + return array; + } + + @Override + public int compareTo(AnalyzeError o) { + if (token.getLine() != o.token.getLine()) { + return token.getLine() - o.token.getLine(); + } + if (token.getCharacter() != o.token.getCharacter()) { + return token.getCharacter() - o.token.getCharacter(); + } + return 0; + } + + // public AnalyzeError(String file, int startLine, int startCharacter, int endLine, int endCharacter) { + // this.file = file; + // this.startLine = startLine; + // this.startCharacter = startCharacter; + // this.endLine = endLine; + // this.endCharacter = endCharacter; + // } +} diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index 0f2df5e8..ed17f9c5 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -1,6 +1,5 @@ package leekscript.compiler; -import leekscript.ErrorManager; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.exceptions.LeekCompilerException; @@ -21,15 +20,13 @@ public static class AnalyzeResult { } private final JSONArray mInformations = new JSONArray(); - private boolean mErrors = false; private AIFile mCurrentAI; public IACompiler() {} public void addError(AIFile ia_context, int line, int pos, String word, String informations, String[] parameters) { - mErrors = true; JSONArray error = new JSONArray(); - error.add(0); + error.add(0); // level error.add(ia_context.getId()); error.add(line); error.add(pos); @@ -40,23 +37,6 @@ public void addError(AIFile ia_context, int line, int pos, String word, Strin mInformations.add(error); } - public void addError(AIFile ia_context, String informations) { - mErrors = true; - JSONArray error = new JSONArray(); - error.add(1); - error.add(ia_context.getId()); - error.add(informations); - mInformations.add(error); - } - - public void addInformations(AIFile ia_context, int level) { - JSONArray error = new JSONArray(); - error.add(2); - error.add(ia_context.getId()); - error.add(level); - mInformations.add(error); - } - public AnalyzeResult analyze(AIFile ai) throws LeekCompilerException { AnalyzeResult result = new AnalyzeResult(); try { @@ -66,16 +46,21 @@ public AnalyzeResult analyze(AIFile ai) throws LeekCompilerException { MainLeekBlock main = new MainLeekBlock(this, ai); WordCompiler compiler = new WordCompiler(parser, main, ai, ai.getVersion()); compiler.readCode(); - // On sauvegarde les dépendances - addInformations(ai, main.getMinLevel()); - result.includedAIs = main.getIncludedAIs(); - result.success = true; + compiler.analyze(); + + System.out.println("errors " + compiler.getErrors().size()); + if (compiler.getErrors().size() > 0) { + for (var error : compiler.getErrors()) { + mInformations.add(error.toJSON()); + } + result.success = false; + } else { + result.includedAIs = main.getIncludedAIs(); + result.success = true; + } } catch (LeekCompilerException e) { addError(e.getIA(), e.getLine(), e.getChar(), e.getWord(), e.getError(), e.getParameters()); result.success = false; - } catch (Exception e) { - addError(ai, e.getMessage()); - result.success = false; } result.informations = mInformations; return result; @@ -90,17 +75,13 @@ public String compile(AIFile ai, String javaClassName, String AIClass) throws MainLeekBlock main = new MainLeekBlock(this, ai); WordCompiler compiler = new WordCompiler(parser, main, ai, ai.getVersion()); compiler.readCode(); + compiler.analyze(); compiler.writeJava(javaClassName, writer, AIClass); - // On sauvegarde les dépendances - addInformations(ai, main.getMinLevel()); } catch (LeekCompilerException e) { addError(e.getIA(), e.getLine(), e.getChar(), e.getWord(), e.getError(), e.getParameters()); throw e; - } catch (Exception e) { - ErrorManager.exception(e); - addError(ai, e.getMessage()); } return writer.getJavaCode(); } @@ -109,10 +90,6 @@ public String getInformations() { return mInformations.toJSONString(); } - public boolean hasError() { - return mErrors; - } - public AIFile getCurrentAI() { return mCurrentAI; } diff --git a/src/main/java/leekscript/compiler/IAWord.java b/src/main/java/leekscript/compiler/IAWord.java index 5dd65ba8..ff28bdb6 100644 --- a/src/main/java/leekscript/compiler/IAWord.java +++ b/src/main/java/leekscript/compiler/IAWord.java @@ -7,6 +7,14 @@ public class IAWord { private final int character; private final AIFile ai; + public IAWord(String word) { + this.ai = null; + this.type = 0; + this.word = word; + this.line = 0; + this.character = 0; + } + public IAWord(AIFile ai, int type, String word, int line, int character) { this.ai = ai; this.type = type; @@ -34,4 +42,9 @@ public int getLine() { public int getCharacter() { return character; } + + @Override + public String toString() { + return word; + } } diff --git a/src/main/java/leekscript/compiler/JavaWriter.java b/src/main/java/leekscript/compiler/JavaWriter.java index e514c8a9..553288f6 100644 --- a/src/main/java/leekscript/compiler/JavaWriter.java +++ b/src/main/java/leekscript/compiler/JavaWriter.java @@ -45,6 +45,11 @@ public void addLine(String datas) { mLine++; } + public void addLine() { + mCode.append("\n"); + mLine++; + } + public void addCode(String datas) { mCode.append(datas); } diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index b84c4d13..2d159603 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -1,5 +1,9 @@ package leekscript.compiler; +import java.util.Set; +import java.util.TreeSet; + +import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.AbstractLeekBlock; import leekscript.compiler.bloc.AnonymousFunctionBlock; import leekscript.compiler.bloc.ConditionalBloc; @@ -11,7 +15,6 @@ import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.bloc.WhileBlock; import leekscript.compiler.exceptions.LeekCompilerException; -import leekscript.compiler.exceptions.LeekInstructionException; import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekAnonymousFunction; import leekscript.compiler.expression.LeekArray; @@ -20,8 +23,6 @@ import leekscript.compiler.expression.LeekExpression; import leekscript.compiler.expression.LeekExpressionException; import leekscript.compiler.expression.LeekExpressionFunction; -import leekscript.compiler.expression.LeekFunction; -import leekscript.compiler.expression.LeekFunctionValue; import leekscript.compiler.expression.LeekGlobal; import leekscript.compiler.expression.LeekNull; import leekscript.compiler.expression.LeekNumber; @@ -29,6 +30,7 @@ import leekscript.compiler.expression.LeekString; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.Operators; +import leekscript.compiler.expression.LeekVariable.VariableType; import leekscript.compiler.instruction.BlankInstruction; import leekscript.compiler.instruction.LeekBreakInstruction; import leekscript.compiler.instruction.LeekContinueInstruction; @@ -37,7 +39,6 @@ import leekscript.compiler.instruction.LeekReturnInstruction; import leekscript.compiler.instruction.LeekVariableDeclarationInstruction; import leekscript.runner.LeekConstants; -import leekscript.runner.LeekFunctions; public class WordCompiler { @@ -46,6 +47,7 @@ public class WordCompiler { private final WordParser mCompiler; private int mLine; private AIFile mAI = null; + private Set errors = new TreeSet<>(); private final int version; public WordCompiler(WordParser cmp, MainLeekBlock main, AIFile ai, int version) { @@ -56,7 +58,7 @@ public WordCompiler(WordParser cmp, MainLeekBlock main, AIFile ai, int versio this.version = version; } - public void readCode() throws Exception { + public void readCode() throws LeekCompilerException { try { mCompiler.compile(this); // Receherche des fonctions utilisateur @@ -135,26 +137,32 @@ public void readCode() throws Exception { } if (!mMain.equals(mCurentBlock)) throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPEN_BLOC_REMAINING); - } catch (LeekInstructionException e) { - throw new LeekCompilerException(mCompiler.lastWord(), e.getMessage()); + } catch (IndexOutOfBoundsException e) { throw new LeekCompilerException(mCompiler.endWord(), LeekCompilerException.END_OF_SCRIPT_UNEXPECTED); } } - private void compileWord() throws Exception { + public void analyze() { + // Analyse sémantique + mCurentBlock = mMain; + mMain.analyze(this); + } + + private void compileWord() throws LeekCompilerException { mLine = mCompiler.getWord().getLine(); mMain.addInstruction(); IAWord word = mCompiler.getWord(); if (word.getType() == WordParser.T_END_INSTRUCTION) { - mCurentBlock.addInstruction(new BlankInstruction()); + mCurentBlock.addInstruction(this, new BlankInstruction()); mCompiler.skipWord(); return; } else if (word.getType() == WordParser.T_ACCOLADE_RIGHT) { // Fermeture de bloc - if (!mCurentBlock.hasAccolade() || mCurentBlock.getParent() == null) - throw new LeekCompilerException(word, LeekCompilerException.NO_BLOC_TO_CLOSE); - else { + if (!mCurentBlock.hasAccolade() || mCurentBlock.getParent() == null) { + // throw new LeekCompilerException(word, LeekCompilerException.NO_BLOC_TO_CLOSE); + errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.NO_BLOC_TO_CLOSE)); + } else { if (mCurentBlock instanceof DoWhileBlock) { DoWhileBlock do_block = (DoWhileBlock) mCurentBlock; mCurentBlock.checkEndBlock(); @@ -208,9 +216,10 @@ private void compileWord() throws Exception { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.BREAK_OUT_OF_LOOP); } mCompiler.skipWord(); - if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); - mCurentBlock.addInstruction(new LeekBreakInstruction(mCurentBlock.countInstructions(), mCompiler.lastWord().getLine(), mCompiler.lastWord().getAI())); + if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) + mCompiler.skipWord(); + // throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + mCurentBlock.addInstruction(this, new LeekBreakInstruction(mCurentBlock.countInstructions(), mCompiler.lastWord().getLine(), mCompiler.lastWord().getAI())); return; } else if (word.getWord().equals("continue")) { @@ -218,9 +227,11 @@ private void compileWord() throws Exception { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CONTINUE_OUT_OF_LOOP); } mCompiler.skipWord(); - if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); - mCurentBlock.addInstruction(new LeekContinueInstruction(mCurentBlock.countInstructions(), mLine, mAI)); + if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) + mCompiler.skipWord(); + // if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) + // throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + mCurentBlock.addInstruction(this, new LeekContinueInstruction(mCurentBlock.countInstructions(), mLine, mAI)); return; } else if (word.getWord().equals("return")) { mCompiler.skipWord(); @@ -228,9 +239,9 @@ private void compileWord() throws Exception { if (mCompiler.getWord().getType() != WordParser.T_END_INSTRUCTION) { exp = readExpression().getAbstractExpression(); } - if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); - mCurentBlock.addInstruction(new LeekReturnInstruction(mCurentBlock.countInstructions(), exp, mLine, mAI)); + if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) + mCompiler.skipWord(); + mCurentBlock.addInstruction(this, new LeekReturnInstruction(mCurentBlock.countInstructions(), exp, mLine, mAI)); return; } else if (word.getWord().equals("function")) { mCompiler.skipWord(); @@ -240,16 +251,19 @@ private void compileWord() throws Exception { } AbstractExpression exp = readExpression().getAbstractExpression(); - if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); - mCurentBlock.addInstruction(new LeekExpressionInstruction(exp, mLine, mAI)); + if (mCompiler.haveWords() && mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) { + mCompiler.skipWord(); + } + // if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) + // throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + mCurentBlock.addInstruction(this, new LeekExpressionInstruction(exp, mLine, mAI)); } public void writeJava(String className, JavaWriter writer, String AIClass) { mMain.writeJavaCode(writer, className, AIClass); } - private void includeBlock() throws Exception { + private void includeBlock() throws LeekCompilerException { // On vérifie qu'on est dans le bloc principal if (!mCurentBlock.equals(mMain)) throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.INCLUDE_ONLY_IN_MAIN_BLOCK); @@ -262,14 +276,11 @@ private void includeBlock() throws Exception { String iaName = mCompiler.readWord().getWord(); if (!mMain.includeAI(this, iaName)) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.AI_NOT_EXISTING, new String[] { iaName }); + errors.add(new AnalyzeError(mCompiler.lastWord(), AnalyzeErrorLevel.ERROR, LeekCompilerException.AI_NOT_EXISTING, new String[] { iaName })); } if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); - - if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); } private void functionBlock() throws LeekCompilerException { @@ -279,16 +290,15 @@ private void functionBlock() throws LeekCompilerException { // Récupération du nom de la fonction if (mCompiler.getWord().getType() != WordParser.T_STRING) throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.FUNCTION_NAME_EXPECTED); - String funcName = mCompiler.readWord().getWord(); - if (!isAvailable(funcName, false)) + IAWord funcName = mCompiler.readWord(); + if (!isAvailable(funcName.getWord(), false)) throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.FUNCTION_NAME_UNAVAILABLE); if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); } - FunctionBlock block = new FunctionBlock(mCurentBlock, mMain, mLine, mAI); - block.setName(funcName); + FunctionBlock block = new FunctionBlock(mCurentBlock, mMain, mLine, mAI, funcName); mCurentBlock = block; while (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { boolean is_reference = false; @@ -300,7 +310,7 @@ private void functionBlock() throws LeekCompilerException { throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_EXPECTED); if (!isAvailable(mCompiler.getWord().getWord(), true)) throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_UNAVAILABLE); - block.addParameter(mCompiler.readWord().getWord(), is_reference); + block.addParameter(mCompiler.readWord(), is_reference); if (mCompiler.getWord().getType() == WordParser.T_VIRG) mCompiler.skipWord(); } @@ -314,7 +324,7 @@ private void functionBlock() throws LeekCompilerException { mMain.addFunction(block); } - private void forBlock() throws Exception { + private void forBlock() throws LeekCompilerException { // Bloc de type for(i=0;i<5;i++) ou encore for(element in tableau) // On peut déclarer une variable pendant l'instruction d'initialisation if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { @@ -322,7 +332,6 @@ private void forBlock() throws Exception { } boolean isDeclaration = false; - String varName = ""; AbstractLeekBlock forBlock = null; // Là on doit déterminer si y'a déclaration de variable @@ -339,8 +348,9 @@ private void forBlock() throws Exception { // On récupère ensuite le nom de la variable if (mCompiler.getWord().getType() != WordParser.T_STRING) throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.VARIABLE_NAME_EXPECTED); - varName = mCompiler.readWord().getWord(); + IAWord varName = mCompiler.readWord(); // Si c'est une déclaration on vérifie que le nom est disponnible + /* if (isDeclaration) { if (!isAvailable(varName, true)) throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); @@ -349,6 +359,7 @@ private void forBlock() throws Exception { if (!mCurentBlock.hasVariable(varName) && !mMain.hasGlobal(varName)) throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.VARIABLE_NOT_EXISTS); } + */ // Maintenant on va savoir si on a affaire à un for(i in array) ou à un // for(i=0;i<... if (mCompiler.getWord().getWord().equals(":")) {// C'est un @@ -371,8 +382,8 @@ private void forBlock() throws Exception { // On récupère ensuite le nom de la variable accueillant la valeur if (mCompiler.getWord().getType() != WordParser.T_STRING) throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.VARIABLE_NAME_EXPECTED); - String valueVarName = mCompiler.readWord().getWord(); - + IAWord valueVarName = mCompiler.readWord(); + /* if (isValueDeclaration) { if (!isAvailable(valueVarName, true)) throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); @@ -381,13 +392,13 @@ private void forBlock() throws Exception { if (!mCurentBlock.hasVariable(valueVarName) && !mMain.hasGlobal(valueVarName)) throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.VARIABLE_NOT_EXISTS); } - + */ if (!mCompiler.readWord().getWord().equals("in")) throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.KEYWORD_IN_EXPECTED); // On déclare notre bloc foreach et on entre dedans ForeachKeyBlock block = new ForeachKeyBlock(mCurentBlock, mMain, isDeclaration, isValueDeclaration, mLine, mAI, reference1, reference2); - mCurentBlock.addInstruction(block); + mCurentBlock.addInstruction(this, block); mCurentBlock = block; // On lit le array (ou liste de valeurs) @@ -403,7 +414,7 @@ private void forBlock() throws Exception { mCompiler.skipWord(); ForeachBlock block = new ForeachBlock(mCurentBlock, mMain, isDeclaration, mLine, mAI, reference1); - mCurentBlock.addInstruction(block); + mCurentBlock.addInstruction(this, block); mCurentBlock = block; // On lit le array (ou liste de valeurs) @@ -417,18 +428,28 @@ private void forBlock() throws Exception { mCompiler.skipWord(); ForBlock block = new ForBlock(mCurentBlock, mMain, mLine, mAI); - mCurentBlock.addInstruction(block); + mCurentBlock.addInstruction(this, block); mCurentBlock = block; // On récupère la valeur de base du compteur AbstractExpression initValue = readExpression().getAbstractExpression(); - if (isDeclaration) - block.addVariable(varName); - if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) + if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) { + // errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.ERROR, LeekCompilerException.END_OF_INSTRUCTION_EXPECTED)); throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + // return; + } + // if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) { + // mCompiler.skipWord(); + // } AbstractExpression condition = readExpression().getAbstractExpression(); - if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) + if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) { + // errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.ERROR, LeekCompilerException.END_OF_INSTRUCTION_EXPECTED)); throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + // return; + } + // if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) { + // mCompiler.skipWord(); + // } AbstractExpression incrementation = readExpression().getAbstractExpression(); // Attention si l'incrémentation n'est pas une expression Java fait @@ -438,7 +459,7 @@ private void forBlock() throws Exception { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.UNCOMPLETE_EXPRESSION); } - block.setInitialisation(varName, initValue, isDeclaration, block.hasGlobal(varName)); + block.setInitialisation(varName, initValue, isDeclaration, block.hasGlobal(varName.getWord())); block.setCondition(condition); block.setIncrementation(incrementation); @@ -457,7 +478,7 @@ private void forBlock() throws Exception { forBlock.noAccolade(); } - private void whileBlock() throws Exception { + private void whileBlock() throws LeekCompilerException { if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); } @@ -471,21 +492,21 @@ private void whileBlock() throws Exception { mCompiler.skipWord(); } else bloc.noAccolade(); - mCurentBlock.addInstruction(bloc); + mCurentBlock.addInstruction(this, bloc); mCurentBlock = bloc; } - private void dowhileBlock() throws LeekCompilerException, LeekInstructionException { + private void dowhileBlock() throws LeekCompilerException { DoWhileBlock bloc = new DoWhileBlock(mCurentBlock, mMain, mAI); if (mCompiler.getWord().getType() == WordParser.T_ACCOLADE_LEFT) { mCompiler.skipWord(); } else bloc.noAccolade(); - mCurentBlock.addInstruction(bloc); + mCurentBlock.addInstruction(this, bloc); mCurentBlock = bloc; } - private void dowhileendBlock(DoWhileBlock bloc) throws Exception { + private void dowhileendBlock(DoWhileBlock bloc) throws LeekCompilerException { if (!mCompiler.readWord().getWord().equals("while")) throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.WHILE_EXPECTED_AFTER_DO); if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { @@ -495,11 +516,11 @@ private void dowhileendBlock(DoWhileBlock bloc) throws Exception { if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); } - if (mCompiler.getWord().getType() != WordParser.T_END_INSTRUCTION) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + // if (mCompiler.getWord().getType() != WordParser.T_END_INSTRUCTION) + // throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); } - private void elseBlock() throws Exception { + private void elseBlock() throws LeekCompilerException { // On vérifie qu'on est bien associé à un bloc conditionnel ConditionalBloc last = mCurentBlock.getLastOpenedConditionalBlock(); if (last == null || last.getCondition() == null) { @@ -524,11 +545,11 @@ private void elseBlock() throws Exception { mCompiler.skipWord(); } else bloc.noAccolade(); - last.getParent().addInstruction(bloc); + last.getParent().addInstruction(this, bloc); mCurentBlock = bloc; } - private void ifBlock() throws Exception { + private void ifBlock() throws LeekCompilerException { if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); } @@ -542,20 +563,20 @@ private void ifBlock() throws Exception { mCompiler.skipWord(); } else bloc.noAccolade(); - mCurentBlock.addInstruction(bloc); + mCurentBlock.addInstruction(this, bloc); mCurentBlock = bloc; } - private void globalDeclaration() throws Exception { + private void globalDeclaration() throws LeekCompilerException { // Il y a au moins une premiere variable IAWord word = mCompiler.readWord(); if (!(mCurentBlock instanceof MainLeekBlock)) throw new LeekCompilerException(word, LeekCompilerException.GLOBAL_ONLY_IN_MAIN_BLOCK); if (word.getType() != WordParser.T_STRING) throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED_AFTER_GLOBAL); - if (!isGlobalAvailable(word.getWord()) || mMain.hasDeclaredGlobal(word.getWord())) - throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); - LeekGlobalDeclarationInstruction variable = new LeekGlobalDeclarationInstruction(word.getWord(), mLine, mAI); + // if (!isGlobalAvailable(word.getWord()) || mMain.hasDeclaredGlobal(word.getWord())) + // throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); + LeekGlobalDeclarationInstruction variable = new LeekGlobalDeclarationInstruction(word, mLine, mAI); // On regarde si une valeur est assignée if (mCompiler.getWord().getWord().equals("=")) { mCompiler.skipWord(); @@ -564,16 +585,16 @@ private void globalDeclaration() throws Exception { } // On ajoute la variable mMain.addGlobal(variable.getName()); - mCurentBlock.addInstruction(variable); - while (mCompiler.getWord().getType() == WordParser.T_VIRG) { + mCurentBlock.addInstruction(this, variable); + while (mCompiler.haveWords() && mCompiler.getWord().getType() == WordParser.T_VIRG) { // On regarde si y'en a d'autres mCompiler.skipWord();// On passe la virgule word = mCompiler.readWord(); if (word.getType() != WordParser.T_STRING) throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED); - if (!isGlobalAvailable(word.getWord()) || mMain.hasDeclaredGlobal(word.getWord())) - throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); - variable = new LeekGlobalDeclarationInstruction(word.getWord(), mLine, mAI); + // if (!isGlobalAvailable(word.getWord()) || mMain.hasDeclaredGlobal(word.getWord())) + // throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); + variable = new LeekGlobalDeclarationInstruction(word, mLine, mAI); // On regarde si une valeur est assign�e if (mCompiler.getWord().getWord().equals("=")) { mCompiler.skipWord(); @@ -582,59 +603,61 @@ private void globalDeclaration() throws Exception { } // On ajoute la variable mMain.addGlobal(variable.getName()); - mCurentBlock.addInstruction(variable); + mCurentBlock.addInstruction(this, variable); } - word = mCompiler.readWord(); - if (word.getType() != WordParser.T_END_INSTRUCTION) - throw new LeekCompilerException(word, LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + // word = mCompiler.readWord(); + // if (word.getType() != WordParser.T_END_INSTRUCTION) + // throw new LeekCompilerException(word, LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + if (mCompiler.haveWords() && mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) + mCompiler.skipWord(); } - private void variableDeclaration() throws Exception { + private void variableDeclaration() throws LeekCompilerException { // Il y a au moins une premiere variable IAWord word = mCompiler.readWord(); if (word.getType() != WordParser.T_STRING) throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED); - if (!isAvailable(word.getWord(), true)) - throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); - LeekVariableDeclarationInstruction variable = new LeekVariableDeclarationInstruction(word.getWord(), mLine, mAI); + // if (!isAvailable(word.getWord(), true)) + // throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); + LeekVariableDeclarationInstruction variable = new LeekVariableDeclarationInstruction(word, mLine, mAI); // On regarde si une valeur est assignée if (mCompiler.getWord().getWord().equals("=")) { mCompiler.skipWord(); // Si oui on récupère la valeur en question - mCurentBlock.setDeclaringVariable(variable.getName()); + mCurentBlock.setDeclaringVariable(variable.getToken()); variable.setValue(readExpression().getAbstractExpression()); if (mCurentBlock.isDeclaringBariableUsed()) variable.mustSepare(); mCurentBlock.setDeclaringVariable(null); } - // On ajoute la variable - mCurentBlock.addVariable(variable.getName()); - mCurentBlock.addInstruction(variable); + mCurentBlock.addInstruction(this, variable); while (mCompiler.getWord().getType() == WordParser.T_VIRG) { // On regarde si y'en a d'autres mCompiler.skipWord();// On passe la virgule word = mCompiler.readWord(); if (word.getType() != WordParser.T_STRING) throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED); - if (!isAvailable(word.getWord(), true)) - throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); - variable = new LeekVariableDeclarationInstruction(word.getWord(), mLine, mAI); - // On regarde si une valeur est assign�e + // if (!isAvailable(word.getWord(), true)) + // throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); + variable = new LeekVariableDeclarationInstruction(word, mLine, mAI); + // On regarde si une valeur est assignée if (mCompiler.getWord().getWord().equals("=")) { mCompiler.skipWord(); // Si oui on récupère la valeur en question variable.setValue(readExpression().getAbstractExpression()); } // On ajoute la variable - mCurentBlock.addVariable(variable.getName()); - mCurentBlock.addInstruction(variable); + mCurentBlock.addInstruction(this, variable); + } + if (mCompiler.haveWords() && mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) { + mCompiler.skipWord(); } word = mCompiler.readWord(); if (word.getType() != WordParser.T_END_INSTRUCTION) throw new LeekCompilerException(word, LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); } - public LeekExpression readExpression() throws Exception { + public LeekExpression readExpression() throws LeekCompilerException { LeekExpression retour = new LeekExpression(); while (mCompiler.haveWords()) { IAWord word = mCompiler.getWord(); @@ -660,7 +683,7 @@ public LeekExpression readExpression() throws Exception { if (mCompiler.getWord().getType() == WordParser.T_VIRG) mCompiler.skipWord(); } - if (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { + if (mCompiler.haveWords() && mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); } @@ -676,18 +699,18 @@ public LeekExpression readExpression() throws Exception { break; if (Operators.isUnarySuffix(operator)) - retour.addUnarySuffix(operator); + retour.addUnarySuffix(operator, word); else - retour.addOperator(operator); + retour.addOperator(operator, word); } else if (word.getType() == WordParser.T_STRING) { if (word.getWord().equals("is")) { mCompiler.skipWord(); word = mCompiler.getWord(); if (word.getWord().equals("not")) { - mCompiler.skipWord(); - retour.addOperator(Operators.NOTEQUALS); + IAWord token = mCompiler.readWord(); + retour.addOperator(Operators.NOTEQUALS, token); } else { - retour.addOperator(Operators.EQUALS); + retour.addOperator(Operators.EQUALS, word); } continue; } @@ -730,36 +753,39 @@ else if (type == 2) } retour.addExpression(array); } else if (word.getType() == WordParser.T_STRING) { - if (mCurentBlock.hasVariable(word.getWord())) - retour.addExpression(new LeekVariable(word.getWord())); - else if (mMain.hasGlobal(word.getWord())) - retour.addExpression(new LeekGlobal(word.getWord())); - else if (LeekFunctions.isFunction(word.getWord()) > -1 || mMain.hasUserFunction(word.getWord(), true)) { - LeekFunction function = new LeekFunction(word.getWord()); - String fname = word.getWord(); - // On doit lire la fonction - mCompiler.skipWord(); - if (mCompiler.getWord().getType() != WordParser.T_PAR_LEFT) { - // On utilise le nom de la fonction comme une - // variable - String namespace = LeekFunctions.getNamespace(fname); - retour.addExpression(new LeekFunctionValue(fname, namespace)); - continue; - } else { - mCompiler.skipWord(); - while (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { - function.addParameter(readExpression().getAbstractExpression()); - if (mCompiler.getWord().getType() == WordParser.T_VIRG) - mCompiler.skipWord(); - } - if (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); - } - retour.addExpression(function); - } + // var variable = mCurentBlock.getVariable(word.getWord()); + // if (variable != null) { + // retour.addExpression(variable); + // } + // else + if (mMain.hasGlobal(word.getWord())) { + retour.addExpression(new LeekGlobal(word)); + // } else if (LeekFunctions.isFunction(word.getWord()) > -1 || mMain.hasUserFunction(word.getWord(), true) || mMain.hasUserClass(word.getWord())) { + // // System.out.println("Function call " + word.getWord()); + // boolean isClass = mMain.hasUserClass(word.getWord()); + // LeekFunction function = new LeekFunction(word.getWord(), isClass); + // String fname = word.getWord(); + // // On doit lire la fonction + // mCompiler.skipWord(); + // if (mCompiler.getWord().getType() != WordParser.T_PAR_LEFT) { + // // On utilise le nom de la fonction comme une variable + // String namespace = LeekFunctions.getNamespace(fname); + // retour.addExpression(new LeekFunctionValue(fname, namespace)); + // continue; + // } else { + // mCompiler.skipWord(); + // while (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { + // function.addParameter(readExpression().getAbstractExpression()); + // if (mCompiler.getWord().getType() == WordParser.T_VIRG) + // mCompiler.skipWord(); + // } + // if (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { + // throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); + // } + // retour.addExpression(function); + // } } else if (word.getWord().equalsIgnoreCase("function")) { retour.addExpression(readAnonymousFunction()); - } else if (word.getWord().equalsIgnoreCase("true")) retour.addExpression(new LeekBoolean(true)); else if (word.getWord().equalsIgnoreCase("false")) @@ -767,11 +793,12 @@ else if (word.getWord().equalsIgnoreCase("false")) else if (word.getWord().equalsIgnoreCase("null")) retour.addExpression(new LeekNull()); else if (word.getWord().equalsIgnoreCase("not")) - retour.addUnaryPrefix(Operators.NOT); + retour.addUnaryPrefix(Operators.NOT, word); else if (LeekConstants.get(word.getWord()) != null) retour.addExpression(new LeekConstant(word.getWord(), LeekConstants.get(word.getWord()))); else { - throw new LeekCompilerException(word, LeekCompilerException.UNKNOWN_VARIABLE_OR_FUNCTION); + retour.addExpression(new LeekVariable(word, VariableType.LOCAL)); + // throw new LeekCompilerException(word, LeekCompilerException.UNKNOWN_VARIABLE_OR_FUNCTION); } } else if (word.getType() == WordParser.T_PAR_LEFT) { mCompiler.skipWord();// On avance le curseur pour bien être @@ -795,26 +822,28 @@ else if (operator == Operators.INCREMENT) if (Operators.isUnaryPrefix(operator)) { // Si oui on l'ajoute - retour.addUnaryPrefix(operator); + retour.addUnaryPrefix(operator, word); } else { - throw new LeekCompilerException(word, LeekCompilerException.OPERATOR_UNEXPECTED); + errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.OPERATOR_UNEXPECTED)); + // throw new LeekCompilerException(word, LeekCompilerException.OPERATOR_UNEXPECTED); } } else { - throw new LeekCompilerException(word, LeekCompilerException.VALUE_EXPECTED); + errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.VALUE_EXPECTED)); + // throw new LeekCompilerException(word, LeekCompilerException.VALUE_EXPECTED); } } mCompiler.skipWord(); } // Avant de retourner, on valide l'expression try { - retour.getAbstractExpression().validExpression(mMain); + retour.getAbstractExpression().validExpression(this, mMain); } catch (LeekExpressionException e) { throw new LeekCompilerException(mCompiler.lastWord(), e.getMessage(), new String[] { e.getExpression() }); } return retour; } - private LeekAnonymousFunction readAnonymousFunction() throws Exception { + private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerException { mCompiler.skipWord(); if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_FUNCTION); @@ -825,7 +854,7 @@ private LeekAnonymousFunction readAnonymousFunction() throws Exception { AIFile initialAI = mAI; AnonymousFunctionBlock block = new AnonymousFunctionBlock(mCurentBlock, mMain, mLine, mAI); if (initialBlock.getDeclaringVariable() != null) - block.addVariable(initialBlock.getDeclaringVariable()); + block.addVariable(new LeekVariable(initialBlock.getDeclaringVariable(), VariableType.LOCAL)); mCurentBlock = block; // Lecture des paramètres @@ -837,9 +866,9 @@ private LeekAnonymousFunction readAnonymousFunction() throws Exception { } if (mCompiler.getWord().getType() != WordParser.T_STRING) throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_EXPECTED); - if (!isAvailable(mCompiler.getWord().getWord(), true)) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_UNAVAILABLE); - block.addParameter(mCompiler.readWord().getWord(), is_reference); + // if (!isAvailable(mCompiler.getWord().getWord(), true)) + // throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_UNAVAILABLE); + block.addParameter(mCompiler.readWord(), is_reference); if (mCompiler.getWord().getType() == WordParser.T_VIRG) mCompiler.skipWord(); } @@ -912,7 +941,35 @@ public String getString() { return mMain.getCode(); } + public Set getErrors() { + return this.errors; + } + + public AbstractLeekBlock getCurrentBlock() { + return mCurentBlock; + } + + public void addError(AnalyzeError error) { + this.errors.add(error); + } + + public void setCurrentBlock(AbstractLeekBlock block) { + mCurentBlock = block; + } + + public WordParser getParser() { + return mCompiler; + } + + public MainLeekBlock getMainBlock() { + return mMain; + } + public int getVersion() { return this.version; } + + public void addErrors(Set errors) { + this.errors.addAll(errors); + } } diff --git a/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java b/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java index 2480d031..eb0d05af 100644 --- a/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java @@ -1,19 +1,23 @@ package leekscript.compiler.bloc; import java.util.ArrayList; +import java.util.HashMap; import leekscript.compiler.AIFile; +import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.exceptions.LeekCompilerException; -import leekscript.compiler.exceptions.LeekInstructionException; +import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.instruction.LeekInstruction; public abstract class AbstractLeekBlock implements LeekInstruction { + protected ArrayList mInstructions = new ArrayList(); protected AbstractLeekBlock mParent = null; - protected ArrayList mVariables = new ArrayList(); + protected HashMap mVariables = new HashMap<>(); - protected String mDeclaringVariable = null; + protected IAWord mDeclaringVariable = null; protected boolean mDeclaringVariableUsed = false; protected boolean mAccolade = true; protected MainLeekBlock mMain = null; @@ -55,9 +59,9 @@ public AbstractLeekBlock(AbstractLeekBlock parent, MainLeekBlock main, int line, mAI = ai; } - public void addInstruction(LeekInstruction instruction) throws LeekInstructionException { + public void addInstruction(WordCompiler compiler, LeekInstruction instruction) throws LeekCompilerException { if (mEndInstruction != 0) { - throw new LeekInstructionException(LeekCompilerException.CANT_ADD_INSTRUCTION_AFTER_BREAK); + throw new LeekCompilerException(compiler.getParser().lastWord(), LeekCompilerException.CANT_ADD_INSTRUCTION_AFTER_BREAK); } mEndInstruction = instruction.getEndBlock(); mInstructions.add(instruction); @@ -71,12 +75,12 @@ public boolean hasAccolade() { return mAccolade; } - public void setDeclaringVariable(String variable) { + public void setDeclaringVariable(IAWord variable) { mDeclaringVariable = variable; mDeclaringVariableUsed = false; } - public String getDeclaringVariable() { + public IAWord getDeclaringVariable() { mDeclaringVariableUsed = true; return mDeclaringVariable; } @@ -104,8 +108,8 @@ public AbstractLeekBlock endInstruction() { return this; } - public void addVariable(String variable) { - mVariables.add(variable); + public void addVariable(LeekVariable variable) { + mVariables.put(variable.getName(), variable); } public LeekInstruction lastInstruction() { @@ -113,11 +117,16 @@ public LeekInstruction lastInstruction() { } public boolean hasVariable(String variable) { - if (mVariables.contains(variable)) - return true; + return mVariables.containsKey(variable); + // return getVariable(variable, false) != null; + } + + public LeekVariable getVariable(String variable, boolean includeClassMembers) { + var v = mVariables.get(variable); + if (v != null) return v; if (mParent != null) - return mParent.hasVariable(variable); - return false; + return mParent.getVariable(variable, includeClassMembers); + return null; } public boolean hasGlobal(String globale) { @@ -167,4 +176,20 @@ public int getEndBlock() { public boolean putCounterBefore() { return mEndInstruction != 0; } + + public void analyze(WordCompiler compiler) { + AbstractLeekBlock initialBlock = compiler.getCurrentBlock(); + compiler.setCurrentBlock(this); + for (var instruction : mInstructions) { + instruction.analyze(compiler); + } + compiler.setCurrentBlock(initialBlock); + } + + public int getLine() { + return mLine; + } + public AIFile getFile() { + return mAI; + } } diff --git a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java index c88db95c..d4f03469 100644 --- a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java @@ -3,7 +3,10 @@ import java.util.ArrayList; import leekscript.compiler.AIFile; +import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; +import leekscript.compiler.expression.LeekVariable; +import leekscript.compiler.expression.LeekVariable.VariableType; public class AnonymousFunctionBlock extends AbstractLeekBlock { @@ -37,10 +40,10 @@ public String referenceArray() { return str + "}"; } - public void addParameter(String parameter, boolean is_reference) { - mParameters.add(parameter); + public void addParameter(IAWord token, boolean is_reference) { + mParameters.add(token.getWord()); mReferences.add(is_reference); - addVariable(parameter); + addVariable(new LeekVariable(token, VariableType.ARGUMENT)); } @Override diff --git a/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java b/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java index a6075b1b..d2042610 100644 --- a/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java +++ b/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java @@ -2,6 +2,7 @@ import leekscript.compiler.AIFile; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.expression.AbstractExpression; public class ConditionalBloc extends AbstractLeekBlock { @@ -89,4 +90,11 @@ private void setPutCounterBefore(boolean value) { else mPutCounterBefore = value; } + @Override + public void analyze(WordCompiler compiler) { + if (mCondition != null) { + mCondition.analyze(compiler); + } + super.analyze(compiler); + } } diff --git a/src/main/java/leekscript/compiler/bloc/DoWhileBlock.java b/src/main/java/leekscript/compiler/bloc/DoWhileBlock.java index a21c334d..53a521c6 100644 --- a/src/main/java/leekscript/compiler/bloc/DoWhileBlock.java +++ b/src/main/java/leekscript/compiler/bloc/DoWhileBlock.java @@ -2,6 +2,7 @@ import leekscript.compiler.AIFile; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.expression.AbstractExpression; public class DoWhileBlock extends AbstractLeekBlock { @@ -39,4 +40,11 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { public boolean isBreakable() { return true; } + + public void analyze(WordCompiler compiler) { + if (mCondition != null) { + mCondition.analyze(compiler); + } + super.analyze(compiler); + } } diff --git a/src/main/java/leekscript/compiler/bloc/ForBlock.java b/src/main/java/leekscript/compiler/bloc/ForBlock.java index 1ca3440f..ee7dc97d 100644 --- a/src/main/java/leekscript/compiler/bloc/ForBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForBlock.java @@ -1,12 +1,15 @@ package leekscript.compiler.bloc; import leekscript.compiler.AIFile; +import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekExpression; import leekscript.compiler.expression.LeekGlobal; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.Operators; +import leekscript.compiler.expression.LeekVariable.VariableType; import leekscript.compiler.instruction.LeekExpressionInstruction; import leekscript.compiler.instruction.LeekInstruction; import leekscript.compiler.instruction.LeekVariableDeclarationInstruction; @@ -21,16 +24,15 @@ public ForBlock(AbstractLeekBlock parent, MainLeekBlock main, int line, AIFile mParameters = new ArrayList(); private final ArrayList mReferences = new ArrayList(); - public FunctionBlock(AbstractLeekBlock parent, MainLeekBlock main, int line, AIFile ai) { + public FunctionBlock(AbstractLeekBlock parent, MainLeekBlock main, int line, AIFile ai, IAWord token) { super(parent, main, line, ai); + this.token = token; } public int getId() { @@ -25,7 +30,7 @@ public void setId(int id) { } public String getName() { - return mName; + return token.getWord(); } public int countParameters() { @@ -42,24 +47,20 @@ public String referenceArray() { return str + "}"; } - public void setName(String name) { - mName = name; - } - - public void addParameter(String parameter, boolean is_reference) { - mParameters.add(parameter); + public void addParameter(IAWord parameter, boolean is_reference) { + mParameters.add(parameter.getWord()); mReferences.add(is_reference); - addVariable(parameter); + addVariable(new LeekVariable(parameter, VariableType.ARGUMENT)); } @Override public boolean hasVariable(String variable) { - return mVariables.contains(variable); + return mVariables.containsKey(variable); } @Override public String getCode() { - String str = "function " + mName + "("; + String str = "function " + token.getWord() + "("; for (int i = 0; i < mParameters.size(); i++) { if (i != 0) str += ", "; @@ -76,7 +77,7 @@ public void checkEndBlock() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { StringBuilder sb = new StringBuilder(); - sb.append("private AbstractLeekValue user_function_").append(mName).append("("); + sb.append("private AbstractLeekValue user_function_").append(token.getWord()).append("("); for (int i = 0; i < mParameters.size(); i++) { if (i != 0) sb.append(", "); @@ -101,4 +102,10 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { public boolean isReference(int i) { return mReferences.get(i); } + + public void declare(WordCompiler compiler) { + // On ajoute la fonction + compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.FUNCTION)); + // System.out.println("Declare function " + token.getWord()); + } } diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 89493c42..76f34cc7 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -13,6 +13,7 @@ import leekscript.compiler.LeekScript; import leekscript.compiler.WordCompiler; import leekscript.compiler.WordParser; +import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.instruction.LeekInstruction; import leekscript.runner.LeekFunctions; @@ -73,7 +74,7 @@ public void setMinLevel(int min_level) { this.mMinLevel = min_level; } - public boolean includeAI(WordCompiler compiler, String path) throws Exception { + public boolean includeAI(WordCompiler compiler, String path) throws LeekCompilerException { try { AIFile ai = LeekScript.getResolver().resolve(path, mCompiler.getCurrentAI().getContext()); if (mIncluded.contains(ai.getId())) { @@ -85,6 +86,7 @@ public boolean includeAI(WordCompiler compiler, String path) throws Exception { WordParser words = new WordParser(ai, compiler.getVersion()); WordCompiler newCompiler = new WordCompiler(words, this, ai, compiler.getVersion()); newCompiler.readCode(); + compiler.addErrors(newCompiler.getErrors()); mCompiler.setCurrentAI(previousAI); return true; } catch (FileNotFoundException e) { @@ -122,7 +124,9 @@ public int getUserFunctionParametersCount(String name) { if (block.getName().equals(name)) return block.countParameters(); } - return mUserFunctions.get(name); + var f = mUserFunctions.get(name); + if (f != null) return f; + return -1; } public FunctionBlock getUserFunction(String name) { @@ -171,11 +175,13 @@ public String getCode() { public void writeJavaCode(JavaWriter writer, String className, String AIClass) { writer.addLine("import leekscript.runner.*;"); writer.addLine("import leekscript.runner.values.*;"); + writer.addLine(); writer.addLine("public class " + className + " extends " + AIClass + " {"); writer.addLine("public " + className + "() throws LeekRunException {"); writer.addLine("super();"); writer.addLine("mInstructions = " + mInstructions.size() + ";"); writer.addLine("}"); + // Variables globales for (String global : mGobales) { writer.addLine("private VariableLeekValue globale_" + global + " = null;"); @@ -236,8 +242,8 @@ public void printFunctionInformations(JavaWriter writer) { } writer.addLine("} return -1; }"); // Références - writer.addLine("public boolean[] userFunctionReference(int id){"); - writer.addLine("switch(id){"); + writer.addLine("public boolean[] userFunctionReference(int id) {"); + writer.addLine("switch(id) {"); for (FunctionBlock f : mFunctions) { writer.addLine("case " + f.getId() + ": return new boolean[]" + f.referenceArray() + ";"); } @@ -269,6 +275,9 @@ public void printFunctionInformations(JavaWriter writer) { writer.addLine("case " + f.getId() + ": return new boolean[]" + f.referenceArray() + ";"); } writer.addLine("} return null; }"); + writer.addLine("public int getVersion() {"); + writer.addLine("return " + mCompiler.getCurrentAI().getVersion() + ";"); + writer.addLine("}"); // Execute /* * writer.addLine( @@ -304,4 +313,14 @@ public List getIncludedAIs() { public IACompiler getCompiler() { return mCompiler; } + + public void analyze(WordCompiler compiler) { + for (var function : mFunctions) { + function.declare(compiler); + } + for (var function : mFunctions) { + function.analyze(compiler); + } + super.analyze(compiler); + } } diff --git a/src/main/java/leekscript/compiler/bloc/WhileBlock.java b/src/main/java/leekscript/compiler/bloc/WhileBlock.java index f8a11f8c..d245256b 100644 --- a/src/main/java/leekscript/compiler/bloc/WhileBlock.java +++ b/src/main/java/leekscript/compiler/bloc/WhileBlock.java @@ -2,6 +2,7 @@ import leekscript.compiler.AIFile; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.expression.AbstractExpression; public class WhileBlock extends AbstractLeekBlock { @@ -44,4 +45,11 @@ public boolean isBreakable() { public int getEndBlock() { return 0; } + + public void analyze(WordCompiler compiler) { + if (mCondition != null) { + mCondition.analyze(compiler); + } + super.analyze(compiler); + } } diff --git a/src/main/java/leekscript/compiler/exceptions/LeekInstructionException.java b/src/main/java/leekscript/compiler/exceptions/LeekInstructionException.java deleted file mode 100644 index 369cce4c..00000000 --- a/src/main/java/leekscript/compiler/exceptions/LeekInstructionException.java +++ /dev/null @@ -1,13 +0,0 @@ -package leekscript.compiler.exceptions; - - -public class LeekInstructionException extends Exception { - /** - * - */ - private static final long serialVersionUID = 1L; - - public LeekInstructionException(String message){ - super(message); - } -} diff --git a/src/main/java/leekscript/compiler/expression/AbstractExpression.java b/src/main/java/leekscript/compiler/expression/AbstractExpression.java index d9d53d5f..7525033c 100644 --- a/src/main/java/leekscript/compiler/expression/AbstractExpression.java +++ b/src/main/java/leekscript/compiler/expression/AbstractExpression.java @@ -1,6 +1,7 @@ package leekscript.compiler.expression; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; public abstract class AbstractExpression { @@ -22,9 +23,15 @@ public abstract class AbstractExpression { public abstract void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer); - public abstract boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException; + public abstract boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException; public AbstractExpression trim() { return this; } + + public boolean isLeftValue() { + return false; + } + + public abstract void analyze(WordCompiler compiler); } diff --git a/src/main/java/leekscript/compiler/expression/LeekAnonymousFunction.java b/src/main/java/leekscript/compiler/expression/LeekAnonymousFunction.java index 6ca99820..877b1d6b 100644 --- a/src/main/java/leekscript/compiler/expression/LeekAnonymousFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekAnonymousFunction.java @@ -1,6 +1,7 @@ package leekscript.compiler.expression; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.AnonymousFunctionBlock; import leekscript.compiler.bloc.MainLeekBlock; @@ -23,7 +24,7 @@ public String getString() { } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { return true; } @@ -34,4 +35,8 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(")"); } + @Override + public void analyze(WordCompiler compiler) { + mBlock.analyze(compiler); + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekArray.java b/src/main/java/leekscript/compiler/expression/LeekArray.java index 7b5a6344..89236816 100644 --- a/src/main/java/leekscript/compiler/expression/LeekArray.java +++ b/src/main/java/leekscript/compiler/expression/LeekArray.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; public class LeekArray extends AbstractExpression { @@ -37,9 +38,9 @@ public String getString() { } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { for(AbstractExpression parameter : mValues){ - parameter.validExpression(mainblock); + parameter.validExpression(compiler, mainblock); } return true; } @@ -56,4 +57,11 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("}, " + (mIsKeyVal ? "true" : "false") + ")"); } } + + @Override + public void analyze(WordCompiler compiler) { + for (var value : mValues) { + value.analyze(compiler); + } + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekBoolean.java b/src/main/java/leekscript/compiler/expression/LeekBoolean.java index 74df9a88..6264b584 100644 --- a/src/main/java/leekscript/compiler/expression/LeekBoolean.java +++ b/src/main/java/leekscript/compiler/expression/LeekBoolean.java @@ -1,6 +1,7 @@ package leekscript.compiler.expression; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; public class LeekBoolean extends AbstractExpression { @@ -27,8 +28,12 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { return true; } + @Override + public void analyze(WordCompiler compiler) { + + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekConstant.java b/src/main/java/leekscript/compiler/expression/LeekConstant.java index f1d1a026..92c7c52e 100644 --- a/src/main/java/leekscript/compiler/expression/LeekConstant.java +++ b/src/main/java/leekscript/compiler/expression/LeekConstant.java @@ -1,6 +1,7 @@ package leekscript.compiler.expression; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.runner.ILeekConstant; import leekscript.runner.LeekFunctions; @@ -9,7 +10,7 @@ public class LeekConstant extends AbstractExpression { private final String mConstantName; private final ILeekConstant mConstant; - + public LeekConstant(String word, ILeekConstant constant) { mConstantName = word; mConstant = constant; @@ -33,9 +34,13 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { // La vérification se fait en amont return true; } + @Override + public void analyze(WordCompiler compiler) { + + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index c48f79a0..e8e9614c 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -1,12 +1,17 @@ package leekscript.compiler.expression; +import leekscript.compiler.AnalyzeError; +import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; +import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.exceptions.LeekCompilerException; public class LeekExpression extends AbstractExpression { private int mOperator = -1; + private IAWord mOperatorToken; protected AbstractExpression mExpression1 = null; protected AbstractExpression mExpression2 = null; @@ -48,8 +53,32 @@ public int getOperator() { return mOperator; } - public void setOperator(int operator) { + public int getLastOperator() { + if (mExpression2 != null && mExpression2 instanceof LeekExpression) { + return ((LeekExpression) mExpression2).getLastOperator(); + } + return mOperator; + } + + public AbstractExpression getLastExpression() { + if (mExpression2 != null) { + if (mExpression2 instanceof LeekExpression) { + return ((LeekExpression) mExpression2).getLastExpression(); + } + return mExpression2; + } + if (mExpression1 != null) { + if (mExpression1 instanceof LeekExpression) { + return ((LeekExpression) mExpression1).getLastExpression(); + } + return mExpression1; + } + return mExpression1; + } + + public void setOperator(int operator, IAWord operatorToken) { mOperator = operator; + mOperatorToken = operatorToken; } public boolean needOperator() { @@ -107,12 +136,12 @@ else if (mExpression1.getType() == EXPRESSION && !((LeekExpression) mExpression1 } } - public void addUnaryPrefix(int operator) { + public void addUnaryPrefix(int operator, IAWord operatorToken) { // On doit trouver à quel endroit de l'arborescence on doit placer le // préfix // En général c'est un => ! LeekExpression exp = new LeekExpression(); - exp.setOperator(operator); + exp.setOperator(operator, operatorToken); exp.setParent(this); exp.setExpression1(new LeekNull()); addExpression(exp); @@ -166,30 +195,30 @@ else if (mExpression2 != null) { } } - public void addUnarySuffix(int suffix) { + public void addUnarySuffix(int suffix, IAWord token) { // On doit ajouter ce suffix au dernier élément ajouté if (mExpression1 != null && mExpression2 == null) { if (mExpression1.getType() == EXPRESSION) - ((LeekExpression) mExpression1).addUnarySuffix(suffix); + ((LeekExpression) mExpression1).addUnarySuffix(suffix, token); else { // On doit ajouter à l'élément mExpression1 LeekExpression exp = new LeekExpression(); exp.setParent(this); exp.setExpression1(new LeekNull()); - exp.setOperator(suffix); + exp.setOperator(suffix, token); exp.setExpression2(mExpression1); mExpression1 = exp; } } else if (mExpression2 != null) { if (mExpression2.getType() == EXPRESSION) - ((LeekExpression) mExpression2).addUnarySuffix(suffix); + ((LeekExpression) mExpression2).addUnarySuffix(suffix, token); else { // On doit ajouter à l'élément mExpression2 LeekExpression exp = new LeekExpression(); exp.setParent(this); exp.setExpression1(new LeekNull()); - exp.setOperator(suffix); + exp.setOperator(suffix, token); exp.setExpression2(mExpression2); mExpression2 = exp; } @@ -202,7 +231,7 @@ public void addTernaire() { if (mExpression1 != null) { LeekTernaire ternaire = new LeekTernaire(); ternaire.addExpression(mExpression1); - ternaire.addOperator(Operators.TERNAIRE); + ternaire.addOperator(Operators.TERNAIRE, null); ternaire.setParent(this); mExpression1 = ternaire; } @@ -217,12 +246,12 @@ public void addTernaire() { new_e.setParent(this); new_e.setExpression1(mExpression1); new_e.setExpression2(mExpression2); - new_e.setOperator(mOperator); + new_e.setOperator(mOperator, null); // Et la mettre en condition de ternaire LeekTernaire ternaire = new LeekTernaire(); ternaire.addExpression(new_e); - ternaire.addOperator(Operators.TERNAIRE); + ternaire.addOperator(Operators.TERNAIRE, null); ternaire.setParent(this); mExpression1 = ternaire; mExpression2 = null; @@ -232,12 +261,12 @@ else if (mExpression2.getType() != EXPRESSION) { // On doit englober l'expression de droite LeekTernaire ternaire = new LeekTernaire(); ternaire.addExpression(mExpression2); - ternaire.addOperator(Operators.TERNAIRE); + ternaire.addOperator(Operators.TERNAIRE, null); ternaire.setParent(this); mExpression2 = ternaire; } else - ((LeekExpression) mExpression2).addOperator(operator); + ((LeekExpression) mExpression2).addOperator(operator, null); } } @@ -254,7 +283,7 @@ else if (mExpression2 == base) { } } - public void addOperator(int operator) { + public void addOperator(int operator, IAWord token) { // On doit trouver à quel endroit de l'arborescence on doit placer // l'opérateur /* @@ -266,7 +295,7 @@ public void addOperator(int operator) { * mExpression1).addOperator(operator); } else */ if (mExpression1 != null && mExpression1.getType() == EXPRESSION && !((LeekExpression) mExpression1).complete(operator)) { - ((LeekExpression) mExpression1).addOperator(operator); + ((LeekExpression) mExpression1).addOperator(operator, token); } else if (mOperator == -1) { if (operator == Operators.TERNAIRE) { @@ -274,7 +303,7 @@ else if (mOperator == -1) { if (mExpression1.getType() == EXPRESSION) ((LeekExpression) mExpression1).setParent(trn); trn.addExpression(mExpression1); - trn.addOperator(operator); + trn.addOperator(operator, token); if (mParent != null) mParent.replaceExpression(this, trn); else { @@ -294,13 +323,13 @@ else if (mOperator == -1) { new_e.setParent(this); new_e.setExpression1(mExpression1); new_e.setExpression2(mExpression2); - new_e.setOperator(mOperator); + new_e.setOperator(mOperator, token); if (operator == Operators.TERNAIRE) { LeekTernaire trn = new LeekTernaire(); if (mExpression1.getType() == EXPRESSION) ((LeekExpression) mExpression1).setParent(trn); trn.addExpression(new_e); - trn.addOperator(operator); + trn.addOperator(operator, token); if (mParent != null) mParent.replaceExpression(this, trn); else { @@ -322,19 +351,19 @@ else if (mExpression2.getType() != EXPRESSION) { LeekTernaire trn = new LeekTernaire(); trn.setParent(this); trn.addExpression(mExpression2); - trn.addOperator(operator); + trn.addOperator(operator, token); mExpression2 = trn; } else { LeekExpression new_e = new LeekExpression(); new_e.setParent(this); new_e.setExpression1(mExpression2); - new_e.setOperator(operator); + new_e.setOperator(operator, token); mExpression2 = new_e; } } else - ((LeekExpression) mExpression2).addOperator(operator); + ((LeekExpression) mExpression2).addOperator(operator, token); } } @@ -367,7 +396,7 @@ public AbstractExpression getAbstractExpression() { } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { if (mExpression1 instanceof LeekExpression) mExpression1 = ((LeekExpression) mExpression1).getAbstractExpression(); if (mExpression2 instanceof LeekExpression) @@ -379,8 +408,9 @@ public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionExc // on doit vérifier qu'on a bien une variable (l-value) if (mOperator == Operators.ADDASSIGN || mOperator == Operators.MINUSASSIGN || mOperator == Operators.DIVIDEASSIGN || mOperator == Operators.ASSIGN || mOperator == Operators.MODULUSASSIGN || mOperator == Operators.MULTIPLIEASSIGN || mOperator == Operators.POWERASSIGN) { - if (!(mExpression1 instanceof LeekFunctionValue) && !(mExpression1 instanceof LeekVariable) && !(mExpression1 instanceof LeekGlobal) && !(mExpression1 instanceof LeekTabularValue)) - throw new LeekExpressionException(mExpression1, LeekCompilerException.CANT_ASSIGN_VALUE); + if (!mExpression1.isLeftValue()) + compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.CANT_ASSIGN_VALUE)); + // throw new LeekExpressionException(mExpression1, LeekCompilerException.CANT_ASSIGN_VALUE); if (mExpression1 instanceof LeekFunctionValue) mainblock.addRedefinedFunction(((LeekFunctionValue) mExpression1).getFunctionName()); if (mExpression1 instanceof LeekTabularValue) @@ -388,14 +418,15 @@ public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionExc } if (mOperator == Operators.INCREMENT || mOperator == Operators.DECREMENT || mOperator == Operators.PRE_INCREMENT || mOperator == Operators.PRE_DECREMENT) { if (!(mExpression2 instanceof LeekFunctionValue) && !(mExpression2 instanceof LeekVariable) && !(mExpression2 instanceof LeekGlobal) && !(mExpression2 instanceof LeekTabularValue)) - throw new LeekExpressionException(mExpression2, LeekCompilerException.CANT_ASSIGN_VALUE); + compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.CANT_ASSIGN_VALUE)); + // throw new LeekExpressionException(mExpression2, LeekCompilerException.CANT_ASSIGN_VALUE); if (mExpression2 instanceof LeekFunctionValue) mainblock.addRedefinedFunction(((LeekFunctionValue) mExpression2).getFunctionName()); if (mExpression2 instanceof LeekTabularValue) ((LeekTabularValue) mExpression2).setLeftValue(true); } - return mExpression1.validExpression(mainblock) && mExpression2.validExpression(mainblock); + return mExpression1.validExpression(compiler, mainblock) && mExpression2.validExpression(compiler, mainblock); } @Override @@ -693,4 +724,10 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } return; } + + @Override + public void analyze(WordCompiler compiler) { + if (mExpression1 != null) mExpression1.analyze(compiler); + if (mExpression2 != null) mExpression2.analyze(compiler); + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 66a4c4aa..c12f7564 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -3,15 +3,17 @@ import java.util.ArrayList; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; +import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.runner.LeekFunctions; public class LeekExpressionFunction extends AbstractExpression { private final ArrayList mParameters = new ArrayList(); private AbstractExpression mExpression = null; - public LeekExpressionFunction() { - } + public LeekExpressionFunction() {} public void setExpression(AbstractExpression expression) { mExpression = expression; @@ -37,25 +39,50 @@ public String getString() { } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { - if(mExpression == null || !mExpression.validExpression(mainblock)) return false; + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { + if(mExpression == null || !mExpression.validExpression(compiler, mainblock)) return false; //Vérification de chaque paramètre for(AbstractExpression parameter : mParameters){ - parameter.validExpression(mainblock); + parameter.validExpression(compiler, mainblock); } return true; } @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - mExpression.writeJavaCode(mainblock, writer); - writer.addCode(".executeFunction(mUAI, new AbstractLeekValue[]{"); - for(int i = 0; i < mParameters.size(); i++){ - if(i > 0) writer.addCode(", "); - if(i < mParameters.size()) mParameters.get(i).writeJavaCode(mainblock, writer); - else writer.addCode("LeekValueManager.NULL"); + boolean addComma = true; + if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.SYSTEM_FUNCTION) { + var variable = (LeekVariable) mExpression; + String namespace = LeekFunctions.getNamespace(variable.getName()); + writer.addCode("LeekValueManager.getFunction(" + namespace + "." + variable.getName() + ")"); + writer.addCode(".executeFunction(mUAI"); + } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.FUNCTION) { + writer.addCode("user_function_"); + writer.addCode(((LeekVariable) mExpression).getName()); + writer.addCode("("); + addComma = false; + } else { + mExpression.writeJavaCode(mainblock, writer); + writer.addCode(".executeFunction(mUAI"); + } + for (int i = 0; i < mParameters.size(); i++) { + if (i > 0 || addComma) writer.addCode(", "); + if (i < mParameters.size()) { + mParameters.get(i).writeJavaCode(mainblock, writer); + writer.addCode(".getValue()"); + } else { + writer.addCode("LeekValueManager.NULL"); + } + } + writer.addCode(")"); + } + + @Override + public void analyze(WordCompiler compiler) { + mExpression.analyze(compiler); + for (AbstractExpression parameter : mParameters) { + parameter.analyze(compiler); } - writer.addCode("})"); } } diff --git a/src/main/java/leekscript/compiler/expression/LeekFunction.java b/src/main/java/leekscript/compiler/expression/LeekFunction.java index 17a9dcf2..3155ec14 100644 --- a/src/main/java/leekscript/compiler/expression/LeekFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekFunction.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.FunctionBlock; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.exceptions.LeekCompilerException; @@ -11,11 +12,13 @@ public class LeekFunction extends AbstractExpression { + private final boolean isClass; private final String mName; private final ArrayList mParameters = new ArrayList(); - public LeekFunction(String name) { + public LeekFunction(String name, boolean isClass) { mName = name; + this.isClass = isClass; } public void addParameter(AbstractExpression param) { @@ -39,30 +42,43 @@ public String getString() { } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { - int nb_params = LeekFunctions.isFunction(mName); - if (nb_params == -1) { - nb_params = mainblock.getUserFunctionParametersCount(mName); - if (nb_params == -1) - throw new LeekExpressionException(this, LeekCompilerException.FUNCTION_NOT_EXISTS); - if (mParameters.size() != nb_params) - throw new LeekExpressionException(this, LeekCompilerException.INVALID_PAREMETER_COUNT); - } - else { - ILeekFunction f = LeekFunctions.getValue(mName); - if (mParameters.size() > nb_params || mParameters.size() < f.getArgumentsMin()) - throw new LeekExpressionException(this, LeekCompilerException.INVALID_PAREMETER_COUNT); + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { + if (!isClass) { + int nb_params = LeekFunctions.isFunction(mName); + if (nb_params == -1) { + nb_params = mainblock.getUserFunctionParametersCount(mName); + if (nb_params == -1) { + throw new LeekExpressionException(this, LeekCompilerException.FUNCTION_NOT_EXISTS); + } else if (mParameters.size() != nb_params) { + throw new LeekExpressionException(this, LeekCompilerException.INVALID_PAREMETER_COUNT); + } + } + else { + ILeekFunction f = LeekFunctions.getValue(mName); + if (mParameters.size() > nb_params || mParameters.size() < f.getArgumentsMin()) + throw new LeekExpressionException(this, LeekCompilerException.INVALID_PAREMETER_COUNT); + } } // Vérification de chaque paramètre for (AbstractExpression parameter : mParameters) { - parameter.validExpression(mainblock); + parameter.validExpression(compiler, mainblock); } return true; } @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { + if (isClass) { + writer.addCode("user_" + mName + ".executeFunction(mUAI, new AbstractLeekValue[] {"); + for (int i = 0; i < mParameters.size(); i++) { + if (i > 0) + writer.addCode(", "); + mParameters.get(i).writeJavaCode(mainblock, writer); + } + writer.addCode("})"); + return; + } if (mainblock.isRedefinedFunction(mName)) { writer.addCode("rfunction_" + mName); writer.addCode(".executeFunction(mUAI, new AbstractLeekValue[]{"); @@ -116,4 +132,9 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } } } + + @Override + public void analyze(WordCompiler compiler) { + + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekFunctionValue.java b/src/main/java/leekscript/compiler/expression/LeekFunctionValue.java index 2a816ddc..a4dfa82d 100644 --- a/src/main/java/leekscript/compiler/expression/LeekFunctionValue.java +++ b/src/main/java/leekscript/compiler/expression/LeekFunctionValue.java @@ -1,6 +1,7 @@ package leekscript.compiler.expression; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.FunctionBlock; import leekscript.compiler.bloc.MainLeekBlock; @@ -26,24 +27,22 @@ public String getString() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - //return "Fonction[" + mFunctionName + "]"; - //FunctionLeekValue - if(mainblock.isRedefinedFunction(mFunctionName)){ + // return "Fonction[" + mFunctionName + "]"; + // FunctionLeekValue + if (mainblock.isRedefinedFunction(mFunctionName)) { writer.addCode("rfunction_" + mFunctionName); - } - else{ + } else { FunctionBlock user_function = mainblock.getUserFunction(mFunctionName); - if(user_function != null){ + if (user_function != null) { writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); - } - else{ + } else { writer.addCode("LeekValueManager.getFunction(" + mFunctionNamespace + "." + mFunctionName + ")"); } } } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { return true; } @@ -51,4 +50,8 @@ public String getFunctionName() { return mFunctionName; } + @Override + public void analyze(WordCompiler compiler) { + + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekGlobal.java b/src/main/java/leekscript/compiler/expression/LeekGlobal.java index dec196ca..c5b6bb00 100644 --- a/src/main/java/leekscript/compiler/expression/LeekGlobal.java +++ b/src/main/java/leekscript/compiler/expression/LeekGlobal.java @@ -1,14 +1,16 @@ package leekscript.compiler.expression; +import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; public class LeekGlobal extends AbstractExpression { - private final String mVariable; + private final IAWord token; - public LeekGlobal(String variable) { - mVariable = variable; + public LeekGlobal(IAWord token) { + this.token = token; } @Override @@ -18,18 +20,27 @@ public int getType() { @Override public String getString() { - return mVariable; + return token.getWord(); } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { - //Pour une globale, la vérification est faite avant l'ajout donc pas besoin de refaire + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { + // Pour une globale, la vérification est faite avant l'ajout donc pas besoin de refaire return true; } @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addCode("(globale_" + mVariable + "==null?LeekValueManager.NULL:globale_" + mVariable + ")"); + writer.addCode("(globale_" + token.getWord() + "==null?LeekValueManager.NULL:globale_" + token.getWord() + ")"); } + @Override + public boolean isLeftValue() { + return true; + } + + @Override + public void analyze(WordCompiler compiler) { + + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekNull.java b/src/main/java/leekscript/compiler/expression/LeekNull.java index 1444915a..44e13f97 100644 --- a/src/main/java/leekscript/compiler/expression/LeekNull.java +++ b/src/main/java/leekscript/compiler/expression/LeekNull.java @@ -1,6 +1,7 @@ package leekscript.compiler.expression; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; public class LeekNull extends AbstractExpression { @@ -16,7 +17,7 @@ public String getString() { } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { //Pour une valeur null pas de soucis return true; } @@ -26,4 +27,8 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("LeekValueManager.NULL"); } + @Override + public void analyze(WordCompiler compiler) { + + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekNumber.java b/src/main/java/leekscript/compiler/expression/LeekNumber.java index bd150249..29f09e38 100644 --- a/src/main/java/leekscript/compiler/expression/LeekNumber.java +++ b/src/main/java/leekscript/compiler/expression/LeekNumber.java @@ -1,6 +1,7 @@ package leekscript.compiler.expression; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; public class LeekNumber extends AbstractExpression { @@ -22,7 +23,7 @@ public String getString() { } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { //Pour un nombre pas de soucis return true; } @@ -37,4 +38,8 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } } + @Override + public void analyze(WordCompiler compiler) { + + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java new file mode 100644 index 00000000..6c2a055d --- /dev/null +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -0,0 +1,75 @@ +package leekscript.compiler.expression; + +import leekscript.compiler.AnalyzeError; +import leekscript.compiler.IAWord; +import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; +import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; +import leekscript.compiler.bloc.MainLeekBlock; +import leekscript.compiler.exceptions.LeekCompilerException; +import leekscript.compiler.expression.LeekVariable.VariableType; + +public class LeekObjectAccess extends AbstractExpression { + + private AbstractExpression object; + private IAWord field; + + public LeekObjectAccess(AbstractExpression object, IAWord field) { + this.object = object; + this.field = field; + } + + @Override + public int getType() { + return OBJECT_ACCESS; + } + + @Override + public String getString() { + return ""; + } + + public AbstractExpression getObject() { + return object; + } + + @Override + public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { + object.writeJavaCode(mainblock, writer); + writer.addCode(".getField(mUAI, \"" + field.getWord() + "\")"); + } + + @Override + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { + + return true; + } + + @Override + public boolean isLeftValue() { + return true; + } + + @Override + public void analyze(WordCompiler compiler) { + object.analyze(compiler); + if (object instanceof LeekVariable) { + var v = (LeekVariable) object; + if (v.getName().equals("this")) { + // this, check field exists in class + var clazz = compiler.getCurrentClass(); + if (clazz != null && !clazz.hasMember(field)) { + compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, LeekCompilerException.CLASS_MEMBER_DOES_NOT_EXIST)); + } + } else if (v.getVariableType() == VariableType.CLASS && v.getClassDeclaration() != null) { + if (!v.getClassDeclaration().hasStaticMember(field)) { + compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, LeekCompilerException.CLASS_STATIC_MEMBER_DOES_NOT_EXIST, new String[] { v.getClassDeclaration().getName(), field.getWord() })); + } + } + } + } + + public String getField() { + return field.getWord(); + } +} diff --git a/src/main/java/leekscript/compiler/expression/LeekParenthesis.java b/src/main/java/leekscript/compiler/expression/LeekParenthesis.java index cf71a58a..e3fed26b 100644 --- a/src/main/java/leekscript/compiler/expression/LeekParenthesis.java +++ b/src/main/java/leekscript/compiler/expression/LeekParenthesis.java @@ -1,6 +1,7 @@ package leekscript.compiler.expression; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; public class LeekParenthesis extends AbstractExpression { @@ -32,8 +33,12 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { - return mExpression.validExpression(mainblock); + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { + return mExpression.validExpression(compiler, mainblock); } + @Override + public void analyze(WordCompiler compiler) { + mExpression.analyze(compiler); + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekString.java b/src/main/java/leekscript/compiler/expression/LeekString.java index c62fe133..7c124b7e 100644 --- a/src/main/java/leekscript/compiler/expression/LeekString.java +++ b/src/main/java/leekscript/compiler/expression/LeekString.java @@ -1,6 +1,7 @@ package leekscript.compiler.expression; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; public class LeekString extends AbstractExpression { @@ -22,7 +23,7 @@ public String getString() { } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { //Pour une chaine de caractères pas de problèmes return true; } @@ -50,4 +51,9 @@ else if (mString.charAt(i) == '\\') { } writer.addCode("new StringLeekValue(\"" + str + "\")"); } + + @Override + public void analyze(WordCompiler compiler) { + + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekTabularValue.java b/src/main/java/leekscript/compiler/expression/LeekTabularValue.java index 64449081..f0ec2c30 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTabularValue.java +++ b/src/main/java/leekscript/compiler/expression/LeekTabularValue.java @@ -1,6 +1,7 @@ package leekscript.compiler.expression; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; public class LeekTabularValue extends AbstractExpression { @@ -36,15 +37,15 @@ public String getString() { } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { //On doit vérifier qu'on a affaire : soit à une expression tabulaire, soit à une variable, soit à une globale if(!(mTabular instanceof LeekVariable) && !(mTabular instanceof LeekGlobal) && !(mTabular instanceof LeekTabularValue)){ //throw new LeekExpressionException(this, "Ce n'est pas un tableau valide"); mLeftValue = false; } //Sinon on valide simplement les deux expressions - mTabular.validExpression(mainblock); - mCase.validExpression(mainblock); + mTabular.validExpression(compiler, mainblock); + mCase.validExpression(compiler, mainblock); return true; } @@ -68,4 +69,14 @@ public void setLeftValue(boolean b) { mLeftValue = b; } + @Override + public boolean isLeftValue() { + return true; + } + + @Override + public void analyze(WordCompiler compiler) { + mTabular.analyze(compiler); + mCase.analyze(compiler); + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekTernaire.java b/src/main/java/leekscript/compiler/expression/LeekTernaire.java index 8682eb30..83ac6ca2 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTernaire.java +++ b/src/main/java/leekscript/compiler/expression/LeekTernaire.java @@ -1,6 +1,8 @@ package leekscript.compiler.expression; +import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.exceptions.LeekCompilerException; @@ -86,9 +88,9 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { if(!complete()) throw new LeekExpressionException(this, LeekCompilerException.UNCOMPLETE_EXPRESSION); - if(!(mCondition.validExpression(mainblock) && mExpression1.validExpression(mainblock) && mExpression2.validExpression(mainblock))) throw new LeekExpressionException(this, LeekCompilerException.UNCOMPLETE_EXPRESSION); + if(!(mCondition.validExpression(compiler, mainblock) && mExpression1.validExpression(compiler, mainblock) && mExpression2.validExpression(compiler, mainblock))) throw new LeekExpressionException(this, LeekCompilerException.UNCOMPLETE_EXPRESSION); return true; } @@ -110,40 +112,40 @@ else if(mOperator == 2){ } @Override - public void addUnarySuffix(int suffix) { + public void addUnarySuffix(int suffix, IAWord token) { //On doit ajouter ce suffix au dernier élément ajouté if(mCondition != null && mExpression1 == null && mExpression2 == null){ - if(mCondition.getType() == EXPRESSION) ((LeekExpression) mCondition).addUnarySuffix(suffix); + if(mCondition.getType() == EXPRESSION) ((LeekExpression) mCondition).addUnarySuffix(suffix, token); else{ //On doit ajouter à l'élément mExpression1 LeekExpression exp = new LeekExpression(); exp.setParent(this); exp.setExpression1(new LeekNull()); - exp.setOperator(suffix); + exp.setOperator(suffix, token); exp.setExpression2(mCondition); mCondition = exp; } } else if(mExpression1 != null && mExpression2 == null){ - if(mExpression1.getType() == EXPRESSION) ((LeekExpression) mExpression1).addUnarySuffix(suffix); + if(mExpression1.getType() == EXPRESSION) ((LeekExpression) mExpression1).addUnarySuffix(suffix, token); else{ //On doit ajouter à l'élément mExpression1 LeekExpression exp = new LeekExpression(); exp.setParent(this); exp.setExpression1(new LeekNull()); - exp.setOperator(suffix); + exp.setOperator(suffix, token); exp.setExpression2(mExpression1); mExpression1 = exp; } } else if(mExpression2 != null){ - if(mExpression2.getType() == EXPRESSION) ((LeekExpression) mExpression2).addUnarySuffix(suffix); + if(mExpression2.getType() == EXPRESSION) ((LeekExpression) mExpression2).addUnarySuffix(suffix, token); else{ //On doit ajouter à l'élément mExpression2 LeekExpression exp = new LeekExpression(); exp.setParent(this); exp.setExpression1(new LeekNull()); - exp.setOperator(suffix); + exp.setOperator(suffix, token); exp.setExpression2(mExpression2); mExpression2 = exp; } @@ -166,64 +168,71 @@ public boolean complete() { } @Override - public void addOperator(int operator) { + public void addOperator(int operator, IAWord token) { //On doit trouver à quel endroit de l'arborescence on doit placer l'opérateur if(mOperator == 0 && operator == Operators.TERNAIRE){ mOperator = 1; } - else if(mExpression1.getType() == EXPRESSION && !((LeekExpression) mExpression1).complete()) ((LeekExpression) mExpression1).addOperator(operator); + else if(mExpression1.getType() == EXPRESSION && !((LeekExpression) mExpression1).complete()) ((LeekExpression) mExpression1).addOperator(operator, token); else if(mOperator == 1 && operator == Operators.DOUBLE_POINT){ mOperator = 2; } else{ if(mOperator == 0){ - if(mCondition.getType() == EXPRESSION) ((LeekExpression) mCondition).addOperator(operator); + if(mCondition.getType() == EXPRESSION) ((LeekExpression) mCondition).addOperator(operator, token); else{ LeekExpression new_e = new LeekExpression(); new_e.setParent(this); new_e.setExpression1(mCondition); - new_e.setOperator(operator); + new_e.setOperator(operator, token); mCondition = new_e; } } else if(mOperator == 1){ - if(mExpression1.getType() == EXPRESSION) ((LeekExpression) mExpression1).addOperator(operator); + if(mExpression1.getType() == EXPRESSION) ((LeekExpression) mExpression1).addOperator(operator, token); else{ if(operator == Operators.TERNAIRE){ LeekTernaire new_e = new LeekTernaire(); new_e.setParent(this); new_e.addExpression(mExpression1); - new_e.addOperator(operator); + new_e.addOperator(operator, token); mExpression1 = new_e; } else{ LeekExpression new_e = new LeekExpression(); new_e.setParent(this); new_e.setExpression1(mExpression1); - new_e.setOperator(operator); + new_e.setOperator(operator, token); mExpression1 = new_e; } } } else{ - if(mExpression2.getType() == EXPRESSION) ((LeekExpression) mExpression2).addOperator(operator); + if(mExpression2.getType() == EXPRESSION) ((LeekExpression) mExpression2).addOperator(operator, token); else{ if(operator == Operators.TERNAIRE){ LeekTernaire new_e = new LeekTernaire(); new_e.setParent(this); new_e.addExpression(mExpression2); - new_e.addOperator(operator); + new_e.addOperator(operator, token); mExpression2 = new_e; } else{ LeekExpression new_e = new LeekExpression(); new_e.setParent(this); new_e.setExpression1(mExpression2); - new_e.setOperator(operator); + new_e.setOperator(operator, token); mExpression2 = new_e; } } } } } + + @Override + public void analyze(WordCompiler compiler) { + if (mCondition != null) mCondition.analyze(compiler); + if (mExpression1 != null) mExpression1.analyze(compiler); + if (mExpression2 != null) mExpression2.analyze(compiler); + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index 1982911f..f4c32119 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -1,14 +1,27 @@ package leekscript.compiler.expression; +import leekscript.compiler.AnalyzeError; +import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; +import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; +import leekscript.compiler.bloc.FunctionBlock; import leekscript.compiler.bloc.MainLeekBlock; +import leekscript.compiler.exceptions.LeekCompilerException; +import leekscript.runner.LeekFunctions; public class LeekVariable extends AbstractExpression { - private final String mVariable; + public static enum VariableType { + LOCAL, GLOBAL, ARGUMENT, FIELD, STATIC_FIELD, THIS, THIS_CLASS, CLASS, SUPER, METHOD, STATIC_METHOD, SYSTEM_FUNCTION, FUNCTION + } + + private final IAWord token; + private VariableType type; - public LeekVariable(String variable) { - mVariable = variable; + public LeekVariable(IAWord token, VariableType type) { + this.token = token; + this.type = type; } @Override @@ -18,16 +31,67 @@ public int getType() { @Override public String getString() { - return mVariable; + return token.getWord(); } @Override - public boolean validExpression(MainLeekBlock mainblock) throws LeekExpressionException { + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { return true; } @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addCode("user_" + mVariable); + if (type == VariableType.FUNCTION) { + FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); + writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); + } else if (type == VariableType.SYSTEM_FUNCTION) { + if (mainblock.isRedefinedFunction(token.getWord())) { + writer.addCode("rfunction_" + token.getWord()); + } else { + FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); + if (user_function != null) { + writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); + } else { + String namespace = LeekFunctions.getNamespace(token.getWord()); + writer.addCode("LeekValueManager.getFunction(" + namespace + "." + token.getWord() + ")"); + } + } + } else { + writer.addCode("user_" + token.getWord()); + } + } + + @Override + public boolean isLeftValue() { + return true; + } + + public VariableType getVariableType() { + return type; + } + + public String getName() { + return token.getWord(); + } + + @Override + public void analyze(WordCompiler compiler) { + if (this.type == VariableType.SUPER) { + return; // Déjà OK + } + if (compiler.getMainBlock().hasUserFunction(token.getWord(), true)) { + this.type = VariableType.FUNCTION; + return; + } + var v = compiler.getCurrentBlock().getVariable(token.getWord(), true); + if (v != null) { + this.type = v.getVariableType(); + return; + } + if (LeekFunctions.isFunction(token.getWord()) != -1) { + this.type = VariableType.SYSTEM_FUNCTION; + return; + } + compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.UNKNOWN_VARIABLE_OR_FUNCTION)); } } diff --git a/src/main/java/leekscript/compiler/instruction/BlankInstruction.java b/src/main/java/leekscript/compiler/instruction/BlankInstruction.java index b60e0d15..bce69693 100644 --- a/src/main/java/leekscript/compiler/instruction/BlankInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/BlankInstruction.java @@ -1,6 +1,7 @@ package leekscript.compiler.instruction; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; public class BlankInstruction implements LeekInstruction { @@ -24,4 +25,8 @@ public boolean putCounterBefore() { return false; } + @Override + public void analyze(WordCompiler compiler) { + + } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekBreakInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekBreakInstruction.java index 5d1e66ad..1d412039 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekBreakInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekBreakInstruction.java @@ -2,6 +2,7 @@ import leekscript.compiler.AIFile; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; public class LeekBreakInstruction implements LeekInstruction { @@ -36,4 +37,9 @@ public int getEndBlock() { public boolean putCounterBefore() { return true; } + + @Override + public void analyze(WordCompiler compiler) { + + } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekContinueInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekContinueInstruction.java index 4f8321d1..8d8973cd 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekContinueInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekContinueInstruction.java @@ -2,6 +2,7 @@ import leekscript.compiler.AIFile; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; public class LeekContinueInstruction implements LeekInstruction { @@ -36,4 +37,9 @@ public int getEndBlock() { public boolean putCounterBefore() { return true; } + + @Override + public void analyze(WordCompiler compiler) { + + } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java index c4102adb..030291b8 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java @@ -2,6 +2,7 @@ import leekscript.compiler.AIFile; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekBoolean; @@ -53,4 +54,9 @@ public int getEndBlock() { public boolean putCounterBefore() { return false; } + + @Override + public void analyze(WordCompiler compiler) { + mExpression.analyze(compiler); + } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java index 0b765b20..4eede182 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java @@ -1,19 +1,21 @@ package leekscript.compiler.instruction; import leekscript.compiler.AIFile; +import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.AbstractExpression; public class LeekGlobalDeclarationInstruction implements LeekInstruction { - private final String mName; + private final IAWord token; private AbstractExpression mValue = null; private final int mLine; private final AIFile mAI; - public LeekGlobalDeclarationInstruction(String name, int line, AIFile ai) { - mName = name; + public LeekGlobalDeclarationInstruction(IAWord token, int line, AIFile ai) { + this.token = token; mLine = line; mAI = ai; } @@ -23,24 +25,24 @@ public void setValue(AbstractExpression value) { } public String getName() { - return mName; + return token.getWord(); } @Override public String getCode() { - return mName + " = " + mValue.getString(); + return token.getWord() + " = " + mValue.getString(); } @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addCode("if(globale_" + mName + " == null){globale_" + mName + " = new VariableLeekValue(mUAI, "); + writer.addCode("if(globale_" + token.getWord() + " == null){globale_" + token.getWord() + " = new VariableLeekValue(mUAI, "); if(mValue != null) mValue.writeJavaCode(mainblock, writer); else writer.addCode("LeekValueManager.NULL"); writer.addLine(");}", mLine, mAI); } public String getJavaDeclaration() { - return "private VariableLeekValue globale_" + mName + " = null;"; + return "private VariableLeekValue globale_" + token.getWord() + " = null;"; } @Override @@ -52,4 +54,16 @@ public int getEndBlock() { public boolean putCounterBefore() { return false; } + + @Override + public void analyze(WordCompiler compiler) { + // if (token.getWord().equals("COLOR_ORANGE")) { + // System.out.println("Add global " + token.getWord()); + // } + // compiler.getMainBlock().addGlobal(token.getWord()); + // compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.GLOBAL)); + if (mValue != null) { + mValue.analyze(compiler); + } + } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekInstruction.java index 41e5c67b..85da0980 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekInstruction.java @@ -1,6 +1,7 @@ package leekscript.compiler.instruction; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; public interface LeekInstruction { @@ -12,4 +13,6 @@ public interface LeekInstruction { public int getEndBlock(); public boolean putCounterBefore(); + + public void analyze(WordCompiler compiler); } diff --git a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java index 94aed65d..772d809f 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java @@ -2,6 +2,7 @@ import leekscript.compiler.AIFile; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.AbstractExpression; @@ -42,4 +43,11 @@ public int getEndBlock() { public boolean putCounterBefore() { return true; } + + @Override + public void analyze(WordCompiler compiler) { + if (mExpression != null) { + mExpression.analyze(compiler); + } + } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index b5bb2384..926e726d 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -1,20 +1,27 @@ package leekscript.compiler.instruction; import leekscript.compiler.AIFile; +import leekscript.compiler.AnalyzeError; +import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; +import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.MainLeekBlock; +import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.expression.AbstractExpression; +import leekscript.compiler.expression.LeekVariable; +import leekscript.compiler.expression.LeekVariable.VariableType; public class LeekVariableDeclarationInstruction implements LeekInstruction { - private final String mName; + private final IAWord token; private final int mLine; private final AIFile mAI; private AbstractExpression mValue = null; private boolean mMustSepare = false; - public LeekVariableDeclarationInstruction(String name, int line, AIFile ai) { - mName = name; + public LeekVariableDeclarationInstruction(IAWord token, int line, AIFile ai) { + this.token = token; mLine = line; mAI = ai; } @@ -28,25 +35,29 @@ public void setValue(AbstractExpression value) { } public String getName() { - return mName; + return token.getWord(); + } + + public IAWord getToken() { + return this.token; } @Override public String getCode() { - if(mValue == null) return "var " + mName; - return "var " + mName + " = " + mValue.getString(); + if(mValue == null) return "var " + token.getWord(); + return "var " + token.getWord() + " = " + mValue.getString(); } @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { if(!mMustSepare){ - writer.addCode("final VariableLeekValue user_" + mName + " = new VariableLeekValue(mUAI, "); + writer.addCode("final VariableLeekValue user_" + token.getWord() + " = new VariableLeekValue(mUAI, "); if(mValue != null) mValue.writeJavaCode(mainblock, writer); else writer.addCode("LeekValueManager.NULL"); writer.addLine(");", mLine, mAI); } else{ - writer.addCode("final VariableLeekValue user_" + mName + " = new VariableLeekValue(mUAI, LeekValueManager.NULL); user_" + mName + ".set(mUAI, "); + writer.addCode("final VariableLeekValue user_" + token.getWord() + " = new VariableLeekValue(mUAI, LeekValueManager.NULL); user_" + token.getWord() + ".set(mUAI, "); if(mValue != null) mValue.writeJavaCode(mainblock, writer); else writer.addCode("LeekValueManager.NULL"); writer.addLine(");", mLine, mAI); @@ -63,4 +74,20 @@ public boolean putCounterBefore() { return false; } + @Override + public void analyze(WordCompiler compiler) { + // Variables interdites + if (token.getWord().equals("this")) { + } else { + // On ajoute la variable + if (compiler.getMainBlock().hasGlobal(token.getWord()) || compiler.getMainBlock().hasUserFunction(token.getWord(), true) || compiler.getCurrentBlock().hasVariable(token.getWord())) { + compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); + } else { + compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.LOCAL)); + } + } + if (mValue != null) { + mValue.analyze(compiler); + } + } } diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index d74c675a..af59ffc8 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -6,6 +6,7 @@ import java.util.Iterator; import java.util.List; import java.util.Random; +import java.util.Set; import leekscript.compiler.LeekScript; import leekscript.runner.values.AbstractLeekValue; @@ -26,7 +27,7 @@ public class PhpArray implements Iterable { public final static int ASC_K = 6; public final static int DESC_K = 7; - private static int RAM_LIMIT = 1000000; + // private static int RAM_LIMIT = 1000000; private class ElementComparator implements Comparator { @@ -199,7 +200,7 @@ public void setValue(AI ai, AbstractLeekValue v) throws LeekRunException { // Calcul optimisé de la ram utilisée (Optimisé niveau UC, pas niveau RAM) private int mTotalSize = 0; - private PhpArrayVariableLeekValue mParent = null; + // private PhpArrayVariableLeekValue mParent = null; private Element[] mTable = null; @@ -823,7 +824,7 @@ private int getIndex(int hash) { return hash & (capacity - 1); } - public String toString(AI ai) throws LeekRunException { + public String toString(AI ai, Set visited) throws LeekRunException { ai.addOperations(1 + mSize * 2); @@ -849,7 +850,14 @@ public String toString(AI ai) throws LeekRunException { sb.append(", "); if (!isInOrder) sb.append(e.key).append(" : "); - sb.append(e.value.getString(ai)); + if (visited.contains(e.value.getValue())) { + sb.append("<...>"); + } else { + if (!e.value.getValue().isPrimitive()) { + visited.add(e.value.getValue()); + } + sb.append(e.value.getString(ai, visited)); + } e = e.next; } sb.append("]"); @@ -905,21 +913,21 @@ public boolean equals(AI ai, PhpArray array) throws LeekRunException { return true; } - public void setParent(PhpArrayVariableLeekValue parent) { - mParent = parent; - } + // public void setParent(PhpArrayVariableLeekValue parent) { + // mParent = parent; + // } public void updateArraySize(int delta) throws LeekRunException { if (delta == 0) { return; } mTotalSize += delta; - if (mTotalSize >= RAM_LIMIT) { - throw new LeekRunException(LeekRunException.OUT_OF_MEMORY); - } - if (mParent != null) { - mParent.updateSize(delta); - } + // if (mTotalSize >= RAM_LIMIT) { + // throw new LeekRunException(LeekRunException.OUT_OF_MEMORY); + // } + // if (mParent != null) { + // mParent.updateSize(delta); + // } } public int getSize() { diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 642b55ef..d84cfb14 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -1,5 +1,8 @@ package leekscript.runner.values; +import java.util.HashSet; +import java.util.Set; + import leekscript.runner.AI; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; @@ -34,7 +37,11 @@ public double getDouble(AI ai) throws LeekRunException { } public String getString(AI ai) throws LeekRunException { - return ""; + return getString(ai, new HashSet<>()); + } + + public String getString(AI ai, Set visited) throws LeekRunException { + return getString(ai); } public boolean getBoolean() { diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index c2f39335..1fe9c5ea 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -2,6 +2,7 @@ import java.util.Comparator; import java.util.Iterator; +import java.util.Set; import leekscript.runner.AI; import leekscript.runner.LeekOperations; @@ -230,8 +231,9 @@ public ArrayLeekValue getArray() { return this; } - public String getString(AI ai) throws LeekRunException { - return mValues.toString(ai); + public String getString(AI ai, Set visited) throws LeekRunException { + visited.add(this); + return mValues.toString(ai, visited); } @Override @@ -295,9 +297,9 @@ public void sort(AI ai, Comparator comparator) throws LeekRunE mValues.sort(ai, comparator); } - public void setParent(PhpArrayVariableLeekValue parent) { - mValues.setParent(parent); - } + // public void setParent(PhpArrayVariableLeekValue parent) { + // mValues.setParent(parent); + // } @Override public Object toJSON(AI ai) throws LeekRunException { diff --git a/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java b/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java index cd935b49..cffa226b 100644 --- a/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java @@ -6,37 +6,37 @@ public class PhpArrayVariableLeekValue extends VariableLeekValue { - private final PhpArray mArray; - private int mTotalSize = 0; + // private final PhpArray mArray; + // private int mTotalSize = 0; public PhpArrayVariableLeekValue(PhpArray array, AI uai, AbstractLeekValue value, int keySize) throws LeekRunException { super(uai, value.getValue()); - mArray = array; - mTotalSize = value.getSize(); - mArray.updateArraySize(mTotalSize + keySize); - if (mValue instanceof ArrayLeekValue) { - mValue.getArray().setParent(this); - } + // mArray = array; + // mTotalSize = value.getSize(); + // mArray.updateArraySize(mTotalSize + keySize); + // if (mValue instanceof ArrayLeekValue) { + // mValue.getArray().setParent(this); + // } } @Override public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunException { value = value.getValue(); - int size = value.getSize(); - mArray.updateArraySize(size - mTotalSize); - mTotalSize = size; + // int size = value.getSize(); + // mArray.updateArraySize(size - mTotalSize); + // mTotalSize = size; super.set(ai, value); - if (mValue instanceof ArrayLeekValue) - mValue.getArray().setParent(this); + // if (mValue instanceof ArrayLeekValue) + // mValue.getArray().setParent(this); return mValue; } public void removeFromTable(int keySize) throws LeekRunException { - mArray.updateArraySize(-mTotalSize - keySize); + // mArray.updateArraySize(-mTotalSize - keySize); } public void updateSize(int delta) throws LeekRunException { - mTotalSize += delta; - mArray.updateArraySize(delta); + // mTotalSize += delta; + // mArray.updateArraySize(delta); } } diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index 118fa5c1..ee3d358a 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -1,5 +1,7 @@ package leekscript.runner.values; +import java.util.Set; + import leekscript.runner.AI; import leekscript.runner.LeekOperations; import leekscript.runner.LeekRunException; @@ -42,8 +44,8 @@ public double getDouble(AI ai) throws LeekRunException { } @Override - public String getString(AI ai) throws LeekRunException { - return mValue.getString(ai); + public String getString(AI ai, Set visited) throws LeekRunException { + return mValue.getString(ai, visited); } @Override From 378122040912ddeb4659ded687b2c826b789c77f Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 15 Feb 2021 19:27:52 +0100 Subject: [PATCH 076/319] [class] Handle dot --- .../java/leekscript/compiler/WordParser.java | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index 6b8e792c..112548e9 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -2,6 +2,7 @@ import java.util.ArrayList; +import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.exceptions.LeekCompilerException; public class WordParser { @@ -28,7 +29,6 @@ public class WordParser { public final static int T_PAR_RIGHT = 7; public final static int T_VIRG = 8; public final static int T_CONDITION_OPERATOR = 9; - public final static int T_DOUBLE_POINT = 14; public final static int T_ACCOLADE_LEFT = 10; public final static int T_ACCOLADE_RIGHT = 11; @@ -36,6 +36,9 @@ public class WordParser { public final static int T_BRACKET_LEFT = 12; public final static int T_BRACKET_RIGHT = 13; + public final static int T_DOUBLE_POINT = 14; + public final static int T_DOT = 15; + private final AIFile mAI; private final ArrayList words = new ArrayList(); @@ -167,11 +170,19 @@ else if(c == '.'){ if(type == T_NUMBER || type == T_VAR_STRING){ word += c; } - else{ - throw new LeekCompilerException(mAI, line_counter, char_counter, word, LeekCompilerException.INVALID_CHAR); + else if (version >= 11) { + if (type == T_STRING) { + newWord(word, type); + } + newWord(".", T_DOT); + word = ""; + type = T_NOTHING; + } else { + compiler.addError(new AnalyzeError(new IAWord(mAI, 0, ".", line_counter, char_counter + 1), AnalyzeErrorLevel.ERROR, LeekCompilerException.INVALID_CHAR)); + // throw new LeekCompilerException(mAI, line_counter, char_counter + 1, ".", LeekCompilerException.INVALID_CHAR); } } - else if(c == '@' || c == '+' || c == '=' || c == '<' || c == '>' || c == '|' || c == '&' || c == '-' || c == '/' || c == '*' || c == '%' || c == '!' || c == '?' || c == '^' || c == '~'){ + else if(c == '@' || c == '+' || c == '=' || c == '<' || c == '>' || c == '|' || c == '&' || c == '-' || c == '/' || c == '*' || c == '%' || c == '!' || c == '?' || c == '^' || c == '~' || c == '.'){ if(type == T_VAR_STRING){ word += c; } @@ -332,12 +343,10 @@ else if(c == ','){ if(type != T_NOTHING){ newWord(word, type); } - /* - * for(int i=0;i "+words.get(i).getWord( - * )); - * } - */ + + // for(int i=0;i "+words.get(i).getWord()); + // } } private void newWord(String word, int type) { @@ -388,6 +397,10 @@ public void skipWord() { cursor++; } + public void back() { + cursor--; + } + public boolean haveWords() { return cursor < words.size(); } @@ -404,4 +417,11 @@ public int getInstructionCount() { return instructions; } + public int getPosition() { + return cursor; + } + + public void setPosition(int position) { + this.cursor = position; + } } From 530a75db05a876727d2662d576a258237e7fdad7 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 15 Feb 2021 22:42:06 +0100 Subject: [PATCH 077/319] [runner] Implement classes --- src/main/java/leekscript/AILog.java | 4 + .../leekscript/runner/LeekOperations.java | 6 + .../runner/values/AbstractLeekValue.java | 10 + .../runner/values/ClassLeekValue.java | 196 ++++++++++++++++++ .../runner/values/FunctionLeekValue.java | 13 ++ .../runner/values/ObjectLeekValue.java | 148 +++++++++++++ .../runner/values/VariableLeekValue.java | 8 + 7 files changed, 385 insertions(+) create mode 100644 src/main/java/leekscript/runner/values/ClassLeekValue.java create mode 100644 src/main/java/leekscript/runner/values/ObjectLeekValue.java diff --git a/src/main/java/leekscript/AILog.java b/src/main/java/leekscript/AILog.java index 548388a0..3421dfaa 100644 --- a/src/main/java/leekscript/AILog.java +++ b/src/main/java/leekscript/AILog.java @@ -28,6 +28,10 @@ public class AILog { public static final String CODE_TOO_LARGE = "code_too_large"; public static final String CODE_TOO_LARGE_FUNCTION = "code_too_large_function"; public static final String NUMBER_OF_OPERATIONS = "number_of_operations"; + public static final String UNKNOWN_METHOD = "unknown_method"; + public static final String UNKNOWN_STATIC_METHOD = "unknown_static_method"; + public static final String STRING_METHOD_MUST_RETURN_STRING = "string_method_must_return_string"; + public static final String UNKNOWN_FIELD = "unknown_field"; public interface Stream { public void write(JSONArray a); diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index 8757fa3f..5bc098ac 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -5,9 +5,11 @@ import leekscript.runner.values.ArrayLeekValue; import leekscript.runner.values.ArrayLeekValue.ArrayIterator; import leekscript.runner.values.BooleanLeekValue; +import leekscript.runner.values.ClassLeekValue; import leekscript.runner.values.DoubleLeekValue; import leekscript.runner.values.FunctionLeekValue; import leekscript.runner.values.IntLeekValue; +import leekscript.runner.values.ObjectLeekValue; import leekscript.runner.values.StringLeekValue; public class LeekOperations { @@ -261,6 +263,10 @@ else if (value instanceof ArrayLeekValue) { ai.addOperations(value.getArray().size() * (ArrayLeekValue.ARRAY_CELL_CREATE_OPERATIONS)); } return new ArrayLeekValue(ai, value.getArray(), level); + } else if (value instanceof ObjectLeekValue) { + return value; + } else if (value instanceof ClassLeekValue) { + return value; } else return LeekValueManager.NULL; } diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index d84cfb14..7b3f277d 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -15,6 +15,8 @@ public abstract class AbstractLeekValue { public final static int NULL = 4; public final static int STRING = 5; public final static int FUNCTION = 6; + public final static int CLASS = 7; + public final static int OBJECT = 8; public final static int ADD_COST = 1; public final static int MUL_COST = 5; @@ -198,6 +200,14 @@ public AbstractLeekValue brotate(AI ai, AbstractLeekValue value) throws LeekRunE throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } + public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { + return LeekValueManager.NULL; + } + + public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + return LeekValueManager.NULL; + } + public abstract int getType(); public boolean isReference() { diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java new file mode 100644 index 00000000..242e5f51 --- /dev/null +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -0,0 +1,196 @@ +package leekscript.runner.values; + +import java.util.HashMap; +import java.util.Map.Entry; + +import leekscript.AILog; +import leekscript.runner.AI; +import leekscript.runner.LeekRunException; +import leekscript.runner.LeekValueManager; +import leekscript.runner.LeekAnonymousFunction; + +public class ClassLeekValue extends AbstractLeekValue { + + public String name; + public AbstractLeekValue parent; + public HashMap fields = new HashMap<>(); + public HashMap staticFields = new HashMap<>(); + public HashMap constructors = new HashMap<>(); + public HashMap methods = new HashMap<>(); + public HashMap genericMethods = new HashMap<>(); + public HashMap staticMethods = new HashMap<>(); + public HashMap genericStaticMethods = new HashMap<>(); + + private ArrayLeekValue fieldsArray; + private ArrayLeekValue methodsArray; + + public ClassLeekValue(String name) { + this.name = name; + this.parent = LeekValueManager.NULL; + } + + public void setParent(AbstractLeekValue parent) { + this.parent = parent; + } + + public void addConstructor(int arg_count, LeekAnonymousFunction function) { + constructors.put(arg_count, function); + } + + public void addField(AI ai, String field, AbstractLeekValue value) { + fields.put(field, value); + } + + public void addStaticField(AI ai, String field, AbstractLeekValue value) throws LeekRunException { + staticFields.put(field, new VariableLeekValue(ai, value)); + } + + public void addMethod(String method, int argCount, LeekAnonymousFunction function) { + methods.put(method + "_" + argCount, function); + } + + public void addGenericMethod(String method, LeekAnonymousFunction function) { + genericMethods.put(method, new FunctionLeekValue(function)); + } + + public void addStaticMethod(String method, int argCount, LeekAnonymousFunction function) { + staticMethods.put(method + "_" + argCount, function); + } + + public void addGenericStaticMethod(String method, LeekAnonymousFunction function) { + genericStaticMethods.put(method, new FunctionLeekValue(function)); + } + + @Override + public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { + AbstractLeekValue result = staticFields.get(field); + if (result == null) { + if (field.equals("fields")) { + return getFieldsArray(ai); + } else if (field.equals("methods")) { + return getMethodsArray(ai); + } else if (field.equals("parent")) { + return parent; + } + return LeekValueManager.NULL; + } + return result; + } + + @Override + public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + LeekAnonymousFunction result = staticMethods.get(method); + if (result == null) { + int underscore = method.lastIndexOf("_"); + int argCount = Integer.parseInt(method.substring(underscore + 1)); + String methodRealName = method.substring(0, underscore) + "("; + for (int i = 0; i < argCount; ++i) { + if (i > 0) methodRealName += ", "; + methodRealName += "x"; + } + methodRealName += ")"; + ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_STATIC_METHOD, new String[] { name, methodRealName }); + return LeekValueManager.NULL; + } + // Call method with new arguments, add the object at the beginning + return result.run(ai, null, arguments); + } + + /** + * Constructors + */ + @Override + public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... arguments) throws LeekRunException { + + // Create the actual object + ObjectLeekValue object = new ObjectLeekValue(this); + // Add fields + for (Entry field : fields.entrySet()) { + object.addField(ai, field.getKey(), field.getValue()); + } + + int arg_count = arguments.length; + if (constructors.containsKey(arg_count)) { + return constructors.get(arg_count).run(ai, object, arguments); + } else { + return object; + } + } + + private ArrayLeekValue getFieldsArray(AI ai) throws LeekRunException { + if (fieldsArray == null) { + AbstractLeekValue[] values = new AbstractLeekValue[fields.size()]; + int i = 0; + for (var f : fields.entrySet()) { + values[i++] = new StringLeekValue(f.getKey()); + } + fieldsArray = new ArrayLeekValue(ai, values); + } + return fieldsArray; + } + + private ArrayLeekValue getMethodsArray(AI ai) throws LeekRunException { + if (methodsArray == null) { + AbstractLeekValue[] values = new AbstractLeekValue[genericMethods.size()]; + int i = 0; + for (var f : genericMethods.entrySet()) { + values[i++] = new StringLeekValue(f.getKey()); + } + methodsArray = new ArrayLeekValue(ai, values); + } + return methodsArray; + } + + @Override + public int getSize() { + return 1; + } + + @Override + public boolean getBoolean() { + return true; + } + + @Override + public int getInt(AI ai) { + return 0; + } + + @Override + public double getDouble(AI ai) { + return 0; + } + + @Override + public boolean isNumeric() { + return false; + } + + @Override + public String getString(AI ai) { + return ""; + } + + @Override + public int getType() { + return CLASS; + } + + @Override + public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { + if (comp instanceof ClassLeekValue) { + return ((ClassLeekValue) comp).name.equals(this.name); + } + return false; + } + + @Override + public Object toJSON(AI ai) { + return name; + } + + @Override + public boolean isPrimitive() { + return false; + } +} diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index be8e3d46..5ba93c3a 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -1,5 +1,7 @@ package leekscript.runner.values; +import java.util.Arrays; + import leekscript.AILog; import leekscript.runner.AI; import leekscript.runner.ILeekFunction; @@ -14,6 +16,7 @@ public class FunctionLeekValue extends AbstractLeekValue { private final static int LEEK_FUNCTION = 1; private final static int USER_FUNCTION = 2; private final static int ANONYMOUS_FUNCTION = 3; + private final static int METHOD = 4; private final int mType; private final int mId; @@ -37,6 +40,12 @@ public FunctionLeekValue(ILeekFunction fonction) { mId = 0; } + public FunctionLeekValue(LeekAnonymousFunction fonction) { + mAnonymous = fonction; + mType = METHOD; + mId = 0; + } + @Override public boolean equals(AI ai, AbstractLeekValue comp) { if (comp.getType() != getType()) { @@ -131,6 +140,8 @@ else if (mType == ANONYMOUS_FUNCTION) { return mAnonymous.run(ai, null, copyValues(ai, values, ai.anonymousFunctionReference(mId))); } + } else if (mType == METHOD) { + return mAnonymous.run(ai, values[0], Arrays.copyOfRange(copyPrimitiveValues(ai, values), 1, values.length)); } return LeekValueManager.NULL; } @@ -141,6 +152,8 @@ public String getString(AI ai) { return "#Function " + mFunction; else if (mType == USER_FUNCTION) return "#User Function"; + else if (mType == METHOD) + return "#Method Function"; else return "#Anonymous Function"; } diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java new file mode 100644 index 00000000..dceb3baf --- /dev/null +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -0,0 +1,148 @@ +package leekscript.runner.values; + +import java.util.HashMap; +import java.util.Set; + +import leekscript.AILog; +import leekscript.runner.AI; +import leekscript.runner.LeekAnonymousFunction; +import leekscript.runner.LeekRunException; +import leekscript.runner.LeekValueManager; + +public class ObjectLeekValue extends AbstractLeekValue { + + public final ClassLeekValue clazz; + public final HashMap fields = new HashMap<>(); + + public ObjectLeekValue(ClassLeekValue clazz) { + this.clazz = clazz; + } + + public void addField(AI ai, String field, AbstractLeekValue value) throws LeekRunException { + fields.put(field, new VariableLeekValue(ai, value)); + } + + @Override + public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { + // System.out.println("getField " + field); + if (field.equals("class")) { + return clazz; + } + AbstractLeekValue result = fields.get(field); + if (result != null) { + return result; + } + var method = clazz.genericMethods.get(field); + if (method != null) { + return method; + } + ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_FIELD, new String[] { clazz.name, field }); + return LeekValueManager.NULL; + } + + @Override + public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunException { + return getField(ai, value.getString(ai)); + } + + @Override + public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + LeekAnonymousFunction result = clazz.methods.get(method); + if (result == null) { + int underscore = method.lastIndexOf("_"); + int argCount = Integer.parseInt(method.substring(underscore + 1)); + String methodRealName = method.substring(0, underscore) + "("; + for (int i = 0; i < argCount; ++i) { + if (i > 0) methodRealName += ", "; + methodRealName += "x"; + } + methodRealName += ")"; + ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_METHOD, new String[] { clazz.name, methodRealName }); + return LeekValueManager.NULL; + } + // Call method with new arguments, add the object at the beginning + return result.run(ai, this, arguments); + } + + @Override + public int getSize() { + return fields.size(); + } + + @Override + public boolean getBoolean() { + return fields.size() > 0; + } + + @Override + public int getInt(AI ai) { + return fields.size(); + } + + @Override + public double getDouble(AI ai) { + return fields.size(); + } + + @Override + public boolean isNumeric() { + return true; + } + + @Override + public String getString(AI ai, Set visited) throws LeekRunException { + visited.add(this); + + if (clazz.methods.containsKey("string_0")) { + var result = clazz.methods.get("string_0").run(ai, this, new AbstractLeekValue[] {}); + if (result.getType() != STRING) { + ai.addSystemLog(AILog.ERROR, AILog.STRING_METHOD_MUST_RETURN_STRING, new String[] { clazz.name }); + } else { + return result.getString(ai, visited); + } + } + + var sb = new StringBuilder(clazz.name + " {"); + boolean first = true; + for (HashMap.Entry field : fields.entrySet()) { + if (first) first = false; + else sb.append(", "); + sb.append(field.getKey()); + sb.append(": "); + if (visited.contains(field.getValue().getValue())) { + sb.append("<...>"); + } else { + if (!field.getValue().getValue().isPrimitive()) { + visited.add(field.getValue().getValue()); + } + sb.append(field.getValue().getValue().getString(ai, visited)); + } + } + sb.append("}"); + return sb.toString(); + } + + @Override + public int getType() { + return OBJECT; + } + + @Override + public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { + if (comp instanceof ObjectLeekValue) { + + } + return false; + } + + @Override + public Object toJSON(AI ai) { + return "object"; + } + + @Override + public boolean isPrimitive() { + return false; + } + +} diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index ee3d358a..6d6ab236 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -218,6 +218,14 @@ public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunExc return mValue = mValue.modulus(ai, val); } + public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { + return mValue.getField(ai, field); + } + + public AbstractLeekValue callMethod(AI ai, String field, AbstractLeekValue... arguments) throws LeekRunException { + return mValue.callMethod(ai, field, arguments); + } + @Override public int getType() { return mValue.getType(); From 72a1c1f318076229b3349ea33d652c762ddb6d79 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 15 Feb 2021 22:42:27 +0100 Subject: [PATCH 078/319] [compiler] Implement classes --- .../leekscript/compiler/WordCompiler.java | 226 ++++++++++++- .../compiler/bloc/ClassMethodBlock.java | 114 +++++++ .../compiler/bloc/MainLeekBlock.java | 29 ++ .../exceptions/LeekCompilerException.java | 12 +- .../expression/AbstractExpression.java | 2 + .../compiler/expression/LeekExpression.java | 12 +- .../expression/LeekExpressionFunction.java | 9 + .../expression/LeekObjectAccess.java_ | 75 +++++ .../compiler/expression/LeekVariable.java | 27 ++ .../compiler/expression/Operators.java | 9 + .../compiler/instruction/AccessLevel.java | 14 + .../ClassDeclarationInstruction.java | 307 ++++++++++++++++++ .../LeekVariableDeclarationInstruction.java | 1 + 13 files changed, 830 insertions(+), 7 deletions(-) create mode 100644 src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java create mode 100644 src/main/java/leekscript/compiler/expression/LeekObjectAccess.java_ create mode 100644 src/main/java/leekscript/compiler/instruction/AccessLevel.java create mode 100644 src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 2d159603..37a38bbb 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -6,6 +6,7 @@ import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.AbstractLeekBlock; import leekscript.compiler.bloc.AnonymousFunctionBlock; +import leekscript.compiler.bloc.ClassMethodBlock; import leekscript.compiler.bloc.ConditionalBloc; import leekscript.compiler.bloc.DoWhileBlock; import leekscript.compiler.bloc.ForBlock; @@ -26,12 +27,15 @@ import leekscript.compiler.expression.LeekGlobal; import leekscript.compiler.expression.LeekNull; import leekscript.compiler.expression.LeekNumber; +import leekscript.compiler.expression.LeekObjectAccess; import leekscript.compiler.expression.LeekParenthesis; import leekscript.compiler.expression.LeekString; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.Operators; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.compiler.instruction.AccessLevel; import leekscript.compiler.instruction.BlankInstruction; +import leekscript.compiler.instruction.ClassDeclarationInstruction; import leekscript.compiler.instruction.LeekBreakInstruction; import leekscript.compiler.instruction.LeekContinueInstruction; import leekscript.compiler.instruction.LeekExpressionInstruction; @@ -44,6 +48,7 @@ public class WordCompiler { private final MainLeekBlock mMain; private AbstractLeekBlock mCurentBlock; + private ClassDeclarationInstruction mCurrentClass; private final WordParser mCompiler; private int mLine; private AIFile mAI = null; @@ -123,7 +128,6 @@ public void readCode() throws LeekCompilerException { break; // Puis on lit l'instruction - compileWord(); } while (mCurentBlock.getParent() != null && !mCurentBlock.hasAccolade()) { @@ -139,6 +143,7 @@ public void readCode() throws LeekCompilerException { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPEN_BLOC_REMAINING); } catch (IndexOutOfBoundsException e) { + e.printStackTrace(System.out); throw new LeekCompilerException(mCompiler.endWord(), LeekCompilerException.END_OF_SCRIPT_UNEXPECTED); } } @@ -187,6 +192,11 @@ private void compileWord() throws LeekCompilerException { mCompiler.skipWord(); globalDeclaration(); return; + } else if (version >= 11 && word.getWord().equals("class")) { + // Déclaration de classe + mCompiler.skipWord(); + classDeclaration(); + return; } else if (word.getWord().equals("if")) { mCompiler.skipWord(); ifBlock(); @@ -652,9 +662,185 @@ private void variableDeclaration() throws LeekCompilerException { if (mCompiler.haveWords() && mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) { mCompiler.skipWord(); } + } + + public void classDeclaration() throws LeekCompilerException { + // Read class name + IAWord word = mCompiler.readWord(); + if (word.getType() != WordParser.T_STRING) { + throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED); + } + // if (!isAvailable(word.getWord(), true)) { + // throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); + // } + ClassDeclarationInstruction classDeclaration = new ClassDeclarationInstruction(word, mLine, mAI); + mMain.addClass(classDeclaration); + mCurrentClass = classDeclaration; + + if (mCompiler.getWord().getWord().equals("extends")) { + mCompiler.skipWord(); + IAWord parent = mCompiler.readWord(); + // if (!mMain.hasUserClass(parentName)) { + // throw new LeekCompilerException(word, LeekCompilerException.NO_SUCH_CLASS); + // } + classDeclaration.setParent(parent); + } + if (mCompiler.getWord().getType() != WordParser.T_ACCOLADE_LEFT) { + throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.OPENING_CURLY_BRACKET_EXPECTED); + } + mCompiler.skipWord(); + word = mCompiler.readWord(); - if (word.getType() != WordParser.T_END_INSTRUCTION) - throw new LeekCompilerException(word, LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + while (word.getType() != WordParser.T_ACCOLADE_RIGHT) { + switch (word.getWord()) { + case "public": + case "private": + case "protected": + { + AccessLevel level = AccessLevel.fromString(word.getWord()); + classAccessLevelMember(classDeclaration, level); + break; + } + case "constructor": { + classConstructor(classDeclaration, AccessLevel.PUBLIC); + break; + } + default: { + if (word.getType() == WordParser.T_STRING) { + mCompiler.back(); + classAccessLevelMember(classDeclaration, AccessLevel.PUBLIC); + } else { + throw new LeekCompilerException(word, LeekCompilerException.KEYWORD_UNEXPECTED); + } + } + } + word = mCompiler.readWord(); + } + if (word.getType() != WordParser.T_ACCOLADE_RIGHT) { + throw new LeekCompilerException(word, LeekCompilerException.END_OF_CLASS_EXPECTED); + } + mCurrentClass = null; + // mMain.addInstruction(this, classDeclaration); + } + + public void classAccessLevelMember(ClassDeclarationInstruction classDeclaration, AccessLevel accessLevel) throws LeekCompilerException { + IAWord name = mCompiler.readWord(); + switch (name.getWord()) { + case "constructor": + classConstructor(classDeclaration, accessLevel); + return; + case "static": + classStaticMember(classDeclaration, accessLevel); + return; + } + IAWord word2 = mCompiler.getWord(); + if (word2.getType() == WordParser.T_PAR_LEFT) { + // Méthode + ClassMethodBlock method = classMethod(classDeclaration, accessLevel, name.getWord(), false); + classDeclaration.addMethod(name, method); + } else { + // Field + AbstractExpression expr = null; + if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("=")) { + mCompiler.skipWord(); + expr = readExpression().getAbstractExpression(); + } + classDeclaration.addField(this, name, expr); + if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) + mCompiler.skipWord(); + } + } + + public void classStaticMember(ClassDeclarationInstruction classDeclaration, AccessLevel accessLevel) throws LeekCompilerException { + IAWord name = mCompiler.readWord(); + // Static field + AbstractExpression expr = null; + if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("=")) { + mCompiler.skipWord(); + expr = readExpression().getAbstractExpression(); + } else if (mCompiler.getWord().getType() == WordParser.T_PAR_LEFT) { + // Méthode + ClassMethodBlock method = classMethod(classDeclaration, accessLevel, name.getWord(), true); + classDeclaration.addStaticMethod(name.getWord(), method); + if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) + mCompiler.skipWord(); + return; + } + classDeclaration.addStaticField(name, expr); + + if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) + mCompiler.skipWord(); + } + + public void classConstructor(ClassDeclarationInstruction classDeclaration, AccessLevel accessLevel) throws LeekCompilerException { + ClassMethodBlock constructor = classMethod(classDeclaration, accessLevel, "constructor", false); + classDeclaration.addConstructor(constructor); + } + + public ClassMethodBlock classMethod(ClassDeclarationInstruction classDeclaration, AccessLevel accessLevel, String name, boolean isStatic) throws LeekCompilerException { + + ClassMethodBlock method = new ClassMethodBlock(classDeclaration, isStatic, mCurentBlock, mMain, mLine, mAI); + + IAWord word = mCompiler.readWord(); + if (word.getType() != WordParser.T_PAR_LEFT) { + throw new LeekCompilerException(word, LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); + } + int param_count = 0; + while (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { + if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("@")) { + errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCE_IGNORED_IN_METHODS)); + mCompiler.skipWord(); + } + if (mCompiler.getWord().getType() != WordParser.T_STRING) + throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_EXPECTED); + method.addParameter(mCompiler.getWord()); + mCompiler.skipWord(); + param_count++; + if (mCompiler.getWord().getType() == WordParser.T_VIRG) + mCompiler.skipWord(); + } + if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { + throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); + } + if (classDeclaration.hasMethod(name, param_count)) { + throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.CONSTRUCTOR_ALREADY_EXISTS); + } + + // On enregistre les block actuels + AbstractLeekBlock initialBlock = mCurentBlock; + int initialLine = mLine; + AIFile initialAI = mAI; + mCurentBlock = method; + + // Ouverture des accolades + if (mCompiler.readWord().getType() != WordParser.T_ACCOLADE_LEFT) + throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_CURLY_BRACKET_EXPECTED); + + // Lecture du corps de la fonction + while (mCompiler.haveWords()) { + // Fermeture des blocs ouverts + if (mCurentBlock instanceof DoWhileBlock && !((DoWhileBlock) mCurentBlock).hasAccolade() && mCurentBlock.lastInstruction() != null) { + DoWhileBlock do_block = (DoWhileBlock) mCurentBlock; + mCurentBlock = mCurentBlock.endInstruction(); + dowhileendBlock(do_block); + mCompiler.skipWord(); + } else + mCurentBlock = mCurentBlock.endInstruction(); + if (!mCompiler.haveWords()) + break; + + // On regarde si on veut fermer la fonction anonyme + if (mCompiler.getWord().getType() == WordParser.T_ACCOLADE_RIGHT && mCurentBlock == method) { + mCompiler.skipWord(); + break; // Fermeture de la fonction anonyme + } else + compileWord(); + } + // On remet le bloc initial + mCurentBlock = initialBlock; + mLine = initialLine; + mAI = initialAI; + return method; } public LeekExpression readExpression() throws LeekCompilerException { @@ -686,8 +872,19 @@ public LeekExpression readExpression() throws LeekCompilerException { if (mCompiler.haveWords() && mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); } - retour.addFunction(function); + } else if (word.getType() == WordParser.T_DOT) { + // Object access + IAWord token = mCompiler.readWord(); + IAWord name = mCompiler.readWord(); + + retour.addOperator(Operators.DOT, token); + + // Object access + LeekObjectAccess objectAccess = new LeekObjectAccess(retour.getLastExpression(), name); + retour.addExpression(objectAccess); + mCompiler.back(); + } else if (word.getType() == WordParser.T_OPERATOR) { int operator = Operators.getOperator(word.getWord(), getVersion()); @@ -796,7 +993,18 @@ else if (word.getWord().equalsIgnoreCase("not")) retour.addUnaryPrefix(Operators.NOT, word); else if (LeekConstants.get(word.getWord()) != null) retour.addExpression(new LeekConstant(word.getWord(), LeekConstants.get(word.getWord()))); - else { + else if (getVersion() >= 11 && word.getWord().equalsIgnoreCase("new")) { + retour.addUnaryPrefix(Operators.NEW, word); + } else if (word.getWord().equals("super")) { + // super doit être dans une méthode + if (!(mCurentBlock instanceof ClassMethodBlock)) { + errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.KEYWORD_MUST_BE_IN_CLASS)); + } + if (mCurentBlock instanceof ClassMethodBlock && ((ClassMethodBlock) mCurentBlock).getClassDeclaration().getParentToken() == null) { + errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.SUPER_NOT_AVAILABLE_PARENT)); + } + retour.addExpression(new LeekVariable(word, VariableType.SUPER, ((ClassMethodBlock) mCurentBlock).getClassDeclaration())); + } else { retour.addExpression(new LeekVariable(word, VariableType.LOCAL)); // throw new LeekCompilerException(word, LeekCompilerException.UNKNOWN_VARIABLE_OR_FUNCTION); } @@ -972,4 +1180,12 @@ public int getVersion() { public void addErrors(Set errors) { this.errors.addAll(errors); } + + public ClassDeclarationInstruction getCurrentClass() { + return mCurrentClass; + } + + public void setCurrentClass(ClassDeclarationInstruction clazz) { + this.mCurrentClass = clazz; + } } diff --git a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java new file mode 100644 index 00000000..37277e28 --- /dev/null +++ b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java @@ -0,0 +1,114 @@ +package leekscript.compiler.bloc; + +import java.util.ArrayList; + +import leekscript.compiler.AIFile; +import leekscript.compiler.IAWord; +import leekscript.compiler.JavaWriter; +import leekscript.compiler.expression.LeekVariable; +import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.compiler.instruction.ClassDeclarationInstruction; + +public class ClassMethodBlock extends AbstractLeekBlock { + + private final ClassDeclarationInstruction clazz; + private final boolean isStatic; + private final ArrayList mParameters = new ArrayList<>(); + private int mId = 0; + + public ClassMethodBlock(ClassDeclarationInstruction clazz, boolean isStatic, AbstractLeekBlock parent, MainLeekBlock main, int line, AIFile ai) { + super(parent, main, line, ai); + this.clazz = clazz; + this.isStatic = isStatic; + } + + public void setId(int id) { + mId = id; + } + + public int getId() { + return mId; + } + + public int countParameters() { + return mParameters.size(); + } + + public String referenceArray() { + String str = "{"; + for (int i = 0; i < mParameters.size(); i++) { + if (i != 0) + str += ","; + } + return str + "}"; + } + + public void addParameter(IAWord token) { + mParameters.add(token); + addVariable(new LeekVariable(token, VariableType.ARGUMENT)); + } + + public LeekVariable getVariable(String variable, boolean includeClassMembers) { + // Arguments + // for (var parameter : mParameters) { + // if (parameter.getWord().equals(variable)) { + // return new LeekVariable(parameter, VariableType.ARGUMENT); + // } + // } + + var v = super.getVariable(variable, includeClassMembers); + if (v != null) return v; + + // Search in fields + if (!isStatic) { + if (variable.equals("this")) return new LeekVariable(new IAWord("this"), VariableType.THIS); + if (variable.equals("class")) return new LeekVariable(new IAWord("class"), VariableType.THIS_CLASS); + if (includeClassMembers) { + v = clazz.getFieldVariables().get(variable); + if (v != null) return v; + v = clazz.getMethodVariables().get(variable); + if (v != null) return v; + } + } + if (includeClassMembers) { + v = clazz.getStaticMethodVariables().get(variable); + if (v != null) return v; + // Search in static fields + return clazz.getStaticFieldVariables().get(variable); + } + return null; + } + + @Override + public String getCode() { + String str = "function method" + mId + "("; + for (int i = 0; i < mParameters.size(); i++) { + if (i != 0) + str += ", "; + str += mParameters.get(i); + } + return str + "){\n" + super.getCode() + "}\n"; + } + + @Override + public void checkEndBlock() { + + } + + @Override + public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { + + for (int i = 0; i < mParameters.size(); i++) { + writer.addCode("final VariableLeekValue user_" + mParameters.get(i) + " = "); + writer.addLine("new VariableLeekValue(mUAI, values[" + i + "].getValue());"); + } + + super.writeJavaCode(mainblock, writer); + if (mEndInstruction == 0) + writer.addLine("return u_this;"); + } + + public ClassDeclarationInstruction getClassDeclaration() { + return this.clazz; + } +} diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 76f34cc7..4f684b82 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -14,6 +14,7 @@ import leekscript.compiler.WordCompiler; import leekscript.compiler.WordParser; import leekscript.compiler.exceptions.LeekCompilerException; +import leekscript.compiler.instruction.ClassDeclarationInstruction; import leekscript.compiler.instruction.LeekInstruction; import leekscript.runner.LeekFunctions; @@ -25,6 +26,7 @@ public class MainLeekBlock extends AbstractLeekBlock { private final ArrayList mFunctions = new ArrayList(); private final ArrayList mAnonymousFunctions = new ArrayList(); private final Map mUserFunctions = new TreeMap(); + private final Map mUserClasses = new TreeMap(); private int mMinLevel = 1; private int mAnonymousId = 1; private int mFunctionId = 1; @@ -80,6 +82,7 @@ public boolean includeAI(WordCompiler compiler, String path) throws LeekCompiler if (mIncluded.contains(ai.getId())) { return true; } + // System.out.println("include " + ai.getPath()); mIncluded.add(ai.getId()); AIFile previousAI = mCompiler.getCurrentAI(); mCompiler.setCurrentAI(ai); @@ -196,11 +199,19 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { for (LeekInstruction instruction : mFunctions) { instruction.writeJavaCode(this, writer); } + for (var clazz : mUserClasses.values()) { + clazz.declareJava(this, writer); + } /* * for(LeekInstruction instruction : mAnonymousFunctions){ * instruction.writeJavaCode(this, writer); } */ writer.addLine("public AbstractLeekValue runIA() throws LeekRunException { resetCounter();"); + + for (var clazz : mUserClasses.values()) { + clazz.writeJavaCode(this, writer); + } + super.writeJavaCode(this, writer); if (mEndInstruction == 0) writer.addLine("return LeekValueManager.NULL;"); @@ -314,10 +325,28 @@ public IACompiler getCompiler() { return mCompiler; } + public boolean hasUserClass(String name) { + return mUserClasses.containsKey(name); + } + + public void addClass(ClassDeclarationInstruction classDeclaration) { + mUserClasses.put(classDeclaration.getName(), classDeclaration); + } + + public ClassDeclarationInstruction getUserClass(String name) { + return mUserClasses.get(name); + } + public void analyze(WordCompiler compiler) { + for (var clazz : mUserClasses.values()) { + clazz.declare(compiler); + } for (var function : mFunctions) { function.declare(compiler); } + for (var clazz : mUserClasses.values()) { + clazz.analyze(compiler); + } for (var function : mFunctions) { function.analyze(compiler); } diff --git a/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java b/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java index 4cb5f3f9..2b1ff5b0 100644 --- a/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java +++ b/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java @@ -47,9 +47,19 @@ public class LeekCompilerException extends Exception { public final static String INVALID_PAREMETER_COUNT = "invalid_parameter_count"; public final static String INVALID_CHAR = "invalid_char"; public final static String INVALID_NUMBER = "invalid_number"; + public final static String CONSTRUCTOR_ALREADY_EXISTS = "constructor_already_exists"; + public final static String END_OF_CLASS_EXPECTED = "end_of_class_expected"; + public final static String FIELD_ALREADY_EXISTS = "field_already_exists"; + public final static String NO_SUCH_CLASS = "no_such_class"; + public final static String THIS_NOT_ALLOWED_HERE = "this_not_allowed_here"; + public final static String REFERENCE_IGNORED_IN_METHODS = "reference_ignored_in_methods"; + public final static String KEYWORD_MUST_BE_IN_CLASS = "keyword_must_be_in_class"; + public final static String SUPER_NOT_AVAILABLE_PARENT = "super_not_available_parent"; + public final static String CLASS_MEMBER_DOES_NOT_EXIST = "class_member_does_not_exist"; + public final static String CLASS_STATIC_MEMBER_DOES_NOT_EXIST = "class_static_member_does_not_exist"; /** - * + * */ private static final long serialVersionUID = 1L; int mLine; diff --git a/src/main/java/leekscript/compiler/expression/AbstractExpression.java b/src/main/java/leekscript/compiler/expression/AbstractExpression.java index 7525033c..b5626fa1 100644 --- a/src/main/java/leekscript/compiler/expression/AbstractExpression.java +++ b/src/main/java/leekscript/compiler/expression/AbstractExpression.java @@ -16,6 +16,8 @@ public abstract class AbstractExpression { public final static int FUNCTION = 8; public final static int GLOBAL = 9; public final static int ARRAY = 10; + public final static int OBJECT = 11; + public final static int OBJECT_ACCESS = 12; public abstract int getType(); diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index e8e9614c..13199c3d 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -617,7 +617,9 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { mExpression2.writeJavaCode(mainblock, writer); writer.addCode(".opposite(mUAI)"); return; - + case Operators.NEW: + mExpression2.writeJavaCode(mainblock, writer); + return; // Les unaires suffixés (++, --), Il a été vérifié au préalable // qu'on avait bien une L-Value case Operators.INCREMENT: @@ -721,10 +723,18 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { mExpression2.writeJavaCode(mainblock, writer); writer.addCode(")"); return; + case Operators.DOT: + mExpression2.writeJavaCode(mainblock, writer); + return; } return; } + @Override + public boolean isLeftValue() { + return mOperator == Operators.DOT; + } + @Override public void analyze(WordCompiler compiler) { if (mExpression1 != null) mExpression1.analyze(compiler); diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index c12f7564..12108b55 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -52,6 +52,15 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { boolean addComma = true; + if (mExpression instanceof LeekObjectAccess) { + var object = ((LeekObjectAccess) mExpression).getObject(); + object.writeJavaCode(mainblock, writer); + writer.addCode(".callMethod(mUAI, \"" + ((LeekObjectAccess) mExpression).getField() + "_" + mParameters.size() + "\""); + } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.METHOD) { + writer.addCode("u_this.callMethod(mUAI, \"" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size() + "\""); + } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.STATIC_METHOD) { + writer.addCode("u_class.callMethod(mUAI, \"" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size() + "\""); + } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.SYSTEM_FUNCTION) { var variable = (LeekVariable) mExpression; String namespace = LeekFunctions.getNamespace(variable.getName()); diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java_ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java_ new file mode 100644 index 00000000..6c2a055d --- /dev/null +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java_ @@ -0,0 +1,75 @@ +package leekscript.compiler.expression; + +import leekscript.compiler.AnalyzeError; +import leekscript.compiler.IAWord; +import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; +import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; +import leekscript.compiler.bloc.MainLeekBlock; +import leekscript.compiler.exceptions.LeekCompilerException; +import leekscript.compiler.expression.LeekVariable.VariableType; + +public class LeekObjectAccess extends AbstractExpression { + + private AbstractExpression object; + private IAWord field; + + public LeekObjectAccess(AbstractExpression object, IAWord field) { + this.object = object; + this.field = field; + } + + @Override + public int getType() { + return OBJECT_ACCESS; + } + + @Override + public String getString() { + return ""; + } + + public AbstractExpression getObject() { + return object; + } + + @Override + public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { + object.writeJavaCode(mainblock, writer); + writer.addCode(".getField(mUAI, \"" + field.getWord() + "\")"); + } + + @Override + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { + + return true; + } + + @Override + public boolean isLeftValue() { + return true; + } + + @Override + public void analyze(WordCompiler compiler) { + object.analyze(compiler); + if (object instanceof LeekVariable) { + var v = (LeekVariable) object; + if (v.getName().equals("this")) { + // this, check field exists in class + var clazz = compiler.getCurrentClass(); + if (clazz != null && !clazz.hasMember(field)) { + compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, LeekCompilerException.CLASS_MEMBER_DOES_NOT_EXIST)); + } + } else if (v.getVariableType() == VariableType.CLASS && v.getClassDeclaration() != null) { + if (!v.getClassDeclaration().hasStaticMember(field)) { + compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, LeekCompilerException.CLASS_STATIC_MEMBER_DOES_NOT_EXIST, new String[] { v.getClassDeclaration().getName(), field.getWord() })); + } + } + } + } + + public String getField() { + return field.getWord(); + } +} diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index f4c32119..dd4cf7a6 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -8,6 +8,7 @@ import leekscript.compiler.bloc.FunctionBlock; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.exceptions.LeekCompilerException; +import leekscript.compiler.instruction.ClassDeclarationInstruction; import leekscript.runner.LeekFunctions; public class LeekVariable extends AbstractExpression { @@ -18,10 +19,18 @@ public static enum VariableType { private final IAWord token; private VariableType type; + private ClassDeclarationInstruction classDeclaration; public LeekVariable(IAWord token, VariableType type) { this.token = token; this.type = type; + this.classDeclaration = null; + } + + public LeekVariable(IAWord token, VariableType type, ClassDeclarationInstruction classDeclaration) { + this.token = token; + this.type = type; + this.classDeclaration = classDeclaration; } @Override @@ -41,6 +50,19 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { + if (type == VariableType.THIS) { + writer.addCode("u_this"); + } else if (type == VariableType.THIS_CLASS) { + writer.addCode("u_class"); + } else if (type == VariableType.SUPER) { + writer.addCode("user_" + classDeclaration.getParent().getName()); + } else if (type == VariableType.FIELD) { + writer.addCode("u_this.getField(mUAI, \"" + token.getWord() + "\")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.getField(mUAI, \"" + token.getWord() + "\")"); + } else if (type == VariableType.METHOD) { + writer.addCode("###"); + } else if (type == VariableType.FUNCTION) { FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); @@ -86,6 +108,7 @@ public void analyze(WordCompiler compiler) { var v = compiler.getCurrentBlock().getVariable(token.getWord(), true); if (v != null) { this.type = v.getVariableType(); + this.classDeclaration = v.getClassDeclaration(); return; } if (LeekFunctions.isFunction(token.getWord()) != -1) { @@ -94,4 +117,8 @@ public void analyze(WordCompiler compiler) { } compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.UNKNOWN_VARIABLE_OR_FUNCTION)); } + + public ClassDeclarationInstruction getClassDeclaration() { + return classDeclaration; + } } diff --git a/src/main/java/leekscript/compiler/expression/Operators.java b/src/main/java/leekscript/compiler/expression/Operators.java index 8fe53997..140a1b7b 100644 --- a/src/main/java/leekscript/compiler/expression/Operators.java +++ b/src/main/java/leekscript/compiler/expression/Operators.java @@ -48,6 +48,8 @@ public class Operators { public final static int PRE_DECREMENT = 45; public final static int REFERENCE = 46; public final static int BITNOT = 47; + public final static int NEW = 48; + public final static int DOT = 49; public final static int getOperator(String operator, int version) { if(operator.equals("[")) return CROCHET; @@ -101,6 +103,8 @@ public final static int getOperator(String operator, int version) { if(operator.equals(">>=")) return SHIFT_RIGHT_ASSIGN; if(operator.equals(">>>=")) return ROTATE_RIGHT_ASSIGN; if(operator.equals("@")) return REFERENCE; + if(operator.equals("new")) return NEW; + if(operator.equals(".")) return DOT; return -1; } @@ -108,6 +112,8 @@ public static int getPriority(int operator) { switch(operator) { case CROCHET: case PARENTHESIS: + return 16; + case DOT: return 15; case INCREMENT: case DECREMENT: @@ -180,6 +186,7 @@ public static boolean isUnaryPrefix(int operator) { case PRE_DECREMENT: case REFERENCE: case BITNOT: + case NEW: return true; } return false; @@ -230,6 +237,8 @@ public static String getString(int operator) { return "^"; case POWERASSIGN: return "^="; + case NEW: + return "new"; } return "null"; } diff --git a/src/main/java/leekscript/compiler/instruction/AccessLevel.java b/src/main/java/leekscript/compiler/instruction/AccessLevel.java new file mode 100644 index 00000000..2243b252 --- /dev/null +++ b/src/main/java/leekscript/compiler/instruction/AccessLevel.java @@ -0,0 +1,14 @@ +package leekscript.compiler.instruction; + +public enum AccessLevel { + PUBLIC, PROTECTED, PRIVATE; + + public static AccessLevel fromString(String word) { + switch (word) { + case "public": return AccessLevel.PUBLIC; + case "protected": return AccessLevel.PROTECTED; + case "private": return AccessLevel.PRIVATE; + } + return AccessLevel.PUBLIC; + } +} \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java new file mode 100644 index 00000000..a7157845 --- /dev/null +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -0,0 +1,307 @@ +package leekscript.compiler.instruction; + +import java.util.HashMap; +import java.util.Map.Entry; + +import leekscript.compiler.AIFile; +import leekscript.compiler.AnalyzeError; +import leekscript.compiler.IAWord; +import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; +import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; +import leekscript.compiler.bloc.ClassMethodBlock; +import leekscript.compiler.bloc.MainLeekBlock; +import leekscript.compiler.exceptions.LeekCompilerException; +import leekscript.compiler.expression.AbstractExpression; +import leekscript.compiler.expression.LeekVariable; +import leekscript.compiler.expression.LeekVariable.VariableType; + +public class ClassDeclarationInstruction implements LeekInstruction { + + private final IAWord token; + private IAWord parentToken; + private ClassDeclarationInstruction parent; + private HashMap fields = new HashMap<>(); + private HashMap staticFields = new HashMap<>(); + private HashMap fieldVariables = new HashMap<>(); + private HashMap staticFieldVariables = new HashMap<>(); + private HashMap methodVariables = new HashMap<>(); + private HashMap staticMethodVariables = new HashMap<>(); + private HashMap constructors = new HashMap<>(); + private HashMap> methods = new HashMap<>(); + private HashMap> staticMethods = new HashMap<>(); + + public ClassDeclarationInstruction(IAWord token, int line, AIFile ai) { + this.token = token; + } + + public HashMap getFields() { + return fields; + } + public HashMap getStaticFields() { + return staticFields; + } + + public HashMap getFieldVariables() { + return fieldVariables; + } + public HashMap getMethodVariables() { + return methodVariables; + } + public HashMap getStaticFieldVariables() { + return staticFieldVariables; + } + public HashMap getStaticMethodVariables() { + return staticMethodVariables; + } + + public String getName() { + return token.getWord(); + } + + @Override + public String getCode() { + return "class"; + } + + @Override + public int getEndBlock() { + return 0; + } + + @Override + public boolean putCounterBefore() { + return false; + } + + public void setParent(IAWord userClass) { + this.parentToken = userClass; + } + + public boolean hasConstructor(int param_count) { + return constructors.containsKey(param_count); + } + + public void addConstructor(ClassMethodBlock block) { + constructors.put(block.countParameters(), block); + } + + public void addMethod(IAWord token, ClassMethodBlock method) { + if (!methods.containsKey(token.getWord())) { + methods.put(token.getWord(), new HashMap<>()); + methodVariables.put(token.getWord(), new LeekVariable(token, VariableType.METHOD)); + } + methods.get(token.getWord()).put(method.countParameters(), method); + } + + public boolean hasMethod(String name, int param_count) { + if (name.equals("constructor")) { + return hasConstructor(param_count); + } + return methods.containsKey(name + "_" + param_count); + } + + public void addStaticMethod(String name, ClassMethodBlock method) { + if (!staticMethods.containsKey(name)) { + staticMethods.put(name, new HashMap<>()); + staticMethodVariables.put(name, new LeekVariable(token, VariableType.STATIC_METHOD)); + } + staticMethods.get(name).put(method.countParameters(), method); + } + + public void addField(WordCompiler compiler, IAWord word, AbstractExpression expr) throws LeekCompilerException { + if (fields.containsKey(word.getWord()) || staticFields.containsKey(word.getWord())) { + compiler.addError(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.FIELD_ALREADY_EXISTS)); + return; + } + fields.put(word.getWord(), expr); + fieldVariables.put(word.getWord(), new LeekVariable(word, VariableType.FIELD)); + } + + public void addStaticField(IAWord word, AbstractExpression expr) throws LeekCompilerException { + if (staticFields.containsKey(word.getWord()) || fields.containsKey(word.getWord())) { + throw new LeekCompilerException(word, LeekCompilerException.FIELD_ALREADY_EXISTS); + } + staticFields.put(word.getWord(), expr); + staticFieldVariables.put(word.getWord(), new LeekVariable(word, VariableType.STATIC_FIELD)); + } + + public void declare(WordCompiler compiler) { + // On ajoute la classe + compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.CLASS, this)); + } + + public void analyze(WordCompiler compiler) { + compiler.setCurrentClass(this); + // Parent + if (parentToken != null) { + var parentVar = compiler.getCurrentBlock().getVariable(this.parentToken.getWord(), true); + if (parentVar == null) { + compiler.addError(new AnalyzeError(parentToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.UNKNOWN_VARIABLE_OR_FUNCTION)); + } else if (parentVar.getVariableType() != VariableType.CLASS) { + compiler.addError(new AnalyzeError(parentToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.UNKNOWN_VARIABLE_OR_FUNCTION)); + } else { + this.parent = parentVar.getClassDeclaration(); + } + } + + for (var constructor : constructors.values()) { + constructor.analyze(compiler); + } + for (var method : methods.values()) { + for (var version : method.values()) { + version.analyze(compiler); + } + } + for (var method : staticMethods.values()) { + for (var version : method.values()) { + version.analyze(compiler); + } + } + compiler.setCurrentClass(null); + } + + public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { + + String className = "user_" + token.getWord(); + writer.addLine("private ClassLeekValue " + className + ";"); + } + + @Override + public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { + + String className = "user_" + token.getWord(); + writer.addCode(className); + writer.addLine(" = new ClassLeekValue(\"" + token.getWord() + "\");"); + + if (parent != null) { + writer.addLine(className + ".setParent(user_" + parent.getName() + ");"); + } + + for (Entry> method : staticMethods.entrySet()) { + for (Entry version : method.getValue().entrySet()) { + String methodName = className + "_" + method.getKey() + "_" + version.getKey(); + writer.addCode("final LeekAnonymousFunction " + methodName + " = new LeekAnonymousFunction() {"); + writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue u_this, AbstractLeekValue... values) throws LeekRunException {"); + writer.addLine("final var u_class = " + className + ";", version.getValue().getLine(), version.getValue().getFile()); + if (parent != null) { + writer.addLine("final var u_super = user_" + parent.token.getWord() + ";"); + } + version.getValue().writeJavaCode(mainblock, writer); + writer.addLine("}};"); + } + } + + for (Entry> method : methods.entrySet()) { + for (Entry version : method.getValue().entrySet()) { + String methodName = className + "_" + method.getKey() + "_" + version.getKey(); + writer.addCode("final LeekAnonymousFunction " + methodName + " = new LeekAnonymousFunction() {"); + writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue u_this, AbstractLeekValue... values) throws LeekRunException {"); + writer.addLine("final var u_class = " + className + ";", version.getValue().getLine(), version.getValue().getFile()); + if (parent != null) { + writer.addLine("final var u_super = user_" + parent.token.getWord() + ";"); + } + writer.addCounter(1); + version.getValue().writeJavaCode(mainblock, writer); + writer.addLine("}};"); + } + } + + for (Entry field : staticFields.entrySet()) { + writer.addCode(className); + writer.addCode(".addStaticField(mUAI, \"" + field.getKey() + "\", "); + if (field.getValue() != null) { + field.getValue().writeJavaCode(mainblock, writer); + } else { + writer.addCode("LeekValueManager.NULL"); + } + writer.addLine(");"); + } + + writeFields(mainblock, writer, className); + + for (Entry> method : staticMethods.entrySet()) { + for (Entry version : method.getValue().entrySet()) { + String methodName = className + "_" + method.getKey() + "_" + version.getKey(); + writer.addCode(className); + writer.addLine(".addStaticMethod(\"" + method.getKey() + "\", " + version.getKey() + ", " + methodName + ");"); + } + writer.addCode(className); + writer.addCode(".addGenericStaticMethod(\"" + method.getKey() + "\", new LeekAnonymousFunction() {"); + writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue thiz, AbstractLeekValue... values) throws LeekRunException {"); + writer.addLine("switch (values.length) {"); + for (Entry version : method.getValue().entrySet()) { + String methodName = className + "_" + method.getKey() + "_" + version.getKey(); + writer.addLine("case " + version.getKey() + ": return " + methodName + ".run(mUAI, thiz, values);"); + } + writer.addLine("default: mUAI.addSystemLog(leekscript.AILog.ERROR, leekscript.AILog.UNKNOWN_METHOD, new String[] { });"); + writer.addLine("return LeekValueManager.NULL;"); + writer.addLine("}}});"); + } + + for (Entry construct : constructors.entrySet()) { + writer.addCode(className); + writer.addLine(".addConstructor(" + construct.getKey() + ", new LeekAnonymousFunction() {"); + writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue u_this, AbstractLeekValue... values) throws LeekRunException {"); + writer.addLine("final var u_class = " + className + ";"); + if (parent != null) { + writer.addLine("final var u_super = user_" + parent.token.getWord() + ";"); + } + construct.getValue().writeJavaCode(mainblock, writer); + writer.addLine("}});"); + } + + for (Entry> method : methods.entrySet()) { + for (Entry version : method.getValue().entrySet()) { + String methodName = className + "_" + method.getKey() + "_" + version.getKey(); + writer.addCode(className); + writer.addLine(".addMethod(\"" + method.getKey() + "\", " + version.getKey() + ", " + methodName + ");"); + } + writer.addCode(className); + writer.addCode(".addGenericMethod(\"" + method.getKey() + "\", new LeekAnonymousFunction() {"); + writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue thiz, AbstractLeekValue... values) throws LeekRunException {"); + writer.addLine("switch (values.length) {"); + for (Entry version : method.getValue().entrySet()) { + String methodName = className + "_" + method.getKey() + "_" + version.getKey(); + writer.addLine("case " + version.getKey() + ": return " + methodName + ".run(mUAI, thiz, values);"); + } + writer.addLine("default: mUAI.addSystemLog(leekscript.AILog.ERROR, leekscript.AILog.UNKNOWN_METHOD, new String[] { });"); + writer.addLine("return LeekValueManager.NULL;"); + writer.addLine("}}});"); + } + } + + private void writeFields(MainLeekBlock mainblock, JavaWriter writer, String className) { + + if (parent != null) { + parent.writeFields(mainblock, writer, className); + } + + for (Entry field : fields.entrySet()) { + writer.addCode(className); + writer.addCode(".addField(mUAI, \"" + field.getKey() + "\", "); + if (field.getValue() != null) { + field.getValue().writeJavaCode(mainblock, writer); + } else { + writer.addCode("LeekValueManager.NULL"); + } + writer.addLine(");"); + } + } + + public IAWord getParentToken() { + return parentToken; + } + + public ClassDeclarationInstruction getParent() { + return parent; + } + + public boolean hasMember(IAWord field) { + return fields.containsKey(field.getWord()) || methods.containsKey(field.getWord()); + } + + public boolean hasStaticMember(IAWord field) { + return staticFields.containsKey(field.getWord()) || staticMethods.containsKey(field.getWord()); + } +} diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index 926e726d..40a5095b 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -78,6 +78,7 @@ public boolean putCounterBefore() { public void analyze(WordCompiler compiler) { // Variables interdites if (token.getWord().equals("this")) { + compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.THIS_NOT_ALLOWED_HERE)); } else { // On ajoute la variable if (compiler.getMainBlock().hasGlobal(token.getWord()) || compiler.getMainBlock().hasUserFunction(token.getWord(), true) || compiler.getCurrentBlock().hasVariable(token.getWord())) { From af4ea5e68cbdcbed82160036eac6577092905a5c Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 15 Feb 2021 17:29:24 +0100 Subject: [PATCH 079/319] [global] Improve globals --- .../leekscript/compiler/WordCompiler.java | 14 +++++------ .../compiler/bloc/FunctionBlock.java | 4 ++++ .../compiler/bloc/MainLeekBlock.java | 24 ++++++++++--------- .../LeekGlobalDeclarationInstruction.java | 24 +++++++++++++++---- .../LeekVariableDeclarationInstruction.java | 4 ++-- 5 files changed, 45 insertions(+), 25 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 37a38bbb..57411c51 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -71,11 +71,11 @@ public void readCode() throws LeekCompilerException { if (mCompiler.getWord().getWord().equals("global")) { mCompiler.skipWord(); String globalName = mCompiler.readWord().getWord(); - mMain.addGlobalDeclaration(globalName); + mMain.addGlobal(globalName); while (mCompiler.getWord().getType() == WordParser.T_VIRG && mCompiler.haveWords()) { mCompiler.skipWord(); globalName = mCompiler.readWord().getWord(); - mMain.addGlobalDeclaration(globalName); + mMain.addGlobal(globalName); } } else if (mCompiler.getWord().getWord().equals("function")) { mCompiler.skipWord(); @@ -95,8 +95,8 @@ public void readCode() throws LeekCompilerException { } if (mCompiler.getWord().getType() != WordParser.T_STRING) throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_EXPECTED); - if (!isAvailable(mCompiler.getWord().getWord(), true)) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_UNAVAILABLE); + // if (!isAvailable(mCompiler.getWord().getWord(), true)) + // throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_UNAVAILABLE); mCompiler.skipWord(); param_count++; @@ -318,8 +318,8 @@ private void functionBlock() throws LeekCompilerException { } if (mCompiler.getWord().getType() != WordParser.T_STRING) throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_EXPECTED); - if (!isAvailable(mCompiler.getWord().getWord(), true)) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_UNAVAILABLE); + // if (!isAvailable(mCompiler.getWord().getWord(), true)) + // throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_UNAVAILABLE); block.addParameter(mCompiler.readWord(), is_reference); if (mCompiler.getWord().getType() == WordParser.T_VIRG) mCompiler.skipWord(); @@ -594,7 +594,7 @@ private void globalDeclaration() throws LeekCompilerException { variable.setValue(readExpression().getAbstractExpression()); } // On ajoute la variable - mMain.addGlobal(variable.getName()); + mMain.addGlobalDeclaration(variable); mCurentBlock.addInstruction(this, variable); while (mCompiler.haveWords() && mCompiler.getWord().getType() == WordParser.T_VIRG) { // On regarde si y'en a d'autres diff --git a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java index 99e045f1..7cbfb2f3 100644 --- a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java @@ -108,4 +108,8 @@ public void declare(WordCompiler compiler) { compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.FUNCTION)); // System.out.println("Declare function " + token.getWord()); } + + public String toString() { + return token.getWord(); + } } diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 4f684b82..ff038700 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -15,13 +15,14 @@ import leekscript.compiler.WordParser; import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.instruction.ClassDeclarationInstruction; +import leekscript.compiler.instruction.LeekGlobalDeclarationInstruction; import leekscript.compiler.instruction.LeekInstruction; import leekscript.runner.LeekFunctions; public class MainLeekBlock extends AbstractLeekBlock { - private final ArrayList mGobales = new ArrayList(); - private final ArrayList mGobalesDeclarations = new ArrayList(); + private final ArrayList mGlobales = new ArrayList<>(); + private final ArrayList mGlobalesDeclarations = new ArrayList<>(); private final HashSet mRedefinedFunctions = new HashSet(); private final ArrayList mFunctions = new ArrayList(); private final ArrayList mAnonymousFunctions = new ArrayList(); @@ -111,8 +112,8 @@ public void addFunctionDeclaration(String name, int count_param) { mUserFunctions.put(name, count_param); } - public void addGlobalDeclaration(String declaration) { - mGobalesDeclarations.add(declaration); + public void addGlobalDeclaration(LeekGlobalDeclarationInstruction declaration) { + mGlobalesDeclarations.add(declaration); } public void addAnonymousFunction(AnonymousFunctionBlock block) { @@ -142,19 +143,17 @@ public FunctionBlock getUserFunction(String name) { @Override public boolean hasGlobal(String globale) { - if (mGobalesDeclarations.contains(globale)) - return true; - return mGobales.contains(globale); + return mGlobales.contains(globale); } @Override public boolean hasDeclaredGlobal(String globale) { - return mGobales.contains(globale); + return mGlobales.contains(globale); } @Override - public void addGlobal(String globale) { - mGobales.add(globale); + public void addGlobal(String variable) { + mGlobales.add(variable); } public void addFunction(FunctionBlock block) { @@ -186,7 +185,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { writer.addLine("}"); // Variables globales - for (String global : mGobales) { + for (String global : mGlobales) { writer.addLine("private VariableLeekValue globale_" + global + " = null;"); } // Fonctions redéfinies @@ -344,6 +343,9 @@ public void analyze(WordCompiler compiler) { for (var function : mFunctions) { function.declare(compiler); } + for (var global : mGlobalesDeclarations) { + global.declare(compiler); + } for (var clazz : mUserClasses.values()) { clazz.analyze(compiler); } diff --git a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java index 4eede182..b79271b8 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java @@ -1,11 +1,16 @@ package leekscript.compiler.instruction; import leekscript.compiler.AIFile; +import leekscript.compiler.AnalyzeError; import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; +import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.MainLeekBlock; +import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.expression.AbstractExpression; +import leekscript.compiler.expression.LeekVariable; +import leekscript.compiler.expression.LeekVariable.VariableType; public class LeekGlobalDeclarationInstruction implements LeekInstruction { @@ -55,13 +60,22 @@ public boolean putCounterBefore() { return false; } + public void declare(WordCompiler compiler) { + // Variables interdites + if (token.getWord().equals("this")) { + } else { + // Vérification déjà existante (on vérifie les globales seulement en 1.1 car il y a un léger bug en 1.0 avec les includes) + if ((compiler.getVersion() >= 11 && compiler.getMainBlock().hasGlobal(token.getWord())) || compiler.getMainBlock().hasUserFunction(token.getWord(), true)) { + compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); + } else { + // On ajoute la variable + compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.GLOBAL)); + } + } + } + @Override public void analyze(WordCompiler compiler) { - // if (token.getWord().equals("COLOR_ORANGE")) { - // System.out.println("Add global " + token.getWord()); - // } - // compiler.getMainBlock().addGlobal(token.getWord()); - // compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.GLOBAL)); if (mValue != null) { mValue.analyze(compiler); } diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index 40a5095b..e0ce77c4 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -80,8 +80,8 @@ public void analyze(WordCompiler compiler) { if (token.getWord().equals("this")) { compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.THIS_NOT_ALLOWED_HERE)); } else { - // On ajoute la variable - if (compiler.getMainBlock().hasGlobal(token.getWord()) || compiler.getMainBlock().hasUserFunction(token.getWord(), true) || compiler.getCurrentBlock().hasVariable(token.getWord())) { + // Vérification déjà existante (on vérifie les globales seulement en 1.1 car il y a un léger bug en 1.0 avec les includes) + if (compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(token.getWord()) || compiler.getMainBlock().hasUserFunction(token.getWord(), true)) || compiler.getCurrentBlock().hasVariable(token.getWord())) { compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); } else { compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.LOCAL)); From 20b8003cb82454b0c43f72290bbcffed8d31d7ca Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 14 Feb 2021 23:39:45 +0100 Subject: [PATCH 080/319] [test] Update tests --- src/test/java/test/TestAI.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/test/TestAI.java b/src/test/java/test/TestAI.java index d135a092..27266f4d 100644 --- a/src/test/java/test/TestAI.java +++ b/src/test/java/test/TestAI.java @@ -1,5 +1,7 @@ package test; + import leekscript.runner.AI; +import leekscript.runner.LeekRunException; import leekscript.runner.values.AbstractLeekValue; public class TestAI extends AI { @@ -52,5 +54,4 @@ public boolean[] anonymousFunctionReference(int id) { public int getVersion() { return 11; } - } From 57fa5510b88044ba0792744741e64076fc8bccec Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 14 Feb 2021 23:45:44 +0100 Subject: [PATCH 081/319] [test] Improve tests --- build.gradle | 8 + .../compiler/resolver/FileSystemResolver.java | 1 + src/test/java/test/TestAdvancedFunctions.java | 18 +- src/test/java/test/TestFunctions.java | 19 +- src/test/java/test/TestGeneral.java | 232 ++---------------- 5 files changed, 42 insertions(+), 236 deletions(-) diff --git a/build.gradle b/build.gradle index fde2821e..acd8f25f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,13 @@ apply plugin: 'java' +sourceSets { + test { + java { + srcDirs = ['src/test/java'] + } + } +} + test { testLogging { events "passed", "skipped", "failed" diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index 0d4a7509..7828fa8b 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -34,6 +34,7 @@ public AIFile resolve(String path, ResolverContext basecontex return new AIFile(path, code, timestamp, 11, newContext, resolvedPath.hashCode() & 0xfffffff); } catch (IOException e) { + e.printStackTrace(); throw new FileNotFoundException(); } } diff --git a/src/test/java/test/TestAdvancedFunctions.java b/src/test/java/test/TestAdvancedFunctions.java index f8c8dbdb..92088b9e 100644 --- a/src/test/java/test/TestAdvancedFunctions.java +++ b/src/test/java/test/TestAdvancedFunctions.java @@ -23,7 +23,7 @@ public class TestAdvancedFunctions { private AI ai; - + @Before public void init() throws Exception { ai = new TestAI(); @@ -155,21 +155,25 @@ public void arrayFilterTest() throws Exception { codes.add("arrayFilter([1,2,3,4,5,6,7,8,9],function(e){ return e>5; })"); values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(5), new IntLeekValue(6), new IntLeekValue(6), - new IntLeekValue(7), new IntLeekValue(7), - new IntLeekValue(8), new IntLeekValue(8), new IntLeekValue(9) }, true)); + new IntLeekValue(6), + new IntLeekValue(7), + new IntLeekValue(8), + new IntLeekValue(9) + })); codes.add("arrayFilter([4,5,6,'test',8,9],function(e){ return e=='test'; })"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(3), new StringLeekValue("test") }, true)); + values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { + new StringLeekValue("test") + })); codes.add("string(arrayFilter(['a','b','c','d'],function(k,v){ return k==3; }))"); - values.add("[3 : d]"); + values.add("[d]"); codes.add("string(function(){ var t = ['a','b','c','d']; arrayFilter(t,function(k,@v){ v=4; return k==3; }); return t;}())"); values.add("[4, 4, 4, 4]"); codes.add("string(arrayFilter(['a','b','c','d'],function(k,@v){ v=4; return k==3; }))"); - values.add("[3 : 4]"); + values.add("[4]"); // Test AI Assert.assertTrue(testAI(codes, values)); diff --git a/src/test/java/test/TestFunctions.java b/src/test/java/test/TestFunctions.java index 9358d424..fd6f1ec3 100644 --- a/src/test/java/test/TestFunctions.java +++ b/src/test/java/test/TestFunctions.java @@ -21,9 +21,9 @@ import org.junit.Test; public class TestFunctions { - + private AI ai; - + @Before public void init() throws Exception { ai = new TestAI(); @@ -384,21 +384,8 @@ public void ArrayFunctionsTest() throws Exception { // Test large array codes.add("function(){ var a = []; for (var i = 0; i < 100000; ++i) { push(a, i); } return a[91212]; }()"); values.add("91212"); - - // Test arrayMap et suivant => plus loin - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - @Test - public void stringTest() throws Exception { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - // Test nombre - codes.add("'\\\\'"); - values.add("\\\\"); + // Test arrayMap et suivant => plus loin // Test AI Assert.assertTrue(testAI(codes, values)); diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index 08f3f73a..30273490 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -18,7 +18,6 @@ import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import com.alibaba.fastjson.JSONObject; @@ -26,7 +25,7 @@ public class TestGeneral { TestAI ai; - + @Before public void init() throws Exception { ai = new TestAI(); @@ -92,19 +91,19 @@ public void conditionTest() throws Exception { @Test public void foreachTest() throws Exception { - Assert.assertTrue(testScript("var test = [0,1,2,3,4,5]; var retour = \"\"; for(var i in test){ retour += i; } return retour;", + Assert.assertTrue(testScript("var test = [0,1,2,3,4,5]; var retour = \"\"; for(var i in test){ retour += i; } return retour;", new StringLeekValue("012345"))); } @Test public void foreachGlobalTest() throws Exception { - Assert.assertTrue(testScript("global i; var test = [0,1,2,3,4,5]; var retour = \"\"; for(i in test){ retour += i; } return retour;", + Assert.assertTrue(testScript("global i; var test = [0,1,2,3,4,5]; var retour = \"\"; for(i in test){ retour += i; } return retour;", new StringLeekValue("012345"))); } @Test public void foreachkeyvalTest() throws Exception { - Assert.assertTrue(testScript("var test = ['a':5,'b':8,'c':8,9:'p']; var retour = \"\"; for(var i : var j in test){ retour += i+':'+j; } return retour;", + Assert.assertTrue(testScript("var test = ['a':5,'b':8,'c':8,9:'p']; var retour = \"\"; for(var i : var j in test){ retour += i+':'+j; } return retour;", new StringLeekValue("a:5b:8c:89:p"))); } @@ -142,46 +141,46 @@ public void dowhileTest() throws Exception { // Test simples d'opérateurs @Test public void additionTest() throws Exception { - Assert.assertTrue(testScript("var test = 1 + 8; test += 3; test++; var a = 7; var b = 1; return [test, a+b, (1+1)+9.5, 'test'+8];", - new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(13), new IntLeekValue(8), new DoubleLeekValue(11.5), + Assert.assertTrue(testScript("var test = 1 + 8; test += 3; test++; var a = 7; var b = 1; return [test, a+b, (1+1)+9.5, 'test'+8];", + new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(13), new IntLeekValue(8), new DoubleLeekValue(11.5), new StringLeekValue("test8") }))); } @Test public void soustractionTest() throws Exception { - Assert.assertTrue(testScript("var test = 20 - 8; test -= 3; test--; var a = 7; var b = 1; return [test, a-b, (1-1)-9.5];", + Assert.assertTrue(testScript("var test = 20 - 8; test -= 3; test--; var a = 7; var b = 1; return [test, a-b, (1-1)-9.5];", new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(8), new IntLeekValue(6), new DoubleLeekValue(-9.5) }))); } @Test public void multiplicationTest() throws Exception { - Assert.assertTrue(testScript("var test = 4; test *= 3; var c = 7;return [test, 8*9, 2*c];", + Assert.assertTrue(testScript("var test = 4; test *= 3; var c = 7;return [test, 8*9, 2*c];", new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(12), new IntLeekValue(72), new DoubleLeekValue(14) }))); } @Test public void modulusTest() throws Exception { - Assert.assertTrue(testScript("var test = 4; test %= 3; var c = 7;return [test, 8%9, 8%c];", + Assert.assertTrue(testScript("var test = 4; test %= 3; var c = 7;return [test, 8%9, 8%c];", new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(1), new IntLeekValue(8), new DoubleLeekValue(1) }))); } @Test public void divisionTest() throws Exception { - Assert.assertTrue(testScript("var test = 7; test /= 2; var c = 7;return [test, 12/6, 14/c];", + Assert.assertTrue(testScript("var test = 7; test /= 2; var c = 7;return [test, 12/6, 14/c];", new ArrayLeekValue(ai, new AbstractLeekValue[] { new DoubleLeekValue(3.5), new IntLeekValue(2), new DoubleLeekValue(2) }))); } @Test public void operatorsTest() throws Exception { - AbstractLeekValue[] values = new AbstractLeekValue[] { new BooleanLeekValue(true), new BooleanLeekValue(false), + AbstractLeekValue[] values = new AbstractLeekValue[] { new BooleanLeekValue(true), new BooleanLeekValue(false), new BooleanLeekValue(true), new BooleanLeekValue(false), new BooleanLeekValue(false), new BooleanLeekValue(true), new BooleanLeekValue(false) }; - Assert.assertTrue(testScript("return [true && true, true && false, true || false, false || false, 1 > 3, 1 < 3, 4 == 7];", + Assert.assertTrue(testScript("return [true && true, true && false, true || false, false || false, 1 > 3, 1 < 3, 4 == 7];", new ArrayLeekValue(ai, values))); } @@ -196,7 +195,7 @@ public void prioritiesTest() throws Exception { new BooleanLeekValue(true), // 7*8 == 56 && 33 -8 new BooleanLeekValue(true) }; - Assert.assertTrue(testScript("return [1+6*2-3*2,7*8-1, 3*3-8>0, 7*8 == 56 && 33-8 ];", + Assert.assertTrue(testScript("return [1+6*2-3*2,7*8-1, 3*3-8>0, 7*8 == 56 && 33-8 ];", new ArrayLeekValue(ai, values))); } @@ -205,13 +204,13 @@ public void prioritiesTest() throws Exception { public void functionTest() throws Exception { Assert.assertTrue(testScript("function test(a){ return a+2; } return test(7);", 9)); } - + @Test public void divisionByZeroTest() throws Exception { Assert.assertTrue(testScript("return 8/0;", null)); Assert.assertTrue(testScript("return 8/null;", null)); } - + @Test public void whileReturnTest() throws Exception { Assert.assertTrue(LeekScript.testScript("var t = 0; while(t<5){ t++; return t;}", new IntLeekValue(1))); @@ -268,199 +267,6 @@ public void forEachKeyReturnTest() throws Exception { Assert.assertTrue(LeekScript.testScript("var tab = [1:0,2:1,3:2,4:3]; for(var i : var j in tab){ return i; } ", new IntLeekValue(1))); Assert.assertTrue(LeekScript.testScript("var tab = [1:0,2:1,3:2,4:3]; for(var i : var j in tab){ return i; } return 0;", new IntLeekValue(1))); } - - @Test - public void arrayMapTest() throws Exception { - - Assert.assertTrue(LeekScript.testScript("return arrayMap([1,2,3,4,5],function(e){ return e*2; });", new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(2), new IntLeekValue(4), new IntLeekValue(6), new IntLeekValue(8), new IntLeekValue(10) }))); - - Assert.assertTrue(LeekScript.testScript("return arrayMap([4,9,16],sqrt);", new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(2), new IntLeekValue(3), new IntLeekValue(4) }))); - - Assert.assertTrue(LeekScript.testScript("return arrayMap(['a':1,'b':2],function(k,v){ return k+v;});", new ArrayLeekValue(ai, new AbstractLeekValue[] { - new StringLeekValue("a"), new StringLeekValue("a1"), - new StringLeekValue("b"), new StringLeekValue("b2") }, true))); - - Assert.assertTrue(LeekScript.testScript("return function(){ var t = ['a':1,'b':2]; arrayMap(t,function(@k,@v){ v='tomate';k='ctus'; return 3;}); return t;}();", new ArrayLeekValue(ai, new AbstractLeekValue[] { new StringLeekValue("a"), - new StringLeekValue("tomate"), - new StringLeekValue("b"), - new StringLeekValue("tomate") }, true))); - } - - @Test - public void arrayFilterTest() throws Exception { - - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("arrayFilter([1,2,3,4,5,6,7,8,9],function(e){ return e>5; })"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(5), new IntLeekValue(6), new IntLeekValue(6), - new IntLeekValue(7), new IntLeekValue(7), - new IntLeekValue(8), new IntLeekValue(8), new IntLeekValue(9) }, true)); - - codes.add("arrayFilter([4,5,6,'test',8,9],function(e){ return e=='test'; })"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(3), new StringLeekValue("test") }, true)); - - codes.add("string(arrayFilter(['a','b','c','d'],function(k,v){ return k==3; }))"); - values.add("[3 : d]"); - - codes.add("string(function(){ var t = ['a','b','c','d']; arrayFilter(t,function(k,@v){ v=4; return k==3; }); return t;}())"); - values.add("[4, 4, 4, 4]"); - - codes.add("string(arrayFilter(['a','b','c','d'],function(k,@v){ v=4; return k==3; }))"); - values.add("[3 : 4]"); - - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void arrayFlatten() throws Exception { - - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("arrayFlatten([6,7,[8,9]],99)"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(6), new IntLeekValue(7), new IntLeekValue(8), new IntLeekValue(9) })); - - codes.add("arrayFlatten([6,[[7]],[8,9]],2)"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(6), new IntLeekValue(7), new IntLeekValue(8), new IntLeekValue(9) })); - - codes.add("arrayFlatten([6,[[7]],[8,9]])"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(6), new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(7) }), - new IntLeekValue(8), new IntLeekValue(9) })); - - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void arrayFoldLeft() throws Exception { - - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("arrayFoldLeft([6,7,8,9], function(a,b){return a+b;},0)"); - values.add(30); - - codes.add("arrayFoldLeft([1,0,1,2,5,7,9], function(a,b){return a+','+b;},'')"); - values.add(",1,0,1,2,5,7,9"); - - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void arrayFoldRight() throws Exception { - - // On lance le test - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("arrayFoldRight([6,7,8,9], function(a,b){return a+b;},0)"); - values.add(30); - - codes.add("arrayFoldRight([1,0,1,2,5,7,9], function(a,b){return a+','+b;},'')"); - values.add("1,0,1,2,5,7,9,"); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void arrayPartition() throws Exception { - - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("arrayPartition([6,7,8,9], function(a){return a&1;})"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(1), new IntLeekValue(7), new IntLeekValue(3), new IntLeekValue(9) }, true), - new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(0), new IntLeekValue(6), new IntLeekValue(2), new IntLeekValue(8) }, true) })); - - codes.add("string(arrayPartition([6,7,8,9], function(k,v){return k;}))"); - values.add("[[1 : 7, 2 : 8, 3 : 9], [6]]"); - - codes.add("string(arrayPartition([4,3,2,1], function(k,v){return k codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("string([0]+[1,2])"); - values.add("[0, 1, 2]"); - - codes.add("function(){ var a = [0,1]; a+= [3]; return string(a);}()"); - values.add("[0, 1, 3]"); - - codes.add("string(arrayConcat([0],[1,2]))"); - values.add("[0, 1, 2]"); - - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void arrayIter() throws Exception { - - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("string(function(){ var t = [1,2,3,4]; arrayIter(t, function(v){ v=2; }); return t; }())"); - values.add("[1, 2, 3, 4]"); - - codes.add("string(function(){ var t = [1,2,3,4]; arrayIter(t, function(@v){ v=2; }); return t; }())"); - values.add("[2, 2, 2, 2]"); - - codes.add("string(function(){ var t = [1,2,3,4]; arrayIter(t, function(k, @v){ v=k; }); return t; }())"); - values.add("[0, 1, 2, 3]"); - - codes.add("string(function(){ var t = [1,2,3,4]; arrayIter(t, function(k, v){ v=k; }); return t; }())"); - values.add("[1, 2, 3, 4]"); - - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void arraySort() throws Exception { - - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("string(function(){var t = [0,1,2]; return arraySort(t,function(e, f){return (e>f)?(-1):(ek2)?(-1):(k1k2)?(-1):(k1 codes = new ArrayList(); @@ -571,7 +377,7 @@ public void colorTest() throws Exception { // Test AI Assert.assertTrue(testAI(codes, values)); } - + @Test public void typeOfTest() throws Exception { @@ -613,7 +419,7 @@ public void stringTest() throws Exception { // Test nombre codes.add("'\\\\'"); - values.add("\\\\"); + values.add("\\"); // Test AI Assert.assertTrue(testAI(codes, values)); @@ -656,7 +462,7 @@ else if (c instanceof AbstractLeekValue) private boolean testScript(String leekscript, AbstractLeekValue value) throws Exception { if (value == null) value = new NullLeekValue(); - + return LeekScript.testScript(leekscript, value); } From 94405d6590570dfee2195ad4709c72900e86ae53 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 20 Feb 2021 23:27:38 +0100 Subject: [PATCH 082/319] [function] Check arguments count --- .../expression/LeekExpressionFunction.java | 18 +++ .../compiler/expression/LeekFunction.java | 140 ------------------ .../compiler/expression/LeekVariable.java | 4 + 3 files changed, 22 insertions(+), 140 deletions(-) delete mode 100644 src/main/java/leekscript/compiler/expression/LeekFunction.java diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 12108b55..b9edba0c 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -2,9 +2,12 @@ import java.util.ArrayList; +import leekscript.compiler.AnalyzeError; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; +import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.MainLeekBlock; +import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.expression.LeekVariable.VariableType; import leekscript.runner.LeekFunctions; @@ -93,5 +96,20 @@ public void analyze(WordCompiler compiler) { for (AbstractExpression parameter : mParameters) { parameter.analyze(compiler); } + + if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.FUNCTION) { + var v = (LeekVariable) mExpression; + int nb_params = LeekFunctions.isFunction(v.getName()); + if (nb_params == -1) { + nb_params = compiler.getMainBlock().getUserFunctionParametersCount(v.getName()); + if (mParameters.size() != nb_params) { + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, LeekCompilerException.INVALID_PAREMETER_COUNT)); + } + } else { + var f = LeekFunctions.getValue(v.getName()); + if (mParameters.size() > nb_params || mParameters.size() < f.getArgumentsMin()) + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, LeekCompilerException.INVALID_PAREMETER_COUNT)); + } + } } } diff --git a/src/main/java/leekscript/compiler/expression/LeekFunction.java b/src/main/java/leekscript/compiler/expression/LeekFunction.java deleted file mode 100644 index 3155ec14..00000000 --- a/src/main/java/leekscript/compiler/expression/LeekFunction.java +++ /dev/null @@ -1,140 +0,0 @@ -package leekscript.compiler.expression; - -import java.util.ArrayList; - -import leekscript.compiler.JavaWriter; -import leekscript.compiler.WordCompiler; -import leekscript.compiler.bloc.FunctionBlock; -import leekscript.compiler.bloc.MainLeekBlock; -import leekscript.compiler.exceptions.LeekCompilerException; -import leekscript.runner.ILeekFunction; -import leekscript.runner.LeekFunctions; - -public class LeekFunction extends AbstractExpression { - - private final boolean isClass; - private final String mName; - private final ArrayList mParameters = new ArrayList(); - - public LeekFunction(String name, boolean isClass) { - mName = name; - this.isClass = isClass; - } - - public void addParameter(AbstractExpression param) { - mParameters.add(param); - } - - @Override - public int getType() { - return FUNCTION; - } - - @Override - public String getString() { - String str = mName + "("; - for (int i = 0; i < mParameters.size(); i++) { - if (i > 0) - str += ", "; - str += mParameters.get(i).getString(); - } - return str + ")"; - } - - @Override - public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { - if (!isClass) { - int nb_params = LeekFunctions.isFunction(mName); - if (nb_params == -1) { - nb_params = mainblock.getUserFunctionParametersCount(mName); - if (nb_params == -1) { - throw new LeekExpressionException(this, LeekCompilerException.FUNCTION_NOT_EXISTS); - } else if (mParameters.size() != nb_params) { - throw new LeekExpressionException(this, LeekCompilerException.INVALID_PAREMETER_COUNT); - } - } - else { - ILeekFunction f = LeekFunctions.getValue(mName); - if (mParameters.size() > nb_params || mParameters.size() < f.getArgumentsMin()) - throw new LeekExpressionException(this, LeekCompilerException.INVALID_PAREMETER_COUNT); - } - } - - // Vérification de chaque paramètre - for (AbstractExpression parameter : mParameters) { - parameter.validExpression(compiler, mainblock); - } - return true; - } - - @Override - public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if (isClass) { - writer.addCode("user_" + mName + ".executeFunction(mUAI, new AbstractLeekValue[] {"); - for (int i = 0; i < mParameters.size(); i++) { - if (i > 0) - writer.addCode(", "); - mParameters.get(i).writeJavaCode(mainblock, writer); - } - writer.addCode("})"); - return; - } - if (mainblock.isRedefinedFunction(mName)) { - writer.addCode("rfunction_" + mName); - writer.addCode(".executeFunction(mUAI, new AbstractLeekValue[]{"); - for (int i = 0; i < mParameters.size(); i++) { - if (i > 0) - writer.addCode(", "); - if (i < mParameters.size()) - mParameters.get(i).writeJavaCode(mainblock, writer); - else - writer.addCode("LeekValueManager.NULL"); - } - writer.addCode("})"); - } - else { - FunctionBlock user_function = mainblock.getUserFunction(mName); - if (user_function != null) { - writer.addCode("user_function_" + mName + "("); - - for (int i = 0; i < mParameters.size(); i++) { - if (i > 0) - writer.addCode(", "); - if (user_function.isReference(i)) - mParameters.get(i).writeJavaCode(mainblock, writer); - else { - writer.addCode("LeekOperations.clone(mUAI, "); - mParameters.get(i).writeJavaCode(mainblock, writer); - writer.addCode(".getValue())"); - } - } - writer.addCode(")"); - } - else { - ILeekFunction fun = LeekFunctions.getValue(mName); - int nb_params = fun.getArguments(); - if (!writer.hasDebug() && (mName.equals("debug") || mName.equalsIgnoreCase("mark") || mName.equals("pause"))) { - writer.addCode("nothing(LeekValueManager.NULL)"); - return; - } - writer.addCode("LeekFunctions.executeFunction(mUAI, " + fun.getNamespace() + "." + mName + ", new AbstractLeekValue[]{"); - for (int i = 0; i < nb_params; i++) { - if (i > 0) - writer.addCode(", "); - if (i < mParameters.size()) { - mParameters.get(i).writeJavaCode(mainblock, writer); - writer.addCode(".getValue()"); - } - else - writer.addCode("LeekValueManager.NULL"); - } - writer.addCode("}, " + mParameters.size() + ")"); - } - } - } - - @Override - public void analyze(WordCompiler compiler) { - - } -} diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index dd4cf7a6..a360b7d1 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -121,4 +121,8 @@ public void analyze(WordCompiler compiler) { public ClassDeclarationInstruction getClassDeclaration() { return classDeclaration; } + + public IAWord getToken() { + return token; + } } From 9c3aad157fd035a74bcbaff49cb351292536d332 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 20 Feb 2021 23:27:38 +0100 Subject: [PATCH 083/319] [global] Don't check global variables in v1.0 (issue with includes) --- .../instruction/LeekVariableDeclarationInstruction.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index e0ce77c4..bec9fbc1 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -81,9 +81,10 @@ public void analyze(WordCompiler compiler) { compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.THIS_NOT_ALLOWED_HERE)); } else { // Vérification déjà existante (on vérifie les globales seulement en 1.1 car il y a un léger bug en 1.0 avec les includes) - if (compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(token.getWord()) || compiler.getMainBlock().hasUserFunction(token.getWord(), true)) || compiler.getCurrentBlock().hasVariable(token.getWord())) { + if ((compiler.getVersion() >= 11 && compiler.getMainBlock().hasGlobal(token.getWord())) || compiler.getMainBlock().hasUserFunction(token.getWord(), true) || compiler.getCurrentBlock().hasVariable(token.getWord())) { compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); } else { + // On ajoute la variable compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.LOCAL)); } } From b909b7d53740c0fde3f5737d0a618a8d1c80383b Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 20 Feb 2021 23:27:38 +0100 Subject: [PATCH 084/319] [compiler] Add error for declaring this --- .../compiler/instruction/LeekGlobalDeclarationInstruction.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java index b79271b8..27b6a66e 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java @@ -63,6 +63,7 @@ public boolean putCounterBefore() { public void declare(WordCompiler compiler) { // Variables interdites if (token.getWord().equals("this")) { + compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.THIS_NOT_ALLOWED_HERE)); } else { // Vérification déjà existante (on vérifie les globales seulement en 1.1 car il y a un léger bug en 1.0 avec les includes) if ((compiler.getVersion() >= 11 && compiler.getMainBlock().hasGlobal(token.getWord())) || compiler.getMainBlock().hasUserFunction(token.getWord(), true)) { From e92809f830ae73b80cfbbd26a2ce6c827aaa0c72 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 20 Feb 2021 23:27:38 +0100 Subject: [PATCH 085/319] [function] Improve function call --- .../expression/LeekExpressionFunction.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index b9edba0c..56cb5c23 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -55,6 +55,7 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { boolean addComma = true; + boolean userFunction = false; if (mExpression instanceof LeekObjectAccess) { var object = ((LeekObjectAccess) mExpression).getObject(); object.writeJavaCode(mainblock, writer); @@ -74,6 +75,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(((LeekVariable) mExpression).getName()); writer.addCode("("); addComma = false; + userFunction = true; } else { mExpression.writeJavaCode(mainblock, writer); writer.addCode(".executeFunction(mUAI"); @@ -81,8 +83,19 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { for (int i = 0; i < mParameters.size(); i++) { if (i > 0 || addComma) writer.addCode(", "); if (i < mParameters.size()) { - mParameters.get(i).writeJavaCode(mainblock, writer); - writer.addCode(".getValue()"); + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + mParameters.get(i).writeJavaCode(mainblock, writer); + writer.addCode(".getValue()"); + } else { + if (userFunction) { + writer.addCode("LeekOperations.clone(mUAI, "); + mParameters.get(i).writeJavaCode(mainblock, writer); + writer.addCode(".getValue())"); + } else { + mParameters.get(i).writeJavaCode(mainblock, writer); + writer.addCode(".getValue()"); + } + } } else { writer.addCode("LeekValueManager.NULL"); } From c9d43fbef1fa5b9f2f90d981e222dd2fc2a5fce2 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 20 Feb 2021 23:27:38 +0100 Subject: [PATCH 086/319] [function] Copy arguments for user functions in v1.0 --- .../expression/LeekExpressionFunction.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 56cb5c23..b8a8ddfb 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -6,6 +6,7 @@ import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; +import leekscript.compiler.bloc.FunctionBlock; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.expression.LeekVariable.VariableType; @@ -55,7 +56,7 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { boolean addComma = true; - boolean userFunction = false; + FunctionBlock user_function = null; if (mExpression instanceof LeekObjectAccess) { var object = ((LeekObjectAccess) mExpression).getObject(); object.writeJavaCode(mainblock, writer); @@ -75,7 +76,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(((LeekVariable) mExpression).getName()); writer.addCode("("); addComma = false; - userFunction = true; + user_function = mainblock.getUserFunction(((LeekVariable) mExpression).getName()); } else { mExpression.writeJavaCode(mainblock, writer); writer.addCode(".executeFunction(mUAI"); @@ -87,10 +88,14 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { mParameters.get(i).writeJavaCode(mainblock, writer); writer.addCode(".getValue()"); } else { - if (userFunction) { - writer.addCode("LeekOperations.clone(mUAI, "); - mParameters.get(i).writeJavaCode(mainblock, writer); - writer.addCode(".getValue())"); + if (user_function != null) { + if (user_function.isReference(i)) + mParameters.get(i).writeJavaCode(mainblock, writer); + else { + writer.addCode("LeekOperations.clone(mUAI, "); + mParameters.get(i).writeJavaCode(mainblock, writer); + writer.addCode(".getValue())"); + } } else { mParameters.get(i).writeJavaCode(mainblock, writer); writer.addCode(".getValue()"); From 1e60fd51af56610626c5ad516bc259494b578217 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 20 Feb 2021 23:27:38 +0100 Subject: [PATCH 087/319] [global] Check global directly --- .../java/leekscript/compiler/WordCompiler.java | 10 ++++++---- .../LeekGlobalDeclarationInstruction.java | 14 ++------------ 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 57411c51..d917764e 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -584,8 +584,9 @@ private void globalDeclaration() throws LeekCompilerException { throw new LeekCompilerException(word, LeekCompilerException.GLOBAL_ONLY_IN_MAIN_BLOCK); if (word.getType() != WordParser.T_STRING) throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED_AFTER_GLOBAL); - // if (!isGlobalAvailable(word.getWord()) || mMain.hasDeclaredGlobal(word.getWord())) - // throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); + if (!isGlobalAvailable(word.getWord()) || mMain.hasDeclaredGlobal(word.getWord())) { + addError(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); + } LeekGlobalDeclarationInstruction variable = new LeekGlobalDeclarationInstruction(word, mLine, mAI); // On regarde si une valeur est assignée if (mCompiler.getWord().getWord().equals("=")) { @@ -602,8 +603,9 @@ private void globalDeclaration() throws LeekCompilerException { word = mCompiler.readWord(); if (word.getType() != WordParser.T_STRING) throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED); - // if (!isGlobalAvailable(word.getWord()) || mMain.hasDeclaredGlobal(word.getWord())) - // throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); + if (!isGlobalAvailable(word.getWord()) || mMain.hasDeclaredGlobal(word.getWord())) { + addError(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); + } variable = new LeekGlobalDeclarationInstruction(word, mLine, mAI); // On regarde si une valeur est assign�e if (mCompiler.getWord().getWord().equals("=")) { diff --git a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java index 27b6a66e..9b05bd7b 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java @@ -61,18 +61,8 @@ public boolean putCounterBefore() { } public void declare(WordCompiler compiler) { - // Variables interdites - if (token.getWord().equals("this")) { - compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.THIS_NOT_ALLOWED_HERE)); - } else { - // Vérification déjà existante (on vérifie les globales seulement en 1.1 car il y a un léger bug en 1.0 avec les includes) - if ((compiler.getVersion() >= 11 && compiler.getMainBlock().hasGlobal(token.getWord())) || compiler.getMainBlock().hasUserFunction(token.getWord(), true)) { - compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); - } else { - // On ajoute la variable - compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.GLOBAL)); - } - } + // On ajoute la variable + compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.GLOBAL)); } @Override From bea6d052b6e1d8d71c17c3ef0ac0ba06ae003fe5 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 20 Feb 2021 23:27:38 +0100 Subject: [PATCH 088/319] [variable-declaration] Analyze value first --- .../instruction/LeekVariableDeclarationInstruction.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index bec9fbc1..a51208c3 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -76,6 +76,9 @@ public boolean putCounterBefore() { @Override public void analyze(WordCompiler compiler) { + if (mValue != null) { + mValue.analyze(compiler); + } // Variables interdites if (token.getWord().equals("this")) { compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.THIS_NOT_ALLOWED_HERE)); @@ -88,8 +91,5 @@ public void analyze(WordCompiler compiler) { compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.LOCAL)); } } - if (mValue != null) { - mValue.analyze(compiler); - } } } From 953f6fc4a93d4645e47f9aa0e5aa4b28febcd5ca Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 20 Feb 2021 23:27:38 +0100 Subject: [PATCH 089/319] [global] Optimize globals and fixes --- .../leekscript/compiler/WordCompiler.java | 34 ++++++++++++------- .../compiler/bloc/MainLeekBlock.java | 3 +- .../compiler/expression/LeekGlobal.java | 2 +- .../compiler/expression/LeekVariable.java | 2 ++ .../LeekGlobalDeclarationInstruction.java | 15 ++++---- .../runner/values/VariableLeekValue.java | 22 ++++++++++++ 6 files changed, 55 insertions(+), 23 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index d917764e..2f0fb201 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -70,12 +70,28 @@ public void readCode() throws LeekCompilerException { while (mCompiler.haveWords()) { if (mCompiler.getWord().getWord().equals("global")) { mCompiler.skipWord(); - String globalName = mCompiler.readWord().getWord(); - mMain.addGlobal(globalName); - while (mCompiler.getWord().getType() == WordParser.T_VIRG && mCompiler.haveWords()) { + var global = mCompiler.readWord(); + if (!isGlobalAvailable(global.getWord()) || mMain.hasDeclaredGlobal(global.getWord())) { + addError(new AnalyzeError(global, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); + } else { + mMain.addGlobal(global.getWord()); + } + if (mCompiler.getWord().getWord().equals("=")) { mCompiler.skipWord(); - globalName = mCompiler.readWord().getWord(); - mMain.addGlobal(globalName); + readExpression(); + } + while (mCompiler.haveWords() && mCompiler.getWord().getType() == WordParser.T_VIRG) { + mCompiler.skipWord(); + global = mCompiler.readWord(); + if (!isGlobalAvailable(global.getWord()) || mMain.hasDeclaredGlobal(global.getWord())) { + addError(new AnalyzeError(global, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); + } else { + mMain.addGlobal(global.getWord()); + } + if (mCompiler.getWord().getWord().equals("=")) { + mCompiler.skipWord(); + readExpression(); + } } } else if (mCompiler.getWord().getWord().equals("function")) { mCompiler.skipWord(); @@ -584,9 +600,6 @@ private void globalDeclaration() throws LeekCompilerException { throw new LeekCompilerException(word, LeekCompilerException.GLOBAL_ONLY_IN_MAIN_BLOCK); if (word.getType() != WordParser.T_STRING) throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED_AFTER_GLOBAL); - if (!isGlobalAvailable(word.getWord()) || mMain.hasDeclaredGlobal(word.getWord())) { - addError(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); - } LeekGlobalDeclarationInstruction variable = new LeekGlobalDeclarationInstruction(word, mLine, mAI); // On regarde si une valeur est assignée if (mCompiler.getWord().getWord().equals("=")) { @@ -603,9 +616,6 @@ private void globalDeclaration() throws LeekCompilerException { word = mCompiler.readWord(); if (word.getType() != WordParser.T_STRING) throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED); - if (!isGlobalAvailable(word.getWord()) || mMain.hasDeclaredGlobal(word.getWord())) { - addError(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); - } variable = new LeekGlobalDeclarationInstruction(word, mLine, mAI); // On regarde si une valeur est assign�e if (mCompiler.getWord().getWord().equals("=")) { @@ -614,7 +624,7 @@ private void globalDeclaration() throws LeekCompilerException { variable.setValue(readExpression().getAbstractExpression()); } // On ajoute la variable - mMain.addGlobal(variable.getName()); + mMain.addGlobalDeclaration(variable); mCurentBlock.addInstruction(this, variable); } // word = mCompiler.readWord(); diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index ff038700..50c5b308 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -186,7 +186,8 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { // Variables globales for (String global : mGlobales) { - writer.addLine("private VariableLeekValue globale_" + global + " = null;"); + writer.addLine("private VariableLeekValue globale_" + global + " = new VariableLeekValue(mUAI);"); + writer.addLine("private boolean globale_init_" + global + " = false;"); } // Fonctions redéfinies for (String redefined : mRedefinedFunctions) { diff --git a/src/main/java/leekscript/compiler/expression/LeekGlobal.java b/src/main/java/leekscript/compiler/expression/LeekGlobal.java index c5b6bb00..583b6886 100644 --- a/src/main/java/leekscript/compiler/expression/LeekGlobal.java +++ b/src/main/java/leekscript/compiler/expression/LeekGlobal.java @@ -31,7 +31,7 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addCode("(globale_" + token.getWord() + "==null?LeekValueManager.NULL:globale_" + token.getWord() + ")"); + writer.addCode("globale_" + token.getWord()); } @Override diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index a360b7d1..cf8ff79a 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -78,6 +78,8 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("LeekValueManager.getFunction(" + namespace + "." + token.getWord() + ")"); } } + } else if (type == VariableType.GLOBAL) { + writer.addCode("globale_" + token.getWord()); } else { writer.addCode("user_" + token.getWord()); } diff --git a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java index 9b05bd7b..00110381 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java @@ -1,13 +1,10 @@ package leekscript.compiler.instruction; import leekscript.compiler.AIFile; -import leekscript.compiler.AnalyzeError; import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; -import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.MainLeekBlock; -import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; @@ -40,14 +37,14 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addCode("if(globale_" + token.getWord() + " == null){globale_" + token.getWord() + " = new VariableLeekValue(mUAI, "); + writer.addCode("if (!globale_init_" + token.getWord() + ") { globale_" + token.getWord() + ".initGlobal(mUAI, "); if(mValue != null) mValue.writeJavaCode(mainblock, writer); else writer.addCode("LeekValueManager.NULL"); - writer.addLine(");}", mLine, mAI); - } - - public String getJavaDeclaration() { - return "private VariableLeekValue globale_" + token.getWord() + " = null;"; + writer.addCode("); globale_init_" + token.getWord() + " = true;"); + if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10) { + writer.addCounter(1); // Add one operation in LS 1.0 + } + writer.addLine("}", mLine, mAI); } @Override diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index 6d6ab236..18d8e2f0 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -2,6 +2,8 @@ import java.util.Set; +import com.leekwars.generator.fight.statistics.FarmerStatistics.LeekValue; + import leekscript.runner.AI; import leekscript.runner.LeekOperations; import leekscript.runner.LeekRunException; @@ -12,6 +14,11 @@ public class VariableLeekValue extends AbstractLeekValue { protected AbstractLeekValue mValue; protected AI mUAI = null; + public VariableLeekValue(AI ai) throws LeekRunException { + mUAI = ai; + mValue = LeekValueManager.NULL; + } + public VariableLeekValue(AI ai, AbstractLeekValue value) throws LeekRunException { mUAI = ai; ai.addOperations(1); @@ -92,6 +99,21 @@ public AbstractLeekValue setRef(AI ai, AbstractLeekValue value) throws LeekRunEx return mValue = value.getValue(); } + public void initGlobal(AI ai, AbstractLeekValue value) throws LeekRunException { + if (value instanceof VariableLeekValue) { + if (ai.getVersion() >= 11) { + mValue = LeekOperations.clonePrimitive(ai, value.getValue()); + } else { + if (value.isReference()) + mValue = value.getValue(); + else + mValue = LeekOperations.clone(ai, value.getValue()); + } + } else { + mValue = value.getValue(); + } + } + @Override public AbstractLeekValue increment(AI ai) throws LeekRunException { mValue = mValue.getValue(); From 6d3ffa7753dd3701672b0b97e4a87274f839f251 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 20 Feb 2021 23:27:38 +0100 Subject: [PATCH 090/319] [compiler] Fix function call and expression --- .../java/leekscript/compiler/IACompiler.java | 6 ++ .../compiler/expression/LeekExpression.java | 49 ++++++++-------- .../expression/LeekExpressionFunction.java | 8 ++- .../expression/LeekFunctionValue.java | 57 ------------------- 4 files changed, 38 insertions(+), 82 deletions(-) delete mode 100644 src/main/java/leekscript/compiler/expression/LeekFunctionValue.java diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index ed17f9c5..98faa56c 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -76,7 +76,13 @@ public String compile(AIFile ai, String javaClassName, String AIClass) throws WordCompiler compiler = new WordCompiler(parser, main, ai, ai.getVersion()); compiler.readCode(); compiler.analyze(); + System.out.println("errors " + compiler.getErrors().size()); + if (compiler.getErrors().size() > 0) { + for (var error : compiler.getErrors()) { + throw new LeekCompilerException(error.token, error.error, error.parameters); + } + } compiler.writeJava(javaClassName, writer, AIClass); } catch (LeekCompilerException e) { diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index 13199c3d..36fb8a36 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -7,6 +7,7 @@ import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.exceptions.LeekCompilerException; +import leekscript.compiler.expression.LeekVariable.VariableType; public class LeekExpression extends AbstractExpression { @@ -311,8 +312,10 @@ else if (mOperator == -1) { mExpression1 = trn; } } - else + else { mOperator = operator; + mOperatorToken = token; + } } else { int cur_p = Operators.getPriority(mOperator); @@ -404,28 +407,6 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t if (mExpression1 == null || mExpression2 == null || mOperator == -1) throw new LeekExpressionException(this, LeekCompilerException.UNCOMPLETE_EXPRESSION); - // Si on a affaire à une assignation, incrémentation ou autre du genre - // on doit vérifier qu'on a bien une variable (l-value) - if (mOperator == Operators.ADDASSIGN || mOperator == Operators.MINUSASSIGN || mOperator == Operators.DIVIDEASSIGN || mOperator == Operators.ASSIGN || mOperator == Operators.MODULUSASSIGN - || mOperator == Operators.MULTIPLIEASSIGN || mOperator == Operators.POWERASSIGN) { - if (!mExpression1.isLeftValue()) - compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.CANT_ASSIGN_VALUE)); - // throw new LeekExpressionException(mExpression1, LeekCompilerException.CANT_ASSIGN_VALUE); - if (mExpression1 instanceof LeekFunctionValue) - mainblock.addRedefinedFunction(((LeekFunctionValue) mExpression1).getFunctionName()); - if (mExpression1 instanceof LeekTabularValue) - ((LeekTabularValue) mExpression1).setLeftValue(true); - } - if (mOperator == Operators.INCREMENT || mOperator == Operators.DECREMENT || mOperator == Operators.PRE_INCREMENT || mOperator == Operators.PRE_DECREMENT) { - if (!(mExpression2 instanceof LeekFunctionValue) && !(mExpression2 instanceof LeekVariable) && !(mExpression2 instanceof LeekGlobal) && !(mExpression2 instanceof LeekTabularValue)) - compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.CANT_ASSIGN_VALUE)); - // throw new LeekExpressionException(mExpression2, LeekCompilerException.CANT_ASSIGN_VALUE); - if (mExpression2 instanceof LeekFunctionValue) - mainblock.addRedefinedFunction(((LeekFunctionValue) mExpression2).getFunctionName()); - if (mExpression2 instanceof LeekTabularValue) - ((LeekTabularValue) mExpression2).setLeftValue(true); - } - return mExpression1.validExpression(compiler, mainblock) && mExpression2.validExpression(compiler, mainblock); } @@ -739,5 +720,27 @@ public boolean isLeftValue() { public void analyze(WordCompiler compiler) { if (mExpression1 != null) mExpression1.analyze(compiler); if (mExpression2 != null) mExpression2.analyze(compiler); + + // Si on a affaire à une assignation, incrémentation ou autre du genre + // on doit vérifier qu'on a bien une variable (l-value) + if (mOperator == Operators.ADDASSIGN || mOperator == Operators.MINUSASSIGN || mOperator == Operators.DIVIDEASSIGN || mOperator == Operators.ASSIGN || mOperator == Operators.MODULUSASSIGN || mOperator == Operators.MULTIPLIEASSIGN || mOperator == Operators.POWERASSIGN) { + if (!mExpression1.isLeftValue()) + compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.CANT_ASSIGN_VALUE)); + // throw new LeekExpressionException(mExpression1, LeekCompilerException.CANT_ASSIGN_VALUE); + if (mExpression1 instanceof LeekVariable && ((LeekVariable) mExpression1).getVariableType() == VariableType.SYSTEM_FUNCTION) + compiler.getMainBlock().addRedefinedFunction(((LeekVariable) mExpression1).getName()); + if (mExpression1 instanceof LeekTabularValue) + ((LeekTabularValue) mExpression1).setLeftValue(true); + } + + if (mOperator == Operators.INCREMENT || mOperator == Operators.DECREMENT || mOperator == Operators.PRE_INCREMENT || mOperator == Operators.PRE_DECREMENT) { + if (!(mExpression2 instanceof LeekVariable) && !(mExpression2 instanceof LeekGlobal) && !(mExpression2 instanceof LeekTabularValue)) + compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.CANT_ASSIGN_VALUE)); + // throw new LeekExpressionException(mExpression2, LeekCompilerException.CANT_ASSIGN_VALUE); + if (mExpression2 instanceof LeekVariable && ((LeekVariable) mExpression2).getVariableType() == VariableType.SYSTEM_FUNCTION) + compiler.getMainBlock().addRedefinedFunction(((LeekVariable) mExpression2).getName()); + if (mExpression2 instanceof LeekTabularValue) + ((LeekTabularValue) mExpression2).setLeftValue(true); + } } } diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index b8a8ddfb..e4e9ae51 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -68,8 +68,12 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.SYSTEM_FUNCTION) { var variable = (LeekVariable) mExpression; - String namespace = LeekFunctions.getNamespace(variable.getName()); - writer.addCode("LeekValueManager.getFunction(" + namespace + "." + variable.getName() + ")"); + if (mainblock.isRedefinedFunction(variable.getName())) { + writer.addCode("rfunction_" + variable.getName()); + } else { + String namespace = LeekFunctions.getNamespace(variable.getName()); + writer.addCode("LeekValueManager.getFunction(" + namespace + "." + variable.getName() + ")"); + } writer.addCode(".executeFunction(mUAI"); } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.FUNCTION) { writer.addCode("user_function_"); diff --git a/src/main/java/leekscript/compiler/expression/LeekFunctionValue.java b/src/main/java/leekscript/compiler/expression/LeekFunctionValue.java deleted file mode 100644 index a4dfa82d..00000000 --- a/src/main/java/leekscript/compiler/expression/LeekFunctionValue.java +++ /dev/null @@ -1,57 +0,0 @@ -package leekscript.compiler.expression; - -import leekscript.compiler.JavaWriter; -import leekscript.compiler.WordCompiler; -import leekscript.compiler.bloc.FunctionBlock; -import leekscript.compiler.bloc.MainLeekBlock; - -public class LeekFunctionValue extends AbstractExpression { - - private final String mFunctionName; - private final String mFunctionNamespace; - - public LeekFunctionValue(String funcname, String namespace) { - mFunctionName = funcname; - mFunctionNamespace = namespace; - } - - @Override - public int getType() { - return 0; - } - - @Override - public String getString() { - return "Fonction[" + mFunctionName + "]"; - } - - @Override - public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - // return "Fonction[" + mFunctionName + "]"; - // FunctionLeekValue - if (mainblock.isRedefinedFunction(mFunctionName)) { - writer.addCode("rfunction_" + mFunctionName); - } else { - FunctionBlock user_function = mainblock.getUserFunction(mFunctionName); - if (user_function != null) { - writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); - } else { - writer.addCode("LeekValueManager.getFunction(" + mFunctionNamespace + "." + mFunctionName + ")"); - } - } - } - - @Override - public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { - return true; - } - - public String getFunctionName() { - return mFunctionName; - } - - @Override - public void analyze(WordCompiler compiler) { - - } -} From 7996787694b9e9ef484821a91d4302a03d66d576 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 20 Feb 2021 23:27:38 +0100 Subject: [PATCH 091/319] [constant] Handle constants as variables --- .../leekscript/compiler/WordCompiler.java | 4 -- .../compiler/expression/LeekConstant.java | 46 ------------------- .../compiler/expression/LeekVariable.java | 12 ++++- .../runner/values/VariableLeekValue.java | 2 - 4 files changed, 11 insertions(+), 53 deletions(-) delete mode 100644 src/main/java/leekscript/compiler/expression/LeekConstant.java diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 2f0fb201..b3794820 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -20,7 +20,6 @@ import leekscript.compiler.expression.LeekAnonymousFunction; import leekscript.compiler.expression.LeekArray; import leekscript.compiler.expression.LeekBoolean; -import leekscript.compiler.expression.LeekConstant; import leekscript.compiler.expression.LeekExpression; import leekscript.compiler.expression.LeekExpressionException; import leekscript.compiler.expression.LeekExpressionFunction; @@ -42,7 +41,6 @@ import leekscript.compiler.instruction.LeekGlobalDeclarationInstruction; import leekscript.compiler.instruction.LeekReturnInstruction; import leekscript.compiler.instruction.LeekVariableDeclarationInstruction; -import leekscript.runner.LeekConstants; public class WordCompiler { @@ -1003,8 +1001,6 @@ else if (word.getWord().equalsIgnoreCase("null")) retour.addExpression(new LeekNull()); else if (word.getWord().equalsIgnoreCase("not")) retour.addUnaryPrefix(Operators.NOT, word); - else if (LeekConstants.get(word.getWord()) != null) - retour.addExpression(new LeekConstant(word.getWord(), LeekConstants.get(word.getWord()))); else if (getVersion() >= 11 && word.getWord().equalsIgnoreCase("new")) { retour.addUnaryPrefix(Operators.NEW, word); } else if (word.getWord().equals("super")) { diff --git a/src/main/java/leekscript/compiler/expression/LeekConstant.java b/src/main/java/leekscript/compiler/expression/LeekConstant.java deleted file mode 100644 index 92c7c52e..00000000 --- a/src/main/java/leekscript/compiler/expression/LeekConstant.java +++ /dev/null @@ -1,46 +0,0 @@ -package leekscript.compiler.expression; - -import leekscript.compiler.JavaWriter; -import leekscript.compiler.WordCompiler; -import leekscript.compiler.bloc.MainLeekBlock; -import leekscript.runner.ILeekConstant; -import leekscript.runner.LeekFunctions; - -public class LeekConstant extends AbstractExpression { - - private final String mConstantName; - private final ILeekConstant mConstant; - - public LeekConstant(String word, ILeekConstant constant) { - mConstantName = word; - mConstant = constant; - } - - @Override - public int getType() { - return 0; - } - - @Override - public String getString() { - return mConstantName; - } - - @Override - public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if (mConstant.getType() == LeekFunctions.INT) writer.addCode("LeekValueManager.getLeekIntValue(" + mConstant.getIntValue() + ")"); - else if (mConstant.getType() == LeekFunctions.DOUBLE) writer.addCode("new DoubleLeekValue(" + mConstant.getValue() + ")"); - else writer.addCode("LeekValueManager.NULL"); - } - - @Override - public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { - // La vérification se fait en amont - return true; - } - - @Override - public void analyze(WordCompiler compiler) { - - } -} diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index cf8ff79a..5665d36e 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -9,12 +9,13 @@ import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.instruction.ClassDeclarationInstruction; +import leekscript.runner.LeekConstants; import leekscript.runner.LeekFunctions; public class LeekVariable extends AbstractExpression { public static enum VariableType { - LOCAL, GLOBAL, ARGUMENT, FIELD, STATIC_FIELD, THIS, THIS_CLASS, CLASS, SUPER, METHOD, STATIC_METHOD, SYSTEM_FUNCTION, FUNCTION + LOCAL, GLOBAL, ARGUMENT, FIELD, STATIC_FIELD, THIS, THIS_CLASS, CLASS, SUPER, METHOD, STATIC_METHOD, SYSTEM_CONSTANT, SYSTEM_FUNCTION, FUNCTION } private final IAWord token; @@ -66,6 +67,11 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { if (type == VariableType.FUNCTION) { FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); + } else if (type == VariableType.SYSTEM_CONSTANT) { + var constant = LeekConstants.get(token.getWord()); + if (constant.getType() == LeekFunctions.INT) writer.addCode("LeekValueManager.getLeekIntValue(" + constant.getIntValue() + ")"); + else if (constant.getType() == LeekFunctions.DOUBLE) writer.addCode("new DoubleLeekValue(" + constant.getValue() + ")"); + else writer.addCode("LeekValueManager.NULL"); } else if (type == VariableType.SYSTEM_FUNCTION) { if (mainblock.isRedefinedFunction(token.getWord())) { writer.addCode("rfunction_" + token.getWord()); @@ -113,6 +119,10 @@ public void analyze(WordCompiler compiler) { this.classDeclaration = v.getClassDeclaration(); return; } + if (LeekConstants.get(token.getWord()) != null) { + this.type = VariableType.SYSTEM_CONSTANT; + return; + } if (LeekFunctions.isFunction(token.getWord()) != -1) { this.type = VariableType.SYSTEM_FUNCTION; return; diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index 18d8e2f0..7359e75e 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -2,8 +2,6 @@ import java.util.Set; -import com.leekwars.generator.fight.statistics.FarmerStatistics.LeekValue; - import leekscript.runner.AI; import leekscript.runner.LeekOperations; import leekscript.runner.LeekRunException; From 1ab33290bfb74d9fe8994b68439b2e5245564497 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 22:06:02 +0100 Subject: [PATCH 092/319] [function] Fix system function calls --- .../expression/LeekExpressionFunction.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index e4e9ae51..4b49fb40 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -10,6 +10,7 @@ import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.runner.ILeekFunction; import leekscript.runner.LeekFunctions; public class LeekExpressionFunction extends AbstractExpression { @@ -57,6 +58,7 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { boolean addComma = true; FunctionBlock user_function = null; + ILeekFunction system_function = null; if (mExpression instanceof LeekObjectAccess) { var object = ((LeekObjectAccess) mExpression).getObject(); object.writeJavaCode(mainblock, writer); @@ -70,11 +72,14 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { var variable = (LeekVariable) mExpression; if (mainblock.isRedefinedFunction(variable.getName())) { writer.addCode("rfunction_" + variable.getName()); + writer.addCode(".executeFunction(mUAI"); } else { + system_function = LeekFunctions.getValue(variable.getName()); String namespace = LeekFunctions.getNamespace(variable.getName()); - writer.addCode("LeekValueManager.getFunction(" + namespace + "." + variable.getName() + ")"); + // writer.addCode("LeekValueManager.getFunction(" + namespace + "." + variable.getName() + ")"); + writer.addCode("LeekFunctions.executeFunction(mUAI, " + namespace + "." + variable.getName() + ", new AbstractLeekValue[] {"); + addComma = false; } - writer.addCode(".executeFunction(mUAI"); } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.FUNCTION) { writer.addCode("user_function_"); writer.addCode(((LeekVariable) mExpression).getName()); @@ -85,12 +90,14 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { mExpression.writeJavaCode(mainblock, writer); writer.addCode(".executeFunction(mUAI"); } - for (int i = 0; i < mParameters.size(); i++) { + int argCount = mParameters.size(); + if (system_function != null) argCount = Math.max(argCount, system_function.getArguments()); + for (int i = 0; i < argCount; i++) { if (i > 0 || addComma) writer.addCode(", "); if (i < mParameters.size()) { if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { mParameters.get(i).writeJavaCode(mainblock, writer); - writer.addCode(".getValue()"); + // writer.addCode(".getValue()"); } else { if (user_function != null) { if (user_function.isReference(i)) @@ -109,6 +116,9 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("LeekValueManager.NULL"); } } + if (system_function != null) { + writer.addCode("}, " + mParameters.size()); + } writer.addCode(")"); } From b046daf98252ec0325c0fe92ba07da607a44830b Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 22:06:02 +0100 Subject: [PATCH 093/319] [function] Fix function call --- .../compiler/expression/LeekExpressionFunction.java | 8 +++++--- .../instruction/LeekGlobalDeclarationInstruction.java | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 4b49fb40..b685d5b0 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -100,16 +100,18 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { // writer.addCode(".getValue()"); } else { if (user_function != null) { - if (user_function.isReference(i)) + if (user_function.isReference(i)) { mParameters.get(i).writeJavaCode(mainblock, writer); - else { + } else { writer.addCode("LeekOperations.clone(mUAI, "); mParameters.get(i).writeJavaCode(mainblock, writer); writer.addCode(".getValue())"); } - } else { + } else if (system_function != null) { mParameters.get(i).writeJavaCode(mainblock, writer); writer.addCode(".getValue()"); + } else { + mParameters.get(i).writeJavaCode(mainblock, writer); } } } else { diff --git a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java index 00110381..7a4121a6 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java @@ -44,7 +44,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10) { writer.addCounter(1); // Add one operation in LS 1.0 } - writer.addLine("}", mLine, mAI); + writer.addLine(" }", mLine, mAI); } @Override From 0f9287e53cbe2a94b0361e71f7a7bc25bb85df1f Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 22:06:02 +0100 Subject: [PATCH 094/319] [array] Remove size calculation --- src/main/java/leekscript/runner/PhpArray.java | 30 ------------------- .../runner/values/AbstractLeekValue.java | 4 --- .../runner/values/ArrayLeekValue.java | 5 ---- .../runner/values/BooleanLeekValue.java | 5 ---- .../runner/values/ClassLeekValue.java | 5 ---- .../runner/values/DoubleLeekValue.java | 5 ---- .../runner/values/IntLeekValue.java | 5 ---- .../runner/values/NullLeekValue.java | 5 ---- .../runner/values/ObjectLeekValue.java | 5 ---- .../runner/values/ReferenceLeekValue.java | 5 ---- .../runner/values/StringLeekValue.java | 8 ----- .../runner/values/VariableLeekValue.java | 5 ---- 12 files changed, 87 deletions(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index af59ffc8..c68a7d6c 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -27,8 +27,6 @@ public class PhpArray implements Iterable { public final static int ASC_K = 6; public final static int DESC_K = 7; - // private static int RAM_LIMIT = 1000000; - private class ElementComparator implements Comparator { private final int mOrder; @@ -192,16 +190,9 @@ public void setValue(AI ai, AbstractLeekValue v) throws LeekRunException { private Element mHead = null; private Element mEnd = null; - private int mIndex = 0; - private int mSize = 0; private int capacity = 0; - - // Calcul optimisé de la ram utilisée (Optimisé niveau UC, pas niveau RAM) - private int mTotalSize = 0; - // private PhpArrayVariableLeekValue mParent = null; - private Element[] mTable = null; public PhpArray() {} @@ -912,25 +903,4 @@ public boolean equals(AI ai, PhpArray array) throws LeekRunException { } return true; } - - // public void setParent(PhpArrayVariableLeekValue parent) { - // mParent = parent; - // } - - public void updateArraySize(int delta) throws LeekRunException { - if (delta == 0) { - return; - } - mTotalSize += delta; - // if (mTotalSize >= RAM_LIMIT) { - // throw new LeekRunException(LeekRunException.OUT_OF_MEMORY); - // } - // if (mParent != null) { - // mParent.updateSize(delta); - // } - } - - public int getSize() { - return mTotalSize; - } } diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 7b3f277d..2d36b565 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -24,10 +24,6 @@ public abstract class AbstractLeekValue { public final static int MOD_COST = 5; public final static int POW_COST = 140; - public int getSize() throws LeekRunException { - return 1; - } - public int getInt(AI ai) throws LeekRunException { return 0; } diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index 1fe9c5ea..51f32967 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -263,11 +263,6 @@ else if (comp.getString(ai).isEmpty() && mValues.size() == 0) return false; } - @Override - public int getSize() throws LeekRunException { - return mValues.getSize(); - } - @Override public AbstractLeekValue add(AI ai, AbstractLeekValue value) throws LeekRunException { value = value.getValue(); diff --git a/src/main/java/leekscript/runner/values/BooleanLeekValue.java b/src/main/java/leekscript/runner/values/BooleanLeekValue.java index 462aec04..e2667157 100644 --- a/src/main/java/leekscript/runner/values/BooleanLeekValue.java +++ b/src/main/java/leekscript/runner/values/BooleanLeekValue.java @@ -12,11 +12,6 @@ public BooleanLeekValue(boolean value) { mValue = value; } - @Override - public int getSize() { - return 1; - } - @Override public boolean getBoolean() { return mValue; diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 242e5f51..94d3fac1 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -141,11 +141,6 @@ private ArrayLeekValue getMethodsArray(AI ai) throws LeekRunException { return methodsArray; } - @Override - public int getSize() { - return 1; - } - @Override public boolean getBoolean() { return true; diff --git a/src/main/java/leekscript/runner/values/DoubleLeekValue.java b/src/main/java/leekscript/runner/values/DoubleLeekValue.java index 58445da3..9fd7f063 100644 --- a/src/main/java/leekscript/runner/values/DoubleLeekValue.java +++ b/src/main/java/leekscript/runner/values/DoubleLeekValue.java @@ -14,11 +14,6 @@ public DoubleLeekValue(double value) { mValue = value; } - @Override - public int getSize() { - return 2; - } - @Override public int getInt(AI ai) { return (int) mValue; diff --git a/src/main/java/leekscript/runner/values/IntLeekValue.java b/src/main/java/leekscript/runner/values/IntLeekValue.java index ae4563e0..cc40a1f2 100644 --- a/src/main/java/leekscript/runner/values/IntLeekValue.java +++ b/src/main/java/leekscript/runner/values/IntLeekValue.java @@ -17,11 +17,6 @@ public void setInt(int nb) { mValue = nb; } - @Override - public int getSize() { - return 1; - } - @Override public int getInt(AI ai) { return mValue; diff --git a/src/main/java/leekscript/runner/values/NullLeekValue.java b/src/main/java/leekscript/runner/values/NullLeekValue.java index 86429c3f..00449a1c 100644 --- a/src/main/java/leekscript/runner/values/NullLeekValue.java +++ b/src/main/java/leekscript/runner/values/NullLeekValue.java @@ -10,11 +10,6 @@ public boolean isNull() { return true; } - @Override - public int getSize() { - return 1; - } - @Override public boolean isNumeric() { return true; diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index dceb3baf..76399a5a 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -64,11 +64,6 @@ public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... a return result.run(ai, this, arguments); } - @Override - public int getSize() { - return fields.size(); - } - @Override public boolean getBoolean() { return fields.size() > 0; diff --git a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java b/src/main/java/leekscript/runner/values/ReferenceLeekValue.java index faad59c8..835bcc8e 100644 --- a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java +++ b/src/main/java/leekscript/runner/values/ReferenceLeekValue.java @@ -19,11 +19,6 @@ public ReferenceLeekValue(AI ai, AbstractLeekValue value) throws LeekRunExceptio } } - @Override - public int getSize() throws LeekRunException { - return mValue.getSize(); - } - @Override public int getInt(AI ai) throws LeekRunException { return mValue.getInt(ai); diff --git a/src/main/java/leekscript/runner/values/StringLeekValue.java b/src/main/java/leekscript/runner/values/StringLeekValue.java index aebd0a84..69ee0f0c 100644 --- a/src/main/java/leekscript/runner/values/StringLeekValue.java +++ b/src/main/java/leekscript/runner/values/StringLeekValue.java @@ -11,14 +11,6 @@ public StringLeekValue(String value) { mValue = value; } - @Override - public int getSize() { - if (mValue == null) { - return 0; - } - return mValue.length(); - } - @Override public String getString(AI ai) { return mValue; diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index 7359e75e..b876a751 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -33,11 +33,6 @@ public VariableLeekValue(AI ai, AbstractLeekValue value) throws LeekRunException } } - @Override - public int getSize() throws LeekRunException { - return mValue.getSize(); - } - @Override public int getInt(AI ai) throws LeekRunException { return mValue.getInt(ai); From 5f691c849594ed26f5af5d312df728b7ddc595b8 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 22:06:02 +0100 Subject: [PATCH 095/319] [global] Fix globals --- src/main/java/leekscript/compiler/bloc/MainLeekBlock.java | 2 +- .../instruction/LeekGlobalDeclarationInstruction.java | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 50c5b308..67ba2fc4 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -186,7 +186,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { // Variables globales for (String global : mGlobales) { - writer.addLine("private VariableLeekValue globale_" + global + " = new VariableLeekValue(mUAI);"); + writer.addLine("private AbstractLeekValue globale_" + global + " = LeekValueManager.NULL;"); writer.addLine("private boolean globale_init_" + global + " = false;"); } // Fonctions redéfinies diff --git a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java index 7a4121a6..151749bd 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java @@ -37,13 +37,10 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addCode("if (!globale_init_" + token.getWord() + ") { globale_" + token.getWord() + ".initGlobal(mUAI, "); + writer.addCode("if (!globale_init_" + token.getWord() + ") { globale_" + token.getWord() + " = new VariableLeekValue(mUAI, "); if(mValue != null) mValue.writeJavaCode(mainblock, writer); else writer.addCode("LeekValueManager.NULL"); writer.addCode("); globale_init_" + token.getWord() + " = true;"); - if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10) { - writer.addCounter(1); // Add one operation in LS 1.0 - } writer.addLine(" }", mLine, mAI); } From ab86efc13b1ad8bfb352be65d2c8c25fa1037191 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 22:06:02 +0100 Subject: [PATCH 096/319] [function] Fix redefined functions --- .../compiler/expression/LeekExpression.java | 16 ++++++++++---- .../expression/LeekExpressionFunction.java | 21 ++++++++----------- .../compiler/expression/LeekVariable.java | 19 +++++++---------- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index 36fb8a36..de131d02 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -727,8 +727,12 @@ public void analyze(WordCompiler compiler) { if (!mExpression1.isLeftValue()) compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.CANT_ASSIGN_VALUE)); // throw new LeekExpressionException(mExpression1, LeekCompilerException.CANT_ASSIGN_VALUE); - if (mExpression1 instanceof LeekVariable && ((LeekVariable) mExpression1).getVariableType() == VariableType.SYSTEM_FUNCTION) - compiler.getMainBlock().addRedefinedFunction(((LeekVariable) mExpression1).getName()); + if (mExpression1 instanceof LeekVariable) { + var v = (LeekVariable) mExpression1; + if (v.getVariableType() == VariableType.SYSTEM_FUNCTION || v.getVariableType() == VariableType.FUNCTION) { + compiler.getMainBlock().addRedefinedFunction(((LeekVariable) mExpression1).getName()); + } + } if (mExpression1 instanceof LeekTabularValue) ((LeekTabularValue) mExpression1).setLeftValue(true); } @@ -737,8 +741,12 @@ public void analyze(WordCompiler compiler) { if (!(mExpression2 instanceof LeekVariable) && !(mExpression2 instanceof LeekGlobal) && !(mExpression2 instanceof LeekTabularValue)) compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.CANT_ASSIGN_VALUE)); // throw new LeekExpressionException(mExpression2, LeekCompilerException.CANT_ASSIGN_VALUE); - if (mExpression2 instanceof LeekVariable && ((LeekVariable) mExpression2).getVariableType() == VariableType.SYSTEM_FUNCTION) - compiler.getMainBlock().addRedefinedFunction(((LeekVariable) mExpression2).getName()); + if (mExpression2 instanceof LeekVariable) { + var v = (LeekVariable) mExpression2; + if (v.getVariableType() == VariableType.SYSTEM_FUNCTION || v.getVariableType() == VariableType.FUNCTION) { + compiler.getMainBlock().addRedefinedFunction(((LeekVariable) mExpression2).getName()); + } + } if (mExpression2 instanceof LeekTabularValue) ((LeekTabularValue) mExpression2).setLeftValue(true); } diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index b685d5b0..74a78402 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -67,19 +67,16 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("u_this.callMethod(mUAI, \"" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size() + "\""); } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.STATIC_METHOD) { writer.addCode("u_class.callMethod(mUAI, \"" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size() + "\""); - } else - if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.SYSTEM_FUNCTION) { + } else if (mExpression instanceof LeekVariable && mainblock.isRedefinedFunction(((LeekVariable) mExpression).getName())) { + writer.addCode("rfunction_" + ((LeekVariable) mExpression).getName()); + writer.addCode(".executeFunction(mUAI"); + } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.SYSTEM_FUNCTION) { var variable = (LeekVariable) mExpression; - if (mainblock.isRedefinedFunction(variable.getName())) { - writer.addCode("rfunction_" + variable.getName()); - writer.addCode(".executeFunction(mUAI"); - } else { - system_function = LeekFunctions.getValue(variable.getName()); - String namespace = LeekFunctions.getNamespace(variable.getName()); - // writer.addCode("LeekValueManager.getFunction(" + namespace + "." + variable.getName() + ")"); - writer.addCode("LeekFunctions.executeFunction(mUAI, " + namespace + "." + variable.getName() + ", new AbstractLeekValue[] {"); - addComma = false; - } + system_function = LeekFunctions.getValue(variable.getName()); + String namespace = LeekFunctions.getNamespace(variable.getName()); + // writer.addCode("LeekValueManager.getFunction(" + namespace + "." + variable.getName() + ")"); + writer.addCode("LeekFunctions.executeFunction(mUAI, " + namespace + "." + variable.getName() + ", new AbstractLeekValue[] {"); + addComma = false; } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.FUNCTION) { writer.addCode("user_function_"); writer.addCode(((LeekVariable) mExpression).getName()); diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index 5665d36e..3d5df040 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -63,8 +63,9 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("u_class.getField(mUAI, \"" + token.getWord() + "\")"); } else if (type == VariableType.METHOD) { writer.addCode("###"); - } else - if (type == VariableType.FUNCTION) { + } else if (mainblock.isRedefinedFunction(token.getWord())) { + writer.addCode("rfunction_" + token.getWord()); + } else if (type == VariableType.FUNCTION) { FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); } else if (type == VariableType.SYSTEM_CONSTANT) { @@ -73,16 +74,12 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { else if (constant.getType() == LeekFunctions.DOUBLE) writer.addCode("new DoubleLeekValue(" + constant.getValue() + ")"); else writer.addCode("LeekValueManager.NULL"); } else if (type == VariableType.SYSTEM_FUNCTION) { - if (mainblock.isRedefinedFunction(token.getWord())) { - writer.addCode("rfunction_" + token.getWord()); + FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); + if (user_function != null) { + writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); } else { - FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); - if (user_function != null) { - writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); - } else { - String namespace = LeekFunctions.getNamespace(token.getWord()); - writer.addCode("LeekValueManager.getFunction(" + namespace + "." + token.getWord() + ")"); - } + String namespace = LeekFunctions.getNamespace(token.getWord()); + writer.addCode("LeekValueManager.getFunction(" + namespace + "." + token.getWord() + ")"); } } else if (type == VariableType.GLOBAL) { writer.addCode("globale_" + token.getWord()); From b38c605b558de258ebb72810ce960ff1b0a62eb1 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 22:06:02 +0100 Subject: [PATCH 097/319] [compiler] Improve lines --- src/main/java/leekscript/compiler/JavaWriter.java | 10 ++++++++++ .../leekscript/compiler/bloc/ClassMethodBlock.java | 1 + src/main/java/leekscript/runner/AI.java | 8 ++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/JavaWriter.java b/src/main/java/leekscript/compiler/JavaWriter.java index 553288f6..0a561e6f 100644 --- a/src/main/java/leekscript/compiler/JavaWriter.java +++ b/src/main/java/leekscript/compiler/JavaWriter.java @@ -74,6 +74,8 @@ public void writeErrorFunction(IACompiler comp, String ai) { array.add(l.mAI.getPath()); array.add(l.mCodeLine); mCode.append(JSON.toJSONString(array.toJSONString())); + + // System.out.println(l.mAI.getPath() + ":" + l.mCodeLine + " -> " + l.mJavaLine); } mCode.append("};}\nprotected String getAItring(){ return "); mCode.append(aiJson); @@ -83,4 +85,12 @@ public void writeErrorFunction(IACompiler comp, String ai) { public void addCounter(int id) { addCode("mUAI.addOperations(1);"); } + + public int getCurrentLine() { + return mLine; + } + + public void addPosition(IAWord token) { + mLines.add(new Line(mLine, token.getLine(), token.getAI())); + } } diff --git a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java index 37277e28..6e527ac4 100644 --- a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java @@ -102,6 +102,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("final VariableLeekValue user_" + mParameters.get(i) + " = "); writer.addLine("new VariableLeekValue(mUAI, values[" + i + "].getValue());"); } + writer.addLine("", mLine, mAI); super.writeJavaCode(mainblock, writer); if (mEndInstruction == 0) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index b9fc3ecf..08e7859e 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -90,7 +90,8 @@ public String getErrorMessage(StackTraceElement[] elements) { StringBuilder sb = new StringBuilder(); int count = 0; for (StackTraceElement element : elements) { - if (element.getMethodName().equals("runIA") || element.getMethodName().startsWith("user_function_")) { + // System.out.println(element.getClassName() + " " + element.getMethodName() + " " + element.getLineNumber()); + if (element.getClassName().startsWith("AI_")) { sb.append(getErrorLocalisation(element.getLineNumber())).append("\n"); if (count++ > 50) { sb.append("[...]"); @@ -98,6 +99,9 @@ public String getErrorMessage(StackTraceElement[] elements) { } } } + // for (StackTraceElement element : elements) { + // sb.append("\t▶ " + element.getClassName() + "." + element.getMethodName() + ", line " + element.getLineNumber()).append("\n"); + // } return sb.toString(); } @@ -123,7 +127,7 @@ protected String getErrorLocalisation(int line) { if (mErrorObject.size() > value) { JSONArray l = mErrorObject.getJSONArray(value); if (l != null && l.size() >= 3) { - return "\t▶ AI " + l.getString(1) + ", line " + l.getString(2); + return "\t▶ AI " + l.getString(1) + ", line " + l.getString(2); // + ", java " + line; } } return ""; From 1a475f3a795cb410517daca9b8c722377eaa5d8a Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 22:06:02 +0100 Subject: [PATCH 098/319] [foreach] By reference in ls 1.1 by default --- src/main/java/leekscript/compiler/bloc/ForeachBlock.java | 2 +- src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java index 1a68e62b..19c65b07 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java @@ -49,7 +49,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine("if(" + ar + ".isArray()){"); if(mIsDeclaration) writer.addLine("final VariableLeekValue " + iterator_name + " = new VariableLeekValue(mUAI, LeekValueManager.NULL);"); else writer.addLine(iterator_name + ".set(mUAI, LeekValueManager.NULL);"); - if (mReference) { + if (mReference || mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { writer.addLine("for(AbstractLeekValue " + var + " : " + ar + ".getArray()){ " + iterator_name + ".setRef(mUAI, " + var + ");"); } else { writer.addLine("for(AbstractLeekValue " + var + " : " + ar + ".getArray()){ " + iterator_name + ".set(mUAI, " + var + ".getValue());"); diff --git a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java index 2910a89a..ed4e632d 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java @@ -71,12 +71,12 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { sb.append("ArrayLeekValue.ArrayIterator ").append(var).append("=").append(ar).append(".getArray().getArrayIterator();"); sb.append("while(!").append(var).append(".ended()){"); //Maj des variables - if (mKeyReference) { + if (mKeyReference || mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { sb.append(key_iterator).append(".setRef(mUAI, ").append(var).append(".getKeyRef());"); } else { sb.append(key_iterator).append(".set(mUAI, ").append(var).append(".getKeyRef());"); } - if (mValueReference) { + if (mValueReference || mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { sb.append(val_iterator).append(".setRef(mUAI, ").append(var).append(".getValueRef());"); } else { sb.append(val_iterator).append(".set(mUAI, ").append(var).append(".getValueRef());"); From ddae6f49f1bf225c4f5410e03dc2193ea2ff8756 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 22:06:02 +0100 Subject: [PATCH 099/319] [object] Continue objects --- src/main/java/leekscript/AILog.java | 1 + .../leekscript/compiler/WordCompiler.java | 105 ++++++------------ .../compiler/expression/LeekExpression.java | 49 ++++---- .../expression/LeekExpressionFunction.java | 16 ++- .../compiler/expression/LeekObjectAccess.java | 6 +- .../expression/LeekObjectAccess.java_ | 75 ------------- .../compiler/expression/LeekTabularValue.java | 10 +- .../ClassDeclarationInstruction.java | 22 +--- .../java/leekscript/runner/LeekFunctions.java | 5 +- .../leekscript/runner/LeekOperations.java | 7 +- src/main/java/leekscript/runner/PhpArray.java | 12 +- .../runner/values/AbstractLeekValue.java | 4 + .../runner/values/ArrayLeekValue.java | 17 +-- .../runner/values/ClassLeekValue.java | 68 +++++++++--- .../runner/values/ObjectLeekValue.java | 17 ++- .../runner/values/VariableLeekValue.java | 4 + 16 files changed, 188 insertions(+), 230 deletions(-) delete mode 100644 src/main/java/leekscript/compiler/expression/LeekObjectAccess.java_ diff --git a/src/main/java/leekscript/AILog.java b/src/main/java/leekscript/AILog.java index 3421dfaa..00a62e7c 100644 --- a/src/main/java/leekscript/AILog.java +++ b/src/main/java/leekscript/AILog.java @@ -32,6 +32,7 @@ public class AILog { public static final String UNKNOWN_STATIC_METHOD = "unknown_static_method"; public static final String STRING_METHOD_MUST_RETURN_STRING = "string_method_must_return_string"; public static final String UNKNOWN_FIELD = "unknown_field"; + public static final String UNKNOWN_CONSTRUCTOR = "unknown_constructor"; public interface Stream { public void write(JSONArray a); diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index b3794820..e15297f1 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -261,7 +261,7 @@ private void compileWord() throws LeekCompilerException { mCompiler.skipWord(); AbstractExpression exp = null; if (mCompiler.getWord().getType() != WordParser.T_END_INSTRUCTION) { - exp = readExpression().getAbstractExpression(); + exp = readExpression(); } if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) mCompiler.skipWord(); @@ -274,7 +274,7 @@ private void compileWord() throws LeekCompilerException { } } - AbstractExpression exp = readExpression().getAbstractExpression(); + AbstractExpression exp = readExpression(); if (mCompiler.haveWords() && mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) { mCompiler.skipWord(); } @@ -426,7 +426,7 @@ private void forBlock() throws LeekCompilerException { mCurentBlock = block; // On lit le array (ou liste de valeurs) - AbstractExpression array = readExpression().getAbstractExpression(); + AbstractExpression array = readExpression(); block.setArray(array); block.setKeyIterator(varName, isDeclaration); block.setValueIterator(valueVarName, isValueDeclaration); @@ -442,7 +442,7 @@ private void forBlock() throws LeekCompilerException { mCurentBlock = block; // On lit le array (ou liste de valeurs) - AbstractExpression array = readExpression().getAbstractExpression(); + AbstractExpression array = readExpression(); block.setArray(array); block.setIterator(varName, isDeclaration); @@ -456,7 +456,7 @@ private void forBlock() throws LeekCompilerException { mCurentBlock = block; // On récupère la valeur de base du compteur - AbstractExpression initValue = readExpression().getAbstractExpression(); + AbstractExpression initValue = readExpression(); if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) { // errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.ERROR, LeekCompilerException.END_OF_INSTRUCTION_EXPECTED)); throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); @@ -465,7 +465,7 @@ private void forBlock() throws LeekCompilerException { // if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) { // mCompiler.skipWord(); // } - AbstractExpression condition = readExpression().getAbstractExpression(); + AbstractExpression condition = readExpression(); if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) { // errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.ERROR, LeekCompilerException.END_OF_INSTRUCTION_EXPECTED)); throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); @@ -474,7 +474,7 @@ private void forBlock() throws LeekCompilerException { // if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) { // mCompiler.skipWord(); // } - AbstractExpression incrementation = readExpression().getAbstractExpression(); + AbstractExpression incrementation = readExpression(); // Attention si l'incrémentation n'est pas une expression Java fait // la gueule ! @@ -506,7 +506,7 @@ private void whileBlock() throws LeekCompilerException { if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); } - AbstractExpression exp = readExpression().getAbstractExpression(); + AbstractExpression exp = readExpression(); if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); } @@ -536,7 +536,7 @@ private void dowhileendBlock(DoWhileBlock bloc) throws LeekCompilerException { if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); } - bloc.setCondition(readExpression().getAbstractExpression()); + bloc.setCondition(readExpression()); if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); } @@ -558,7 +558,7 @@ private void elseBlock() throws LeekCompilerException { if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); } - AbstractExpression exp = readExpression().getAbstractExpression(); + AbstractExpression exp = readExpression(); if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); } @@ -577,7 +577,7 @@ private void ifBlock() throws LeekCompilerException { if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); } - AbstractExpression exp = readExpression().getAbstractExpression(); + AbstractExpression exp = readExpression(); if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); } @@ -603,7 +603,7 @@ private void globalDeclaration() throws LeekCompilerException { if (mCompiler.getWord().getWord().equals("=")) { mCompiler.skipWord(); // Si oui on récupère la valeur en question - variable.setValue(readExpression().getAbstractExpression()); + variable.setValue(readExpression()); } // On ajoute la variable mMain.addGlobalDeclaration(variable); @@ -619,7 +619,7 @@ private void globalDeclaration() throws LeekCompilerException { if (mCompiler.getWord().getWord().equals("=")) { mCompiler.skipWord(); // Si oui on récupère la valeur en question - variable.setValue(readExpression().getAbstractExpression()); + variable.setValue(readExpression()); } // On ajoute la variable mMain.addGlobalDeclaration(variable); @@ -645,7 +645,7 @@ private void variableDeclaration() throws LeekCompilerException { mCompiler.skipWord(); // Si oui on récupère la valeur en question mCurentBlock.setDeclaringVariable(variable.getToken()); - variable.setValue(readExpression().getAbstractExpression()); + variable.setValue(readExpression()); if (mCurentBlock.isDeclaringBariableUsed()) variable.mustSepare(); mCurentBlock.setDeclaringVariable(null); @@ -664,7 +664,7 @@ private void variableDeclaration() throws LeekCompilerException { if (mCompiler.getWord().getWord().equals("=")) { mCompiler.skipWord(); // Si oui on récupère la valeur en question - variable.setValue(readExpression().getAbstractExpression()); + variable.setValue(readExpression()); } // On ajoute la variable mCurentBlock.addInstruction(this, variable); @@ -753,7 +753,7 @@ public void classAccessLevelMember(ClassDeclarationInstruction classDeclaration, AbstractExpression expr = null; if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("=")) { mCompiler.skipWord(); - expr = readExpression().getAbstractExpression(); + expr = readExpression(); } classDeclaration.addField(this, name, expr); if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) @@ -767,7 +767,7 @@ public void classStaticMember(ClassDeclarationInstruction classDeclaration, Acce AbstractExpression expr = null; if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("=")) { mCompiler.skipWord(); - expr = readExpression().getAbstractExpression(); + expr = readExpression(); } else if (mCompiler.getWord().getType() == WordParser.T_PAR_LEFT) { // Méthode ClassMethodBlock method = classMethod(classDeclaration, accessLevel, name.getWord(), true); @@ -853,7 +853,7 @@ public ClassMethodBlock classMethod(ClassDeclarationInstruction classDeclaration return method; } - public LeekExpression readExpression() throws LeekCompilerException { + public AbstractExpression readExpression() throws LeekCompilerException { LeekExpression retour = new LeekExpression(); while (mCompiler.haveWords()) { IAWord word = mCompiler.getWord(); @@ -864,18 +864,18 @@ public LeekExpression readExpression() throws LeekCompilerException { mCompiler.skipWord();// On avance le curseur pour être au // début de l'expression - LeekExpression exp = readExpression(); + AbstractExpression exp = readExpression(); if (mCompiler.getWord().getType() != WordParser.T_BRACKET_RIGHT) { throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.CLOSING_SQUARE_BRACKET_EXPECTED); } - retour.addBracket(exp.getAbstractExpression()); + retour.addBracket(exp); } else if (word.getType() == WordParser.T_PAR_LEFT) { - mCompiler.skipWord();// On avance le curseur pour être au - // début de l'expression - LeekExpressionFunction function = new LeekExpressionFunction(); + + LeekExpressionFunction function = new LeekExpressionFunction(word); + mCompiler.skipWord();// On avance le curseur pour être au début de l'expression while (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { - function.addParameter(readExpression().getAbstractExpression()); + function.addParameter(readExpression()); if (mCompiler.getWord().getType() == WordParser.T_VIRG) mCompiler.skipWord(); } @@ -885,15 +885,9 @@ public LeekExpression readExpression() throws LeekCompilerException { retour.addFunction(function); } else if (word.getType() == WordParser.T_DOT) { // Object access - IAWord token = mCompiler.readWord(); - IAWord name = mCompiler.readWord(); - - retour.addOperator(Operators.DOT, token); - - // Object access - LeekObjectAccess objectAccess = new LeekObjectAccess(retour.getLastExpression(), name); - retour.addExpression(objectAccess); - mCompiler.back(); + mCompiler.skipWord(); + IAWord name = mCompiler.getWord(); + retour.addObjectAccess(name); } else if (word.getType() == WordParser.T_OPERATOR) { int operator = Operators.getOperator(word.getWord(), getVersion()); @@ -936,14 +930,14 @@ else if (word.getType() == WordParser.T_VAR_STRING) { int type = 0;// 0 => A déterminer, 1=> Simple, 2 => // Clé:valeur while (mCompiler.getWord().getType() != WordParser.T_BRACKET_RIGHT) { - AbstractExpression exp = readExpression().getAbstractExpression(); + AbstractExpression exp = readExpression(); if (mCompiler.getWord().getWord().equals(":")) { if (type == 0) type = 2; else if (type == 1) throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.SIMPLE_ARRAY); mCompiler.skipWord(); - AbstractExpression value = readExpression().getAbstractExpression(); + AbstractExpression value = readExpression(); array.addValue(exp, value); } else { if (type == 0) @@ -960,37 +954,8 @@ else if (type == 2) } retour.addExpression(array); } else if (word.getType() == WordParser.T_STRING) { - // var variable = mCurentBlock.getVariable(word.getWord()); - // if (variable != null) { - // retour.addExpression(variable); - // } - // else if (mMain.hasGlobal(word.getWord())) { retour.addExpression(new LeekGlobal(word)); - // } else if (LeekFunctions.isFunction(word.getWord()) > -1 || mMain.hasUserFunction(word.getWord(), true) || mMain.hasUserClass(word.getWord())) { - // // System.out.println("Function call " + word.getWord()); - // boolean isClass = mMain.hasUserClass(word.getWord()); - // LeekFunction function = new LeekFunction(word.getWord(), isClass); - // String fname = word.getWord(); - // // On doit lire la fonction - // mCompiler.skipWord(); - // if (mCompiler.getWord().getType() != WordParser.T_PAR_LEFT) { - // // On utilise le nom de la fonction comme une variable - // String namespace = LeekFunctions.getNamespace(fname); - // retour.addExpression(new LeekFunctionValue(fname, namespace)); - // continue; - // } else { - // mCompiler.skipWord(); - // while (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { - // function.addParameter(readExpression().getAbstractExpression()); - // if (mCompiler.getWord().getType() == WordParser.T_VIRG) - // mCompiler.skipWord(); - // } - // if (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { - // throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); - // } - // retour.addExpression(function); - // } } else if (word.getWord().equalsIgnoreCase("function")) { retour.addExpression(readAnonymousFunction()); } else if (word.getWord().equalsIgnoreCase("true")) @@ -1020,11 +985,11 @@ else if (getVersion() >= 11 && word.getWord().equalsIgnoreCase("new")) { mCompiler.skipWord();// On avance le curseur pour bien être // au début de l'expression - LeekExpression exp = readExpression(); + AbstractExpression exp = readExpression(); if (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); } - retour.addExpression(new LeekParenthesis(exp.getAbstractExpression())); + retour.addExpression(new LeekParenthesis(exp)); } else if (word.getType() == WordParser.T_OPERATOR) { // Si c'est un opérateur (il doit forcément être unaire et // de type préfix (! )) @@ -1051,12 +1016,16 @@ else if (operator == Operators.INCREMENT) mCompiler.skipWord(); } // Avant de retourner, on valide l'expression + AbstractExpression result = retour; + if (retour.getOperator() == -1) { + result = retour.getExpression1(); + } try { - retour.getAbstractExpression().validExpression(this, mMain); + result.validExpression(this, mMain); } catch (LeekExpressionException e) { throw new LeekCompilerException(mCompiler.lastWord(), e.getMessage(), new String[] { e.getExpression() }); } - return retour; + return result; } private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerException { diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index de131d02..a516021d 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -174,6 +174,22 @@ else if (mExpression2 != null) { } } + public void addObjectAccess(IAWord name) { + if (mExpression1 != null && mExpression2 == null) { + if (mExpression1.getType() == EXPRESSION) + ((LeekExpression) mExpression1).addObjectAccess(name); + else { + mExpression1 = new LeekObjectAccess(mExpression1, name); + } + } else if (mExpression2 != null) { + if (mExpression2.getType() == EXPRESSION) + ((LeekExpression) mExpression2).addObjectAccess(name); + else { + mExpression2 = new LeekObjectAccess(mExpression2, name); + } + } + } + public void addFunction(LeekExpressionFunction function) { // On doit ajouter ce crochet au dernier élément ajouté if (mExpression1 != null && mExpression2 == null) { @@ -390,20 +406,12 @@ else if (Operators.isUnarySuffix(mOperator)) { return retour + ")"; } - public AbstractExpression getAbstractExpression() { - // Retourner l'AbstractExpression (dans le cas où on n'aurait pas - // d'expression complete) - if (mOperator == -1) - return mExpression1; - return this; - } - @Override public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { - if (mExpression1 instanceof LeekExpression) - mExpression1 = ((LeekExpression) mExpression1).getAbstractExpression(); - if (mExpression2 instanceof LeekExpression) - mExpression2 = ((LeekExpression) mExpression2).getAbstractExpression(); + // if (mExpression1 instanceof LeekExpression) + // mExpression1 = ((LeekExpression) mExpression1).getAbstractExpression(); + // if (mExpression2 instanceof LeekExpression) + // mExpression2 = ((LeekExpression) mExpression2).getAbstractExpression(); if (mExpression1 == null || mExpression2 == null || mOperator == -1) throw new LeekExpressionException(this, LeekCompilerException.UNCOMPLETE_EXPRESSION); @@ -419,10 +427,10 @@ public AbstractExpression trim() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if (mExpression1 instanceof LeekExpression) - mExpression1 = ((LeekExpression) mExpression1).getAbstractExpression(); - if (mExpression2 instanceof LeekExpression) - mExpression2 = ((LeekExpression) mExpression2).getAbstractExpression(); + // if (mExpression1 instanceof LeekExpression) + // mExpression1 = ((LeekExpression) mExpression1).getAbstractExpression(); + // if (mExpression2 instanceof LeekExpression) + // mExpression2 = ((LeekExpression) mExpression2).getAbstractExpression(); // Retourner le code java de l'expression... plein de cas :) switch (mOperator) { @@ -704,16 +712,17 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { mExpression2.writeJavaCode(mainblock, writer); writer.addCode(")"); return; - case Operators.DOT: - mExpression2.writeJavaCode(mainblock, writer); - return; + // case Operators.DOT: + // mExpression2.writeJavaCode(mainblock, writer); + // return; } return; } @Override public boolean isLeftValue() { - return mOperator == Operators.DOT; + // return mOperator == Operators.DOT; + return false; } @Override diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 74a78402..6818423b 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import leekscript.compiler.AnalyzeError; +import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; @@ -15,10 +16,13 @@ public class LeekExpressionFunction extends AbstractExpression { + private IAWord openParenthesis = null; private final ArrayList mParameters = new ArrayList(); private AbstractExpression mExpression = null; - public LeekExpressionFunction() {} + public LeekExpressionFunction(IAWord openParenthesis) { + this.openParenthesis = openParenthesis; + } public void setExpression(AbstractExpression expression) { mExpression = expression; @@ -63,6 +67,11 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { var object = ((LeekObjectAccess) mExpression).getObject(); object.writeJavaCode(mainblock, writer); writer.addCode(".callMethod(mUAI, \"" + ((LeekObjectAccess) mExpression).getField() + "_" + mParameters.size() + "\""); + } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.SUPER) { + // Super constructor + var variable = (LeekVariable) mExpression; + writer.addCode("user_" + variable.getClassDeclaration().getParent().getName()); + writer.addCode(".callConstructor(mUAI, u_this"); } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.METHOD) { writer.addCode("u_this.callMethod(mUAI, \"" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size() + "\""); } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.STATIC_METHOD) { @@ -94,7 +103,9 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { if (i < mParameters.size()) { if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { mParameters.get(i).writeJavaCode(mainblock, writer); - // writer.addCode(".getValue()"); + if (system_function != null) { + writer.addCode(".getValue()"); + } } else { if (user_function != null) { if (user_function.isReference(i)) { @@ -119,6 +130,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("}, " + mParameters.size()); } writer.addCode(")"); + writer.addPosition(openParenthesis); } @Override diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index 6c2a055d..287d6083 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -26,7 +26,7 @@ public int getType() { @Override public String getString() { - return ""; + return object.getString() + "." + field.getWord(); } public AbstractExpression getObject() { @@ -41,8 +41,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { @Override public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { - - return true; + return object.validExpression(compiler, mainblock); } @Override @@ -52,6 +51,7 @@ public boolean isLeftValue() { @Override public void analyze(WordCompiler compiler) { + // System.out.println("oa " + getString()); object.analyze(compiler); if (object instanceof LeekVariable) { var v = (LeekVariable) object; diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java_ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java_ deleted file mode 100644 index 6c2a055d..00000000 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java_ +++ /dev/null @@ -1,75 +0,0 @@ -package leekscript.compiler.expression; - -import leekscript.compiler.AnalyzeError; -import leekscript.compiler.IAWord; -import leekscript.compiler.JavaWriter; -import leekscript.compiler.WordCompiler; -import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; -import leekscript.compiler.bloc.MainLeekBlock; -import leekscript.compiler.exceptions.LeekCompilerException; -import leekscript.compiler.expression.LeekVariable.VariableType; - -public class LeekObjectAccess extends AbstractExpression { - - private AbstractExpression object; - private IAWord field; - - public LeekObjectAccess(AbstractExpression object, IAWord field) { - this.object = object; - this.field = field; - } - - @Override - public int getType() { - return OBJECT_ACCESS; - } - - @Override - public String getString() { - return ""; - } - - public AbstractExpression getObject() { - return object; - } - - @Override - public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - object.writeJavaCode(mainblock, writer); - writer.addCode(".getField(mUAI, \"" + field.getWord() + "\")"); - } - - @Override - public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { - - return true; - } - - @Override - public boolean isLeftValue() { - return true; - } - - @Override - public void analyze(WordCompiler compiler) { - object.analyze(compiler); - if (object instanceof LeekVariable) { - var v = (LeekVariable) object; - if (v.getName().equals("this")) { - // this, check field exists in class - var clazz = compiler.getCurrentClass(); - if (clazz != null && !clazz.hasMember(field)) { - compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, LeekCompilerException.CLASS_MEMBER_DOES_NOT_EXIST)); - } - } else if (v.getVariableType() == VariableType.CLASS && v.getClassDeclaration() != null) { - if (!v.getClassDeclaration().hasStaticMember(field)) { - compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, LeekCompilerException.CLASS_STATIC_MEMBER_DOES_NOT_EXIST, new String[] { v.getClassDeclaration().getName(), field.getWord() })); - } - } - } - } - - public String getField() { - return field.getWord(); - } -} diff --git a/src/main/java/leekscript/compiler/expression/LeekTabularValue.java b/src/main/java/leekscript/compiler/expression/LeekTabularValue.java index f0ec2c30..adb0948d 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTabularValue.java +++ b/src/main/java/leekscript/compiler/expression/LeekTabularValue.java @@ -39,10 +39,11 @@ public String getString() { @Override public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { //On doit vérifier qu'on a affaire : soit à une expression tabulaire, soit à une variable, soit à une globale - if(!(mTabular instanceof LeekVariable) && !(mTabular instanceof LeekGlobal) && !(mTabular instanceof LeekTabularValue)){ - //throw new LeekExpressionException(this, "Ce n'est pas un tableau valide"); + //throw new LeekExpressionException(this, "Ce n'est pas un tableau valide"); + if (!mTabular.isLeftValue()) { mLeftValue = false; } + //Sinon on valide simplement les deux expressions mTabular.validExpression(compiler, mainblock); mCase.validExpression(compiler, mainblock); @@ -51,13 +52,12 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if(mLeftValue){ + if (mLeftValue) { mTabular.writeJavaCode(mainblock, writer); writer.addCode(".getValue().getOrCreate(mUAI, "); mCase.writeJavaCode(mainblock, writer); writer.addCode(")"); - } - else{ + } else { mTabular.writeJavaCode(mainblock, writer); writer.addCode(".getValue().get(mUAI, "); mCase.writeJavaCode(mainblock, writer); diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index a7157845..682ef100 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -227,16 +227,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine(".addStaticMethod(\"" + method.getKey() + "\", " + version.getKey() + ", " + methodName + ");"); } writer.addCode(className); - writer.addCode(".addGenericStaticMethod(\"" + method.getKey() + "\", new LeekAnonymousFunction() {"); - writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue thiz, AbstractLeekValue... values) throws LeekRunException {"); - writer.addLine("switch (values.length) {"); - for (Entry version : method.getValue().entrySet()) { - String methodName = className + "_" + method.getKey() + "_" + version.getKey(); - writer.addLine("case " + version.getKey() + ": return " + methodName + ".run(mUAI, thiz, values);"); - } - writer.addLine("default: mUAI.addSystemLog(leekscript.AILog.ERROR, leekscript.AILog.UNKNOWN_METHOD, new String[] { });"); - writer.addLine("return LeekValueManager.NULL;"); - writer.addLine("}}});"); + writer.addLine(".addGenericStaticMethod(\"" + method.getKey() + "\");"); } for (Entry construct : constructors.entrySet()) { @@ -258,16 +249,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine(".addMethod(\"" + method.getKey() + "\", " + version.getKey() + ", " + methodName + ");"); } writer.addCode(className); - writer.addCode(".addGenericMethod(\"" + method.getKey() + "\", new LeekAnonymousFunction() {"); - writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue thiz, AbstractLeekValue... values) throws LeekRunException {"); - writer.addLine("switch (values.length) {"); - for (Entry version : method.getValue().entrySet()) { - String methodName = className + "_" + method.getKey() + "_" + version.getKey(); - writer.addLine("case " + version.getKey() + ": return " + methodName + ".run(mUAI, thiz, values);"); - } - writer.addLine("default: mUAI.addSystemLog(leekscript.AILog.ERROR, leekscript.AILog.UNKNOWN_METHOD, new String[] { });"); - writer.addLine("return LeekValueManager.NULL;"); - writer.addLine("}}});"); + writer.addLine(".addGenericMethod(\"" + method.getKey() + "\");"); } } diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 919ac4d4..78ed6795 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -1,5 +1,6 @@ package leekscript.runner; +import java.util.Arrays; import java.util.regex.Pattern; import leekscript.AILog; @@ -1299,7 +1300,9 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu clone(1, 2) { @Override public AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekOperations.clone(ai, parameters[0], parameters[1].getInt(ai)); + // Clone one level by default + int level = count == 1 ? 1 : Math.max(0, parameters[1].getInt(ai)); + return LeekOperations.clone(ai, parameters[0], level); } } ; diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index 5bc098ac..0f89f574 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -259,17 +259,20 @@ else if (value instanceof IntLeekValue) else if (value instanceof DoubleLeekValue) return new DoubleLeekValue(value.getDouble(ai)); else if (value instanceof ArrayLeekValue) { + if (level == 0) return value; if (value.getArray().size() > 0) { ai.addOperations(value.getArray().size() * (ArrayLeekValue.ARRAY_CELL_CREATE_OPERATIONS)); } return new ArrayLeekValue(ai, value.getArray(), level); } else if (value instanceof ObjectLeekValue) { - return value; + if (level == 0) return value; + return new ObjectLeekValue(ai, (ObjectLeekValue) value, level); } else if (value instanceof ClassLeekValue) { return value; - } else + } else { return LeekValueManager.NULL; } + } public static AbstractLeekValue equals_equals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index c68a7d6c..9c428e90 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -7,10 +7,12 @@ import java.util.List; import java.util.Random; import java.util.Set; +import java.util.HashSet; import leekscript.compiler.LeekScript; import leekscript.runner.values.AbstractLeekValue; import leekscript.runner.values.ArrayLeekValue; +import leekscript.runner.values.ObjectLeekValue; import leekscript.runner.values.PhpArrayVariableLeekValue; import leekscript.runner.values.StringLeekValue; @@ -171,6 +173,8 @@ public Element next() { public AbstractLeekValue key() { if (key instanceof Integer) return LeekValueManager.getLeekIntValue(((Integer) key).intValue()); + else if (key instanceof ObjectLeekValue) + return (ObjectLeekValue) key; else return new StringLeekValue(key.toString()); } @@ -207,7 +211,7 @@ public PhpArray(AI ai, PhpArray phpArray, int level) throws LeekRunException { Element e = phpArray.mHead; while (e != null) { if (ai.getVersion() >= 11) { - if (level == 0) { + if (level == 1) { set(ai, e.key, LeekOperations.clonePrimitive(ai, e.value.getValue())); } else { set(ai, e.key, LeekOperations.clone(ai, e.value.getValue(), level - 1)); @@ -793,7 +797,7 @@ private Element getElement(AI ai, Object key) throws LeekRunException { int operations = ArrayLeekValue.ARRAY_CELL_ACCESS_OPERATIONS; ai.addOperationsNoCheck(operations); - int hash = getHash(key); + int hash = key.hashCode(); int index = getIndex(hash); Element f = mTable[index]; @@ -807,10 +811,6 @@ private Element getElement(AI ai, Object key) throws LeekRunException { return null; } - private int getHash(Object key) { - return key.hashCode(); - } - private int getIndex(int hash) { return hash & (capacity - 1); } diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 2d36b565..df9c4d45 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -204,6 +204,8 @@ public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... a return LeekValueManager.NULL; } + public void callConstructor(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException {} + public abstract int getType(); public boolean isReference() { @@ -236,6 +238,8 @@ else if (parameters[j].getValue().getType() == FUNCTION) ret += "function"; else if (parameters[j].getValue().getType() == NULL) ret += "null"; + else if (parameters[j].getValue().getType() == OBJECT) + ret += "object"; else ret += "?"; } diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index 51f32967..f3e03b3a 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -99,10 +99,6 @@ public ArrayLeekValue(AI ai, AbstractLeekValue values[], boolean isKeyValue) thr } } - /* - * public ArrayLeekValue() { mValues = new PhpArray(); } - */ - public ArrayLeekValue(AI ai, ArrayLeekValue array, int level) throws LeekRunException { mValues = new PhpArray(ai, array.mValues, level); } @@ -129,6 +125,8 @@ public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws Leek value = value.getValue(); if (value instanceof StringLeekValue) { key = value.getString(ai); + } else if (value instanceof ObjectLeekValue) { + key = value; } else { key = Integer.valueOf(value.getInt(ai)); } @@ -153,10 +151,11 @@ public void removeByKey(AI ai, AbstractLeekValue value) throws LeekRunException mValues.remove(ai, value.getString(ai)); else if (value.getType() == NUMBER) mValues.remove(ai, value.getInt(ai)); + else if (value.getType() == OBJECT) + mValues.remove(ai, value); } public void shuffle(AI ai) throws LeekRunException { - // Collections.shuffle(mValues); mValues.sort(ai, PhpArray.RANDOM); } @@ -190,8 +189,6 @@ public AbstractLeekValue search(AI ai, AbstractLeekValue search, int pos) throws } public void sort(AI ai, int type) throws LeekRunException { - // Collections.sort(mValues, new - // LeekValueComparator.SortComparator(type)); mValues.sort(ai, type); } @@ -270,7 +267,7 @@ public AbstractLeekValue add(AI ai, AbstractLeekValue value) throws LeekRunExcep // mValues.reindex(ai); ArrayIterator iterator = value.getArray().getArrayIterator(); while (!iterator.ended()) { - if (iterator.key() instanceof String) + if (iterator.key() instanceof String || iterator.key() instanceof ObjectLeekValue) mValues.getOrCreate(ai, iterator.getKey(ai).getString(ai)).set(ai, iterator.getValue(ai)); else mValues.push(ai, iterator.getValue(ai)); @@ -292,10 +289,6 @@ public void sort(AI ai, Comparator comparator) throws LeekRunE mValues.sort(ai, comparator); } - // public void setParent(PhpArrayVariableLeekValue parent) { - // mValues.setParent(parent); - // } - @Override public Object toJSON(AI ai) throws LeekRunException { diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 94d3fac1..ba08d0c9 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -4,6 +4,7 @@ import java.util.Map.Entry; import leekscript.AILog; +import leekscript.compiler.bloc.ClassMethodBlock; import leekscript.runner.AI; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; @@ -49,23 +50,46 @@ public void addMethod(String method, int argCount, LeekAnonymousFunction functio methods.put(method + "_" + argCount, function); } - public void addGenericMethod(String method, LeekAnonymousFunction function) { - genericMethods.put(method, new FunctionLeekValue(function)); + public void addGenericMethod(String method) { + genericMethods.put(method, new FunctionLeekValue(new LeekAnonymousFunction() { + public AbstractLeekValue run(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException { + final var methodCode = method + "_" + arguments.length; + final var m = methods.get(methodCode); + if (m != null) { + return m.run(ai, thiz, arguments); + } + ai.addSystemLog(leekscript.AILog.ERROR, leekscript.AILog.UNKNOWN_METHOD, new String[] { name, createMethodError(methodCode) }); + return LeekValueManager.NULL; + } + })); } public void addStaticMethod(String method, int argCount, LeekAnonymousFunction function) { staticMethods.put(method + "_" + argCount, function); } - public void addGenericStaticMethod(String method, LeekAnonymousFunction function) { - genericStaticMethods.put(method, new FunctionLeekValue(function)); + public void addGenericStaticMethod(String method) { + genericMethods.put(method, new FunctionLeekValue(new LeekAnonymousFunction() { + public AbstractLeekValue run(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException { + final var methodCode = method + "_" + arguments.length; + final var m = methods.get(methodCode); + if (m != null) { + return m.run(ai, null, arguments); + } + ai.addSystemLog(leekscript.AILog.ERROR, leekscript.AILog.UNKNOWN_METHOD, new String[] { name, createMethodError(methodCode) }); + return LeekValueManager.NULL; + } + })); } @Override public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { + ai.addOperations(1); AbstractLeekValue result = staticFields.get(field); if (result == null) { - if (field.equals("fields")) { + if (field.equals("name")) { + return new StringLeekValue(name); + } else if (field.equals("fields")) { return getFieldsArray(ai); } else if (field.equals("methods")) { return getMethodsArray(ai); @@ -79,29 +103,43 @@ public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { @Override public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + ai.addOperations(1); LeekAnonymousFunction result = staticMethods.get(method); if (result == null) { - int underscore = method.lastIndexOf("_"); - int argCount = Integer.parseInt(method.substring(underscore + 1)); - String methodRealName = method.substring(0, underscore) + "("; - for (int i = 0; i < argCount; ++i) { - if (i > 0) methodRealName += ", "; - methodRealName += "x"; - } - methodRealName += ")"; - ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_STATIC_METHOD, new String[] { name, methodRealName }); + ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_STATIC_METHOD, new String[] { name, createMethodError(method) }); return LeekValueManager.NULL; } // Call method with new arguments, add the object at the beginning return result.run(ai, null, arguments); } + public void callConstructor(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException { + ai.addOperations(1); + if (!constructors.containsKey(arguments.length)) { + ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_CONSTRUCTOR, new String[] { name, String.valueOf(arguments.length) }); + return; + } + constructors.get(arguments.length).run(ai, thiz, arguments); + } + + public static String createMethodError(String method) { + int underscore = method.lastIndexOf("_"); + int argCount = Integer.parseInt(method.substring(underscore + 1)); + String methodRealName = method.substring(0, underscore) + "("; + for (int i = 0; i < argCount; ++i) { + if (i > 0) methodRealName += ", "; + methodRealName += "x"; + } + methodRealName += ")"; + return methodRealName; + } + /** * Constructors */ @Override public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... arguments) throws LeekRunException { - + ai.addOperations(1); // Create the actual object ObjectLeekValue object = new ObjectLeekValue(this); // Add fields diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 76399a5a..963ed985 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -6,6 +6,7 @@ import leekscript.AILog; import leekscript.runner.AI; import leekscript.runner.LeekAnonymousFunction; +import leekscript.runner.LeekOperations; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; @@ -18,13 +19,26 @@ public ObjectLeekValue(ClassLeekValue clazz) { this.clazz = clazz; } + public ObjectLeekValue(AI ai, ObjectLeekValue value, int level) throws LeekRunException { + this.clazz = value.clazz; + ai.addOperations(value.fields.size()); + for (var field : value.fields.entrySet()) { + if (level == 1) { + fields.put(field.getKey(), new VariableLeekValue(ai, LeekOperations.clonePrimitive(ai, field.getValue()))); + } else { + fields.put(field.getKey(), new VariableLeekValue(ai, LeekOperations.clone(ai, field.getValue(), level - 1))); + } + } + } + public void addField(AI ai, String field, AbstractLeekValue value) throws LeekRunException { - fields.put(field, new VariableLeekValue(ai, value)); + fields.put(field, new VariableLeekValue(ai, LeekOperations.clone(ai, value))); } @Override public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { // System.out.println("getField " + field); + ai.addOperations(1); if (field.equals("class")) { return clazz; } @@ -47,6 +61,7 @@ public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunExcep @Override public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + ai.addOperations(1); LeekAnonymousFunction result = clazz.methods.get(method); if (result == null) { int underscore = method.lastIndexOf("_"); diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index b876a751..183bccd2 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -241,6 +241,10 @@ public AbstractLeekValue callMethod(AI ai, String field, AbstractLeekValue... ar return mValue.callMethod(ai, field, arguments); } + public void callConstructor(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException { + mValue.callConstructor(ai, thiz, arguments); + } + @Override public int getType() { return mValue.getType(); From c26a040006969289f032736221462b0c9ca60eeb Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 22:06:02 +0100 Subject: [PATCH 100/319] [function] Remove removeByKey function --- src/main/java/leekscript/runner/LeekFunctions.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 78ed6795..dfa130ae 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -714,18 +714,6 @@ public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue p mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); } }, - removeByKey(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - parameters[0].getArray().removeByKey(leekIA, parameters[1]); - return LeekValueManager.NULL; - } - - @Override - public int[] parameters() { - return new int[] { ARRAY, -1 }; - } - }, removeKey(2) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { From 82987d79cf0783148a199de202ab8e2ee87c8da7 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 22:06:02 +0100 Subject: [PATCH 101/319] [class] Improve member search --- .../compiler/bloc/ClassMethodBlock.java | 12 +++----- .../ClassDeclarationInstruction.java | 30 +++++++++++++++++-- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java index 6e527ac4..bbde1b51 100644 --- a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java @@ -61,20 +61,16 @@ public LeekVariable getVariable(String variable, boolean includeClassMembers) { // Search in fields if (!isStatic) { - if (variable.equals("this")) return new LeekVariable(new IAWord("this"), VariableType.THIS); - if (variable.equals("class")) return new LeekVariable(new IAWord("class"), VariableType.THIS_CLASS); + if (variable.getWord().equals("this")) return new LeekVariable(new IAWord("this"), VariableType.THIS); + if (variable.getWord().equals("class")) return new LeekVariable(new IAWord("class"), VariableType.THIS_CLASS); if (includeClassMembers) { - v = clazz.getFieldVariables().get(variable); - if (v != null) return v; - v = clazz.getMethodVariables().get(variable); + v = clazz.getMember(variable); if (v != null) return v; } } if (includeClassMembers) { - v = clazz.getStaticMethodVariables().get(variable); + v = clazz.getStaticMember(variable); if (v != null) return v; - // Search in static fields - return clazz.getStaticFieldVariables().get(variable); } return null; } diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 682ef100..dc68c1b6 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -280,10 +280,36 @@ public ClassDeclarationInstruction getParent() { } public boolean hasMember(IAWord field) { - return fields.containsKey(field.getWord()) || methods.containsKey(field.getWord()); + return getMember(field) != null; } public boolean hasStaticMember(IAWord field) { - return staticFields.containsKey(field.getWord()) || staticMethods.containsKey(field.getWord()); + return getStaticMember(field) != null; + } + + public LeekVariable getMember(IAWord token) { + var f = fieldVariables.get(token.getWord()); + if (f != null) return f; + + var m = methodVariables.get(token.getWord()); + if (m != null) return m; + + if (parent != null) { + return parent.getMember(token); + } + return null; + } + + public LeekVariable getStaticMember(IAWord token) { + var f = staticFieldVariables.get(token.getWord()); + if (f != null) return f; + + var m = staticMethodVariables.get(token.getWord()); + if (m != null) return m; + + if (parent != null) { + return parent.getStaticMember(token); + } + return null; } } From 76c711903eb2115186de00b9f483a4d8a5c4ffa7 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 23:31:19 +0100 Subject: [PATCH 102/319] [class] Improve class declaration --- .../java/leekscript/compiler/WordCompiler.java | 1 - .../compiler/bloc/ClassMethodBlock.java | 9 +++++++-- .../leekscript/compiler/bloc/MainLeekBlock.java | 13 ++++++++++--- .../instruction/ClassDeclarationInstruction.java | 16 +++++++++------- .../java/leekscript/runner/LeekFunctions.java | 1 - 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index e15297f1..d9229daf 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -26,7 +26,6 @@ import leekscript.compiler.expression.LeekGlobal; import leekscript.compiler.expression.LeekNull; import leekscript.compiler.expression.LeekNumber; -import leekscript.compiler.expression.LeekObjectAccess; import leekscript.compiler.expression.LeekParenthesis; import leekscript.compiler.expression.LeekString; import leekscript.compiler.expression.LeekVariable; diff --git a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java index bbde1b51..bda0b625 100644 --- a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java @@ -101,8 +101,13 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine("", mLine, mAI); super.writeJavaCode(mainblock, writer); - if (mEndInstruction == 0) - writer.addLine("return u_this;"); + if (mEndInstruction == 0) { + if (isStatic) { + writer.addLine("return LeekValueManager.NULL;"); + } else { + writer.addLine("return u_this;"); + } + } } public ClassDeclarationInstruction getClassDeclaration() { diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 67ba2fc4..d7a02e28 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -179,9 +179,19 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { writer.addLine("import leekscript.runner.values.*;"); writer.addLine(); writer.addLine("public class " + className + " extends " + AIClass + " {"); + + // Classes + for (var clazz : mUserClasses.values()) { + clazz.declareJava(this, writer); + } + // Constructor writer.addLine("public " + className + "() throws LeekRunException {"); writer.addLine("super();"); writer.addLine("mInstructions = " + mInstructions.size() + ";"); + + for (var clazz : mUserClasses.values()) { + clazz.createJava(this, writer); + } writer.addLine("}"); // Variables globales @@ -199,9 +209,6 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { for (LeekInstruction instruction : mFunctions) { instruction.writeJavaCode(this, writer); } - for (var clazz : mUserClasses.values()) { - clazz.declareJava(this, writer); - } /* * for(LeekInstruction instruction : mAnonymousFunctions){ * instruction.writeJavaCode(this, writer); } diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index dc68c1b6..e9119c0e 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -162,17 +162,14 @@ public void analyze(WordCompiler compiler) { } public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { - + // Declare the class as a field of the AI String className = "user_" + token.getWord(); - writer.addLine("private ClassLeekValue " + className + ";"); + writer.addLine("private ClassLeekValue " + className + " = new ClassLeekValue(\"" + token.getWord() + "\");"); } - @Override - public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - + public void createJava(MainLeekBlock mainblock, JavaWriter writer) { + // Create the class in the constructor of the AI String className = "user_" + token.getWord(); - writer.addCode(className); - writer.addLine(" = new ClassLeekValue(\"" + token.getWord() + "\");"); if (parent != null) { writer.addLine(className + ".setParent(user_" + parent.getName() + ");"); @@ -253,6 +250,11 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } } + @Override + public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { + + } + private void writeFields(MainLeekBlock mainblock, JavaWriter writer, String className) { if (parent != null) { diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index dfa130ae..14cc5cb9 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -1,6 +1,5 @@ package leekscript.runner; -import java.util.Arrays; import java.util.regex.Pattern; import leekscript.AILog; From 0a4577da2e5351e237e8fda7fe2254ada7955f22 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 23:31:19 +0100 Subject: [PATCH 103/319] [parser] Improve line break management --- src/main/java/leekscript/compiler/WordParser.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index 112548e9..4c258c25 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -72,7 +72,12 @@ public void compile(WordCompiler compiler) throws LeekCompilerException { c = code.charAt(i); if(c == '\r') continue; // Compteur caractères/lignes - if(c == '\n'){ + if(c == '\n') { + if (type != T_NOTHING) { + newWord(word, type); + type = T_NOTHING; + word = ""; + } char_counter = 0; line_counter++; comment_line = false; From 7ae3a02a3dff183b4965853c3c334b973f57a1ad Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 23:31:19 +0100 Subject: [PATCH 104/319] [class] Check extends loop --- .../compiler/exceptions/LeekCompilerException.java | 1 + .../instruction/ClassDeclarationInstruction.java | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java b/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java index 2b1ff5b0..7902aedc 100644 --- a/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java +++ b/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java @@ -57,6 +57,7 @@ public class LeekCompilerException extends Exception { public final static String SUPER_NOT_AVAILABLE_PARENT = "super_not_available_parent"; public final static String CLASS_MEMBER_DOES_NOT_EXIST = "class_member_does_not_exist"; public final static String CLASS_STATIC_MEMBER_DOES_NOT_EXIST = "class_static_member_does_not_exist"; + public final static String EXTENDS_LOOP = "extends_loop"; /** * diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index e9119c0e..27a876b1 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -141,7 +141,19 @@ public void analyze(WordCompiler compiler) { } else if (parentVar.getVariableType() != VariableType.CLASS) { compiler.addError(new AnalyzeError(parentToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.UNKNOWN_VARIABLE_OR_FUNCTION)); } else { - this.parent = parentVar.getClassDeclaration(); + var current = parentVar.getClassDeclaration(); + boolean ok = true; + while (current != null) { + if (current == this) { + compiler.addError(new AnalyzeError(parentToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.EXTENDS_LOOP)); + ok = false; + break; + } + current = current.getParent(); + } + if (ok) { + this.parent = parentVar.getClassDeclaration(); + } } } From 81c5e2c39e9b07c97e7227535e0e43a57a8df4e8 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 23:31:19 +0100 Subject: [PATCH 105/319] [object] Fix access error --- .../java/leekscript/compiler/expression/LeekObjectAccess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index 287d6083..dba9cffc 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -59,7 +59,7 @@ public void analyze(WordCompiler compiler) { // this, check field exists in class var clazz = compiler.getCurrentClass(); if (clazz != null && !clazz.hasMember(field)) { - compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, LeekCompilerException.CLASS_MEMBER_DOES_NOT_EXIST)); + compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, LeekCompilerException.CLASS_MEMBER_DOES_NOT_EXIST, new String[] { clazz.getName(), field.getWord() })); } } else if (v.getVariableType() == VariableType.CLASS && v.getClassDeclaration() != null) { if (!v.getClassDeclaration().hasStaticMember(field)) { From f8f8bf66008c355aeec34826a59b0dd49d45c30b Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 23:31:19 +0100 Subject: [PATCH 106/319] [class] Fix field search --- .../compiler/bloc/ClassMethodBlock.java | 4 ++-- .../compiler/expression/LeekObjectAccess.java | 4 ++-- .../instruction/ClassDeclarationInstruction.java | 16 ++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java index bda0b625..4c6b460a 100644 --- a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java @@ -61,8 +61,8 @@ public LeekVariable getVariable(String variable, boolean includeClassMembers) { // Search in fields if (!isStatic) { - if (variable.getWord().equals("this")) return new LeekVariable(new IAWord("this"), VariableType.THIS); - if (variable.getWord().equals("class")) return new LeekVariable(new IAWord("class"), VariableType.THIS_CLASS); + if (variable.equals("this")) return new LeekVariable(new IAWord("this"), VariableType.THIS); + if (variable.equals("class")) return new LeekVariable(new IAWord("class"), VariableType.THIS_CLASS); if (includeClassMembers) { v = clazz.getMember(variable); if (v != null) return v; diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index dba9cffc..44d6bd0a 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -58,11 +58,11 @@ public void analyze(WordCompiler compiler) { if (v.getName().equals("this")) { // this, check field exists in class var clazz = compiler.getCurrentClass(); - if (clazz != null && !clazz.hasMember(field)) { + if (clazz != null && !clazz.hasMember(field.getWord())) { compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, LeekCompilerException.CLASS_MEMBER_DOES_NOT_EXIST, new String[] { clazz.getName(), field.getWord() })); } } else if (v.getVariableType() == VariableType.CLASS && v.getClassDeclaration() != null) { - if (!v.getClassDeclaration().hasStaticMember(field)) { + if (!v.getClassDeclaration().hasStaticMember(field.getWord())) { compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, LeekCompilerException.CLASS_STATIC_MEMBER_DOES_NOT_EXIST, new String[] { v.getClassDeclaration().getName(), field.getWord() })); } } diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 27a876b1..01365a89 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -293,19 +293,19 @@ public ClassDeclarationInstruction getParent() { return parent; } - public boolean hasMember(IAWord field) { + public boolean hasMember(String field) { return getMember(field) != null; } - public boolean hasStaticMember(IAWord field) { + public boolean hasStaticMember(String field) { return getStaticMember(field) != null; } - public LeekVariable getMember(IAWord token) { - var f = fieldVariables.get(token.getWord()); + public LeekVariable getMember(String token) { + var f = fieldVariables.get(token); if (f != null) return f; - var m = methodVariables.get(token.getWord()); + var m = methodVariables.get(token); if (m != null) return m; if (parent != null) { @@ -314,11 +314,11 @@ public LeekVariable getMember(IAWord token) { return null; } - public LeekVariable getStaticMember(IAWord token) { - var f = staticFieldVariables.get(token.getWord()); + public LeekVariable getStaticMember(String token) { + var f = staticFieldVariables.get(token); if (f != null) return f; - var m = staticMethodVariables.get(token.getWord()); + var m = staticMethodVariables.get(token); if (m != null) return m; if (parent != null) { From e9612e49922dbd18d3e83bc2162c0d1ca2cf602b Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 23:31:19 +0100 Subject: [PATCH 107/319] [operator] Implement equals for objects and improve === --- src/main/java/leekscript/runner/LeekOperations.java | 9 ++++++--- .../java/leekscript/runner/values/ObjectLeekValue.java | 10 +++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index 0f89f574..8f871c0a 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -276,12 +276,15 @@ else if (value instanceof ArrayLeekValue) { public static AbstractLeekValue equals_equals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { ai.addOperations(1); + v1 = v1.getValue(); + v2 = v2.getValue(); + if (v1 instanceof ObjectLeekValue && v2 instanceof ObjectLeekValue) { + return LeekValueManager.getLeekBooleanValue(v1.equals(v2)); + } return LeekValueManager.getLeekBooleanValue(v1.getType() == v2.getType() && v1.equals(ai, v2)); } public static AbstractLeekValue notequals_equals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekBooleanValue(v1.getType() != v2.getType() - || v1.notequals(ai, v2)); + return LeekValueManager.getLeekBooleanValue(!equals_equals(ai, v1, v2).getBoolean()); } } diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 963ed985..f159b452 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -139,8 +139,16 @@ public int getType() { @Override public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { + comp = comp.getValue(); if (comp instanceof ObjectLeekValue) { - + var o = (ObjectLeekValue) comp; + if (o.clazz != clazz) return false; + for (var f : fields.entrySet()) { + if (!f.getValue().getValue().equals(ai, o.fields.get(f.getKey()))) { + return false; + } + } + return true; } return false; } From fbb6215d6368280958d06f229c8a466ba5932744 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 23:31:19 +0100 Subject: [PATCH 108/319] [object] Object as array key, improve static fields --- src/main/java/leekscript/runner/PhpArray.java | 11 +++++-- .../runner/values/ArrayLeekValue.java | 2 ++ .../runner/values/ClassLeekValue.java | 29 ++++++++++--------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 9c428e90..bc1e2ad4 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -7,7 +7,6 @@ import java.util.List; import java.util.Random; import java.util.Set; -import java.util.HashSet; import leekscript.compiler.LeekScript; import leekscript.runner.values.AbstractLeekValue; @@ -839,8 +838,14 @@ public String toString(AI ai, Set visited) throws LeekRunException { while (e != null) { if (e != mHead) sb.append(", "); - if (!isInOrder) - sb.append(e.key).append(" : "); + if (!isInOrder) { + if (e.key instanceof ObjectLeekValue) { + sb.append(((ObjectLeekValue) e.key).getString(ai)); + } else { + sb.append(e.key); + } + sb.append(" : "); + } if (visited.contains(e.value.getValue())) { sb.append("<...>"); } else { diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index f3e03b3a..35760750 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -114,6 +114,8 @@ public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunExcep value = value.getValue(); if (value instanceof StringLeekValue) key = value.getString(ai); + else if (value instanceof ObjectLeekValue) + key = value; else key = Integer.valueOf(value.getInt(ai)); return mValues.get(ai, key); diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index ba08d0c9..86525983 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -4,7 +4,6 @@ import java.util.Map.Entry; import leekscript.AILog; -import leekscript.compiler.bloc.ClassMethodBlock; import leekscript.runner.AI; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; @@ -84,21 +83,23 @@ public AbstractLeekValue run(AI ai, AbstractLeekValue thiz, AbstractLeekValue... @Override public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { - ai.addOperations(1); AbstractLeekValue result = staticFields.get(field); - if (result == null) { - if (field.equals("name")) { - return new StringLeekValue(name); - } else if (field.equals("fields")) { - return getFieldsArray(ai); - } else if (field.equals("methods")) { - return getMethodsArray(ai); - } else if (field.equals("parent")) { - return parent; - } - return LeekValueManager.NULL; + if (result != null) { + return result; + } + if (field.equals("name")) { + return new StringLeekValue(name); + } else if (field.equals("fields")) { + return getFieldsArray(ai); + } else if (field.equals("methods")) { + return getMethodsArray(ai); + } else if (field.equals("parent")) { + return parent; + } + if (parent instanceof ClassLeekValue) { + return parent.getField(ai, field); } - return result; + return LeekValueManager.NULL; } @Override From 2e443410ec275372384704940611b706922090b6 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 23:31:19 +0100 Subject: [PATCH 109/319] [class] Add getMethod --- .../java/leekscript/runner/values/ClassLeekValue.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 86525983..318d9fda 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -180,6 +180,15 @@ private ArrayLeekValue getMethodsArray(AI ai) throws LeekRunException { return methodsArray; } + public LeekAnonymousFunction getMethod(String method) { + var m = methods.get(method); + if (m != null) return m; + if (parent instanceof ClassLeekValue) { + return ((ClassLeekValue) parent).getMethod(method); + } + return null; + } + @Override public boolean getBoolean() { return true; From 315f20a5b248b40c06b0b7915831ecd9377a0c00 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 23:31:19 +0100 Subject: [PATCH 110/319] [array] Remove size management --- src/main/java/leekscript/runner/PhpArray.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index bc1e2ad4..7e079012 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -783,10 +783,6 @@ else if (f == e) { private void destroyElement(Element e) throws LeekRunException { mSize--; - if (e.key instanceof Integer) - e.value.removeFromTable(1); - else - e.value.removeFromTable(((String) e.key).length()); } private Element getElement(AI ai, Object key) throws LeekRunException { From 0df18690af901a5cb074f80e5de1e50e77892f31 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 21 Feb 2021 23:31:19 +0100 Subject: [PATCH 111/319] [object] Recursive string() method --- src/main/java/leekscript/runner/values/ObjectLeekValue.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index f159b452..728b8518 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -103,8 +103,9 @@ public boolean isNumeric() { public String getString(AI ai, Set visited) throws LeekRunException { visited.add(this); - if (clazz.methods.containsKey("string_0")) { - var result = clazz.methods.get("string_0").run(ai, this, new AbstractLeekValue[] {}); + var string_method = clazz.getMethod("string_0"); + if (string_method != null) { + var result = string_method.run(ai, this, new AbstractLeekValue[] {}); if (result.getType() != STRING) { ai.addSystemLog(AILog.ERROR, AILog.STRING_METHOD_MUST_RETURN_STRING, new String[] { clazz.name }); } else { From 6d0bf5b4858af9f84042e6d3bfe06bbaa547dca7 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 27 Feb 2021 22:04:27 +0100 Subject: [PATCH 112/319] [array] Cleaning --- .../values/PhpArrayVariableLeekValue.java | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java b/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java index cffa226b..20d7d093 100644 --- a/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java @@ -6,37 +6,14 @@ public class PhpArrayVariableLeekValue extends VariableLeekValue { - // private final PhpArray mArray; - // private int mTotalSize = 0; - public PhpArrayVariableLeekValue(PhpArray array, AI uai, AbstractLeekValue value, int keySize) throws LeekRunException { super(uai, value.getValue()); - // mArray = array; - // mTotalSize = value.getSize(); - // mArray.updateArraySize(mTotalSize + keySize); - // if (mValue instanceof ArrayLeekValue) { - // mValue.getArray().setParent(this); - // } } @Override public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunException { value = value.getValue(); - // int size = value.getSize(); - // mArray.updateArraySize(size - mTotalSize); - // mTotalSize = size; super.set(ai, value); - // if (mValue instanceof ArrayLeekValue) - // mValue.getArray().setParent(this); return mValue; } - - public void removeFromTable(int keySize) throws LeekRunException { - // mArray.updateArraySize(-mTotalSize - keySize); - } - - public void updateSize(int delta) throws LeekRunException { - // mTotalSize += delta; - // mArray.updateArraySize(delta); - } } From 15da0a57eec57e1325c03267382a13f1462999a1 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 27 Feb 2021 22:04:27 +0100 Subject: [PATCH 113/319] [instanceof] Implement instanceof --- src/main/java/leekscript/AILog.java | 1 + src/main/java/leekscript/compiler/WordParser.java | 4 ++++ .../compiler/expression/LeekExpression.java | 9 ++++++--- .../leekscript/compiler/expression/Operators.java | 13 ++++++++++--- .../runner/values/AbstractLeekValue.java | 15 +++++++++++++++ .../leekscript/runner/values/ObjectLeekValue.java | 3 +++ src/test/java/test/TestAI.java | 5 +++++ 7 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/main/java/leekscript/AILog.java b/src/main/java/leekscript/AILog.java index 00a62e7c..dc6bf045 100644 --- a/src/main/java/leekscript/AILog.java +++ b/src/main/java/leekscript/AILog.java @@ -33,6 +33,7 @@ public class AILog { public static final String STRING_METHOD_MUST_RETURN_STRING = "string_method_must_return_string"; public static final String UNKNOWN_FIELD = "unknown_field"; public static final String UNKNOWN_CONSTRUCTOR = "unknown_constructor"; + public static final String INSTANCEOF_MUST_BE_CLASS = "instanceof_must_be_class"; public interface Stream { public void write(JSONArray a); diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index 4c258c25..7b2208c3 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -364,6 +364,10 @@ else if(word.equalsIgnoreCase("and")){ type = T_OPERATOR; word = "&&"; } + else if (word.equalsIgnoreCase("instanceof")) { + type = T_OPERATOR; + word = "instanceof"; + } /* * else if(word.equalsIgnoreCase("not")){ * type = T_OPERATOR; diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index a516021d..2744c630 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -712,9 +712,12 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { mExpression2.writeJavaCode(mainblock, writer); writer.addCode(")"); return; - // case Operators.DOT: - // mExpression2.writeJavaCode(mainblock, writer); - // return; + case Operators.INSTANCEOF: + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(".instanceOf(mUAI, "); + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(")"); + return; } return; } diff --git a/src/main/java/leekscript/compiler/expression/Operators.java b/src/main/java/leekscript/compiler/expression/Operators.java index 140a1b7b..4d1c0e99 100644 --- a/src/main/java/leekscript/compiler/expression/Operators.java +++ b/src/main/java/leekscript/compiler/expression/Operators.java @@ -50,6 +50,7 @@ public class Operators { public final static int BITNOT = 47; public final static int NEW = 48; public final static int DOT = 49; + public final static int INSTANCEOF = 50; public final static int getOperator(String operator, int version) { if(operator.equals("[")) return CROCHET; @@ -105,6 +106,7 @@ public final static int getOperator(String operator, int version) { if(operator.equals("@")) return REFERENCE; if(operator.equals("new")) return NEW; if(operator.equals(".")) return DOT; + if(operator.equals("instanceof")) return INSTANCEOF; return -1; } @@ -112,16 +114,18 @@ public static int getPriority(int operator) { switch(operator) { case CROCHET: case PARENTHESIS: - return 16; + return 17; case DOT: - return 15; + return 16; case INCREMENT: case DECREMENT: case REFERENCE: case UNARY_MINUS: - return 14; + return 15; case NOT: case BITNOT: + return 14; + case NEW: return 13; case POWER: return 12; @@ -140,6 +144,7 @@ public static int getPriority(int operator) { case LESSEQUALS: case MORE: case MOREEQUALS: + case INSTANCEOF: return 8; case EQUALS: case NOTEQUALS: @@ -239,6 +244,8 @@ public static String getString(int operator) { return "^="; case NEW: return "new"; + case INSTANCEOF: + return "instanceof"; } return "null"; } diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index df9c4d45..b59a09d1 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -3,6 +3,7 @@ import java.util.HashSet; import java.util.Set; +import leekscript.AILog; import leekscript.runner.AI; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; @@ -196,6 +197,20 @@ public AbstractLeekValue brotate(AI ai, AbstractLeekValue value) throws LeekRunE throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } + public AbstractLeekValue instanceOf(AI ai, AbstractLeekValue value) throws LeekRunException { + var clazz = value.getValue(); + if (!(clazz instanceof ClassLeekValue)) { + ai.addOperations(AI.ERROR_LOG_COST); + ai.addSystemLog(AILog.ERROR, AILog.INSTANCEOF_MUST_BE_CLASS); + return LeekValueManager.getLeekBooleanValue(false); + } + var v = getValue(); + if (v instanceof ObjectLeekValue && ((ObjectLeekValue) v).getClazz() == clazz) { + return LeekValueManager.getLeekBooleanValue(true); + } + return LeekValueManager.getLeekBooleanValue(false); + } + public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { return LeekValueManager.NULL; } diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 728b8518..5af33415 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -164,4 +164,7 @@ public boolean isPrimitive() { return false; } + public ClassLeekValue getClazz() { + return clazz; + } } diff --git a/src/test/java/test/TestAI.java b/src/test/java/test/TestAI.java index 27266f4d..dff88303 100644 --- a/src/test/java/test/TestAI.java +++ b/src/test/java/test/TestAI.java @@ -54,4 +54,9 @@ public boolean[] anonymousFunctionReference(int id) { public int getVersion() { return 11; } + + @Override + protected String[] getErrorFiles() { + return null; + } } From 76145473b3c487df3ce5329296b6ef67320bc983 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 27 Feb 2021 22:04:27 +0100 Subject: [PATCH 114/319] [object] Continue objects, improve errors --- .../java/leekscript/compiler/JavaWriter.java | 49 ++++++++++++------- .../leekscript/compiler/WordCompiler.java | 19 +++++-- .../exceptions/LeekCompilerException.java | 1 + .../compiler/expression/LeekExpression.java | 5 ++ .../compiler/expression/LeekVariable.java | 12 +++-- .../LeekVariableDeclarationInstruction.java | 6 +-- src/main/java/leekscript/runner/AI.java | 7 ++- 7 files changed, 71 insertions(+), 28 deletions(-) diff --git a/src/main/java/leekscript/compiler/JavaWriter.java b/src/main/java/leekscript/compiler/JavaWriter.java index 0a561e6f..6617f5a3 100644 --- a/src/main/java/leekscript/compiler/JavaWriter.java +++ b/src/main/java/leekscript/compiler/JavaWriter.java @@ -1,6 +1,8 @@ package leekscript.compiler; import java.util.ArrayList; +import java.util.HashMap; +import java.util.TreeMap; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; @@ -8,15 +10,17 @@ public class JavaWriter { private final StringBuilder mCode; private int mLine; - private final ArrayList mLines; + private final TreeMap mLines = new TreeMap<>(); + private final HashMap, Integer> mFiles = new HashMap<>(); + private final ArrayList> mFilesList = new ArrayList<>(); private final boolean mWithDebug; private class Line { private final int mJavaLine; private final int mCodeLine; - private final AIFile mAI; + private final int mAI; - public Line(int java_line, int code_line, AIFile ai) { + public Line(int java_line, int code_line, int ai) { mJavaLine = java_line; mCodeLine = code_line; mAI = ai; @@ -25,7 +29,6 @@ public Line(int java_line, int code_line, AIFile ai) { public JavaWriter(boolean debug) { mCode = new StringBuilder(); - mLines = new ArrayList(); mLine = 1; mWithDebug = debug; } @@ -36,10 +39,20 @@ public boolean hasDebug() { public void addLine(String datas, int line, AIFile ai) { mCode.append(datas).append("\n"); - mLines.add(new Line(mLine, line, ai)); + int fileIndex = getFileIndex(ai); + mLines.put(mLine, new Line(mLine, line, fileIndex)); mLine++; } + private int getFileIndex(AIFile ai) { + var index = mFiles.get(ai); + if (index != null) return index; + var new_index = mFiles.size(); + mFiles.put(ai, new_index); + mFilesList.add(ai); + return new_index; + } + public void addLine(String datas) { mCode.append(datas).append("\n"); mLine++; @@ -59,27 +72,28 @@ public String getJavaCode() { } public void writeErrorFunction(IACompiler comp, String ai) { - mCode.append("protected String[] getErrorString(){ return new String[]{"); + mCode.append("protected String[] getErrorString() { return new String[] {"); String aiJson = JSON.toJSONString(ai); - - boolean first = true; - for (Line l : mLines) { - if (!first) - mCode.append(","); - else - first = false; + for (Line l : mLines.values()) { JSONArray array = new JSONArray(); array.add(l.mJavaLine); - array.add(l.mAI.getPath()); + array.add(l.mAI); array.add(l.mCodeLine); mCode.append(JSON.toJSONString(array.toJSONString())); - + mCode.append(", "); // System.out.println(l.mAI.getPath() + ":" + l.mCodeLine + " -> " + l.mJavaLine); } - mCode.append("};}\nprotected String getAItring(){ return "); + mCode.append("};}\nprotected String getAItring() { return "); mCode.append(aiJson); mCode.append(";}\n"); + + mCode.append("protected String[] getErrorFiles() { return new String[] {"); + for (var f : mFilesList) { + mCode.append("\"" + f.getPath() + "\""); + mCode.append(", "); + } + mCode.append("};}\n"); } public void addCounter(int id) { @@ -91,6 +105,7 @@ public int getCurrentLine() { } public void addPosition(IAWord token) { - mLines.add(new Line(mLine, token.getLine(), token.getAI())); + var index = getFileIndex(token.getAI()); + mLines.put(mLine, new Line(mLine, token.getLine(), index)); } } diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index d9229daf..d2aca33a 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -63,11 +63,12 @@ public WordCompiler(WordParser cmp, MainLeekBlock main, AIFile ai, int versio public void readCode() throws LeekCompilerException { try { mCompiler.compile(this); - // Receherche des fonctions utilisateur + // Recherche des fonctions utilisateur while (mCompiler.haveWords()) { - if (mCompiler.getWord().getWord().equals("global")) { + if (mCompiler.getWord().getType() == WordParser.T_STRING && mCompiler.getWord().getWord().equals("global")) { mCompiler.skipWord(); var global = mCompiler.readWord(); + // System.out.println("global = " + global.getWord() + " " + global.getLine()); if (!isGlobalAvailable(global.getWord()) || mMain.hasDeclaredGlobal(global.getWord())) { addError(new AnalyzeError(global, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); } else { @@ -327,6 +328,9 @@ private void functionBlock() throws LeekCompilerException { boolean is_reference = false; if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("@")) { is_reference = true; + if (getVersion() >= 11) { + addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCES_DEPRECATED)); + } mCompiler.skipWord(); } if (mCompiler.getWord().getType() != WordParser.T_STRING) @@ -366,6 +370,9 @@ private void forBlock() throws LeekCompilerException { boolean reference1 = false; if (mCompiler.getWord().getWord().equals("@")) { reference1 = true; + if (getVersion() >= 11) { + addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCES_DEPRECATED)); + } mCompiler.skipWord(); } // On récupère ensuite le nom de la variable @@ -400,6 +407,9 @@ private void forBlock() throws LeekCompilerException { boolean reference2 = false; if (mCompiler.getWord().getWord().equals("@")) { reference2 = true; + if (getVersion() >= 11) { + addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCES_DEPRECATED)); + } mCompiler.skipWord(); } // On récupère ensuite le nom de la variable accueillant la valeur @@ -797,7 +807,7 @@ public ClassMethodBlock classMethod(ClassDeclarationInstruction classDeclaration int param_count = 0; while (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("@")) { - errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCE_IGNORED_IN_METHODS)); + errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCES_DEPRECATED)); mCompiler.skipWord(); } if (mCompiler.getWord().getType() != WordParser.T_STRING) @@ -1046,6 +1056,9 @@ private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerExcepti boolean is_reference = false; if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("@")) { is_reference = true; + if (getVersion() >= 11) { + addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCES_DEPRECATED)); + } mCompiler.skipWord(); } if (mCompiler.getWord().getType() != WordParser.T_STRING) diff --git a/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java b/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java index 7902aedc..2ff3b399 100644 --- a/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java +++ b/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java @@ -58,6 +58,7 @@ public class LeekCompilerException extends Exception { public final static String CLASS_MEMBER_DOES_NOT_EXIST = "class_member_does_not_exist"; public final static String CLASS_STATIC_MEMBER_DOES_NOT_EXIST = "class_static_member_does_not_exist"; public final static String EXTENDS_LOOP = "extends_loop"; + public final static String REFERENCES_DEPRECATED = "reference_deprecated"; /** * diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index 2744c630..2509fb6a 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -730,6 +730,11 @@ public boolean isLeftValue() { @Override public void analyze(WordCompiler compiler) { + + if (mOperator == Operators.REFERENCE && compiler.getVersion() >= 11) { + compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCES_DEPRECATED)); + } + if (mExpression1 != null) mExpression1.analyze(compiler); if (mExpression2 != null) mExpression2.analyze(compiler); diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index 3d5df040..867328ef 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -106,20 +106,24 @@ public void analyze(WordCompiler compiler) { if (this.type == VariableType.SUPER) { return; // Déjà OK } - if (compiler.getMainBlock().hasUserFunction(token.getWord(), true)) { - this.type = VariableType.FUNCTION; - return; - } + // Local variables first var v = compiler.getCurrentBlock().getVariable(token.getWord(), true); if (v != null) { this.type = v.getVariableType(); this.classDeclaration = v.getClassDeclaration(); return; } + // Global user functions + if (compiler.getMainBlock().hasUserFunction(token.getWord(), true)) { + this.type = VariableType.FUNCTION; + return; + } + // LS constants if (LeekConstants.get(token.getWord()) != null) { this.type = VariableType.SYSTEM_CONSTANT; return; } + // LS functions if (LeekFunctions.isFunction(token.getWord()) != -1) { this.type = VariableType.SYSTEM_FUNCTION; return; diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index a51208c3..812d33c2 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -80,11 +80,11 @@ public void analyze(WordCompiler compiler) { mValue.analyze(compiler); } // Variables interdites - if (token.getWord().equals("this")) { + if (compiler.getVersion() >= 11 && token.getWord().equals("this")) { compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.THIS_NOT_ALLOWED_HERE)); } else { - // Vérification déjà existante (on vérifie les globales seulement en 1.1 car il y a un léger bug en 1.0 avec les includes) - if ((compiler.getVersion() >= 11 && compiler.getMainBlock().hasGlobal(token.getWord())) || compiler.getMainBlock().hasUserFunction(token.getWord(), true) || compiler.getCurrentBlock().hasVariable(token.getWord())) { + // Vérification déjà existante (on vérifie les globales et fonctions seulement en 1.1 car il y a un léger bug en 1.0 avec les includes) + if ((compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(token.getWord()) || compiler.getMainBlock().hasUserFunction(token.getWord(), true))) || compiler.getCurrentBlock().hasVariable(token.getWord())) { compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); } else { // On ajoute la variable diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 08e7859e..a8d26574 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -127,7 +127,10 @@ protected String getErrorLocalisation(int line) { if (mErrorObject.size() > value) { JSONArray l = mErrorObject.getJSONArray(value); if (l != null && l.size() >= 3) { - return "\t▶ AI " + l.getString(1) + ", line " + l.getString(2); // + ", java " + line; + var files = getErrorFiles(); + var f = l.getIntValue(1); + String file = f < files.length ? files[f] : "?"; + return "\t▶ AI " + file + ", line " + l.getString(2); // + ", java " + line; } } return ""; @@ -371,6 +374,8 @@ else if (type == AILog.STANDARD) protected abstract String[] getErrorString(); + protected abstract String[] getErrorFiles(); + protected abstract String getAItring(); public abstract AbstractLeekValue runIA() throws LeekRunException; From 7a7f36ff3e7fbf9b1ffc43057c6e62f6c3e95737 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 27 Feb 2021 22:04:27 +0100 Subject: [PATCH 115/319] [compiler] Escape file path --- src/main/java/leekscript/compiler/JavaWriter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/JavaWriter.java b/src/main/java/leekscript/compiler/JavaWriter.java index 6617f5a3..40bbcd93 100644 --- a/src/main/java/leekscript/compiler/JavaWriter.java +++ b/src/main/java/leekscript/compiler/JavaWriter.java @@ -90,7 +90,7 @@ public void writeErrorFunction(IACompiler comp, String ai) { mCode.append("protected String[] getErrorFiles() { return new String[] {"); for (var f : mFilesList) { - mCode.append("\"" + f.getPath() + "\""); + mCode.append("\"" + f.getPath().replaceAll("\\/", "/") + "\""); mCode.append(", "); } mCode.append("};}\n"); From a0c754e550381809c19fd3364665a99928dfc5eb Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 27 Feb 2021 22:04:27 +0100 Subject: [PATCH 116/319] [compiler] Hide errors --- src/main/java/leekscript/compiler/IACompiler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index 98faa56c..933d5531 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -48,7 +48,7 @@ public AnalyzeResult analyze(AIFile ai) throws LeekCompilerException { compiler.readCode(); compiler.analyze(); - System.out.println("errors " + compiler.getErrors().size()); + // System.out.println("errors " + compiler.getErrors().size()); if (compiler.getErrors().size() > 0) { for (var error : compiler.getErrors()) { mInformations.add(error.toJSON()); @@ -76,7 +76,7 @@ public String compile(AIFile ai, String javaClassName, String AIClass) throws WordCompiler compiler = new WordCompiler(parser, main, ai, ai.getVersion()); compiler.readCode(); compiler.analyze(); - System.out.println("errors " + compiler.getErrors().size()); + // System.out.println("errors " + compiler.getErrors().size()); if (compiler.getErrors().size() > 0) { for (var error : compiler.getErrors()) { From 1cd9370ce7adf28b16df476b325285d182cd2ff6 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 27 Feb 2021 22:04:27 +0100 Subject: [PATCH 117/319] [ternary] Fix --- .../compiler/expression/LeekTernaire.java | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekTernaire.java b/src/main/java/leekscript/compiler/expression/LeekTernaire.java index 83ac6ca2..76383b63 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTernaire.java +++ b/src/main/java/leekscript/compiler/expression/LeekTernaire.java @@ -51,16 +51,8 @@ public int getType() { return EXPRESSION; } - @Override - public AbstractExpression getAbstractExpression() { - return this; - } - @Override public String getString() { - if(mCondition instanceof LeekExpression) mCondition = ((LeekExpression) mCondition).getAbstractExpression(); - if(mExpression1 instanceof LeekExpression) mExpression1 = ((LeekExpression) mExpression1).getAbstractExpression(); - if(mExpression2 instanceof LeekExpression) mExpression2 = ((LeekExpression) mExpression2).getAbstractExpression(); String retour = "("; retour += mCondition == null ? "null" : mCondition.getString(); retour += " ? "; @@ -72,9 +64,9 @@ public String getString() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if(mCondition instanceof LeekExpression) mCondition = ((LeekExpression) mCondition).getAbstractExpression(); - if(mExpression1 instanceof LeekExpression) mExpression1 = ((LeekExpression) mExpression1).getAbstractExpression(); - if(mExpression2 instanceof LeekExpression) mExpression2 = ((LeekExpression) mExpression2).getAbstractExpression(); + // if(mCondition instanceof LeekExpression) mCondition = ((LeekExpression) mCondition).getAbstractExpression(); + // if(mExpression1 instanceof LeekExpression) mExpression1 = ((LeekExpression) mExpression1).getAbstractExpression(); + // if(mExpression2 instanceof LeekExpression) mExpression2 = ((LeekExpression) mExpression2).getAbstractExpression(); if (!complete()) writer.addCode("/* " + getString() + " */"); else{ writer.addCode("("); From cfece79b8235c90915e00a9c9703ee39f38ac9b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Sun, 28 Feb 2021 23:37:09 +0100 Subject: [PATCH 118/319] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 79ed40d8..090f8811 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# LeekScript v1 +# LeekScript First version of LeekScript language, built in Java. -Used in the [leek-wars-generator-v1](https://github.com/leek-wars/leek-wars-generator-v1) project. +Used in the [leek-wars-generator](https://github.com/leek-wars/leek-wars-generator) project. ### Build ``` From c40cd2b935ee084ec4da39e309ec7d39570c4b5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Sun, 28 Feb 2021 23:59:00 +0100 Subject: [PATCH 119/319] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 090f8811..74464628 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # LeekScript -First version of LeekScript language, built in Java. +The language of Leek Wars, built in Java. Used in the [leek-wars-generator](https://github.com/leek-wars/leek-wars-generator) project. ### Build From cd83efe9d2c4a5d349e16dee0ff8dff0b284a3b4 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 14 Mar 2021 18:27:06 +0100 Subject: [PATCH 120/319] [compiler] Fix file names with \ --- src/main/java/leekscript/compiler/JavaWriter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/JavaWriter.java b/src/main/java/leekscript/compiler/JavaWriter.java index 40bbcd93..9089f17c 100644 --- a/src/main/java/leekscript/compiler/JavaWriter.java +++ b/src/main/java/leekscript/compiler/JavaWriter.java @@ -90,7 +90,7 @@ public void writeErrorFunction(IACompiler comp, String ai) { mCode.append("protected String[] getErrorFiles() { return new String[] {"); for (var f : mFilesList) { - mCode.append("\"" + f.getPath().replaceAll("\\/", "/") + "\""); + mCode.append("\"" + f.getPath().replaceAll("\\\\/", "/").replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\"") + "\""); mCode.append(", "); } mCode.append("};}\n"); From 9321aba8df3544f021ffbd6372622959c024f45f Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 20:51:57 +0200 Subject: [PATCH 121/319] [constant] Add object type --- src/main/java/leekscript/runner/AI.java | 2 ++ .../java/leekscript/runner/LeekConstants.java | 15 ++++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index a8d26574..743d7e29 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -153,6 +153,8 @@ public int typeOf(AbstractLeekValue value) { return (int) LeekConstants.TYPE_BOOLEAN.getValue(); if (value.getType() == AbstractLeekValue.FUNCTION) return (int) LeekConstants.TYPE_FUNCTION.getValue(); + if (value.getType() == AbstractLeekValue.OBJECT) + return (int) LeekConstants.TYPE_OBJECT.getValue(); return 0; } diff --git a/src/main/java/leekscript/runner/LeekConstants.java b/src/main/java/leekscript/runner/LeekConstants.java index 0fc9cd93..3627c43f 100644 --- a/src/main/java/leekscript/runner/LeekConstants.java +++ b/src/main/java/leekscript/runner/LeekConstants.java @@ -3,7 +3,7 @@ import java.util.HashMap; public enum LeekConstants implements ILeekConstant { - + PI(Math.PI, LeekFunctions.DOUBLE), E(Math.E, LeekFunctions.DOUBLE), @@ -26,18 +26,19 @@ public enum LeekConstants implements ILeekConstant { TYPE_BOOLEAN(2, LeekFunctions.INT), TYPE_STRING(3, LeekFunctions.INT), TYPE_ARRAY(4, LeekFunctions.INT), - TYPE_FUNCTION(5, LeekFunctions.INT); - + TYPE_FUNCTION(5, LeekFunctions.INT), + TYPE_OBJECT(6, LeekFunctions.INT); + private static HashMap extraConstants = new HashMap(); - + private double value; private int type; - + LeekConstants(double value, int type) { this.value = value; this.type = type; } - + @Override public double getValue() { return value; @@ -61,7 +62,7 @@ public static void setExtraConstants(String extraConstantsClass) { e.printStackTrace(); } } - + public static ILeekConstant get(String name) { for (LeekConstants constant : LeekConstants.values()) { if (constant.name().equals(name)) From 0cbe8d83ab7b158b4901d923d95cc8de700b23bd Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 20:53:26 +0200 Subject: [PATCH 122/319] [log] Improve logs --- src/main/java/leekscript/runner/AI.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 743d7e29..a4c26da4 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -74,7 +74,7 @@ public void addOperations(int nb) throws LeekRunException { } } - public void addOperationsNoCheck(int nb) throws LeekRunException { + public void addOperationsNoCheck(int nb) { mOperations += nb; } @@ -354,16 +354,11 @@ public AbstractLeekValue jsonDecode(String json) { } } - public void addSystemLog(int type, String key) { + public void addSystemLog(int type, String key) throws LeekRunException { addSystemLog(type, key, null); } - public void addSystemLog(int type, String key, String[] parameters) { - addSystemLog(type, key, parameters, Thread.currentThread().getStackTrace()); - } - - public void addSystemLog(int type, String key, String[] parameters, StackTraceElement[] elements) { - + public void addSystemLog(int type, String key, String[] parameters) throws LeekRunException { if (type == AILog.WARNING) type = AILog.SWARNING; else if (type == AILog.ERROR) @@ -371,7 +366,7 @@ else if (type == AILog.ERROR) else if (type == AILog.STANDARD) type = AILog.SSTANDARD; - logs.addSystemLog(type, getErrorMessage(elements), key, parameters); + logs.addSystemLog(type, getErrorMessage(Thread.currentThread().getStackTrace()), key, parameters); } protected abstract String[] getErrorString(); From f00dee0f54109e12eb8a848c00f0109b0e20ebd0 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 20:53:47 +0200 Subject: [PATCH 123/319] [class] Fix instanceof --- .../leekscript/runner/values/AbstractLeekValue.java | 3 ++- .../leekscript/runner/values/ClassLeekValue.java | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index b59a09d1..8db7b480 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -198,6 +198,7 @@ public AbstractLeekValue brotate(AI ai, AbstractLeekValue value) throws LeekRunE } public AbstractLeekValue instanceOf(AI ai, AbstractLeekValue value) throws LeekRunException { + ai.addOperations(2); var clazz = value.getValue(); if (!(clazz instanceof ClassLeekValue)) { ai.addOperations(AI.ERROR_LOG_COST); @@ -205,7 +206,7 @@ public AbstractLeekValue instanceOf(AI ai, AbstractLeekValue value) throws LeekR return LeekValueManager.getLeekBooleanValue(false); } var v = getValue(); - if (v instanceof ObjectLeekValue && ((ObjectLeekValue) v).getClazz() == clazz) { + if (v instanceof ObjectLeekValue && ((ObjectLeekValue) v).getClazz().descendsFrom((ClassLeekValue) clazz)) { return LeekValueManager.getLeekBooleanValue(true); } return LeekValueManager.getLeekBooleanValue(false); diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 318d9fda..6b8264a8 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -236,4 +236,17 @@ public Object toJSON(AI ai) { public boolean isPrimitive() { return false; } + + public boolean descendsFrom(ClassLeekValue clazz) { + var current = this; + while (current != null) { + if (current == clazz) return true; + if (current.parent instanceof ClassLeekValue) { + current = (ClassLeekValue) current.parent; + } else { + return false; + } + } + return false; + } } From 518831fbe1b3ac13f8ed3d002c605fed1533719c Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 20:54:04 +0200 Subject: [PATCH 124/319] [class] Improve super methods --- .../leekscript/compiler/WordCompiler.java | 10 ++++--- .../exceptions/LeekCompilerException.java | 1 + .../compiler/expression/LeekExpression.java | 12 ++++----- .../expression/LeekExpressionFunction.java | 8 ++++-- .../ClassDeclarationInstruction.java | 20 +++++++++----- .../runner/values/AbstractLeekValue.java | 4 +++ .../runner/values/ClassLeekValue.java | 7 +++++ .../runner/values/ObjectLeekValue.java | 27 ++++++++++++++++++- .../runner/values/VariableLeekValue.java | 4 +++ 9 files changed, 75 insertions(+), 18 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index d2aca33a..2d2e5b92 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -144,7 +144,8 @@ public void readCode() throws LeekCompilerException { // Puis on lit l'instruction compileWord(); } - while (mCurentBlock.getParent() != null && !mCurentBlock.hasAccolade()) { + int i = 0; + while (i++ < 100 && mCurentBlock.getParent() != null && !mCurentBlock.hasAccolade()) { if (mCurentBlock instanceof DoWhileBlock) { DoWhileBlock do_block = (DoWhileBlock) mCurentBlock; mCurentBlock = mCurentBlock.endInstruction(); @@ -756,7 +757,7 @@ public void classAccessLevelMember(ClassDeclarationInstruction classDeclaration, if (word2.getType() == WordParser.T_PAR_LEFT) { // Méthode ClassMethodBlock method = classMethod(classDeclaration, accessLevel, name.getWord(), false); - classDeclaration.addMethod(name, method); + classDeclaration.addMethod(this, name, method); } else { // Field AbstractExpression expr = null; @@ -780,7 +781,7 @@ public void classStaticMember(ClassDeclarationInstruction classDeclaration, Acce } else if (mCompiler.getWord().getType() == WordParser.T_PAR_LEFT) { // Méthode ClassMethodBlock method = classMethod(classDeclaration, accessLevel, name.getWord(), true); - classDeclaration.addStaticMethod(name.getWord(), method); + classDeclaration.addStaticMethod(this, name, method); if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) mCompiler.skipWord(); return; @@ -1029,6 +1030,9 @@ else if (operator == Operators.INCREMENT) if (retour.getOperator() == -1) { result = retour.getExpression1(); } + if (result == null) { + throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.UNCOMPLETE_EXPRESSION); + } try { result.validExpression(this, mMain); } catch (LeekExpressionException e) { diff --git a/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java b/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java index 2ff3b399..3a1f0ec4 100644 --- a/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java +++ b/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java @@ -59,6 +59,7 @@ public class LeekCompilerException extends Exception { public final static String CLASS_STATIC_MEMBER_DOES_NOT_EXIST = "class_static_member_does_not_exist"; public final static String EXTENDS_LOOP = "extends_loop"; public final static String REFERENCES_DEPRECATED = "reference_deprecated"; + public final static String DUPLICATED_METHOD = "duplicated_method"; /** * diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index 2509fb6a..ee0a0863 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -755,15 +755,15 @@ public void analyze(WordCompiler compiler) { } if (mOperator == Operators.INCREMENT || mOperator == Operators.DECREMENT || mOperator == Operators.PRE_INCREMENT || mOperator == Operators.PRE_DECREMENT) { - if (!(mExpression2 instanceof LeekVariable) && !(mExpression2 instanceof LeekGlobal) && !(mExpression2 instanceof LeekTabularValue)) + if (!mExpression2.isLeftValue()) compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.CANT_ASSIGN_VALUE)); // throw new LeekExpressionException(mExpression2, LeekCompilerException.CANT_ASSIGN_VALUE); - if (mExpression2 instanceof LeekVariable) { - var v = (LeekVariable) mExpression2; - if (v.getVariableType() == VariableType.SYSTEM_FUNCTION || v.getVariableType() == VariableType.FUNCTION) { - compiler.getMainBlock().addRedefinedFunction(((LeekVariable) mExpression2).getName()); - } + if (mExpression2 instanceof LeekVariable) { + var v = (LeekVariable) mExpression2; + if (v.getVariableType() == VariableType.SYSTEM_FUNCTION || v.getVariableType() == VariableType.FUNCTION) { + compiler.getMainBlock().addRedefinedFunction(((LeekVariable) mExpression2).getName()); } + } if (mExpression2 instanceof LeekTabularValue) ((LeekTabularValue) mExpression2).setLeftValue(true); } diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 6818423b..9dc69350 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -65,8 +65,12 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { ILeekFunction system_function = null; if (mExpression instanceof LeekObjectAccess) { var object = ((LeekObjectAccess) mExpression).getObject(); - object.writeJavaCode(mainblock, writer); - writer.addCode(".callMethod(mUAI, \"" + ((LeekObjectAccess) mExpression).getField() + "_" + mParameters.size() + "\""); + if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.SUPER) { + writer.addCode("u_this.callSuperMethod(mUAI, \"" + ((LeekObjectAccess) mExpression).getField() + "_" + mParameters.size() + "\""); + } else { + object.writeJavaCode(mainblock, writer); + writer.addCode(".callMethod(mUAI, \"" + ((LeekObjectAccess) mExpression).getField() + "_" + mParameters.size() + "\""); + } } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.SUPER) { // Super constructor var variable = (LeekVariable) mExpression; diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 01365a89..83e07d3f 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -86,7 +86,11 @@ public void addConstructor(ClassMethodBlock block) { constructors.put(block.countParameters(), block); } - public void addMethod(IAWord token, ClassMethodBlock method) { + public void addMethod(WordCompiler compiler, IAWord token, ClassMethodBlock method) { + // On regarde si il n'y a pas déjà une méthode statique du même nom + if (staticMethods.containsKey(token.getWord())) { + compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.DUPLICATED_METHOD)); + } if (!methods.containsKey(token.getWord())) { methods.put(token.getWord(), new HashMap<>()); methodVariables.put(token.getWord(), new LeekVariable(token, VariableType.METHOD)); @@ -101,12 +105,16 @@ public boolean hasMethod(String name, int param_count) { return methods.containsKey(name + "_" + param_count); } - public void addStaticMethod(String name, ClassMethodBlock method) { - if (!staticMethods.containsKey(name)) { - staticMethods.put(name, new HashMap<>()); - staticMethodVariables.put(name, new LeekVariable(token, VariableType.STATIC_METHOD)); + public void addStaticMethod(WordCompiler compiler, IAWord token, ClassMethodBlock method) { + // On regarde si il n'y a pas déjà une méthode du même nom + if (methods.containsKey(token.getWord())) { + compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.DUPLICATED_METHOD)); + } + if (!staticMethods.containsKey(token.getWord())) { + staticMethods.put(token.getWord(), new HashMap<>()); + staticMethodVariables.put(token.getWord(), new LeekVariable(token, VariableType.STATIC_METHOD)); } - staticMethods.get(name).put(method.countParameters(), method); + staticMethods.get(token.getWord()).put(method.countParameters(), method); } public void addField(WordCompiler compiler, IAWord word, AbstractExpression expr) throws LeekCompilerException { diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 8db7b480..87aefec2 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -220,6 +220,10 @@ public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... a return LeekValueManager.NULL; } + public AbstractLeekValue callSuperMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + return LeekValueManager.NULL; + } + public void callConstructor(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException {} public abstract int getType(); diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 6b8264a8..5d356d41 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -189,6 +189,13 @@ public LeekAnonymousFunction getMethod(String method) { return null; } + public LeekAnonymousFunction getSuperMethod(String method) { + if (parent instanceof ClassLeekValue) { + return ((ClassLeekValue) parent).getMethod(method); + } + return null; + } + @Override public boolean getBoolean() { return true; diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 5af33415..25f720f7 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -59,10 +59,35 @@ public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunExcep return getField(ai, value.getString(ai)); } + @Override + public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws LeekRunException { + return getField(ai, value.getString(ai)); + } + @Override public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { ai.addOperations(1); - LeekAnonymousFunction result = clazz.methods.get(method); + LeekAnonymousFunction result = clazz.getMethod(method); + if (result == null) { + int underscore = method.lastIndexOf("_"); + int argCount = Integer.parseInt(method.substring(underscore + 1)); + String methodRealName = method.substring(0, underscore) + "("; + for (int i = 0; i < argCount; ++i) { + if (i > 0) methodRealName += ", "; + methodRealName += "x"; + } + methodRealName += ")"; + ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_METHOD, new String[] { clazz.name, methodRealName }); + return LeekValueManager.NULL; + } + // Call method with new arguments, add the object at the beginning + return result.run(ai, this, arguments); + } + + @Override + public AbstractLeekValue callSuperMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + ai.addOperations(1); + LeekAnonymousFunction result = clazz.getSuperMethod(method); if (result == null) { int underscore = method.lastIndexOf("_"); int argCount = Integer.parseInt(method.substring(underscore + 1)); diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index 183bccd2..98e82002 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -241,6 +241,10 @@ public AbstractLeekValue callMethod(AI ai, String field, AbstractLeekValue... ar return mValue.callMethod(ai, field, arguments); } + public AbstractLeekValue callSuperMethod(AI ai, String field, AbstractLeekValue... arguments) throws LeekRunException { + return mValue.callSuperMethod(ai, field, arguments); + } + public void callConstructor(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException { mValue.callConstructor(ai, thiz, arguments); } From 93e8e37d65c3dc91cd67bba5d9a139abf4a501f1 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 14 Mar 2021 18:56:15 +0100 Subject: [PATCH 125/319] [log] Fix log costs --- src/main/java/leekscript/runner/AI.java | 1 + src/main/java/leekscript/runner/LeekFunctions.java | 2 -- src/main/java/leekscript/runner/LeekOperations.java | 2 -- src/main/java/leekscript/runner/values/AbstractLeekValue.java | 4 +--- src/main/java/leekscript/runner/values/FunctionLeekValue.java | 4 ---- 5 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index a4c26da4..bcd3b75a 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -359,6 +359,7 @@ public void addSystemLog(int type, String key) throws LeekRunException { } public void addSystemLog(int type, String key, String[] parameters) throws LeekRunException { + addOperations(AI.ERROR_LOG_COST); if (type == AILog.WARNING) type = AILog.SWARNING; else if (type == AILog.ERROR) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 14cc5cb9..619ffd57 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -1216,7 +1216,6 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu color(3) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - leekIA.addOperations(AI.ERROR_LOG_COST); leekIA.addSystemLog(AILog.WARNING, AILog.DEPRECATED_FUNCTION, new String[] { "color", "getColor" }); return leekIA.color(parameters[0], parameters[1], parameters[2]); } @@ -1437,7 +1436,6 @@ public static AbstractLeekValue executeFunction(AI leekIA, ILeekFunction functio } else { // Message d'erreur String ret = AbstractLeekValue.getParamString(parameters); - leekIA.addOperations(AI.ERROR_LOG_COST); leekIA.addSystemLog(AILog.ERROR, AILog.UNKNOWN_FUNCTION, new String[] { function + "(" + ret + ")" }); return LeekValueManager.NULL; } diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index 8f871c0a..46bd9a03 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -117,7 +117,6 @@ public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeek v2 = v2.getValue(); if (v1.isNumeric() && v2.isNumeric()) { if (v2.getDouble(ai) == 0) { - ai.addOperations(AI.ERROR_LOG_COST); ai.addSystemLog(AILog.ERROR, AILog.DIVISION_BY_ZERO); return LeekValueManager.NULL; } @@ -140,7 +139,6 @@ public static AbstractLeekValue modulus(AI ai, AbstractLeekValue v1, AbstractLee v2 = v2.getValue(); if (v1.isNumeric() && v2.isNumeric()) { if (v2.getDouble(ai) == 0) { - ai.addOperations(AI.ERROR_LOG_COST); ai.addSystemLog(AILog.ERROR, AILog.DIVISION_BY_ZERO); return LeekValueManager.NULL; } diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 87aefec2..87053928 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -201,7 +201,6 @@ public AbstractLeekValue instanceOf(AI ai, AbstractLeekValue value) throws LeekR ai.addOperations(2); var clazz = value.getValue(); if (!(clazz instanceof ClassLeekValue)) { - ai.addOperations(AI.ERROR_LOG_COST); ai.addSystemLog(AILog.ERROR, AILog.INSTANCEOF_MUST_BE_CLASS); return LeekValueManager.getLeekBooleanValue(false); } @@ -235,9 +234,8 @@ public boolean isReference() { public abstract Object toJSON(AI ai) throws LeekRunException; public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... value) throws LeekRunException { - // On ne peux pas exécuter ce type de variable - ai.addOperations(AI.ERROR_LOG_COST); + ai.addOperations(1); return LeekValueManager.NULL; } diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index 5ba93c3a..d31f7ec2 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -114,8 +114,6 @@ public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... values) thr } else if (mType == USER_FUNCTION) { if (values.length != ai.userFunctionCount(mId)) { - - ai.addOperations(AI.ERROR_LOG_COST); ai.addSystemLog(AILog.ERROR, AILog.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { AbstractLeekValue.getParamString(values), String.valueOf(ai.userFunctionCount(mId)) }); } else { @@ -128,8 +126,6 @@ else if (mType == USER_FUNCTION) { } else if (mType == ANONYMOUS_FUNCTION) { if (values.length != ai.anonymousFunctionCount(mId)) { - - ai.addOperations(AI.ERROR_LOG_COST); ai.addSystemLog(AILog.ERROR, AILog.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { AbstractLeekValue.getParamString(values), String.valueOf(ai.anonymousFunctionCount(mId)) }); } From 021aaa93670fd15912932334a064b8ea72854fb9 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 20:54:51 +0200 Subject: [PATCH 126/319] [function] Add error when calling a wrong value --- src/main/java/leekscript/runner/values/AbstractLeekValue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 87053928..3b5b0dd8 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -235,7 +235,7 @@ public boolean isReference() { public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... value) throws LeekRunException { // On ne peux pas exécuter ce type de variable - ai.addOperations(1); + ai.addSystemLog(AILog.ERROR, AILog.CAN_NOT_EXECUTE_VALUE, new String[] { getString(ai) }); return LeekValueManager.NULL; } From 4659b68d113368bccd0a7579135877eb19526040 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 20:54:51 +0200 Subject: [PATCH 127/319] [operator] Fix not for ls 1.0 --- src/main/java/leekscript/compiler/WordCompiler.java | 10 ++++++++++ .../leekscript/compiler/expression/LeekExpression.java | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 2d2e5b92..332a3685 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -867,6 +867,9 @@ public AbstractExpression readExpression() throws LeekCompilerException { LeekExpression retour = new LeekExpression(); while (mCompiler.haveWords()) { IAWord word = mCompiler.getWord(); + if (word.getType() == WordParser.T_PAR_RIGHT) { + break; + } if (retour.needOperator()) { // Si on attend un opérateur mais qu'il vient pas @@ -1030,6 +1033,13 @@ else if (operator == Operators.INCREMENT) if (retour.getOperator() == -1) { result = retour.getExpression1(); } + if (getVersion() == 10 && result instanceof LeekExpression) { + var expr = (LeekExpression) result; + if (expr.getOperator() == Operators.NOT && expr.getExpression2() == null) { + // Un "not" tout seul est valide en LS 1.0 + result = new LeekVariable(expr.getOperatorToken(), VariableType.LOCAL); + } + } if (result == null) { throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.UNCOMPLETE_EXPRESSION); } diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index ee0a0863..9fd08019 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -54,6 +54,10 @@ public int getOperator() { return mOperator; } + public IAWord getOperatorToken() { + return mOperatorToken; + } + public int getLastOperator() { if (mExpression2 != null && mExpression2 instanceof LeekExpression) { return ((LeekExpression) mExpression2).getLastOperator(); @@ -414,7 +418,6 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t // mExpression2 = ((LeekExpression) mExpression2).getAbstractExpression(); if (mExpression1 == null || mExpression2 == null || mOperator == -1) throw new LeekExpressionException(this, LeekCompilerException.UNCOMPLETE_EXPRESSION); - return mExpression1.validExpression(compiler, mainblock) && mExpression2.validExpression(compiler, mainblock); } From 4105e18f88e7cc9b2e94a94696a17e21abadfd1f Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 20:54:51 +0200 Subject: [PATCH 128/319] [object] Fix == --- .../java/leekscript/runner/values/ObjectLeekValue.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 25f720f7..eef3b90d 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -165,6 +165,14 @@ public int getType() { @Override public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { + comp = comp.getValue(); + if (comp instanceof ObjectLeekValue) { + return this == comp; + } + return false; + } + + public boolean equalsDeep(AI ai, AbstractLeekValue comp) throws LeekRunException { comp = comp.getValue(); if (comp instanceof ObjectLeekValue) { var o = (ObjectLeekValue) comp; From 9212a012cc495a13341caa4437cc559234a10051 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 20:54:51 +0200 Subject: [PATCH 129/319] [error] Add new errors for object methods --- .../java/leekscript/runner/values/AbstractLeekValue.java | 6 ++++++ src/main/java/leekscript/runner/values/ClassLeekValue.java | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 3b5b0dd8..1e999595 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -212,14 +212,20 @@ public AbstractLeekValue instanceOf(AI ai, AbstractLeekValue value) throws LeekR } public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { + // Aucun champ + ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_FIELD, new String[] { getString(ai), field }); return LeekValueManager.NULL; } public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + // Aucune méthode + ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_METHOD, new String[] { getString(ai), method }); return LeekValueManager.NULL; } public AbstractLeekValue callSuperMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + // Aucune méthode + ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_METHOD, new String[] { getString(ai), method }); return LeekValueManager.NULL; } diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 5d356d41..402a9a39 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -152,6 +152,9 @@ public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... arguments) if (constructors.containsKey(arg_count)) { return constructors.get(arg_count).run(ai, object, arguments); } else { + if (arg_count > 0) { + ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_CONSTRUCTOR, new String[] { name, String.valueOf(arguments.length) }); + } return object; } } From 9c586ab491f43c11b7e506f672d8269c9fb54111 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 20:54:51 +0200 Subject: [PATCH 130/319] [foreach] Check if value is array + fix cost --- src/main/java/leekscript/AILog.java | 1 + src/main/java/leekscript/compiler/bloc/ForeachBlock.java | 2 +- src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java | 5 ++--- .../java/leekscript/runner/values/AbstractLeekValue.java | 6 ++++++ src/main/java/leekscript/runner/values/ArrayLeekValue.java | 5 +++++ .../java/leekscript/runner/values/ReferenceLeekValue.java | 5 +++++ .../java/leekscript/runner/values/VariableLeekValue.java | 5 +++++ 7 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/main/java/leekscript/AILog.java b/src/main/java/leekscript/AILog.java index dc6bf045..4748591f 100644 --- a/src/main/java/leekscript/AILog.java +++ b/src/main/java/leekscript/AILog.java @@ -34,6 +34,7 @@ public class AILog { public static final String UNKNOWN_FIELD = "unknown_field"; public static final String UNKNOWN_CONSTRUCTOR = "unknown_constructor"; public static final String INSTANCEOF_MUST_BE_CLASS = "instanceof_must_be_class"; + public static final String NOT_ITERABLE = "not_iterable"; public interface Stream { public void write(JSONArray a); diff --git a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java index 19c65b07..56b80940 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java @@ -46,7 +46,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("final AbstractLeekValue " + ar + " = "); mArray.writeJavaCode(mainblock, writer); writer.addLine(".getValue();", mLine, mAI); - writer.addLine("if(" + ar + ".isArray()){"); + writer.addLine("if(" + ar + ".isArrayForIteration(mUAI)){"); if(mIsDeclaration) writer.addLine("final VariableLeekValue " + iterator_name + " = new VariableLeekValue(mUAI, LeekValueManager.NULL);"); else writer.addLine(iterator_name + ".set(mUAI, LeekValueManager.NULL);"); if (mReference || mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { diff --git a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java index ed4e632d..1214fe49 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java @@ -59,7 +59,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { mArray.writeJavaCode(mainblock, writer); writer.addCode(".getValue();"); StringBuilder sb = new StringBuilder(); - sb.append("if(").append(ar).append(".isArray()){"); + sb.append("if(").append(ar).append(".isArrayForIteration(mUAI)){"); //Clé if(mIsKeyDeclaration) sb.append("final VariableLeekValue ").append(key_iterator).append(" = new VariableLeekValue(mUAI, LeekValueManager.NULL);"); else sb.append(key_iterator).append(".set(mUAI, LeekValueManager.NULL);"); @@ -69,7 +69,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { //On fait le parcours //Déclaration de la variable sb.append("ArrayLeekValue.ArrayIterator ").append(var).append("=").append(ar).append(".getArray().getArrayIterator();"); - sb.append("while(!").append(var).append(".ended()){"); + sb.append("while(!").append(var).append(".ended()){ mUAI.addOperations(1); "); //Maj des variables if (mKeyReference || mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { sb.append(key_iterator).append(".setRef(mUAI, ").append(var).append(".getKeyRef());"); @@ -82,7 +82,6 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { sb.append(val_iterator).append(".set(mUAI, ").append(var).append(".getValueRef());"); } sb.append(var).append(".next();"); - writer.addCounter(1); writer.addLine(sb.toString(), mLine, mAI); //Instructions diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 1e999595..ef258b01 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -60,6 +60,12 @@ public boolean isArray() { return false; } + public boolean isArrayForIteration(AI ai) throws LeekRunException { + // Pas itérable + ai.addSystemLog(AILog.ERROR, AILog.NOT_ITERABLE, new String[] { getString(ai) }); + return false; + } + public boolean isNull() { return false; } diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index 35760750..f7141437 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -225,6 +225,11 @@ public boolean isArray() { return true; } + @Override + public boolean isArrayForIteration(AI ai) throws LeekRunException { + return true; + } + @Override public ArrayLeekValue getArray() { return this; diff --git a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java b/src/main/java/leekscript/runner/values/ReferenceLeekValue.java index 835bcc8e..bd0aa993 100644 --- a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java +++ b/src/main/java/leekscript/runner/values/ReferenceLeekValue.java @@ -49,6 +49,11 @@ public boolean isArray() { return mValue.isArray(); } + @Override + public boolean isArrayForIteration(AI ai) throws LeekRunException { + return mValue.isArray(); + } + @Override public boolean isNull() { return mValue.isNull(); diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index 98e82002..f399a375 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -63,6 +63,11 @@ public boolean isArray() { return mValue.isArray(); } + @Override + public boolean isArrayForIteration(AI ai) throws LeekRunException { + return mValue.isArray(); + } + @Override public boolean isNull() { return mValue.isNull(); From baac6a89804eb2465618285a4a15a893d56b4cd2 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 20:54:51 +0200 Subject: [PATCH 131/319] [string] Allow free \ in strings --- .../java/leekscript/compiler/expression/LeekString.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekString.java b/src/main/java/leekscript/compiler/expression/LeekString.java index 7c124b7e..1a1989eb 100644 --- a/src/main/java/leekscript/compiler/expression/LeekString.java +++ b/src/main/java/leekscript/compiler/expression/LeekString.java @@ -40,7 +40,12 @@ else if (mString.charAt(i) == '\\') { else if (len > i && mString.charAt(i + 1) == 't') str += "\\"; else { if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { - str += "\\"; + if (len > i && mString.charAt(i + 1) == '\\') { + str += "\\\\"; + i++; + } else { + str += "\\\\"; + } } else { // LeekScript 1.0 had a bug with "\\" strings producing 4 \ str += "\\\\"; From d35d64665d20a1d2945b65df20951f0c0bf3f80f Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 20:54:51 +0200 Subject: [PATCH 132/319] [operations] Fix operations for operators <, <=, > and >= --- src/main/java/leekscript/runner/LeekOperations.java | 4 ---- src/main/java/leekscript/runner/values/IntLeekValue.java | 2 -- 2 files changed, 6 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index 46bd9a03..ce305582 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -201,22 +201,18 @@ public static AbstractLeekValue notequals(AI ai, AbstractLeekValue v1, AbstractL } public static AbstractLeekValue less(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.less(ai, v2)); } public static AbstractLeekValue more(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.more(ai, v2)); } public static AbstractLeekValue lessequals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.lessequals(ai, v2)); } public static AbstractLeekValue moreequals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v1.moreequals(ai, v2)); } diff --git a/src/main/java/leekscript/runner/values/IntLeekValue.java b/src/main/java/leekscript/runner/values/IntLeekValue.java index cc40a1f2..52648bfe 100644 --- a/src/main/java/leekscript/runner/values/IntLeekValue.java +++ b/src/main/java/leekscript/runner/values/IntLeekValue.java @@ -67,7 +67,6 @@ public AbstractLeekValue pre_decrement(AI ai) throws LeekRunException { @Override public boolean less(AI ai, AbstractLeekValue comp) throws LeekRunException { - ai.addOperations(1); comp = comp.getValue(); if (comp instanceof DoubleLeekValue) return getDouble(ai) < comp.getDouble(ai); @@ -76,7 +75,6 @@ public boolean less(AI ai, AbstractLeekValue comp) throws LeekRunException { @Override public boolean more(AI ai, AbstractLeekValue comp) throws LeekRunException { - ai.addOperations(1); comp = comp.getValue(); if (comp instanceof DoubleLeekValue) return getDouble(ai) > comp.getDouble(ai); From 0d153c0af625b0b1ed72d35c68cc6a3b4b623301 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 20:54:51 +0200 Subject: [PATCH 133/319] [block] Fix variable search --- src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java b/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java index eb0d05af..054f88c1 100644 --- a/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java @@ -117,8 +117,7 @@ public LeekInstruction lastInstruction() { } public boolean hasVariable(String variable) { - return mVariables.containsKey(variable); - // return getVariable(variable, false) != null; + return getVariable(variable, false) != null; } public LeekVariable getVariable(String variable, boolean includeClassMembers) { From 55243e38b3edbff0f7c7df5471e4840f9299d4d8 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 20:54:51 +0200 Subject: [PATCH 134/319] [compiler] Add errors for wrong constructor and static methods --- .../exceptions/LeekCompilerException.java | 2 + .../expression/LeekExpressionFunction.java | 45 ++++++++++++++----- .../compiler/expression/LeekObjectAccess.java | 4 ++ .../ClassDeclarationInstruction.java | 10 +++-- 4 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java b/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java index 3a1f0ec4..287951c5 100644 --- a/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java +++ b/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java @@ -60,6 +60,8 @@ public class LeekCompilerException extends Exception { public final static String EXTENDS_LOOP = "extends_loop"; public final static String REFERENCES_DEPRECATED = "reference_deprecated"; public final static String DUPLICATED_METHOD = "duplicated_method"; + public final static String UNKNOWN_CONSTRUCTOR = "unknown_constructor"; + public final static String UNKNOWN_STATIC_METHOD = "unknown_static_method"; /** * diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 9dc69350..6d353183 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -2,6 +2,8 @@ import java.util.ArrayList; +import org.graalvm.compiler.word.ObjectAccess; + import leekscript.compiler.AnalyzeError; import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; @@ -11,6 +13,7 @@ import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.compiler.instruction.ClassDeclarationInstruction; import leekscript.runner.ILeekFunction; import leekscript.runner.LeekFunctions; @@ -144,18 +147,40 @@ public void analyze(WordCompiler compiler) { parameter.analyze(compiler); } - if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.FUNCTION) { + if (mExpression instanceof LeekVariable) { var v = (LeekVariable) mExpression; - int nb_params = LeekFunctions.isFunction(v.getName()); - if (nb_params == -1) { - nb_params = compiler.getMainBlock().getUserFunctionParametersCount(v.getName()); - if (mParameters.size() != nb_params) { - compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, LeekCompilerException.INVALID_PAREMETER_COUNT)); + if (v.getVariableType() == VariableType.FUNCTION) { + int nb_params = LeekFunctions.isFunction(v.getName()); + if (nb_params == -1) { + nb_params = compiler.getMainBlock().getUserFunctionParametersCount(v.getName()); + if (mParameters.size() != nb_params) { + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, LeekCompilerException.INVALID_PAREMETER_COUNT)); + } + } else { + var f = LeekFunctions.getValue(v.getName()); + if (mParameters.size() > nb_params || mParameters.size() < f.getArgumentsMin()) + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, LeekCompilerException.INVALID_PAREMETER_COUNT)); + } + } else if (v.getVariableType() == VariableType.CLASS) { + System.out.println("Class " + v); + + var clazz = v.getClassDeclaration(); + if (mParameters.size() != 0 && !clazz.hasConstructor(mParameters.size())) { + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, LeekCompilerException.UNKNOWN_CONSTRUCTOR, new String[] { clazz.getName() })); + } + } + } else if (mExpression instanceof LeekObjectAccess) { + System.out.println("OA " + mExpression.getString()); + + var oa = (LeekObjectAccess) mExpression; + if (oa.getObject() instanceof LeekVariable) { + var v = (LeekVariable) oa.getObject(); + if (v.getVariableType() == VariableType.CLASS) { + var clazz = v.getClassDeclaration(); + if (!clazz.hasStaticMethod(oa.getField(), mParameters.size())) { + compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, LeekCompilerException.UNKNOWN_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); + } } - } else { - var f = LeekFunctions.getValue(v.getName()); - if (mParameters.size() > nb_params || mParameters.size() < f.getArgumentsMin()) - compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, LeekCompilerException.INVALID_PAREMETER_COUNT)); } } } diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index 44d6bd0a..aa5f3cce 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -72,4 +72,8 @@ public void analyze(WordCompiler compiler) { public String getField() { return field.getWord(); } + + public IAWord getFieldToken() { + return field; + } } diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 83e07d3f..ca969c29 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -98,11 +98,11 @@ public void addMethod(WordCompiler compiler, IAWord token, ClassMethodBlock meth methods.get(token.getWord()).put(method.countParameters(), method); } - public boolean hasMethod(String name, int param_count) { + public boolean hasMethod(String name, int paramCount) { if (name.equals("constructor")) { - return hasConstructor(param_count); + return hasConstructor(paramCount); } - return methods.containsKey(name + "_" + param_count); + return methods.containsKey(name + "_" + paramCount); } public void addStaticMethod(WordCompiler compiler, IAWord token, ClassMethodBlock method) { @@ -117,6 +117,10 @@ public void addStaticMethod(WordCompiler compiler, IAWord token, ClassMethodBloc staticMethods.get(token.getWord()).put(method.countParameters(), method); } + public boolean hasStaticMethod(String name, int paramCount) { + return staticMethods.containsKey(name) && staticMethods.get(name).containsKey(paramCount); + } + public void addField(WordCompiler compiler, IAWord word, AbstractExpression expr) throws LeekCompilerException { if (fields.containsKey(word.getWord()) || staticFields.containsKey(word.getWord())) { compiler.addError(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.FIELD_ALREADY_EXISTS)); From aa89982a3aa70ad612b7a6d097b97aeef7d00cd0 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 14 Mar 2021 18:27:06 +0100 Subject: [PATCH 135/319] [value] Add callSuperMethod and getOrCreate --- src/main/java/leekscript/runner/values/AbstractLeekValue.java | 4 ++++ src/main/java/leekscript/runner/values/ObjectLeekValue.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index ef258b01..6919131f 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -235,6 +235,10 @@ public AbstractLeekValue callSuperMethod(AI ai, String method, AbstractLeekValue return LeekValueManager.NULL; } + public AbstractLeekValue callSuperMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + return LeekValueManager.NULL; + } + public void callConstructor(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException {} public abstract int getType(); diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index eef3b90d..219acb67 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -58,6 +58,10 @@ public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunException { return getField(ai, value.getString(ai)); } + @Override + public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws LeekRunException { + return getField(ai, value.getString(ai)); + } @Override public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws LeekRunException { From 80c54850c6aad16474c75cdf36cf8af4fac5a464 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 21:27:15 +0200 Subject: [PATCH 136/319] [error] Use enum for errors --- src/main/java/leekscript/AILog.java | 27 +-- src/main/java/leekscript/common/Error.java | 79 +++++++ .../leekscript/compiler/AnalyzeError.java | 9 +- .../java/leekscript/compiler/IACompiler.java | 5 +- .../leekscript/compiler/WordCompiler.java | 199 +++++++++--------- .../java/leekscript/compiler/WordParser.java | 9 +- .../compiler/bloc/AbstractLeekBlock.java | 3 +- .../exceptions/LeekCompilerException.java | 88 ++------ .../compiler/expression/LeekExpression.java | 10 +- .../expression/LeekExpressionException.java | 16 +- .../expression/LeekExpressionFunction.java | 13 +- .../compiler/expression/LeekObjectAccess.java | 6 +- .../compiler/expression/LeekTernaire.java | 6 +- .../compiler/expression/LeekVariable.java | 4 +- .../ClassDeclarationInstruction.java | 15 +- .../LeekVariableDeclarationInstruction.java | 6 +- src/main/java/leekscript/runner/AI.java | 17 +- .../java/leekscript/runner/LeekFunctions.java | 5 +- .../leekscript/runner/LeekOperations.java | 5 +- .../runner/values/AbstractLeekValue.java | 17 +- .../runner/values/ClassLeekValue.java | 11 +- .../runner/values/FunctionLeekValue.java | 11 +- .../runner/values/ObjectLeekValue.java | 13 +- 23 files changed, 290 insertions(+), 284 deletions(-) create mode 100644 src/main/java/leekscript/common/Error.java diff --git a/src/main/java/leekscript/AILog.java b/src/main/java/leekscript/AILog.java index 4748591f..972e0899 100644 --- a/src/main/java/leekscript/AILog.java +++ b/src/main/java/leekscript/AILog.java @@ -13,29 +13,6 @@ public class AILog { public final static int SWARNING = 7; public final static int SERROR = 8; - // Clés - public static final String DEPRECATED_FUNCTION = "deprecated_function"; - public static final String UNKNOWN_FUNCTION = "unknown_function"; - public static final String DIVISION_BY_ZERO = "division_by_zero"; - public static final String CAN_NOT_EXECUTE_VALUE = "can_not_execute_value"; - public static final String CAN_NOT_EXECUTE_WITH_ARGUMENTS = "can_not_execute_with_arguments"; - public static final String NO_AI_EQUIPPED = "no_ai_equipped"; - public static final String INVALID_AI = "invalid_ai"; - public static final String CAN_NOT_COMPILE_AI = "can_not_compile_ai"; - public static final String AI_DISABLED = "ai_disabled"; - public static final String AI_INTERRUPTED = "ai_interrupted"; - public static final String AI_TIMEOUT = "ai_timeout"; - public static final String CODE_TOO_LARGE = "code_too_large"; - public static final String CODE_TOO_LARGE_FUNCTION = "code_too_large_function"; - public static final String NUMBER_OF_OPERATIONS = "number_of_operations"; - public static final String UNKNOWN_METHOD = "unknown_method"; - public static final String UNKNOWN_STATIC_METHOD = "unknown_static_method"; - public static final String STRING_METHOD_MUST_RETURN_STRING = "string_method_must_return_string"; - public static final String UNKNOWN_FIELD = "unknown_field"; - public static final String UNKNOWN_CONSTRUCTOR = "unknown_constructor"; - public static final String INSTANCEOF_MUST_BE_CLASS = "instanceof_must_be_class"; - public static final String NOT_ITERABLE = "not_iterable"; - public interface Stream { public void write(JSONArray a); } @@ -53,7 +30,7 @@ public void write(JSONArray a) { }; } - public void addSystemLog(int type, String trace, String key, String[] parameters) { + public void addSystemLog(int type, String trace, int key, String[] parameters) { int paramSize = 0; if (parameters != null) { @@ -62,7 +39,7 @@ public void addSystemLog(int type, String trace, String key, String[] parameters } } - if (!addSize(20 + trace.length() + key.length() + paramSize)) { + if (!addSize(20 + trace.length() + paramSize)) { return; } diff --git a/src/main/java/leekscript/common/Error.java b/src/main/java/leekscript/common/Error.java new file mode 100644 index 00000000..88e06c3e --- /dev/null +++ b/src/main/java/leekscript/common/Error.java @@ -0,0 +1,79 @@ +package leekscript.common; + +public enum Error { + UNKNOWN, + FUNCTION_NAME_UNAVAILABLE, // 1 + PARAMETER_NAME_UNAVAILABLE, // 2 + OPENING_PARENTHESIS_EXPECTED, // 3 + OPENING_CURLY_BRACKET_EXPECTED, // 4 + PARAMETER_NAME_EXPECTED, // 5 + FUNCTION_NAME_EXPECTED, // 6 + PARENTHESIS_EXPECTED_AFTER_PARAMETERS, // 7 + OPEN_BLOC_REMAINING, // 8 + NO_BLOC_TO_CLOSE, // 9 + END_OF_SCRIPT_UNEXPECTED, // 10 + END_OF_INSTRUCTION_EXPECTED, // 11 + BREAK_OUT_OF_LOOP, // 12 + CONTINUE_OUT_OF_LOOP, // 13 + INCLUDE_ONLY_IN_MAIN_BLOCK, // 14 + AI_NAME_EXPECTED, // 15 + AI_NOT_EXISTING, // 16 + CLOSING_PARENTHESIS_EXPECTED, // 17 + CLOSING_SQUARE_BRACKET_EXPECTED, // 18 + FUNCTION_ONLY_IN_MAIN_BLOCK, // 19 + VARIABLE_NAME_EXPECTED, // 20 + VARIABLE_NAME_UNAVAILABLE, // 21 + VARIABLE_NOT_EXISTS, // 22 + KEYWORD_UNEXPECTED, // 23 + KEYWORD_IN_EXPECTED, // 24 + WHILE_EXPECTED_AFTER_DO, // 25 + NO_IF_BLOCK, // 26 + GLOBAL_ONLY_IN_MAIN_BLOCK, // 27 + VAR_NAME_EXPECTED_AFTER_GLOBAL, // 28 + VAR_NAME_EXPECTED, // 29 + SIMPLE_ARRAY, // 30 + ASSOCIATIVE_ARRAY, // 31 + PARENTHESIS_EXPECTED_AFTER_FUNCTION, // 32 + UNKNOWN_VARIABLE_OR_FUNCTION, // 33 + OPERATOR_UNEXPECTED, // 34 + VALUE_EXPECTED, // 35 + CANT_ADD_INSTRUCTION_AFTER_BREAK, // 36 + UNCOMPLETE_EXPRESSION, // 37 + CANT_ASSIGN_VALUE, // 38 + FUNCTION_NOT_EXISTS, // 39 + INVALID_PARAMETER_COUNT, // 40 + INVALID_CHAR, // 41 + INVALID_NUMBER, // 42 + CONSTRUCTOR_ALREADY_EXISTS, // 43 + END_OF_CLASS_EXPECTED, // 44 + FIELD_ALREADY_EXISTS, // 45 + NO_SUCH_CLASS, // 46 + THIS_NOT_ALLOWED_HERE, // 47 + KEYWORD_MUST_BE_IN_CLASS, // 48 + SUPER_NOT_AVAILABLE_PARENT, // 49 + CLASS_MEMBER_DOES_NOT_EXIST, // 50 + CLASS_STATIC_MEMBER_DOES_NOT_EXIST, // 51 + EXTENDS_LOOP, // 52 + REFERENCE_DEPRECATED, // 53 + DUPLICATED_METHOD, // 54 + DEPRECATED_FUNCTION, // 55 + UNKNOWN_FUNCTION, // 56 + DIVISION_BY_ZERO, // 57 + CAN_NOT_EXECUTE_VALUE, // 58 + CAN_NOT_EXECUTE_WITH_ARGUMENTS, // 59 + NO_AI_EQUIPPED, // 60 + INVALID_AI, // 61 + CAN_NOT_COMPILE_AI, // 62 + AI_DISABLED, // 63 + AI_INTERRUPTED, // 64 + AI_TIMEOUT, // 65 + CODE_TOO_LARGE, // 66 + CODE_TOO_LARGE_FUNCTION, // 67 + NOT_ITERABLE, // 68 + UNKNOWN_METHOD, // 69 + UNKNOWN_STATIC_METHOD, // 70 + STRING_METHOD_MUST_RETURN_STRING, // 71 + UNKNOWN_FIELD, // 72 + UNKNOWN_CONSTRUCTOR, // 73 + INSTANCEOF_MUST_BE_CLASS // 74 +} \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/AnalyzeError.java b/src/main/java/leekscript/compiler/AnalyzeError.java index 42934acd..16a413c9 100644 --- a/src/main/java/leekscript/compiler/AnalyzeError.java +++ b/src/main/java/leekscript/compiler/AnalyzeError.java @@ -1,6 +1,7 @@ package leekscript.compiler; import com.alibaba.fastjson.JSONArray; +import leekscript.common.Error; public class AnalyzeError implements Comparable { @@ -15,14 +16,14 @@ public static enum AnalyzeErrorLevel { // public int endLine; // public int endCharacter; public IAWord token; - public String error; + public Error error; public AnalyzeErrorLevel level; public String[] parameters; - public AnalyzeError(IAWord token, AnalyzeErrorLevel level, String error) { + public AnalyzeError(IAWord token, AnalyzeErrorLevel level, Error error) { this(token, level, error, null); } - public AnalyzeError(IAWord token, AnalyzeErrorLevel level, String error, String[] parameters) { + public AnalyzeError(IAWord token, AnalyzeErrorLevel level, Error error, String[] parameters) { this.token = token; this.error = error; this.level = level; @@ -36,7 +37,7 @@ public JSONArray toJSON() { array.add(token.getLine()); array.add(token.getCharacter()); array.add(token.getWord()); - array.add(this.error); + array.add(this.error.ordinal()); if (parameters != null) { array.add(parameters); } diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index 933d5531..85a05144 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -2,6 +2,7 @@ import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.exceptions.LeekCompilerException; +import leekscript.common.Error; import java.util.ArrayList; import java.util.List; @@ -24,14 +25,14 @@ public static class AnalyzeResult { public IACompiler() {} - public void addError(AIFile ia_context, int line, int pos, String word, String informations, String[] parameters) { + public void addError(AIFile ia_context, int line, int pos, String word, Error errorType, String[] parameters) { JSONArray error = new JSONArray(); error.add(0); // level error.add(ia_context.getId()); error.add(line); error.add(pos); error.add(word); - error.add(informations); + error.add(errorType.ordinal()); if (parameters != null) error.add(parameters); mInformations.add(error); diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 332a3685..3d5f83a5 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -3,6 +3,7 @@ import java.util.Set; import java.util.TreeSet; +import leekscript.common.Error; import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.AbstractLeekBlock; import leekscript.compiler.bloc.AnonymousFunctionBlock; @@ -70,7 +71,7 @@ public void readCode() throws LeekCompilerException { var global = mCompiler.readWord(); // System.out.println("global = " + global.getWord() + " " + global.getLine()); if (!isGlobalAvailable(global.getWord()) || mMain.hasDeclaredGlobal(global.getWord())) { - addError(new AnalyzeError(global, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); + addError(new AnalyzeError(global, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); } else { mMain.addGlobal(global.getWord()); } @@ -82,7 +83,7 @@ public void readCode() throws LeekCompilerException { mCompiler.skipWord(); global = mCompiler.readWord(); if (!isGlobalAvailable(global.getWord()) || mMain.hasDeclaredGlobal(global.getWord())) { - addError(new AnalyzeError(global, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); + addError(new AnalyzeError(global, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); } else { mMain.addGlobal(global.getWord()); } @@ -97,10 +98,10 @@ public void readCode() throws LeekCompilerException { if (funcName.equals("(")) continue; if (!isAvailable(funcName, false)) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.FUNCTION_NAME_UNAVAILABLE); + throw new LeekCompilerException(mCompiler.getWord(), Error.FUNCTION_NAME_UNAVAILABLE); if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_PARENTHESIS_EXPECTED); } int param_count = 0; while (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { @@ -108,9 +109,9 @@ public void readCode() throws LeekCompilerException { mCompiler.skipWord(); } if (mCompiler.getWord().getType() != WordParser.T_STRING) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_EXPECTED); + throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_EXPECTED); // if (!isAvailable(mCompiler.getWord().getWord(), true)) - // throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_UNAVAILABLE); + // throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_UNAVAILABLE); mCompiler.skipWord(); param_count++; @@ -118,7 +119,7 @@ public void readCode() throws LeekCompilerException { mCompiler.skipWord(); } if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); + throw new LeekCompilerException(mCompiler.getWord(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); } mMain.addFunctionDeclaration(funcName, param_count); @@ -155,11 +156,11 @@ public void readCode() throws LeekCompilerException { mCurentBlock = mCurentBlock.endInstruction(); } if (!mMain.equals(mCurentBlock)) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPEN_BLOC_REMAINING); + throw new LeekCompilerException(mCompiler.lastWord(), Error.OPEN_BLOC_REMAINING); } catch (IndexOutOfBoundsException e) { e.printStackTrace(System.out); - throw new LeekCompilerException(mCompiler.endWord(), LeekCompilerException.END_OF_SCRIPT_UNEXPECTED); + throw new LeekCompilerException(mCompiler.endWord(), Error.END_OF_SCRIPT_UNEXPECTED); } } @@ -180,8 +181,8 @@ private void compileWord() throws LeekCompilerException { } else if (word.getType() == WordParser.T_ACCOLADE_RIGHT) { // Fermeture de bloc if (!mCurentBlock.hasAccolade() || mCurentBlock.getParent() == null) { - // throw new LeekCompilerException(word, LeekCompilerException.NO_BLOC_TO_CLOSE); - errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.NO_BLOC_TO_CLOSE)); + // throw new LeekCompilerException(word, Error.NO_BLOC_TO_CLOSE); + errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.NO_BLOC_TO_CLOSE)); } else { if (mCurentBlock instanceof DoWhileBlock) { DoWhileBlock do_block = (DoWhileBlock) mCurentBlock; @@ -238,24 +239,24 @@ private void compileWord() throws LeekCompilerException { return; } else if (word.getWord().equals("break")) { if (!mCurentBlock.isBreakable()) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.BREAK_OUT_OF_LOOP); + throw new LeekCompilerException(mCompiler.lastWord(), Error.BREAK_OUT_OF_LOOP); } mCompiler.skipWord(); if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) mCompiler.skipWord(); - // throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + // throw new LeekCompilerException(mCompiler.lastWord(), Error.END_OF_INSTRUCTION_EXPECTED); mCurentBlock.addInstruction(this, new LeekBreakInstruction(mCurentBlock.countInstructions(), mCompiler.lastWord().getLine(), mCompiler.lastWord().getAI())); return; } else if (word.getWord().equals("continue")) { if (!mCurentBlock.isBreakable()) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CONTINUE_OUT_OF_LOOP); + throw new LeekCompilerException(mCompiler.lastWord(), Error.CONTINUE_OUT_OF_LOOP); } mCompiler.skipWord(); if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) mCompiler.skipWord(); // if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) - // throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + // throw new LeekCompilerException(mCompiler.lastWord(), Error.END_OF_INSTRUCTION_EXPECTED); mCurentBlock.addInstruction(this, new LeekContinueInstruction(mCurentBlock.countInstructions(), mLine, mAI)); return; } else if (word.getWord().equals("return")) { @@ -280,7 +281,7 @@ private void compileWord() throws LeekCompilerException { mCompiler.skipWord(); } // if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) - // throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + // throw new LeekCompilerException(mCompiler.lastWord(), Error.END_OF_INSTRUCTION_EXPECTED); mCurentBlock.addInstruction(this, new LeekExpressionInstruction(exp, mLine, mAI)); } @@ -291,36 +292,36 @@ public void writeJava(String className, JavaWriter writer, String AIClass) { private void includeBlock() throws LeekCompilerException { // On vérifie qu'on est dans le bloc principal if (!mCurentBlock.equals(mMain)) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.INCLUDE_ONLY_IN_MAIN_BLOCK); + throw new LeekCompilerException(mCompiler.lastWord(), Error.INCLUDE_ONLY_IN_MAIN_BLOCK); // On récupere l'ia if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_PARENTHESIS_EXPECTED); if (mCompiler.getWord().getType() != WordParser.T_VAR_STRING) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.AI_NAME_EXPECTED); + throw new LeekCompilerException(mCompiler.getWord(), Error.AI_NAME_EXPECTED); String iaName = mCompiler.readWord().getWord(); if (!mMain.includeAI(this, iaName)) { - errors.add(new AnalyzeError(mCompiler.lastWord(), AnalyzeErrorLevel.ERROR, LeekCompilerException.AI_NOT_EXISTING, new String[] { iaName })); + errors.add(new AnalyzeError(mCompiler.lastWord(), AnalyzeErrorLevel.ERROR, Error.AI_NOT_EXISTING, new String[] { iaName })); } if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.CLOSING_PARENTHESIS_EXPECTED); } private void functionBlock() throws LeekCompilerException { // Déclaration de fonction utilisateur if (!mCurentBlock.equals(mMain)) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.FUNCTION_ONLY_IN_MAIN_BLOCK); + throw new LeekCompilerException(mCompiler.lastWord(), Error.FUNCTION_ONLY_IN_MAIN_BLOCK); // Récupération du nom de la fonction if (mCompiler.getWord().getType() != WordParser.T_STRING) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.FUNCTION_NAME_EXPECTED); + throw new LeekCompilerException(mCompiler.getWord(), Error.FUNCTION_NAME_EXPECTED); IAWord funcName = mCompiler.readWord(); if (!isAvailable(funcName.getWord(), false)) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.FUNCTION_NAME_UNAVAILABLE); + throw new LeekCompilerException(mCompiler.getWord(), Error.FUNCTION_NAME_UNAVAILABLE); if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_PARENTHESIS_EXPECTED); } FunctionBlock block = new FunctionBlock(mCurentBlock, mMain, mLine, mAI, funcName); @@ -330,25 +331,25 @@ private void functionBlock() throws LeekCompilerException { if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("@")) { is_reference = true; if (getVersion() >= 11) { - addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCES_DEPRECATED)); + addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, Error.REFERENCE_DEPRECATED)); } mCompiler.skipWord(); } if (mCompiler.getWord().getType() != WordParser.T_STRING) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_EXPECTED); + throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_EXPECTED); // if (!isAvailable(mCompiler.getWord().getWord(), true)) - // throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_UNAVAILABLE); + // throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_UNAVAILABLE); block.addParameter(mCompiler.readWord(), is_reference); if (mCompiler.getWord().getType() == WordParser.T_VIRG) mCompiler.skipWord(); } if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); + throw new LeekCompilerException(mCompiler.getWord(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); } // On regarde s'il y a des accolades if (mCompiler.readWord().getType() != WordParser.T_ACCOLADE_LEFT) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_CURLY_BRACKET_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_CURLY_BRACKET_EXPECTED); mMain.addFunction(block); } @@ -356,7 +357,7 @@ private void forBlock() throws LeekCompilerException { // Bloc de type for(i=0;i<5;i++) ou encore for(element in tableau) // On peut déclarer une variable pendant l'instruction d'initialisation if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_PARENTHESIS_EXPECTED); } boolean isDeclaration = false; @@ -372,23 +373,23 @@ private void forBlock() throws LeekCompilerException { if (mCompiler.getWord().getWord().equals("@")) { reference1 = true; if (getVersion() >= 11) { - addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCES_DEPRECATED)); + addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, Error.REFERENCE_DEPRECATED)); } mCompiler.skipWord(); } // On récupère ensuite le nom de la variable if (mCompiler.getWord().getType() != WordParser.T_STRING) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.VARIABLE_NAME_EXPECTED); + throw new LeekCompilerException(mCompiler.getWord(), Error.VARIABLE_NAME_EXPECTED); IAWord varName = mCompiler.readWord(); // Si c'est une déclaration on vérifie que le nom est disponnible /* if (isDeclaration) { if (!isAvailable(varName, true)) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); + throw new LeekCompilerException(mCompiler.lastWord(), Error.VARIABLE_NAME_UNAVAILABLE); } else { // Sinon on vérifie que la variable existe if (!mCurentBlock.hasVariable(varName) && !mMain.hasGlobal(varName)) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.VARIABLE_NOT_EXISTS); + throw new LeekCompilerException(mCompiler.lastWord(), Error.VARIABLE_NOT_EXISTS); } */ // Maintenant on va savoir si on a affaire à un for(i in array) ou à un @@ -409,26 +410,26 @@ private void forBlock() throws LeekCompilerException { if (mCompiler.getWord().getWord().equals("@")) { reference2 = true; if (getVersion() >= 11) { - addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCES_DEPRECATED)); + addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, Error.REFERENCE_DEPRECATED)); } mCompiler.skipWord(); } // On récupère ensuite le nom de la variable accueillant la valeur if (mCompiler.getWord().getType() != WordParser.T_STRING) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.VARIABLE_NAME_EXPECTED); + throw new LeekCompilerException(mCompiler.getWord(), Error.VARIABLE_NAME_EXPECTED); IAWord valueVarName = mCompiler.readWord(); /* if (isValueDeclaration) { if (!isAvailable(valueVarName, true)) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); + throw new LeekCompilerException(mCompiler.lastWord(), Error.VARIABLE_NAME_UNAVAILABLE); } else { // Sinon on vérifie que la variable existe if (!mCurentBlock.hasVariable(valueVarName) && !mMain.hasGlobal(valueVarName)) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.VARIABLE_NOT_EXISTS); + throw new LeekCompilerException(mCompiler.lastWord(), Error.VARIABLE_NOT_EXISTS); } */ if (!mCompiler.readWord().getWord().equals("in")) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.KEYWORD_IN_EXPECTED); + throw new LeekCompilerException(mCompiler.getWord(), Error.KEYWORD_IN_EXPECTED); // On déclare notre bloc foreach et on entre dedans ForeachKeyBlock block = new ForeachKeyBlock(mCurentBlock, mMain, isDeclaration, isValueDeclaration, mLine, mAI, reference1, reference2); @@ -468,8 +469,8 @@ private void forBlock() throws LeekCompilerException { // On récupère la valeur de base du compteur AbstractExpression initValue = readExpression(); if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) { - // errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.ERROR, LeekCompilerException.END_OF_INSTRUCTION_EXPECTED)); - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + // errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.ERROR, Error.END_OF_INSTRUCTION_EXPECTED)); + throw new LeekCompilerException(mCompiler.lastWord(), Error.END_OF_INSTRUCTION_EXPECTED); // return; } // if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) { @@ -477,8 +478,8 @@ private void forBlock() throws LeekCompilerException { // } AbstractExpression condition = readExpression(); if (mCompiler.readWord().getType() != WordParser.T_END_INSTRUCTION) { - // errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.ERROR, LeekCompilerException.END_OF_INSTRUCTION_EXPECTED)); - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + // errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.ERROR, Error.END_OF_INSTRUCTION_EXPECTED)); + throw new LeekCompilerException(mCompiler.lastWord(), Error.END_OF_INSTRUCTION_EXPECTED); // return; } // if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) { @@ -490,7 +491,7 @@ private void forBlock() throws LeekCompilerException { // la gueule ! if (incrementation != null && (incrementation instanceof LeekVariable || (incrementation instanceof LeekExpression && ((LeekExpression) incrementation).getOperator() == -1))) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.UNCOMPLETE_EXPRESSION); + throw new LeekCompilerException(mCompiler.lastWord(), Error.UNCOMPLETE_EXPRESSION); } block.setInitialisation(varName, initValue, isDeclaration, block.hasGlobal(varName.getWord())); @@ -499,11 +500,11 @@ private void forBlock() throws LeekCompilerException { forBlock = block; } else - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.KEYWORD_UNEXPECTED); + throw new LeekCompilerException(mCompiler.getWord(), Error.KEYWORD_UNEXPECTED); // On vérifie la parenthèse fermante if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.CLOSING_PARENTHESIS_EXPECTED); } // On regarde s'il y a des accolades if (mCompiler.getWord().getType() == WordParser.T_ACCOLADE_LEFT) { @@ -514,11 +515,11 @@ private void forBlock() throws LeekCompilerException { private void whileBlock() throws LeekCompilerException { if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_PARENTHESIS_EXPECTED); } AbstractExpression exp = readExpression(); if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.CLOSING_PARENTHESIS_EXPECTED); } WhileBlock bloc = new WhileBlock(mCurentBlock, mMain, mLine, mAI); bloc.setCondition(exp); @@ -542,23 +543,23 @@ private void dowhileBlock() throws LeekCompilerException { private void dowhileendBlock(DoWhileBlock bloc) throws LeekCompilerException { if (!mCompiler.readWord().getWord().equals("while")) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.WHILE_EXPECTED_AFTER_DO); + throw new LeekCompilerException(mCompiler.lastWord(), Error.WHILE_EXPECTED_AFTER_DO); if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_PARENTHESIS_EXPECTED); } bloc.setCondition(readExpression()); if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.CLOSING_PARENTHESIS_EXPECTED); } // if (mCompiler.getWord().getType() != WordParser.T_END_INSTRUCTION) - // throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + // throw new LeekCompilerException(mCompiler.lastWord(), Error.END_OF_INSTRUCTION_EXPECTED); } private void elseBlock() throws LeekCompilerException { // On vérifie qu'on est bien associé à un bloc conditionnel ConditionalBloc last = mCurentBlock.getLastOpenedConditionalBlock(); if (last == null || last.getCondition() == null) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.NO_IF_BLOCK); + throw new LeekCompilerException(mCompiler.lastWord(), Error.NO_IF_BLOCK); } ConditionalBloc bloc = new ConditionalBloc(mCurentBlock, mMain, mLine, mAI); bloc.setParentCondition(last); @@ -566,11 +567,11 @@ private void elseBlock() throws LeekCompilerException { // On veut un elseif mCompiler.skipWord(); if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_PARENTHESIS_EXPECTED); } AbstractExpression exp = readExpression(); if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.CLOSING_PARENTHESIS_EXPECTED); } bloc.setCondition(exp); } @@ -585,11 +586,11 @@ private void elseBlock() throws LeekCompilerException { private void ifBlock() throws LeekCompilerException { if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_PARENTHESIS_EXPECTED); } AbstractExpression exp = readExpression(); if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.CLOSING_PARENTHESIS_EXPECTED); } ConditionalBloc bloc = new ConditionalBloc(mCurentBlock, mMain, mLine, mAI); bloc.setCondition(exp); @@ -605,9 +606,9 @@ private void globalDeclaration() throws LeekCompilerException { // Il y a au moins une premiere variable IAWord word = mCompiler.readWord(); if (!(mCurentBlock instanceof MainLeekBlock)) - throw new LeekCompilerException(word, LeekCompilerException.GLOBAL_ONLY_IN_MAIN_BLOCK); + throw new LeekCompilerException(word, Error.GLOBAL_ONLY_IN_MAIN_BLOCK); if (word.getType() != WordParser.T_STRING) - throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED_AFTER_GLOBAL); + throw new LeekCompilerException(word, Error.VAR_NAME_EXPECTED_AFTER_GLOBAL); LeekGlobalDeclarationInstruction variable = new LeekGlobalDeclarationInstruction(word, mLine, mAI); // On regarde si une valeur est assignée if (mCompiler.getWord().getWord().equals("=")) { @@ -623,7 +624,7 @@ private void globalDeclaration() throws LeekCompilerException { mCompiler.skipWord();// On passe la virgule word = mCompiler.readWord(); if (word.getType() != WordParser.T_STRING) - throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED); + throw new LeekCompilerException(word, Error.VAR_NAME_EXPECTED); variable = new LeekGlobalDeclarationInstruction(word, mLine, mAI); // On regarde si une valeur est assign�e if (mCompiler.getWord().getWord().equals("=")) { @@ -637,7 +638,7 @@ private void globalDeclaration() throws LeekCompilerException { } // word = mCompiler.readWord(); // if (word.getType() != WordParser.T_END_INSTRUCTION) - // throw new LeekCompilerException(word, LeekCompilerException.END_OF_INSTRUCTION_EXPECTED); + // throw new LeekCompilerException(word, Error.END_OF_INSTRUCTION_EXPECTED); if (mCompiler.haveWords() && mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) mCompiler.skipWord(); } @@ -646,9 +647,9 @@ private void variableDeclaration() throws LeekCompilerException { // Il y a au moins une premiere variable IAWord word = mCompiler.readWord(); if (word.getType() != WordParser.T_STRING) - throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED); + throw new LeekCompilerException(word, Error.VAR_NAME_EXPECTED); // if (!isAvailable(word.getWord(), true)) - // throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); + // throw new LeekCompilerException(word, Error.VARIABLE_NAME_UNAVAILABLE); LeekVariableDeclarationInstruction variable = new LeekVariableDeclarationInstruction(word, mLine, mAI); // On regarde si une valeur est assignée if (mCompiler.getWord().getWord().equals("=")) { @@ -666,9 +667,9 @@ private void variableDeclaration() throws LeekCompilerException { mCompiler.skipWord();// On passe la virgule word = mCompiler.readWord(); if (word.getType() != WordParser.T_STRING) - throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED); + throw new LeekCompilerException(word, Error.VAR_NAME_EXPECTED); // if (!isAvailable(word.getWord(), true)) - // throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); + // throw new LeekCompilerException(word, Error.VARIABLE_NAME_UNAVAILABLE); variable = new LeekVariableDeclarationInstruction(word, mLine, mAI); // On regarde si une valeur est assignée if (mCompiler.getWord().getWord().equals("=")) { @@ -688,10 +689,10 @@ public void classDeclaration() throws LeekCompilerException { // Read class name IAWord word = mCompiler.readWord(); if (word.getType() != WordParser.T_STRING) { - throw new LeekCompilerException(word, LeekCompilerException.VAR_NAME_EXPECTED); + throw new LeekCompilerException(word, Error.VAR_NAME_EXPECTED); } // if (!isAvailable(word.getWord(), true)) { - // throw new LeekCompilerException(word, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE); + // throw new LeekCompilerException(word, Error.VARIABLE_NAME_UNAVAILABLE); // } ClassDeclarationInstruction classDeclaration = new ClassDeclarationInstruction(word, mLine, mAI); mMain.addClass(classDeclaration); @@ -701,12 +702,12 @@ public void classDeclaration() throws LeekCompilerException { mCompiler.skipWord(); IAWord parent = mCompiler.readWord(); // if (!mMain.hasUserClass(parentName)) { - // throw new LeekCompilerException(word, LeekCompilerException.NO_SUCH_CLASS); + // throw new LeekCompilerException(word, Error.NO_SUCH_CLASS); // } classDeclaration.setParent(parent); } if (mCompiler.getWord().getType() != WordParser.T_ACCOLADE_LEFT) { - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.OPENING_CURLY_BRACKET_EXPECTED); + throw new LeekCompilerException(mCompiler.getWord(), Error.OPENING_CURLY_BRACKET_EXPECTED); } mCompiler.skipWord(); @@ -730,14 +731,14 @@ public void classDeclaration() throws LeekCompilerException { mCompiler.back(); classAccessLevelMember(classDeclaration, AccessLevel.PUBLIC); } else { - throw new LeekCompilerException(word, LeekCompilerException.KEYWORD_UNEXPECTED); + throw new LeekCompilerException(word, Error.KEYWORD_UNEXPECTED); } } } word = mCompiler.readWord(); } if (word.getType() != WordParser.T_ACCOLADE_RIGHT) { - throw new LeekCompilerException(word, LeekCompilerException.END_OF_CLASS_EXPECTED); + throw new LeekCompilerException(word, Error.END_OF_CLASS_EXPECTED); } mCurrentClass = null; // mMain.addInstruction(this, classDeclaration); @@ -803,16 +804,16 @@ public ClassMethodBlock classMethod(ClassDeclarationInstruction classDeclaration IAWord word = mCompiler.readWord(); if (word.getType() != WordParser.T_PAR_LEFT) { - throw new LeekCompilerException(word, LeekCompilerException.OPENING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(word, Error.OPENING_PARENTHESIS_EXPECTED); } int param_count = 0; while (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("@")) { - errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCES_DEPRECATED)); + errors.add(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, Error.REFERENCE_DEPRECATED)); mCompiler.skipWord(); } if (mCompiler.getWord().getType() != WordParser.T_STRING) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_EXPECTED); + throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_EXPECTED); method.addParameter(mCompiler.getWord()); mCompiler.skipWord(); param_count++; @@ -820,10 +821,10 @@ public ClassMethodBlock classMethod(ClassDeclarationInstruction classDeclaration mCompiler.skipWord(); } if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); + throw new LeekCompilerException(mCompiler.getWord(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); } if (classDeclaration.hasMethod(name, param_count)) { - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.CONSTRUCTOR_ALREADY_EXISTS); + throw new LeekCompilerException(mCompiler.getWord(), Error.CONSTRUCTOR_ALREADY_EXISTS); } // On enregistre les block actuels @@ -834,7 +835,7 @@ public ClassMethodBlock classMethod(ClassDeclarationInstruction classDeclaration // Ouverture des accolades if (mCompiler.readWord().getType() != WordParser.T_ACCOLADE_LEFT) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_CURLY_BRACKET_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_CURLY_BRACKET_EXPECTED); // Lecture du corps de la fonction while (mCompiler.haveWords()) { @@ -879,7 +880,7 @@ public AbstractExpression readExpression() throws LeekCompilerException { AbstractExpression exp = readExpression(); if (mCompiler.getWord().getType() != WordParser.T_BRACKET_RIGHT) { - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.CLOSING_SQUARE_BRACKET_EXPECTED); + throw new LeekCompilerException(mCompiler.getWord(), Error.CLOSING_SQUARE_BRACKET_EXPECTED); } retour.addBracket(exp); } else if (word.getType() == WordParser.T_PAR_LEFT) { @@ -893,7 +894,7 @@ public AbstractExpression readExpression() throws LeekCompilerException { mCompiler.skipWord(); } if (mCompiler.haveWords() && mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); + throw new LeekCompilerException(mCompiler.getWord(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); } retour.addFunction(function); } else if (word.getType() == WordParser.T_DOT) { @@ -948,7 +949,7 @@ else if (word.getType() == WordParser.T_VAR_STRING) { if (type == 0) type = 2; else if (type == 1) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.SIMPLE_ARRAY); + throw new LeekCompilerException(mCompiler.getWord(), Error.SIMPLE_ARRAY); mCompiler.skipWord(); AbstractExpression value = readExpression(); array.addValue(exp, value); @@ -956,14 +957,14 @@ else if (type == 1) if (type == 0) type = 1; else if (type == 2) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.ASSOCIATIVE_ARRAY); + throw new LeekCompilerException(mCompiler.getWord(), Error.ASSOCIATIVE_ARRAY); array.addValue(exp); } if (mCompiler.getWord().getType() == WordParser.T_VIRG) mCompiler.skipWord(); } if (mCompiler.getWord().getType() != WordParser.T_BRACKET_RIGHT) { - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); + throw new LeekCompilerException(mCompiler.getWord(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); } retour.addExpression(array); } else if (word.getType() == WordParser.T_STRING) { @@ -984,15 +985,15 @@ else if (getVersion() >= 11 && word.getWord().equalsIgnoreCase("new")) { } else if (word.getWord().equals("super")) { // super doit être dans une méthode if (!(mCurentBlock instanceof ClassMethodBlock)) { - errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.KEYWORD_MUST_BE_IN_CLASS)); + errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.KEYWORD_MUST_BE_IN_CLASS)); } if (mCurentBlock instanceof ClassMethodBlock && ((ClassMethodBlock) mCurentBlock).getClassDeclaration().getParentToken() == null) { - errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.SUPER_NOT_AVAILABLE_PARENT)); + errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.SUPER_NOT_AVAILABLE_PARENT)); } retour.addExpression(new LeekVariable(word, VariableType.SUPER, ((ClassMethodBlock) mCurentBlock).getClassDeclaration())); } else { retour.addExpression(new LeekVariable(word, VariableType.LOCAL)); - // throw new LeekCompilerException(word, LeekCompilerException.UNKNOWN_VARIABLE_OR_FUNCTION); + // throw new LeekCompilerException(word, Error.UNKNOWN_VARIABLE_OR_FUNCTION); } } else if (word.getType() == WordParser.T_PAR_LEFT) { mCompiler.skipWord();// On avance le curseur pour bien être @@ -1000,7 +1001,7 @@ else if (getVersion() >= 11 && word.getWord().equalsIgnoreCase("new")) { AbstractExpression exp = readExpression(); if (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.CLOSING_PARENTHESIS_EXPECTED); + throw new LeekCompilerException(mCompiler.getWord(), Error.CLOSING_PARENTHESIS_EXPECTED); } retour.addExpression(new LeekParenthesis(exp)); } else if (word.getType() == WordParser.T_OPERATOR) { @@ -1018,12 +1019,12 @@ else if (operator == Operators.INCREMENT) // Si oui on l'ajoute retour.addUnaryPrefix(operator, word); } else { - errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.OPERATOR_UNEXPECTED)); - // throw new LeekCompilerException(word, LeekCompilerException.OPERATOR_UNEXPECTED); + errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.OPERATOR_UNEXPECTED)); + // throw new LeekCompilerException(word, Error.OPERATOR_UNEXPECTED); } } else { - errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.VALUE_EXPECTED)); - // throw new LeekCompilerException(word, LeekCompilerException.VALUE_EXPECTED); + errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.VALUE_EXPECTED)); + // throw new LeekCompilerException(word, Error.VALUE_EXPECTED); } } mCompiler.skipWord(); @@ -1041,12 +1042,12 @@ else if (operator == Operators.INCREMENT) } } if (result == null) { - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.UNCOMPLETE_EXPRESSION); + throw new LeekCompilerException(mCompiler.lastWord(), Error.UNCOMPLETE_EXPRESSION); } try { result.validExpression(this, mMain); } catch (LeekExpressionException e) { - throw new LeekCompilerException(mCompiler.lastWord(), e.getMessage(), new String[] { e.getExpression() }); + throw new LeekCompilerException(mCompiler.lastWord(), e.getError(), new String[] { e.getExpression() }); } return result; } @@ -1054,7 +1055,7 @@ else if (operator == Operators.INCREMENT) private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerException { mCompiler.skipWord(); if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_FUNCTION); + throw new LeekCompilerException(mCompiler.getWord(), Error.PARENTHESIS_EXPECTED_AFTER_FUNCTION); } // On enregistre les block actuels AbstractLeekBlock initialBlock = mCurentBlock; @@ -1071,25 +1072,25 @@ private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerExcepti if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("@")) { is_reference = true; if (getVersion() >= 11) { - addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCES_DEPRECATED)); + addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, Error.REFERENCE_DEPRECATED)); } mCompiler.skipWord(); } if (mCompiler.getWord().getType() != WordParser.T_STRING) - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_EXPECTED); + throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_EXPECTED); // if (!isAvailable(mCompiler.getWord().getWord(), true)) - // throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARAMETER_NAME_UNAVAILABLE); + // throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_UNAVAILABLE); block.addParameter(mCompiler.readWord(), is_reference); if (mCompiler.getWord().getType() == WordParser.T_VIRG) mCompiler.skipWord(); } if (mCompiler.readWord().getType() != WordParser.T_PAR_RIGHT) { - throw new LeekCompilerException(mCompiler.getWord(), LeekCompilerException.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); + throw new LeekCompilerException(mCompiler.getWord(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); } // Ouverture des accolades if (mCompiler.readWord().getType() != WordParser.T_ACCOLADE_LEFT) - throw new LeekCompilerException(mCompiler.lastWord(), LeekCompilerException.OPENING_CURLY_BRACKET_EXPECTED); + throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_CURLY_BRACKET_EXPECTED); // Lecture du corp de la fonction while (mCompiler.haveWords()) { diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index 7b2208c3..1023cfdb 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -4,6 +4,7 @@ import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.exceptions.LeekCompilerException; +import leekscript.common.Error; public class WordParser { /** @@ -147,7 +148,7 @@ else if(type == T_STRING || type == T_VAR_STRING){ type = T_STRING; } else if(type == T_NUMBER){ - throw new LeekCompilerException(mAI, line_counter, char_counter, word, LeekCompilerException.INVALID_NUMBER); + throw new LeekCompilerException(mAI, line_counter, char_counter, word, Error.INVALID_NUMBER); } } } @@ -183,8 +184,8 @@ else if (version >= 11) { word = ""; type = T_NOTHING; } else { - compiler.addError(new AnalyzeError(new IAWord(mAI, 0, ".", line_counter, char_counter + 1), AnalyzeErrorLevel.ERROR, LeekCompilerException.INVALID_CHAR)); - // throw new LeekCompilerException(mAI, line_counter, char_counter + 1, ".", LeekCompilerException.INVALID_CHAR); + compiler.addError(new AnalyzeError(new IAWord(mAI, 0, ".", line_counter, char_counter + 1), AnalyzeErrorLevel.ERROR, Error.INVALID_CHAR)); + // throw new LeekCompilerException(mAI, line_counter, char_counter + 1, ".", Error.INVALID_CHAR); } } else if(c == '@' || c == '+' || c == '=' || c == '<' || c == '>' || c == '|' || c == '&' || c == '-' || c == '/' || c == '*' || c == '%' || c == '!' || c == '?' || c == '^' || c == '~' || c == '.'){ @@ -340,7 +341,7 @@ else if(c == ','){ word += c; } else{ - throw new LeekCompilerException(mAI, line_counter, char_counter, "" + c, LeekCompilerException.INVALID_CHAR); + throw new LeekCompilerException(mAI, line_counter, char_counter, "" + c, Error.INVALID_CHAR); } } } diff --git a/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java b/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java index 054f88c1..21ce3c83 100644 --- a/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java @@ -10,6 +10,7 @@ import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.instruction.LeekInstruction; +import leekscript.common.Error; public abstract class AbstractLeekBlock implements LeekInstruction { @@ -61,7 +62,7 @@ public AbstractLeekBlock(AbstractLeekBlock parent, MainLeekBlock main, int line, public void addInstruction(WordCompiler compiler, LeekInstruction instruction) throws LeekCompilerException { if (mEndInstruction != 0) { - throw new LeekCompilerException(compiler.getParser().lastWord(), LeekCompilerException.CANT_ADD_INSTRUCTION_AFTER_BREAK); + throw new LeekCompilerException(compiler.getParser().lastWord(), Error.CANT_ADD_INSTRUCTION_AFTER_BREAK); } mEndInstruction = instruction.getEndBlock(); mInstructions.add(instruction); diff --git a/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java b/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java index 287951c5..8f8cfefa 100644 --- a/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java +++ b/src/main/java/leekscript/compiler/exceptions/LeekCompilerException.java @@ -2,109 +2,45 @@ import leekscript.compiler.AIFile; import leekscript.compiler.IAWord; +import leekscript.common.Error; public class LeekCompilerException extends Exception { - public final static String FUNCTION_NAME_UNAVAILABLE = "function_name_unavailable"; - public final static String PARAMETER_NAME_UNAVAILABLE = "parameter_name_unavailable"; - public final static String OPENING_PARENTHESIS_EXPECTED = "opening_parenthesis_expected"; - public final static String OPENING_CURLY_BRACKET_EXPECTED = "opening_curly_bracket_expected"; - public final static String PARAMETER_NAME_EXPECTED = "parameter_name_expected"; - public final static String FUNCTION_NAME_EXPECTED = "function_name_expected"; - public final static String PARENTHESIS_EXPECTED_AFTER_PARAMETERS = "parenthesis_expected_after_parameters"; - public final static String OPEN_BLOC_REMAINING = "open_bloc_remaining"; - public final static String NO_BLOC_TO_CLOSE = "no_bloc_to_close"; - public final static String END_OF_SCRIPT_UNEXPECTED = "end_of_script_unexpected"; - public final static String END_OF_INSTRUCTION_EXPECTED = "end_of_instruction_expected"; - public final static String BREAK_OUT_OF_LOOP = "break_out_of_loop"; - public final static String CONTINUE_OUT_OF_LOOP = "continue_out_of_loop"; - public final static String INCLUDE_ONLY_IN_MAIN_BLOCK = "include_only_in_main_block"; - public final static String AI_NAME_EXPECTED = "ai_name_expected"; - public final static String AI_NOT_EXISTING = "ai_not_existing"; - public final static String CLOSING_PARENTHESIS_EXPECTED = "closing_parenthesis_expected"; - public final static String CLOSING_SQUARE_BRACKET_EXPECTED = "closing_square_bracket_expected"; - public final static String FUNCTION_ONLY_IN_MAIN_BLOCK = "function_only_in_main_block"; - public final static String VARIABLE_NAME_EXPECTED = "variable_name_expected"; - public final static String VARIABLE_NAME_UNAVAILABLE = "variable_name_unavailable"; - public final static String VARIABLE_NOT_EXISTS = "variable_not_exists"; - public final static String KEYWORD_UNEXPECTED = "keyword_unexpected"; - public final static String KEYWORD_IN_EXPECTED = "keyword_in_expected"; - public final static String WHILE_EXPECTED_AFTER_DO = "while_expected_after_do"; - public final static String NO_IF_BLOCK = "no_if_block"; - public final static String GLOBAL_ONLY_IN_MAIN_BLOCK = "global_only_in_main_block"; - public final static String VAR_NAME_EXPECTED_AFTER_GLOBAL = "var_name_expected_after_global"; - public final static String VAR_NAME_EXPECTED = "var_name_expected"; - public final static String SIMPLE_ARRAY = "simple_array"; - public final static String ASSOCIATIVE_ARRAY = "associative_array"; - public final static String PARENTHESIS_EXPECTED_AFTER_FUNCTION = "parenthesis_expected_after_function"; - public final static String UNKNOWN_VARIABLE_OR_FUNCTION = "unknown_variable_or_function"; - public final static String OPERATOR_UNEXPECTED = "operator_unexpected"; - public final static String VALUE_EXPECTED = "value_expected"; - public final static String CANT_ADD_INSTRUCTION_AFTER_BREAK = "cant_add_instruction_after_break"; - public final static String UNCOMPLETE_EXPRESSION = "uncomplete_expression"; - public final static String CANT_ASSIGN_VALUE = "cant_assign_value"; - public final static String FUNCTION_NOT_EXISTS = "function_not_exists"; - public final static String INVALID_PAREMETER_COUNT = "invalid_parameter_count"; - public final static String INVALID_CHAR = "invalid_char"; - public final static String INVALID_NUMBER = "invalid_number"; - public final static String CONSTRUCTOR_ALREADY_EXISTS = "constructor_already_exists"; - public final static String END_OF_CLASS_EXPECTED = "end_of_class_expected"; - public final static String FIELD_ALREADY_EXISTS = "field_already_exists"; - public final static String NO_SUCH_CLASS = "no_such_class"; - public final static String THIS_NOT_ALLOWED_HERE = "this_not_allowed_here"; - public final static String REFERENCE_IGNORED_IN_METHODS = "reference_ignored_in_methods"; - public final static String KEYWORD_MUST_BE_IN_CLASS = "keyword_must_be_in_class"; - public final static String SUPER_NOT_AVAILABLE_PARENT = "super_not_available_parent"; - public final static String CLASS_MEMBER_DOES_NOT_EXIST = "class_member_does_not_exist"; - public final static String CLASS_STATIC_MEMBER_DOES_NOT_EXIST = "class_static_member_does_not_exist"; - public final static String EXTENDS_LOOP = "extends_loop"; - public final static String REFERENCES_DEPRECATED = "reference_deprecated"; - public final static String DUPLICATED_METHOD = "duplicated_method"; - public final static String UNKNOWN_CONSTRUCTOR = "unknown_constructor"; - public final static String UNKNOWN_STATIC_METHOD = "unknown_static_method"; - /** * */ private static final long serialVersionUID = 1L; + int mLine; int mChar; String mWord; - String mType; + Error mError; AIFile mIA; private String[] mParameters = null; - public LeekCompilerException(IAWord word) { - mLine = word.getLine(); - mChar = word.getCharacter(); - mWord = word.getWord(); - mIA = word.getAI(); - mType = ""; - } - - public LeekCompilerException(IAWord word, String informations) { + public LeekCompilerException(IAWord word, Error error) { mLine = word.getLine(); mChar = word.getCharacter(); mWord = word.getWord(); mIA = word.getAI(); - mType = informations; + mError = error; } - public LeekCompilerException(IAWord word, String informations, String[] parameters) { + public LeekCompilerException(IAWord word, Error error, String[] parameters) { mLine = word.getLine(); mChar = word.getCharacter(); mWord = word.getWord(); mIA = word.getAI(); - mType = informations; + mError = error; mParameters = parameters; } - public LeekCompilerException(AIFile ai, int line, int char_pos, String word, String informations) { + public LeekCompilerException(AIFile ai, int line, int char_pos, String word, Error error) { mLine = line; mChar = char_pos; mWord = word; mIA = ai; - mType = informations; + mError = error; } public String[] getParameters() { @@ -125,11 +61,11 @@ public int getChar() { @Override public String getMessage() { - return mIA.getPath() + ":" + mLine + " : " + mWord + " : " + mType; + return mIA.getPath() + ":" + mLine + " : " + mWord + " : " + mError.name(); } - public String getError() { - return mType; + public Error getError() { + return mError; } public AIFile getIA() { diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index 9fd08019..c2b190a9 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -6,8 +6,8 @@ import leekscript.compiler.WordCompiler; import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.MainLeekBlock; -import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.common.Error; public class LeekExpression extends AbstractExpression { @@ -417,7 +417,7 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t // if (mExpression2 instanceof LeekExpression) // mExpression2 = ((LeekExpression) mExpression2).getAbstractExpression(); if (mExpression1 == null || mExpression2 == null || mOperator == -1) - throw new LeekExpressionException(this, LeekCompilerException.UNCOMPLETE_EXPRESSION); + throw new LeekExpressionException(this, Error.UNCOMPLETE_EXPRESSION); return mExpression1.validExpression(compiler, mainblock) && mExpression2.validExpression(compiler, mainblock); } @@ -735,7 +735,7 @@ public boolean isLeftValue() { public void analyze(WordCompiler compiler) { if (mOperator == Operators.REFERENCE && compiler.getVersion() >= 11) { - compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.WARNING, LeekCompilerException.REFERENCES_DEPRECATED)); + compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.WARNING, Error.REFERENCE_DEPRECATED)); } if (mExpression1 != null) mExpression1.analyze(compiler); @@ -745,7 +745,7 @@ public void analyze(WordCompiler compiler) { // on doit vérifier qu'on a bien une variable (l-value) if (mOperator == Operators.ADDASSIGN || mOperator == Operators.MINUSASSIGN || mOperator == Operators.DIVIDEASSIGN || mOperator == Operators.ASSIGN || mOperator == Operators.MODULUSASSIGN || mOperator == Operators.MULTIPLIEASSIGN || mOperator == Operators.POWERASSIGN) { if (!mExpression1.isLeftValue()) - compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.CANT_ASSIGN_VALUE)); + compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, Error.CANT_ASSIGN_VALUE)); // throw new LeekExpressionException(mExpression1, LeekCompilerException.CANT_ASSIGN_VALUE); if (mExpression1 instanceof LeekVariable) { var v = (LeekVariable) mExpression1; @@ -759,7 +759,7 @@ public void analyze(WordCompiler compiler) { if (mOperator == Operators.INCREMENT || mOperator == Operators.DECREMENT || mOperator == Operators.PRE_INCREMENT || mOperator == Operators.PRE_DECREMENT) { if (!mExpression2.isLeftValue()) - compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.CANT_ASSIGN_VALUE)); + compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, Error.CANT_ASSIGN_VALUE)); // throw new LeekExpressionException(mExpression2, LeekCompilerException.CANT_ASSIGN_VALUE); if (mExpression2 instanceof LeekVariable) { var v = (LeekVariable) mExpression2; diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionException.java b/src/main/java/leekscript/compiler/expression/LeekExpressionException.java index e07a68fb..1cbd02f0 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionException.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionException.java @@ -1,25 +1,31 @@ package leekscript.compiler.expression; +import leekscript.common.Error; + public class LeekExpressionException extends Exception { /** - * + * */ private static final long serialVersionUID = 5724420043991763088L; private final AbstractExpression mExpression; - private final String mMessage; + private final Error mError; - public LeekExpressionException(AbstractExpression exp, String message) { + public LeekExpressionException(AbstractExpression exp, Error error) { mExpression = exp; - mMessage = message; + mError = error; } @Override public String getMessage() { - return mMessage; + return mError.name(); } public String getExpression() { return mExpression.getString(); } + + public Error getError() { + return mError; + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 6d353183..197a7c37 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -2,8 +2,6 @@ import java.util.ArrayList; -import org.graalvm.compiler.word.ObjectAccess; - import leekscript.compiler.AnalyzeError; import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; @@ -11,11 +9,10 @@ import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.FunctionBlock; import leekscript.compiler.bloc.MainLeekBlock; -import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.expression.LeekVariable.VariableType; -import leekscript.compiler.instruction.ClassDeclarationInstruction; import leekscript.runner.ILeekFunction; import leekscript.runner.LeekFunctions; +import leekscript.common.Error; public class LeekExpressionFunction extends AbstractExpression { @@ -154,19 +151,19 @@ public void analyze(WordCompiler compiler) { if (nb_params == -1) { nb_params = compiler.getMainBlock().getUserFunctionParametersCount(v.getName()); if (mParameters.size() != nb_params) { - compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, LeekCompilerException.INVALID_PAREMETER_COUNT)); + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.INVALID_PARAMETER_COUNT)); } } else { var f = LeekFunctions.getValue(v.getName()); if (mParameters.size() > nb_params || mParameters.size() < f.getArgumentsMin()) - compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, LeekCompilerException.INVALID_PAREMETER_COUNT)); + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.INVALID_PARAMETER_COUNT)); } } else if (v.getVariableType() == VariableType.CLASS) { System.out.println("Class " + v); var clazz = v.getClassDeclaration(); if (mParameters.size() != 0 && !clazz.hasConstructor(mParameters.size())) { - compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, LeekCompilerException.UNKNOWN_CONSTRUCTOR, new String[] { clazz.getName() })); + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.UNKNOWN_CONSTRUCTOR, new String[] { clazz.getName() })); } } } else if (mExpression instanceof LeekObjectAccess) { @@ -178,7 +175,7 @@ public void analyze(WordCompiler compiler) { if (v.getVariableType() == VariableType.CLASS) { var clazz = v.getClassDeclaration(); if (!clazz.hasStaticMethod(oa.getField(), mParameters.size())) { - compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, LeekCompilerException.UNKNOWN_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); + compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.UNKNOWN_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); } } } diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index aa5f3cce..02abfc9c 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -6,8 +6,8 @@ import leekscript.compiler.WordCompiler; import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.MainLeekBlock; -import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.common.Error; public class LeekObjectAccess extends AbstractExpression { @@ -59,11 +59,11 @@ public void analyze(WordCompiler compiler) { // this, check field exists in class var clazz = compiler.getCurrentClass(); if (clazz != null && !clazz.hasMember(field.getWord())) { - compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, LeekCompilerException.CLASS_MEMBER_DOES_NOT_EXIST, new String[] { clazz.getName(), field.getWord() })); + compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, Error.CLASS_MEMBER_DOES_NOT_EXIST, new String[] { clazz.getName(), field.getWord() })); } } else if (v.getVariableType() == VariableType.CLASS && v.getClassDeclaration() != null) { if (!v.getClassDeclaration().hasStaticMember(field.getWord())) { - compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, LeekCompilerException.CLASS_STATIC_MEMBER_DOES_NOT_EXIST, new String[] { v.getClassDeclaration().getName(), field.getWord() })); + compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, Error.CLASS_STATIC_MEMBER_DOES_NOT_EXIST, new String[] { v.getClassDeclaration().getName(), field.getWord() })); } } } diff --git a/src/main/java/leekscript/compiler/expression/LeekTernaire.java b/src/main/java/leekscript/compiler/expression/LeekTernaire.java index 76383b63..28fce1ca 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTernaire.java +++ b/src/main/java/leekscript/compiler/expression/LeekTernaire.java @@ -4,7 +4,7 @@ import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; -import leekscript.compiler.exceptions.LeekCompilerException; +import leekscript.common.Error; public class LeekTernaire extends LeekExpression { @@ -81,8 +81,8 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { @Override public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { - if(!complete()) throw new LeekExpressionException(this, LeekCompilerException.UNCOMPLETE_EXPRESSION); - if(!(mCondition.validExpression(compiler, mainblock) && mExpression1.validExpression(compiler, mainblock) && mExpression2.validExpression(compiler, mainblock))) throw new LeekExpressionException(this, LeekCompilerException.UNCOMPLETE_EXPRESSION); + if(!complete()) throw new LeekExpressionException(this, Error.UNCOMPLETE_EXPRESSION); + if(!(mCondition.validExpression(compiler, mainblock) && mExpression1.validExpression(compiler, mainblock) && mExpression2.validExpression(compiler, mainblock))) throw new LeekExpressionException(this, Error.UNCOMPLETE_EXPRESSION); return true; } diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index 867328ef..24419d20 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -7,10 +7,10 @@ import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.FunctionBlock; import leekscript.compiler.bloc.MainLeekBlock; -import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.instruction.ClassDeclarationInstruction; import leekscript.runner.LeekConstants; import leekscript.runner.LeekFunctions; +import leekscript.common.Error; public class LeekVariable extends AbstractExpression { @@ -128,7 +128,7 @@ public void analyze(WordCompiler compiler) { this.type = VariableType.SYSTEM_FUNCTION; return; } - compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.UNKNOWN_VARIABLE_OR_FUNCTION)); + compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, Error.UNKNOWN_VARIABLE_OR_FUNCTION)); } public ClassDeclarationInstruction getClassDeclaration() { diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index ca969c29..286f0d15 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -15,6 +15,7 @@ import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.common.Error; public class ClassDeclarationInstruction implements LeekInstruction { @@ -89,7 +90,7 @@ public void addConstructor(ClassMethodBlock block) { public void addMethod(WordCompiler compiler, IAWord token, ClassMethodBlock method) { // On regarde si il n'y a pas déjà une méthode statique du même nom if (staticMethods.containsKey(token.getWord())) { - compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.DUPLICATED_METHOD)); + compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, Error.DUPLICATED_METHOD)); } if (!methods.containsKey(token.getWord())) { methods.put(token.getWord(), new HashMap<>()); @@ -108,7 +109,7 @@ public boolean hasMethod(String name, int paramCount) { public void addStaticMethod(WordCompiler compiler, IAWord token, ClassMethodBlock method) { // On regarde si il n'y a pas déjà une méthode du même nom if (methods.containsKey(token.getWord())) { - compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.DUPLICATED_METHOD)); + compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, Error.DUPLICATED_METHOD)); } if (!staticMethods.containsKey(token.getWord())) { staticMethods.put(token.getWord(), new HashMap<>()); @@ -123,7 +124,7 @@ public boolean hasStaticMethod(String name, int paramCount) { public void addField(WordCompiler compiler, IAWord word, AbstractExpression expr) throws LeekCompilerException { if (fields.containsKey(word.getWord()) || staticFields.containsKey(word.getWord())) { - compiler.addError(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, LeekCompilerException.FIELD_ALREADY_EXISTS)); + compiler.addError(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.FIELD_ALREADY_EXISTS)); return; } fields.put(word.getWord(), expr); @@ -132,7 +133,7 @@ public void addField(WordCompiler compiler, IAWord word, AbstractExpression expr public void addStaticField(IAWord word, AbstractExpression expr) throws LeekCompilerException { if (staticFields.containsKey(word.getWord()) || fields.containsKey(word.getWord())) { - throw new LeekCompilerException(word, LeekCompilerException.FIELD_ALREADY_EXISTS); + throw new LeekCompilerException(word, Error.FIELD_ALREADY_EXISTS); } staticFields.put(word.getWord(), expr); staticFieldVariables.put(word.getWord(), new LeekVariable(word, VariableType.STATIC_FIELD)); @@ -149,15 +150,15 @@ public void analyze(WordCompiler compiler) { if (parentToken != null) { var parentVar = compiler.getCurrentBlock().getVariable(this.parentToken.getWord(), true); if (parentVar == null) { - compiler.addError(new AnalyzeError(parentToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.UNKNOWN_VARIABLE_OR_FUNCTION)); + compiler.addError(new AnalyzeError(parentToken, AnalyzeErrorLevel.ERROR, Error.UNKNOWN_VARIABLE_OR_FUNCTION)); } else if (parentVar.getVariableType() != VariableType.CLASS) { - compiler.addError(new AnalyzeError(parentToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.UNKNOWN_VARIABLE_OR_FUNCTION)); + compiler.addError(new AnalyzeError(parentToken, AnalyzeErrorLevel.ERROR, Error.UNKNOWN_VARIABLE_OR_FUNCTION)); } else { var current = parentVar.getClassDeclaration(); boolean ok = true; while (current != null) { if (current == this) { - compiler.addError(new AnalyzeError(parentToken, AnalyzeErrorLevel.ERROR, LeekCompilerException.EXTENDS_LOOP)); + compiler.addError(new AnalyzeError(parentToken, AnalyzeErrorLevel.ERROR, Error.EXTENDS_LOOP)); ok = false; break; } diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index 812d33c2..7b38e42d 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -7,10 +7,10 @@ import leekscript.compiler.WordCompiler; import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.MainLeekBlock; -import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.common.Error; public class LeekVariableDeclarationInstruction implements LeekInstruction { @@ -81,11 +81,11 @@ public void analyze(WordCompiler compiler) { } // Variables interdites if (compiler.getVersion() >= 11 && token.getWord().equals("this")) { - compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.THIS_NOT_ALLOWED_HERE)); + compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, Error.THIS_NOT_ALLOWED_HERE)); } else { // Vérification déjà existante (on vérifie les globales et fonctions seulement en 1.1 car il y a un léger bug en 1.0 avec les includes) if ((compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(token.getWord()) || compiler.getMainBlock().hasUserFunction(token.getWord(), true))) || compiler.getCurrentBlock().hasVariable(token.getWord())) { - compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, LeekCompilerException.VARIABLE_NAME_UNAVAILABLE)); + compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); } else { // On ajoute la variable compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.LOCAL)); diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index bcd3b75a..66ff2316 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -10,6 +10,7 @@ import leekscript.runner.values.StringLeekValue; import leekscript.runner.values.VariableLeekValue; import leekscript.runner.values.ArrayLeekValue.ArrayIterator; +import leekscript.common.Error; import java.util.Comparator; import java.util.Iterator; @@ -354,11 +355,19 @@ public AbstractLeekValue jsonDecode(String json) { } } - public void addSystemLog(int type, String key) throws LeekRunException { - addSystemLog(type, key, null); + public void addSystemLog(int type, Error error) throws LeekRunException { + addSystemLog(type, error.ordinal(), null); } - public void addSystemLog(int type, String key, String[] parameters) throws LeekRunException { + public void addSystemLog(int type, int error) throws LeekRunException { + addSystemLog(type, error, null); + } + + public void addSystemLog(int type, Error error, String[] parameters) throws LeekRunException { + addSystemLog(type, error.ordinal(), parameters); + } + + public void addSystemLog(int type, int error, String[] parameters) throws LeekRunException { addOperations(AI.ERROR_LOG_COST); if (type == AILog.WARNING) type = AILog.SWARNING; @@ -367,7 +376,7 @@ else if (type == AILog.ERROR) else if (type == AILog.STANDARD) type = AILog.SSTANDARD; - logs.addSystemLog(type, getErrorMessage(Thread.currentThread().getStackTrace()), key, parameters); + logs.addSystemLog(type, getErrorMessage(Thread.currentThread().getStackTrace()), error, parameters); } protected abstract String[] getErrorString(); diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 619ffd57..a02409b8 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -13,6 +13,7 @@ import leekscript.runner.values.IntLeekValue; import leekscript.runner.values.NullLeekValue; import leekscript.runner.values.StringLeekValue; +import leekscript.common.Error; public enum LeekFunctions implements ILeekFunction { // Fonctions mathématiques @@ -1216,7 +1217,7 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu color(3) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - leekIA.addSystemLog(AILog.WARNING, AILog.DEPRECATED_FUNCTION, new String[] { "color", "getColor" }); + leekIA.addSystemLog(AILog.WARNING, Error.DEPRECATED_FUNCTION, new String[] { "color", "getColor" }); return leekIA.color(parameters[0], parameters[1], parameters[2]); } }, @@ -1436,7 +1437,7 @@ public static AbstractLeekValue executeFunction(AI leekIA, ILeekFunction functio } else { // Message d'erreur String ret = AbstractLeekValue.getParamString(parameters); - leekIA.addSystemLog(AILog.ERROR, AILog.UNKNOWN_FUNCTION, new String[] { function + "(" + ret + ")" }); + leekIA.addSystemLog(AILog.ERROR, Error.UNKNOWN_FUNCTION, new String[] { function + "(" + ret + ")" }); return LeekValueManager.NULL; } // throw new LeekRunException(LeekRunException.UNKNOWN_FUNCTION); diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index ce305582..33299374 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -11,6 +11,7 @@ import leekscript.runner.values.IntLeekValue; import leekscript.runner.values.ObjectLeekValue; import leekscript.runner.values.StringLeekValue; +import leekscript.common.Error; public class LeekOperations { @@ -117,7 +118,7 @@ public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeek v2 = v2.getValue(); if (v1.isNumeric() && v2.isNumeric()) { if (v2.getDouble(ai) == 0) { - ai.addSystemLog(AILog.ERROR, AILog.DIVISION_BY_ZERO); + ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); return LeekValueManager.NULL; } if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { @@ -139,7 +140,7 @@ public static AbstractLeekValue modulus(AI ai, AbstractLeekValue v1, AbstractLee v2 = v2.getValue(); if (v1.isNumeric() && v2.isNumeric()) { if (v2.getDouble(ai) == 0) { - ai.addSystemLog(AILog.ERROR, AILog.DIVISION_BY_ZERO); + ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); return LeekValueManager.NULL; } if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 6919131f..01c2238e 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -7,6 +7,7 @@ import leekscript.runner.AI; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; +import leekscript.common.Error; public abstract class AbstractLeekValue { @@ -62,7 +63,7 @@ public boolean isArray() { public boolean isArrayForIteration(AI ai) throws LeekRunException { // Pas itérable - ai.addSystemLog(AILog.ERROR, AILog.NOT_ITERABLE, new String[] { getString(ai) }); + ai.addSystemLog(AILog.ERROR, Error.NOT_ITERABLE, new String[] { getString(ai) }); return false; } @@ -207,7 +208,7 @@ public AbstractLeekValue instanceOf(AI ai, AbstractLeekValue value) throws LeekR ai.addOperations(2); var clazz = value.getValue(); if (!(clazz instanceof ClassLeekValue)) { - ai.addSystemLog(AILog.ERROR, AILog.INSTANCEOF_MUST_BE_CLASS); + ai.addSystemLog(AILog.ERROR, Error.INSTANCEOF_MUST_BE_CLASS); return LeekValueManager.getLeekBooleanValue(false); } var v = getValue(); @@ -219,23 +220,19 @@ public AbstractLeekValue instanceOf(AI ai, AbstractLeekValue value) throws LeekR public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { // Aucun champ - ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_FIELD, new String[] { getString(ai), field }); + ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { getString(ai), field }); return LeekValueManager.NULL; } public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { // Aucune méthode - ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_METHOD, new String[] { getString(ai), method }); + ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { getString(ai), method }); return LeekValueManager.NULL; } public AbstractLeekValue callSuperMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { // Aucune méthode - ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_METHOD, new String[] { getString(ai), method }); - return LeekValueManager.NULL; - } - - public AbstractLeekValue callSuperMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { getString(ai), method }); return LeekValueManager.NULL; } @@ -251,7 +248,7 @@ public boolean isReference() { public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... value) throws LeekRunException { // On ne peux pas exécuter ce type de variable - ai.addSystemLog(AILog.ERROR, AILog.CAN_NOT_EXECUTE_VALUE, new String[] { getString(ai) }); + ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_VALUE, new String[] { getString(ai) }); return LeekValueManager.NULL; } diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 402a9a39..655120c5 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -8,6 +8,7 @@ import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; import leekscript.runner.LeekAnonymousFunction; +import leekscript.common.Error; public class ClassLeekValue extends AbstractLeekValue { @@ -57,7 +58,7 @@ public AbstractLeekValue run(AI ai, AbstractLeekValue thiz, AbstractLeekValue... if (m != null) { return m.run(ai, thiz, arguments); } - ai.addSystemLog(leekscript.AILog.ERROR, leekscript.AILog.UNKNOWN_METHOD, new String[] { name, createMethodError(methodCode) }); + ai.addSystemLog(leekscript.AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { name, createMethodError(methodCode) }); return LeekValueManager.NULL; } })); @@ -75,7 +76,7 @@ public AbstractLeekValue run(AI ai, AbstractLeekValue thiz, AbstractLeekValue... if (m != null) { return m.run(ai, null, arguments); } - ai.addSystemLog(leekscript.AILog.ERROR, leekscript.AILog.UNKNOWN_METHOD, new String[] { name, createMethodError(methodCode) }); + ai.addSystemLog(leekscript.AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { name, createMethodError(methodCode) }); return LeekValueManager.NULL; } })); @@ -107,7 +108,7 @@ public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... a ai.addOperations(1); LeekAnonymousFunction result = staticMethods.get(method); if (result == null) { - ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_STATIC_METHOD, new String[] { name, createMethodError(method) }); + ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_STATIC_METHOD, new String[] { name, createMethodError(method) }); return LeekValueManager.NULL; } // Call method with new arguments, add the object at the beginning @@ -117,7 +118,7 @@ public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... a public void callConstructor(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException { ai.addOperations(1); if (!constructors.containsKey(arguments.length)) { - ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_CONSTRUCTOR, new String[] { name, String.valueOf(arguments.length) }); + ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_CONSTRUCTOR, new String[] { name, String.valueOf(arguments.length) }); return; } constructors.get(arguments.length).run(ai, thiz, arguments); @@ -153,7 +154,7 @@ public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... arguments) return constructors.get(arg_count).run(ai, object, arguments); } else { if (arg_count > 0) { - ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_CONSTRUCTOR, new String[] { name, String.valueOf(arguments.length) }); + ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_CONSTRUCTOR, new String[] { name, String.valueOf(arguments.length) }); } return object; } diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index d31f7ec2..921b38f3 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -10,6 +10,7 @@ import leekscript.runner.LeekOperations; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; +import leekscript.common.Error; public class FunctionLeekValue extends AbstractLeekValue { @@ -114,7 +115,7 @@ public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... values) thr } else if (mType == USER_FUNCTION) { if (values.length != ai.userFunctionCount(mId)) { - ai.addSystemLog(AILog.ERROR, AILog.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { AbstractLeekValue.getParamString(values), String.valueOf(ai.userFunctionCount(mId)) }); + ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { AbstractLeekValue.getParamString(values), String.valueOf(ai.userFunctionCount(mId)) }); } else { if (ai.getVersion() >= 11) { @@ -126,16 +127,14 @@ else if (mType == USER_FUNCTION) { } else if (mType == ANONYMOUS_FUNCTION) { if (values.length != ai.anonymousFunctionCount(mId)) { - ai.addSystemLog(AILog.ERROR, AILog.CAN_NOT_EXECUTE_WITH_ARGUMENTS, - new String[] { AbstractLeekValue.getParamString(values), String.valueOf(ai.anonymousFunctionCount(mId)) }); - } - else + ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { AbstractLeekValue.getParamString(values), String.valueOf(ai.anonymousFunctionCount(mId)) }); + } else { if (ai.getVersion() >= 11) { return mAnonymous.run(ai, null, copyPrimitiveValues(ai, values)); } else { return mAnonymous.run(ai, null, copyValues(ai, values, ai.anonymousFunctionReference(mId))); } - + } } else if (mType == METHOD) { return mAnonymous.run(ai, values[0], Arrays.copyOfRange(copyPrimitiveValues(ai, values), 1, values.length)); } diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 219acb67..b4b8b9bf 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -9,6 +9,7 @@ import leekscript.runner.LeekOperations; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; +import leekscript.common.Error; public class ObjectLeekValue extends AbstractLeekValue { @@ -50,7 +51,7 @@ public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { if (method != null) { return method; } - ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_FIELD, new String[] { clazz.name, field }); + ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { clazz.name, field }); return LeekValueManager.NULL; } @@ -58,10 +59,6 @@ public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunException { return getField(ai, value.getString(ai)); } - @Override - public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws LeekRunException { - return getField(ai, value.getString(ai)); - } @Override public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws LeekRunException { @@ -81,7 +78,7 @@ public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... a methodRealName += "x"; } methodRealName += ")"; - ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_METHOD, new String[] { clazz.name, methodRealName }); + ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { clazz.name, methodRealName }); return LeekValueManager.NULL; } // Call method with new arguments, add the object at the beginning @@ -101,7 +98,7 @@ public AbstractLeekValue callSuperMethod(AI ai, String method, AbstractLeekValue methodRealName += "x"; } methodRealName += ")"; - ai.addSystemLog(AILog.ERROR, AILog.UNKNOWN_METHOD, new String[] { clazz.name, methodRealName }); + ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { clazz.name, methodRealName }); return LeekValueManager.NULL; } // Call method with new arguments, add the object at the beginning @@ -136,7 +133,7 @@ public String getString(AI ai, Set visited) throws LeekRunException { if (string_method != null) { var result = string_method.run(ai, this, new AbstractLeekValue[] {}); if (result.getType() != STRING) { - ai.addSystemLog(AILog.ERROR, AILog.STRING_METHOD_MUST_RETURN_STRING, new String[] { clazz.name }); + ai.addSystemLog(AILog.ERROR, Error.STRING_METHOD_MUST_RETURN_STRING, new String[] { clazz.name }); } else { return result.getString(ai, visited); } From 60e8f7529f1a511d523a28bd7362009c14ab927b Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 21:27:15 +0200 Subject: [PATCH 137/319] [parser] Fix comments and double dot in numbers --- src/main/java/leekscript/compiler/WordParser.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index 1023cfdb..e01e76bf 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -120,8 +120,9 @@ else if(type == T_VAR_STRING && opener == c){ continue; } - if(c == '/' && i > 1 && code.charAt(i - 1) == '*' && comment_block && code.charAt(i - 2) != '/'){ + if (comment_block && c == '*' && length > i + 1 && code.charAt(i + 1) == '/') { comment_block = false; + i++; continue; } if(comment_line || comment_block) continue; @@ -173,8 +174,14 @@ else if(c == ':'){ type = T_NOTHING; } else if(c == '.'){ - if(type == T_NUMBER || type == T_VAR_STRING){ + if (type == T_VAR_STRING) { word += c; + } else if (type == T_NUMBER) { + if (word.contains(".")) { + compiler.addError(new AnalyzeError(new IAWord(mAI, 0, ".", line_counter, char_counter + 1), AnalyzeErrorLevel.ERROR, Error.INVALID_CHAR)); + } else { + word += c; + } } else if (version >= 11) { if (type == T_STRING) { From ebe50c025a0588fc61e7dad27215227b0c5497a3 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 21:27:15 +0200 Subject: [PATCH 138/319] [compiler] Fix expression parsing --- src/main/java/leekscript/compiler/WordCompiler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 3d5f83a5..a48600b6 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -868,7 +868,7 @@ public AbstractExpression readExpression() throws LeekCompilerException { LeekExpression retour = new LeekExpression(); while (mCompiler.haveWords()) { IAWord word = mCompiler.getWord(); - if (word.getType() == WordParser.T_PAR_RIGHT) { + if (word.getType() == WordParser.T_PAR_RIGHT || word.getType() == WordParser.T_ACCOLADE_RIGHT || word.getType() == WordParser.T_END_INSTRUCTION) { break; } if (retour.needOperator()) { From 9fba7609ec95751af158869b2c259a1d8f45a039 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 31 Mar 2021 21:27:15 +0200 Subject: [PATCH 139/319] [error] Add errors --- src/main/java/leekscript/common/Error.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/common/Error.java b/src/main/java/leekscript/common/Error.java index 88e06c3e..0e4e4287 100644 --- a/src/main/java/leekscript/common/Error.java +++ b/src/main/java/leekscript/common/Error.java @@ -69,11 +69,13 @@ public enum Error { AI_TIMEOUT, // 65 CODE_TOO_LARGE, // 66 CODE_TOO_LARGE_FUNCTION, // 67 - NOT_ITERABLE, // 68 + INTERNAL_ERROR, // 68 UNKNOWN_METHOD, // 69 UNKNOWN_STATIC_METHOD, // 70 STRING_METHOD_MUST_RETURN_STRING, // 71 UNKNOWN_FIELD, // 72 UNKNOWN_CONSTRUCTOR, // 73 - INSTANCEOF_MUST_BE_CLASS // 74 + INSTANCEOF_MUST_BE_CLASS, // 74 + NOT_ITERABLE, // 75 + STACKOVERFLOW, // 76 } \ No newline at end of file From cbf3c936cbf498eca57c78de501ba49d9e1d913b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Sat, 8 May 2021 13:33:18 +0200 Subject: [PATCH 140/319] Create build.yml --- .github/workflows/build.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..15bdca63 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,27 @@ +# This workflow will build a Java project with Gradle +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Java CI with Gradle + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Build with Gradle + run: ./gradlew build From c56590f1bb28afe10879424a8788f8751fa92fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Sat, 8 May 2021 13:35:01 +0200 Subject: [PATCH 141/319] Update build.yml --- .github/workflows/build.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 15bdca63..fedf50f3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,5 @@ jobs: with: java-version: '11' distribution: 'adopt' - - name: Grant execute permission for gradlew - run: chmod +x gradlew - name: Build with Gradle - run: ./gradlew build + run: gradle build From 1b9224829c0ab6384114a2275f5f8b1482c1ecf0 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 6 Apr 2021 23:06:36 +0200 Subject: [PATCH 142/319] [function] Remove logs --- .../leekscript/compiler/expression/LeekExpressionFunction.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 197a7c37..ccbfb434 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -159,7 +159,6 @@ public void analyze(WordCompiler compiler) { compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.INVALID_PARAMETER_COUNT)); } } else if (v.getVariableType() == VariableType.CLASS) { - System.out.println("Class " + v); var clazz = v.getClassDeclaration(); if (mParameters.size() != 0 && !clazz.hasConstructor(mParameters.size())) { @@ -167,7 +166,6 @@ public void analyze(WordCompiler compiler) { } } } else if (mExpression instanceof LeekObjectAccess) { - System.out.println("OA " + mExpression.getString()); var oa = (LeekObjectAccess) mExpression; if (oa.getObject() instanceof LeekVariable) { From 2fccaa3b395f2bc87d2be23c09ad8803cc309700 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 11 Apr 2021 12:11:35 +0200 Subject: [PATCH 143/319] [compiler] Use javax.tools.JavaCompiler --- .../leekscript/compiler/JavaCompiler.java | 90 ++----------------- 1 file changed, 5 insertions(+), 85 deletions(-) diff --git a/src/main/java/leekscript/compiler/JavaCompiler.java b/src/main/java/leekscript/compiler/JavaCompiler.java index 81605277..54c506f9 100644 --- a/src/main/java/leekscript/compiler/JavaCompiler.java +++ b/src/main/java/leekscript/compiler/JavaCompiler.java @@ -6,6 +6,8 @@ import java.io.InputStream; import java.io.InputStreamReader; +import javax.tools.ToolProvider; + public class JavaCompiler { public final static int INIT = 0; @@ -28,96 +30,14 @@ public void compile() throws Exception { return; } + javax.tools.JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); String classpath = JavaCompiler.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath(); - String[] args = new String[] { "javac", "-encoding", "utf8", "-classpath", classpath, mInput.getPath() }; - // System.out.println(String.join(" ", args)); - ProcessBuilder pb = new ProcessBuilder(args); - Worker worker = new Worker(pb); - Process process = worker.begin(); - - Gobbler outGobbler = new Gobbler(process.getInputStream()); - Gobbler errGobbler = new Gobbler(process.getErrorStream()); - Thread outThread = new Thread(outGobbler); - Thread errThread = new Thread(errGobbler); - outThread.start(); - errThread.start(); - try { - worker.join(20000); - if (worker.exit == null) { - throw new CompilationException("too_long_java"); - } - outThread.join(); - errThread.join(); - process.waitFor(); - String error = errGobbler.getOuput(); - if (error.length() > 0) { - mStatus = END; - throw new CompilationException(error); - } - if (process.exitValue() == 0) { - mStatus = END; - } - } catch (InterruptedException ex) { - worker.interrupt(); - Thread.currentThread().interrupt(); - throw ex; - } finally { - process.destroy(); - } + compiler.run(null, System.out, System.out, "-encoding", "utf8", "-classpath", classpath, mInput.getPath()); + // System.out.println("Javac result = " + result); } public static int getStatus() { return 0; } - - public static class Worker extends Thread { - private final ProcessBuilder pb; - private Process p; - public Integer exit; - public Worker(ProcessBuilder pb) { - this.pb = pb; - } - public Process begin() { - try { - p = pb.start(); - } catch (IOException e) { - e.printStackTrace(); - } - super.start(); - return p; - } - public void run() { - try { - exit = p.waitFor(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - public static class Gobbler implements Runnable { - private BufferedReader reader; - private StringBuilder output; - public Gobbler(InputStream inputStream) { - this.reader = new BufferedReader(new InputStreamReader(inputStream)); - } - public void run() { - String line; - output = new StringBuilder(); - try { - while ((line = reader.readLine()) != null) { - // Limit the length of the line to 500 characters - output.append(line.substring(0, Math.min(line.length(), 500)) + "\n"); - } - reader.close(); - } catch (IOException e) { - System.err.println("ERROR: " + e.getMessage()); - e.printStackTrace(); - } - } - public String getOuput() { - return this.output.toString(); - } - } } From 640056971e06f9131122c37edcf9764350a9ea6c Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 8 May 2021 13:58:33 +0200 Subject: [PATCH 144/319] [build] Fix build for gradle 7 --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index acd8f25f..5f494d27 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ jar { attributes "Main-Class": "leekscript.TopLevel" } from { - configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } } @@ -32,6 +32,6 @@ repositories { } dependencies { - testCompile 'junit:junit:4.12' - compile group: 'com.alibaba', name: 'fastjson', version: '1.1.25' + testImplementation 'junit:junit:4.12' + implementation group: 'com.alibaba', name: 'fastjson', version: '1.1.25' } From 3515ce2f81027f0aa0c6db6af19f484adfe8486f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Sat, 8 May 2021 14:03:11 +0200 Subject: [PATCH 145/319] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 74464628..5b5243d7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # LeekScript +[![Java CI with Gradle](https://github.com/leek-wars/leekscript/actions/workflows/build.yml/badge.svg)](https://github.com/leek-wars/leekscript/actions/workflows/build.yml) + The language of Leek Wars, built in Java. Used in the [leek-wars-generator](https://github.com/leek-wars/leek-wars-generator) project. From ff840cf55058b671bcdc455f1bce9db499ed99a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Sat, 8 May 2021 14:03:39 +0200 Subject: [PATCH 146/319] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fedf50f3..8a1b940b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,7 @@ # This workflow will build a Java project with Gradle # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle -name: Java CI with Gradle +name: CI on: push: From 5639fcad609fd55db505b68d7f7bde79eedcf42c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Sat, 8 May 2021 14:03:54 +0200 Subject: [PATCH 147/319] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8a1b940b..c68fb341 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,5 +21,5 @@ jobs: with: java-version: '11' distribution: 'adopt' - - name: Build with Gradle + - name: Build run: gradle build From 01a777832e106d850f935577af204516e7c2dfa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Sat, 8 May 2021 14:04:12 +0200 Subject: [PATCH 148/319] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b5243d7..5cfa84a4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # LeekScript -[![Java CI with Gradle](https://github.com/leek-wars/leekscript/actions/workflows/build.yml/badge.svg)](https://github.com/leek-wars/leekscript/actions/workflows/build.yml) +[![CI](https://github.com/leek-wars/leekscript/actions/workflows/build.yml/badge.svg)](https://github.com/leek-wars/leekscript/actions/workflows/build.yml) The language of Leek Wars, built in Java. Used in the [leek-wars-generator](https://github.com/leek-wars/leek-wars-generator) project. From 576b6cdb939b3ade7fdd644a7174f11d0f58bac5 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 149/319] [test] Add tests from LeekScript V2 --- .../java/leekscript/compiler/LeekScript.java | 7 + src/test/java/test/TestArray.java | 344 +++++++ src/test/java/test/TestComments.java | 14 + src/test/java/test/TestCommon.java | 208 ++++ src/test/java/test/TestEuler.java | 42 + src/test/java/test/TestFiles.java | 49 + src/test/java/test/TestFunction.java | 49 + src/test/java/test/TestGeneral | 278 ++++++ src/test/java/test/TestGeneral.java | 476 +-------- src/test/java/test/TestGlobals.java | 35 + src/test/java/test/TestIf.java | 88 ++ src/test/java/test/TestLoops.java | 222 +++++ src/test/java/test/TestMain.java | 27 + src/test/java/test/TestNumber.java | 939 ++++++++++++++++++ src/test/java/test/TestOperators.java | 265 ++--- src/test/java/test/TestReference.java | 23 + src/test/java/test/TestString.java | 51 + src/test/java/test/TestWithFile | 65 ++ src/test/resources/ai/array_keys.leek | 5 + src/test/resources/ai/bonjour.leek | 1 + src/test/resources/ai/code/ai.leek | 51 + src/test/resources/ai/code/array.leek | 12 + src/test/resources/ai/code/assignments.leek | 19 + .../resources/ai/code/break_and_continue.leek | 25 + src/test/resources/ai/code/catch_else.leek | 1 + src/test/resources/ai/code/class.txt | 31 + .../resources/ai/code/classes_multiple.leek | 22 + .../resources/ai/code/classes_simple.leek | 14 + src/test/resources/ai/code/code.ls | 330 ++++++ src/test/resources/ai/code/divisors.leek | 2 + .../resources/ai/code/dynamic_operators.leek | 5 + src/test/resources/ai/code/euler1.leek | 10 + src/test/resources/ai/code/fact1000.leek | 5 + src/test/resources/ai/code/fibonacci.leek | 2 + .../resources/ai/code/fibonacci_long.leek | 2 + src/test/resources/ai/code/fibonacci_v12.leek | 2 + src/test/resources/ai/code/fold_left.leek | 1 + src/test/resources/ai/code/fold_left_2.leek | 2 + src/test/resources/ai/code/fold_right.leek | 1 + src/test/resources/ai/code/fold_right_2.leek | 2 + src/test/resources/ai/code/french.leek | 63 ++ src/test/resources/ai/code/french.min.leek | 5 + src/test/resources/ai/code/gcd.leek | 10 + .../resources/ai/code/global_functions_1.leek | 7 + .../resources/ai/code/global_functions_2.leek | 9 + src/test/resources/ai/code/knapsack.leek | 33 + src/test/resources/ai/code/knapsack_11.leek | 32 + src/test/resources/ai/code/match.leek | 6 + src/test/resources/ai/code/mul_array.leek | 26 + src/test/resources/ai/code/pow5.leek | 14 + src/test/resources/ai/code/primes.leek | 17 + src/test/resources/ai/code/primes_gmp.leek | 9 + .../resources/ai/code/product_coproduct.leek | 8 + src/test/resources/ai/code/product_n.leek | 8 + .../resources/ai/code/product_n_arrays.leek | 8 + .../resources/ai/code/product_n_return.leek | 8 + .../resources/ai/code/project_euler_20.ls | 30 + .../resources/ai/code/project_euler_61.ls | 110 ++ src/test/resources/ai/code/quine.leek | 1 + src/test/resources/ai/code/quine_zwik.leek | 16 + .../resources/ai/code/reachable_cells.leek | 39 + .../ai/code/recursive_2_functions.leek | 4 + .../resources/ai/code/recursive_2_vars.leek | 12 + .../ai/code/recursive_2_versions.leek | 12 + .../ai/code/recursive_conditions.leek | 22 + .../ai/code/recursive_conditions_2.leek | 22 + .../resources/ai/code/return_in_function.leek | 6 + src/test/resources/ai/code/strings.leek | 15 + src/test/resources/ai/code/swap.leek | 23 + src/test/resources/ai/code/tarai.leek | 9 + src/test/resources/ai/code/text_analysis.leek | 9 + src/test/resources/ai/code/trivial.leek | 1 + src/test/resources/ai/code/two_functions.leek | 3 + src/test/resources/ai/euler/pe001.leek | 7 + src/test/resources/ai/euler/pe002.leek | 12 + src/test/resources/ai/euler/pe003.leek | 7 + src/test/resources/ai/euler/pe004.leek | 10 + src/test/resources/ai/euler/pe005.leek | 15 + src/test/resources/ai/euler/pe006.leek | 9 + src/test/resources/ai/euler/pe007.leek | 19 + src/test/resources/ai/euler/pe008.leek | 36 + src/test/resources/ai/euler/pe009.leek | 8 + src/test/resources/ai/euler/pe010.leek | 20 + src/test/resources/ai/euler/pe011.leek | 60 ++ src/test/resources/ai/euler/pe012.leek | 29 + src/test/resources/ai/euler/pe013.leek | 102 ++ src/test/resources/ai/euler/pe014.leek | 33 + src/test/resources/ai/euler/pe015.leek | 22 + src/test/resources/ai/euler/pe016.leek | 4 + src/test/resources/ai/euler/pe017.leek | 54 + src/test/resources/ai/euler/pe018.leek | 34 + src/test/resources/ai/euler/pe019.leek | 22 + src/test/resources/ai/euler/pe020.leek | 12 + src/test/resources/ai/euler/pe021.leek | 15 + src/test/resources/ai/euler/pe022.leek | 15 + src/test/resources/ai/euler/pe023.leek | 39 + src/test/resources/ai/euler/pe024.leek | 28 + src/test/resources/ai/euler/pe025.leek | 15 + src/test/resources/ai/euler/pe027.leek | 33 + src/test/resources/ai/euler/pe028.leek | 15 + src/test/resources/ai/euler/pe062.leek | 20 + src/test/resources/ai/euler/pe063.leek | 10 + src/test/resources/ai/euler/pe064.leek | 11 + src/test/resources/ai/euler/pe066.leek | 23 + src/test/resources/ai/euler/pe206.leek | 24 + src/test/resources/ai/french.leek | 6 + src/test/resources/ai/include_multiple.leek | 2 + src/test/resources/ai/include_sub.leek | 1 + src/test/resources/ai/library.leek | 5 + src/test/resources/ai/multiple_includes.leek | 3 + .../ai/subfolder/include_parent.leek | 1 + src/test/resources/ai/subfolder/sub.leek | 1 + 112 files changed, 4475 insertions(+), 631 deletions(-) create mode 100644 src/test/java/test/TestArray.java create mode 100644 src/test/java/test/TestComments.java create mode 100644 src/test/java/test/TestCommon.java create mode 100644 src/test/java/test/TestEuler.java create mode 100644 src/test/java/test/TestFiles.java create mode 100644 src/test/java/test/TestFunction.java create mode 100644 src/test/java/test/TestGeneral create mode 100644 src/test/java/test/TestGlobals.java create mode 100644 src/test/java/test/TestIf.java create mode 100644 src/test/java/test/TestLoops.java create mode 100644 src/test/java/test/TestMain.java create mode 100644 src/test/java/test/TestNumber.java create mode 100644 src/test/java/test/TestReference.java create mode 100644 src/test/java/test/TestString.java create mode 100644 src/test/java/test/TestWithFile create mode 100644 src/test/resources/ai/array_keys.leek create mode 100644 src/test/resources/ai/bonjour.leek create mode 100644 src/test/resources/ai/code/ai.leek create mode 100644 src/test/resources/ai/code/array.leek create mode 100644 src/test/resources/ai/code/assignments.leek create mode 100644 src/test/resources/ai/code/break_and_continue.leek create mode 100644 src/test/resources/ai/code/catch_else.leek create mode 100644 src/test/resources/ai/code/class.txt create mode 100644 src/test/resources/ai/code/classes_multiple.leek create mode 100644 src/test/resources/ai/code/classes_simple.leek create mode 100644 src/test/resources/ai/code/code.ls create mode 100644 src/test/resources/ai/code/divisors.leek create mode 100644 src/test/resources/ai/code/dynamic_operators.leek create mode 100644 src/test/resources/ai/code/euler1.leek create mode 100644 src/test/resources/ai/code/fact1000.leek create mode 100644 src/test/resources/ai/code/fibonacci.leek create mode 100644 src/test/resources/ai/code/fibonacci_long.leek create mode 100644 src/test/resources/ai/code/fibonacci_v12.leek create mode 100644 src/test/resources/ai/code/fold_left.leek create mode 100644 src/test/resources/ai/code/fold_left_2.leek create mode 100644 src/test/resources/ai/code/fold_right.leek create mode 100644 src/test/resources/ai/code/fold_right_2.leek create mode 100644 src/test/resources/ai/code/french.leek create mode 100644 src/test/resources/ai/code/french.min.leek create mode 100644 src/test/resources/ai/code/gcd.leek create mode 100644 src/test/resources/ai/code/global_functions_1.leek create mode 100644 src/test/resources/ai/code/global_functions_2.leek create mode 100644 src/test/resources/ai/code/knapsack.leek create mode 100644 src/test/resources/ai/code/knapsack_11.leek create mode 100644 src/test/resources/ai/code/match.leek create mode 100644 src/test/resources/ai/code/mul_array.leek create mode 100644 src/test/resources/ai/code/pow5.leek create mode 100644 src/test/resources/ai/code/primes.leek create mode 100644 src/test/resources/ai/code/primes_gmp.leek create mode 100644 src/test/resources/ai/code/product_coproduct.leek create mode 100644 src/test/resources/ai/code/product_n.leek create mode 100644 src/test/resources/ai/code/product_n_arrays.leek create mode 100644 src/test/resources/ai/code/product_n_return.leek create mode 100644 src/test/resources/ai/code/project_euler_20.ls create mode 100644 src/test/resources/ai/code/project_euler_61.ls create mode 100644 src/test/resources/ai/code/quine.leek create mode 100644 src/test/resources/ai/code/quine_zwik.leek create mode 100644 src/test/resources/ai/code/reachable_cells.leek create mode 100644 src/test/resources/ai/code/recursive_2_functions.leek create mode 100644 src/test/resources/ai/code/recursive_2_vars.leek create mode 100644 src/test/resources/ai/code/recursive_2_versions.leek create mode 100644 src/test/resources/ai/code/recursive_conditions.leek create mode 100644 src/test/resources/ai/code/recursive_conditions_2.leek create mode 100644 src/test/resources/ai/code/return_in_function.leek create mode 100644 src/test/resources/ai/code/strings.leek create mode 100644 src/test/resources/ai/code/swap.leek create mode 100644 src/test/resources/ai/code/tarai.leek create mode 100644 src/test/resources/ai/code/text_analysis.leek create mode 100644 src/test/resources/ai/code/trivial.leek create mode 100644 src/test/resources/ai/code/two_functions.leek create mode 100644 src/test/resources/ai/euler/pe001.leek create mode 100644 src/test/resources/ai/euler/pe002.leek create mode 100644 src/test/resources/ai/euler/pe003.leek create mode 100644 src/test/resources/ai/euler/pe004.leek create mode 100644 src/test/resources/ai/euler/pe005.leek create mode 100644 src/test/resources/ai/euler/pe006.leek create mode 100644 src/test/resources/ai/euler/pe007.leek create mode 100644 src/test/resources/ai/euler/pe008.leek create mode 100644 src/test/resources/ai/euler/pe009.leek create mode 100644 src/test/resources/ai/euler/pe010.leek create mode 100644 src/test/resources/ai/euler/pe011.leek create mode 100644 src/test/resources/ai/euler/pe012.leek create mode 100644 src/test/resources/ai/euler/pe013.leek create mode 100644 src/test/resources/ai/euler/pe014.leek create mode 100644 src/test/resources/ai/euler/pe015.leek create mode 100644 src/test/resources/ai/euler/pe016.leek create mode 100644 src/test/resources/ai/euler/pe017.leek create mode 100644 src/test/resources/ai/euler/pe018.leek create mode 100644 src/test/resources/ai/euler/pe019.leek create mode 100644 src/test/resources/ai/euler/pe020.leek create mode 100644 src/test/resources/ai/euler/pe021.leek create mode 100644 src/test/resources/ai/euler/pe022.leek create mode 100644 src/test/resources/ai/euler/pe023.leek create mode 100644 src/test/resources/ai/euler/pe024.leek create mode 100644 src/test/resources/ai/euler/pe025.leek create mode 100644 src/test/resources/ai/euler/pe027.leek create mode 100644 src/test/resources/ai/euler/pe028.leek create mode 100644 src/test/resources/ai/euler/pe062.leek create mode 100644 src/test/resources/ai/euler/pe063.leek create mode 100644 src/test/resources/ai/euler/pe064.leek create mode 100644 src/test/resources/ai/euler/pe066.leek create mode 100644 src/test/resources/ai/euler/pe206.leek create mode 100644 src/test/resources/ai/french.leek create mode 100644 src/test/resources/ai/include_multiple.leek create mode 100644 src/test/resources/ai/include_sub.leek create mode 100644 src/test/resources/ai/library.leek create mode 100644 src/test/resources/ai/multiple_includes.leek create mode 100644 src/test/resources/ai/subfolder/include_parent.leek create mode 100644 src/test/resources/ai/subfolder/sub.leek diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 9fadc4e7..5d25db47 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -1,6 +1,7 @@ package leekscript.compiler; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -50,6 +51,11 @@ public static AI compileFile(String filepath, String AIClass, boolean nocache) t return compile(ai, AIClass, nocache); } + public static AI compileFile(String filepath, String AIClass, int version) throws LeekScriptException, LeekCompilerException, IOException { + AIFile ai = getResolver().resolve(filepath, null); + return compile(ai, AIClass, true); + } + public static AI compileFileContext(String filepath, String AIClass, ResolverContext context, boolean nocache) throws LeekScriptException, LeekCompilerException, IOException { AIFile ai = getResolver().resolve(filepath, context); return compile(ai, AIClass, nocache); @@ -169,4 +175,5 @@ public static void throwException(String error) throws LeekScriptException { } throw new LeekScriptException(LeekScriptException.CANT_COMPILE, error); } + } \ No newline at end of file diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java new file mode 100644 index 00000000..cae77a7f --- /dev/null +++ b/src/test/java/test/TestArray.java @@ -0,0 +1,344 @@ +package test; + +public class TestArray extends TestCommon { + + public void run() throws Exception { + + section("Array.constructor()"); + // DISABLED_code("Array").equals(""); + // DISABLED_code("Array()").equals("[]"); + // DISABLED_code("new Array").equals("[]"); + // DISABLED_code("new Array()").equals("[]"); + // DISABLED_code("new Array() + 1").equals("[1]"); + code("return [];").equals("[]"); + code("return [1];").equals("[1]"); + code("return [1, 2, 3];").equals("[1, 2, 3]"); + // DISABLED_code("[1l, 2l, 3l]").equals("[1, 2, 3]"); + code_v10("return [1.21, -5, 4.55, 12, -6.7];").equals("[1,21, -5, 4,55, 12, -6,7]"); + code_v11("return [1.21, -5, 4.55, 12, -6.7];").equals("[1.21, -5, 4.55, 12, -6.7]"); + code("return [true, false, true];").equals("[true, false, true]"); + // DISABLED_code("[23, true, '', {}, 123]").equals("[23, true, '', {}, 123]"); + // DISABLED_code("let a = x -> x [1, 2, a]").equals("[1, 2, ]"); + // DISABLED_code("[1m, 34324234m, 231232131232132134379897874534243257343341432423m]").equals("[1, 34324234, 231232131232132134379897874534243257343341432423]"); + // DISABLED_code("[true, 'hello', 231232131232132134379897874534243257343341432423m]").equals("[true, 'hello', 231232131232132134379897874534243257343341432423]"); + + section("Array & variables"); + code("var a = []; return a;").equals("[]"); + code_v10("var a = @[]; return a;").equals("[]"); + code_v10("var a = [1, 2, 3] var b = a push(b, 4) return a;").equals("[1, 2, 3]"); + code_v10("var a = [1, 2, 3] var b = (function() { return @a })() push(b, 4) return a;").equals("[1, 2, 3, 4]"); + + section("Array.operator +"); + code("return [1, 2, 3] + [4, 5, 6];").equals("[1, 2, 3, 4, 5, 6]"); + // DISABLED_code("return [] + 1;").equals("[1]"); + // DISABLED_code("return [] + 1 + 2 + 3;").equals("[1, 2, 3]"); + // DISABLED_code("return [1] + 2;").equals("[1, 2]"); + // DISABLED_code("return [1] + 0.5;").equals("[1, 0.5]"); + // DISABLED_code("return [0.5] + 'a';").equals("[0.5, 'a']"); + code("return ['a'] + ['b'];").equals("[a, b]"); + // DISABLED_code("return [1] + 0.5 + 'a';").equals("[1, 0.5, 'a']"); + // DISABLED_code("return [1] + 0.5 + 'a' + 'b';").equals("[1, 0.5, 'a', 'b']"); + // DISABLED_code("return [1] + null;").equals("[1, null]"); + // DISABLED_code("return [1] + true;").equals("[1, true]"); + code("return [1] + [2] + [3];").equals("[1, 2, 3]"); + code_v10("return [1] + [2.5] + ['a'];").equals("[1, 2,5, a]"); + code_v11("return [1] + [2.5] + ['a'];").equals("[1, 2.5, a]"); + code_v10("return ['a'] + [2.5] + [1];").equals("[a, 2,5, 1]"); + code_v11("return ['a'] + [2.5] + [1];").equals("[a, 2.5, 1]"); + code("return [1] + ['a'];").equals("[1, a]"); + code("return ['a'] + [1];").equals("[a, 1]"); + // DISABLED_code("return [12.5] + null;").equals("[12.5, null]"); + // DISABLED_code("var a = ['yo'] return a + null;").equals("['yo', null]"); + // DISABLED_code("return [12.5] + true;").equals("[12.5, true]"); + // DISABLED_code("return ['yo'] + true;").equals("['yo', true]"); + // DISABLED_code("var a = ['yo'] return a + true;").equals("['yo', true]"); + // DISABLED_code("return [15.5] + [12, ''][0];").equals("[15.5, 12]"); + // DISABLED_code("var a = [15.5] return a + [12, ''][0];").equals("[15.5, 12]"); + // DISABLED_code("var a = [1] return a + [12, ''][0];").equals("[1, 12]"); + // DISABLED_code("return ['yo'] + '!';").equals("['yo', '!']"); + // DISABLED_code("var a = ['yo'] return a + '!';").equals("['yo', '!']"); + code("var a = [5] var b = ['b'] return a + b;").equals("[5, b]"); + code("var a = ['a'] return a + ['b'];").equals("[a, b]"); + // DISABLED_code("[1, 2] + {};").equals("[1, 2, {}]"); + // DISABLED_code("let a = [1, 2] a + {};").equals("[1, 2, {}]"); + // DISABLED_code("['a', 'b'] + {};").equals("['a', 'b', {}]"); + // DISABLED_code("let a = ['a', 'b'] a + {}").equals("['a', 'b', {}]"); + // DISABLED_code("return ['a', 'b'] + (x -> x)").equals("['a', 'b', ]"); + // DISABLED_code("let a = ['a', 'b'] a + (x -> x)").equals("['a', 'b', ]"); + // DISABLED_code("['a', 'b'] + Number").equals("['a', 'b', ]"); + // DISABLED_code("let a = ['a', 'b'] a + Number").equals("['a', 'b', ]"); + // DISABLED_code("var a = [1, 2] return a + [3, 4];").equals("[1, 2, 3, 4]"); + // DISABLED_code("var a = ['a'] return [3.5, 4.6] + a;").equals("[3.5, 4.6, 'a']"); + // DISABLED_code("var pq = [] pq = pq + 1 return pq;").equals("[1]"); + // DISABLED_code("[1l] + 12l").equals("[1, 12]"); + // DISABLED_code("[] + 12l").equals("[12]"); + + section("null array"); + code("var a = null return a[1]").equals("null"); + code("var a = null return a['a']").equals("null"); + code("var a = null return a[1] = 12").equals("null"); + + section("Array.operator +="); + // DISABLED_code("var a = [1.55] a += 12.9 return a;").equals("[1.55]"); + // DISABLED_code("var a = ['a'] a += 'b' return a;").equals("['a', 'b']"); + // DISABLED_code("var a = [1, 2, 3] a[0] += 5 return a[0];").equals("6"); + // DISABLED_code("var v = 12 var a = [v, 2, 3] a[0] += 5 return a[0];").equals("17"); + // DISABLED_code("var a = [1, 2, 3] a += 'hello' return a;").equals("[1, 2, 3, 'hello']"); + code_v10("var a = [1.5] a += ['a', 'b'] return a").equals("[1,5, a, b]"); + code_v11("var a = [1.5] a += ['a', 'b'] return a").equals("[1.5, a, b]"); + // DISABLED_code("var a = [1.5] a += false return a;").equals("[1.5, false]"); + // DISABLED_code("var a = [1] a += <2, 3> a").equals("[1, 2, 3]"); + // DISABLED_code("var a = [1] a += <5.5, 7.314> a").equals("[1, 5.5, 7.314]"); + // DISABLED_code("var a = [1] a += <5, 7.314, 'hello'> a").equals("[1, 5, 7.314, 'hello']"); + // DISABLED_code("var a = [1] a += [<5, 7.314, 'hello'>, ''][0] a").equals("[1, 5, 7.314, 'hello']"); + // DISABLED_code("var a = [1] a += <'z', 'a'> a").equals("[1, 'a', 'z']"); + // DISABLED_code("var a = [1] a += 'a' return a;").equals("[1, 'a']"); + // DISABLED_code("var a = [[1]] a[0] += [12, ''][0] return a[0];").equals("[1, 12]"); + code_v10("var a = [1.11] a += [2, 3] return a").equals("[1,11, 2, 3]"); + code_v11("var a = [1.11] a += [2, 3] return a").equals("[1.11, 2, 3]"); + // DISABLED_code("var a = [[1.55]] a[0] += [12.9, ''][0] return a[0];").equals("[1.55, 12.9]"); + // DISABLED_code("var a = [[1.55]] a[0] += [-1.5, 6.7] return a[0];").equals("[1.55, -1.5, 6.7]"); + // DISABLED_code("var a = [[1.55]] a[0] += <8, 4> a[0]").equals("[1.55, 4, 8]"); + // DISABLED_code("var a = [[1.55]] a[0] += < -8.5, 4.7> a[0]").equals("[1.55, -8.5, 4.7]"); + // DISABLED_code("var a = [[1.55]] a[0] += < -8.5, 4.7, 'hello'> a[0]").equals("[1.55, -8.5, 4.7, 'hello']"); + code("var a = ['a'] return a += [1, 2]").equals("[a, 1, 2]"); + code_v10("var a = ['a'] return a += [1.5, 2.5]").equals("[a, 1,5, 2,5]"); + code_v11("var a = ['a'] return a += [1.5, 2.5]").equals("[a, 1.5, 2.5]"); + // DISABLED_code("var a = ['a'] a += <1, 2>").equals("['a', 1, 2]"); + // DISABLED_code("var a = ['a'] a += <1.5, 2.5>").equals("['a', 1.5, 2.5]"); + // DISABLED_code("var a = ['a'] var b = <'b'> a += b a").equals("['a', 'b']"); + code("var a = ['a'] var b = [12] a += b return a").equals("[a, 12]"); + // DISABLED_code("var a = [1, 2, 3] a[1] += 0.5 return a;").equals("[1, 2.5, 3]"); + code("var a = [1, 2, 3] a += [4] return a").equals("[1, 2, 3, 4]"); + // DISABLED_code("var a = [1, 2, 3] a[1] += 500l a").equals("[1, 502, 3]"); + // DISABLED_code("var a = [] if (true) a += 12 return a;").equals("[12]"); + // DISABLED_code("var a = [1] if (true) a += 12 return a;").equals("[1, 12]"); + // DISABLED_code("var a = ['a'] if (true) a += 12 return a;").equals("['a', 12]"); + + section("Array.operator += on element"); + code("var a = [5] a[0] += 1 return a;").equals("[6]"); + code("var a = [5, 6, 7] a[0] += 10 a[1] += 10 return a;").equals("[15, 16, 7]"); + code("var a = [[5]] a[0][0] += 1 return a;").equals("[[6]]"); + code("var a = [] a[0] += 1 return a;").equals("[1]"); + + section("Array.operator ++ on element"); + code("var a = [5] a[0]++ return a;").equals("[6]"); + code("var a = [5, 6, 7] a[0]++ a[1]++ return a;").equals("[6, 7, 7]"); + code("var a = [[5]] a[0][0]++ return a;").equals("[[6]]"); + + section("Array.operator -- on element"); + code("var a = [5] a[0]-- return a;").equals("[4]"); + code("var a = [5, 6, 7] a[0]-- a[1]-- return a;").equals("[4, 5, 7]"); + code("var a = [[5]] a[0][0]-- return a;").equals("[[4]]"); + + section("Array.operator -= on element"); + code("var a = [5] a[0] -= 1 return a;").equals("[4]"); + code("var a = [5, 6, 7] a[0] -= 10 a[1] -= 10 return a;").equals("[-5, -4, 7]"); + code("var a = [[5]] a[0][0] -= 1 return a;").equals("[[4]]"); + code("var a = [] a[0] -= 1 return a;").equals("[-1]"); + + section("Array.operator *= on element"); + code("var a = [5] a[0] *= 10 return a;").equals("[50]"); + code("var a = [5, 6, 7] a[0] *= 10 a[1] *= 10 return a;").equals("[50, 60, 7]"); + code("var a = [[5]] a[0][0] *= 10 return a;").equals("[[50]]"); + + section("Array.operator |= on element"); + code("var a = [5] a[0] |= 2 return a;").equals("[7]"); + code("var a = [5, 6, 7] a[0] |= 8 a[1] |= 8 return a;").equals("[13, 14, 7]"); + code("var a = [[5]] a[0][0] |= 2 return a;").equals("[[7]]"); + code("var a = [] a[0] |= 1 return a;").equals("[1]"); + + section("Array.count()"); + code("return count([1, 2, 3, 4, 5]);").equals("5"); + + section("Array.push()"); + code("var a = [] push(a, 12) return a;").equals("[12]"); + code("var a = [] push(a, 1) push(a, 2) push(a, 3) return a;").equals("[1, 2, 3]"); + code("var a = [1, 2, 3] push(a, 4) return a;").equals("[1, 2, 3, 4]"); + code("var a = [1, 2, 3] push(a, 'hello') return a;").equals("[1, 2, 3, hello]"); + code("return push([], 'hello');").equals("null"); + code("var a = [[]] push(a[0], 'hello') return a;").equals("[[hello]]"); + code("var a = [[]] push(a, [1, 2, 3]) return a;").equals("[[], [1, 2, 3]]"); + code("var a = [1, [1, 2]] push(a[1], 3) return a;").equals("[1, [1, 2, 3]]"); + code("var a = [1, [1, 2]] push(a[1], 3) return a[1];").equals("[1, 2, 3]"); + code("var a = [1, ['a', 'b']] push(a[1], 'c') return a[1];").equals("[a, b, c]"); + code("var a = [[], ['a']] push(a[1], 'b') return a;").equals("[[], [a, b]]"); + code("return function() { var a = []; for (var i = 0; i < 100000; ++i) { push(a, i); } return a[91212]; }();").equals("91212"); + code("return function() { var a = ['a','b','c','d']; push(a, 'b'); return string(a); }();").equals("[a, b, c, d, b]"); + + section("Array.pushAll()"); + code("var a = [] pushAll(a, [1, 2, 3]) return a;").equals("[1, 2, 3]"); + code("var a = [1, 2, 3] pushAll(a, [4, 5, 6]) return a;").equals("[1, 2, 3, 4, 5, 6]"); + code("var a = [] var b = [1, 2, 3] pushAll(a, b) return a;").equals("[1, 2, 3]"); + code("var a = [1, 2, 3] var b = [4, 5, 6] pushAll(a, b) return a;").equals("[1, 2, 3, 4, 5, 6]"); + code("var a = [[], ['a']] pushAll(a[1], ['b', 'c']) return a;").equals("[[], [a, b, c]]"); + code("return function() { var a = [1, 2, 3]; pushAll(a, [5, 6, 7]); return a; }();").equals("[1, 2, 3, 5, 6, 7]"); + + section("Array.filter() v1.0"); + code_v10("return arrayFilter([1, 2, 3, 4, 5, 6, 7, 8, 9], function(e) { return e > 5; });").equals("[5 : 6, 6 : 7, 7 : 8, 8 : 9]"); + code_v10("return arrayFilter([4, 5, 6, 'test', 8, 9], function(e) { return e == 'test'; });").equals("[3 : test]"); + code_v10("return arrayFilter(['a', 'b', 'c', 'd'], function(k, v) { return k == 3; });").equals("[3 : d]"); + code_v10("return function() { var t = ['a', 'b', 'c', 'd']; arrayFilter(t, function(k, @v) { v = 4; return k == 3; }); return t; }();").equals("[4, 4, 4, 4]"); + code_v10("return arrayFilter(['a', 'b', 'c', 'd'], function(k, @v) { v = 4; return k == 3; });").equals("[3 : 4]"); + + section("Array.filter() v1.1"); + code_v11("return arrayFilter([1, 2, 3, 4, 5, 6, 7, 8, 9], function(e) { return e > 5; });").equals("[6, 7, 8, 9]"); + code_v11("return arrayFilter([4, 5, 6, 'test', 8, 9], function(e) { return e == 'test'; });").equals("[test]"); + code_v11("return string(arrayFilter(['a', 'b', 'c', 'd'], function(k, v) { return k == 3; }));").equals("[d]"); + + section("Array.flatten()"); + code("return arrayFlatten([6,7,[8,9]],99);").equals("[6, 7, 8, 9]"); + code("return arrayFlatten([6,[[7]],[8,9]],2);").equals("[6, 7, 8, 9]"); + code("return arrayFlatten([6,[[7]],[8,9]]);").equals("[6, [7], 8, 9]"); + + section("Array.sort"); + code("return function() { var t = [null, null, 4, 8, 9]; sort(t); return t; }();").equals("[null, null, 4, 8, 9]"); + code("return function() { var t = [4, null, 4, null, 4]; sort(t); return t; }();").equals("[null, null, 4, 4, 4]"); + code("return function() { var t = [4, null, 5, null, 8]; sort(t, SORT_DESC); return t; }();").equals("[8, 5, 4, null, null]"); + + section("Array and references"); + code_v10("var t = [@3, @4, @5]; return t;").equals("[3, 4, 5]"); + code_v10("var t = [3, 4, 5]; var a = 12; t[1] = @a return t;").equals("[3, 12, 5]"); + code_v10("var t = [3, 4, 5]; var a = @t[1] a++ return t;").equals("[3, 4, 5]"); + code_v10("var t = [3, 4, 5]; var a = null a = @t[1] a++ return t;").equals("[3, 4, 5]"); + code_v10("var t = [3, 4, 5]; t[3] = [1, 2, 3, 4]; var r = @t[3]; r[4] = 'coucou'; return t;").equals("[3, 4, 5, [1, 2, 3, 4, coucou]]"); + + section("Array.map() v1.0"); + code_v10("return arrayMap([1, 2, 3, 4, 5], function(e) { return e * 2; });").equals("[2, 4, 6, 8, 10]"); + code_v10("return arrayMap([4, 9, 16], sqrt);").equals("[2, 3, 4]"); + code_v10("return arrayMap(['a': 1,'b': 2], function(k, v) { return k + v; });").equals("[a : a1, b : b2]"); + code_v10("return function() { var t = ['a':1,'b':2]; arrayMap(t, function(@k, @v) { v = 'tomate'; k = 'ctus'; return 3; }); return t; }();").equals("[a : tomate, b : tomate]"); + + section("Array.map() v1.1"); + code_v11("return arrayMap([1, 2, 3, 4, 5], function(e) { return e * 2; });").equals("[2, 4, 6, 8, 10]"); + code_v11("return arrayMap([4, 9, 16], sqrt);").equals("[2.0, 3.0, 4.0]"); + code_v11("return arrayMap(['a': 1, 'b': 2], function(k, v) { return k + v; });").equals("[a : a1, b : b2]"); + code_v11("return function() { var t = ['a': 1, 'b': 2]; arrayMap(t, function(k, v) { v = 'tomate'; k = 'ctus'; return 3; }); return t; }();").equals("[a : 1, b : 2]"); + + section("Array.foldLeft()"); + code("return arrayFoldLeft([6, 7, 8, 9], function(a, b) { return a + b; }, 0)").equals("30"); + code("return arrayFoldLeft([1,0,1,2,5,7,9], function(a,b){return a+','+b;},'')").equals(",1,0,1,2,5,7,9"); + + section("Array.foldRight()"); + code("return arrayFoldRight([6,7,8,9], function(a,b){return a+b;},0)").equals("30"); + code("return arrayFoldRight([1,0,1,2,5,7,9], function(a,b){return a+','+b;},'')").equals("1,0,1,2,5,7,9,"); + + section("Array.partition()"); + code("return arrayPartition([6,7,8,9], function(a){return a&1;})").equals("[[1 : 7, 3 : 9], [0 : 6, 2 : 8]]"); + code("return string(arrayPartition([6,7,8,9], function(k,v){return k;}))").equals("[[1 : 7, 2 : 8, 3 : 9], [6]]"); + code("return string(arrayPartition([4,3,2,1], function(k,v){return kf)?(-1):(ek2)?(-1):(k1k2)?(-1):(k1 failedTests = new ArrayList(); + private static List disabledTests = new ArrayList(); + + public static class Case { + String code; + boolean enabled = true; + int version = -1; + + public Case(String code, boolean enabled) { + this.code = code; + this.enabled = enabled; + } + + public Case(String code, boolean enabled, int version) { + this.code = code; + this.enabled = enabled; + this.version = version; + } + + public void equals(String expected) { + run(version, new Checker() { + public boolean check(Result result) { + return result.result.equals(expected); + } + public String getExpected() { return expected; } + }); + } + + public void almost(double expected) { + almost(expected, 1e-10); + } + + public void almost(double expected, double delta) { + run(version, new Checker() { + public boolean check(Result result) { + double r = Double.parseDouble(result.result); + return Math.abs(r - expected) < delta; + } + public String getExpected() { return String.valueOf(expected); } + }); + } + + public void run(int version, Checker checker) { + if (!enabled) { + disabled++; + var s = C_PINK + "[DISA] " + END_COLOR + "[v" + version + "] " + code; + System.out.println(s); + disabledTests.add(s); + return; + } + if (version == -1) { + run_version(10, checker); + run_version(11, checker); + } else { + run_version(version, checker); + } + } + public void run_version(int version, Checker checker) { + tests++; + int aiID = 0; + Result result; + long compile_time = 0; + try { + boolean is_file = code.contains(".leek"); + + AI ai = is_file ? LeekScript.compileFile(code, "AI", version) : LeekScript.compileSnippet(code, "AI"); + aiID = ai.getId(); + + // compile_time = ai.getCompileTime() / 1000000; + // TestCommon.analyze_time += ai.getAnalyzeTime() / 1000000; + // TestCommon.compile_time += ai.getCompileTime() / 1000000; + // TestCommon.load_time += ai.getLoadTime() / 1000000; + + ai.maxOperations = Integer.MAX_VALUE; + + long t = System.nanoTime(); + var v = ai.runIA(); + long exec_time = (System.nanoTime() - t) / 1000; + TestCommon.execution_time += exec_time / 1000; + + var vs = v.getString(ai); + result = new Result(vs, (int) ai.getOperations(), exec_time); + + } catch (Exception e) { + e.printStackTrace(); + result = new Result("", 0, 0); + } + + if (checker.check(result)) { + System.out.println(GREEN_BOLD + " [OK] " + END_COLOR + "[v" + version + "] " + code + " === " + result.result + " " + C_GREY + compile_time + "ms + " + fn(result.exec_time) + "µs" + ", " + fn(result.operations) + " ops" + END_COLOR); + success++; + } else { + var err = C_RED + "[FAIL] " + END_COLOR + "[v" + version + "] " + code + " =/= " + checker.getExpected() + " got " + result.result + "\n" + + "/home/pierre/dev/leek-wars/server/daemon/generator-v1/leekscript-v1/ai/AI_" + aiID + ".java"; + System.out.println(err); + failedTests.add(err); + } + } + } + + public static class Result { + String result; + int operations; + long exec_time; + + public Result(String result, int operations, long exec_time) { + this.result = result; + this.operations = operations; + this.exec_time = exec_time; + } + } + + public static interface Checker { + public boolean check(Result result); + + public String getExpected(); + } + + public Case code(String code) { + return new Case(code, true); + } + public Case file(String code) { + return new Case(code, true); + } + public Case file_v10(String code) { + return new Case(code, true, 10); + } + public Case file_v11(String code) { + return new Case(code, true, 11); + } + public Case DISABLED_file(String code) { + return new Case(code, false); + } + public Case code_v10(String code) { + return new Case(code, true, 10); + } + public Case code_v11(String code) { + return new Case(code, true, 11); + } + public Case DISABLED_code(String code) { + return new Case(code, false); + } + + public void section(String title) { + System.out.println("========== " + title + " =========="); + } + public void header(String title) { + System.out.println("================================================"); + System.out.println("========== " + title + " =========="); + System.out.println("================================================"); + } + + public static boolean summary() { + System.out.println("================================================"); + System.out.println(success + " / " + tests + " tests passed, " + (tests - success) + " errors, " + disabled + " disabled"); + System.out.println("Total time: " + fn(analyze_time + compile_time + execution_time) + " ms" + + " = Analyze: " + fn(analyze_time) + " ms" + + " + Compile: " + fn(compile_time) + " ms" + + " + Execution: " + fn(execution_time) + " ms"); + System.out.println("================================================"); + + for (String test : disabledTests) { + System.out.println(test); + } + for (String test : failedTests) { + System.out.println(test); + } + return success == tests; + } + + public static String fn(long n) { + DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.US); + DecimalFormatSymbols symbols = formatter.getDecimalFormatSymbols(); + + symbols.setGroupingSeparator(' '); + formatter.setDecimalFormatSymbols(symbols); + return formatter.format(n); + } +} diff --git a/src/test/java/test/TestEuler.java b/src/test/java/test/TestEuler.java new file mode 100644 index 00000000..2ce92172 --- /dev/null +++ b/src/test/java/test/TestEuler.java @@ -0,0 +1,42 @@ +package test; + +public class TestEuler extends TestCommon { + + public void run() { + + section("Project Euler"); + file("ai/euler/pe001.leek").equals("233168"); + file("ai/euler/pe002.leek").equals("4613732"); + file("ai/euler/pe003.leek").equals("6857"); + // DISABLED_file("ai/euler/pe004.leek").equals("906609"); + file("ai/euler/pe005.leek").equals("232792560"); + file("ai/euler/pe006.leek").equals("25164150"); + file("ai/euler/pe007.leek").equals("104743"); + // DISABLED_file("ai/euler/pe008.leek").equals("23514624000"); + file("ai/euler/pe009.leek").equals("31875000"); + // DISABLED_file("ai/euler/pe010.leek").equals("142913828922"); + // DISABLED_file("ai/euler/pe011.leek").equals("70600674"); + file("ai/euler/pe012.leek").equals("76576500"); + // DISABLED_file("ai/euler/pe013.leek").equals("5537376230"); + // Too long + DISABLED_file("ai/euler/pe014.leek").equals("837799"); + // DISABLED_file("ai/euler/pe015.leek").equals("137846528820"); + // DISABLED_file("ai/euler/pe016.leek").equals("1366"); + file("ai/euler/pe017.leek").equals("21124"); + file("ai/euler/pe018.leek").equals("1074"); + file("ai/euler/pe019.leek").equals("171"); + // DISABLED_file("ai/euler/pe020.leek").equals("648"); + // file("ai/euler/pe021.leek").equals("31626"); + // file("ai/euler/pe022.leek").equals("871198282"); + // file("ai/euler/pe023.leek").equals("4179871"); + // file("ai/euler/pe024.leek").equals("2783915460"); + // file("ai/euler/pe025.leek").equals("4782"); + // file("ai/euler/pe026.leek").equals(""); + // file("ai/euler/pe027.leek").equals("-59231"); + // file("ai/euler/pe028.leek").equals("669171001"); + // file("ai/euler/pe062.leek").equals("127035954683"); + // file("ai/euler/pe063.leek").equals("49"); + // file("ai/euler/pe064.leek").equals("1322"); + // DISABLED_file("ai/euler/pe206.leek").equals("1389019170"); + } +} diff --git a/src/test/java/test/TestFiles.java b/src/test/java/test/TestFiles.java new file mode 100644 index 00000000..a7e6baee --- /dev/null +++ b/src/test/java/test/TestFiles.java @@ -0,0 +1,49 @@ +package test; + +public class TestFiles extends TestCommon { + + public void run() { + + /** Complex codes */ + header("Files"); + section("General"); + file_v11("ai/code/primes.leek").equals("78498"); + // DISABLED_file("test/code/primes_gmp.leek").equals("9591"); + file("ai/code/gcd.leek").equals("151"); + file("ai/code/strings.leek").equals("true"); + file("ai/code/reachable_cells.leek").equals("383"); + file("ai/code/french.leek").equals("cent-soixante-huit millions quatre-cent-quatre-vingt-neuf-mille-neuf-cent-quatre-vingt-dix-neuf"); + // DISABLED_file("test/code/break_and_continue.leek").equals("2504"); + file("ai/code/french.min.leek").equals("neuf-cent-quatre-vingt-sept milliards six-cent-cinquante-quatre millions trois-cent-vingt-et-un-mille-douze"); + // file("test/code/quine.leek").quine(); + // file_v1("test/code/quine_zwik.leek").quine(); + // file("test/code/dynamic_operators").works(); + // file("ai/code/euler1.leek").equals("2333316668"); + // DISABLED_file("ai/code/text_analysis.leek").equals("[3, 47, 338]"); + // DISABLED_file("ai/code/divisors.leek").equals("[1, 3, 9, 13, 17, 39]"); + // DISABLED_file("test/code/two_functions.leek").equals("[{p: 2, v: 5}, [{p: 3, v: 6}]]"); + // file("test/code/product_n.leek").equals("5040"); + // file("test/code/product_n_return.leek").equals("265252859812191058636308480000000"); + // file("test/code/product_n_arrays.leek").equals("[5040]"); + // file("test/code/product_coproduct.leek").equals("171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000"); + // file("test/code/fold_left.leek").equals("[{w: 1}, {w: 3}, {w: 4}, {w: 2}, {w: 7}, {w: 5}, {w: 8}, {w: 9}, {w: 6}]"); + // file("test/code/fold_left_2.leek").equals("{p: 6, v: {p: 9, v: {p: 8, v: {p: 5, v: {p: 7, v: { ... }}}}}}"); + // file("test/code/fold_right.leek").equals("[{w: 6}, {w: 9}, {w: 8}, {w: 5}, {w: 7}, {w: 2}, {w: 4}, {w: 3}, {w: 1}]"); + // file("test/code/fold_right_2.leek").equals("{p: {p: {p: {p: {p: { ... }, v: 7}, v: 2}, v: 4}, v: 3}, v: 1}"); + file("ai/code/assignments.leek").equals("15"); + file("ai/code/recursive_2_vars.leek").equals("1021"); + file("ai/code/global_functions_1.leek").equals("false"); + file("ai/code/global_functions_2.leek").equals("[false, true]"); + file("ai/code/recursive_2_functions.leek").equals("10"); + // DISABLED_file("test/code/recursive_2_versions.leek").equals("9.5"); + // DISABLED_file("test/code/swap.leek").equals("[{p: 1}, {p: 3}, {p: 4}, {p: 12}, {p: 5}]"); + file_v11("ai/code/classes_simple.leek").equals("[Ferrari, Maserati, Lamborghini]"); + file_v11("ai/code/classes_multiple.leek").equals("[4, 40, 80]"); + // DISABLED_file("test/code/match.leek").output("Yeah!\n"); + file("ai/code/fibonacci.leek").equals("832040"); + // file("ai/code/fibonacci_long.leek").equals("1346269"); + // file("ai/code/pow5.leek").equals("6938893903907228377647697925567626953125"); + file("ai/code/tarai.leek").equals("16"); + file("ai/code/return_in_function.leek").equals("2"); + } +} diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java new file mode 100644 index 00000000..3b862a7b --- /dev/null +++ b/src/test/java/test/TestFunction.java @@ -0,0 +1,49 @@ +package test; + +public class TestFunction extends TestCommon { + + public void run() { + + section("Recursive"); + code("var fact = function(x) { if (x == 1) { return 1 } else { return fact(x - 1) * x } } return fact(8);").equals("40320"); + // code("var fact = function(x) { if (x == 1) { return 1m } else { return fact(x - 1) * x } } return fact(30m);").equals("265252859812191058636308480000000"); + // code("var fact = function(x) { if (x == 1) { 1m } else { fact(x - 1) * x } } return fact(30);").equals("265252859812191058636308480000000"); + code("var fact = function(x) { if (x > 1) { return fact(x - 1) * x } else { return 1 } } return fact(10);").equals("3628800"); + code("var fib = function(n) { if (n <= 1) { return n } else { return fib(n - 1) + fib(n - 2) } } return fib(25);").equals("75025"); + // code("var fact = x -> if x > 1 x * fact(x - 1) else x fact(5)").equals("120"); + // code("var test = x -> if x > 0 { test(x - 1) } else { 77 } test(4)").equals("77"); + // code("var fact = (x, a) -> { if x == 0 then return a end return fact(x - 1, x * a) } fact(10, 1)").equals("3628800"); + // code("var fact = (x, a) -> { if x == 0m then return a end return fact(x - 1, x * a) } fact(10m, 1m)").equals("3628800"); + // code("function test() { var fact = x -> if x == 1 { 1 } else { fact(x - 1) * x } fact(8) } test()").equals("40320"); + file_v10("ai/code/knapsack.leek").equals("761"); + file_v11("ai/code/knapsack_11.leek").equals("761"); + + section("Redefinition"); + code("var count = count([1, 2, 3]) return count;").equals("3"); + + section("System function as argument"); + code_v10("function t(@f) { return function(@a) { return arrayMap(a, f); } } return t(sqrt)([1, 4, 9, 16, 25]);").equals("[1, 2, 3, 4, 5]"); + code_v11("function t(f) { return function(a) { return arrayMap(a, f); } } return t(sqrt)([1, 4, 9, 16, 25]);").equals("[1.0, 2.0, 3.0, 4.0, 5.0]"); + + section("Single null argument"); + code("function f(a) { return 12; } return f(null);").equals("12"); + code("var fa = [function(a) { return 12; }] return fa[0](null);").equals("12"); + + section("Capture argument"); + code_v10("function f(@a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("12"); + code_v11("function f(a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("10"); + code_v10("var f = function(@a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("12"); + code_v11("var f = function(a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("10"); + + code("function f(x) { var s = 0 s |= 12 return s } f(12);").equals("null"); + code("function te(a){ return function(){ return a**2; }; } return te(2)();").equals("4"); + code("function te(a){ return function(b){ return function(c){return a*b*c;}; }; } return te(2)(1)(2);").equals("4"); + code("var tab = [2, 3, 4, 5, 6]; var r = []; for (var i : var j in tab) { r[i] = function() { return j; }; } return 4;").equals("4"); + code_v10("var retour = [];for(var i=0;i<5;i++){if(i&1){var sqrt=function(e){return 1;}; push(retour, sqrt(4));}else{push(retour, sqrt(4));}}return string(retour);").equals("[2, 1, 2, 1, 2]"); + code_v11("var retour = [];for(var i=0;i<5;i++){if(i&1){var sqrt=function(e){return 1;}; push(retour, sqrt(4));}else{push(retour, sqrt(4));}}return string(retour);").equals("[2.0, 1, 2.0, 1, 2.0]"); + + section("Modify argument"); + code("function test(x) { x += 10 return x } return test(5)").equals("15"); + code("var a = [1, 2, 3] function test(x) { push(x, 10) return x } return [a, test([])]").equals("[[1, 2, 3], [10]]"); + } +} diff --git a/src/test/java/test/TestGeneral b/src/test/java/test/TestGeneral new file mode 100644 index 00000000..748d0901 --- /dev/null +++ b/src/test/java/test/TestGeneral @@ -0,0 +1,278 @@ +package test; + +import leekscript.LSException; +import leekscript.compiler.LeekScript; +import leekscript.compiler.exceptions.LeekCompilerException; +import leekscript.functions.VariableOperations; +import leekscript.runner.LeekConstants; +import leekscript.runner.values.ArrayLeekValue; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.alibaba.fastjson.JSONObject; + +public class TestGeneral { + + TestAI ai; + + @Before + public void init() throws Exception { + ai = new TestAI(); + } + + @Test + public void lsOperationsTest() throws Exception { + VariableOperations op = new VariableOperations(JSONObject.parseObject("{\"1\":\"50\",\"10\":\"100\",\"50\":\"1000\",\"100\":\"5000\"}")); + System.out.println(op.getOperations(501)); + } + + @Test + public void ternaireBisTest() throws Exception { + Assert.assertFalse(LeekScript.testScript("return (1 & 2 ? 'coucou');", false)); + } + + @Test + public void incrementTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var u=0; return 1*u++ +2-2;", 0)); + } + + @Test + public void decrementTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var u=2; return 1*u--+2-2;", 2)); + } + + @Test + public void preIncrementTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var u=0; return 1*++u+2-2;", 1)); + } + + @Test + public void preDecrementTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var u=2; return 1*--u+2-2;", 1)); + } + + @Test + public void tripleEqualsTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("return 1 === true;", false)); + } + + @Test + public void ternaireTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var t = true; return t === 2?6:2*4;", 8)); + } + + @Test + public void anonymousFunctionTest() throws Exception { + Assert.assertTrue(LeekScript.testScript(10, "var test = function(@a) { a = 8; }; var test2 = function(b, d) { var c = 1; d(c); return c; }; return test2(1, test);", 8)); + } + + @Test + public void conditionTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var test = 8; if(test == 7) return 1; else if(test == 8) return 2; else return 3;", 2)); + } + + @Test + public void foreachTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var test = [0,1,2,3,4,5]; var retour = \"\"; for(var i in test){ retour += i; } return retour;", + "012345")); + } + + @Test + public void foreachGlobalTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("global i; var test = [0,1,2,3,4,5]; var retour = \"\"; for(i in test){ retour += i; } return retour;", + "012345")); + } + + @Test + public void foreachkeyvalTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var test = ['a':5,'b':8,'c':8,9:'p']; var retour = \"\"; for(var i : var j in test){ retour += i+':'+j; } return retour;", + "a:5b:8c:89:p")); + } + + @Test + public void foreachkeyvalGlobalTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("global i,j; var test = ['a':5,'b':8,'c':8,9:'p']; var retour = \"\"; for(i : j in test){ retour += i+':'+j; } return retour;", + "a:5b:8c:89:p")); + } + + @Test + public void forTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("for(var i=0;i<1000;i++){}", null)); + } +/* + @Test + public void forGlobalTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("global i; for(i=0;i<1000;i++){}", null)); + } +*/ + + @Test + public void functionGlobalTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("function testi() { var tab=[1,5]; for (i in tab) debug(i); } global i;", null)); + } + + @Test + public void foreach() throws Exception { + Assert.assertTrue(LeekScript.testScript( + "var a = [1, 2, 3, 4, 5] var s = 0 for (var i in a) { s += i } return s;", 15)); + + Assert.assertTrue(LeekScript.testScript(10, + "var a = [1, 2, 3, 4, 5] var s = 0 for (var i in a) { s += i } return s;", 15)); + + // Assert.assertTrue(LeekScript.testScript(10, "var a = [1, 2, 3, 4, 5] var i var s = 0 for (i in a) { s += i } return s;", 15)); + + Assert.assertTrue(LeekScript.testScript(10, + "var a = [1, 2, 3, 4, 5] var s = 0 for (var i : var j in a) { s += i * j } return s;", 40)); + + Assert.assertTrue(LeekScript.testScript(10, + "var a = [[1], [2], [3], [4], [5]] var s = 0 for (var i : var j in a) { s += i } return s;", 10)); + + Assert.assertTrue(LeekScript.testScript(10, + "var a = [[1], [2], [3], [4], [5]] var s = 0 for (var i : var j in a) { push(j, 12) s += i * count(j) } return s;", 20)); + + Assert.assertTrue(LeekScript.testScript(10, + "var a = [[1], [2], [3], [4], [5]] var s = 0 for (var i in a) { push(i, 12) s += count(i) } return s;", 10)); + } + + @Test + public void whileTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var i = 0; while(i<1000){ i++; }", null)); + } + + // Test simples d'opérateurs + @Test + public void additionTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var test = 1 + 8; test += 3; test++; var a = 7; var b = 1; return [test, a+b, (1+1)+9.5, 'test'+8];", + new ArrayLeekValue(ai, new Object[] { 13, 8, 11.5, "test8" }))); + } + + @Test + public void soustractionTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var test = 20 - 8; test -= 3; test--; var a = 7; var b = 1; return [test, a-b, (1-1)-9.5];", + new ArrayLeekValue(ai, new Object[] { + 8, 6, -9.5 }))); + } + + @Test + public void multiplicationTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var test = 4; test *= 3; var c = 7;return [test, 8*9, 2*c];", + new ArrayLeekValue(ai, new Object[] { 12, 72, 14 }))); + } + + @Test + public void modulusTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var test = 4; test %= 3; var c = 7;return [test, 8%9, 8%c];", + new ArrayLeekValue(ai, new Object[] { 1, + 8, 1 }))); + } + + @Test + public void divisionTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var test = 7; test /= 2; var c = 7;return [test, 12/6, 14/c];", + new ArrayLeekValue(ai, new Object[] { 3.5, 2, 2 }))); + } + + @Test + public void operatorsTest() throws Exception { + Object[] values = new Object[] { true, false, true, false, false, true, false }; + Assert.assertTrue(LeekScript.testScript("return [true && true, true && false, true || false, false || false, 1 > 3, 1 < 3, 4 == 7];", + new ArrayLeekValue(ai, values))); + } + + @Test + public void prioritiesTest() throws Exception { + Object[] values = new Object[] { + // 1+6*2 - 3*2 + 7, + // 7*8 - 1 + 55, + // 3*3 - 8 > 0 + true, + // 7*8 == 56 && 33 -8 + true }; + Assert.assertTrue(LeekScript.testScript("return [1+6*2-3*2,7*8-1, 3*3-8>0, 7*8 == 56 && 33-8 ];", + new ArrayLeekValue(ai, values))); + } + + // Test un peu plus poussés + @Test + public void functionTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("function test(a){ return a+2; } return test(7);", 9)); + } + + @Test + public void divisionByZeroTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("return 8/0;", null)); + Assert.assertTrue(LeekScript.testScript("return 8/null;", null)); + } + + @Test + public void whileReturnTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var t = 0; while(t<5){ t++; return t;}", 1)); + Assert.assertTrue(LeekScript.testScript("var t = 0; while(t<5){ t++; return t;} return 0;", 1)); + } + + @Test + public void doWhileReturnTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var t = 0; do { t++; return t; } while (t < 5);", 1)); + Assert.assertFalse(LeekScript.testScript("var t = 0; do { t++; return t; } while (t < 5); return 2;", 1)); + } + + @Test + public void forReturnTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("for(var i=0;i<3;i++){ return i; }", 0)); + Assert.assertTrue(LeekScript.testScript("for(var i=0;i<3;i++){ return i; } return 2;", 0)); + } + + @Test + public void anonymousTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("function te(a){ return function(){ return a**2; }; } return te(2)();", 4)); + } + + @Test + public void anonymous2Test() throws Exception { + Assert.assertTrue(LeekScript.testScript("function te(a){ return function(b){ return function(c){return a*b*c;}; }; } return te(2)(1)(2);", 4)); + } + + @Test + public void conditionalTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var test = 0; if(false) if(true) test = 3; else test = 1; return test;", 0)); + } + + @Test + public void forEachReturnTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var tab = [0,1,2,3]; for(var i in tab){ return i; }", 0)); + Assert.assertTrue(LeekScript.testScript("var tab = [0,1,2,3]; for(var i in tab){ return i; } return 5;", 0)); + } + + @Test + public void forEachKeyReturnTest() throws Exception { + Assert.assertTrue(LeekScript.testScript("var tab = [1:0,2:1,3:2,4:3]; for(var i : var j in tab){ return i; } ", 1)); + Assert.assertTrue(LeekScript.testScript("var tab = [1:0,2:1,3:2,4:3]; for(var i : var j in tab){ return i; } return 0;", 1)); + } + + + @Test + public void testAnonymousFunctioNSelfAccess() throws Exception { + String leekscript = "var t = function(){ return t; };"; + LeekScript.testScript(leekscript, null); + } + + @Test + public void stringTest() throws Exception { + ArrayList codes = new ArrayList(); + ArrayList values = new ArrayList(); + + // Test nombre + codes.add("'\\\\'"); + values.add("\\"); + + // Test AI + Assert.assertTrue(testAI(codes, values)); + } +} diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index 30273490..2ec56e0d 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -1,472 +1,38 @@ package test; -import leekscript.LSException; -import leekscript.compiler.LeekScript; -import leekscript.compiler.exceptions.LeekCompilerException; -import leekscript.functions.VariableOperations; import leekscript.runner.LeekConstants; -import leekscript.runner.values.AbstractLeekValue; -import leekscript.runner.values.ArrayLeekValue; -import leekscript.runner.values.BooleanLeekValue; -import leekscript.runner.values.DoubleLeekValue; -import leekscript.runner.values.IntLeekValue; -import leekscript.runner.values.NullLeekValue; -import leekscript.runner.values.StringLeekValue; -import java.util.ArrayList; -import java.util.List; +public class TestGeneral extends TestCommon { -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.alibaba.fastjson.JSONObject; - -public class TestGeneral { - - TestAI ai; - - @Before - public void init() throws Exception { - ai = new TestAI(); - } - - @Test - public void lsOperationsTest() throws Exception { - VariableOperations op = new VariableOperations(JSONObject.parseObject("{\"1\":\"50\",\"10\":\"100\",\"50\":\"1000\",\"100\":\"5000\"}")); - System.out.println(op.getOperations(501)); - } - - @Test - public void ternaireBisTest() throws Exception { - try { - LeekScript.testScript("return (1&2?'coucou');", new BooleanLeekValue(false)); - Assert.fail("Compilation validée..."); - } catch (LeekCompilerException exp) { - return; - } catch (Exception e) { - Assert.fail("Compilation validée..."); - } - } - - @Test - public void incrementTest() throws Exception { - Assert.assertTrue(testScript("var u=0; return 1*u++ +2-2;", new IntLeekValue(0))); - } - - @Test - public void decrementTest() throws Exception { - Assert.assertTrue(testScript("var u=2; return 1*u--+2-2;", new IntLeekValue(2))); - } - - @Test - public void preIncrementTest() throws Exception { - Assert.assertTrue(testScript("var u=0; return 1*++u+2-2;", new IntLeekValue(1))); - } - - @Test - public void preDecrementTest() throws Exception { - Assert.assertTrue(testScript("var u=2; return 1*--u+2-2;", new IntLeekValue(1))); - } - - @Test - public void tripleEqualsTest() throws Exception { - Assert.assertTrue(testScript("return 1 === true;", new BooleanLeekValue(false))); - } - - @Test - public void ternaireTest() throws Exception { - Assert.assertTrue(testScript("var t = true; return t === 2?6:2*4;", 8)); - } - - @Test - public void anonymousFunctionTest() throws Exception { - Assert.assertTrue(testScript("var test = function(@a){ a = 8; }; var test2 = function(b, d){ var c = 1; d(c); return c; }; return test2(1, test);", 8)); - } - - @Test - public void conditionTest() throws Exception { - Assert.assertTrue(testScript("var test = 8; if(test == 7) return 1; else if(test == 8) return 2; else return 3;", new IntLeekValue(2))); - } - - @Test - public void foreachTest() throws Exception { - Assert.assertTrue(testScript("var test = [0,1,2,3,4,5]; var retour = \"\"; for(var i in test){ retour += i; } return retour;", - new StringLeekValue("012345"))); - } - - @Test - public void foreachGlobalTest() throws Exception { - Assert.assertTrue(testScript("global i; var test = [0,1,2,3,4,5]; var retour = \"\"; for(i in test){ retour += i; } return retour;", - new StringLeekValue("012345"))); - } - - @Test - public void foreachkeyvalTest() throws Exception { - Assert.assertTrue(testScript("var test = ['a':5,'b':8,'c':8,9:'p']; var retour = \"\"; for(var i : var j in test){ retour += i+':'+j; } return retour;", - new StringLeekValue("a:5b:8c:89:p"))); - } - - @Test - public void foreachkeyvalGlobalTest() throws Exception { - Assert.assertTrue(testScript("global i,j; var test = ['a':5,'b':8,'c':8,9:'p']; var retour = \"\"; for(i : j in test){ retour += i+':'+j; } return retour;", - new StringLeekValue("a:5b:8c:89:p"))); - } - - @Test - public void forTest() throws Exception { - Assert.assertTrue(testScript("for(var i=0;i<1000;i++){}", new NullLeekValue())); - } - - @Test - public void forGlobalTest() throws Exception { - Assert.assertTrue(testScript("global i; for(i=0;i<1000;i++){}", new NullLeekValue())); - } - - @Test - public void functionGlobalTest() throws Exception { - Assert.assertTrue(testScript("function testi() { var tab=[1,5]; for (i in tab) debug(i); } global i;", new NullLeekValue())); - } - - @Test - public void whileTest() throws Exception { - Assert.assertTrue(testScript("var i = 0; while(i<1000){ i++; }", new NullLeekValue())); - } - - @Test - public void dowhileTest() throws Exception { - Assert.assertTrue(testScript("var i = 0; do{ i++; } while(i < 1000);", new NullLeekValue())); - } - - // Test simples d'opérateurs - @Test - public void additionTest() throws Exception { - Assert.assertTrue(testScript("var test = 1 + 8; test += 3; test++; var a = 7; var b = 1; return [test, a+b, (1+1)+9.5, 'test'+8];", - new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(13), new IntLeekValue(8), new DoubleLeekValue(11.5), - new StringLeekValue("test8") }))); - } - - @Test - public void soustractionTest() throws Exception { - Assert.assertTrue(testScript("var test = 20 - 8; test -= 3; test--; var a = 7; var b = 1; return [test, a-b, (1-1)-9.5];", - new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(8), new IntLeekValue(6), new DoubleLeekValue(-9.5) }))); - } - - @Test - public void multiplicationTest() throws Exception { - Assert.assertTrue(testScript("var test = 4; test *= 3; var c = 7;return [test, 8*9, 2*c];", - new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(12), - new IntLeekValue(72), new DoubleLeekValue(14) }))); - } - - @Test - public void modulusTest() throws Exception { - Assert.assertTrue(testScript("var test = 4; test %= 3; var c = 7;return [test, 8%9, 8%c];", - new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(1), - new IntLeekValue(8), new DoubleLeekValue(1) }))); - } - - @Test - public void divisionTest() throws Exception { - Assert.assertTrue(testScript("var test = 7; test /= 2; var c = 7;return [test, 12/6, 14/c];", - new ArrayLeekValue(ai, new AbstractLeekValue[] { new DoubleLeekValue(3.5), - new IntLeekValue(2), new DoubleLeekValue(2) }))); - } - - @Test - public void operatorsTest() throws Exception { - AbstractLeekValue[] values = new AbstractLeekValue[] { new BooleanLeekValue(true), new BooleanLeekValue(false), - new BooleanLeekValue(true), new BooleanLeekValue(false), - - new BooleanLeekValue(false), new BooleanLeekValue(true), new BooleanLeekValue(false) }; - Assert.assertTrue(testScript("return [true && true, true && false, true || false, false || false, 1 > 3, 1 < 3, 4 == 7];", - new ArrayLeekValue(ai, values))); - } - - @Test - public void prioritiesTest() throws Exception { - AbstractLeekValue[] values = new AbstractLeekValue[] { - // 1+6*2 - 3*2 - new IntLeekValue(7), - // 7*8 - 1 - new IntLeekValue(55), - // 3*3 - 8 > 0 - new BooleanLeekValue(true), - // 7*8 == 56 && 33 -8 - new BooleanLeekValue(true) }; - Assert.assertTrue(testScript("return [1+6*2-3*2,7*8-1, 3*3-8>0, 7*8 == 56 && 33-8 ];", - new ArrayLeekValue(ai, values))); - } - - // Test un peu plus poussés - @Test - public void functionTest() throws Exception { - Assert.assertTrue(testScript("function test(a){ return a+2; } return test(7);", 9)); - } - - @Test - public void divisionByZeroTest() throws Exception { - Assert.assertTrue(testScript("return 8/0;", null)); - Assert.assertTrue(testScript("return 8/null;", null)); - } - - @Test - public void whileReturnTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var t = 0; while(t<5){ t++; return t;}", new IntLeekValue(1))); - Assert.assertTrue(LeekScript.testScript("var t = 0; while(t<5){ t++; return t;} return 0;", new IntLeekValue(1))); - } - - @Test - public void doWhileReturnTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var t = 0; do{ t++; return t;}while(t<5);", new IntLeekValue(1))); - try { - LeekScript.testScript("var t = 0; do{ t++; return t;}while(t<5); return 2;", new IntLeekValue(1)); - Assert.fail("Compilation validée..."); - } catch (LeekCompilerException e) { - return; - } catch (Exception e) { - Assert.fail("Compilation validée..."); - } - } - - @Test - public void forReturnTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("for(var i=0;i<3;i++){ return i; }", new IntLeekValue(0))); - Assert.assertTrue(LeekScript.testScript("for(var i=0;i<3;i++){ return i; } return 2;", new IntLeekValue(0))); - } - - @Test - public void anonymousTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("function te(a){ return function(){ return a**2; }; } return te(2)();", new IntLeekValue(4))); - } - - @Test - public void anonymous2Test() throws Exception { - Assert.assertTrue(LeekScript.testScript("function te(a){ return function(b){ return function(c){return a*b*c;}; }; } return te(2)(1)(2);", new IntLeekValue(4))); - } - - @Test - public void anonymous3Test() throws Exception { - Assert.assertTrue(LeekScript.testScript("var tab = [2,3,4,5,6];var r = [];for(var i: var j in tab){ r[i] = function(){ return j; };}return 4;", new IntLeekValue(4))); - } - - @Test - public void conditionalTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var test = 0; if(false) if(true) test = 3; else test = 1; return test;", new IntLeekValue(0))); - } - - @Test - public void forEachReturnTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var tab = [0,1,2,3]; for(var i in tab){ return i; }", new IntLeekValue(0))); - Assert.assertTrue(LeekScript.testScript("var tab = [0,1,2,3]; for(var i in tab){ return i; } return 5;", new IntLeekValue(0))); - } - - @Test - public void forEachKeyReturnTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var tab = [1:0,2:1,3:2,4:3]; for(var i : var j in tab){ return i; } ", new IntLeekValue(1))); - Assert.assertTrue(LeekScript.testScript("var tab = [1:0,2:1,3:2,4:3]; for(var i : var j in tab){ return i; } return 0;", new IntLeekValue(1))); - } - - @Test - public void testReference() throws Exception { - String leekscript = "var t = [3,4,5]; t[3]=[1,2,3,4]; var r = @t[3]; r[4] ='prou3t'; return t;"; - LeekScript.testScript(leekscript, new NullLeekValue()); - } - - @Test - public void testAnonymousFunctioNSelfAccess() throws Exception { - String leekscript = "var t = function(){ return t; };"; - LeekScript.testScript(leekscript, new NullLeekValue()); - } - - @Test - public void testIfIfNot() { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("function(){ var a = 1; if(a is 1) return 2; else return 0;}()"); - values.add(2); - - codes.add("function(){ var a = 1; if(a is 2) return 2; else return 0;}()"); - values.add(0); - - codes.add("function(){ var a = 1; if(a is not 2) return 2; else return 0;}()"); - values.add(2); - - codes.add("function(){ var a = 1; if(a is not 1) return 2; else return 0;}()"); - values.add(0); - - codes.add("function(){ var a = true; if(not a) return 2; else return 0;}()"); - values.add(0); - - // Test AI - try { - Assert.assertTrue(testAI(codes, values)); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(); - } - } - - @Test - public void testOperators() { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("function(){ var a = 1; var result = -10 + (1- (a-1)); return result;}()"); - values.add(-9); - - codes.add("function(){ var a = 1; var result = 0; result = -10 + (1- (a-1)); return result;}()"); - values.add(-9); - // Test AI - try { - Assert.assertTrue(testAI(codes, values)); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(); - } - } - - @Test - public void sortTest() throws Exception { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - // Test sort - codes.add("function(){ var t =[null,null,4,8,9]; sort(t); return t;}()"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(4), new IntLeekValue(8), new IntLeekValue(9), new NullLeekValue(), new NullLeekValue() })); - - // Test sort - codes.add("function(){ var t =[4, null, 4, null, 4]; sort(t); return t;}()"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(4), new IntLeekValue(4), new IntLeekValue(4), new NullLeekValue(), new NullLeekValue() })); - - // Test sort desc - codes.add("function(){ var t =[4, null, 5, null, 8]; sort(t,SORT_DESC); return t;}()"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { new NullLeekValue(), new NullLeekValue(), new IntLeekValue(8), new IntLeekValue(5), new IntLeekValue(4) })); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void colorTest() throws Exception { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - // Test color - codes.add("color(255,0,255)"); - values.add(0xFF00FF); - // Test color - codes.add("color(255,255,0)"); - values.add(0xFFFF00); - // Test color - codes.add("color(0,255,255)"); - values.add(0x00FFFF); - - // Red - codes.add("getRed(" + 0xAE0000 + ")"); - values.add(174); - // Green - codes.add("getGreen(" + 0xAF00 + ")"); - values.add(175); - // Blue - codes.add("getBlue(" + 0xAD + ")"); - values.add(173); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - - @Test - public void typeOfTest() throws Exception { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); + public void run() { + section("typeOf()"); // Test nombre - codes.add("typeOf(255)"); - values.add(LeekConstants.TYPE_NUMBER.getIntValue()); - codes.add("typeOf(255.8)"); - values.add(LeekConstants.TYPE_NUMBER.getIntValue()); + code("return typeOf(255)").equals(String.valueOf(LeekConstants.TYPE_NUMBER.getIntValue())); + code("return typeOf(255.8)").equals(String.valueOf(LeekConstants.TYPE_NUMBER.getIntValue())); // Test string - codes.add("typeOf('coucou')"); - values.add(LeekConstants.TYPE_STRING.getIntValue()); + code("return typeOf('coucou')").equals(String.valueOf(LeekConstants.TYPE_STRING.getIntValue())); // Test boolean - codes.add("typeOf(false)"); - values.add(LeekConstants.TYPE_BOOLEAN.getIntValue()); + code("return typeOf(false)").equals(String.valueOf(LeekConstants.TYPE_BOOLEAN.getIntValue())); // Test array - codes.add("typeOf([1,false])"); - values.add(LeekConstants.TYPE_ARRAY.getIntValue()); + code("return typeOf([1,false])").equals(String.valueOf(LeekConstants.TYPE_ARRAY.getIntValue())); // Test fonction - codes.add("typeOf(function(){ return null; })"); - values.add(LeekConstants.TYPE_FUNCTION.getIntValue()); + code("return typeOf(function(){ return null; })").equals(String.valueOf(LeekConstants.TYPE_FUNCTION.getIntValue())); // Test null - codes.add("typeOf(null)"); - values.add(LeekConstants.TYPE_NULL.getIntValue()); + code("return typeOf(null)").equals(String.valueOf(LeekConstants.TYPE_NULL.getIntValue())); // Test piège - codes.add("typeOf(function(){ return 4; }())"); - values.add(LeekConstants.TYPE_NUMBER.getIntValue()); + code("return typeOf(function(){ return 4; }())").equals(String.valueOf(LeekConstants.TYPE_NUMBER.getIntValue())); - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void stringTest() throws Exception { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - // Test nombre - codes.add("'\\\\'"); - values.add("\\"); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - private boolean testAI(List mCodes, List mValues) throws Exception { - String leekscript = "return ["; - AbstractLeekValue[] values = new AbstractLeekValue[mValues.size()]; - - for (int i = 0; i < mValues.size(); i++) { - if (i != 0) - leekscript += ","; - leekscript += mCodes.get(i); - Object c = mValues.get(i); - if (c instanceof Integer) - values[i] = new IntLeekValue(((Integer) mValues.get(i))); - else if (c instanceof Double) - values[i] = new DoubleLeekValue(((Double) mValues.get(i))); - else if (c instanceof String) - values[i] = new StringLeekValue(((String) mValues.get(i))); - else if (c instanceof Boolean) - values[i] = new BooleanLeekValue(((Boolean) mValues.get(i))); - else if (c instanceof AbstractLeekValue) - values[i] = (AbstractLeekValue) mValues.get(i); - else - values[i] = new NullLeekValue(); - } + section("color()"); + code("return color(255,0,255)").equals(String.valueOf(0xFF00FF)); + code("return color(255,255,0)").equals(String.valueOf(0xFFFF00)); + code("return color(0,255,255)").equals(String.valueOf(0x00FFFF)); - leekscript += "];"; - try { - return LeekScript.testScript(leekscript, new ArrayLeekValue(ai, values)); - } catch (LSException e) { - System.err.println("Erreur :\n" + leekscript); - System.err.println("Valeur attendue :\n" + e.getThe().getString(ai)); - System.err.println("Valeur renvoyée :\n" + e.getRun().getString(ai)); - return false; - } - } - - private boolean testScript(String leekscript, AbstractLeekValue value) throws Exception { - if (value == null) - value = new NullLeekValue(); - - return LeekScript.testScript(leekscript, value); - } - - private boolean testScript(String leekscript, int value) throws Exception { - return testScript(leekscript, new IntLeekValue(value)); + // Red + code("return getRed(" + 0xAE0000 + ")").equals("174"); + // Green + code("return getGreen(" + 0xAF00 + ")").equals("175"); + // Blue + code("return getBlue(" + 0xAD + ")").equals("173"); } } diff --git a/src/test/java/test/TestGlobals.java b/src/test/java/test/TestGlobals.java new file mode 100644 index 00000000..86ec6715 --- /dev/null +++ b/src/test/java/test/TestGlobals.java @@ -0,0 +1,35 @@ +package test; + +public class TestGlobals extends TestCommon { + + public void run() throws Exception { + + section("Globals"); + code("global x; return x;").equals("null"); + code("global x = null; return x;").equals("null"); + code("global x = 12; return x;").equals("12"); + code("global x = [1, 2, 3]; return x;").equals("[1, 2, 3]"); + code("global x; x = 12 return x;").equals("12"); + code("global x; x = [1, 2, 3]; return x;").equals("[1, 2, 3]"); + code("var r = x; global x; return r;").equals("null"); + code("var r = x; global x = 12; return r;").equals("null"); + + section("Globals operators"); + code("global x = 12; x++; return x;").equals("13"); + code("global x = 12; x--; return x;").equals("11"); + code("global x = 12; ++x; return x;").equals("13"); + code("global x = 12; --x; return x;").equals("11"); + code("global x = 12; x += 5; return x;").equals("17"); + code("global x = 12; x -= 5; return x;").equals("7"); + code("global x = 12; x *= 5; return x;").equals("60"); + code("global x = 12; x /= 5; return x;").equals("2.4"); + code("global x = 12; x %= 5; return x;").equals("2"); + code("global x = 2; x **= 5; return x;").equals("32"); + code("global x = 12; x |= 5; return x;").equals("13"); + code("global x = 12; x &= 5; return x;").equals("4"); + code_v10("global x = 12; x ^= 5; return x;").equals("248832"); + code_v11("global x = 12; x ^= 5; return x;").equals("9"); + code("global x = 12; return x == 5;").equals("false"); + code("global x = 12; return x === 5;").equals("false"); + } +} \ No newline at end of file diff --git a/src/test/java/test/TestIf.java b/src/test/java/test/TestIf.java new file mode 100644 index 00000000..d127c088 --- /dev/null +++ b/src/test/java/test/TestIf.java @@ -0,0 +1,88 @@ +package test; + +public class TestIf extends TestCommon { + + public void run() throws Exception { + /* + * Conditions + */ + header("Conditions"); + // code("if true then 12 else 5 end").equals("12"); + // code("if false then 12 else 5 end").equals("5"); + code("if (true) { return 12 } else { return 5 }").equals("12"); + code("if (false) { return 12 } else { return 5 }").equals("5"); + // code("let a = if (false) { 12 } else { 5 } a").equals("5"); + // code("let a = if (true) { 'yo' } else { 'hello' } a").equals("'yo'"); + // code("let a = if (true) { 12 } else { 'hello' } a").equals("12"); + // code("let a = if (true) { 'hello' } else { 12 } a").equals("'hello'"); + // code("if (true) {} else {}").equals("{}"); + code("if (true) {;} else {}").equals("null"); + // code("if (true) { {} } else {}").equals("{}"); + code("if (true) null else {}").equals("null"); + // code("if true").error(ls::Error::UNEXPECTED_TOKEN, {""}); + // code("if true else").error(ls::Error::UNEXPECTED_TOKEN, {"else"}); + // code("if (true) {a: 12} else {b: 5}").equals("{a: 12}"); + // code("if (true) { {a: 12} } else { {b: 5} }").equals("{a: 12}"); + code("if (true) return 12 else return 5;").equals("12"); + code("if (false) return 12 else return 5;").equals("5"); + code("if (true) return 12;").equals("12"); + code("if (false) return 12;").equals("null"); + // code("if true then 12 end").equals("12"); + // code("if false then 12 end").equals("null"); + // code("if (true) { 5 } else { return 2 }").equals("5"); + code("if (true) { return 5 } else { 2 }").equals("5"); + code("if (false) { 5 } else { return 2 }").equals("2"); + // code("if (false) { return 5 } else { 2 }").equals("2"); + // code("let a = 5m if true { a } else { 2m }").equals("5"); + // code("let a = 5m if true { a } else { a }").equals("5"); + // code("if true then 1 else 2 end").equals("1"); + // code("if true then if false then 1 else 2 end end").equals("2"); + // code("if true then if false then 1 end else 2 end").equals("null"); + code("if (false) { return 12 } return 5;").equals("5"); + code("var k = '121212' if (false) { return 12 } return 5;").equals("5"); + code("var L = 5 if (L < 1) {;}").equals("null"); + code("var L = 5 if (L > 1) {;}").equals("null"); + code("if (false) { return 'hello' }").equals("null"); + // code("let x = { if 1 2 else 3 } let y = { if x == 0 { 'error' } else { 8 * x } } y").equals("16"); + code("var test = 0; if(false) if(true) test = 3; else test = 1; return test;").equals("0"); + + code("var a = 1; if(a is 1) return 2; else return 0").equals("2"); + code("var a = 1; if(a is 2) return 2; else return 0").equals("0"); + code("var a = 1; if(a is not 2) return 2; else return 0").equals("2"); + code("var a = 1; if(a is not 1) return 2; else return 0").equals("0"); + code("var a = true; if(not a) return 2; else return 0").equals("0"); + code("var Bob = 12 if (Bob = 75);").equals("null"); + + section("Conditions with other types"); + code("if (1212) { return 'ok' } else { return 5 }").equals("ok"); + code("if (['str', true][0]) { return 12 } else { return 5 }").equals("12"); + code("if (null) { return 12 } else { return 5 }").equals("5"); + + section("Different branch types"); + code("if (1) return ['a'] else if (0) return [2] else return [5.5];").equals("[a]"); + code("if (0) return ['a'] else if (1) return [2] else return [5.5];").equals("[2]"); + code_v10("if (0) return ['a'] else if (0) return [2] else return [5.5];").equals("[5,5]"); + code_v11("if (0) return ['a'] else if (0) return [2] else return [5.5];").equals("[5.5]"); + + section("Ternary conditions"); + code("return true ? 5 : 12;").equals("5"); + code("return false ? 5 : 12;").equals("12"); + code("return true ? 'a' : 'b';").equals("a"); + code("return false ? 'a' : 'b';").equals("b"); + code("return true ? 'a' : 5;").equals("a"); + code("return false ? 'a' : 5;").equals("5"); + code("return true ? 5 : 'b';").equals("5"); + code("return false ? 5 : 'b';").equals("b"); + code("return 'good' ? 5 : 12;").equals("5"); + code("return '' ? 5 : 12;").equals("12"); + code("return 'good' ? 'a' : 'b';").equals("a"); + code("return true ? true ? 5 : 12 : 7;").equals("5"); + code("return true ? false ? 5 : 12 : 7;").equals("12"); + code("return false ? false ? 5 : 12 : 7;").equals("7"); + code("return false ? true ? 5 : 12 : 7;").equals("7"); + code("return true ? true ? true ? 5 : 12 : 7 : 8;").equals("5"); + code("return true ? true ? false ? 5 : 12 : 7 : 8;").equals("12"); + code("return true ? false ? false ? 5 : 12 : 7 : 8;").equals("7"); + code("return (5 > 10) ? 'a' : (4 == 2 ** 2) ? 'yes' : 'no';").equals("yes"); + } +} \ No newline at end of file diff --git a/src/test/java/test/TestLoops.java b/src/test/java/test/TestLoops.java new file mode 100644 index 00000000..2bc49e57 --- /dev/null +++ b/src/test/java/test/TestLoops.java @@ -0,0 +1,222 @@ +package test; + +public class TestLoops extends TestCommon { + + public void run() { + + /* + * While loops + */ + section("While loops"); + code("var i = 0 while (i < 10) { i++ } return i;").equals("10"); + code("var i = 0 var s = 0 while (i < 10) { s += i i++ } return s;").equals("45"); + code("var i = 0 while (i < 100) { i++ if (i == 50) break } return i;").equals("50"); + code("var i = 0 var a = 0 while (i < 10) { i++ if (i < 8) continue a++ } return a;").equals("3"); + code("while (true) { break }").equals("null"); + code("var i = 10 while (['hello', i][1]) { i-- } return i;").equals("0"); + code("var i = 0 while (i < 10) i++ return i;").equals("10"); + // code("var i = 5 while (i-- > 0) { System.print(i) }").output("4\n3\n2\n1\n0\n"); + code("while (true) { return 12 }").equals("12"); + code("var n = 5 var a = [] while (n--) { push(a, 1) }").equals("null"); + code("var n = 5 var a = [] while (n--) { push(a, 1) } return a;").equals("[1, 1, 1, 1, 1]"); + code("var n = 5 var a = [] while (n--) { push(a, 1) } return a;").equals("[1, 1, 1, 1, 1]"); + code("var mp = 10, grow = [100] while (mp--) { grow = [1] } return grow;").equals("[1]"); + // DISABLED_code("var a = [] while |a += 'a'| < 5 { a += 'b' } return a;").equals("['a', 'b', 'a', 'b', 'a']"); + code("var s = 0 var j = [] while (count(j) < 10) { push(j, 'a') s++ } return s;").equals("10"); + // DISABLED_code("var s = [] var i = 10 while (i--) { if i < 5 { s += i } else { s += ('a'.code() + i).char() } } return s;").equals("['j', 'i', 'h', 'g', 'f', 4, 3, 2, 1, 0]"); + // DISABLED_code("var s = <> var i = 10 while (i--) { if i < 5 { s += i } else { s += ('a'.code() + i).char() } } return s;").equals("<0, 1, 2, 3, 4, 'f', 'g', 'h', 'i', 'j'>"); + // DISABLED_code("var s = [:] var i = 10 while (i--) { if i < 5 { s[i] = 5.5 } else { s['a'] = i } } return s;").equals("[0: 5.5, 1: 5.5, 2: 5.5, 3: 5.5, 4: 5.5, 'a': 5]"); + // DISABLED_code("var s = [:] var i = 10 while (i--) { if i < 5 { s[i] = 12 } else { s[1 / i] = 7 } } return s;").equals("[0: 12, 0.111111: 7, 0.125: 7, 0.142857: 7, 0.166667: 7, 0.2: 7, 1: 12, 2: 12, 3: 12, 4: 12]"); + // DISABLED_code("var s = [:] var i = 10 while (i--) { if i < 5 { s[i] = 12 } else { s[12] = i } } return s;").equals("[0: 12, 1: 12, 2: 12, 3: 12, 4: 12, 12: 5]"); + // DISABLED_code("var a = 5 while (a-- > 0);").equals("null"); + code("var i = 10 while (i--); return i;").equals("-1"); + code("var i = 10 while (--i); return i;").equals("0"); + code("var t = 0; while(t<5){ t++; return t;}").equals("1"); + code("var t = 0; while(t<5){ t++; return t;} return 0;").equals("1"); + + section("Double while loops"); + code("var s = [] var i = 0 while (i < 2) { i++ var j = 0 while (j < 3) { j++ push(s, j) }} return s;").equals("[1, 2, 3, 1, 2, 3]"); + code("var s = [] var i = 0 var j = 0 while (i < 2) { i++ j = 0 while (j < 3) { j++ push(s, j) }} return s;").equals("[1, 2, 3, 1, 2, 3]"); + code("var s = [] var i = 0 var j = 0 while (i < 4) { j = i i++ while (j < 4) { j++ push(s, j) }} return s;").equals("[1, 2, 3, 4, 2, 3, 4, 3, 4, 4]"); + code("var s = [] var i = 0 while (i < 2) { i++ var j = 0 while (j < 2) { j++ var k = 0 while (k < 2) { k++ push(s, k) }}} return s;").equals("[1, 2, 1, 2, 1, 2, 1, 2]"); + code_v10("var s = [] var i = 0 while (i < 2) { i++ push(s, 0.5) var j = 0 while (j < 3) { j++ push(s, j) }} return s;").equals("[0,5, 1, 2, 3, 0,5, 1, 2, 3]"); + code_v11("var s = [] var i = 0 while (i < 2) { i++ push(s, 0.5) var j = 0 while (j < 3) { j++ push(s, j) }} return s;").equals("[0.5, 1, 2, 3, 0.5, 1, 2, 3]"); + // DISABLED_code("var s = [] var i = 0 while (i < 2) { i++ s.push([]) var j = 0 while j < 3 { j++ s[|s| - 1] += 1 }} s").equals("[[1, 1, 1], [1, 1, 1]]"); + // DISABLED_code("var s = [] var i = 0 while (i < 2) { i++ s.push([]) var j = 0 while j < 3 { j++ s[|s| - 1] += ('a'.code() + 3 * (i - 1) + j - 1).char() }} s").equals("[['a', 'b', 'c'], ['d', 'e', 'f']]"); + // file("test/code/loops/lot_of_whiles_int.leek").equals("30030"); + // file("test/code/loops/lot_of_whiles_array.leek").equals("30030"); + + section("Do while"); + code("var i = 0 do { i++ } while (i < 10); return i;").equals("10"); + code("var i = 0 var s = 0 do { s += i i++ } while (i < 10); return s;").equals("45"); + code("var i = 0 do { i++ if (i == 50) break } while (i < 100); return i;").equals("50"); + code("function f(A) { var i = 0 do { i++ } while (i < A); return i } return f(10);").equals("10"); + code("var i = 0 var a = 0 do { i++ if (i < 8) continue a++ } while (i < 10); return a;").equals("3"); + code("do { break } while (true);").equals("null"); + code("do { if (true) return 12 } while (true); return 1;").equals("12"); + code("var t = 0; do { t++; return t; } while (t < 5);").equals("1"); + // TODO catch error + // code("var t = 0; do { t++; return t;} while (t < 5); return 2;").equals("1"); + + // header("For loops"); + // code("for var i = 0; ; i++ {}").ops_limit(1000).exception(ls::vm::Exception::OPERATION_LIMIT_EXCEEDED); + code("for (var i = 0; false; i++) {}").equals("null"); + code("for (var i = 0; i < 10; i++) {}").equals("null"); + // DISABLED_code("var s = 0 for (var i = 0; i < 5; i++) do s += i end s").equals("10"); + // DISABLED_code("var s = 0 for (var i = 0; i < 10; i += 2) do s += i end s").equals("20"); + code("var s = 0 for (var i = 0; i < 5; i++) { s += i } return s;").equals("10"); + code("var s = 0 for (var i = 0; i < 10; i += 2) { s += i } return s;").equals("20"); + code("var a = 0 for (var i = 0; i < 10; i++) { a++ } return a;").equals("10"); + code("var a = 0 for (var i = 0; i < 10; i++) { if (i < 5) { continue } a++ } return a;").equals("5"); + code("var a = 0 for (var i = 0; i < 10; i++) { if (i > 5) { break } a++ } return a;").equals("6"); + code("var c = 0 for (var t = []; count(t) < 10; push(t, 'x')) { c++ } return c;").equals("10"); + // DISABLED_code("var s = 0 for (var m = [1: 3, 2: 2, 3: 1]; m; var l = 0 for (k, x in m) { l = k } m.erase(l)) { for (x in m) { s += x } } return s;").equals("14"); + code("for (var i = 0; ['', i < 10][1]; i++) {}").equals("null"); + // DISABLED_code("var i = ['', 1][1] for (; i < 10; i <<= 1) {}").equals("null"); + // code("for (var i = 0, j = 0; i < 5; i++, j++) { System.print(i + ', ' + j) }").output("0, 0\n1, 1\n2, 2\n3, 3\n4, 4\n"); + // code("for (var i = 0, j = 10; i < 5; i++, j += 2) { System.print(i + ', ' + j) }").output("0, 10\n1, 12\n2, 14\n3, 16\n4, 18\n"); + // DISABLED_code("for (var i = 0, j = 1, k = 2, l = 3; i < 5; i++, j++, k++, l++) { System.print([i j k l]) }").output("[0, 1, 2, 3]\n[1, 2, 3, 4]\n[2, 3, 4, 5]\n[3, 4, 5, 6]\n[4, 5, 6, 7]\n"); + // code("for var i = 0m; i < 10m; i++ {}").equals("(void)"); + // code("var s = 0m for var i = 0m; i < 10m; i++ { s += i } s").equals("45"); + // code("var s = 0m for var i = 0m; i < 10m; i += 2m { s += i } s").equals("20"); + + section("For variable defined before the loop"); + // DISABLED_code("var i = 0 for (; i < 10; i++) { } return i;").equals("10"); + code("var i = 0 for (i = 0; i < 10; i++) { } return i;").equals("10"); + code("var i = 0 for (i = 0; i < 10; i++) { if (i == 5) { break } } return i;").equals("5"); + code("var i var c = 0 for (i = 0; i < 20; i += 0.573) { c++ } return i;").equals("20.05500000000001"); + code("var i = 's' var c = 0 for (i = []; count(i) < 8; push(i, 1)) { c++ } return i;").equals("[1, 1, 1, 1, 1, 1, 1, 1]"); + // DISABLED_code("var i = 0 for (; i < 10; i += 0.5) { } return i;").equals("10"); + // code("var i = 0 for (i = 2l; i < 10; i += 0.5) { } return i;").equals("10"); + + section("For whitout braces"); + code("var s = 0 for (var i = 0; i < 10; i++) s += i return s;").equals("45"); + + section("For loops with returns"); + // DISABLED_code("for (return 12; true; null) {}").equals("12"); + // DISABLED_code("for (;; return 'hello') {}").equals("'hello'"); + code("for(var i=0;i<3;i++){ return i; }").equals("0"); + code("for(var i=0;i<3;i++){ return i; } return 2;").equals("0"); + + section("Nested for loops"); + code("var s = 0 for (var i = 0; i < 10; ++i) { for (var j = 0; j < 10; ++j) { s++ }} return s;").equals("100"); + code("var s = 0 for (var i = 0; i < 5; ++i) { for (var j = 0; j < 5; ++j) { for (var k = 0; k < 5; ++k) { s++ }}} return s;").equals("125"); + code("var s = 0 for (var i = 0; i < 10; i += 1) { for (var j = 0; j < 10; j += 1) { s++ }} return s;").equals("100"); + // DISABLED_code("var s = 0 for (var i = 0; i < 10; i += 1) { var j = 0 for (; j < 10; j += 1) { s++ }} return s;").equals("100"); + // file("test/code/loops/lot_of_fors_int.leek").equals("15015"); + // file("test/code/loops/lot_of_fors_array.leek").equals("15015"); + + section("Mix for and while loops"); + code("var s = 0 for (var i = 0; i < 10; i += 1) { var j = 10 while (j--) { s++ }} return s;").equals("100"); + code("var s = [] for (var i = 0; i < 2; i += 1) { var j = 0 while (j < 3) { j++ push(s, 1) }} return s;").equals("[1, 1, 1, 1, 1, 1]"); + code("var s = 0 for (var i = 0; i < 10; i += 1) { var j = [] while (count(j) < 10) { push(j, 'a') s++ }} return s;").equals("100"); + code("var s = [] var i = 3 while (i--) { for (var j = 0; j < 2; ++j) { push(s, j) }} return s;").equals("[0, 1, 0, 1, 0, 1]"); + code("var s = [] var i = 3 var j while (i--) { for (j = 0; j < 2; ++j) { push(s, j) }} return s;").equals("[0, 1, 0, 1, 0, 1]"); + + header("Foreach loops"); + section("Empty containers"); + code("for (var v in []) {}").equals("null"); + // code("for (v in new Array) {}").equals("(void)"); + code("var s = 0; var a; for (a in [1, 2, 3]) { s += a } return s").equals("6"); + code("var s = 0; var a; for (var k : a in [1, 2, 3]) { s += a } return s").equals("6"); + code("var s = 0; var k; for (k : var a in [1, 2, 3, 4, 5]) { s += k } return s").equals("10"); + + section("Normal containers"); + code("for (var v in [1, 2, 3, 4]) {}").equals("null"); + // code("for (var v in [1, 2, 3, 4]) do end").equals("(void)"); + code("var s = 0 for (var v in [1, 2, 3, 4]) { s += v } return s;").equals("10"); + // code("var s = 0 for v in [1l, 2l, 3l, 4l] { s += v } return s;").equals("10"); + // code("var s = 0.0 for v in [1.2, 2, 3.76, 4.01] { s += v } s").almost(10.97); + // code("var s = 0 for v in [1.2, 2, 3.76, 4.01] { s += v } s").almost(10.97); + code("var s = '' for (var v in ['salut ', 'ça ', 'va ?']) { s += v } return s;").equals("salut ça va ?"); + code("var a = 0 var x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] for (var i in x) { if (i < 5) { continue } a++ } return a;").equals("5"); + code("var s = 0 for (var k : var v in [1, 2, 3, 4]) { s += k * v } return s;").equals("20"); + // code("var s = '' for (var k : var v in ['a': 1, 'b': 2, 'c': 3, 'd': 4]) { s += v * k } return s;").equals("abbcccdddd"); + code("return (function (a) { var s = 0.0; for (var x in a) { s += x } return s; })([1, 2, 3, 4.25]);").equals("10.25"); + // DISABLED_code("var y = '' for k, x in { var x = [] x.push(4) x } { y += k + ':' + x + ' ' } y").equals("'0:4 '"); + // DISABLED_code("var y = '' for k, x in { var x = [1: 2] x.insert(3, 4) x } { y += k + ':' + x + ' ' } y").equals("'1:2 3:4 '"); + // DISABLED_code("var y = '' for k, x in { var x = [1: 2.5] x.insert(3, 4) x } { y += k + ':' + x + ' ' } y").equals("'1:2.5 3:4 '"); + // DISABLED_code("var y = '' for k, x in { var x = [1: '2'] x.insert(3, 4) x } { y += k + ':' + x + ' ' } y").equals("'1:2 3:4 '"); + // code("var y = 'test' for (var x in 1) { y = x } y").equals("1"); + // code("var y = 'test' for (var x in 'salut') { y = x } y").equals("'t'"); + // Working but should error + DISABLED_code("var x = 'test' for (var x in [1]) {} return x;").equals("'test'"); + // code("var y = '' for k, x in { var x = <> x.insert(4) x } { y += k + ':' + x } y").equals("'0:4'"); + // DISABLED_code("var fs = [] fs.push(s -> {var sum = 0 for v in s {sum += v} sum}) fs[0](<1, 2>)").equals("3"); // TODO issue #243 + // DISABLED_code("var fs = [] fs.push(s -> {[for v in s {v}]}) fs[0](<2,1>)").equals("[1, 2]"); // TODO issue #243 + // code("var s = 0l for i in [0..1000] { s += i ** 2 } s").equals("333833500"); + // code("var S = 'salut' var N = [] for var s in S.split('') { N += String.code(s) } N").equals("[115, 97, 108, 117, 116]"); + code("var tab = [0,1,2,3]; for(var i in tab){ return i; }").equals("0"); + code("var tab = [0,1,2,3]; for(var i in tab){ return i; } return 5;").equals("0"); + code("var tab = [1:0,2:1,3:2,4:3]; for(var i : var j in tab){ return i; } ").equals("1"); + code("var tab = [1:0,2:1,3:2,4:3]; for(var i : var j in tab){ return i; } return 0;").equals("1"); + + section("Foreach - no braces"); + code("var s = 0 for (var v in [1, 2, 3, 4]) s += v return s;").equals("10"); + + section("Foreach - double"); + code("var r = [] for (var x in [1, 2, 3]) { for (var y in [4, 5, 6]) { push(r, x * y) }} return r;").equals("[4, 5, 6, 8, 10, 12, 12, 15, 18]"); + // code("var r = [] for x in ['a', 'b', 'c'] { for y in [4, 5, 6] { r += x * y }} r").equals("['aaaa', 'aaaaa', 'aaaaaa', 'bbbb', 'bbbbb', 'bbbbbb', 'cccc', 'ccccc', 'cccccc']"); + + section("Foreach - mix"); + // code("var n = 3 while (n--) { var r = [] for x in [1, 2, 3] { r += x } print(r) }").output("[1, 2, 3]\n[1, 2, 3]\n[1, 2, 3]\n"); + + section("Foreach - references"); + code_v10("var s = 0 for (var @v in [1, 2, 3, 4]) { s += v } return s;").equals("10"); + code_v10("var s = 0 for (var @k : var @v in [1, 2, 3, 4]) { s += k * v } return s;").equals("20"); + + section("Foreach - captures"); + code("for (var e in [1, 2, 3]) { (function() { return e })() } return null;").equals("null"); + code("for (var i : var e in [1, 2, 3]) { (function() { return e })() } return null;").equals("null"); + code_v10("var a = [1, 2, 3] for (var @e in a) { (function() { e = 5 })() } return a;").equals("[1, 2, 3]"); + code_v10("var a = [1, 2, 3] for (var i : var @e in a) { (function() { e = 5 })() } return a;").equals("[1, 2, 3]"); + code("var a = [1, 2, 3] for (var i : var v in a) { (function() { i += 1 })() } return a;").equals("[1, 2, 3]"); + + section("Foreach - return"); + code("for (var x in [1]) { return 12 }").equals("12"); + // code("for (var x in 'salut') { return 13 }").equals("13"); + // code("for (var x in 123) { return 14 }").equals("14"); + + section("Foreach - argument"); + code("function main(r) { for (var x in [1, 2, 3]) { for (var y in [4, 5, 6]) { push(r, x * y) }} return r } return main([]);").equals("[4, 5, 6, 8, 10, 12, 12, 15, 18]"); + + // header("Foreach - unknown container"); + // code("for x in ['hello', 12345][0] { print(x) }").equals("h\ne\nl\nl\no\n"); + + // header("Foreach - not iterable"); + // code("for x in null {}").error(ls::Error::Type::VALUE_NOT_ITERABLE, {"null", env.null->to_string()}); + // code("for x in true {}").error(ls::Error::Type::VALUE_NOT_ITERABLE, {"true", env.boolean->to_string()}); + // code("for x in Number {}").error(ls::Error::Type::VALUE_NOT_ITERABLE, {"Number", env.const_class()->to_string()}); + + // header("Array For"); + // code("[for var i = 0; i < 5; ++i { i }]").equals("[0, 1, 2, 3, 4]"); + // code("[for var i = 1; i <= 10; ++i { [for var j = 1; j <= 3; ++j { if i == 3 break 2 i * j}] }]").equals("[[1, 2, 3], [2, 4, 6]]"); + // code("[for x in [1, 2, 3] { x }]").equals("[1, 2, 3]"); + // code("let a = ['a': 'b', 'c': 'd'] [for k, x in a { k + x }]").equals("['ab', 'cd']"); + // code("[for x in [1, 2, 3] {[ for y in [1, 2, 3] { if y == 2 continue x * y }] }]").equals("[[1, 3], [2, 6], [3, 9]]"); + // code("let sorted = [for x in <5, 2, 4, 1, 3> { x }] sorted").equals("[1, 2, 3, 4, 5]"); + // code("[for i in [1..10] { i }]").equals("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"); + // DISABLED_code("function attrs(o) { [for k : v in o {v}] } attrs(['a'])").equals("['a']"); + // DISABLED_code("function attrs(o) { [for k : v in o {v}] } attrs([1])").equals("[1]"); + // DISABLED_code("function attrs(o) { [for k : v in o {v}] } attrs([])").equals("[]"); + // DISABLED_code("function f() { [for x in [1, 2, 3] { x }] } f()").equals("[1, 2, 3]"); + // DISABLED_code("function f() { for x in [1, 2, 3] { print(x) } } f()").output("1\n2\n3\n"); + + // header("Breaks and Continues"); + // code("break").error(ls::Error::Type::BREAK_MUST_BE_IN_LOOP, {}); + // code("continue").error(ls::Error::Type::CONTINUE_MUST_BE_IN_LOOP, {}); + // code("while (true) { break 2 }").error(ls::Error::Type::BREAK_MUST_BE_IN_LOOP, {}); + // code("while (true) { continue 2 }").error(ls::Error::Type::CONTINUE_MUST_BE_IN_LOOP, {}); + // code("var r = 0 for (var x in [1, 2]) { for (var y in [3, 4]) { r = 10 * x + y if (x + y) >= 5 break 2 }} r").equals("14"); + // code("var r = 0 for (var x in [1, 2]) { for (var y in [3, 4]) { r = 10 * x + y continue 2 } r = 0 } r").equals("23"); + // code("for (var x in ['a']) { var a = 'a' { var b = 'b' break } var d = 'd' } return 0;").equals("0"); + code("for (var x in ['a']) { var a = 'a' for (var y in ['a']) { var b = 'b' break } var d = 'd' } return 0;").equals("0"); + // code("for (var x in ['a']) { var a = 'a' for y in ['a'] { var b = 'b' break 2 let c = 'c' } let d = 'd' } 0").equals("0"); + // code("for (var x = 0; x < 2; ++x) { var a = 'a' { var b = 'b' break } let d = 'd' } 0").equals("0"); + code("for (var x = 0; x < 2; ++x) { var a = 'a' for (var y = 0; y < 2; ++y) { var b = 'b' break } var d = 'd' } return 0;").equals("0"); + // code("for (var x = 0; x < 2; ++x) { var a = 'a' for (var y = 0; y < 2; ++y) { var b = 'b' break 2 var c = 'c' } var d = 'd' } return 0;").equals("0"); + // code("while (true) { break 0 }").error(ls::Error::Type::BREAK_LEVEL_ZERO, {}); + // code("while (true) { continue 0 }").error(ls::Error::Type::CONTINUE_LEVEL_ZERO, {}); + + } +} diff --git a/src/test/java/test/TestMain.java b/src/test/java/test/TestMain.java new file mode 100644 index 00000000..d110d2ee --- /dev/null +++ b/src/test/java/test/TestMain.java @@ -0,0 +1,27 @@ +package test; + +import org.junit.Assert; + +public class TestMain { + + public static void main(String[] args) throws Exception { + System.out.println("Start tests..."); + + // new TestCommon().code_v11("return 5 + 5;").equals("10"); + new TestGeneral().run(); + new TestNumber().run(); + new TestString().run(); + new TestArray().run(); + new TestComments().run(); + new TestOperators().run(); + new TestReference().run(); + new TestGlobals().run(); + new TestIf().run(); + new TestLoops().run(); + new TestFunction().run(); + new TestFiles().run(); + new TestEuler().run(); + + Assert.assertTrue(TestCommon.summary()); + } +} diff --git a/src/test/java/test/TestNumber.java b/src/test/java/test/TestNumber.java new file mode 100644 index 00000000..be1e260f --- /dev/null +++ b/src/test/java/test/TestNumber.java @@ -0,0 +1,939 @@ +package test; + +public class TestNumber extends TestCommon { + + public void run() throws Exception { + + // header("Numbers"); + + section("Basic numbers"); + code("return 0;").equals("0"); + code("return -1;").equals("-1"); + code("return -(-1);").equals("1"); + // code("π").almost(3.141592653589793116); + + section("Lexical errors"); + // code("12345r").error(ls::Error::Type::NUMBER_INVALID_REPRESENTATION); + // code("0b011001711").error(ls::Error::Type::NUMBER_INVALID_REPRESENTATION); + // code("0b").error(ls::Error::Type::NUMBER_INVALID_REPRESENTATION); + // code("0x").error(ls::Error::Type::NUMBER_INVALID_REPRESENTATION); + // code("0x+").error(ls::Error::Type::NUMBER_INVALID_REPRESENTATION); + // code("0b#").error(ls::Error::Type::NUMBER_INVALID_REPRESENTATION); + // code("0b'").error(ls::Error::Type::NUMBER_INVALID_REPRESENTATION); + // code("0b\"").error(ls::Error::Type::NUMBER_INVALID_REPRESENTATION); + + section("Basic operations"); + code("return 0 + 5;").equals("5"); + code("return 5 + 5;").equals("10"); + code("return 10 - 3;").equals("7"); + code("return -2 + 3;").equals("1"); + code("return 5 * 5;").equals("25"); + code("return 15 / 3;").equals("5.0"); + code("return 15 / 2;").equals("7.5"); + code("return 12 ** 2;").equals("144"); + code("return 2 ** 5;").equals("32"); + code("return 2 < 5;").equals("true"); + code("return 12 < 5;").equals("false"); + code("return 5 == 12;").equals("false"); + code("return 12 == 12;").equals("true"); + // codreturn e("0.2 + 0.1").almost(0.3); + // DISABLED_code("return |-12|;").equals("12"); + code("return -12 * 2;").equals("-24"); + code("return (-12) * 2;").equals("-24"); + code("return -12 ** 2;").equals("144"); + code("return (-12) ** 2;").equals("144"); + code("return -12 + 2;").equals("-10"); + code("var a = [2, 'a'] return [-a[0], ~a[0]] == [-2, ~2];").equals("true"); + // DISABLED_code("var a = [2, 'a'] return [-a[0], +a[0], ~a[0]] == [-2, 2, ~2];").equals("true"); + + section("Hexadecimal representation"); + // DISABLED_code("0x0").equals("0"); + // DISABLED_code("0x00000000").equals("0"); + // DISABLED_code("0x1").equals("1"); + // DISABLED_code("0x00000001").equals("1"); + // DISABLED_code("0xf").equals("15"); + // DISABLED_code("0x0000000f").equals("15"); + // DISABLED_code("-0xf").equals("-15"); + // DISABLED_code("0xff").equals("255"); + // DISABLED_code("0x10").equals("16"); + // DISABLED_code("-0xffff").equals("-65535"); + // DISABLED_code("0xffffffff").equals("4294967295"); + // DISABLED_code("0x8fa6cd83e41a6f4ec").equals("165618988158544180460"); + // DISABLED_code("-0xa71ed8fa6cd83e41a6f4eaf4ed9dff8cc3ab1e9a4ec6baf1ea77db4fa1c").equals("-72088955549248787618860543269425825306377186794534918826231778059287068"); + // DISABLED_code("0xfe54c4ceabf93c4eaeafcde94eba4c79741a7cc8ef43daec6a71ed8fa6cd8b3e41a6f4ea7f4ed9dff8cc3ab61e9a4ec6baf1ea77deb4fa1c").equals("722100440055342029825617696009879717719483550913608718409456486549003139646247155371523487552495527165084677501327990299146441654073884"); + + section("Binary representation"); + // DISABLED_code("0b0").equals("0"); + // DISABLED_code("0b00001").equals("1"); + // DISABLED_code("0b1001010110").equals("598"); + // DISABLED_code("-0b0101101001111").equals("-2895"); + // DISABLED_code("0b010101010101110101010101011111111110111110111110000000011101101010101001").equals("1574698668551521295017"); + // DISABLED_code("-0b101010101011101010101010111111111101111101111100000000111011010101010010011111100000011111111111110000").equals("-3381639641241763826573319995376"); + + section("null must not be considered as 0"); + code("return null == 0;").equals("false"); + code("return null < 0;").equals("false"); + // code("null + 5").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("5 + null").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("5 / null").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("null / 12").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("null * 5").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("5 * null").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + + section("Numbers with variables"); + code("var a = 2 return a++;").equals("2"); + code("var a = 2; return ++a;").equals("3"); + code("var a = 2 return a--;").equals("2"); + code("var a = 2; return --a;").equals("1"); + code("var a = 2 return a += 5;").equals("7"); + code("var a = 2 return a -= 5;").equals("-3"); + code("var a = 2 return a *= 5;").equals("10"); + code("var a = 100 return a /= 5;").equals("20.0"); + code("var a = 56 return a %= 17;").equals("5"); + code("var a = 15 return a **= 2;").equals("225"); + code("var a = 1.5 return a * 0.5;").equals("0.75"); + // DISABLED_code("var i = 1m return i = i + 2m;").equals("3"); + code("var a = 10; a += 10 - 2 * 3; return a;").equals("14"); + + section("multiple operations"); + code("return (33 - 2) / 2;").equals("15.5"); + code("return 12 < (45 / 4);").equals("false"); + code("return 12 == (24 / 2);").equals("true"); + // code("2.5 + 4.7").almost(7.2); + // DISABLED_code("return 2.5 × 4.7;").equals("11.75"); + code("return 5 * 2 + 3 * 4;").equals("22"); + + section("String conversions"); + // DISABLED_code("65.char()").equals("'A'"); + // DISABLED_code("char(65)").equals("'A'"); + // DISABLED_code("126.char()").equals("'~'"); + // DISABLED_code("char(128040)").equals("'🐨'"); + // DISABLED_code("126.784.char()").equals("'~'"); + // DISABLED_code("char([126.784, 'hello'][0])").equals("'~'"); + // DISABLED_code("let c = 65 (c.char())").equals("'A'"); + // DISABLED_code("let c = 65 (c.char() + '!')").equals("'A!'"); + // DISABLED_code("0x2764.char()").equals("'❤'"); + + section("Multiple precision numbers"); + // DISABLED_code("12344532132423").equals("12344532132423"); + // DISABLED_code("var a = 10m a").equals("10"); + // DISABLED_code("0m").equals("0"); + // DISABLED_code("0xf45eab5c9d13aab44376beff").equals("75628790656539575381594128127"); + // TODO floating-point multiple precision numbers + // TODO code("123456.78910m").equals("123456.7891"); + // TODO code("123456789123456789123456789.5").equals(""); + // TODO code("1234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567891234567883459720303390827584524332795121111123456788999999999999999999999999999999999.5").equals(""); + // DISABLED_code("let a = 1209876543789765432456765432087654321 a").equals("1209876543789765432456765432087654321"); + // DISABLED_code("let a = { 1209876543789765432456765432087654321 } a").equals("1209876543789765432456765432087654321"); + // DISABLED_code("var a = 5m a = 12m").equals("12"); + // DISABLED_code("var a = 5m a = 12m a").equals("12"); + // DISABLED_code("let f = -> 12m f().string()").equals("'12'"); + + section("Integer division by zero"); + // code("1 \\ 0").exception(ls::vm::Exception::DIVISION_BY_ZERO); + // code("1 % 0").exception(ls::vm::Exception::DIVISION_BY_ZERO); + + /* + * Number standard library + */ + // header("Number standard library"); + section("Constructor"); + // DISABLED_code("Number").equals(""); + // DISABLED_code("Number()").equals("0"); + // DISABLED_code("Number(12)").equals("12"); + // DISABLED_code("Number(12.5)").equals("12.5"); + // DISABLED_code("Number(12l)").equals("12"); + // DISABLED_code("Number(12m)").equals("12"); + // DISABLED_code("[Number(), 'str']").equals("[0, 'str']"); + // DISABLED_code("new Number").equals("0"); + // DISABLED_code("new Number()").equals("0"); + // DISABLED_code("new Number(12)").equals("12"); + // DISABLED_code("['', new Number()]").equals("['', 0]"); + // DISABLED_code("['', new Number]").equals("['', 0]"); + // DISABLED_code("['', Number()]").equals("['', 0]"); + // DISABLED_code("['', new Number(12)]").equals("['', 12]"); + // DISABLED_code("['', Number(12)]").equals("['', 12]"); + + section("Constants"); + // code("pi").almost(3.141592653589793116); + // code("['', pi]").equals("['', 3.1415926536]"); + // code("2 × pi").almost(6.283185307179586232); + // code("e").almost(2.718281828459045091); + // code("phi").almost(1.618033988749894903); + // code("epsilon").almost(0.000000000000000222); + // code("pi").almost(3.141592653589793116); + // code("e").almost(2.718281828459045091); + // code("phi").almost(1.618033988749894903); + // code("epsilon").almost(0.000000000000000222); + // code("let pi = 3 pi").equals("3"); + // code("{ let pi = 3 } pi").almost(3.141592653589793116); + + /* + * Operators + */ + section("Number.operator unary -"); + code("var a = [12, ''] var b = a[0]; return -b;").equals("-12"); + code("return -(12 ** 2);").equals("-144"); + // DISABLED_code("return -(12m ** 2);").equals("-144"); + // DISABLED_code("-100m").equals("-100"); + + section("Number.operator unary !"); + code("var a = [12, ''] var b = a[0]; return !b;").equals("false"); + + section("Number.operator unary ~"); + code("var a = [12, ''] var b = a[0]; return ~b;").equals("-13"); + code("var a = 12 return ['', ~a];").equals("[, -13]"); + + section("Number.operator ++x"); + code("var a = 20; return ++a;").equals("21"); + code("var a = 30; ++a return a;").equals("31"); + // DISABLED_code("var a = 20m; return ++a;").equals("21"); + // DISABLED_code("var a = 20m; ++a return a;").equals("21"); + // DISABLED_code("var a = 20m; let b = ++a return b;").equals("21"); + // code("++5").error(ls::Error::Type::VALUE_MUST_BE_A_LVALUE, {"5"}); + code("var a = 5 return ['', ++a];").equals("[, 6]"); + + section("Number.operator --x"); + code("var a = 20; return --a;").equals("19"); + code("var a = 30; --a return a;").equals("29"); + // code("--5").error(ls::Error::Type::VALUE_MUST_BE_A_LVALUE, {"5"}); + code("var a = 5 return ['', --a];").equals("[, 4]"); + + section("Number.operator x++"); + code("var a = 20; return a++;").equals("20"); + code("var a = 20; a++ return a;").equals("21"); + code("var a = 20; var b = a++ return b;").equals("20"); + // DISABLED_code("var a = 20m; a++").equals("20"); + // DISABLED_code("var a = 20m; a++ a").equals("21"); + // DISABLED_code("var a = 20m; var b = a++ b").equals("20"); + // code("5++").error(ls::Error::Type::VALUE_MUST_BE_A_LVALUE, {"5"}); + + section("Number.operator x--"); + code("var a = 20; return a--;").equals("20"); + code("var a = 20; a-- return a;").equals("19"); + code("var a = 20; var b = a-- return b;").equals("20"); + // DISABLED_code("var a = 20m; a--").equals("20"); + // DISABLED_code("var a = 20m; a-- a").equals("19"); + // DISABLED_code("var a = 20m; var b = a-- b").equals("20"); + // code("5--").error(ls::Error::Type::VALUE_MUST_BE_A_LVALUE, {"5"}); + + section("Number.operator in"); + // TODO idea : a in b returns true if a is a divisor of b + // code("2 in 12").error(ls::Error::Type::VALUE_MUST_BE_A_CONTAINER, {"12"}); + + section("Number.operator ="); + // DISABLED_code("var a = 1m, b = 4m; a = b").equals("4"); + + section("Number.operator =="); + code("return 12 == 12;").equals("true"); + code("return 13 == 12;").equals("false"); + // DISABLED_code("12m == 12m").equals("true"); + // DISABLED_code("13m == 12m").equals("false"); + code("return 12 ** 5 == 12 ** 5;").equals("true"); + code("return 12 ** 5 == (3 * 4) ** 5;").equals("true"); + code("return 12 ** 5 == 248832;").equals("true"); + code("return 248832 == 12 ** 5;").equals("true"); + // DISABLED_code("12m ** 5m == 12m ** 5m").equals("true"); + // DISABLED_code("12m ** 5m == (3m * 4m) ** 5m").equals("true"); + // DISABLED_code("12m ** 5m == 248832").equals("true"); + // DISABLED_code("248832 == 12m ** 5m").equals("true"); + + section("Number.operator +"); + code("return 1 + 2;").equals("3"); + code("return 1 + (2 + 3);").equals("6"); + code("return (1 + 2) + 3;").equals("6"); + code("return (1 + 2) + (3 + 4);").equals("10"); + // DISABLED_code("1m + 2m").equals("3"); + // DISABLED_code("1m + (2m + 3m)").equals("6"); + // DISABLED_code("(1m + 2m) + 3m").equals("6"); + // DISABLED_code("(1m + 2m) + (3m + 4m)").equals("10"); + code("return 15 + false;").equals("15"); + code("return 15 + true;").equals("16"); + code("var a = 15 return a + true;").equals("16"); + // DISABLED_code("10000m + 15").equals("10015"); + // DISABLED_code("let a = ['a', 12321111111111111111111111111111111321321321999999] a[1] + 123456789").equals("12321111111111111111111111111111111321321445456788"); + code("return 10000 + (-15);").equals("9985"); + // DISABLED_code("10000m + (-15)").equals("9985"); + code("return null + 2;").equals("2"); + code("return 2 + null;").equals("2"); + code("return null + null;").equals("0"); + + section("Number.operator +="); + code("var a = 15 a += true return a;").equals("16"); + // code("var a = 15$ a += []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var a = 15$ a += [] a").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + code("var a = 10 return a += 4;").equals("14"); + code("var a = 10 a += 4 return a;").equals("14"); + code("var a = 15 return ['', a += 7];").equals("[, 22]"); + code("var a = 10 a += 5 return a;").equals("15"); + code("var a = 10 a += 78 return a;").equals("88"); + code("var a = 10 a += (-6) return a;").equals("4"); + // DISABLED_code("var a = 10m return a += 4m;").equals("14"); + // DISABLED_code("var a = 10m a += 4m return a;").equals("14"); + // DISABLED_code("var a = 15 return ['', a += 7];").equals("['', 22]"); + // DISABLED_code("var a = 10m a += 5 return a;").equals("15"); + // DISABLED_code("var a = 10m a += 78m return a;").equals("88"); + // DISABLED_code("var a = 10m a += (-6) return a;").equals("4"); + + section("Number.operator -"); + code("return -12").equals("-12"); + code("return -0").equals("0"); + code("return -null").equals("0"); + code("return 1 - 2;").equals("-1"); + code("return 1 - (2 - 3);").equals("2"); + code("return (1 - 2) - 3;").equals("-4"); + code("return (1 - 2) - (3 - 4);").equals("0"); + code("return (10 + 10) - 1;").equals("19"); + // DISABLED_code("return 1m - 2m;").equals("-1"); + // DISABLED_code("return 1m - (2m - 3m);").equals("2"); + // DISABLED_code("return (1m - 2m) - 3m;").equals("-4"); + // DISABLED_code("return (1m - 2m) - (3m - 4m);").equals("0"); + // DISABLED_code("return (10m + 10m) - 1").equals("19"); + code("return 15 - 3;").equals("12"); + // DISABLED_code("1000m - 12").equals("988"); + // DISABLED_code("1000m - (-12)").equals("1012"); + code("return 15 - false;").equals("15"); + code("return 15 - true;").equals("14"); + code("var a = 15 return a - true;").equals("14"); + // code("12$ - []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + code("var a = 100 return a - 20;").equals("80"); + code("return null - null;").equals("0"); + code("return 12 - null;").equals("12"); + code("return null - 12;").equals("-12"); + + section("Number.operator -="); + code("var a = 15 a -= true return a;").equals("14"); + // code("var a = 15$ a -= []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var a = 15$ a -= [] a").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + code("var a = 15 return ['', a -= 6];").equals("[, 9]"); + + section("Number.operator *"); + code("return 3 * 4;").equals("12"); + code("return 10 + 3 * 4;").equals("22"); + code("return (5 + 2) * (16 * 2);").equals("224"); + // DISABLED_code("3m * 4m").equals("12"); + // DISABLED_code("10m + 3m * 4m").equals("22"); + // DISABLED_code("(5m + 2m) * (16m * 2m)").equals("224"); + code("return 12 * false;").equals("0"); + code("var a = 13; return a * false;").equals("0"); + code("return 13 * true;").equals("13"); + code("return 7 * 2;").equals("14"); + code("var a = 6; return a * 3;").equals("18"); + // code("14$ * []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // DISABLED_code("return 12344532132423 * 987657897613412;").equals("12192174652930109838844857276"); + // DISABLED_code("12344532132423m * 987657897613412m").equals("12192174652930109838844857276"); + // DISABLED_code("5 * 'yo'").equals("'yoyoyoyoyo'"); + // DISABLED_code("50m * 10").equals("500"); + // DISABLED_code("50 * 10m").equals("500"); + // DISABLED_code("let a = ['a', 12321111111111111111111111111111111321321321999999] a[1] * 123456789").equals("1521124814690000000000000000000000025951877651354934543211"); + code("return null * 2;").equals("0"); + code("return 2 * null;").equals("0"); + code("return null * null;").equals("0"); + + section("Number.operator *="); + code("var a = 15 a *= true return a;").equals("15"); + code("var a = 15 a *= false return a;").equals("0"); + code("var a = 15 a *= null return a;").equals("0"); + // code("var a = 15$ a *= []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var a = 15$ a *= [] a").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + code("var a = 15; return ['', a *= 2];").equals("[, 30]"); + code("var a = 5 a *= 0 return a;").equals("0"); + code("var a = 5 a *= 12 return a;").equals("60"); + code("var a = 5 a *= 5 return a;").equals("25"); + code("var a = null a *= 5 return a;").equals("0"); + code("var a = null a *= null return a;").equals("0"); + code("var a = null return a *= 5").equals("0"); + code("var a = null return a *= null").equals("0"); + // DISABLED_code("var a = 5m a *= 0 a").equals("0"); + // DISABLED_code("var a = 5m a *= 12 a").equals("60"); + // DISABLED_code("var a = 5m a *= 5m a").equals("25"); + // DISABLED_code("var a = 91591785496891278315799124157189514175m a *= 157854689278315792457851475m a").equals("14458192840057923568549758280294876918394393505787702519557158125"); + // DISABLED_code("var a = 78m a *= true a").equals("78"); + + section("Number.operator **"); + code("return 14 ** 3;").equals("2744"); + code("return 14 ** null;").equals("1"); + code("return null ** 2;").equals("0"); + code("return null ** null;").equals("0"); + // DISABLED_code("return 14 ** true;").equals("14"); + // DISABLED_code("return 14 ** false;").equals("1"); + // DISABLED_code("let a = 14 return a ** false;").equals("1"); + // code("14$ ** []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // DISABLED_code("return 2 ** 50;").equals("1.125899906842624E15"); + // DISABLED_code("return 2l ** 50;").equals("1125899906842624"); + // DISABLED_code("257l ** 20").equals("-9223372036854775808"); // overflow + // DISABLED_code("257m ** 20").equals("1580019571820317063568778786121273112555213952001"); + // DISABLED_code("2m ** 50").equals("1125899906842624"); + // DISABLED_code("(5m + 2m) ** (16m * 2m)").equals("1104427674243920646305299201"); + // code("123m ** 1900").exception(ls::vm::Exception::NUMBER_OVERFLOW); + code("var s = 0 s = 5 ** 2 return s;").equals("25"); + + section("Number.operator **="); + code("var a = 5; a **= 4 return a").equals("625"); + code("var a = 5; return a **= 4").equals("625"); + code("var a = 5; return a **= true").equals("5"); + code("var a = null a **= 5 return a").equals("0"); + code("var a = null return a **= 5").equals("0"); + // DISABLED_code("var a = 5$; a **= false").equals("1"); + // code("var a = 5$; a **= []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // DISABLED_code("var a = 5; ['', a **= 4]").equals("['', 625]"); + + section("Number.operator %"); + code("return 721 % 57;").equals("37"); + code("return false % 3;").equals("0"); + code("return true % 3;").equals("1"); + code("var a = 721 return a % 57;").equals("37"); + code("var a = null return a % 57;").equals("0"); + // code("let a = 721$ a % []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // DISABLED_code("721 % true").equals("0"); + // code("721$ % false").exception(ls::vm::Exception::DIVISION_BY_ZERO); + // code("let a = 721$ a % false").exception(ls::vm::Exception::DIVISION_BY_ZERO); + // DISABLED_code("let a = 721$ a % true").equals("0"); + // DISABLED_code("123456789123456789m % 234567m").equals("221463"); + // DISABLED_code("(12m ** 40m) % 234567m").equals("228798"); + // DISABLED_code("100000m % (12m ** 3m)").equals("1504"); + // DISABLED_code("(100000m * 10m) % (12m ** 3m)").equals("1216"); + // code("['salut', 123][0] % 5").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // TODO should have semantic error + // code("['salut', 'a'][0] % 5").error(ls::Error::NO_SUCH_OPERATOR, {}); + + section("Number.operator %="); + code("var a = 721 return a %= 17;").equals("7"); + // DISABLED_code("var a = 721 a %= true").equals("0"); + // code("var a = 721$ a %= []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + + // section("Number.operator %%"); + // DISABLED_code("0 %% 1").equals("0"); + // DISABLED_code("2 %% 5").equals("2"); + // DISABLED_code("(-2) %% 5").equals("3"); + // DISABLED_code("(-12) %% 5").equals("3"); + // DISABLED_code("721 %% 57").equals("37"); + // DISABLED_code("(-721) %% 57").equals("20"); + // DISABLED_code("(-721$) %% 57$").equals("20"); + + // section("Number.operator %%="); + // DISABLED_code("var a = 0 a %%= 1").equals("0"); + // DISABLED_code("var a = 2 a %%= 5").equals("2"); + // DISABLED_code("var a = -2 a %%= 5").equals("3"); + // DISABLED_code("var a = -12 a %%= 5").equals("3"); + // DISABLED_code("var a = 721 a %%= 57").equals("37"); + // DISABLED_code("var a = -721 a %%= 57").equals("20"); + // DISABLED_code("var a = -721$ a %%= 57$").equals("20"); + + section("Number.operator /"); + code("8 / 0").equals("null"); + code("8 / null").equals("null"); + code("null / 5").equals("null"); + // code("12$ / false").exception(ls::vm::Exception::DIVISION_BY_ZERO); + // code("let a = 13$; a / false").exception(ls::vm::Exception::DIVISION_BY_ZERO); + code("return 13 / true;").equals("13"); + code("return 14 / 2;").equals("7.0"); + code("var a = 18; return a / 3;").equals("6.0"); + // code("14$ / []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + code("var a = 17, b = 5 return a / b;").equals("3.4"); + + section("Number.operator /="); + code("var a = 12 a /= 3 return a;").equals("4.0"); + code("var a = 12 a /= 0.5 return a;").equals("24.0"); + code("var a = 12 a /= true return a;").equals("12"); + code("var a = null a /= 5 return a;").equals("0"); + // code("var a = 12 a /= false return a;").equals("nan"); + // code("var a = 12$ a /= []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var a = 12$ a /= [] a").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + code_v10("var a = 15; return ['', a /= 2];").equals("[, 7,5]"); + code_v11("var a = 15; return ['', a /= 2];").equals("[, 7.5]"); + + section("Number.operator <"); + code("return 5 < 2;").equals("false"); + code("return 2 < 5;").equals("true"); + code("return 5.1 < 2.1;").equals("false"); + code("return 2.1 < 5.1;").equals("true"); + // code("3m < 4m").equals("true"); + // code("10m < (3m * 4m)").equals("true"); + // code("(5m + 5m) < (3m * 4m)").equals("true"); + // code("(5m + 5m) < 12m").equals("true"); + // code("3m < 4").equals("true"); + + section("Number.operator <="); + code("return 5 <= 2;").equals("false"); + code("return 2 <= 5;").equals("true"); + code("return 5.1 <= 2.1;").equals("false"); + code("return 2.1 <= 5.1;").equals("true"); + code("return 3 <= 4;").equals("true"); + code("return 3 <= [];").equals("false"); + + section("Number.operator >"); + code("return 5 > 2;").equals("true"); + code("return 2 > 5;").equals("false"); + code("return 5.1 > 2.1;").equals("true"); + code("return 2.1 > 5.1;").equals("false"); + // code("12 > 5m").equals("true"); + code("return [] > true;").equals("false"); + // code("-100m > 0").equals("false"); + + section("Number.operator >="); + code("return 5 >= 2;").equals("true"); + code("return 2 >= 5;").equals("false"); + code("return 5.1 >= 2.1;").equals("true"); + code("return 2.1 >= 5.1;").equals("false"); + + // section("Number.operator \\"); + // code("10 \\ 2").equals("5"); + // code("10 \\ 4").equals("2"); + // code("2432431 \\ 2313").equals("1051"); + // code("let a = 420987$ a \\ 546$").equals("771"); + // code("420987$ \\ 12").equals("35082"); + // code("12345678912345l \\ 1234").equals("10004602035"); + // code("12$ \\ false").exception(ls::vm::Exception::DIVISION_BY_ZERO); + // code("let a = 13$; a \\ false").exception(ls::vm::Exception::DIVISION_BY_ZERO); + // code("13$ \\ true").equals("13"); + // code("17$ \\ 4").equals("4"); + // code("let a = 10.7$; a \\ true").equals("10"); + // code("let a = 10$; a \\ 4").equals("2"); + // code("14$ \\ []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("67.89$ \\ 1").equals("67"); + // code("['', 10 \\ 2]").equals("['', 5]"); + // code("['', 10$ \\ 2]").equals("['', 5]"); + + // section("Number.operator \\="); + // code("var a = 12 a \\= 5").equals("2"); + // code("var a = 12$ a \\= 5").equals("2"); + // code("var a = 30$ a \\= 4 a").equals("7"); + // code("var a = 12$ a \\= true a").equals("12"); + // code("var a = 12$ a \\= false a").exception(ls::vm::Exception::DIVISION_BY_ZERO); + // code("var a = 12$ a \\= []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var a = 12$ a \\= [] a").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var a = 12 ['', a \\= 5]").equals("['', 2]"); + + section("Number.operator &"); + code("return 0 & 0;").equals("0"); + code("return 1 & 0;").equals("0"); + code("return 1 & 1;").equals("1"); + code("return 5 & 12;").equals("4"); + code("return 87619 & 18431;").equals("17987"); + code("return 87619 & [18431, ''][0];").equals("17987"); + code("var a = 87619 return a &= 18431;").equals("17987"); + code("var a = 87619 a &= 18431 return a;").equals("17987"); + code("return 87619 & 18431;").equals("17987"); + // code("87619$ &= 18431").error(ls::Error::VALUE_MUST_BE_A_LVALUE, {"87619"}); + code("var a = 87619 a &= 18431 return a;").equals("17987"); + // code("[12, 'hello'][1] & 5").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var a = [12, 'hello'][1] a &= 18431 a").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + + section("Number.operator |"); + code("return 0 | 0;").equals("0"); + code("return 1 | 0;").equals("1"); + code("return 1 | 1;").equals("1"); + code("return 5 | 12;").equals("13"); + code("return [5, ''][0] | [12, ''][0];").equals("13"); + code("return 87619 | 18431;").equals("88063"); + code("var a = 87619 return a |= 18431;").equals("88063"); + code("var a = 87619 a |= 18431 return a;").equals("88063"); + code("return [87619, ''][0] | 18431;").equals("88063"); + // code("87619$ |= 18431").error(ls::Error::VALUE_MUST_BE_A_LVALUE, {"87619"}); + code("var a = 87619 a |= 18431 return a;").equals("88063"); + // code("[12, 'hello'][1] | 5").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + + section("Number.operator ^"); + code("return 0 ^ 0;").equals("0"); + code("return 1 ^ 0;").equals("1"); + code("return 1 ^ 1;").equals("0"); + code("return 5 ^ 12;").equals("9"); + code("return 87619 ^ 18431;").equals("70076"); + code("return [87619, ''][0] ^ [18431, ''][0];").equals("70076"); + code_v10("var a = 5 a ^= 2 return a;").equals("25"); // In LS 1.0, ^= was power equals + code_v11("var a = 87619 return a ^= 18431;").equals("70076"); + code_v11("var a = 87619 a ^= 18431 return a;").equals("70076"); + code("return [87619, ''][0] ^ 18431;").equals("70076"); + // code("87619$ ^= 18431").error(ls::Error::VALUE_MUST_BE_A_LVALUE, {"87619"}); + code_v11("var a = 87619 a ^= 18431 return a;").equals("70076"); + // code("[12, 'hello'][1] ^ 5").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + + section("Number.operator <<"); + code("return 0 << 0;").equals("0"); + code("return 1 << 0;").equals("1"); + code("return 123456 << 0;").equals("123456"); + code("return 0 << 1;").equals("0"); + code("return 0 << 12;").equals("0"); + code("return 1 << 8;").equals("256"); + code("return 123 << 12;").equals("503808"); + code("return [123, ''][0] << 12;").equals("503808"); + code("var a = 123 return a <<= 11;").equals("251904"); + code("var a = 123 a <<= 13 return a;").equals("1007616"); + code("var a = [123, ''] return a[0] <<= 13;").equals("1007616"); + code("var a = 123 return ['', a <<= 13];").equals("[, 1007616]"); + // code("'salut' << 5").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + + section("Number.operator >>"); + code("return 0 >> 0;").equals("0"); + code("return 1 >> 0;").equals("1"); + code("return 123456 >> 0;").equals("123456"); + code("return 0 >> 1;").equals("0"); + code("return 0 >> 12;").equals("0"); + code("return 155 >> 3;").equals("19"); + code("return -155 >> 3;").equals("-20"); + code("return 12345 >> 8;").equals("48"); + code("return 123123123 >> 5;").equals("3847597"); + code("return [123123123, ''][0] >> 5;").equals("3847597"); + code("var a = 123123123 return a >>= 6;").equals("1923798"); + code("var a = 123123123 a >>= 7 return a;").equals("961899"); + code("var a = [123123123, ''] return a[0] >>= 7;").equals("961899"); + code("var a = 12345 return ['', a >>= 8];").equals("[, 48]"); + // code("'salut' >> 5").error(ls::Error::NO_SUCH_OPERATOR, {env.tmp_string->to_string(), ">>", env.integer->to_string()}); + + section("Number.operator >>>"); + code("return 155 >>> 3;").equals("19"); + code("return -155 >>> 3;").equals("536870892"); + code("return [-155, ''][0] >>> 3;").equals("536870892"); + code("var a = -155 return a >>>= 4;").equals("268435446"); + code("var a = -155 a >>>= 5 return a;").equals("134217723"); + code("var a = [-155, ''] return a[0] >>>= 5;").equals("134217723"); + code("var a = -155 return ['', a >>>= 5];").equals("[, 134217723]"); + // code("'salut' >>> 5").error(ls::Error::NO_SUCH_OPERATOR, {env.tmp_string->to_string(), ">>>", env.integer->to_string()}); + + section("Not a statement errors"); + code("null; return null;").equals("null"); + code("(null); return null;").equals("null"); + code("((null)); return null;").equals("null"); + code("true; return null;").equals("null"); + code("false; return null;").equals("null"); + code("'salut'; return null;").equals("null"); + code("var a; a; return null;").equals("null"); + code("12; return null;").equals("null"); + code("12 && 5; return null;").equals("null"); + code("12 + 5; return null;").equals("null"); + code("12 - 5; return null;").equals("null"); + code("12 * 5; return null;").equals("null"); + code("12 / 5; return null;").equals("null"); + code("12 % 5; return null;").equals("null"); + code("12 ** 5; return null;").equals("null"); + code("12 ^ 5; return null;").equals("null"); + code("12 & 5; return null;").equals("null"); + code("12 | 5; return null;").equals("null"); + code("12 < 5; return null;").equals("null"); + code("12 > 5; return null;").equals("null"); + code("12 <= 5; return null;").equals("null"); + code("12 >= 5; return null;").equals("null"); + code("12 == 5; return null;").equals("null"); + code("12 === 5; return null;").equals("null"); + code("(12 && 5); return null;").equals("null"); + code("true ? 1 : 2; return null;").equals("null"); + code("(true ? 1 : 2); return null;").equals("null"); + + /* + * Methods + */ + section("Number.abs()"); + // code("return abs;").equals(""); + code("return abs(-12);").equals("12"); + code("return abs(-19.5);").equals("19.5"); + code("return abs(12);").equals("12"); + // code("return abs(-16436435l)").equals("16436435"); + code("return abs(-12.67);").almost(12.67); + code("return abs(['a', -15][1]);").equals("15"); + // code("return (-17).abs()").equals("17"); + // code("return (-19.5).abs()").equals("19.5"); + // code("return 12.abs").equals(""); + // code("abs([1, 'salut'][1])").exception(ls::vm::Exception::WRONG_ARGUMENT_TYPE); + + section("Number.exp()"); + code("return exp(0)").equals("1.0"); + code("return exp(1)").almost(Math.E); + code("return exp(4)").almost(54.598150033144236204); + code("return exp(4.89)").almost(132.953574051282743085); + code("return exp(-2.97)").almost(0.051303310331919108); + code("return exp(['a', 7.78][1])").almost(2392.274820537377763685); + // code("return 0.exp();").equals("1"); + // code("return 1.exp();").almost(Math.E); + // code("return 7.exp();").almost(1096.633158428458500566); + // code("return (-7).exp();").almost(0.000911881965554516); + // code("return (-3.33).exp();").almost(0.035793105067655297); + code("return E ** 5;").almost(148.413159102576571513); + + section("Number.floor()"); + code("return floor(5.9);").equals("5"); + code("var a = 5 return floor(a);").equals("5"); + code("var a = 5.4 return floor(a);").equals("5"); + code("return floor(['a', -14.7][1]);").equals("-15"); + code("return floor(5.5);").equals("5"); + code("return floor(1.897)").equals("1"); + code("return floor(3.01)").equals("3"); + + section("Number.round()"); + code("return round(5.7)").equals("6"); + code("return round(5.4)").equals("5"); + code("return round(['a', -15.89][1])").equals("-16"); + code("return round(12)").equals("12"); + code("return round(-1000)").equals("-1000"); + code("return round(1.897)").equals("2"); + code("return round(3.01)").equals("3"); + + section("Number.ceil()"); + code("return ceil(5.1)").equals("6"); + code("return ceil(188)").equals("188"); + code("return ceil(1.897)").equals("2"); + code("return ceil(3.01)").equals("4"); + + section("Number.max()"); + code("return max(8, 5)").equals("8"); + code("return max(8, 88)").equals("88"); + code("return max(5, 12);").equals("12"); + code("return max(5.0, 12);").equals("12.0"); + code("return max(75.7, 12);").almost(75.7); + code("return max(5, 12.451);").almost(12.451); + code("return max([5, 'a'][0], 4);").equals("5"); + code("return max([5, 'a'][0], 76);").equals("76"); + code("return max(4, [5, 'a'][0]);").equals("5"); + code("return max(77, [5, 'a'][0]);").equals("77"); + code("return max([55, 'a'][0], [5, 'a'][0]);").equals("55"); + code("return max(5, 12.8);").equals("12.8"); + code("return max(15.7, 12.8);").equals("15.7"); + code("return max([15.7, ''][0], 12.8);").equals("15.7"); + code("return max(5.5, [12.8, ''][0]);").equals("12.8"); + // code("return 2.max([7.5, ''][0]);").equals("7.5"); + // code("return [2, ''][0].max([7.5, ''][0]);").equals("7.5"); + // code("2.max([7.5, ''][1])").exception(ls::vm::Exception::WRONG_ARGUMENT_TYPE); + // code("return max(5l, 10.5)").equals("10.5"); + // code("return max(5l, 10)").equals("10"); + // code("return max(true, 10l)").equals("10"); + // code("max('string', 12)").error(ls::Error::METHOD_NOT_FOUND, {"max(" + env.tmp_string->to_string() + ", " + env.integer->to_string() + ")"}); + + section("Number.min()"); + code("return min(8, 5)").equals("5"); + code("return min(8, 88)").equals("8"); + code("return min(5, 12)").equals("5"); + code("return min(75.7, 12)").almost(12.0); + code("return min(5, 12.451)").almost(5.0); + code("return min([5, 'a'][0], 4)").equals("4"); + code("return min([5, 'a'][0], 76)").equals("5"); + code("return min(4, [5, 'a'][0])").equals("4"); + code("return min(77, [5, 'a'][0])").equals("5"); + code("return min([55, 'a'][0], [5, 'a'][0])").equals("5"); + code("return min(5, 12.8)").equals("5.0"); + code("return min(15.7, 12.8)").equals("12.8"); + code("return min([15.7, ''][0], 12.8)").equals("12.8"); + code("return min(5.5, [12.8, ''][0])").equals("5.5"); + // code("return min(5l, 10.5);").equals("5"); + // code("return min(5l, 10);").equals("5"); + // code("return min(true, 10l);").equals("1"); + // code("min('string', 12)").error(ls::Error::METHOD_NOT_FOUND, {"min(" + env.tmp_string->to_string() + ", " + env.integer->to_string() + ")"}); + + section("Number.cos()"); + code("return cos(0)").equals("1.0"); + code("return cos(2.5)").almost(Math.cos(2.5)); + code("return cos(PI)").equals("-1.0"); + code("return cos(PI / 2)").almost(0.0); + // code("return π.cos()").equals("-1"); + // code("return ['', π][1].cos()").equals("-1"); + code("return cos(['', PI][1]);").equals("-1.0"); + code("return cos(PI);").equals("-1.0"); + + section("Number.acos()"); + code("return acos(1)").equals("0.0"); + code("return acos(-1)").almost(Math.PI); + code("return acos(0)").almost(Math.PI / 2); + // code("return (-0.33).acos()").almost(1.907099901948877019); + code("return acos(['y', 0][1])").almost(Math.PI / 2); + + section("Number.sin()"); + code("return sin(0)").equals("0.0"); + code("return sin(2.5)").almost(Math.sin(2.5)); + code("return sin(PI)").almost(0.0); + code("return sin(PI / 2)").equals("1.0"); + code("return sin(- PI / 2)").equals("-1.0"); + code("return sin(['', PI / 2][1])").equals("1.0"); + code("return sin(PI / 2)").equals("1.0"); + + section("Number.tan()"); + code("return tan(0)").equals("0.0"); + code("return tan(2.5)").almost(Math.tan(2.5)); + code("return tan(PI)").almost(0.0); + code("return tan(PI / 4)").almost(1.0); + code("return tan(- PI / 4)").almost(-1.0); + code("return tan(['', PI / 4][1])").almost(1.0); + + section("Number.asin()"); + code("return asin(0)").equals("0.0"); + code("return asin(-1)").almost(-Math.PI / 2); + code("return asin(1)").almost(Math.PI / 2); + // code("return 0.33.asin()").almost(0.33630357515398035); + code("return asin(['y', -1][1])").almost(-Math.PI / 2); + + section("Number.atan()"); + code("return atan(1)").almost(Math.PI / 4); + code("return atan(-1)").almost(-Math.PI / 4); + code("return atan(0.5)").almost(0.463647609000806094); + // code("return 0.atan()").equals("0"); + code("return atan(['y', 0.5][1])").almost(0.463647609000806094); + + section("Number.atan2()"); + code("return atan2(1, 1)").almost(Math.PI / 4); + code("return atan2(150.78, 150.78)").almost(Math.PI / 4); + code("return atan2(1, 0)").almost(Math.PI / 2); + code("return atan2(-1, 0)").almost(-Math.PI / 2); + code("return atan2(0, 1)").equals("0.0"); + code("return atan2(0, -1)").almost(Math.PI); + code("return atan2(12.12, 42.42)").almost(0.278299659005111333); + // code("return 1.atan2(1)").almost(Math.PI / 4); + // code("return ['', -1][1].atan2(1)").almost(-Math.PI / 4); + // code("return 1.atan2(['', -1][1])").almost(3 * Math.PI / 4); + // code("return ['', -1][1].atan2(['', -1][1])").almost(-3 * Math.PI / 4); + code("return atan2(1, 1)").almost(Math.PI / 4); + code("return atan2(['', -1][1], 1)").almost(-Math.PI / 4); + code("return atan2(1, ['', -1][1])").almost(3 * Math.PI / 4); + code("return atan2(['', -1][1], ['', -1][1])").almost(-3 * Math.PI / 4); + // code("return atan2(1, true)").almost(Math.PI / 4); + // code("return atan2(true, false)").almost(Math.PI / 2); + + section("Number.cbrt()"); + code("return cbrt(125)").almost(5.0); + code("return cbrt(1000)").almost(10.0); + code("return cbrt(1728)").almost(12.0, 1e-14); + // code("return 1728.cbrt()").almost(12.0, 0.00000000000001); + code("return cbrt(['', 1728][1])").almost(12.0, 0.00000000000001); + // code("return ['', 1728][1].cbrt()").almost(12.0, 0.00000000000001); + + // section("Number.int()"); + // code("int(15.1)").equals("15"); + // code("int(15.5)").equals("15"); + // code("int(15.9)").equals("15"); + + // section("Number.isInteger()"); + // code("isInteger(12)").equals("true"); + // code("isInteger(0)").equals("true"); + // code("isInteger(-5)").equals("true"); + // code("isInteger(12.9)").equals("false"); + // code("isInteger(-5.2)").equals("false"); + // code("isInteger(π)").equals("false"); + // code("12.isInteger()").equals("true"); + // code("12.5.isInteger()").equals("false"); + // code("[12, 0][0].isInteger()").equals("true"); + // code("[12.5, 0][0].isInteger()").equals("false"); + + // section("Number.fold"); + // code("1234567.fold((x, y) -> x + y, 0)").equals("28"); + // code("1234567.fold((x, y) -> x + y, 1000)").equals("1028"); + // code("1234567.fold((x, y) -> x * y, 1)").equals("5040"); + // code("1234567.fold((x, y) -> x + y ** 2, 0)").equals("140"); + + section("Number.hypot"); + code("return hypot(3, 4)").equals("5.0"); + // code("return 3.hypot(4)").equals("5"); + code("return hypot(34, 74)").almost(81.437092286); + code("return hypot([34, ''][0], 74)").almost(81.437092286); + + section("Number.signum"); + // code("0.signum()").equals("0"); + // code("-0.signum()").equals("0"); + // code("12.signum()").equals("1"); + // code("12.5.signum()").equals("1"); + // code("-12.signum()").equals("-1"); + // code("-12.5.signum()").equals("-1"); + code("return signum(0)").equals("0"); + code("return signum(12)").equals("1"); + code("return signum(-17)").equals("-1"); + code("return signum(-12.5)").equals("-1"); + code("return signum(85)").equals("1"); + + section("Number.sqrt"); + code("return sqrt(2)").almost(Math.sqrt(2)); + // code("return sqrt(123456789123456789123456789)").equals("11111111066111"); + // code("return sqrt(55m ** 20m)").equals("253295162119140625"); + // code("return sqrt(12m + 5m)").equals("4"); + // code("return var n = 12; n.sqrt()").equals("3.4641016151"); + // code("return let f = sqrt f(5)").equals("2.2360679775"); + code("return sqrt(16)").equals("4.0"); + code("return sqrt(25)").equals("5.0"); + + section("Number.toDegrees"); + // code("return π.toDegrees()").equals("180"); + // code("return (π / 2).toDegrees()").equals("90"); + // code("return (-π / 2).toDegrees()").equals("-90"); + // code("return 0.toDegrees()").equals("0"); + code("return toDegrees(PI)").equals("180.0"); + code("return toDegrees(PI / 2)").equals("90.0"); + code("return toDegrees(-PI / 2)").equals("-90.0"); + code("return toDegrees(0)").equals("0.0"); + + section("Number.toRadians"); + // code("return 180.toRadians()").almost(Math.PI); + // code("return 90.toRadians()").almost(Math.PI / 2); + // code("return (-90).toRadians()").almost(-Math.PI / 2); + // code("return 0.toRadians()").equals("0"); + code("return toRadians(180)").almost(Math.PI); + code("return toRadians(90)").almost(Math.PI / 2); + code("return toRadians(-90)").almost(-Math.PI / 2); + code("return toRadians(0)").equals("0.0"); + + section("Number.log"); + // code("1.log()").equals("0"); + code("return log(1)").equals("0.0"); + code("return log(E)").equals("1.0"); + // code("123456.log()").equals("11.7236400963"); + code("return log(654321)").almost(13.3913533357); + code("return log([55555, ''][0])").almost(10.9251288); + + section("Number.log10"); + code("return log10(10)").equals("1.0"); + // code("return 1.log10()").equals("0"); + // code("return 123456.log10()").equals("5.0915122016"); + code("return log10(654321)").almost(5.8157908589); + code("return log10([55555, ''][0])").almost(4.7447231519); + + section("Number.pow"); + // code("2.pow(10)").equals("1024"); + code("return pow(5, 3)").equals("125.0"); + code("return pow(2, 10)").equals("1024.0"); + // code("pow([10, ''][0], 5)").equals("100000"); + // code("3000.pow(3)").equals("2147483648"); + // code("return pow(3000, 3)").equals("2147483648"); + // code("3000l.pow(3)").equals("27000000000"); + + // section("Object-like calls"); + // code("(-12).abs()").equals("12"); + // code("π.cos()").equals("-1"); + // code("(π / 2).sin()").equals("1"); + // code("12.sqrt()").almost(3.464101615137754386); + // code("12.8.floor()").equals("12"); + // code("-12.8.floor()").equals("-12"); + // code("(-12.8).floor()").equals("-13"); + // code("12.2.ceil()").equals("13"); + // code("12.8.round()").equals("13"); + // code("-12.8.round()").equals("-13"); + // code("2.pow(10)").equals("1024"); + // code("0.isInteger()").equals("true"); + // code("56.7.isInteger()").equals("false"); + // code("(-56.7).isInteger()").equals("false"); + // code("3.max(5)").equals("5"); + // code("5.max(3)").equals("5"); + + // section("Combinated"); + // code("3.max(5).min(2)").equals("2"); + // code("3.max(5).max(10).max(12)").equals("12"); + // code("10.max(5).max(8.7).max(-3.91)").equals("10"); + // code("10.sqrt().cos()").almost(-0.99978607287932586); + + // section("Number.isPrime()"); + // code("0.isPrime()").equals("false"); + // code("1.isPrime()").equals("false"); + // code("2.isPrime()").equals("true"); + // code("3.isPrime()").equals("true"); + // code("4.isPrime()").equals("false"); + // code("5.isPrime()").equals("true"); + // code("1993.isPrime()").equals("true"); + // code("3972049.isPrime()").equals("false"); + // code("(1993l).isPrime()").equals("true"); + // code("4398042316799.isPrime()").equals("true"); + // code("(4398042316799m).isPrime() >= 1").equals("true"); + // code("359334085968622831041960188598043661065388726959079837.isPrime()").equals("1"); + // code("(146m ** 45m).isPrime()").equals("0"); + // code("1993l.isPrime()").equals("true"); + // code("1993m.isPrime()").equals("2"); + + // section("Number.rand()"); + // code("var a = rand() a >= 0 and a <= 1").equals("true"); + // code("var a = rand() a > 1").equals("false"); + // code("var a = randInt(2067, 2070) a >= 2067 and a < 2070").equals("true"); + // code("var a = randFloat(500, 510) a >= 500 and a < 510 and !a.isInteger()").equals("true"); + } +} diff --git a/src/test/java/test/TestOperators.java b/src/test/java/test/TestOperators.java index 27b4ddf8..1727ac1c 100644 --- a/src/test/java/test/TestOperators.java +++ b/src/test/java/test/TestOperators.java @@ -1,182 +1,95 @@ package test; -import static org.junit.Assert.fail; - -import org.junit.Before; - -import leekscript.runner.AI; -import leekscript.runner.LeekFunctions; -import leekscript.runner.LeekOperations; -import leekscript.runner.values.AbstractLeekValue; -import leekscript.runner.values.ArrayLeekValue; -import leekscript.runner.values.BooleanLeekValue; -import leekscript.runner.values.DoubleLeekValue; -import leekscript.runner.values.FunctionLeekValue; -import leekscript.runner.values.IntLeekValue; -import leekscript.runner.values.NullLeekValue; -import leekscript.runner.values.StringLeekValue; - -import org.junit.Test; - -public class TestOperators { - - AI ai; - - @Before - public void init() throws Exception { - ai = new TestAI(); - } - - @Test - public void simpleEqualsOperators() throws Exception { - try { - AI uai = new TestAI(); - if (!LeekOperations.equals(uai, new StringLeekValue("Chaine1"), new StringLeekValue("Chaine1")).getBoolean()) - fail("Chaine1 != Chaine1"); - if (LeekOperations.equals(uai, new StringLeekValue("Chaine1"), new StringLeekValue("Chaine2")).getBoolean()) - fail("Chaine1 == Chaine2"); - if (!LeekOperations.equals(uai, new BooleanLeekValue(false), new BooleanLeekValue(false)).getBoolean()) - fail("false != false"); - if (!LeekOperations.equals(uai, new BooleanLeekValue(true), new BooleanLeekValue(true)).getBoolean()) - fail("true != true"); - if (LeekOperations.equals(uai, new BooleanLeekValue(false), new BooleanLeekValue(true)).getBoolean()) - fail("false == true"); - if (LeekOperations.equals(uai, new BooleanLeekValue(true), new BooleanLeekValue(false)).getBoolean()) - fail("true == false"); - if (LeekOperations.equals(uai, new IntLeekValue(1), new IntLeekValue(2)).getBoolean()) - fail("1 == 2"); - if (LeekOperations.equals(uai, new IntLeekValue(-1), new IntLeekValue(-5)).getBoolean()) - fail("-1 == -5"); - if (!LeekOperations.equals(uai, new IntLeekValue(50), new IntLeekValue(50)).getBoolean()) - fail("50 != 50"); - if (!LeekOperations.equals(uai, new IntLeekValue(0), new IntLeekValue(0)).getBoolean()) - fail("0 != 0"); - if (!LeekOperations.equals(uai, new DoubleLeekValue(0), new DoubleLeekValue(0)).getBoolean()) - fail("0.0 != 0.0"); - if (!LeekOperations.equals(uai, new DoubleLeekValue(5), new DoubleLeekValue(5)).getBoolean()) - fail("5.0 != 5.0"); - if (LeekOperations.equals(uai, new DoubleLeekValue(45), new DoubleLeekValue(5)).getBoolean()) - fail("45.0 == 5.0"); - if (!LeekOperations.equals(uai, new NullLeekValue(), new NullLeekValue()).getBoolean()) - fail("null != null"); - if (!LeekOperations.equals(uai, new ArrayLeekValue(), new ArrayLeekValue()).getBoolean()) - fail("[] != []"); - if (!LeekOperations.equals(uai, new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(0) }), - new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(0) })) - .getBoolean()) - fail("[0] != [0]"); - if (!LeekOperations.equals(uai, new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(0), new IntLeekValue(1) }), - new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(0), new IntLeekValue(1) })).getBoolean()) - fail("[0,1] != [0,1]"); - if (LeekOperations.equals(uai, new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(0), new IntLeekValue(1) }), - new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(0) })).getBoolean()) - fail("[0,1] == [0]"); - - if (LeekOperations.equals(uai, new ArrayLeekValue(ai, new AbstractLeekValue[] { new StringLeekValue("Chaine1") }), - new ArrayLeekValue(ai, new AbstractLeekValue[] { new StringLeekValue("Chaine2") })).getBoolean()) - fail("[\"Chaine1\"] == [\"Chaine2\"]"); - if (!LeekOperations.equals(uai, new ArrayLeekValue(ai, new AbstractLeekValue[] { new StringLeekValue("Chaine1") }), - new ArrayLeekValue(ai, new AbstractLeekValue[] { new StringLeekValue("Chaine1") })).getBoolean()) - fail("[\"Chaine1\"] != [\"Chaine1\"]"); - - if (!LeekOperations.equals(uai, new FunctionLeekValue(1), new FunctionLeekValue(1)).getBoolean()) - fail("#F1 != #F1"); - if (LeekOperations.equals(uai, new FunctionLeekValue(1), new FunctionLeekValue(2)).getBoolean()) - fail("#F1 == #AF1"); - if (LeekOperations.equals(uai, new FunctionLeekValue(LeekFunctions.endsWith), new FunctionLeekValue(1)).getBoolean()) - fail("#endsWith == #AF1"); - if (!LeekOperations.equals(uai, new FunctionLeekValue(LeekFunctions.endsWith), new FunctionLeekValue(LeekFunctions.endsWith)).getBoolean()) - fail("#endsWith != #endsWith"); - } catch (Exception e) { - fail(e.getMessage()); - } - } - - @Test - public void advancedEqualsOperators() { - try { - // String-Intger - AI uai = new TestAI(); - if (!LeekOperations.equals(uai, new StringLeekValue("1"), new IntLeekValue(1)).getBoolean()) - fail("\"1\" != 1"); - if (!LeekOperations.equals(uai, new StringLeekValue("0"), new IntLeekValue(0)).getBoolean()) - fail("\"0\" != 0"); - if (!LeekOperations.equals(uai, new StringLeekValue("10"), new IntLeekValue(10)).getBoolean()) - fail("\"10\" != 10"); - if (LeekOperations.equals(uai, new StringLeekValue("15"), new IntLeekValue(10)).getBoolean()) - fail("\"15\" == 10"); - if (!LeekOperations.equals(uai, new IntLeekValue(1), new StringLeekValue("1")).getBoolean()) - fail("1 != \"1\""); - if (!LeekOperations.equals(uai, new IntLeekValue(0), new StringLeekValue("0")).getBoolean()) - fail("0 != \"0\""); - if (!LeekOperations.equals(uai, new DoubleLeekValue(0), new StringLeekValue("0")).getBoolean()) - fail("0.0 != \"0\""); - if (!LeekOperations.equals(uai, new IntLeekValue(10), new StringLeekValue("10")).getBoolean()) - fail("10 != \"10\""); - if (!LeekOperations.equals(uai, new DoubleLeekValue(10), new StringLeekValue("10")).getBoolean()) - fail("10.0 != \"10\""); - if (LeekOperations.equals(uai, new IntLeekValue(10), new StringLeekValue("15")).getBoolean()) - fail("10 == \"15\""); - if (LeekOperations.equals(uai, new DoubleLeekValue(10), new StringLeekValue("15")).getBoolean()) - fail("10.0 == \"15\""); - if (!LeekOperations.equals(uai, new DoubleLeekValue(10.8), new StringLeekValue("10.8")).getBoolean()) - fail("10.8 != \"10.8\""); - if (LeekOperations.equals(uai, new DoubleLeekValue(10.8), new StringLeekValue("10.87")).getBoolean()) - fail("10.8 == \"10.87\""); - - if (!LeekOperations.equals(uai, new BooleanLeekValue(true), new StringLeekValue("true")).getBoolean()) - fail("true != \"true\""); - if (!LeekOperations.equals(uai, new BooleanLeekValue(false), new StringLeekValue("false")).getBoolean()) - fail("false != \"false\""); - if (LeekOperations.equals(uai, new BooleanLeekValue(true), new StringLeekValue("false")).getBoolean()) - fail("true == \"false\""); - if (LeekOperations.equals(uai, new BooleanLeekValue(false), new StringLeekValue("true")).getBoolean()) - fail("false == \"true\""); - - if (!LeekOperations.equals(uai, new IntLeekValue(1), new StringLeekValue("true")).getBoolean()) - fail("1 != \"true\""); - if (!LeekOperations.equals(uai, new IntLeekValue(0), new StringLeekValue("false")).getBoolean()) - fail("0 != \"false\""); - if (!LeekOperations.equals(uai, new IntLeekValue(12), new StringLeekValue("true")).getBoolean()) - fail("12 != \"true\""); - if (LeekOperations.equals(uai, new IntLeekValue(2), new StringLeekValue("false")).getBoolean()) - fail("2 == \"false\""); - - if (!LeekOperations.equals(uai, new IntLeekValue(0), new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(0) })).getBoolean()) - fail("0 != [0]"); - if (!LeekOperations.equals(uai, new IntLeekValue(1), new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(1) })).getBoolean()) - fail("1 != [1]"); - if (!LeekOperations.equals(uai, new IntLeekValue(0), new ArrayLeekValue()).getBoolean()) - fail("0 != []"); - if (!LeekOperations.equals(uai, new BooleanLeekValue(false), new ArrayLeekValue()).getBoolean()) - fail("0 != []"); - } catch (Exception e) { - fail(e.getMessage()); - } - } - - @Test - public void tripleEqualsTest() throws Exception { - - AbstractLeekValue[] values = new AbstractLeekValue[] { new IntLeekValue(0), new IntLeekValue(1), - new IntLeekValue(12), new DoubleLeekValue(13), new BooleanLeekValue(false), - new BooleanLeekValue(true), new NullLeekValue(), new StringLeekValue("true"), - new StringLeekValue("false"), new StringLeekValue("12"), - new StringLeekValue("lama"), - new ArrayLeekValue(), new ArrayLeekValue(ai, new AbstractLeekValue[] { - new StringLeekValue("12") }) }; - - int i, j; - for (i = 0; i < values.length; i++) { - for (j = 0; j < values.length; j++) { - if (LeekOperations.equals_equals(ai, values[i], values[j]).getBoolean() != (i == j)) - fail(values[i].getString(ai) + ((i == j) ? "!==" : "===") + values[j].getString(ai)); +public class TestOperators extends TestCommon { + + public void run() throws Exception { + + code("return 'Chaine1' == 'Chaine1'").equals("true"); + code("return 'Chaine1' == 'Chaine2'").equals("false"); + code("return false == false").equals("true"); + code("return true == true").equals("true"); + code("return false == true").equals("false"); + code("return true == false").equals("false"); + code("return 1 == 2").equals("false"); + code("return -1 == -5").equals("false"); + code("return 50 == 50").equals("true"); + code("return 0 == 0").equals("true"); + code("return 0 == 0").equals("true"); + code("return 5 == 5").equals("true"); + code("return 45 == 5").equals("false"); + code("return null == null").equals("true"); + code("return [] == []").equals("true"); + code("return [0] == [0]").equals("true"); + code("return [0, 1] == [0, 1]").equals("true"); + code("return [0, 1] == [0]").equals("false"); + code("return ['Chaine1'] == ['Chaine2']").equals("false"); + code("return ['Chaine1'] == ['Chaine1']").equals("true"); + code("return function() {} == function() {}").equals("false"); + code("return endsWith == function() {}").equals("false"); + code("return endsWith == endsWith").equals("true"); + + code("return '1' == 1").equals("true"); + code("return '0' == 0").equals("true"); + code("return '10' == 10").equals("true"); + code("return '15' == 10").equals("false"); + code("return 1 == '1'").equals("true"); + code("return 0 == '0'").equals("true"); + code("return 0 == '0'").equals("true"); + code("return 10 == '10'").equals("true"); + code("return 10 == '10'").equals("true"); + code("return 10 == '15'").equals("false"); + code("return 10 == '15'").equals("false"); + code("return 10.8 == '10.8'").equals("true"); + code("return 10.8 == '10.87'").equals("false"); + code("return true == 'true'").equals("true"); + code("return false == 'false'").equals("true"); + code("return true == 'false'").equals("false"); + code("return false == 'true'").equals("false"); + code("return 1 == 'true'").equals("true"); + code("return 0 == 'false'").equals("true"); + code("return 12 == 'true'").equals("true"); + code("return 2 == 'false'").equals("false"); + code("return 0 == [0]").equals("true"); + code("return 1 == [1]").equals("true"); + code("return 0 == []").equals("true"); + code("return false == []").equals("true"); + code("return false == 0").equals("true"); + code("return false != 0").equals("false"); + code("return true != 1").equals("false"); + + Object[] values = new Object[] { "0", "1", + "12", "13", "false", + "true", "null", "'true'", + "'false'", "'12'", + "'lama'", + "[]", "['12']" }; + + for (int i = 0; i < values.length; i++) { + for (int j = 0; j < values.length; j++) { + code("return " + values[i] + " === " + values[j]).equals(String.valueOf(i == j)); } } - - if (!LeekOperations.equals_equals(ai, new IntLeekValue(1), new DoubleLeekValue(1)).getBoolean()) - fail("1 !== 1.0"); - if (!LeekOperations.equals_equals(ai, new DoubleLeekValue(12), new IntLeekValue(12)).getBoolean()) - fail("12.0 !== 12"); + code("return 1 === 1.0").equals("true"); + code("return 12 === 12.0").equals("true"); + + code("var a = 1; var result = -10 + (1- (a-1)); return result").equals("-9"); + code("var a = 1; var result = 0; result = -10 + (1- (a-1)); return result").equals("-9"); + + code("return null < 3").equals("true"); + code("var a = null return a < 3").equals("true"); + code("return true < 10").equals("true"); + code("return false < 10").equals("true"); + code("return 10 < true").equals("false"); + code("return 10 < false").equals("false"); + code("return 10 > true").equals("true"); + code("return 10 > false").equals("true"); + code("return true > 10").equals("false"); + code("return false > 10").equals("false"); + + code("var a = 20 if (15 > a > 11) { return true } return false").equals("false"); + code("return 15 > 14 > 11 and 150 < 200 < 250").equals("false"); + code("return 15 > 10 > 11 and 150 < 200 < 250").equals("false"); + code("return 15 > 14 > 11 and 150 < 100 < 250").equals("false"); + code("return 15 > 10 > 11 and 150 < 100 < 250").equals("false"); } } diff --git a/src/test/java/test/TestReference.java b/src/test/java/test/TestReference.java new file mode 100644 index 00000000..13291c3c --- /dev/null +++ b/src/test/java/test/TestReference.java @@ -0,0 +1,23 @@ + + +package test; + +public class TestReference extends TestCommon { + + public void run() throws Exception { + + section("Références"); + code_v10("var t = [3, 4, 5]; var a = @t[1] a++ return t;").equals("[3, 4, 5]"); + code_v10("var t = [3, 4, 5]; var a = null a = @t[1] a++ return t;").equals("[3, 4, 5]"); + code_v10("var t = 0; var f = function(a) { t = a }; var b = []; f(b); push(t, 5); return [t, b];").equals("[[5], []]"); + code_v10("var t = 0; var f = function(a) { t = @a }; var b = []; f(b); push(t, 5); return b;").equals("[]"); + code_v10("var t = 0; var f = function(@a) { t = @a }; var b = []; f(b); push(t, 5); return b;").equals("[5]"); + code_v10("var t = 0; var f = function(a) { t; }; f(t); return 'ok';").equals("ok"); + code_v10("function ref() { var a = 2; return @a; } return 1 / ref();").equals("0.5"); + code_v10("var a = @[1, 2, 3]; var b = @a; return (@(b));").equals("[1, 2, 3]"); + code_v10("var count = count([1, 2, 3]) return count").equals("3"); + code_v10("var a = 12; var b = @a; a++; return [a, b]").equals("[13, 12]"); + code_v10("var a = 12; var b = @a; var c = @b; a++; return [a, b, c]").equals("[13, 12, 12]"); + code_v10("var a = [12]; var b = @a[0]; a[0]++; return [a, b]").equals("[[13], 12]"); + } +} diff --git a/src/test/java/test/TestString.java b/src/test/java/test/TestString.java new file mode 100644 index 00000000..10d040c7 --- /dev/null +++ b/src/test/java/test/TestString.java @@ -0,0 +1,51 @@ +package test; + +public class TestString extends TestCommon { + + public void run() { + + section("String.charAt()"); + code("return charAt('bonjour', 1)").equals("o"); + + section("String.length()"); + code("return length('bonjour')").equals("7"); + + section("String.substring()"); + code("return substring('bonjour',2,3)").equals("njo"); + + section("String.replace()"); + code("return replace('bonjour','onj','pro')").equals("bproour"); + + section("String.indexOf()"); + code("return indexOf('bonjour','o')").equals("1"); + code("return indexOf('bonjour','o',2)").equals("4"); + + section("String.split()"); + code("return split('1:2:3:4:5',':')").equals("[1, 2, 3, 4, 5]"); + code("return split('1:2:3:4:5',':',2)").equals("[1, 2:3:4:5]"); + + section("String.toLower()"); + code("return toLower('AbCDefgh')").equals("abcdefgh"); + + section("String.toUpper()"); + code("return toUpper('AbCDefgh')").equals("ABCDEFGH"); + + section("String.startsWith()"); + code("return startsWith('bonjour','bon')").equals("true"); + code("return startsWith('bonjour','jour')").equals("false"); + + section("String.endsWith()"); + code("return endsWith('bonjour','bon')").equals("false"); + code("return endsWith('bonjour','jour')").equals("true"); + + section("String.contains()"); + code("return contains('bonjour','bon')").equals("true"); + code("return contains('bonjour','jour')").equals("true"); + code("return contains('bonjour','jourr')").equals("false"); + + section("String.number()"); + code("return contains('bonjour','bon')").equals("true"); + code("return contains('bonjour','jour')").equals("true"); + code("return contains('bonjour','jourr')").equals("false"); + } +} diff --git a/src/test/java/test/TestWithFile b/src/test/java/test/TestWithFile new file mode 100644 index 00000000..4c8974ea --- /dev/null +++ b/src/test/java/test/TestWithFile @@ -0,0 +1,65 @@ +package test; + +import leekscript.compiler.AIFile; +import leekscript.compiler.LeekScript; +import leekscript.compiler.resolver.ResolverContext; +import leekscript.compiler.resolver.Resolver; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class TestWithFile { + + @Test + public void testBasicFile() throws Exception { + assertEquals("bonjour", LeekScript.runFile("ai/bonjour.leek")); + } + + @Test + public void testLargeFile() throws Exception { + assertEquals("cent-vingt-trois millions quatre-cent-cinquante-six-mille-sept-cent-quatre-vingt-neuf", LeekScript.runFile("ai/french.leek")); + } + + @Test + public void testInclude() throws Exception { + assertEquals("[a, b, KEY]", LeekScript.runFile("ai/array_keys.leek")); + } + + @Test + public void testIncludeMultiple() throws Exception { + assertEquals("[a, b, KEY]", LeekScript.runFile("ai/include_multiple.leek")); + } + + @Test + public void testCustomResolver() throws Exception { + class CustomContext extends ResolverContext {} + LeekScript.setResolver(new Resolver() { + @Override + public AIFile resolve(String path, ResolverContext context) { + return new AIFile(path, "return 'generated';", System.currentTimeMillis(), 11, new CustomContext()); + } + @Override + public ResolverContext createContext(int parameter1, int parameter2, int parameter3) { + return null; + } + }); + assertEquals("generated", LeekScript.runFile("whatever")); + LeekScript.resetResolver(); + } + + @Test + public void testSubFolder() throws Exception { + assertEquals("sub", LeekScript.runFile("ai/include_sub.leek")); + } + + @Test + public void testRelativePath() throws Exception { + assertEquals("cent-vingt-trois millions quatre-cent-cinquante-six-mille-sept-cent-quatre-vingt-neuf", LeekScript.runFile("ai/subfolder/include_parent.leek")); + } + + @Test + public void testMultipleInclude() throws Exception { + assertEquals("bonjour", LeekScript.runFile("ai/multiple_includes.leek")); + } +} diff --git a/src/test/resources/ai/array_keys.leek b/src/test/resources/ai/array_keys.leek new file mode 100644 index 00000000..c0205278 --- /dev/null +++ b/src/test/resources/ai/array_keys.leek @@ -0,0 +1,5 @@ +include("library.leek"); + +var array = ['a': 12, 'b': 13, 'KEY': 15]; + +return arrayKeys(array); \ No newline at end of file diff --git a/src/test/resources/ai/bonjour.leek b/src/test/resources/ai/bonjour.leek new file mode 100644 index 00000000..df3498c4 --- /dev/null +++ b/src/test/resources/ai/bonjour.leek @@ -0,0 +1 @@ +return 'bonjour'; \ No newline at end of file diff --git a/src/test/resources/ai/code/ai.leek b/src/test/resources/ai/code/ai.leek new file mode 100644 index 00000000..c33143d7 --- /dev/null +++ b/src/test/resources/ai/code/ai.leek @@ -0,0 +1,51 @@ +function isWeapon(w) { + if (w == 12) return true + return false +} +function isChip(w) { + if (w != 12) return true + return false +} +function getChipCooldown(x) { + return 0 +} +function count(array) { + return Array.size(array) +} +function inArray(array, element) { + return Array.contains(array, element) +} + +function _partition(n, si, items, added) { + + var combos = []; + for (var i = si; i < count(items); i++) { + + var item = items[i]; + var cost = item[1]; + + if (isWeapon(item[0]) && inArray(added, item)) cost--; + + if (cost > n) continue; + + if (isChip(item[0]) && getChipCooldown(item[0]) > 0 && inArray(added, item)) continue; + + added += item; + + var subs = _partition(n - cost, i, items, added); + if (count(subs) > 0) { + for (var sub in subs) { Array.push(combos, [ + [item[0], cost] + ] + sub); } + } else { + Array.push(combos, [ + [item[0], cost] + ]); + } + } + combos; +} + +var items = [12, 5, 18] + +_partition(10, 0, items, []) diff --git a/src/test/resources/ai/code/array.leek b/src/test/resources/ai/code/array.leek new file mode 100644 index 00000000..ce976968 --- /dev/null +++ b/src/test/resources/ai/code/array.leek @@ -0,0 +1,12 @@ +var a = [] +let n = 12345 + +for (var i = 0; i < n; ++i) { + a += i +} + +var b = a.filter(x -> x > 11111) +a = a.map(x -> x + 12).filter(x -> x < 11999) +a = a.map(x -> x - 9999) + +a.foldLeft(x, y -> x + y, -1000) diff --git a/src/test/resources/ai/code/assignments.leek b/src/test/resources/ai/code/assignments.leek new file mode 100644 index 00000000..28bc0a48 --- /dev/null +++ b/src/test/resources/ai/code/assignments.leek @@ -0,0 +1,19 @@ +function f() { + var y + var x = 15 + if (false) { + if (true) { + return; + } else { + y = x + } + } else { + if (true) { + y = x + } else { + y = x + } + } + return y +} +return f(); diff --git a/src/test/resources/ai/code/break_and_continue.leek b/src/test/resources/ai/code/break_and_continue.leek new file mode 100644 index 00000000..1cf2a56c --- /dev/null +++ b/src/test/resources/ai/code/break_and_continue.leek @@ -0,0 +1,25 @@ +var values = [] + +for var i = 0; i < 10; ++i { + var b = [] + for var j = 0; j < 10; ++j { + var c = [] + for var k = 1; k <= 30; ++k { c += k } + b += [c] + } + values += [b] +} + +var sum = 0 +for v in values { + for w in v { + for x in w { + if x % 2 { continue } + if x == 18 { continue 2 } + sum += x + if (sum > 2500) { break 3 } + } + } +} + +sum diff --git a/src/test/resources/ai/code/catch_else.leek b/src/test/resources/ai/code/catch_else.leek new file mode 100644 index 00000000..d65fcb03 --- /dev/null +++ b/src/test/resources/ai/code/catch_else.leek @@ -0,0 +1 @@ +[][0] !? 6 \ No newline at end of file diff --git a/src/test/resources/ai/code/class.txt b/src/test/resources/ai/code/class.txt new file mode 100644 index 00000000..2168f48a --- /dev/null +++ b/src/test/resources/ai/code/class.txt @@ -0,0 +1,31 @@ +class A extends B { + const STATIC_CLASS_CONSTANT = 12; + let constant_field + var mutable_field = 0 + constructor(a) => constant_field = a + constructor() { + mutable_field = 12 + } + update() { ... } + update2() => ... + let f = () => 'salut' // function field +} +class Operation { + let op = + + constructor(op) => this.op = op + operator () (a, b) { + return op(a, b) + } + run(a, b) => op(a, b) +} +let plus = new Operation(×) +plus(5, 6) +plus.run(5, 6) + +var a +const a +var a = [] +function() { return 'salut' } +function m() { return 'salut' } +() => 'salut' +m() => 'salut' \ No newline at end of file diff --git a/src/test/resources/ai/code/classes_multiple.leek b/src/test/resources/ai/code/classes_multiple.leek new file mode 100644 index 00000000..4c0fbf09 --- /dev/null +++ b/src/test/resources/ai/code/classes_multiple.leek @@ -0,0 +1,22 @@ +class Engine { + power = 5000 +} +class Wheel { + diameter = 45.7 +} +class Car { + // engine = new Engine() + wheels = [] +} + +var ferrari = new Car() +for (var i in [1, 2, 3, 4]) { + var w = new Wheel() + w.diameter = i * 20 + push(ferrari.wheels, w) +} + +// TODO not working +// ferrari.wheels.foldLeft((x, s) -> s + x.diameter, 0) + +return [count(ferrari.wheels), ferrari.wheels[1].diameter, ferrari.wheels[3].diameter]; diff --git a/src/test/resources/ai/code/classes_simple.leek b/src/test/resources/ai/code/classes_simple.leek new file mode 100644 index 00000000..5e0459fb --- /dev/null +++ b/src/test/resources/ai/code/classes_simple.leek @@ -0,0 +1,14 @@ +class Car { + name = "" + engine = 5000 +} + +var ferrari = Car() +var maserati = new Car() +var lamborghini = new Car() + +ferrari.name = "Ferrari" +maserati.name = "Maserati" +lamborghini.name = "Lamborghini" + +return [ferrari.name, maserati.name, lamborghini.name]; diff --git a/src/test/resources/ai/code/code.ls b/src/test/resources/ai/code/code.ls new file mode 100644 index 00000000..8ccdf20e --- /dev/null +++ b/src/test/resources/ai/code/code.ls @@ -0,0 +1,330 @@ +/* + * Commentaire large + */ + +/* Commentaire /* Imbriqué */ */ + +/* Commentaire commenté +// */ +*/ + +// Déclaration de variables + +let e +let b = 2 +let c, d = "salut" +let k, f = 12, 5 // Commentaire à la fin +let g, h, i = 12 +global super + + +// Points virgules +var aa = 2; + +// Nombres à virgule + +__debug(12.56 - 2) +12.4 +100.0001 + + +// Chaines + +let a = '', b = "" +a = 'bonjour ça va ?' +'toto' +b = "double quotes" +let cc = " 'salut', 'yeah' " + + +// Tableaux + +let a1 = [] +let a2 = [1, 2, 3] +let a3 = [3: 12, "toto": 5] +let b2 = [12, "toto", 1.1, [1, 2, 3]] +let cles = [1: 12, 3: 5, "lama": 177] + +__debug(a1) +__debug(a2) +__debug(a3) +__debug(cles) + +__debug(a2[1]) +__debug(a3['toto']) +__debug(a2[1]) +__debug(cles["lama"]) + +//__debug(b2[toto:5]) +//__debug(b2[1:12][5:6]) + +// Swap + +// a <-> b +// a <=> b + + +// Objets + +let array = [1, 2, 3] +let o = {x: 2, y: 13, z: {a: 2}} +let compound = {x: 2, other: {val: 7, tab: [1, 2, 3]}, y: 'zzz'} + +__debug(o) +__debug(compound) + +__debug(array.size) +__debug(array.0) +__debug(o.size) +__debug(o.x) +__debug(o.z.a) +__debug(compound.other.tab[1]) + +__debug(2.class) +__debug("salut".class) +__debug({x: 12}.class) +__debug([7,"a"].class) +__debug((x -> x + 5).class) + +// Conditions + +if array is not null and a is 'z' { + let c = 13 +} else { + print("yeah") +} + +if cc or cles { + print(a) +} + +if c then print(c) else !12 xor -5 end +if a then print(a) else { + let c = 12 +} +if (a != 2) { + print(a) +} + + +// Fonctions et Lambdas + +let f1 = function(x, y = 2, z = false) return 0 end + +let f2 = function(x = "salut", y, z) { + return x * x +} + +let f3 = function(x) return x end +let f4 = -> -> -> 127 +let f9 = x,y -> [y: x, x: y] +let f10 = x,y -> z -> [[x,z], [y,z], -> x+y+z] + +getLife(12) + +[1, 2, 3].sort(a,b -> a < b) +[1, 2, 3].reverse().first().abs() + 5 ^ 2 + +let f5 = x -> x ^ 2 +let g2 = x, y, z -> x * y * z +let h2 = -> "salut" +getCell(-> 12) + +let o2 = i,j -> a,b -> i * b + j * a +a -> b -> 2 + a -> c, d -> 5 and print("yeah") +var res = getLife(x -> getID(x)) + +__debug(f1(1, 2, true)) +__debug(f2("salut")) +__debug(f4()()()) +__debug(f9(4, "salut")) +let ress = f10(5,6)(100) +__debug(ress) +__debug(ress[2]()) + + +// Accents + +let état = "test" +let àôé = 2 + + +// Opérations diverses + +2 + 1 +'bonjour ça va ?' 5 [1,2] + 4 a = (2 || b) c - 12 +let ccc = 16 + b - 5 +let ddd = 4 * "salut" / true +let x = 2['salut' - 1] && true || false xor 1 + +let vv = -15 +__debug(vv.abs()) + + +// Signes moins +-1 +2 - 5 +4 + -5 +-10 - -10 +- (5 - (-7)) - +-4 + +(-5 - -13) - (-3) + + +// Opérations sur plusieurs lignes +5 +-4 + +5 - +4 + +5 +- 4 + +b += +a +- +5 ++ +"a" + + +// Opérateurs préfixes + +-2 +not false +!"salut" +new a + +// Parenthèses + +(5) * (4 + 2) - 7 / (4 - (((5)))) +print(f(a) + 5) + +// Classes + +class Combo { + + let score = 12 + + let new = function(score = 0) { + this.score = score + } + + let b = x -> x + 1 + + let update = function() { + score = score + 1 + return score + } + let updateSimple = -> ++score +} + +class Test {} + +let combo = new Combo(12) +let combo2 = new Combo() +let combo3 = Combo.new(13) +combo3.score = 55 +combo3.update() + +// Closures + +var ext = 55 +var fun = function(a) { // [ext] + + let b = 12 + let c = function(d) { // [b, ext] + return function(e) { [a, b, ext] + return a + b + d + e + ext + } + } + return c +} + +// Opérateurs en mode fonctions + +var plus = + +let minus = - +let modulo = (%) +var ternary = (?:) +array.map(+) + +var array = [ [true, 10, 12], [false, 5, 7] ] +var res1 = array.map(?:).transform(10, ^, +) + +// Valeurs absolues + +var res2 = |pos - 12| +var dd = |5 - |pos + 5| | +var dist = |getX(celll) - getY(|cell.pos.x|)| + +12.abs() +12.5.abs() + +a === b +a !== b +!!a +!!!!!a + +a-- +b++ +--c +++d +a *= b +b -= a +c /= e +g %= r +p ^= z + +p = ++(i++ ^ --z % ++z--)-- +a -- +++ a +a = -b++ +12 + +// Opérateur de fonction + +var yoyo = x -> x + " !" +var yo = "salut" +yo ->= yoyo +yo ~= yoyo // yo = "salut !" +yo ()= yoyo + + +// Boucles for + +for ;; {} +for ;; do end +for (;;) {} +for ; ; { + print("salut") +} + +for let i;; {} +for let i = 0;; {} +for let i = 0; i < 10; i++ {} +for let i = 0, j; i < 10; i++ {} +for i,j,let k = 2, l = "salut"; k !== "lama"; l++ {} +for let i,j, let k ;; {} + +for let i; i < 10; i++ do + print(i + 100) +end + +// Foreach + +for i in array {} +for i,j in array {} +for i:j in array do end +for let i,j in array {} +for let i, let j in array {} + +for leek in getLeeks() do + print(leek.getLife()) + for i in leek.cells { + print(i + 1) + } + leek.cells.each(x -> print(x)) +end diff --git a/src/test/resources/ai/code/divisors.leek b/src/test/resources/ai/code/divisors.leek new file mode 100644 index 00000000..e44a6af5 --- /dev/null +++ b/src/test/resources/ai/code/divisors.leek @@ -0,0 +1,2 @@ +var divisors = function(n) { return [1..n.sqrt()].filter(x -> !(n % x) } +return divisors(1989); \ No newline at end of file diff --git a/src/test/resources/ai/code/dynamic_operators.leek b/src/test/resources/ai/code/dynamic_operators.leek new file mode 100644 index 00000000..c8a3eb6a --- /dev/null +++ b/src/test/resources/ai/code/dynamic_operators.leek @@ -0,0 +1,5 @@ +// Add more iterations to test the speed of a simple operator +var a = 12$ +for var i = 0; i < 100; ++i { + a * 5 +} diff --git a/src/test/resources/ai/code/euler1.leek b/src/test/resources/ai/code/euler1.leek new file mode 100644 index 00000000..3dc514f6 --- /dev/null +++ b/src/test/resources/ai/code/euler1.leek @@ -0,0 +1,10 @@ +var n = 100000 + +var x3 = floor(n / 3) +var d3 = (x3 * (x3 + 1) / 2 | 0) * 3 +var x5 = floor((n - 1) / 5) +var d5 = (x5 * (x5 + 1) / 2 | 0) * 5 +var x15 = floor((n - 1) / 15) +var d15 = (x15 * (x15 + 1) / 2 | 0) * 15 + +return d3 + d5 - d15; diff --git a/src/test/resources/ai/code/fact1000.leek b/src/test/resources/ai/code/fact1000.leek new file mode 100644 index 00000000..b7facc22 --- /dev/null +++ b/src/test/resources/ai/code/fact1000.leek @@ -0,0 +1,5 @@ +var n = 1m +for var i = 1m; i < 1000m; i = i + 1m { + n = n * i +} +return n diff --git a/src/test/resources/ai/code/fibonacci.leek b/src/test/resources/ai/code/fibonacci.leek new file mode 100644 index 00000000..9f460cb9 --- /dev/null +++ b/src/test/resources/ai/code/fibonacci.leek @@ -0,0 +1,2 @@ +var fib = function(n) { return n < 2 ? n : fib(n - 1) + fib(n - 2) } +return fib(30); \ No newline at end of file diff --git a/src/test/resources/ai/code/fibonacci_long.leek b/src/test/resources/ai/code/fibonacci_long.leek new file mode 100644 index 00000000..723cc0f3 --- /dev/null +++ b/src/test/resources/ai/code/fibonacci_long.leek @@ -0,0 +1,2 @@ +let fib = n => n < 2 ? n : fib(n - 1) + fib(n - 2) +fib(31l) \ No newline at end of file diff --git a/src/test/resources/ai/code/fibonacci_v12.leek b/src/test/resources/ai/code/fibonacci_v12.leek new file mode 100644 index 00000000..98f27c7b --- /dev/null +++ b/src/test/resources/ai/code/fibonacci_v12.leek @@ -0,0 +1,2 @@ +let fib = n => n < 2 ? n : fib(n - 1) + fib(n - 2) +fib(30) \ No newline at end of file diff --git a/src/test/resources/ai/code/fold_left.leek b/src/test/resources/ai/code/fold_left.leek new file mode 100644 index 00000000..af15ffd5 --- /dev/null +++ b/src/test/resources/ai/code/fold_left.leek @@ -0,0 +1 @@ +[1, 3, 4, 2, 7, 5, 8, 9, 6].foldLeft((acc, x) -> acc.push({w: x}), []) diff --git a/src/test/resources/ai/code/fold_left_2.leek b/src/test/resources/ai/code/fold_left_2.leek new file mode 100644 index 00000000..b43a37b6 --- /dev/null +++ b/src/test/resources/ai/code/fold_left_2.leek @@ -0,0 +1,2 @@ +function ppair(p, v) { {p: p, v: v} } +[1, 3, 4, 2, 7, 5, 8, 9, 6].foldLeft((pq, x) -> ppair(x, pq), {}) diff --git a/src/test/resources/ai/code/fold_right.leek b/src/test/resources/ai/code/fold_right.leek new file mode 100644 index 00000000..c691fb5e --- /dev/null +++ b/src/test/resources/ai/code/fold_right.leek @@ -0,0 +1 @@ +[1, 3, 4, 2, 7, 5, 8, 9, 6].foldRight((x, acc) -> acc.push({w: x}), []) diff --git a/src/test/resources/ai/code/fold_right_2.leek b/src/test/resources/ai/code/fold_right_2.leek new file mode 100644 index 00000000..dfad76a3 --- /dev/null +++ b/src/test/resources/ai/code/fold_right_2.leek @@ -0,0 +1,2 @@ +function ppair(p, v) { {p: p, v: v} } +[1, 3, 4, 2, 7, 5, 8, 9, 6].foldRight((pq, x) -> ppair(x, pq), {}) diff --git a/src/test/resources/ai/code/french.leek b/src/test/resources/ai/code/french.leek new file mode 100644 index 00000000..2a35e717 --- /dev/null +++ b/src/test/resources/ai/code/french.leek @@ -0,0 +1,63 @@ +var french = function(n) { + var T = '-' + var V = '' + var x = split('s un deux trois quatre cinq six sept huit neuf dix onze douze treize quatorze quinze seize dix vingt trente quarante cinquante soixante quatre-vingt cent', ' ') + var b = n % 100 + var d = 17 + b / 10 + var u = n % 10 + var c = floor(n / 100) + var e = (u - 1) ? T : '-et-' + var L = floor(log10(n) / 3) + var H = pow(1000, L) + var v = floor(n / H) + if (x[d] == '') { d-- u += 10 } + var k = L > 1 ? 1 : 0 + var i = [T, ' '][k] + + if (L < 1) { + if (c) { + var r = '' + if (c > 1) { r = french(c) r += T } + r += x[27] + if (!(c * !b < 2)) { r += x[0] } + r += (b ? T : V) + french(b) + return r + } else { + if (n < 17) { + return x[n + 1] + } else { + if (n < 20) { + return x[11] + T + x[u + 1] + } else { + var r = x[d] + if (u) { + return r + e + french(u) + } else { + if (d == 25) { r += x[0] } + return r + } + } + } + } + } else { + var r = '' + if (L * v > 1) { r = french(v) + i } + r += 'mill' + r += ['', 'e', 'ion', 'iard'][L] + if (!(v < 2 or L < 2)) { r += x[0] } + if (n) { r += i } + n %= H + r += french(n) + return r + } +} + +return french(168489999); + +/* +for (var j = 0; j < 3; ++j) { + for (var i = 1; i < 5; ++i) { + var n = Number.randInt(1000 ** j, 1000 ** (j + 1)) + System.print(n + " ==> " + french(n)) + } +} diff --git a/src/test/resources/ai/code/french.min.leek b/src/test/resources/ai/code/french.min.leek new file mode 100644 index 00000000..64105b09 --- /dev/null +++ b/src/test/resources/ai/code/french.min.leek @@ -0,0 +1,5 @@ +function _(n) { + var T = '-', V = '', x = split('s un deux trois quatre cinq six sept huit neuf dix onze douze treize quatorze quinze seize dix vingt trente quarante cinquante soixante quatre-vingt cent' ' '), b = n % 100, d = (17 + b / 10) | 0, u = n % 10, c = floor(n / 100), e = u - 1 ? T : '-et-', L = (log10(n) / 3) | 0, H = 1000 ** L, v = floor(n / H), i = [T ' ' x[d] ? 0 : d-- or (u += 10)][L > 1] + return (L < 1) ? c ? (c > 1 ? _(c) + T : '') + x[27] + x[c * !b < 2] + (b ? T : '') + _(b) : n < 17 ? x[n + 1] : n < 20 ? x[11] + '-' + x[u + 1] : x[d] + (u ? e + _(u) : x[d != 25]) : (L * v > 1 ? _(v) + i : '') + 'mill' + [n %= H 'e' 'ion' 'iard'][L] + x[v < 2 or L < 2] + (n ? i : '') + _(n) +} +return _(987654321012); diff --git a/src/test/resources/ai/code/gcd.leek b/src/test/resources/ai/code/gcd.leek new file mode 100644 index 00000000..8028387f --- /dev/null +++ b/src/test/resources/ai/code/gcd.leek @@ -0,0 +1,10 @@ +var gcd = function(a, b) { + while (b > 0) { + var c = a % b + a = b + b = c + } + return a +} + +return gcd(163231, 135749); \ No newline at end of file diff --git a/src/test/resources/ai/code/global_functions_1.leek b/src/test/resources/ai/code/global_functions_1.leek new file mode 100644 index 00000000..d2e4c8ab --- /dev/null +++ b/src/test/resources/ai/code/global_functions_1.leek @@ -0,0 +1,7 @@ +var v = is_good(5, 6) + +function is_good(x, y) { + return x == y +} + +return v; diff --git a/src/test/resources/ai/code/global_functions_2.leek b/src/test/resources/ai/code/global_functions_2.leek new file mode 100644 index 00000000..56d770b1 --- /dev/null +++ b/src/test/resources/ai/code/global_functions_2.leek @@ -0,0 +1,9 @@ +function is_good(x, y) { + return inc(x) == inc(y) +} + +function inc(x) { + return x + 1 +} + +return [is_good(5, 6), is_good(6, 6)]; diff --git a/src/test/resources/ai/code/knapsack.leek b/src/test/resources/ai/code/knapsack.leek new file mode 100644 index 00000000..983b458f --- /dev/null +++ b/src/test/resources/ai/code/knapsack.leek @@ -0,0 +1,33 @@ +var items = [ + [37, 3], [47, 10], [28, 5], [89, 7], [55, 11], [11, 2], [75, 4] +] + +var all = []; +var aux; +aux = function(@current, i, tp, added, last) { + + if (count(current[1])) push(all, current); + var item_count = count(items); + + for (var j = i; j < item_count; ++j) { + var item = @items[j]; + var item_id = item[0]; + var cost = item[1]; + + if (cost > tp) continue; + + var new_added = added; + new_added[item_id] = true; + + var copy = current; + if (item_id === last) { + copy[1][count(copy[1]) - 1][2]++; + } else { + push(copy[1], @[item, cost, 1]); + } + copy[0] += cost; + aux(copy, j, tp - cost, new_added, item_id); + } +}; +aux([0, []], 0, 25, [], -1); +return count(all); \ No newline at end of file diff --git a/src/test/resources/ai/code/knapsack_11.leek b/src/test/resources/ai/code/knapsack_11.leek new file mode 100644 index 00000000..31caff9b --- /dev/null +++ b/src/test/resources/ai/code/knapsack_11.leek @@ -0,0 +1,32 @@ +var items = [ + [37, 3], [47, 10], [28, 5], [89, 7], [55, 11], [11, 2], [75, 4] +] + +var all = []; +var aux = function(current, i, tp, added, last) { + + if (count(current[1])) push(all, current); + var item_count = count(items); + + for (var j = i; j < item_count; ++j) { + var item = items[j]; + var item_id = item[0]; + var cost = item[1]; + + if (cost > tp) continue; + + var new_added = clone(added); + new_added[item_id] = true; + + var copy = current; + if (item_id === last) { + copy[1][count(copy[1]) - 1][2]++; + } else { + push(copy[1], [item, cost, 1]); + } + copy[0] += cost; + aux(copy, j, tp - cost, new_added, item_id); + } +}; +aux([0, []], 0, 25, [], -1); +return count(all); \ No newline at end of file diff --git a/src/test/resources/ai/code/match.leek b/src/test/resources/ai/code/match.leek new file mode 100644 index 00000000..e2212950 --- /dev/null +++ b/src/test/resources/ai/code/match.leek @@ -0,0 +1,6 @@ +let v = "oui" +match v { + "oui": print("Yeah!") + "non": print("snif") + ..: print("ok") +} \ No newline at end of file diff --git a/src/test/resources/ai/code/mul_array.leek b/src/test/resources/ai/code/mul_array.leek new file mode 100644 index 00000000..6a85f97b --- /dev/null +++ b/src/test/resources/ai/code/mul_array.leek @@ -0,0 +1,26 @@ +// TODO allow 'new' token in v1 + +function _mulArrays(arrays) { + + if (count(arrays) == 0) return [] + + var aux = function(stack, neww) { + var res = [] + for (var n in neww) { + for (var e in stack) { + push(res, e + [n]) + } + } + return res + } + + var res = arrayMap(shift(arrays), function(e) { + return [e] + }) + for (var array in arrays) { + res = aux(res, array) + } + return res +} + +_mulArrays([[1, 2, 3], [4, 5, 6]]) diff --git a/src/test/resources/ai/code/pow5.leek b/src/test/resources/ai/code/pow5.leek new file mode 100644 index 00000000..b99dcf99 --- /dev/null +++ b/src/test/resources/ai/code/pow5.leek @@ -0,0 +1,14 @@ +function pow5(p) { + var x = 1m + var n = 0 + while (p > 0) { + if ((p & 1) != 0) { + x *= 5m ** (1 << n) + } + p = p >> 1 + n++ + } + x +} + +pow5(57) \ No newline at end of file diff --git a/src/test/resources/ai/code/primes.leek b/src/test/resources/ai/code/primes.leek new file mode 100644 index 00000000..e578b64d --- /dev/null +++ b/src/test/resources/ai/code/primes.leek @@ -0,0 +1,17 @@ +var f = function(number) { + for (var k = 1; 36 * k * k - 12 * k < number; k += 1) { + if ((number % (6 * k + 1) == 0) or (number % (6 * k - 1) == 0)) { + return false + } + } + return true +} + +var c = 2 + +for (var i = 5; i < 1000000; i += 6) { + if (f(i)) ++c + if (f(i + 2)) ++c +} + +return c; diff --git a/src/test/resources/ai/code/primes_gmp.leek b/src/test/resources/ai/code/primes_gmp.leek new file mode 100644 index 00000000..84eb8306 --- /dev/null +++ b/src/test/resources/ai/code/primes_gmp.leek @@ -0,0 +1,9 @@ +var c = 0 + +for var i = 1m; i < 100000m; i += 2m { + if i.isPrime() > 0 { + c++ + } +} + +return c diff --git a/src/test/resources/ai/code/product_coproduct.leek b/src/test/resources/ai/code/product_coproduct.leek new file mode 100644 index 00000000..ba9226e4 --- /dev/null +++ b/src/test/resources/ai/code/product_coproduct.leek @@ -0,0 +1,8 @@ +function coProductN(n, i, acc) { + if (i == n) { + return i * acc; + } else { + return coProductN(n, i + 1, i * acc); + } +} +coProductN(69m, 1m, 1m) diff --git a/src/test/resources/ai/code/product_n.leek b/src/test/resources/ai/code/product_n.leek new file mode 100644 index 00000000..9c8cb6d6 --- /dev/null +++ b/src/test/resources/ai/code/product_n.leek @@ -0,0 +1,8 @@ +function productN(n) { + if (n == 1) { + 1m; + } else { + n * productN(n - 1); + } +} +productN(7m) diff --git a/src/test/resources/ai/code/product_n_arrays.leek b/src/test/resources/ai/code/product_n_arrays.leek new file mode 100644 index 00000000..99447dd8 --- /dev/null +++ b/src/test/resources/ai/code/product_n_arrays.leek @@ -0,0 +1,8 @@ +function productN(n) { + if n == [1] { + [1] + } else { + [n[0] * productN([n[0] - 1])[0]] + } +} +productN([7]) diff --git a/src/test/resources/ai/code/product_n_return.leek b/src/test/resources/ai/code/product_n_return.leek new file mode 100644 index 00000000..2a605cac --- /dev/null +++ b/src/test/resources/ai/code/product_n_return.leek @@ -0,0 +1,8 @@ +function productN(n) { + if (n == 1) { + return 1m; + } else { + return n * productN(n - 1); + } +} +productN(30m) diff --git a/src/test/resources/ai/code/project_euler_20.ls b/src/test/resources/ai/code/project_euler_20.ls new file mode 100644 index 00000000..b9f21434 --- /dev/null +++ b/src/test/resources/ai/code/project_euler_20.ls @@ -0,0 +1,30 @@ +var digits = [1] + +for var p = 1; p <= 100; p++ { + for var j = 0; j < digits.size(); j++ { + digits[j] *= p + } + for var i = 0; i < digits.size(); i++ { + if (9 < digits[i]) { + let m = digits[i] % 10 + var q = (digits[i] - m) / 10 + digits[i] = m + if (i < digits.size() - 1) { + digits[i + 1] += q + } else { + digits += q + break + } + } + } + var n = digits.size() - 1 + while (9 < digits[n]) { + let mo = digits[n] % 10 + let qu = (digits[n] - mo) / 10 + digits[n] = mo + digits += qu + n++ + } +} +// print(~digits) +digits.sum() diff --git a/src/test/resources/ai/code/project_euler_61.ls b/src/test/resources/ai/code/project_euler_61.ls new file mode 100644 index 00000000..b50f5106 --- /dev/null +++ b/src/test/resources/ai/code/project_euler_61.ls @@ -0,0 +1,110 @@ +var tri = [] +for (var t = 0; t < 142; ++t) { + print(t * (t + 1) / 2) + //Array.insert(tri, true, t * (t + 1) / 2) +} + +print(tri) + +/* +var squ = [] +for (var s = 0; s < 102; ++s) { Array.insert(squ, true, s * s) } +var pen = [] +for (var p = 0; p < 83; ++p) { Array.insert(pen, true, p * (3 * p - 1) / 2) } +var hex = [] +for (var h = 0; h < 72; ++h) { Array.insert(hex, true, h * (2 * h - 1)) } +var hep = [] +for (var g = 0; g < 65; ++g) { Array.insert(hep, true, g * (5 * g - 3) / 2) } +var oct = [] +for (var o = 0; o < 61; ++o) { Array.insert(oct, true, o * (3 * o - 2)) } + +var P = [tri, squ, pen, hex, hep, oct] +var poly = [0, 0, 0, 0, 0, 0] + +print(P) + +/* + +var NUL = [] +for (var nul = 1000; nul <= 9999; ++nul) { + if (tri[nul] == null && squ[nul] == null && pen[nul] == null && + hex[nul] == null && hep[nul] == null && oct[nul] == null) { + Array.insert(NUL, true, nul) + } +} +var min = 1000 +var max = 9999 + +for (var a = min; a <= max; ++a) { + if NUL[a] continue + + for (var pa = 0; pa < 6; ++pa) { + + if (P[pa][a] == null) continue + poly[pa] = 1 + var al = a % 100 + var af = (a - al) / 100 + + for (var b = Number.max(min, al * 100); b < Number.min(max, (al + 1) * 100); ++b) { + if NUL[b] continue + + for (var pb = 0; pb < 6; ++pb) { + + if (poly[pb] or P[pb][b] == null) continue + poly[pb] = 1 + var bl = b % 100 + + for (var c = Number.max(min, bl * 100); c < Number.min(max, (bl + 1) * 100); ++c) { + if NUL[c] continue + + for (var pc = 0; pc < 6; ++pc) { + + if (poly[pc] or P[pc][c] == null) continue + poly[pc] = 1 + var cl = c % 100 + + for (var d = Number.max(min, cl * 100); d < Number.min(max, (cl + 1) * 100); ++d) { + if NUL[d] continue + + for (var pd = 0; pd < 6; ++pd) { + + if (poly[pd] or P[pd][d] == null) continue + poly[pd] = 1 + var dl = d % 100 + + for (var e = Number.max(min, dl * 100); e < Number.min(max, (dl + 1) * 100); ++e) { + if NUL[e] continue + + for (var pe = 0; pe < 6; ++pe) { + + if (poly[pe] or P[pe][e] == null) continue + poly[pe] = 1 + var el = e % 100 + + for (var f = Number.max(min, el * 100); f < Number.min(max, (el + 1) * 100); ++f) { + if NUL[f] continue + + if (f % 100 == af) { + for (var pf = 0; pf < 6; ++pf) { + if (!poly[pf] and P[pf][f]) { + print(a + " " + b + " " + c + " " + d + " " + e + " " + f) + return "sum : " + (a + b + c + d + e + f) + } + } + } + } + poly[pe] = 0 + } + } + poly[pd] = 0 + } + } + poly[pc] = 0 + } + } + poly[pb] = 0 + } + } + poly[pa] = 0 + } +} \ No newline at end of file diff --git a/src/test/resources/ai/code/quine.leek b/src/test/resources/ai/code/quine.leek new file mode 100644 index 00000000..af6745c8 --- /dev/null +++ b/src/test/resources/ai/code/quine.leek @@ -0,0 +1 @@ +var q=Json.encode('')[0]var a="var q=Json.encode('')[0]var a="+q var b="System.print(a+a+'+q var b='+q+b+q+b)"System.print(a+a+'+q var b='+q+b+q+b) diff --git a/src/test/resources/ai/code/quine_zwik.leek b/src/test/resources/ai/code/quine_zwik.leek new file mode 100644 index 00000000..ce5f3ed9 --- /dev/null +++ b/src/test/resources/ai/code/quine_zwik.leek @@ -0,0 +1,16 @@ +var s=charAt('\"'0); +var q=charAt('\"'1); +var l=[]; +pushAll(l,[ +"var s=charAt('\"'0);", +"var q=charAt('\"'1);", +"var l=[];", +"pushAll(l,[", +"]);", +"for(var i=0;i<4;i++)debug(replace(l[i],q,s+s+q));", +"for(var i=0;i 10 ? fun_real(x - 0.5) : x } + +return fun_int(20); diff --git a/src/test/resources/ai/code/recursive_2_vars.leek b/src/test/resources/ai/code/recursive_2_vars.leek new file mode 100644 index 00000000..d4590eb1 --- /dev/null +++ b/src/test/resources/ai/code/recursive_2_vars.leek @@ -0,0 +1,12 @@ +var ack = function(m, n) { + if (m == 0) { + return n + 1 + } else { + if (n == 0) { + return ack(m - 1, 1) + } else { + return ack(m - 1, ack(m, n - 1)) + } + } +} +return ack(3, 7); diff --git a/src/test/resources/ai/code/recursive_2_versions.leek b/src/test/resources/ai/code/recursive_2_versions.leek new file mode 100644 index 00000000..953bb145 --- /dev/null +++ b/src/test/resources/ai/code/recursive_2_versions.leek @@ -0,0 +1,12 @@ +let fun = n -> { + if n < 10 { + n + } else { + if (n.isInteger()) { + fun(n - 0.5) + } else { + fun((n - 0.5).floor()) + } + } +} +fun(20) diff --git a/src/test/resources/ai/code/recursive_conditions.leek b/src/test/resources/ai/code/recursive_conditions.leek new file mode 100644 index 00000000..6f70b603 --- /dev/null +++ b/src/test/resources/ai/code/recursive_conditions.leek @@ -0,0 +1,22 @@ +function fact(x) { + let a = if x < 5 { + if x == 1 { + 1 + } else { + fact(x + 1) * x + } + } else { + if x > 10 { + fact(x - 1) * x + } else { + 1 + } + } + if a % 2 { + a + } else { + fact(4) + a + } +} + +fact(12) diff --git a/src/test/resources/ai/code/recursive_conditions_2.leek b/src/test/resources/ai/code/recursive_conditions_2.leek new file mode 100644 index 00000000..1797de30 --- /dev/null +++ b/src/test/resources/ai/code/recursive_conditions_2.leek @@ -0,0 +1,22 @@ +function hello(x) { + let a = if x < 5 { + if x == 1 { + '_' + } else { + hello(x + 1) + x + } + } else { + if x > 10 { + hello(x - 1) + x + } else { + '-' + } + } + if x % 2 { + a + } else { + hello(4) + a + } +} + +hello(12) diff --git a/src/test/resources/ai/code/return_in_function.leek b/src/test/resources/ai/code/return_in_function.leek new file mode 100644 index 00000000..c26f5147 --- /dev/null +++ b/src/test/resources/ai/code/return_in_function.leek @@ -0,0 +1,6 @@ +function f() { + var cells = [12] + push(cells, 1) + return cells +} +return count(f()); \ No newline at end of file diff --git a/src/test/resources/ai/code/strings.leek b/src/test/resources/ai/code/strings.leek new file mode 100644 index 00000000..133667a6 --- /dev/null +++ b/src/test/resources/ai/code/strings.leek @@ -0,0 +1,15 @@ +var m = ['A', 'T', 'C', 'G'] +var count = 0 +var tests = 500 + +for (var k = 0; k < tests; k++) { + + var adn = '' + for (var j = 0; j < 200; j++) { + adn += m[randInt(0, 4)] + } + var c = contains(adn, 'GAGA'); + if (c) count++ +} + +return abs(100 * (count / tests) - 52) < 12; // ~ 52% diff --git a/src/test/resources/ai/code/swap.leek b/src/test/resources/ai/code/swap.leek new file mode 100644 index 00000000..f13bad0e --- /dev/null +++ b/src/test/resources/ai/code/swap.leek @@ -0,0 +1,23 @@ +let siftUp = (c, pq) -> { + if (c > 0) { + let p = (c - 1) >> 1 + if (pq[c].p < pq[p].p) { + pq[p] <=> pq[c] + return siftUp(p, pq) + } else { + return pq + } + } else { + return pq + } +} + +let pqInsert = (p, pq) -> { + siftUp(pq.size(), pq.push({p: p})) +} + +var pq = [{p: 4}] +pqInsert(5, pq) +pqInsert(3, pq) +pqInsert(12, pq) +pqInsert(1, pq) diff --git a/src/test/resources/ai/code/tarai.leek b/src/test/resources/ai/code/tarai.leek new file mode 100644 index 00000000..b3408230 --- /dev/null +++ b/src/test/resources/ai/code/tarai.leek @@ -0,0 +1,9 @@ +function tarai(x, y, z) { + if (x <= y) { + return y + } else { + return tarai(tarai(x - 1, y, z), tarai(y - 1, z, x), tarai(z - 1, x, y)) + } +} + +return tarai(16, 13, 5); \ No newline at end of file diff --git a/src/test/resources/ai/code/text_analysis.leek b/src/test/resources/ai/code/text_analysis.leek new file mode 100644 index 00000000..17c577dc --- /dev/null +++ b/src/test/resources/ai/code/text_analysis.leek @@ -0,0 +1,9 @@ +var text = "Le Poireau (Allium porrum) est une espèce de plante herbacée vivace largement cultivée comme plante potagère pour ses feuilles (pseudo-tiges) consommées comme légumes. +Il appartient à la famille des Amaryllidacées (précédemment famille des Liliacées puis des Alliacées). +Noms communs : poireau, porreau, poirée, poirette, asperge du pauvre." + +let lines = text.lines().size() +let words = text.wordCount() +let chars = text.lines().map(x -> x.size()).foldLeft((x, y -> x + y), 0) + +return [lines, words, chars]; diff --git a/src/test/resources/ai/code/trivial.leek b/src/test/resources/ai/code/trivial.leek new file mode 100644 index 00000000..d8263ee9 --- /dev/null +++ b/src/test/resources/ai/code/trivial.leek @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/src/test/resources/ai/code/two_functions.leek b/src/test/resources/ai/code/two_functions.leek new file mode 100644 index 00000000..1d4d2de0 --- /dev/null +++ b/src/test/resources/ai/code/two_functions.leek @@ -0,0 +1,3 @@ +let ppair = (p, v) -> {p: p, v: v} +let pqSingleton = (p, v) -> [{p: p, v: v}] +[ppair(2, 5), pqSingleton(3, 6)] diff --git a/src/test/resources/ai/euler/pe001.leek b/src/test/resources/ai/euler/pe001.leek new file mode 100644 index 00000000..06697166 --- /dev/null +++ b/src/test/resources/ai/euler/pe001.leek @@ -0,0 +1,7 @@ +var sum = 0 +for (var n = 0; n < 1000; ++n) { + if (n % 3 == 0 or n % 5 == 0) { + sum += n + } +} +return sum; diff --git a/src/test/resources/ai/euler/pe002.leek b/src/test/resources/ai/euler/pe002.leek new file mode 100644 index 00000000..c6496c1b --- /dev/null +++ b/src/test/resources/ai/euler/pe002.leek @@ -0,0 +1,12 @@ +var f1 = 1 +var f2 = 1 +var sum = 0 +while (f2 < 4000000) { + var n = f1 + f2 + f1 = f2 + f2 = n + if (n % 2 == 0) { + sum += n + } +} +return sum; diff --git a/src/test/resources/ai/euler/pe003.leek b/src/test/resources/ai/euler/pe003.leek new file mode 100644 index 00000000..d87ac224 --- /dev/null +++ b/src/test/resources/ai/euler/pe003.leek @@ -0,0 +1,7 @@ +var p = 600851475143 +for (var i = 2; i * i <= p; i++) { + if (p % i == 0) { + p /= i + } +} +return p | 0; diff --git a/src/test/resources/ai/euler/pe004.leek b/src/test/resources/ai/euler/pe004.leek new file mode 100644 index 00000000..2d43197f --- /dev/null +++ b/src/test/resources/ai/euler/pe004.leek @@ -0,0 +1,10 @@ +var max = 0 +for (var a = 999; a >= 100; --a) { + for (var b = a; b >= 100; --b) { + let p = a × b + if (p > max and p.isPalindrome()) { + max = p + } + } +} +return max diff --git a/src/test/resources/ai/euler/pe005.leek b/src/test/resources/ai/euler/pe005.leek new file mode 100644 index 00000000..db4fafd6 --- /dev/null +++ b/src/test/resources/ai/euler/pe005.leek @@ -0,0 +1,15 @@ +/* +1 (2) (3) 4 (5) 6 (7) 8 9 10 (11) 12 (13) 14 15 16 (17) 18 (19) 20 + 4 = 2 ^ 2 : two 2 needed +(6 = 2 * 3) + 8 = 2 ^ 3 : three 2 needed + 9 = 3 ^ 2 : two 3 needed +(10 = 5 * 2) +(12 = 3 * 2 ^ 2) +(14 = 2 * 7) + 16 = 2 ^ 4 : four 2 needed +(18 = 2 * 3 ^ 2) +(20 = 2 ^ 2 * 5) +*/ + +return (2 ** 4) * (3 ** 2) * 5 * 7 * 11 * 13 * 17 * 19; diff --git a/src/test/resources/ai/euler/pe006.leek b/src/test/resources/ai/euler/pe006.leek new file mode 100644 index 00000000..dd7b7431 --- /dev/null +++ b/src/test/resources/ai/euler/pe006.leek @@ -0,0 +1,9 @@ +var sum = 0 +var squares_sum = 0 + +for (var n = 1; n <= 100; ++n) { + sum += n + squares_sum += n * n +} + +return sum * sum - squares_sum; diff --git a/src/test/resources/ai/euler/pe007.leek b/src/test/resources/ai/euler/pe007.leek new file mode 100644 index 00000000..46fc465d --- /dev/null +++ b/src/test/resources/ai/euler/pe007.leek @@ -0,0 +1,19 @@ +function is_prime(n) { + var s = sqrt(n) + for (var d = 3; d <= s; d += 2) { + if (n % d == 0) { + return false + } + } + return true +} + +var count = 2 +var i = 3 +while (i) { + if (is_prime(i += 2)) { + if (++count == 10001) { + if (true) return i + } + } +} diff --git a/src/test/resources/ai/euler/pe008.leek b/src/test/resources/ai/euler/pe008.leek new file mode 100644 index 00000000..b31b641f --- /dev/null +++ b/src/test/resources/ai/euler/pe008.leek @@ -0,0 +1,36 @@ +let S = +"73167176531330624919225119674426574742355349194934" + +"96983520312774506326239578318016984801869478851843" + +"85861560789112949495459501737958331952853208805511" + +"12540698747158523863050715693290963295227443043557" + +"66896648950445244523161731856403098711121722383113" + +"62229893423380308135336276614282806444486645238749" + +"30358907296290491560440772390713810515859307960866" + +"70172427121883998797908792274921901699720888093776" + +"65727333001053367881220235421809751254540594752243" + +"52584907711670556013604839586446706324415722155397" + +"53697817977846174064955149290862569321978468622482" + +"83972241375657056057490261407972968652414535100474" + +"82166370484403199890008895243450658541227588666881" + +"16427171479924442928230863465674813919123162824586" + +"17866458359124566529476545682848912883142607690042" + +"24219022671055626321111109370544217506941658960408" + +"07198403850962455444362981230987879927244284909188" + +"84580156166097919133875499200524063689912560717606" + +"05886116467109405077541002256983155200055935729725" + +"71636269561882670428252483600823257530420752963450" + +var N = [] +for var s in S.split('') { + N += String.code(s) - String.code('0') +} + +var max = 1l +for var i = 0; i < N.size() - 12; ++i { + var prod = N[i : i + 12].foldLeft((x, y -> x × y), 1.0) + var prod_int = String.number('' + prod) + if max < prod_int { + max = prod_int + } +} +return max diff --git a/src/test/resources/ai/euler/pe009.leek b/src/test/resources/ai/euler/pe009.leek new file mode 100644 index 00000000..82c1bb68 --- /dev/null +++ b/src/test/resources/ai/euler/pe009.leek @@ -0,0 +1,8 @@ +for (var a = 1; a < 1000; a++) { + for (var b = a + 1; b < 1000 - a; b++) { + var c = 1000 - a - b + if (a * a + b * b == c * c) { + return a * b * c + } + } +} diff --git a/src/test/resources/ai/euler/pe010.leek b/src/test/resources/ai/euler/pe010.leek new file mode 100644 index 00000000..c37010d9 --- /dev/null +++ b/src/test/resources/ai/euler/pe010.leek @@ -0,0 +1,20 @@ +var N = 2000000 +var numbers = [] +numbers.fill(1, N + 1) +numbers[1] = 0 + +var S = N.sqrt().floor() +for var i = 2; i < S; ++i { + if numbers[i] { + for (var j = i * i; j <= N; j += i) { + numbers[j] = 0 + } + } +} +numbers.size() + +var sum = 0l +for i, p in numbers { + if p sum += i +} +sum diff --git a/src/test/resources/ai/euler/pe011.leek b/src/test/resources/ai/euler/pe011.leek new file mode 100644 index 00000000..db4c173b --- /dev/null +++ b/src/test/resources/ai/euler/pe011.leek @@ -0,0 +1,60 @@ +let grid = [08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 +49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 +81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 +52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 +22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 +24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 +32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70 +67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 +24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 +21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 +78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 +16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 +86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 +19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 +04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66 +88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 +04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 +20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 +20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54 +01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48].chunk(20) + +var max = 0 + +// TODO in future use advanced array range operators to select +// diagonally or backwards + +for var j = 0; j < grid.size(); ++j { // TODO use |grid| instead of grid.size() + for var i = 0; i < grid.size() - 3; ++i { + + // horizontal + max = max.max(grid[j][i:i + 3].product()) + + // vertical + var hprod = 1 + for (var k = 0; k < 4; ++k) { + hprod *= grid[i + k][j] + } + max = max.max(hprod) + + if (j < grid.size() - 3) { + // diagonal 1 + var dprod1 = 1 + for (var k = 0; k < 4; ++k) { + dprod1 *= grid[i + k][j + k] + } + max = max.max(dprod1) + + if (i > 3) { + // diagonal 2 + var dprod2 = 1 + for (var k = 0; k < 4; ++k) { + dprod2 *= grid[i - k][j + k] + } + max = max.max(dprod2) + } + } + } +} + +max diff --git a/src/test/resources/ai/euler/pe012.leek b/src/test/resources/ai/euler/pe012.leek new file mode 100644 index 00000000..88bac4cb --- /dev/null +++ b/src/test/resources/ai/euler/pe012.leek @@ -0,0 +1,29 @@ +var n = 50000 +var N = 500 +var d = [] +fill(d, 0, n + 2) + +for (var i = 1; i <= n + 1; i++) { + for (var j = i; j <= n + 1; j += i) { + d[j]++ + } +} + +var r = 0 +var t = 0 +for (var i = 1; i <= n; i++) { + var res = 0 + if (i & 1) { + res = d[i] * d[(i + 1) / 2] + } else { + res = d[i / 2] * d[i + 1] + } + if (res > t) { + t = res + } + if (res > N) { + r = i * (i + 1) / 2 | 0 + break + } +} +return r; diff --git a/src/test/resources/ai/euler/pe013.leek b/src/test/resources/ai/euler/pe013.leek new file mode 100644 index 00000000..5e87a457 --- /dev/null +++ b/src/test/resources/ai/euler/pe013.leek @@ -0,0 +1,102 @@ +var sum = 37107287533902102798797998220837590246510135740250 + +46376937677490009712648124896970078050417018260538 + +74324986199524741059474233309513058123726617309629 + +91942213363574161572522430563301811072406154908250 + +23067588207539346171171980310421047513778063246676 + +89261670696623633820136378418383684178734361726757 + +28112879812849979408065481931592621691275889832738 + +44274228917432520321923589422876796487670272189318 + +47451445736001306439091167216856844588711603153276 + +70386486105843025439939619828917593665686757934951 + +62176457141856560629502157223196586755079324193331 + +64906352462741904929101432445813822663347944758178 + +92575867718337217661963751590579239728245598838407 + +58203565325359399008402633568948830189458628227828 + +80181199384826282014278194139940567587151170094390 + +35398664372827112653829987240784473053190104293586 + +86515506006295864861532075273371959191420517255829 + +71693888707715466499115593487603532921714970056938 + +54370070576826684624621495650076471787294438377604 + +53282654108756828443191190634694037855217779295145 + +36123272525000296071075082563815656710885258350721 + +45876576172410976447339110607218265236877223636045 + +17423706905851860660448207621209813287860733969412 + +81142660418086830619328460811191061556940512689692 + +51934325451728388641918047049293215058642563049483 + +62467221648435076201727918039944693004732956340691 + +15732444386908125794514089057706229429197107928209 + +55037687525678773091862540744969844508330393682126 + +18336384825330154686196124348767681297534375946515 + +80386287592878490201521685554828717201219257766954 + +78182833757993103614740356856449095527097864797581 + +16726320100436897842553539920931837441497806860984 + +48403098129077791799088218795327364475675590848030 + +87086987551392711854517078544161852424320693150332 + +59959406895756536782107074926966537676326235447210 + +69793950679652694742597709739166693763042633987085 + +41052684708299085211399427365734116182760315001271 + +65378607361501080857009149939512557028198746004375 + +35829035317434717326932123578154982629742552737307 + +94953759765105305946966067683156574377167401875275 + +88902802571733229619176668713819931811048770190271 + +25267680276078003013678680992525463401061632866526 + +36270218540497705585629946580636237993140746255962 + +24074486908231174977792365466257246923322810917141 + +91430288197103288597806669760892938638285025333403 + +34413065578016127815921815005561868836468420090470 + +23053081172816430487623791969842487255036638784583 + +11487696932154902810424020138335124462181441773470 + +63783299490636259666498587618221225225512486764533 + +67720186971698544312419572409913959008952310058822 + +95548255300263520781532296796249481641953868218774 + +76085327132285723110424803456124867697064507995236 + +37774242535411291684276865538926205024910326572967 + +23701913275725675285653248258265463092207058596522 + +29798860272258331913126375147341994889534765745501 + +18495701454879288984856827726077713721403798879715 + +38298203783031473527721580348144513491373226651381 + +34829543829199918180278916522431027392251122869539 + +40957953066405232632538044100059654939159879593635 + +29746152185502371307642255121183693803580388584903 + +41698116222072977186158236678424689157993532961922 + +62467957194401269043877107275048102390895523597457 + +23189706772547915061505504953922979530901129967519 + +86188088225875314529584099251203829009407770775672 + +11306739708304724483816533873502340845647058077308 + +82959174767140363198008187129011875491310547126581 + +97623331044818386269515456334926366572897563400500 + +42846280183517070527831839425882145521227251250327 + +55121603546981200581762165212827652751691296897789 + +32238195734329339946437501907836945765883352399886 + +75506164965184775180738168837861091527357929701337 + +62177842752192623401942399639168044983993173312731 + +32924185707147349566916674687634660915035914677504 + +99518671430235219628894890102423325116913619626622 + +73267460800591547471830798392868535206946944540724 + +76841822524674417161514036427982273348055556214818 + +97142617910342598647204516893989422179826088076852 + +87783646182799346313767754307809363333018982642090 + +10848802521674670883215120185883543223812876952786 + +71329612474782464538636993009049310363619763878039 + +62184073572399794223406235393808339651327408011116 + +66627891981488087797941876876144230030984490851411 + +60661826293682836764744779239180335110989069790714 + +85786944089552990653640447425576083659976645795096 + +66024396409905389607120198219976047599490197230297 + +64913982680032973156037120041377903785566085089252 + +16730939319872750275468906903707539413042652315011 + +94809377245048795150954100921645863754710598436791 + +78639167021187492431995700641917969777599028300699 + +15368713711936614952811305876380278410754449733078 + +40789923115535562561142322423255033685442488917353 + +44889911501440648020369068063960672322193204149535 + +41503128880339536053299340368006977710650566631954 + +81234880673210146739058568557934581403627822703280 + +82616570773948327592232845941706525094512325230608 + +22918802058777319719839450180888072429661980811197 + +77158542502016545090413245809786882778948721859617 + +72107838435069186155435662884062257473692284509516 + +20849603980134001723930671666823555245252804609722 + +53503534226472524250874054075591789781264330331690 + +sum.string().substring(0, 10).number() diff --git a/src/test/resources/ai/euler/pe014.leek b/src/test/resources/ai/euler/pe014.leek new file mode 100644 index 00000000..5a7fa604 --- /dev/null +++ b/src/test/resources/ai/euler/pe014.leek @@ -0,0 +1,33 @@ +var N = 1000000 +var cache = [] +fill(cache, 0, N) +cache[1] = 1 + +var sequence_length = function(n) { + if (n >= N) { + return n % 2 ? + 1 + sequence_length(n * 3 + 1) + : + 1 + sequence_length(n / 2) + } + var c = cache[n] + if (c) return c + + return cache[n] = n % 2 ? + 1 + sequence_length(n * 3 + 1) + : + 1 + sequence_length(n / 2) +} + +var max = 0 +var n = 0 + +for (var i = 1; i < 1000000; i++) { + var l = sequence_length(i) + if (l > max) { + max = l + n = i + } +} + +return n; diff --git a/src/test/resources/ai/euler/pe015.leek b/src/test/resources/ai/euler/pe015.leek new file mode 100644 index 00000000..65145c4a --- /dev/null +++ b/src/test/resources/ai/euler/pe015.leek @@ -0,0 +1,22 @@ +var S = 20 + +var paths = [] +fill(paths, 0, 21) + +var walk = function(x, y) { + if (x + y == S) { + paths[y]++ + return; + } + if (x > 0) walk(x - 1, y) + if (y > 0) walk(x, y - 1) +} + +walk(S, S) + +var sum = 1 +for (var i = 0; i < S; ++i) { + var long = paths[i] * paths[i] + sum += long +} +return sum; diff --git a/src/test/resources/ai/euler/pe016.leek b/src/test/resources/ai/euler/pe016.leek new file mode 100644 index 00000000..d8af28ad --- /dev/null +++ b/src/test/resources/ai/euler/pe016.leek @@ -0,0 +1,4 @@ + (2m ** 1000).string().fold((x, y) -> x + y.number(), 0) + +// TODO : only 2 ** 1000 without the m -> detect that it's a large number constant +// TODO : fold the number itself (base 10 by default), iterate over digits as integers diff --git a/src/test/resources/ai/euler/pe017.leek b/src/test/resources/ai/euler/pe017.leek new file mode 100644 index 00000000..459261a1 --- /dev/null +++ b/src/test/resources/ai/euler/pe017.leek @@ -0,0 +1,54 @@ +function get(n) { + if (n == 1) return "one" + if (n == 2) return "two" + if (n == 3) return "three" + if (n == 4) return "four" + if (n == 5) return "five" + if (n == 6) return "six" + if (n == 7) return "seven" + if (n == 8) return "eight" + if (n == 9) return "nine" + if (n == 10) return "ten" + if (n == 11) return "eleven" + if (n == 12) return "twelve" + if (n == 13) return "thirteen" + if (n == 14) return "fourteen" + if (n == 15) return "fifteen" + if (n == 16) return "sixteen" + if (n == 17) return "seventeen" + if (n == 18) return "eighteen" + if (n == 19) return "nineteen" + + if (n == 20) return "twenty" + if (n == 30) return "thirty" + if (n == 40) return "forty" + if (n == 50) return "fifty" + if (n == 60) return "sixty" + if (n == 70) return "seventy" + if (n == 80) return "eighty" + if (n == 90) return "ninety" + + if (n < 100) { + var diz = (n / 10 | 0) * 10 + return get(diz) + get(n - diz) + } + + if (n < 1000) { + var cent = n / 100 | 0 + var reste = n % 100 + var res = get(cent) + "hundred" + if (reste > 0) { + // TODO res += + res = res + "and" + get(reste) + } + return res + } + return "onethousand" +} + +var sum = 0 +for (var i = 1; i <= 1000; ++i) { + sum += length(get(i)) +} + +return sum; \ No newline at end of file diff --git a/src/test/resources/ai/euler/pe018.leek b/src/test/resources/ai/euler/pe018.leek new file mode 100644 index 00000000..699f4e0a --- /dev/null +++ b/src/test/resources/ai/euler/pe018.leek @@ -0,0 +1,34 @@ + + +var tryRoute = function (level, x, sum, maxi) { + + var tri = [ + [75], + [95, 64], + [17, 47, 82], + [18, 35, 87, 10], + [20, 4, 82, 47, 65], + [19, 1, 23, 75, 3, 34], + [88, 2, 77, 73, 7, 63, 67], + [99, 65, 4, 28, 6, 16, 70, 92], + [41, 41, 26, 56, 83, 40, 80, 70, 33], + [41, 48, 72, 33, 47, 32, 37, 16, 94, 29], + [53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14], + [70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57], + [91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48], + [63, 66, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31], + [ 4, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23] + ] + sum += tri[level][x] + + if (level == 14) { + if (sum > maxi) maxi = sum + return maxi + } else { + maxi = tryRoute(level + 1, x, sum, maxi) + return tryRoute(level + 1, x + 1, sum, maxi) + } +} + +return tryRoute(0, 0, 0, 0); + diff --git a/src/test/resources/ai/euler/pe019.leek b/src/test/resources/ai/euler/pe019.leek new file mode 100644 index 00000000..e9ddfd4b --- /dev/null +++ b/src/test/resources/ai/euler/pe019.leek @@ -0,0 +1,22 @@ +var day = 1 // 1 janvier 1901 => mardi +var sundays = 0 + +for (var i = 1901; i <= 2000; ++i) { + + var leap = (i % 100 != 0 && i % 4 == 0) || (i % 400 == 0) + + for (var m = 0; m < 12; ++m) { + + if (day % 7 == 6) sundays++ + + if (m == 3 || m == 5 || m == 8 || m == 10) { + day += 30 + } else if (m == 1) { + day += leap ? 29 : 28 + } else { + day += 31 + } + } +} + +return sundays; \ No newline at end of file diff --git a/src/test/resources/ai/euler/pe020.leek b/src/test/resources/ai/euler/pe020.leek new file mode 100644 index 00000000..bece303a --- /dev/null +++ b/src/test/resources/ai/euler/pe020.leek @@ -0,0 +1,12 @@ +// TODO create a builtin fact function +var fact = function(x) { x == 1 ? 1 : fact(x - 1) * x } + +var f = fact(100) +var s = f.string() // TODO mpz.string() directly + +var sum = 0 +for (var c in s) { + sum += c.code() - '0'.code() +} + +sum \ No newline at end of file diff --git a/src/test/resources/ai/euler/pe021.leek b/src/test/resources/ai/euler/pe021.leek new file mode 100644 index 00000000..f640f76e --- /dev/null +++ b/src/test/resources/ai/euler/pe021.leek @@ -0,0 +1,15 @@ +function sumDiv(n) { + var num = 0 + for (var i = 1; i < n; ++i) + if (n % i == 0) { + num += i + } + num +} + +function isAmicable(i) { + var sum = sumDiv(i) + sum != i && sumDiv(sum) == i +} + +[1..10000].filter(isAmicable).sum() \ No newline at end of file diff --git a/src/test/resources/ai/euler/pe022.leek b/src/test/resources/ai/euler/pe022.leek new file mode 100644 index 00000000..6a6f78d7 --- /dev/null +++ b/src/test/resources/ai/euler/pe022.leek @@ -0,0 +1,15 @@ +var names = "MARY PATRICIA LINDA BARBARA ELIZABETH JENNIFER MARIA SUSAN MARGARET DOROTHY LISA NANCY KAREN BETTY HELEN SANDRA DONNA CAROL RUTH SHARON MICHELLE LAURA SARAH KIMBERLY DEBORAH JESSICA SHIRLEY CYNTHIA ANGELA MELISSA BRENDA AMY ANNA REBECCA VIRGINIA KATHLEEN PAMELA MARTHA DEBRA AMANDA STEPHANIE CAROLYN CHRISTINE MARIE JANET CATHERINE FRANCES ANN JOYCE DIANE ALICE JULIE HEATHER TERESA DORIS GLORIA EVELYN JEAN CHERYL MILDRED KATHERINE JOAN ASHLEY JUDITH ROSE JANICE KELLY NICOLE JUDY CHRISTINA KATHY THERESA BEVERLY DENISE TAMMY IRENE JANE LORI RACHEL MARILYN ANDREA KATHRYN LOUISE SARA ANNE JACQUELINE WANDA BONNIE JULIA RUBY LOIS TINA PHYLLIS NORMA PAULA DIANA ANNIE LILLIAN EMILY ROBIN PEGGY CRYSTAL GLADYS RITA DAWN CONNIE FLORENCE TRACY EDNA TIFFANY CARMEN ROSA CINDY GRACE WENDY VICTORIA EDITH KIM SHERRY SYLVIA JOSEPHINE THELMA SHANNON SHEILA ETHEL ELLEN ELAINE MARJORIE CARRIE CHARLOTTE MONICA ESTHER PAULINE EMMA JUANITA ANITA RHONDA HAZEL AMBER EVA DEBBIE APRIL LESLIE CLARA LUCILLE JAMIE JOANNE ELEANOR VALERIE DANIELLE MEGAN ALICIA SUZANNE MICHELE GAIL BERTHA DARLENE VERONICA JILL ERIN GERALDINE LAUREN CATHY JOANN LORRAINE LYNN SALLY REGINA ERICA BEATRICE DOLORES BERNICE AUDREY YVONNE ANNETTE JUNE SAMANTHA MARION DANA STACY ANA RENEE IDA VIVIAN ROBERTA HOLLY BRITTANY MELANIE LORETTA YOLANDA JEANETTE LAURIE KATIE KRISTEN VANESSA ALMA SUE ELSIE BETH JEANNE VICKI CARLA TARA ROSEMARY EILEEN TERRI GERTRUDE LUCY TONYA ELLA STACEY WILMA GINA KRISTIN JESSIE NATALIE AGNES VERA WILLIE CHARLENE BESSIE DELORES MELINDA PEARL ARLENE MAUREEN COLLEEN ALLISON TAMARA JOY GEORGIA CONSTANCE LILLIE CLAUDIA JACKIE MARCIA TANYA NELLIE MINNIE MARLENE HEIDI GLENDA LYDIA VIOLA COURTNEY MARIAN STELLA CAROLINE DORA JO VICKIE MATTIE TERRY MAXINE IRMA MABEL MARSHA MYRTLE LENA CHRISTY DEANNA PATSY HILDA GWENDOLYN JENNIE NORA MARGIE NINA CASSANDRA LEAH PENNY KAY PRISCILLA NAOMI CAROLE BRANDY OLGA BILLIE DIANNE TRACEY LEONA JENNY FELICIA SONIA MIRIAM VELMA BECKY BOBBIE VIOLET KRISTINA TONI MISTY MAE SHELLY DAISY RAMONA SHERRI ERIKA KATRINA CLAIRE LINDSEY LINDSAY GENEVA GUADALUPE BELINDA MARGARITA SHERYL CORA FAYE ADA NATASHA SABRINA ISABEL MARGUERITE HATTIE HARRIET MOLLY CECILIA KRISTI BRANDI BLANCHE SANDY ROSIE JOANNA IRIS EUNICE ANGIE INEZ LYNDA MADELINE AMELIA ALBERTA GENEVIEVE MONIQUE JODI JANIE MAGGIE KAYLA SONYA JAN LEE KRISTINE CANDACE FANNIE MARYANN OPAL ALISON YVETTE MELODY LUZ SUSIE OLIVIA FLORA SHELLEY KRISTY MAMIE LULA LOLA VERNA BEULAH ANTOINETTE CANDICE JUANA JEANNETTE PAM KELLI HANNAH WHITNEY BRIDGET KARLA CELIA LATOYA PATTY SHELIA GAYLE DELLA VICKY LYNNE SHERI MARIANNE KARA JACQUELYN ERMA BLANCA MYRA LETICIA PAT KRISTA ROXANNE ANGELICA JOHNNIE ROBYN FRANCIS ADRIENNE ROSALIE ALEXANDRA BROOKE BETHANY SADIE BERNADETTE TRACI JODY KENDRA JASMINE NICHOLE RACHAEL CHELSEA MABLE ERNESTINE MURIEL MARCELLA ELENA KRYSTAL ANGELINA NADINE KARI ESTELLE DIANNA PAULETTE LORA MONA DOREEN ROSEMARIE ANGEL DESIREE ANTONIA HOPE GINGER JANIS BETSY CHRISTIE FREDA MERCEDES MEREDITH LYNETTE TERI CRISTINA EULA LEIGH MEGHAN SOPHIA ELOISE ROCHELLE GRETCHEN CECELIA RAQUEL HENRIETTA ALYSSA JANA KELLEY GWEN KERRY JENNA TRICIA LAVERNE OLIVE ALEXIS TASHA SILVIA ELVIRA CASEY DELIA SOPHIE KATE PATTI LORENA KELLIE SONJA LILA LANA DARLA MAY MINDY ESSIE MANDY LORENE ELSA JOSEFINA JEANNIE MIRANDA DIXIE LUCIA MARTA FAITH LELA JOHANNA SHARI CAMILLE TAMI SHAWNA ELISA EBONY MELBA ORA NETTIE TABITHA OLLIE JAIME WINIFRED KRISTIE MARINA ALISHA AIMEE RENA MYRNA MARLA TAMMIE LATASHA BONITA PATRICE RONDA SHERRIE ADDIE FRANCINE DELORIS STACIE ADRIANA CHERI SHELBY ABIGAIL CELESTE JEWEL CARA ADELE REBEKAH LUCINDA DORTHY CHRIS EFFIE TRINA REBA SHAWN SALLIE AURORA LENORA ETTA LOTTIE KERRI TRISHA NIKKI ESTELLA FRANCISCA JOSIE TRACIE MARISSA KARIN BRITTNEY JANELLE LOURDES LAUREL HELENE FERN ELVA CORINNE KELSEY INA BETTIE ELISABETH AIDA CAITLIN INGRID IVA EUGENIA CHRISTA GOLDIE CASSIE MAUDE JENIFER THERESE FRANKIE DENA LORNA JANETTE LATONYA CANDY MORGAN CONSUELO TAMIKA ROSETTA DEBORA CHERIE POLLY DINA JEWELL FAY JILLIAN DOROTHEA NELL TRUDY ESPERANZA PATRICA KIMBERLEY SHANNA HELENA CAROLINA CLEO STEFANIE ROSARIO OLA JANINE MOLLIE LUPE ALISA LOU MARIBEL SUSANNE BETTE SUSANA ELISE CECILE ISABELLE LESLEY JOCELYN PAIGE JONI RACHELLE LEOLA DAPHNE ALTA ESTER PETRA GRACIELA IMOGENE JOLENE KEISHA LACEY GLENNA GABRIELA KERI URSULA LIZZIE KIRSTEN SHANA ADELINE MAYRA JAYNE JACLYN GRACIE SONDRA CARMELA MARISA ROSALIND CHARITY TONIA BEATRIZ MARISOL CLARICE JEANINE SHEENA ANGELINE FRIEDA LILY ROBBIE SHAUNA MILLIE CLAUDETTE CATHLEEN ANGELIA GABRIELLE AUTUMN KATHARINE SUMMER JODIE STACI LEA CHRISTI JIMMIE JUSTINE ELMA LUELLA MARGRET DOMINIQUE SOCORRO RENE MARTINA MARGO MAVIS CALLIE BOBBI MARITZA LUCILE LEANNE JEANNINE DEANA AILEEN LORIE LADONNA WILLA MANUELA GALE SELMA DOLLY SYBIL ABBY LARA DALE IVY DEE WINNIE MARCY LUISA JERI MAGDALENA OFELIA MEAGAN AUDRA MATILDA LEILA CORNELIA BIANCA SIMONE BETTYE RANDI VIRGIE LATISHA BARBRA GEORGINA ELIZA LEANN BRIDGETTE RHODA HALEY ADELA NOLA BERNADINE FLOSSIE ILA GRETA RUTHIE NELDA MINERVA LILLY TERRIE LETHA HILARY ESTELA VALARIE BRIANNA ROSALYN EARLINE CATALINA AVA MIA CLARISSA LIDIA CORRINE ALEXANDRIA CONCEPCION TIA SHARRON RAE DONA ERICKA JAMI ELNORA CHANDRA LENORE NEVA MARYLOU MELISA TABATHA SERENA AVIS ALLIE SOFIA JEANIE ODESSA NANNIE HARRIETT LORAINE PENELOPE MILAGROS EMILIA BENITA ALLYSON ASHLEE TANIA TOMMIE ESMERALDA KARINA EVE PEARLIE ZELMA MALINDA NOREEN TAMEKA SAUNDRA HILLARY AMIE ALTHEA ROSALINDA JORDAN LILIA ALANA GAY CLARE ALEJANDRA ELINOR MICHAEL LORRIE JERRI DARCY EARNESTINE CARMELLA TAYLOR NOEMI MARCIE LIZA ANNABELLE LOUISA EARLENE MALLORY CARLENE NITA SELENA TANISHA KATY JULIANNE JOHN LAKISHA EDWINA MARICELA MARGERY KENYA DOLLIE ROXIE ROSLYN KATHRINE NANETTE CHARMAINE LAVONNE ILENE KRIS TAMMI SUZETTE CORINE KAYE JERRY MERLE CHRYSTAL LINA DEANNE LILIAN JULIANA ALINE LUANN KASEY MARYANNE EVANGELINE COLETTE MELVA LAWANDA YESENIA NADIA MADGE KATHIE EDDIE OPHELIA VALERIA NONA MITZI MARI GEORGETTE CLAUDINE FRAN ALISSA ROSEANN LAKEISHA SUSANNA REVA DEIDRE CHASITY SHEREE CARLY JAMES ELVIA ALYCE DEIRDRE GENA BRIANA ARACELI KATELYN ROSANNE WENDI TESSA BERTA MARVA IMELDA MARIETTA MARCI LEONOR ARLINE SASHA MADELYN JANNA JULIETTE DEENA AURELIA JOSEFA AUGUSTA LILIANA YOUNG CHRISTIAN LESSIE AMALIA SAVANNAH ANASTASIA VILMA NATALIA ROSELLA LYNNETTE CORINA ALFREDA LEANNA CAREY AMPARO COLEEN TAMRA AISHA WILDA KARYN CHERRY QUEEN MAURA MAI EVANGELINA ROSANNA HALLIE ERNA ENID MARIANA LACY JULIET JACKLYN FREIDA MADELEINE MARA HESTER CATHRYN LELIA CASANDRA BRIDGETT ANGELITA JANNIE DIONNE ANNMARIE KATINA BERYL PHOEBE MILLICENT KATHERYN DIANN CARISSA MARYELLEN LIZ LAURI HELGA GILDA ADRIAN RHEA MARQUITA HOLLIE TISHA TAMERA ANGELIQUE FRANCESCA BRITNEY KAITLIN LOLITA FLORINE ROWENA REYNA TWILA FANNY JANELL INES CONCETTA BERTIE ALBA BRIGITTE ALYSON VONDA PANSY ELBA NOELLE LETITIA KITTY DEANN BRANDIE LOUELLA LETA FELECIA SHARLENE LESA BEVERLEY ROBERT ISABELLA HERMINIA TERRA CELINA TORI OCTAVIA JADE DENICE GERMAINE SIERRA MICHELL CORTNEY NELLY DORETHA SYDNEY DEIDRA MONIKA LASHONDA JUDI CHELSEY ANTIONETTE MARGOT BOBBY ADELAIDE NAN LEEANN ELISHA DESSIE LIBBY KATHI GAYLA LATANYA MINA MELLISA KIMBERLEE JASMIN RENAE ZELDA ELDA MA JUSTINA GUSSIE EMILIE CAMILLA ABBIE ROCIO KAITLYN JESSE EDYTHE ASHLEIGH SELINA LAKESHA GERI ALLENE PAMALA MICHAELA DAYNA CARYN ROSALIA SUN JACQULINE REBECA MARYBETH KRYSTLE IOLA DOTTIE BENNIE BELLE AUBREY GRISELDA ERNESTINA ELIDA ADRIANNE DEMETRIA DELMA CHONG JAQUELINE DESTINY ARLEEN VIRGINA RETHA FATIMA TILLIE ELEANORE CARI TREVA BIRDIE WILHELMINA ROSALEE MAURINE LATRICE YONG JENA TARYN ELIA DEBBY MAUDIE JEANNA DELILAH CATRINA SHONDA HORTENCIA THEODORA TERESITA ROBBIN DANETTE MARYJANE FREDDIE DELPHINE BRIANNE NILDA DANNA CINDI BESS IONA HANNA ARIEL WINONA VIDA ROSITA MARIANNA WILLIAM RACHEAL GUILLERMINA ELOISA CELESTINE CAREN MALISSA LONA CHANTEL SHELLIE MARISELA LEORA AGATHA SOLEDAD MIGDALIA IVETTE CHRISTEN ATHENA JANEL CHLOE VEDA PATTIE TESSIE TERA MARILYNN LUCRETIA KARRIE DINAH DANIELA ALECIA ADELINA VERNICE SHIELA PORTIA MERRY LASHAWN DEVON DARA TAWANA OMA VERDA CHRISTIN ALENE ZELLA SANDI RAFAELA MAYA KIRA CANDIDA ALVINA SUZAN SHAYLA LYN LETTIE ALVA SAMATHA ORALIA MATILDE MADONNA LARISSA VESTA RENITA INDIA DELOIS SHANDA PHILLIS LORRI ERLINDA CRUZ CATHRINE BARB ZOE ISABELL IONE GISELA CHARLIE VALENCIA ROXANNA MAYME KISHA ELLIE MELLISSA DORRIS DALIA BELLA ANNETTA ZOILA RETA REINA LAURETTA KYLIE CHRISTAL PILAR CHARLA ELISSA TIFFANI TANA PAULINA LEOTA BREANNA JAYME CARMEL VERNELL TOMASA MANDI DOMINGA SANTA MELODIE LURA ALEXA TAMELA RYAN MIRNA KERRIE VENUS NOEL FELICITA CRISTY CARMELITA BERNIECE ANNEMARIE TIARA ROSEANNE MISSY CORI ROXANA PRICILLA KRISTAL JUNG ELYSE HAYDEE ALETHA BETTINA MARGE GILLIAN FILOMENA CHARLES ZENAIDA HARRIETTE CARIDAD VADA UNA ARETHA PEARLINE MARJORY MARCELA FLOR EVETTE ELOUISE ALINA TRINIDAD DAVID DAMARIS CATHARINE CARROLL BELVA NAKIA MARLENA LUANNE LORINE KARON DORENE DANITA BRENNA TATIANA SAMMIE LOUANN LOREN JULIANNA ANDRIA PHILOMENA LUCILA LEONORA DOVIE ROMONA MIMI JACQUELIN GAYE TONJA MISTI JOE GENE CHASTITY STACIA ROXANN MICAELA NIKITA MEI VELDA MARLYS JOHNNA AURA LAVERN IVONNE HAYLEY NICKI MAJORIE HERLINDA GEORGE ALPHA YADIRA PERLA GREGORIA DANIEL ANTONETTE SHELLI MOZELLE MARIAH JOELLE CORDELIA JOSETTE CHIQUITA TRISTA LOUIS LAQUITA GEORGIANA CANDI SHANON LONNIE HILDEGARD CECIL VALENTINA STEPHANY MAGDA KAROL GERRY GABRIELLA TIANA ROMA RICHELLE RAY PRINCESS OLETA JACQUE IDELLA ALAINA SUZANNA JOVITA BLAIR TOSHA RAVEN NEREIDA MARLYN KYLA JOSEPH DELFINA TENA STEPHENIE SABINA NATHALIE MARCELLE GERTIE DARLEEN THEA SHARONDA SHANTEL BELEN VENESSA ROSALINA ONA GENOVEVA COREY CLEMENTINE ROSALBA RENATE RENATA MI IVORY GEORGIANNA FLOY DORCAS ARIANA TYRA THEDA MARIAM JULI JESICA DONNIE VIKKI VERLA ROSELYN MELVINA JANNETTE GINNY DEBRAH CORRIE ASIA VIOLETA MYRTIS LATRICIA COLLETTE CHARLEEN ANISSA VIVIANA TWYLA PRECIOUS NEDRA LATONIA LAN HELLEN FABIOLA ANNAMARIE ADELL SHARYN CHANTAL NIKI MAUD LIZETTE LINDY KIA KESHA JEANA DANELLE CHARLINE CHANEL CARROL VALORIE LIA DORTHA CRISTAL SUNNY LEONE LEILANI GERRI DEBI ANDRA KESHIA IMA EULALIA EASTER DULCE NATIVIDAD LINNIE KAMI GEORGIE CATINA BROOK ALDA WINNIFRED SHARLA RUTHANN MEAGHAN MAGDALENE LISSETTE ADELAIDA VENITA TRENA SHIRLENE SHAMEKA ELIZEBETH DIAN SHANTA MICKEY LATOSHA CARLOTTA WINDY SOON ROSINA MARIANN LEISA JONNIE DAWNA CATHIE BILLY ASTRID SIDNEY LAUREEN JANEEN HOLLI FAWN VICKEY TERESSA SHANTE RUBYE MARCELINA CHANDA CARY TERESE SCARLETT MARTY MARNIE LULU LISETTE JENIFFER ELENOR DORINDA DONITA CARMAN BERNITA ALTAGRACIA ALETA ADRIANNA ZORAIDA RONNIE NICOLA LYNDSEY KENDALL JANINA CHRISSY AMI STARLA PHYLIS PHUONG KYRA CHARISSE BLANCH SANJUANITA RONA NANCI MARILEE MARANDA CORY BRIGETTE SANJUANA MARITA KASSANDRA JOYCELYN IRA FELIPA CHELSIE BONNY MIREYA LORENZA KYONG ILEANA CANDELARIA TONY TOBY SHERIE OK MARK LUCIE LEATRICE LAKESHIA GERDA EDIE BAMBI MARYLIN LAVON HORTENSE GARNET EVIE TRESSA SHAYNA LAVINA KYUNG JEANETTA SHERRILL SHARA PHYLISS MITTIE ANABEL ALESIA THUY TAWANDA RICHARD JOANIE TIFFANIE LASHANDA KARISSA ENRIQUETA DARIA DANIELLA CORINNA ALANNA ABBEY ROXANE ROSEANNA MAGNOLIA LIDA KYLE JOELLEN ERA CORAL CARLEEN TRESA PEGGIE NOVELLA NILA MAYBELLE JENELLE CARINA NOVA MELINA MARQUERITE MARGARETTE JOSEPHINA EVONNE DEVIN CINTHIA ALBINA TOYA TAWNYA SHERITA SANTOS MYRIAM LIZABETH LISE KEELY JENNI GISELLE CHERYLE ARDITH ARDIS ALESHA ADRIANE SHAINA LINNEA KAROLYN HONG FLORIDA FELISHA DORI DARCI ARTIE ARMIDA ZOLA XIOMARA VERGIE SHAMIKA NENA NANNETTE MAXIE LOVIE JEANE JAIMIE INGE FARRAH ELAINA CAITLYN STARR FELICITAS CHERLY CARYL YOLONDA YASMIN TEENA PRUDENCE PENNIE NYDIA MACKENZIE ORPHA MARVEL LIZBETH LAURETTE JERRIE HERMELINDA CAROLEE TIERRA MIRIAN META MELONY KORI JENNETTE JAMILA ENA ANH YOSHIKO SUSANNAH SALINA RHIANNON JOLEEN CRISTINE ASHTON ARACELY TOMEKA SHALONDA MARTI LACIE KALA JADA ILSE HAILEY BRITTANI ZONA SYBLE SHERRYL RANDY NIDIA MARLO KANDICE KANDI DEB DEAN AMERICA ALYCIA TOMMY RONNA NORENE MERCY JOSE INGEBORG GIOVANNA GEMMA CHRISTEL AUDRY ZORA VITA VAN TRISH STEPHAINE SHIRLEE SHANIKA MELONIE MAZIE JAZMIN INGA HOA HETTIE GERALYN FONDA ESTRELLA ADELLA SU SARITA RINA MILISSA MARIBETH GOLDA EVON ETHELYN ENEDINA CHERISE CHANA VELVA TAWANNA SADE MIRTA LI KARIE JACINTA ELNA DAVINA CIERRA ASHLIE ALBERTHA TANESHA STEPHANI NELLE MINDI LU LORINDA LARUE FLORENE DEMETRA DEDRA CIARA CHANTELLE ASHLY SUZY ROSALVA NOELIA LYDA LEATHA KRYSTYNA KRISTAN KARRI DARLINE DARCIE CINDA CHEYENNE CHERRIE AWILDA ALMEDA ROLANDA LANETTE JERILYN GISELE EVALYN CYNDI CLETA CARIN ZINA ZENA VELIA TANIKA PAUL CHARISSA THOMAS TALIA MARGARETE LAVONDA KAYLEE KATHLENE JONNA IRENA ILONA IDALIA CANDIS CANDANCE BRANDEE ANITRA ALIDA SIGRID NICOLETTE MARYJO LINETTE HEDWIG CHRISTIANA CASSIDY ALEXIA TRESSIE MODESTA LUPITA LITA GLADIS EVELIA DAVIDA CHERRI CECILY ASHELY ANNABEL AGUSTINA WANITA SHIRLY ROSAURA HULDA EUN BAILEY YETTA VERONA THOMASINA SIBYL SHANNAN MECHELLE LUE LEANDRA LANI KYLEE KANDY JOLYNN FERNE EBONI CORENE ALYSIA ZULA NADA MOIRA LYNDSAY LORRETTA JUAN JAMMIE HORTENSIA GAYNELL CAMERON ADRIA VINA VICENTA TANGELA STEPHINE NORINE NELLA LIANA LESLEE KIMBERELY ILIANA GLORY FELICA EMOGENE ELFRIEDE EDEN EARTHA CARMA BEA OCIE MARRY LENNIE KIARA JACALYN CARLOTA ARIELLE YU STAR OTILIA KIRSTIN KACEY JOHNETTA JOEY JOETTA JERALDINE JAUNITA ELANA DORTHEA CAMI AMADA ADELIA VERNITA TAMAR SIOBHAN RENEA RASHIDA OUIDA ODELL NILSA MERYL KRISTYN JULIETA DANICA BREANNE AUREA ANGLEA SHERRON ODETTE MALIA LORELEI LIN LEESA KENNA KATHLYN FIONA CHARLETTE SUZIE SHANTELL SABRA RACQUEL MYONG MIRA MARTINE LUCIENNE LAVADA JULIANN JOHNIE ELVERA DELPHIA CLAIR CHRISTIANE CHAROLETTE CARRI AUGUSTINE ASHA ANGELLA PAOLA NINFA LEDA LAI EDA SUNSHINE STEFANI SHANELL PALMA MACHELLE LISSA KECIA KATHRYNE KARLENE JULISSA JETTIE JENNIFFER HUI CORRINA CHRISTOPHER CAROLANN ALENA TESS ROSARIA MYRTICE MARYLEE LIANE KENYATTA JUDIE JANEY IN ELMIRA ELDORA DENNA CRISTI CATHI ZAIDA VONNIE VIVA VERNIE ROSALINE MARIELA LUCIANA LESLI KARAN FELICE DENEEN ADINA WYNONA TARSHA SHERON SHASTA SHANITA SHANI SHANDRA RANDA PINKIE PARIS NELIDA MARILOU LYLA LAURENE LACI JOI JANENE DOROTHA DANIELE DANI CAROLYNN CARLYN BERENICE AYESHA ANNELIESE ALETHEA THERSA TAMIKO RUFINA OLIVA MOZELL MARYLYN MADISON KRISTIAN KATHYRN KASANDRA KANDACE JANAE GABRIEL DOMENICA DEBBRA DANNIELLE CHUN BUFFY BARBIE ARCELIA AJA ZENOBIA SHAREN SHAREE PATRICK PAGE MY LAVINIA KUM KACIE JACKELINE HUONG FELISA EMELIA ELEANORA CYTHIA CRISTIN CLYDE CLARIBEL CARON ANASTACIA ZULMA ZANDRA YOKO TENISHA SUSANN SHERILYN SHAY SHAWANDA SABINE ROMANA MATHILDA LINSEY KEIKO JOANA ISELA GRETTA GEORGETTA EUGENIE DUSTY DESIRAE DELORA CORAZON ANTONINA ANIKA WILLENE TRACEE TAMATHA REGAN NICHELLE MICKIE MAEGAN LUANA LANITA KELSIE EDELMIRA BREE AFTON TEODORA TAMIE SHENA MEG LINH KELI KACI DANYELLE BRITT ARLETTE ALBERTINE ADELLE TIFFINY STORMY SIMONA NUMBERS NICOLASA NICHOL NIA NAKISHA MEE MAIRA LOREEN KIZZY JOHNNY JAY FALLON CHRISTENE BOBBYE ANTHONY YING VINCENZA TANJA RUBIE RONI QUEENIE MARGARETT KIMBERLI IRMGARD IDELL HILMA EVELINA ESTA EMILEE DENNISE DANIA CARL CARIE ANTONIO WAI SANG RISA RIKKI PARTICIA MUI MASAKO MARIO LUVENIA LOREE LONI LIEN KEVIN GIGI FLORENCIA DORIAN DENITA DALLAS CHI BILLYE ALEXANDER TOMIKA SHARITA RANA NIKOLE NEOMA MARGARITE MADALYN LUCINA LAILA KALI JENETTE GABRIELE EVELYNE ELENORA CLEMENTINA ALEJANDRINA ZULEMA VIOLETTE VANNESSA THRESA RETTA PIA PATIENCE NOELLA NICKIE JONELL DELTA CHUNG CHAYA CAMELIA BETHEL ANYA ANDREW THANH SUZANN SPRING SHU MILA LILLA LAVERNA KEESHA KATTIE GIA GEORGENE EVELINE ESTELL ELIZBETH VIVIENNE VALLIE TRUDIE STEPHANE MICHEL MAGALY MADIE KENYETTA KARREN JANETTA HERMINE HARMONY DRUCILLA DEBBI CELESTINA CANDIE BRITNI BECKIE AMINA ZITA YUN YOLANDE VIVIEN VERNETTA TRUDI SOMMER PEARLE PATRINA OSSIE NICOLLE LOYCE LETTY LARISA KATHARINA JOSELYN JONELLE JENELL IESHA HEIDE FLORINDA FLORENTINA FLO ELODIA DORINE BRUNILDA BRIGID ASHLI ARDELLA TWANA THU TARAH SUNG SHEA SHAVON SHANE SERINA RAYNA RAMONITA NGA MARGURITE LUCRECIA KOURTNEY KATI JESUS JESENIA DIAMOND CRISTA AYANA ALICA ALIA VINNIE SUELLEN ROMELIA RACHELL PIPER OLYMPIA MICHIKO KATHALEEN JOLIE JESSI JANESSA HANA HA ELEASE CARLETTA BRITANY SHONA SALOME ROSAMOND REGENA RAINA NGOC NELIA LOUVENIA LESIA LATRINA LATICIA LARHONDA JINA JACKI HOLLIS HOLLEY EMMY DEEANN CORETTA ARNETTA VELVET THALIA SHANICE NETA MIKKI MICKI LONNA LEANA LASHUNDA KILEY JOYE JACQULYN IGNACIA HYUN HIROKO HENRY HENRIETTE ELAYNE DELINDA DARNELL DAHLIA COREEN CONSUELA CONCHITA CELINE BABETTE AYANNA ANETTE ALBERTINA SKYE SHAWNEE SHANEKA QUIANA PAMELIA MIN MERRI MERLENE MARGIT KIESHA KIERA KAYLENE JODEE JENISE ERLENE EMMIE ELSE DARYL DALILA DAISEY CODY CASIE BELIA BABARA VERSIE VANESA SHELBA SHAWNDA SAM NORMAN NIKIA NAOMA MARNA MARGERET MADALINE LAWANA KINDRA JUTTA JAZMINE JANETT HANNELORE GLENDORA GERTRUD GARNETT FREEDA FREDERICA FLORANCE FLAVIA DENNIS CARLINE BEVERLEE ANJANETTE VALDA TRINITY TAMALA STEVIE SHONNA SHA SARINA ONEIDA MICAH MERILYN MARLEEN LURLINE LENNA KATHERIN JIN JENI HAE GRACIA GLADY FARAH ERIC ENOLA EMA DOMINQUE DEVONA DELANA CECILA CAPRICE ALYSHA ALI ALETHIA VENA THERESIA TAWNY SONG SHAKIRA SAMARA SACHIKO RACHELE PAMELLA NICKY MARNI MARIEL MAREN MALISA LIGIA LERA LATORIA LARAE KIMBER KATHERN KAREY JENNEFER JANETH HALINA FREDIA DELISA DEBROAH CIERA CHIN ANGELIKA ANDREE ALTHA YEN VIVAN TERRESA TANNA SUK SUDIE SOO SIGNE SALENA RONNI REBBECCA MYRTIE MCKENZIE MALIKA MAIDA LOAN LEONARDA KAYLEIGH FRANCE ETHYL ELLYN DAYLE CAMMIE BRITTNI BIRGIT AVELINA ASUNCION ARIANNA AKIKO VENICE TYESHA TONIE TIESHA TAKISHA STEFFANIE SINDY SANTANA MEGHANN MANDA MACIE LADY KELLYE KELLEE JOSLYN JASON INGER INDIRA GLINDA GLENNIS FERNANDA FAUSTINA ENEIDA ELICIA DOT DIGNA DELL ARLETTA ANDRE WILLIA TAMMARA TABETHA SHERRELL SARI REFUGIO REBBECA PAULETTA NIEVES NATOSHA NAKITA MAMMIE KENISHA KAZUKO KASSIE GARY EARLEAN DAPHINE CORLISS CLOTILDE CAROLYNE BERNETTA AUGUSTINA AUDREA ANNIS ANNABELL YAN TENNILLE TAMICA SELENE SEAN ROSANA REGENIA QIANA MARKITA MACY LEEANNE LAURINE KYM JESSENIA JANITA GEORGINE GENIE EMIKO ELVIE DEANDRA DAGMAR CORIE COLLEN CHERISH ROMAINE PORSHA PEARLENE MICHELINE MERNA MARGORIE MARGARETTA LORE KENNETH JENINE HERMINA FREDERICKA ELKE DRUSILLA DORATHY DIONE DESIRE CELENA BRIGIDA ANGELES ALLEGRA THEO TAMEKIA SYNTHIA STEPHEN SOOK SLYVIA ROSANN REATHA RAYE MARQUETTA MARGART LING LAYLA KYMBERLY KIANA KAYLEEN KATLYN KARMEN JOELLA IRINA EMELDA ELENI DETRA CLEMMIE CHERYLL CHANTELL CATHEY ARNITA ARLA ANGLE ANGELIC ALYSE ZOFIA THOMASINE TENNIE SON SHERLY SHERLEY SHARYL REMEDIOS PETRINA NICKOLE MYUNG MYRLE MOZELLA LOUANNE LISHA LATIA LANE KRYSTA JULIENNE JOEL JEANENE JACQUALINE ISAURA GWENDA EARLEEN DONALD CLEOPATRA CARLIE AUDIE ANTONIETTA ALISE ALEX VERDELL VAL TYLER TOMOKO THAO TALISHA STEVEN SO SHEMIKA SHAUN SCARLET SAVANNA SANTINA ROSIA RAEANN ODILIA NANA MINNA MAGAN LYNELLE LE KARMA JOEANN IVANA INELL ILANA HYE HONEY HEE GUDRUN FRANK DREAMA CRISSY CHANTE CARMELINA ARVILLA ARTHUR ANNAMAE ALVERA ALEIDA AARON YEE YANIRA VANDA TIANNA TAM STEFANIA SHIRA PERRY NICOL NANCIE MONSERRATE MINH MELYNDA MELANY MATTHEW LOVELLA LAURE KIRBY KACY JACQUELYNN HYON GERTHA FRANCISCO ELIANA CHRISTENA CHRISTEEN CHARISE CATERINA CARLEY CANDYCE ARLENA AMMIE YANG WILLETTE VANITA TUYET TINY SYREETA SILVA SCOTT RONALD PENNEY NYLA MICHAL MAURICE MARYAM MARYA MAGEN LUDIE LOMA LIVIA LANELL KIMBERLIE JULEE DONETTA DIEDRA DENISHA DEANE DAWNE CLARINE CHERRYL BRONWYN BRANDON ALLA VALERY TONDA SUEANN SORAYA SHOSHANA SHELA SHARLEEN SHANELLE NERISSA MICHEAL MERIDITH MELLIE MAYE MAPLE MAGARET LUIS LILI LEONILA LEONIE LEEANNA LAVONIA LAVERA KRISTEL KATHEY KATHE JUSTIN JULIAN JIMMY JANN ILDA HILDRED HILDEGARDE GENIA FUMIKO EVELIN ERMELINDA ELLY DUNG DOLORIS DIONNA DANAE BERNEICE ANNICE ALIX VERENA VERDIE TRISTAN SHAWNNA SHAWANA SHAUNNA ROZELLA RANDEE RANAE MILAGRO LYNELL LUISE LOUIE LOIDA LISBETH KARLEEN JUNITA JONA ISIS HYACINTH HEDY GWENN ETHELENE ERLINE EDWARD DONYA DOMONIQUE DELICIA DANNETTE CICELY BRANDA BLYTHE BETHANN ASHLYN ANNALEE ALLINE YUKO VELLA TRANG TOWANDA TESHA SHERLYN NARCISA MIGUELINA MERI MAYBELL MARLANA MARGUERITA MADLYN LUNA LORY LORIANN LIBERTY LEONORE LEIGHANN LAURICE LATESHA LARONDA KATRICE KASIE KARL KALEY JADWIGA GLENNIE GEARLDINE FRANCINA EPIFANIA DYAN DORIE DIEDRE DENESE DEMETRICE DELENA DARBY CRISTIE CLEORA CATARINA CARISA BERNIE BARBERA ALMETA TRULA TEREASA SOLANGE SHEILAH SHAVONNE SANORA ROCHELL MATHILDE MARGARETA MAIA LYNSEY LAWANNA LAUNA KENA KEENA KATIA JAMEY GLYNDA GAYLENE ELVINA ELANOR DANUTA DANIKA CRISTEN CORDIE COLETTA CLARITA CARMON BRYNN AZUCENA AUNDREA ANGELE YI WALTER VERLIE VERLENE TAMESHA SILVANA SEBRINA SAMIRA REDA RAYLENE PENNI PANDORA NORAH NOMA MIREILLE MELISSIA MARYALICE LARAINE KIMBERY KARYL KARINE KAM JOLANDA JOHANA JESUSA JALEESA JAE JACQUELYNE IRISH ILUMINADA HILARIA HANH GENNIE FRANCIE FLORETTA EXIE EDDA DREMA DELPHA BEV BARBAR ASSUNTA ARDELL ANNALISA ALISIA YUKIKO YOLANDO WONDA WEI WALTRAUD VETA TEQUILA TEMEKA TAMEIKA SHIRLEEN SHENITA PIEDAD OZELLA MIRTHA MARILU KIMIKO JULIANE JENICE JEN JANAY JACQUILINE HILDE FE FAE EVAN EUGENE ELOIS ECHO DEVORAH CHAU BRINDA BETSEY ARMINDA ARACELIS APRYL ANNETT ALISHIA VEOLA USHA TOSHIKO THEOLA TASHIA TALITHA SHERY RUDY RENETTA REIKO RASHEEDA OMEGA OBDULIA MIKA MELAINE MEGGAN MARTIN MARLEN MARGET MARCELINE MANA MAGDALEN LIBRADA LEZLIE LEXIE LATASHIA LASANDRA KELLE ISIDRA ISA INOCENCIA GWYN FRANCOISE ERMINIA ERINN DIMPLE DEVORA CRISELDA ARMANDA ARIE ARIANE ANGELO ANGELENA ALLEN ALIZA ADRIENE ADALINE XOCHITL TWANNA TRAN TOMIKO TAMISHA TAISHA SUSY SIU RUTHA ROXY RHONA RAYMOND OTHA NORIKO NATASHIA MERRIE MELVIN MARINDA MARIKO MARGERT LORIS LIZZETTE LEISHA KAILA KA JOANNIE JERRICA JENE JANNET JANEE JACINDA HERTA ELENORE DORETTA DELAINE DANIELL CLAUDIE CHINA BRITTA APOLONIA AMBERLY ALEASE YURI YUK WEN WANETA UTE TOMI SHARRI SANDIE ROSELLE REYNALDA RAGUEL PHYLICIA PATRIA OLIMPIA ODELIA MITZIE MITCHELL MISS MINDA MIGNON MICA MENDY MARIVEL MAILE LYNETTA LAVETTE LAURYN LATRISHA LAKIESHA KIERSTEN KARY JOSPHINE JOLYN JETTA JANISE JACQUIE IVELISSE GLYNIS GIANNA GAYNELLE EMERALD DEMETRIUS DANYELL DANILLE DACIA CORALEE CHER CEOLA BRETT BELL ARIANNE ALESHIA YUNG WILLIEMAE TROY TRINH THORA TAI SVETLANA SHERIKA SHEMEKA SHAUNDA ROSELINE RICKI MELDA MALLIE LAVONNA LATINA LARRY LAQUANDA LALA LACHELLE KLARA KANDIS JOHNA JEANMARIE JAYE HANG GRAYCE GERTUDE EMERITA EBONIE CLORINDA CHING CHERY CAROLA BREANN BLOSSOM BERNARDINE BECKI ARLETHA ARGELIA ARA ALITA YULANDA YON YESSENIA TOBI TASIA SYLVIE SHIRL SHIRELY SHERIDAN SHELLA SHANTELLE SACHA ROYCE REBECKA REAGAN PROVIDENCIA PAULENE MISHA MIKI MARLINE MARICA LORITA LATOYIA LASONYA KERSTIN KENDA KEITHA KATHRIN JAYMIE JACK GRICELDA GINETTE ERYN ELINA ELFRIEDA DANYEL CHEREE CHANELLE BARRIE AVERY AURORE ANNAMARIA ALLEEN AILENE AIDE YASMINE VASHTI VALENTINE TREASA TORY TIFFANEY SHERYLL SHARIE SHANAE SAU RAISA PA NEDA MITSUKO MIRELLA MILDA MARYANNA MARAGRET MABELLE LUETTA LORINA LETISHA LATARSHA LANELLE LAJUANA KRISSY KARLY KARENA JON JESSIKA JERICA JEANELLE JANUARY JALISA JACELYN IZOLA IVEY GREGORY EUNA ETHA DREW DOMITILA DOMINICA DAINA CREOLA CARLI CAMIE BUNNY BRITTNY ASHANTI ANISHA ALEEN ADAH YASUKO WINTER VIKI VALRIE TONA TINISHA THI TERISA TATUM TANEKA SIMONNE SHALANDA SERITA RESSIE REFUGIA PAZ OLENE NA MERRILL MARGHERITA MANDIE MAN MAIRE LYNDIA LUCI LORRIANE LORETA LEONIA LAVONA LASHAWNDA LAKIA KYOKO KRYSTINA KRYSTEN KENIA KELSI JUDE JEANICE ISOBEL GEORGIANN GENNY FELICIDAD EILENE DEON DELOISE DEEDEE DANNIE CONCEPTION CLORA CHERILYN CHANG CALANDRA BERRY ARMANDINA ANISA ULA TIMOTHY TIERA THERESSA STEPHANIA SIMA SHYLA SHONTA SHERA SHAQUITA SHALA SAMMY ROSSANA NOHEMI NERY MORIAH MELITA MELIDA MELANI MARYLYNN MARISHA MARIETTE MALORIE MADELENE LUDIVINA LORIA LORETTE LORALEE LIANNE LEON LAVENIA LAURINDA LASHON KIT KIMI KEILA KATELYNN KAI JONE JOANE JI JAYNA JANELLA JA HUE HERTHA FRANCENE ELINORE DESPINA DELSIE DEEDRA CLEMENCIA CARRY CAROLIN CARLOS BULAH BRITTANIE BOK BLONDELL BIBI BEAULAH BEATA ANNITA AGRIPINA VIRGEN VALENE UN TWANDA TOMMYE TOI TARRA TARI TAMMERA SHAKIA SADYE RUTHANNE ROCHEL RIVKA PURA NENITA NATISHA MING MERRILEE MELODEE MARVIS LUCILLA LEENA LAVETA LARITA LANIE KEREN ILEEN GEORGEANN GENNA GENESIS FRIDA EWA EUFEMIA EMELY ELA EDYTH DEONNA DEADRA DARLENA CHANELL CHAN CATHERN CASSONDRA CASSAUNDRA BERNARDA BERNA ARLINDA ANAMARIA ALBERT WESLEY VERTIE VALERI TORRI TATYANA STASIA SHERISE SHERILL SEASON SCOTTIE SANDA RUTHE ROSY ROBERTO ROBBI RANEE QUYEN PEARLY PALMIRA ONITA NISHA NIESHA NIDA NEVADA NAM MERLYN MAYOLA MARYLOUISE MARYLAND MARX MARTH MARGENE MADELAINE LONDA LEONTINE LEOMA LEIA LAWRENCE LAURALEE LANORA LAKITA KIYOKO KETURAH KATELIN KAREEN JONIE JOHNETTE JENEE JEANETT IZETTA HIEDI HEIKE HASSIE HAROLD GIUSEPPINA GEORGANN FIDELA FERNANDE ELWANDA ELLAMAE ELIZ DUSTI DOTTY CYNDY CORALIE CELESTA ARGENTINA ALVERTA XENIA WAVA VANETTA TORRIE TASHINA TANDY TAMBRA TAMA STEPANIE SHILA SHAUNTA SHARAN SHANIQUA SHAE SETSUKO SERAFINA SANDEE ROSAMARIA PRISCILA OLINDA NADENE MUOI MICHELINA MERCEDEZ MARYROSE MARIN MARCENE MAO MAGALI MAFALDA LOGAN LINN LANNIE KAYCE KAROLINE KAMILAH KAMALA JUSTA JOLINE JENNINE JACQUETTA IRAIDA GERALD GEORGEANNA FRANCHESCA FAIRY EMELINE ELANE EHTEL EARLIE DULCIE DALENE CRIS CLASSIE CHERE CHARIS CAROYLN CARMINA CARITA BRIAN BETHANIE AYAKO ARICA AN ALYSA ALESSANDRA AKILAH ADRIEN ZETTA YOULANDA YELENA YAHAIRA XUAN WENDOLYN VICTOR TIJUANA TERRELL TERINA TERESIA SUZI SUNDAY SHERELL SHAVONDA SHAUNTE SHARDA SHAKITA SENA RYANN RUBI RIVA REGINIA REA RACHAL PARTHENIA PAMULA MONNIE MONET MICHAELE MELIA MARINE MALKA MAISHA LISANDRA LEO LEKISHA LEAN LAURENCE LAKENDRA KRYSTIN KORTNEY KIZZIE KITTIE KERA KENDAL KEMBERLY KANISHA JULENE JULE JOSHUA JOHANNE JEFFREY JAMEE HAN HALLEY GIDGET GALINA FREDRICKA FLETA FATIMAH EUSEBIA ELZA ELEONORE DORTHEY DORIA DONELLA DINORAH DELORSE CLARETHA CHRISTINIA CHARLYN BONG BELKIS AZZIE ANDERA AIKO ADENA YER YAJAIRA WAN VANIA ULRIKE TOSHIA TIFANY STEFANY SHIZUE SHENIKA SHAWANNA SHAROLYN SHARILYN SHAQUANA SHANTAY SEE ROZANNE ROSELEE RICKIE REMONA REANNA RAELENE QUINN PHUNG PETRONILA NATACHA NANCEY MYRL MIYOKO MIESHA MERIDETH MARVELLA MARQUITTA MARHTA MARCHELLE LIZETH LIBBIE LAHOMA LADAWN KINA KATHELEEN KATHARYN KARISA KALEIGH JUNIE JULIEANN JOHNSIE JANEAN JAIMEE JACKQUELINE HISAKO HERMA HELAINE GWYNETH GLENN GITA EUSTOLIA EMELINA ELIN EDRIS DONNETTE DONNETTA DIERDRE DENAE DARCEL CLAUDE CLARISA CINDERELLA CHIA CHARLESETTA CHARITA CELSA CASSY CASSI CARLEE BRUNA BRITTANEY BRANDE BILLI BAO ANTONETTA ANGLA ANGELYN ANALISA ALANE WENONA WENDIE VERONIQUE VANNESA TOBIE TEMPIE SUMIKO SULEMA SPARKLE SOMER SHEBA SHAYNE SHARICE SHANEL SHALON SAGE ROY ROSIO ROSELIA RENAY REMA REENA PORSCHE PING PEG OZIE ORETHA ORALEE ODA NU NGAN NAKESHA MILLY MARYBELLE MARLIN MARIS MARGRETT MARAGARET MANIE LURLENE LILLIA LIESELOTTE LAVELLE LASHAUNDA LAKEESHA KEITH KAYCEE KALYN JOYA JOETTE JENAE JANIECE ILLA GRISEL GLAYDS GENEVIE GALA FREDDA FRED ELMER ELEONOR DEBERA DEANDREA DAN CORRINNE CORDIA CONTESSA COLENE CLEOTILDE CHARLOTT CHANTAY CECILLE BEATRIS AZALEE ARLEAN ARDATH ANJELICA ANJA ALFREDIA ALEISHA ADAM ZADA YUONNE XIAO WILLODEAN WHITLEY VENNIE VANNA TYISHA TOVA TORIE TONISHA TILDA TIEN TEMPLE SIRENA SHERRIL SHANTI SHAN SENAIDA SAMELLA ROBBYN RENDA REITA PHEBE PAULITA NOBUKO NGUYET NEOMI MOON MIKAELA MELANIA MAXIMINA MARG MAISIE LYNNA LILLI LAYNE LASHAUN LAKENYA LAEL KIRSTIE KATHLINE KASHA KARLYN KARIMA JOVAN JOSEFINE JENNELL JACQUI JACKELYN HYO HIEN GRAZYNA FLORRIE FLORIA ELEONORA DWANA DORLA DONG DELMY DEJA DEDE DANN CRYSTA CLELIA CLARIS CLARENCE CHIEKO CHERLYN CHERELLE CHARMAIN CHARA CAMMY BEE ARNETTE ARDELLE ANNIKA AMIEE AMEE ALLENA YVONE YUKI YOSHIE YEVETTE YAEL WILLETTA VONCILE VENETTA TULA TONETTE TIMIKA TEMIKA TELMA TEISHA TAREN TA STACEE SHIN SHAWNTA SATURNINA RICARDA POK PASTY ONIE NUBIA MORA MIKE MARIELLE MARIELLA MARIANELA MARDELL MANY LUANNA LOISE LISABETH LINDSY LILLIANA LILLIAM LELAH LEIGHA LEANORA LANG KRISTEEN KHALILAH KEELEY KANDRA JUNKO JOAQUINA JERLENE JANI JAMIKA JAME HSIU HERMILA GOLDEN GENEVIVE EVIA EUGENA EMMALINE ELFREDA ELENE DONETTE DELCIE DEEANNA DARCEY CUC CLARINDA CIRA CHAE CELINDA CATHERYN CATHERIN CASIMIRA CARMELIA CAMELLIA BREANA BOBETTE BERNARDINA BEBE BASILIA ARLYNE AMAL ALAYNA ZONIA ZENIA YURIKO YAEKO WYNELL WILLOW WILLENA VERNIA TU TRAVIS TORA TERRILYN TERICA TENESHA TAWNA TAJUANA TAINA STEPHNIE SONA SOL SINA SHONDRA SHIZUKO SHERLENE SHERICE SHARIKA ROSSIE ROSENA RORY RIMA RIA RHEBA RENNA PETER NATALYA NANCEE MELODI MEDA MAXIMA MATHA MARKETTA MARICRUZ MARCELENE MALVINA LUBA LOUETTA LEIDA LECIA LAURAN LASHAWNA LAINE KHADIJAH KATERINE KASI KALLIE JULIETTA JESUSITA JESTINE JESSIA JEREMY JEFFIE JANYCE ISADORA GEORGIANNE FIDELIA EVITA EURA EULAH ESTEFANA ELSY ELIZABET ELADIA DODIE DION DIA DENISSE DELORAS DELILA DAYSI DAKOTA CURTIS CRYSTLE CONCHA COLBY CLARETTA CHU CHRISTIA CHARLSIE CHARLENA CARYLON BETTYANN ASLEY ASHLEA AMIRA AI AGUEDA AGNUS YUETTE VINITA VICTORINA TYNISHA TREENA TOCCARA TISH THOMASENA TEGAN SOILA SHILOH SHENNA SHARMAINE SHANTAE SHANDI SEPTEMBER SARAN SARAI SANA SAMUEL SALLEY ROSETTE ROLANDE REGINE OTELIA OSCAR OLEVIA NICHOLLE NECOLE NAIDA MYRTA MYESHA MITSUE MINTA MERTIE MARGY MAHALIA MADALENE LOVE LOURA LOREAN LEWIS LESHA LEONIDA LENITA LAVONE LASHELL LASHANDRA LAMONICA KIMBRA KATHERINA KARRY KANESHA JULIO JONG JENEVA JAQUELYN HWA GILMA GHISLAINE GERTRUDIS FRANSISCA FERMINA ETTIE ETSUKO ELLIS ELLAN ELIDIA EDRA DORETHEA DOREATHA DENYSE DENNY DEETTA DAINE CYRSTAL CORRIN CAYLA CARLITA CAMILA BURMA BULA BUENA BLAKE BARABARA AVRIL AUSTIN ALAINE ZANA WILHEMINA WANETTA VIRGIL VI VERONIKA VERNON VERLINE VASILIKI TONITA TISA TEOFILA TAYNA TAUNYA TANDRA TAKAKO SUNNI SUANNE SIXTA SHARELL SEEMA RUSSELL ROSENDA ROBENA RAYMONDE PEI PAMILA OZELL NEIDA NEELY MISTIE MICHA MERISSA MAURITA MARYLN MARYETTA MARSHALL MARCELL MALENA MAKEDA MADDIE LOVETTA LOURIE LORRINE LORILEE LESTER LAURENA LASHAY LARRAINE LAREE LACRESHA KRISTLE KRISHNA KEVA KEIRA KAROLE JOIE JINNY JEANNETTA JAMA HEIDY GILBERTE GEMA FAVIOLA EVELYNN ENDA ELLI ELLENA DIVINA DAGNY COLLENE CODI CINDIE CHASSIDY CHASIDY CATRICE CATHERINA CASSEY CAROLL CARLENA CANDRA CALISTA BRYANNA BRITTENY BEULA BARI AUDRIE AUDRIA ARDELIA ANNELLE ANGILA ALONA ALLYN DOUGLAS ROGER JONATHAN RALPH NICHOLAS BENJAMIN BRUCE HARRY WAYNE STEVE HOWARD ERNEST PHILLIP TODD CRAIG ALAN PHILIP EARL DANNY BRYAN STANLEY LEONARD NATHAN MANUEL RODNEY MARVIN VINCENT JEFFERY JEFF CHAD JACOB ALFRED BRADLEY HERBERT FREDERICK EDWIN DON RICKY RANDALL BARRY BERNARD LEROY MARCUS THEODORE CLIFFORD MIGUEL JIM TOM CALVIN BILL LLOYD DEREK WARREN DARRELL JEROME FLOYD ALVIN TIM GORDON GREG JORGE DUSTIN PEDRO DERRICK ZACHARY HERMAN GLEN HECTOR RICARDO RICK BRENT RAMON GILBERT MARC REGINALD RUBEN NATHANIEL RAFAEL EDGAR MILTON RAUL BEN CHESTER DUANE FRANKLIN BRAD RON ROLAND ARNOLD HARVEY JARED ERIK DARRYL NEIL JAVIER FERNANDO CLINTON TED MATHEW TYRONE DARREN LANCE KURT ALLAN NELSON GUY CLAYTON HUGH MAX DWAYNE DWIGHT ARMANDO FELIX EVERETT IAN WALLACE KEN BOB ALFREDO ALBERTO DAVE IVAN BYRON ISAAC MORRIS CLIFTON WILLARD ROSS ANDY SALVADOR KIRK SERGIO SETH KENT TERRANCE EDUARDO TERRENCE ENRIQUE WADE STUART FREDRICK ARTURO ALEJANDRO NICK LUTHER WENDELL JEREMIAH JULIUS OTIS TREVOR OLIVER LUKE HOMER GERARD DOUG KENNY HUBERT LYLE MATT ALFONSO ORLANDO REX CARLTON ERNESTO NEAL PABLO LORENZO OMAR WILBUR GRANT HORACE RODERICK ABRAHAM WILLIS RICKEY ANDRES CESAR JOHNATHAN MALCOLM RUDOLPH DAMON KELVIN PRESTON ALTON ARCHIE MARCO WM PETE RANDOLPH GARRY GEOFFREY JONATHON FELIPE GERARDO ED DOMINIC DELBERT COLIN GUILLERMO EARNEST LUCAS BENNY SPENCER RODOLFO MYRON EDMUND GARRETT SALVATORE CEDRIC LOWELL GREGG SHERMAN WILSON SYLVESTER ROOSEVELT ISRAEL JERMAINE FORREST WILBERT LELAND SIMON CLARK IRVING BRYANT OWEN RUFUS WOODROW KRISTOPHER MACK LEVI MARCOS GUSTAVO JAKE LIONEL GILBERTO CLINT NICOLAS ISMAEL ORVILLE ERVIN DEWEY AL WILFRED JOSH HUGO IGNACIO CALEB TOMAS SHELDON ERICK STEWART DOYLE DARREL ROGELIO TERENCE SANTIAGO ALONZO ELIAS BERT ELBERT RAMIRO CONRAD NOAH GRADY PHIL CORNELIUS LAMAR ROLANDO CLAY PERCY DEXTER BRADFORD DARIN AMOS MOSES IRVIN SAUL ROMAN RANDAL TIMMY DARRIN WINSTON BRENDAN ABEL DOMINICK BOYD EMILIO ELIJAH DOMINGO EMMETT MARLON EMANUEL JERALD EDMOND EMIL DEWAYNE WILL OTTO TEDDY REYNALDO BRET JESS TRENT HUMBERTO EMMANUEL STEPHAN VICENTE LAMONT GARLAND MILES EFRAIN HEATH RODGER HARLEY ETHAN ELDON ROCKY PIERRE JUNIOR FREDDY ELI BRYCE ANTOINE STERLING CHASE GROVER ELTON CLEVELAND DYLAN CHUCK DAMIAN REUBEN STAN AUGUST LEONARDO JASPER RUSSEL ERWIN BENITO HANS MONTE BLAINE ERNIE CURT QUENTIN AGUSTIN MURRAY JAMAL ADOLFO HARRISON TYSON BURTON BRADY ELLIOTT WILFREDO BART JARROD VANCE DENIS DAMIEN JOAQUIN HARLAN DESMOND ELLIOT DARWIN GREGORIO BUDDY XAVIER KERMIT ROSCOE ESTEBAN ANTON SOLOMON SCOTTY NORBERT ELVIN WILLIAMS NOLAN ROD QUINTON HAL BRAIN ROB ELWOOD KENDRICK DARIUS MOISES FIDEL THADDEUS CLIFF MARCEL JACKSON RAPHAEL BRYON ARMAND ALVARO JEFFRY DANE JOESPH THURMAN NED RUSTY MONTY FABIAN REGGIE MASON GRAHAM ISAIAH VAUGHN GUS LOYD DIEGO ADOLPH NORRIS MILLARD ROCCO GONZALO DERICK RODRIGO WILEY RIGOBERTO ALPHONSO TY NOE VERN REED JEFFERSON ELVIS BERNARDO MAURICIO HIRAM DONOVAN BASIL RILEY NICKOLAS MAYNARD SCOT VINCE QUINCY EDDY SEBASTIAN FEDERICO ULYSSES HERIBERTO DONNELL COLE DAVIS GAVIN EMERY WARD ROMEO JAYSON DANTE CLEMENT COY MAXWELL JARVIS BRUNO ISSAC DUDLEY BROCK SANFORD CARMELO BARNEY NESTOR STEFAN DONNY ART LINWOOD BEAU WELDON GALEN ISIDRO TRUMAN DELMAR JOHNATHON SILAS FREDERIC DICK IRWIN MERLIN CHARLEY MARCELINO HARRIS CARLO TRENTON KURTIS HUNTER AURELIO WINFRED VITO COLLIN DENVER CARTER LEONEL EMORY PASQUALE MOHAMMAD MARIANO DANIAL LANDON DIRK BRANDEN ADAN BUFORD GERMAN WILMER EMERSON ZACHERY FLETCHER JACQUES ERROL DALTON MONROE JOSUE EDWARDO BOOKER WILFORD SONNY SHELTON CARSON THERON RAYMUNDO DAREN HOUSTON ROBBY LINCOLN GENARO BENNETT OCTAVIO CORNELL HUNG ARRON ANTONY HERSCHEL GIOVANNI GARTH CYRUS CYRIL RONNY LON FREEMAN DUNCAN KENNITH CARMINE ERICH CHADWICK WILBURN RUSS REID MYLES ANDERSON MORTON JONAS FOREST MITCHEL MERVIN ZANE RICH JAMEL LAZARO ALPHONSE RANDELL MAJOR JARRETT BROOKS ABDUL LUCIANO SEYMOUR EUGENIO MOHAMMED VALENTIN CHANCE ARNULFO LUCIEN FERDINAND THAD EZRA ALDO RUBIN ROYAL MITCH EARLE ABE WYATT MARQUIS LANNY KAREEM JAMAR BORIS ISIAH EMILE ELMO ARON LEOPOLDO EVERETTE JOSEF ELOY RODRICK REINALDO LUCIO JERROD WESTON HERSHEL BARTON PARKER LEMUEL BURT JULES GIL ELISEO AHMAD NIGEL EFREN ANTWAN ALDEN MARGARITO COLEMAN DINO OSVALDO LES DEANDRE NORMAND KIETH TREY NORBERTO NAPOLEON JEROLD FRITZ ROSENDO MILFORD CHRISTOPER ALFONZO LYMAN JOSIAH BRANT WILTON RICO JAMAAL DEWITT BRENTON OLIN FOSTER FAUSTINO CLAUDIO JUDSON GINO EDGARDO ALEC TANNER JARRED DONN TAD PRINCE PORFIRIO ODIS LENARD CHAUNCEY TOD MEL MARCELO KORY AUGUSTUS KEVEN HILARIO BUD SAL ORVAL MAURO ZACHARIAH OLEN ANIBAL MILO JED DILLON AMADO NEWTON LENNY RICHIE HORACIO BRICE MOHAMED DELMER DARIO REYES MAC JONAH JERROLD ROBT HANK RUPERT ROLLAND KENTON DAMION ANTONE WALDO FREDRIC BRADLY KIP BURL WALKER TYREE JEFFEREY AHMED WILLY STANFORD OREN NOBLE MOSHE MIKEL ENOCH BRENDON QUINTIN JAMISON FLORENCIO DARRICK TOBIAS HASSAN GIUSEPPE DEMARCUS CLETUS TYRELL LYNDON KEENAN WERNER GERALDO COLUMBUS CHET BERTRAM MARKUS HUEY HILTON DWAIN DONTE TYRON OMER ISAIAS HIPOLITO FERMIN ADALBERTO BO BARRETT TEODORO MCKINLEY MAXIMO GARFIELD RALEIGH LAWERENCE ABRAM RASHAD KING EMMITT DARON SAMUAL MIQUEL EUSEBIO DOMENIC DARRON BUSTER WILBER RENATO JC HOYT HAYWOOD EZEKIEL CHAS FLORENTINO ELROY CLEMENTE ARDEN NEVILLE EDISON DESHAWN NATHANIAL JORDON DANILO CLAUD SHERWOOD RAYMON RAYFORD CRISTOBAL AMBROSE TITUS HYMAN FELTON EZEQUIEL ERASMO STANTON LONNY LEN IKE MILAN LINO JAROD HERB ANDREAS WALTON RHETT PALMER DOUGLASS CORDELL OSWALDO ELLSWORTH VIRGILIO TONEY NATHANAEL DEL BENEDICT MOSE JOHNSON ISREAL GARRET FAUSTO ASA ARLEN ZACK WARNER MODESTO FRANCESCO MANUAL GAYLORD GASTON FILIBERTO DEANGELO MICHALE GRANVILLE WES MALIK ZACKARY TUAN ELDRIDGE CRISTOPHER CORTEZ ANTIONE MALCOM LONG KOREY JOSPEH COLTON WAYLON VON HOSEA SHAD SANTO RUDOLF ROLF REY RENALDO MARCELLUS LUCIUS KRISTOFER BOYCE BENTON HAYDEN HARLAND ARNOLDO RUEBEN LEANDRO KRAIG JERRELL JEROMY HOBERT CEDRICK ARLIE WINFORD WALLY LUIGI KENETH JACINTO GRAIG FRANKLYN EDMUNDO SID PORTER LEIF JERAMY BUCK WILLIAN VINCENZO SHON LYNWOOD JERE HAI ELDEN DORSEY DARELL BRODERICK ALONSO".split(" ") + +names.sort() + +var sum = 0 + +for (var i : var name in names) { + var score = 0 + for (var c in name) { + score += c.code() - '@'.code() + } + sum += score * (i + 1) +} + +return sum; \ No newline at end of file diff --git a/src/test/resources/ai/euler/pe023.leek b/src/test/resources/ai/euler/pe023.leek new file mode 100644 index 00000000..c98abaa0 --- /dev/null +++ b/src/test/resources/ai/euler/pe023.leek @@ -0,0 +1,39 @@ +function isAbundant(n) { + var sum = 0; + var half = n \ 2; + for (var i = 1; i <= half; ++i) + if (n % i == 0) { + sum += i + } + return sum > n +} + +let N = 28123 + +var numbers = [].fill(0, N) +var abundant = [].fill(false, N) +var canBeWritten = [].fill(false, N) + +for (var i = 0; i < N; ++i) { + numbers[i] = i + 1 + abundant[i] = isAbundant(i + 1) + canBeWritten[i] = false +} + +for (var i = 0; i < N; ++i) { + if (abundant[i]) { + for (var j = 0; j < N; ++j) { + if (abundant[j]) { + var sum = numbers[i] + numbers[j]; + if (sum <= N) canBeWritten[sum - 1] = true; + } + } + } +} + +var sum = 0; +for (var i = 0; i < N; ++i) { + if (!canBeWritten[i]) sum += (i + 1); +} + +sum \ No newline at end of file diff --git a/src/test/resources/ai/euler/pe024.leek b/src/test/resources/ai/euler/pe024.leek new file mode 100644 index 00000000..7bd42ac2 --- /dev/null +++ b/src/test/resources/ai/euler/pe024.leek @@ -0,0 +1,28 @@ +var p = 1 + +for (var a = 0; a <= 9; ++a) +for (var b = 0; b <= 9; ++b) +if (b != a) +for (var c = 0; c <= 9; ++c) +if (c != b && c != a) +for (var d = 0; d <= 9; ++d) +if (d != c && d != b && d != a) +for (var e = 0; e <= 9; ++e) +if (e != d && e != c && e != b && e != a) +for (var f = 0; f <= 9; ++f) +if (f != e && f != d && f != c && f != b && f != a) +for (var g = 0; g <= 9; ++g) +if (g != f && g != e && g != d && g != c && g != b && g != a) +for (var h = 0; h <= 9; ++h) +if (h != g && h != f && h != e && h != d && h != c && h != b && h != a) +for (var i = 0; i <= 9; ++i) +if (i != h && i != g && i != f && i != e && i != d && i != c && i != b && i != a) +for (var j = 0; j <= 9; ++j) +if (j != i && j != h && j != g && j != f && j != e && j != d && j != c && j != b && j != a) { + + var n = a*1000000000L + b*100000000L + c*10000000L + d*1000000 + e*100000 + f*10000 + g*1000 + h*100 + i * 10 + j + + if (p++ == 1000000) { + return n + } +} \ No newline at end of file diff --git a/src/test/resources/ai/euler/pe025.leek b/src/test/resources/ai/euler/pe025.leek new file mode 100644 index 00000000..987111f9 --- /dev/null +++ b/src/test/resources/ai/euler/pe025.leek @@ -0,0 +1,15 @@ +var n1 = 1m +var n2 = 1m + +var t = 2 + +while |n1.string()| < 1000 { + + var tmp = n1 + n1 = n1 + n2 + n2 = tmp + + t++ +} + +t \ No newline at end of file diff --git a/src/test/resources/ai/euler/pe027.leek b/src/test/resources/ai/euler/pe027.leek new file mode 100644 index 00000000..350a7fa2 --- /dev/null +++ b/src/test/resources/ai/euler/pe027.leek @@ -0,0 +1,33 @@ +function numPrimes(a, b) { + var n = 0 + // TODO while (n*n + a*n + b).isPrime() not working + while ((n*n + a*n + b).isPrime()) { n++ } + return n +} + +// print(numPrimes(-79, 1601)) + +var max = 0; +var maxA = 0, maxB = 0; + +for (var a = -999; a < 1000; ++a) { + for (var b = -999; b < 1000; ++b) { + + if (b.isPrime()) { // b doit etre premier ! + + var num = numPrimes(a, b); + if (num > max) { + max = num + maxA = a + maxB = b + } + } + } +} +/* +print("Nombre de premiers : " + max) +print("a : " + maxA) +print("b : " + maxB) +print("ab : " + maxA * maxB) +*/ +return maxA * maxB diff --git a/src/test/resources/ai/euler/pe028.leek b/src/test/resources/ai/euler/pe028.leek new file mode 100644 index 00000000..9ac3cdfd --- /dev/null +++ b/src/test/resources/ai/euler/pe028.leek @@ -0,0 +1,15 @@ + + +var size = 1001 +var n = 1m +var steps = size \ 2 + +for i in [1..steps] { + var x = 2*i + 1 + n += x*x + n += x*x - 6*i + n += x*x - 4*i + n += x*x - 2*i +} + +n \ No newline at end of file diff --git a/src/test/resources/ai/euler/pe062.leek b/src/test/resources/ai/euler/pe062.leek new file mode 100644 index 00000000..c72f80bb --- /dev/null +++ b/src/test/resources/ai/euler/pe062.leek @@ -0,0 +1,20 @@ +var singles = [] +var groups = ['s' : 12] groups.erase('s') +var first = [:] +var i = 405l + +while i++ { + + var n = '' + i.pow(3) + var ns = n.sort() + + if ns in groups { + var c = groups[ns] = groups[ns] + 1 + if (c == 5) { + return String.number(first[ns]) + } + } else { + groups.insert(ns, 1) + first.insert(ns, n) + } +} diff --git a/src/test/resources/ai/euler/pe063.leek b/src/test/resources/ai/euler/pe063.leek new file mode 100644 index 00000000..795537c5 --- /dev/null +++ b/src/test/resources/ai/euler/pe063.leek @@ -0,0 +1,10 @@ +var c = 0 +for (var power = 1m; power < 25m; power++) { + for (var n = 1m; n < 10m; n++) { + var s = '' + (n ** power) + if power == s.size() { + c++ + } + } +} +c diff --git a/src/test/resources/ai/euler/pe064.leek b/src/test/resources/ai/euler/pe064.leek new file mode 100644 index 00000000..f120c2e5 --- /dev/null +++ b/src/test/resources/ai/euler/pe064.leek @@ -0,0 +1,11 @@ +let period = n => { + var s = n.sqrt(), a0 = s.int() + if (n == a0 * a0) return 0 + var a = a0 var b = 1 var l = 0 // TODO with commas + while ++l { + b = (n - a * a) \ b + a = b * ((s + a) \ b) - a + if (a == a0 and b == 1) return l + } +} +[2..10000].filter(i => period(i) % 2).size() \ No newline at end of file diff --git a/src/test/resources/ai/euler/pe066.leek b/src/test/resources/ai/euler/pe066.leek new file mode 100644 index 00000000..18ac3703 --- /dev/null +++ b/src/test/resources/ai/euler/pe066.leek @@ -0,0 +1,23 @@ +function solve(D) { + var x = 1l + while x++ { + var s = ((x * x - 1) / D).sqrt() + if s.long() == s { + print((x * x - 1) / D) + print(s) + print(s.long()) + return x + } + } +} + +solve(61) +/* +var max = 0 +var maxD = 0 +for D in [1..1000] { + if D.sqrt().isInteger() continue + var x = solve(D) + x > max ? { max = x maxD = D } : 0 +} +maxD \ No newline at end of file diff --git a/src/test/resources/ai/euler/pe206.leek b/src/test/resources/ai/euler/pe206.leek new file mode 100644 index 00000000..0566af03 --- /dev/null +++ b/src/test/resources/ai/euler/pe206.leek @@ -0,0 +1,24 @@ +var res = '' +var search = function(start, base, level) { + if (level == 5) { + var b = base + (10m ** (20 - 2 * level)) + for (var j = Number.sqrt(start); j < Number.sqrt(b); ++j) { + var s = '' + (j ** 2) + for var k = 0; k < 9; { + if s[k * 2] != ('' + (++k)) continue 2 + } + res += ('' + j) + } + } else { + for var i = 0m; i < 10m; ++i { + var p = i * (10m ** (19 - 2 * level)) + var a = start + p + var b = base + (level + 1) * (10m ** (18 - 2 * level)) + p + search(a, b, level + 1) + } + } +} + +search(1020304050607080900m, 1000000000000000000m, 1) + +res.number() diff --git a/src/test/resources/ai/french.leek b/src/test/resources/ai/french.leek new file mode 100644 index 00000000..ef2a01ca --- /dev/null +++ b/src/test/resources/ai/french.leek @@ -0,0 +1,6 @@ +function _(n) { + var T = '-', V = '', x = split('s un deux trois quatre cinq six sept huit neuf dix onze douze treize quatorze quinze seize dix vingt trente quarante cinquante soixante quatre-vingt cent' ' '), b = n % 100, d = 17 + b / 10, u = n % 10, c = n / 100 | 0, e = u - 1 ? T : '-et-', L = log10(n) / 3 | 0, H = 1000 ** L, v = n / H | 0, i = [T ' ' x[d] ? 0 : d-- | (u += 10)][L > 1]; + return L < 1 ? c ? (c > 1 ? _(c) + T : V) + x[27] + x[c * !b < 2] + (b ? T : V) + _(b) : n < 17 ? x[n + 1] : n < 20 ? x[11] + T + x[u + 1] : x[d] + (u ? e + _(u) : x[d != 25]) : (L * v > 1 ? _(v) + i : V) + 'mill' + [n %= H 'e' 'ion' 'iard'][L] + x[v < 2 | L < 2] + (n ? i : V) + _(n); +} + +return _(123456789); \ No newline at end of file diff --git a/src/test/resources/ai/include_multiple.leek b/src/test/resources/ai/include_multiple.leek new file mode 100644 index 00000000..aaaa73d6 --- /dev/null +++ b/src/test/resources/ai/include_multiple.leek @@ -0,0 +1,2 @@ + +include("array_keys.leek"); \ No newline at end of file diff --git a/src/test/resources/ai/include_sub.leek b/src/test/resources/ai/include_sub.leek new file mode 100644 index 00000000..6e944acd --- /dev/null +++ b/src/test/resources/ai/include_sub.leek @@ -0,0 +1 @@ +include('subfolder/sub.leek'); \ No newline at end of file diff --git a/src/test/resources/ai/library.leek b/src/test/resources/ai/library.leek new file mode 100644 index 00000000..513fa824 --- /dev/null +++ b/src/test/resources/ai/library.leek @@ -0,0 +1,5 @@ +function arrayKeys(array) { + var keys = []; + for (var k : var _ in array) push(keys, k); + return keys; +} \ No newline at end of file diff --git a/src/test/resources/ai/multiple_includes.leek b/src/test/resources/ai/multiple_includes.leek new file mode 100644 index 00000000..2e975a1c --- /dev/null +++ b/src/test/resources/ai/multiple_includes.leek @@ -0,0 +1,3 @@ +include("bonjour.leek"); +include("bonjour.leek"); +include("bonjour.leek"); \ No newline at end of file diff --git a/src/test/resources/ai/subfolder/include_parent.leek b/src/test/resources/ai/subfolder/include_parent.leek new file mode 100644 index 00000000..1684b3f4 --- /dev/null +++ b/src/test/resources/ai/subfolder/include_parent.leek @@ -0,0 +1 @@ +include('../french.leek'); \ No newline at end of file diff --git a/src/test/resources/ai/subfolder/sub.leek b/src/test/resources/ai/subfolder/sub.leek new file mode 100644 index 00000000..fcedbf97 --- /dev/null +++ b/src/test/resources/ai/subfolder/sub.leek @@ -0,0 +1 @@ +return 'sub'; \ No newline at end of file From 7c621b9a37018567d86907bdbc9435b6b21d0848 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 150/319] [ai] Add custom operation limit --- src/main/java/leekscript/runner/AI.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 66ff2316..019f4d6f 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -25,7 +25,8 @@ public abstract class AI { public final static int MAX_MEMORY = 100000; protected long mOperations = 0; - public final static long MAX_OPERATIONS = 20000000; + public final static int MAX_OPERATIONS = 20000000; + public int maxOperations = MAX_OPERATIONS; protected JSONArray mErrorObject = null; protected String thisObject = null; @@ -36,6 +37,7 @@ public abstract class AI { protected int mInstructions; protected RandomGenerator randomGenerator; + public AI() { mUAI = this; logs = new AILog(); @@ -70,7 +72,7 @@ public AILog getLogs() { public void addOperations(int nb) throws LeekRunException { mOperations += nb; - if (mOperations >= MAX_OPERATIONS) { + if (mOperations >= maxOperations) { throw new LeekRunException(LeekRunException.TOO_MUCH_OPERATIONS); } } From 9041b255670ab930d2ffb9e97bb9d4ae102cd4cd Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 151/319] [test] Run tests with gradle --- build.gradle | 18 +++++++++++------- .../java/leekscript/compiler/LeekScript.java | 6 ++++++ src/test/java/test/TestCommon.java | 10 +++++++--- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index 5f494d27..f435f102 100644 --- a/build.gradle +++ b/build.gradle @@ -5,12 +5,9 @@ sourceSets { java { srcDirs = ['src/test/java'] } - } -} - -test { - testLogging { - events "passed", "skipped", "failed" + resources { + srcDirs = ['src/test/resources'] + } } } @@ -23,7 +20,7 @@ jar { attributes "Main-Class": "leekscript.TopLevel" } from { - configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } } @@ -35,3 +32,10 @@ dependencies { testImplementation 'junit:junit:4.12' implementation group: 'com.alibaba', name: 'fastjson', version: '1.1.25' } + +task tests(type: Exec) { + group = "Execution" + description = "Run the main class with ExecTask" + commandLine "java", "-classpath", sourceSets.test.runtimeClasspath.getAsPath(), "test.TestMain" +} +test.dependsOn(tests) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 5d25db47..70b5ae34 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -66,6 +66,11 @@ public static AI compileSnippet(String snippet, String AIClass) throws LeekScrip return compile(ai, AIClass, false); } + public static AI compileSnippet(String snippet, String AIClass, int version) throws LeekScriptException, LeekCompilerException, IOException { + AIFile ai = new AIFile("", snippet, System.currentTimeMillis(), version, null); + return compile(ai, AIClass, false); + } + public static boolean testScript(String leek, String script, AbstractLeekValue s, String AIClass, boolean nocache) throws Exception { AI ai = LeekScript.compileSnippet(script, AIClass); AbstractLeekValue v = ai.runIA(); @@ -176,4 +181,5 @@ public static void throwException(String error) throws LeekScriptException { throw new LeekScriptException(LeekScriptException.CANT_COMPILE, error); } + } \ No newline at end of file diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index 3b12cc98..c8e7a692 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -62,8 +62,12 @@ public void almost(double expected) { public void almost(double expected, double delta) { run(version, new Checker() { public boolean check(Result result) { - double r = Double.parseDouble(result.result); - return Math.abs(r - expected) < delta; + try { + double r = Double.parseDouble(result.result); + return Math.abs(r - expected) < delta; + } catch (Exception e) { + return false; + } } public String getExpected() { return String.valueOf(expected); } }); @@ -92,7 +96,7 @@ public void run_version(int version, Checker checker) { try { boolean is_file = code.contains(".leek"); - AI ai = is_file ? LeekScript.compileFile(code, "AI", version) : LeekScript.compileSnippet(code, "AI"); + AI ai = is_file ? LeekScript.compileFile(code, "AI", version) : LeekScript.compileSnippet(code, "AI", version); aiID = ai.getId(); // compile_time = ai.getCompileTime() / 1000000; From 9b4185f5001d900454b4ab2af9ef4004c7476d9a Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 152/319] [number] Change formatting for double numbers in LS1.1 --- .../java/leekscript/runner/values/DoubleLeekValue.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/runner/values/DoubleLeekValue.java b/src/main/java/leekscript/runner/values/DoubleLeekValue.java index 9fd7f063..08d58761 100644 --- a/src/main/java/leekscript/runner/values/DoubleLeekValue.java +++ b/src/main/java/leekscript/runner/values/DoubleLeekValue.java @@ -32,9 +32,12 @@ public boolean getBoolean() { @Override public String getString(AI ai) throws LeekRunException { ai.addOperations(3); - DecimalFormat df = new DecimalFormat(); - df.setMinimumFractionDigits(0); - return df.format(mValue); + if (ai.getVersion() <= 10) { + DecimalFormat df = new DecimalFormat(); + df.setMinimumFractionDigits(0); + return df.format(mValue); + } + return String.valueOf(mValue); } @Override From 3514ab4d8730e471e64fc655b63ec52d534180ea Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 153/319] [compiler] Fix **= operator --- src/main/java/leekscript/compiler/WordParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index e01e76bf..3bff2554 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -270,7 +270,7 @@ else if(word.equals("<<")){ word = "" + c; } } - else if(word.equals("*") || word.equals("/") || word.equals("%") || word.equals("=") || word.equals("!") || word.equals("<") || word.equals(">") || word.equals("^") || word.equals("==") || word.equals("!=")){ + else if(word.equals("*") || word.equals("**") || word.equals("/") || word.equals("%") || word.equals("=") || word.equals("!") || word.equals("<") || word.equals(">") || word.equals("^") || word.equals("==") || word.equals("!=")){ if(c == '=') word += c; else{ newWord(word, type); From 3aad34b10570369f135f1941c5af29f6d241dc13 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 154/319] [compiler] Fix end of script error --- src/main/java/leekscript/compiler/WordCompiler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index a48600b6..8bacb9f3 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -265,7 +265,7 @@ private void compileWord() throws LeekCompilerException { if (mCompiler.getWord().getType() != WordParser.T_END_INSTRUCTION) { exp = readExpression(); } - if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) + if (mCompiler.haveWords() && mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) mCompiler.skipWord(); mCurentBlock.addInstruction(this, new LeekReturnInstruction(mCurentBlock.countInstructions(), exp, mLine, mAI)); return; From 4c3e1ffac45bcdd53ad112d4b6e693d76b901435 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 155/319] [test] Fix tests --- src/test/java/test/TestGlobals.java | 3 +- src/test/java/test/TestLoops.java | 6 ++- src/test/java/test/TestNumber.java | 69 +++++++++++++++++++---------- 3 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/test/java/test/TestGlobals.java b/src/test/java/test/TestGlobals.java index 86ec6715..8029e477 100644 --- a/src/test/java/test/TestGlobals.java +++ b/src/test/java/test/TestGlobals.java @@ -22,7 +22,8 @@ public void run() throws Exception { code("global x = 12; x += 5; return x;").equals("17"); code("global x = 12; x -= 5; return x;").equals("7"); code("global x = 12; x *= 5; return x;").equals("60"); - code("global x = 12; x /= 5; return x;").equals("2.4"); + code_v10("global x = 12; x /= 5; return x;").equals("2,4"); + code_v11("global x = 12; x /= 5; return x;").equals("2.4"); code("global x = 12; x %= 5; return x;").equals("2"); code("global x = 2; x **= 5; return x;").equals("32"); code("global x = 12; x |= 5; return x;").equals("13"); diff --git a/src/test/java/test/TestLoops.java b/src/test/java/test/TestLoops.java index 2bc49e57..95807270 100644 --- a/src/test/java/test/TestLoops.java +++ b/src/test/java/test/TestLoops.java @@ -84,7 +84,8 @@ public void run() { // DISABLED_code("var i = 0 for (; i < 10; i++) { } return i;").equals("10"); code("var i = 0 for (i = 0; i < 10; i++) { } return i;").equals("10"); code("var i = 0 for (i = 0; i < 10; i++) { if (i == 5) { break } } return i;").equals("5"); - code("var i var c = 0 for (i = 0; i < 20; i += 0.573) { c++ } return i;").equals("20.05500000000001"); + code_v10("var i var c = 0 for (i = 0; i < 20; i += 0.573) { c++ } return i;").equals("20,055"); + code_v11("var i var c = 0 for (i = 0; i < 20; i += 0.573) { c++ } return i;").equals("20.05500000000001"); code("var i = 's' var c = 0 for (i = []; count(i) < 8; push(i, 1)) { c++ } return i;").equals("[1, 1, 1, 1, 1, 1, 1, 1]"); // DISABLED_code("var i = 0 for (; i < 10; i += 0.5) { } return i;").equals("10"); // code("var i = 0 for (i = 2l; i < 10; i += 0.5) { } return i;").equals("10"); @@ -132,7 +133,8 @@ public void run() { code("var a = 0 var x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] for (var i in x) { if (i < 5) { continue } a++ } return a;").equals("5"); code("var s = 0 for (var k : var v in [1, 2, 3, 4]) { s += k * v } return s;").equals("20"); // code("var s = '' for (var k : var v in ['a': 1, 'b': 2, 'c': 3, 'd': 4]) { s += v * k } return s;").equals("abbcccdddd"); - code("return (function (a) { var s = 0.0; for (var x in a) { s += x } return s; })([1, 2, 3, 4.25]);").equals("10.25"); + code_v10("return (function (a) { var s = 0.0; for (var x in a) { s += x } return s; })([1, 2, 3, 4.25]);").equals("10,25"); + code_v11("return (function (a) { var s = 0.0; for (var x in a) { s += x } return s; })([1, 2, 3, 4.25]);").equals("10.25"); // DISABLED_code("var y = '' for k, x in { var x = [] x.push(4) x } { y += k + ':' + x + ' ' } y").equals("'0:4 '"); // DISABLED_code("var y = '' for k, x in { var x = [1: 2] x.insert(3, 4) x } { y += k + ':' + x + ' ' } y").equals("'1:2 3:4 '"); // DISABLED_code("var y = '' for k, x in { var x = [1: 2.5] x.insert(3, 4) x } { y += k + ':' + x + ' ' } y").equals("'1:2.5 3:4 '"); diff --git a/src/test/java/test/TestNumber.java b/src/test/java/test/TestNumber.java index be1e260f..6c18955e 100644 --- a/src/test/java/test/TestNumber.java +++ b/src/test/java/test/TestNumber.java @@ -28,8 +28,10 @@ public void run() throws Exception { code("return 10 - 3;").equals("7"); code("return -2 + 3;").equals("1"); code("return 5 * 5;").equals("25"); - code("return 15 / 3;").equals("5.0"); - code("return 15 / 2;").equals("7.5"); + code_v10("return 15 / 3;").equals("5"); + code_v11("return 15 / 3;").equals("5.0"); + code_v10("return 15 / 2;").equals("7,5"); + code_v11("return 15 / 2;").equals("7.5"); code("return 12 ** 2;").equals("144"); code("return 2 ** 5;").equals("32"); code("return 2 < 5;").equals("true"); @@ -88,15 +90,18 @@ public void run() throws Exception { code("var a = 2 return a += 5;").equals("7"); code("var a = 2 return a -= 5;").equals("-3"); code("var a = 2 return a *= 5;").equals("10"); - code("var a = 100 return a /= 5;").equals("20.0"); + code_v10("var a = 100 return a /= 5;").equals("20"); + code_v11("var a = 100 return a /= 5;").equals("20.0"); code("var a = 56 return a %= 17;").equals("5"); code("var a = 15 return a **= 2;").equals("225"); - code("var a = 1.5 return a * 0.5;").equals("0.75"); + code_v10("var a = 1.5 return a * 0.5;").equals("0,75"); + code_v11("var a = 1.5 return a * 0.5;").equals("0.75"); // DISABLED_code("var i = 1m return i = i + 2m;").equals("3"); code("var a = 10; a += 10 - 2 * 3; return a;").equals("14"); section("multiple operations"); - code("return (33 - 2) / 2;").equals("15.5"); + code_v10("return (33 - 2) / 2;").equals("15,5"); + code_v11("return (33 - 2) / 2;").equals("15.5"); code("return 12 < (45 / 4);").equals("false"); code("return 12 == (24 / 2);").equals("true"); // code("2.5 + 4.7").almost(7.2); @@ -354,7 +359,8 @@ public void run() throws Exception { code("return 14 ** 3;").equals("2744"); code("return 14 ** null;").equals("1"); code("return null ** 2;").equals("0"); - code("return null ** null;").equals("0"); + code("return null ** null;").equals("1"); + code("return 0 ** 0;").equals("1"); // DISABLED_code("return 14 ** true;").equals("14"); // DISABLED_code("return 14 ** false;").equals("1"); // DISABLED_code("let a = 14 return a ** false;").equals("1"); @@ -426,17 +432,25 @@ public void run() throws Exception { code("null / 5").equals("null"); // code("12$ / false").exception(ls::vm::Exception::DIVISION_BY_ZERO); // code("let a = 13$; a / false").exception(ls::vm::Exception::DIVISION_BY_ZERO); - code("return 13 / true;").equals("13"); - code("return 14 / 2;").equals("7.0"); - code("var a = 18; return a / 3;").equals("6.0"); + code_v10("return 13 / true;").equals("13"); + code_v11("return 13 / true;").equals("13.0"); + code_v10("return 14 / 2;").equals("7"); + code_v11("return 14 / 2;").equals("7.0"); + code_v10("var a = 18; return a / 3;").equals("6"); + code_v11("var a = 18; return a / 3;").equals("6.0"); // code("14$ / []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); - code("var a = 17, b = 5 return a / b;").equals("3.4"); + code_v10("var a = 17, b = 5 return a / b;").equals("3,4"); + code_v11("var a = 17, b = 5 return a / b;").equals("3.4"); section("Number.operator /="); - code("var a = 12 a /= 3 return a;").equals("4.0"); - code("var a = 12 a /= 0.5 return a;").equals("24.0"); - code("var a = 12 a /= true return a;").equals("12"); - code("var a = null a /= 5 return a;").equals("0"); + code_v10("var a = 12 a /= 3 return a;").equals("4"); + code_v11("var a = 12 a /= 3 return a;").equals("4.0"); + code_v10("var a = 12 a /= 0.5 return a;").equals("24"); + code_v11("var a = 12 a /= 0.5 return a;").equals("24.0"); + code_v10("var a = 12 a /= true return a;").equals("12"); + code_v11("var a = 12 a /= true return a;").equals("12.0"); + code_v10("var a = null a /= 5 return a;").equals("0"); + code_v11("var a = null a /= 5 return a;").equals("0.0"); // code("var a = 12 a /= false return a;").equals("nan"); // code("var a = 12$ a /= []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); // code("var a = 12$ a /= [] a").exception(ls::vm::Exception::NO_SUCH_OPERATOR); @@ -626,10 +640,12 @@ public void run() throws Exception { section("Number.abs()"); // code("return abs;").equals(""); code("return abs(-12);").equals("12"); - code("return abs(-19.5);").equals("19.5"); + code_v10("return abs(-19.5);").equals("19,5"); + code_v11("return abs(-19.5);").equals("19.5"); code("return abs(12);").equals("12"); // code("return abs(-16436435l)").equals("16436435"); - code("return abs(-12.67);").almost(12.67); + code_v10("return abs(-12.67);").equals("12,67"); + code_v11("return abs(-12.67);").equals("12.67"); code("return abs(['a', -15][1]);").equals("15"); // code("return (-17).abs()").equals("17"); // code("return (-19.5).abs()").equals("19.5"); @@ -637,18 +653,25 @@ public void run() throws Exception { // code("abs([1, 'salut'][1])").exception(ls::vm::Exception::WRONG_ARGUMENT_TYPE); section("Number.exp()"); - code("return exp(0)").equals("1.0"); - code("return exp(1)").almost(Math.E); - code("return exp(4)").almost(54.598150033144236204); - code("return exp(4.89)").almost(132.953574051282743085); - code("return exp(-2.97)").almost(0.051303310331919108); - code("return exp(['a', 7.78][1])").almost(2392.274820537377763685); + code_v10("return exp(0)").equals("1"); + code_v11("return exp(0)").equals("1.0"); + code_v10("return exp(1)").equals("2,718"); + code_v11("return exp(1)").almost(Math.E); + code_v10("return exp(4)").equals("54,598"); + code_v11("return exp(4)").almost(54.598150033144236204); + code_v10("return exp(4.89)").equals("132,954"); + code_v11("return exp(4.89)").almost(132.953574051282743085); + code_v10("return exp(-2.97)").equals("0,051"); + code_v11("return exp(-2.97)").almost(0.051303310331919108); + code_v10("return exp(['a', 7.78][1])").equals("2 392,275"); + code_v11("return exp(['a', 7.78][1])").almost(2392.274820537377763685); // code("return 0.exp();").equals("1"); // code("return 1.exp();").almost(Math.E); // code("return 7.exp();").almost(1096.633158428458500566); // code("return (-7).exp();").almost(0.000911881965554516); // code("return (-3.33).exp();").almost(0.035793105067655297); - code("return E ** 5;").almost(148.413159102576571513); + code_v10("return E ** 5;").equals("148,413"); + code_v11("return E ** 5;").almost(148.413159102576571513); section("Number.floor()"); code("return floor(5.9);").equals("5"); From 51c8d05ec0bbe5d95b72c3da967ef51049c38c2e Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 156/319] [expression] Fix left value operators --- .../java/leekscript/compiler/expression/LeekExpression.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index c2b190a9..6b725510 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -743,7 +743,7 @@ public void analyze(WordCompiler compiler) { // Si on a affaire à une assignation, incrémentation ou autre du genre // on doit vérifier qu'on a bien une variable (l-value) - if (mOperator == Operators.ADDASSIGN || mOperator == Operators.MINUSASSIGN || mOperator == Operators.DIVIDEASSIGN || mOperator == Operators.ASSIGN || mOperator == Operators.MODULUSASSIGN || mOperator == Operators.MULTIPLIEASSIGN || mOperator == Operators.POWERASSIGN) { + if (mOperator == Operators.ADDASSIGN || mOperator == Operators.MINUSASSIGN || mOperator == Operators.DIVIDEASSIGN || mOperator == Operators.ASSIGN || mOperator == Operators.MODULUSASSIGN || mOperator == Operators.MULTIPLIEASSIGN || mOperator == Operators.POWERASSIGN || mOperator == Operators.BITOR_ASSIGN || mOperator == Operators.BITAND_ASSIGN || mOperator == Operators.BITXOR_ASSIGN || mOperator == Operators.SHIFT_LEFT_ASSIGN || mOperator == Operators.SHIFT_RIGHT_ASSIGN || mOperator == Operators.ROTATE_RIGHT_ASSIGN) { if (!mExpression1.isLeftValue()) compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, Error.CANT_ASSIGN_VALUE)); // throw new LeekExpressionException(mExpression1, LeekCompilerException.CANT_ASSIGN_VALUE); From 7f253bb64c78347e3af02cdff2896c419f54d83c Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 157/319] [operator] Add operators -=, **= and |= on null --- .../leekscript/runner/values/NullLeekValue.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/leekscript/runner/values/NullLeekValue.java b/src/main/java/leekscript/runner/values/NullLeekValue.java index 00449a1c..db806b9f 100644 --- a/src/main/java/leekscript/runner/values/NullLeekValue.java +++ b/src/main/java/leekscript/runner/values/NullLeekValue.java @@ -25,6 +25,11 @@ public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunExcepti return LeekOperations.add(ai, this, val); } + @Override + public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.minus(ai, this, val); + } + @Override public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { return LeekOperations.multiply(ai, this, val); @@ -40,6 +45,16 @@ public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunExc return LeekOperations.modulus(ai, this, val); } + @Override + public AbstractLeekValue power(AI ai, AbstractLeekValue value) throws LeekRunException { + return LeekOperations.power(ai, this, value); + } + + @Override + public AbstractLeekValue bor(AI ai, AbstractLeekValue value) throws LeekRunException { + return LeekOperations.bor(ai, this, value); + } + @Override public int getType() { return NULL; From aecb003c75738761d8512ea2441bfbd3fefbc2b0 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 158/319] [resolver] Use resources for fileSystem resolver --- .../leekscript/compiler/resolver/FileSystemResolver.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index 7828fa8b..80ebef82 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -3,7 +3,6 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -22,7 +21,8 @@ public AIFile resolve(String path, ResolverContext basecontex try { Path resolvedPath = context.getFolder().toPath().resolve(path).normalize(); - String code = new String(Files.readAllBytes(resolvedPath), StandardCharsets.UTF_8); + var is = getClass().getClassLoader().getResourceAsStream(resolvedPath.toString()); + String code = new String(is.readAllBytes(), StandardCharsets.UTF_8); Path parent = resolvedPath.getParent(); if (parent == null) parent = Paths.get("."); @@ -31,7 +31,7 @@ public AIFile resolve(String path, ResolverContext basecontex long timestamp = resolvedPath.toFile().lastModified(); - return new AIFile(path, code, timestamp, 11, newContext, resolvedPath.hashCode() & 0xfffffff); + return new AIFile(path, code, timestamp, 11, newContext, resolvedPath.toString().hashCode() & 0xfffffff); } catch (IOException e) { e.printStackTrace(); From 72856fa1f9b5cc625a2117d4f02532931820ad3d Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 159/319] [function] Fix abs() function in 1.1 --- src/main/java/leekscript/runner/LeekFunctions.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index a02409b8..1ff4238c 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -20,7 +20,14 @@ public enum LeekFunctions implements ILeekFunction { abs(1) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekDoubleValue(Math.abs(parameters[0].getDouble(leekIA))); + if (leekIA.getVersion() == 10) { + return LeekValueManager.getLeekDoubleValue(Math.abs(parameters[0].getDouble(leekIA))); + } + if (parameters[0] instanceof DoubleLeekValue) { + return LeekValueManager.getLeekDoubleValue(Math.abs(parameters[0].getDouble(leekIA))); + } else { + return LeekValueManager.getLeekIntValue(Math.abs(parameters[0].getInt(leekIA))); + } } @Override From 5ca6e441496dbb9b7d9fa89c4037199cc737cd20 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 160/319] [operator] Change / operator in 1.1 --- src/main/java/leekscript/runner/LeekOperations.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index 33299374..aa483969 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -124,10 +124,10 @@ public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeek if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { return LeekValueManager.getLeekDoubleValue(v1.getDouble(ai) / v2.getDouble(ai)); } else { - if (v1.getInt(ai) % v2.getInt(ai) != 0) - return new DoubleLeekValue(v1.getDouble(ai) / v2.getDouble(ai)); - else + if (ai.getVersion() == 10 && v1.getInt(ai) % v2.getInt(ai) == 0) return LeekValueManager.getLeekIntValue(v1.getInt(ai) / v2.getInt(ai)); + else + return new DoubleLeekValue(v1.getDouble(ai) / v2.getDouble(ai)); } } throw new LeekRunException(LeekRunException.INVALID_OPERATOR); From ed4307b29f406f84e1c6f4d1f146dcd3624d524e Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 161/319] [ai] Fix file version --- src/main/java/leekscript/compiler/AIFile.java | 3 +++ src/main/java/leekscript/compiler/LeekScript.java | 1 + 2 files changed, 4 insertions(+) diff --git a/src/main/java/leekscript/compiler/AIFile.java b/src/main/java/leekscript/compiler/AIFile.java index 838dce42..71a9e64b 100644 --- a/src/main/java/leekscript/compiler/AIFile.java +++ b/src/main/java/leekscript/compiler/AIFile.java @@ -55,4 +55,7 @@ public void setTimestamp(long timestamp) { public int getVersion() { return this.version; } + public void setVersion(int version) { + this.version = version; + } } diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 70b5ae34..b1de64f3 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -53,6 +53,7 @@ public static AI compileFile(String filepath, String AIClass, boolean nocache) t public static AI compileFile(String filepath, String AIClass, int version) throws LeekScriptException, LeekCompilerException, IOException { AIFile ai = getResolver().resolve(filepath, null); + ai.setVersion(version); return compile(ai, AIClass, true); } From 480e14b7cb73ffd68bb20813131010afc9c608e9 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 162/319] [array] Fix sort + getType in 1.0 --- src/main/java/leekscript/runner/PhpArray.java | 70 ++++++++++++++++++- .../runner/values/AbstractLeekValue.java | 25 +++++-- .../runner/values/ArrayLeekValue.java | 5 ++ .../runner/values/BooleanLeekValue.java | 5 ++ .../runner/values/ClassLeekValue.java | 5 ++ .../runner/values/DoubleLeekValue.java | 5 ++ .../runner/values/FunctionLeekValue.java | 7 +- .../runner/values/IntLeekValue.java | 5 ++ .../runner/values/NullLeekValue.java | 5 ++ .../runner/values/ObjectLeekValue.java | 5 ++ .../runner/values/ReferenceLeekValue.java | 5 ++ .../runner/values/StringLeekValue.java | 6 ++ .../runner/values/VariableLeekValue.java | 5 ++ src/test/java/test/TestArray.java | 9 ++- 14 files changed, 149 insertions(+), 13 deletions(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 7e079012..00b3a490 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -28,6 +28,65 @@ public class PhpArray implements Iterable { public final static int ASC_K = 6; public final static int DESC_K = 7; + private class ElementComparatorV10 implements Comparator { + + private final int mOrder; + private final AI ai; + + public final static int SORT_ASC = 1; + public final static int SORT_DESC = 2; + + public ElementComparatorV10(AI ai, int order) { + mOrder = order; + this.ai = ai; + } + + @Override + public int compare(Element v1, Element v2) { + try { + if (mOrder == SORT_ASC) + return compareAsc(v1.value.getValue(), v2.value.getValue()); + else if (mOrder == SORT_DESC) + return compareAsc(v2.value.getValue(), v1.value.getValue()); + } catch (Exception e) {} + return 0; + } + + public int compareAsc(AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { + if (v1.getV10Type() < v2.getV10Type()) + return -1; + else if (v1.getV10Type() > v2.getV10Type()) + return 1; + if (v1.getType() == AbstractLeekValue.BOOLEAN) { + if (v1.getBoolean() == v2.getBoolean()) + return 0; + else if (v1.getBoolean()) + return 1; + else + return -1; + } else if (v1.getType() == AbstractLeekValue.NUMBER) { + if (v1.getDouble(ai) == v2.getDouble(ai)) + return 0; + else if (v1.getDouble(ai) < v2.getDouble(ai)) + return -1; + else + return 1; + } else if (v1.getType() == AbstractLeekValue.STRING) { + return v1.getString(ai).compareTo(v2.getString(ai)); + } else if (v1.getType() == AbstractLeekValue.ARRAY) { + if (v1.getArray().size() == v2.getArray().size()) + return 0; + else if (v1.getArray().size() < v2.getArray().size()) + return -1; + else + return 1; + } else if (v1.getType() == AbstractLeekValue.NULL) + return 0; + else + return -1; + } + } + private class ElementComparator implements Comparator { private final int mOrder; @@ -399,10 +458,17 @@ else if (comparator == ASC_K || comparator == DESC_K) { Collections.sort(liste, new KeyComparator( (comparator == ASC_K) ? ElementComparator.SORT_ASC : ElementComparator.SORT_DESC)); - } else - Collections.sort(liste, new ElementComparator(ai, + } else { + if (ai.getVersion() == 10) { + Collections.sort(liste, new ElementComparatorV10(ai, (comparator == ASC || comparator == ASC_A) ? ElementComparator.SORT_ASC : ElementComparator.SORT_DESC)); + } else { + Collections.sort(liste, new ElementComparator(ai, + (comparator == ASC || comparator == ASC_A) ? ElementComparator.SORT_ASC + : ElementComparator.SORT_DESC)); + } + } // Mise en place de la liste mHead = liste.get(0); diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 01c2238e..9b7f1f08 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -11,14 +11,23 @@ public abstract class AbstractLeekValue { - public final static int NUMBER = 1; + public final static int NUMBER_V10 = 1; + public final static int BOOLEAN_V10 = 2; + public final static int ARRAY_V10 = 3; + public final static int NULL_V10 = 4; + public final static int STRING_V10 = 5; + public final static int FUNCTION_V10 = 6; + public final static int CLASS_V10 = 7; + public final static int OBJECT_V10 = 8; + + public final static int NULL = 1; public final static int BOOLEAN = 2; - public final static int ARRAY = 3; - public final static int NULL = 4; - public final static int STRING = 5; - public final static int FUNCTION = 6; - public final static int CLASS = 7; - public final static int OBJECT = 8; + public final static int NUMBER = 3; + public final static int STRING = 4; + public final static int ARRAY = 5; + public final static int OBJECT = 6; + public final static int FUNCTION = 7; + public final static int CLASS = 8; public final static int ADD_COST = 1; public final static int MUL_COST = 5; @@ -238,6 +247,8 @@ public AbstractLeekValue callSuperMethod(AI ai, String method, AbstractLeekValue public void callConstructor(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException {} + public abstract int getV10Type(); + public abstract int getType(); public boolean isReference() { diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index f7141437..0ed37dc4 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -215,6 +215,11 @@ public void push(AI ai, AbstractLeekValue m) throws LeekRunException { mValues.push(ai, m); } + @Override + public int getV10Type() { + return ARRAY_V10; + } + @Override public int getType() { return ARRAY; diff --git a/src/main/java/leekscript/runner/values/BooleanLeekValue.java b/src/main/java/leekscript/runner/values/BooleanLeekValue.java index e2667157..d353ef87 100644 --- a/src/main/java/leekscript/runner/values/BooleanLeekValue.java +++ b/src/main/java/leekscript/runner/values/BooleanLeekValue.java @@ -57,6 +57,11 @@ public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunExc return LeekOperations.modulus(ai, this, val); } + @Override + public int getV10Type() { + return BOOLEAN_V10; + } + @Override public int getType() { return BOOLEAN; diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 655120c5..e57c4869 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -225,6 +225,11 @@ public String getString(AI ai) { return ""; } + @Override + public int getV10Type() { + return CLASS_V10; + } + @Override public int getType() { return CLASS; diff --git a/src/main/java/leekscript/runner/values/DoubleLeekValue.java b/src/main/java/leekscript/runner/values/DoubleLeekValue.java index 08d58761..639c8934 100644 --- a/src/main/java/leekscript/runner/values/DoubleLeekValue.java +++ b/src/main/java/leekscript/runner/values/DoubleLeekValue.java @@ -169,6 +169,11 @@ public AbstractLeekValue brotate(AI ai, AbstractLeekValue value) throws LeekRunE return LeekValueManager.getLeekIntValue(getInt(ai) >>> value.getInt(ai)); } + @Override + public int getV10Type() { + return NUMBER_V10; + } + @Override public int getType() { return NUMBER; diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index 921b38f3..52a7673f 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -65,9 +65,14 @@ public boolean equals(AI ai, AbstractLeekValue comp) { } } + @Override + public int getV10Type() { + return FUNCTION_V10; + } + @Override public int getType() { - return AbstractLeekValue.FUNCTION; + return FUNCTION; } private AbstractLeekValue[] copyValues(AI uai, AbstractLeekValue[] values, boolean[] references) throws LeekRunException { diff --git a/src/main/java/leekscript/runner/values/IntLeekValue.java b/src/main/java/leekscript/runner/values/IntLeekValue.java index 52648bfe..8a5a687f 100644 --- a/src/main/java/leekscript/runner/values/IntLeekValue.java +++ b/src/main/java/leekscript/runner/values/IntLeekValue.java @@ -170,6 +170,11 @@ public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunExc return LeekValueManager.getLeekIntValue(ai, mValue % val.getInt(ai), this); } + @Override + public int getV10Type() { + return NUMBER_V10; + } + @Override public int getType() { return NUMBER; diff --git a/src/main/java/leekscript/runner/values/NullLeekValue.java b/src/main/java/leekscript/runner/values/NullLeekValue.java index db806b9f..b9ab2c19 100644 --- a/src/main/java/leekscript/runner/values/NullLeekValue.java +++ b/src/main/java/leekscript/runner/values/NullLeekValue.java @@ -55,6 +55,11 @@ public AbstractLeekValue bor(AI ai, AbstractLeekValue value) throws LeekRunExcep return LeekOperations.bor(ai, this, value); } + @Override + public int getV10Type() { + return NULL_V10; + } + @Override public int getType() { return NULL; diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index b4b8b9bf..be18fc22 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -159,6 +159,11 @@ public String getString(AI ai, Set visited) throws LeekRunException { return sb.toString(); } + @Override + public int getV10Type() { + return OBJECT_V10; + } + @Override public int getType() { return OBJECT; diff --git a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java b/src/main/java/leekscript/runner/values/ReferenceLeekValue.java index bd0aa993..045565d6 100644 --- a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java +++ b/src/main/java/leekscript/runner/values/ReferenceLeekValue.java @@ -177,6 +177,11 @@ public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunExc return mValue = mValue.modulus(ai, val); } + @Override + public int getV10Type() { + return mValue.getV10Type(); + } + @Override public int getType() { return mValue.getType(); diff --git a/src/main/java/leekscript/runner/values/StringLeekValue.java b/src/main/java/leekscript/runner/values/StringLeekValue.java index 69ee0f0c..f4de2183 100644 --- a/src/main/java/leekscript/runner/values/StringLeekValue.java +++ b/src/main/java/leekscript/runner/values/StringLeekValue.java @@ -66,6 +66,12 @@ public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunExcepti return this; } + @Override + public int getV10Type() { + return STRING_V10; + } + + @Override public int getType() { return STRING; diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index f399a375..259a5664 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -254,6 +254,11 @@ public void callConstructor(AI ai, AbstractLeekValue thiz, AbstractLeekValue... mValue.callConstructor(ai, thiz, arguments); } + @Override + public int getV10Type() { + return mValue.getV10Type(); + } + @Override public int getType() { return mValue.getType(); diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index cae77a7f..a653ae2f 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -192,9 +192,12 @@ public void run() throws Exception { code("return arrayFlatten([6,[[7]],[8,9]]);").equals("[6, [7], 8, 9]"); section("Array.sort"); - code("return function() { var t = [null, null, 4, 8, 9]; sort(t); return t; }();").equals("[null, null, 4, 8, 9]"); - code("return function() { var t = [4, null, 4, null, 4]; sort(t); return t; }();").equals("[null, null, 4, 4, 4]"); - code("return function() { var t = [4, null, 5, null, 8]; sort(t, SORT_DESC); return t; }();").equals("[8, 5, 4, null, null]"); + code_v10("return function() { var t = [null, null, 4, 8, 9]; sort(t); return t; }();").equals("[4, 8, 9, null, null]"); + code_v11("return function() { var t = [null, null, 4, 8, 9]; sort(t); return t; }();").equals("[null, null, 4, 8, 9]"); + code_v10("return function() { var t = [4, null, 4, null, 4]; sort(t); return t; }();").equals("[4, 4, 4, null, null]"); + code_v11("return function() { var t = [4, null, 4, null, 4]; sort(t); return t; }();").equals("[null, null, 4, 4, 4]"); + code_v10("return function() { var t = [4, null, 5, null, 8]; sort(t, SORT_DESC); return t; }();").equals("[null, null, 8, 5, 4]"); + code_v11("return function() { var t = [4, null, 5, null, 8]; sort(t, SORT_DESC); return t; }();").equals("[8, 5, 4, null, null]"); section("Array and references"); code_v10("var t = [@3, @4, @5]; return t;").equals("[3, 4, 5]"); From 9a23371ae4bcc0c8d9c501055c75ddc4daf1dce3 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 163/319] [test] Fix tests --- src/test/java/test/TestArray.java | 18 +- src/test/java/test/TestNumber.java | 236 +++++++++++++++++--------- src/test/java/test/TestReference.java | 2 +- 3 files changed, 170 insertions(+), 86 deletions(-) diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index a653ae2f..3a7357f0 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -318,14 +318,20 @@ public void run() throws Exception { code("return arrayMax([0:7,8:9,'a':2])").equals("9"); section("Array.sum()"); - code("return sum([1,5,7])").equals("13.0"); - code("return sum([0:1,'a':5,'test':7])").equals("13.0"); - code("return sum([])").equals("0.0"); + code_v10("return sum([1,5,7])").equals("13"); + code_v11("return sum([1,5,7])").equals("13.0"); + code_v10("return sum([0:1,'a':5,'test':7])").equals("13"); + code_v11("return sum([0:1,'a':5,'test':7])").equals("13.0"); + code_v10("return sum([])").equals("0"); + code_v11("return sum([])").equals("0.0"); section("Array.average()"); - code("return average([2,4,6])").equals("4.0"); - code("return average([0:2,'a':4,'test':6])").equals("4.0"); - code("return average([])").equals("0.0"); + code_v10("return average([2, 4, 6])").equals("4"); + code_v11("return average([2, 4, 6])").equals("4.0"); + code_v10("return average([0: 2, 'a': 4, 'test': 6])").equals("4"); + code_v11("return average([0: 2, 'a': 4, 'test': 6])").equals("4.0"); + code_v10("return average([])").equals("0"); + code_v11("return average([])").equals("0.0"); section("Array.fill()"); code("var a = [1,2,3]; fill(a, 'a'); return a").equals("[a, a, a]"); diff --git a/src/test/java/test/TestNumber.java b/src/test/java/test/TestNumber.java index 6c18955e..fbeb5b3c 100644 --- a/src/test/java/test/TestNumber.java +++ b/src/test/java/test/TestNumber.java @@ -663,7 +663,7 @@ public void run() throws Exception { code_v11("return exp(4.89)").almost(132.953574051282743085); code_v10("return exp(-2.97)").equals("0,051"); code_v11("return exp(-2.97)").almost(0.051303310331919108); - code_v10("return exp(['a', 7.78][1])").equals("2 392,275"); + code_v10("return exp(['a', 7.78][1])").equals("2 392,275"); code_v11("return exp(['a', 7.78][1])").almost(2392.274820537377763685); // code("return 0.exp();").equals("1"); // code("return 1.exp();").almost(Math.E); @@ -701,18 +701,25 @@ public void run() throws Exception { code("return max(8, 5)").equals("8"); code("return max(8, 88)").equals("88"); code("return max(5, 12);").equals("12"); - code("return max(5.0, 12);").equals("12.0"); - code("return max(75.7, 12);").almost(75.7); - code("return max(5, 12.451);").almost(12.451); + code_v10("return max(5.0, 12);").equals("12"); + code_v11("return max(5.0, 12);").equals("12.0"); + code_v10("return max(75.7, 12);").equals("75,7"); + code_v11("return max(75.7, 12);").almost(75.7); + code_v10("return max(5, 12.451);").equals("12,451"); + code_v11("return max(5, 12.451);").almost(12.451); code("return max([5, 'a'][0], 4);").equals("5"); code("return max([5, 'a'][0], 76);").equals("76"); code("return max(4, [5, 'a'][0]);").equals("5"); code("return max(77, [5, 'a'][0]);").equals("77"); code("return max([55, 'a'][0], [5, 'a'][0]);").equals("55"); - code("return max(5, 12.8);").equals("12.8"); - code("return max(15.7, 12.8);").equals("15.7"); - code("return max([15.7, ''][0], 12.8);").equals("15.7"); - code("return max(5.5, [12.8, ''][0]);").equals("12.8"); + code_v10("return max(5, 12.8);").equals("12,8"); + code_v11("return max(5, 12.8);").equals("12.8"); + code_v10("return max(15.7, 12.8);").equals("15,7"); + code_v11("return max(15.7, 12.8);").equals("15.7"); + code_v10("return max([15.7, ''][0], 12.8);").equals("15,7"); + code_v11("return max([15.7, ''][0], 12.8);").equals("15.7"); + code_v10("return max(5.5, [12.8, ''][0]);").equals("12,8"); + code_v11("return max(5.5, [12.8, ''][0]);").equals("12.8"); // code("return 2.max([7.5, ''][0]);").equals("7.5"); // code("return [2, ''][0].max([7.5, ''][0]);").equals("7.5"); // code("2.max([7.5, ''][1])").exception(ls::vm::Exception::WRONG_ARGUMENT_TYPE); @@ -725,86 +732,134 @@ public void run() throws Exception { code("return min(8, 5)").equals("5"); code("return min(8, 88)").equals("8"); code("return min(5, 12)").equals("5"); - code("return min(75.7, 12)").almost(12.0); - code("return min(5, 12.451)").almost(5.0); + code_v10("return min(75.7, 12)").equals("12"); + code_v11("return min(75.7, 12)").almost(12.0); + code_v10("return min(5, 12.451)").equals("5"); + code_v11("return min(5, 12.451)").almost(5.0); code("return min([5, 'a'][0], 4)").equals("4"); code("return min([5, 'a'][0], 76)").equals("5"); code("return min(4, [5, 'a'][0])").equals("4"); code("return min(77, [5, 'a'][0])").equals("5"); code("return min([55, 'a'][0], [5, 'a'][0])").equals("5"); - code("return min(5, 12.8)").equals("5.0"); - code("return min(15.7, 12.8)").equals("12.8"); - code("return min([15.7, ''][0], 12.8)").equals("12.8"); - code("return min(5.5, [12.8, ''][0])").equals("5.5"); + code_v10("return min(5, 12.8)").equals("5"); + code_v11("return min(5, 12.8)").equals("5.0"); + code_v10("return min(15.7, 12.8)").equals("12,8"); + code_v11("return min(15.7, 12.8)").equals("12.8"); + code_v10("return min([15.7, ''][0], 12.8)").equals("12,8"); + code_v11("return min([15.7, ''][0], 12.8)").equals("12.8"); + code_v10("return min(5.5, [12.8, ''][0])").equals("5,5"); + code_v11("return min(5.5, [12.8, ''][0])").equals("5.5"); // code("return min(5l, 10.5);").equals("5"); // code("return min(5l, 10);").equals("5"); // code("return min(true, 10l);").equals("1"); // code("min('string', 12)").error(ls::Error::METHOD_NOT_FOUND, {"min(" + env.tmp_string->to_string() + ", " + env.integer->to_string() + ")"}); section("Number.cos()"); - code("return cos(0)").equals("1.0"); - code("return cos(2.5)").almost(Math.cos(2.5)); - code("return cos(PI)").equals("-1.0"); - code("return cos(PI / 2)").almost(0.0); + code_v10("return cos(0)").equals("1"); + code_v11("return cos(0)").equals("1.0"); + code_v10("return cos(2.5)").equals("-0,801"); + code_v11("return cos(2.5)").almost(Math.cos(2.5)); + code_v10("return cos(PI)").equals("-1"); + code_v11("return cos(PI)").equals("-1.0"); + code_v10("return cos(PI / 2)").equals("0"); + code_v11("return cos(PI / 2)").almost(0.0); // code("return π.cos()").equals("-1"); // code("return ['', π][1].cos()").equals("-1"); - code("return cos(['', PI][1]);").equals("-1.0"); - code("return cos(PI);").equals("-1.0"); + code_v10("return cos(['', PI][1]);").equals("-1"); + code_v11("return cos(['', PI][1]);").equals("-1.0"); + code_v10("return cos(PI);").equals("-1"); + code_v11("return cos(PI);").equals("-1.0"); section("Number.acos()"); - code("return acos(1)").equals("0.0"); - code("return acos(-1)").almost(Math.PI); - code("return acos(0)").almost(Math.PI / 2); + code_v10("return acos(1)").equals("0"); + code_v11("return acos(1)").equals("0.0"); + code_v10("return acos(-1)").equals("3,142"); + code_v11("return acos(-1)").almost(Math.PI); + code_v10("return acos(0)").equals("1,571"); + code_v11("return acos(0)").almost(Math.PI / 2); // code("return (-0.33).acos()").almost(1.907099901948877019); - code("return acos(['y', 0][1])").almost(Math.PI / 2); + code_v10("return acos(['y', 0][1])").equals("1,571"); + code_v11("return acos(['y', 0][1])").almost(Math.PI / 2); section("Number.sin()"); - code("return sin(0)").equals("0.0"); - code("return sin(2.5)").almost(Math.sin(2.5)); - code("return sin(PI)").almost(0.0); - code("return sin(PI / 2)").equals("1.0"); - code("return sin(- PI / 2)").equals("-1.0"); - code("return sin(['', PI / 2][1])").equals("1.0"); - code("return sin(PI / 2)").equals("1.0"); + code_v10("return sin(0)").equals("0"); + code_v11("return sin(0)").equals("0.0"); + code_v10("return sin(2.5)").equals("0,598"); + code_v11("return sin(2.5)").almost(Math.sin(2.5)); + code_v10("return sin(PI)").equals("0"); + code_v11("return sin(PI)").almost(0.0); + code_v10("return sin(PI / 2)").equals("1"); + code_v11("return sin(PI / 2)").equals("1.0"); + code_v10("return sin(- PI / 2)").equals("-1"); + code_v11("return sin(- PI / 2)").equals("-1.0"); + code_v10("return sin(['', PI / 2][1])").equals("1"); + code_v11("return sin(['', PI / 2][1])").equals("1.0"); + code_v10("return sin(PI / 2)").equals("1"); + code_v11("return sin(PI / 2)").equals("1.0"); section("Number.tan()"); - code("return tan(0)").equals("0.0"); - code("return tan(2.5)").almost(Math.tan(2.5)); - code("return tan(PI)").almost(0.0); - code("return tan(PI / 4)").almost(1.0); - code("return tan(- PI / 4)").almost(-1.0); - code("return tan(['', PI / 4][1])").almost(1.0); + code_v10("return tan(0)").equals("0"); + code_v11("return tan(0)").equals("0.0"); + code_v10("return tan(2.5)").equals("-0,747"); + code_v11("return tan(2.5)").almost(Math.tan(2.5)); + code_v10("return tan(PI)").equals("-0"); + code_v11("return tan(PI)").almost(0.0); + code_v10("return tan(PI / 4)").equals("1"); + code_v11("return tan(PI / 4)").almost(1.0); + code_v10("return tan(- PI / 4)").equals("-1"); + code_v11("return tan(- PI / 4)").almost(-1.0); + code_v10("return tan(['', PI / 4][1])").equals("1"); + code_v11("return tan(['', PI / 4][1])").almost(1.0); section("Number.asin()"); - code("return asin(0)").equals("0.0"); - code("return asin(-1)").almost(-Math.PI / 2); - code("return asin(1)").almost(Math.PI / 2); + code_v10("return asin(0)").equals("0"); + code_v11("return asin(0)").equals("0.0"); + code_v10("return asin(-1)").equals("-1,571"); + code_v11("return asin(-1)").almost(-Math.PI / 2); + code_v10("return asin(1)").equals("1,571"); + code_v11("return asin(1)").almost(Math.PI / 2); // code("return 0.33.asin()").almost(0.33630357515398035); - code("return asin(['y', -1][1])").almost(-Math.PI / 2); + code_v10("return asin(['y', -1][1])").equals("-1,571"); + code_v11("return asin(['y', -1][1])").almost(-Math.PI / 2); section("Number.atan()"); - code("return atan(1)").almost(Math.PI / 4); - code("return atan(-1)").almost(-Math.PI / 4); - code("return atan(0.5)").almost(0.463647609000806094); + code_v10("return atan(1)").equals("0,785"); + code_v11("return atan(1)").almost(Math.PI / 4); + code_v10("return atan(-1)").equals("-0,785"); + code_v11("return atan(-1)").almost(-Math.PI / 4); + code_v10("return atan(0.5)").equals("0,464"); + code_v11("return atan(0.5)").almost(0.463647609000806094); // code("return 0.atan()").equals("0"); - code("return atan(['y', 0.5][1])").almost(0.463647609000806094); + code_v10("return atan(['y', 0.5][1])").equals("0,464"); + code_v11("return atan(['y', 0.5][1])").almost(0.463647609000806094); section("Number.atan2()"); - code("return atan2(1, 1)").almost(Math.PI / 4); - code("return atan2(150.78, 150.78)").almost(Math.PI / 4); - code("return atan2(1, 0)").almost(Math.PI / 2); - code("return atan2(-1, 0)").almost(-Math.PI / 2); - code("return atan2(0, 1)").equals("0.0"); - code("return atan2(0, -1)").almost(Math.PI); - code("return atan2(12.12, 42.42)").almost(0.278299659005111333); + code_v10("return atan2(1, 1)").equals("0,785"); + code_v11("return atan2(1, 1)").almost(Math.PI / 4); + code_v10("return atan2(150.78, 150.78)").equals("0,785"); + code_v11("return atan2(150.78, 150.78)").almost(Math.PI / 4); + code_v10("return atan2(1, 0)").equals("1,571"); + code_v11("return atan2(1, 0)").almost(Math.PI / 2); + code_v10("return atan2(-1, 0)").equals("-1,571"); + code_v11("return atan2(-1, 0)").almost(-Math.PI / 2); + code_v10("return atan2(0, 1)").equals("0"); + code_v11("return atan2(0, 1)").equals("0.0"); + code_v10("return atan2(0, -1)").equals("3,142"); + code_v11("return atan2(0, -1)").almost(Math.PI); + code_v10("return atan2(12.12, 42.42)").equals("0,278"); + code_v11("return atan2(12.12, 42.42)").almost(0.278299659005111333); // code("return 1.atan2(1)").almost(Math.PI / 4); // code("return ['', -1][1].atan2(1)").almost(-Math.PI / 4); // code("return 1.atan2(['', -1][1])").almost(3 * Math.PI / 4); // code("return ['', -1][1].atan2(['', -1][1])").almost(-3 * Math.PI / 4); - code("return atan2(1, 1)").almost(Math.PI / 4); - code("return atan2(['', -1][1], 1)").almost(-Math.PI / 4); - code("return atan2(1, ['', -1][1])").almost(3 * Math.PI / 4); - code("return atan2(['', -1][1], ['', -1][1])").almost(-3 * Math.PI / 4); + code_v10("return atan2(1, 1)").equals("0,785"); + code_v11("return atan2(1, 1)").almost(Math.PI / 4); + code_v10("return atan2(['', -1][1], 1)").equals("-0,785"); + code_v11("return atan2(['', -1][1], 1)").almost(-Math.PI / 4); + code_v10("return atan2(1, ['', -1][1])").equals("2,356"); + code_v11("return atan2(1, ['', -1][1])").almost(3 * Math.PI / 4); + code_v10("return atan2(['', -1][1], ['', -1][1])").equals("-2,356"); + code_v11("return atan2(['', -1][1], ['', -1][1])").almost(-3 * Math.PI / 4); // code("return atan2(1, true)").almost(Math.PI / 4); // code("return atan2(true, false)").almost(Math.PI / 2); @@ -840,10 +895,13 @@ public void run() throws Exception { // code("1234567.fold((x, y) -> x + y ** 2, 0)").equals("140"); section("Number.hypot"); - code("return hypot(3, 4)").equals("5.0"); + code_v10("return hypot(3, 4)").equals("5"); + code_v11("return hypot(3, 4)").equals("5.0"); // code("return 3.hypot(4)").equals("5"); - code("return hypot(34, 74)").almost(81.437092286); - code("return hypot([34, ''][0], 74)").almost(81.437092286); + code_v10("return hypot(34, 74)").equals("81,437"); + code_v11("return hypot(34, 74)").almost(81.437092286); + code_v10("return hypot([34, ''][0], 74)").equals("81,437"); + code_v11("return hypot([34, ''][0], 74)").almost(81.437092286); section("Number.signum"); // code("0.signum()").equals("0"); @@ -859,54 +917,74 @@ public void run() throws Exception { code("return signum(85)").equals("1"); section("Number.sqrt"); - code("return sqrt(2)").almost(Math.sqrt(2)); + code_v10("return sqrt(2)").equals("1,414"); + code_v11("return sqrt(2)").almost(Math.sqrt(2)); // code("return sqrt(123456789123456789123456789)").equals("11111111066111"); // code("return sqrt(55m ** 20m)").equals("253295162119140625"); // code("return sqrt(12m + 5m)").equals("4"); // code("return var n = 12; n.sqrt()").equals("3.4641016151"); // code("return let f = sqrt f(5)").equals("2.2360679775"); - code("return sqrt(16)").equals("4.0"); - code("return sqrt(25)").equals("5.0"); + code_v10("return sqrt(16)").equals("4"); + code_v11("return sqrt(16)").equals("4.0"); + code_v10("return sqrt(25)").equals("5"); + code_v11("return sqrt(25)").equals("5.0"); section("Number.toDegrees"); // code("return π.toDegrees()").equals("180"); // code("return (π / 2).toDegrees()").equals("90"); // code("return (-π / 2).toDegrees()").equals("-90"); // code("return 0.toDegrees()").equals("0"); - code("return toDegrees(PI)").equals("180.0"); - code("return toDegrees(PI / 2)").equals("90.0"); - code("return toDegrees(-PI / 2)").equals("-90.0"); - code("return toDegrees(0)").equals("0.0"); + code_v10("return toDegrees(PI)").equals("180"); + code_v11("return toDegrees(PI)").equals("180.0"); + code_v10("return toDegrees(PI / 2)").equals("90"); + code_v11("return toDegrees(PI / 2)").equals("90.0"); + code_v10("return toDegrees(-PI / 2)").equals("-90"); + code_v11("return toDegrees(-PI / 2)").equals("-90.0"); + code_v10("return toDegrees(0)").equals("0"); + code_v11("return toDegrees(0)").equals("0.0"); section("Number.toRadians"); // code("return 180.toRadians()").almost(Math.PI); // code("return 90.toRadians()").almost(Math.PI / 2); // code("return (-90).toRadians()").almost(-Math.PI / 2); // code("return 0.toRadians()").equals("0"); - code("return toRadians(180)").almost(Math.PI); - code("return toRadians(90)").almost(Math.PI / 2); - code("return toRadians(-90)").almost(-Math.PI / 2); - code("return toRadians(0)").equals("0.0"); + code_v10("return toRadians(180)").equals("3,142"); + code_v11("return toRadians(180)").almost(Math.PI); + code_v10("return toRadians(90)").equals("1,571"); + code_v11("return toRadians(90)").almost(Math.PI / 2); + code_v10("return toRadians(-90)").equals("-1,571"); + code_v11("return toRadians(-90)").almost(-Math.PI / 2); + code_v10("return toRadians(0)").equals("0"); + code_v11("return toRadians(0)").equals("0.0"); section("Number.log"); // code("1.log()").equals("0"); - code("return log(1)").equals("0.0"); - code("return log(E)").equals("1.0"); + code_v10("return log(1)").equals("0"); + code_v11("return log(1)").equals("0.0"); + code_v10("return log(E)").equals("1"); + code_v11("return log(E)").equals("1.0"); // code("123456.log()").equals("11.7236400963"); - code("return log(654321)").almost(13.3913533357); - code("return log([55555, ''][0])").almost(10.9251288); + code_v10("return log(654321)").equals("13,391"); + code_v11("return log(654321)").almost(13.3913533357); + code_v10("return log([55555, ''][0])").equals("10,925"); + code_v11("return log([55555, ''][0])").almost(10.9251288); section("Number.log10"); - code("return log10(10)").equals("1.0"); + code_v10("return log10(10)").equals("1"); + code_v11("return log10(10)").equals("1.0"); // code("return 1.log10()").equals("0"); // code("return 123456.log10()").equals("5.0915122016"); - code("return log10(654321)").almost(5.8157908589); - code("return log10([55555, ''][0])").almost(4.7447231519); + code_v10("return log10(654321)").equals("5,816"); + code_v11("return log10(654321)").almost(5.8157908589); + code_v10("return log10([55555, ''][0])").equals("4,745"); + code_v11("return log10([55555, ''][0])").almost(4.7447231519); section("Number.pow"); // code("2.pow(10)").equals("1024"); - code("return pow(5, 3)").equals("125.0"); - code("return pow(2, 10)").equals("1024.0"); + code_v10("return pow(5, 3)").equals("125"); + code_v11("return pow(5, 3)").equals("125.0"); + code_v10("return pow(2, 10)").equals("1 024"); + code_v11("return pow(2, 10)").equals("1024.0"); // code("pow([10, ''][0], 5)").equals("100000"); // code("3000.pow(3)").equals("2147483648"); // code("return pow(3000, 3)").equals("2147483648"); diff --git a/src/test/java/test/TestReference.java b/src/test/java/test/TestReference.java index 13291c3c..d8da7de4 100644 --- a/src/test/java/test/TestReference.java +++ b/src/test/java/test/TestReference.java @@ -13,7 +13,7 @@ public void run() throws Exception { code_v10("var t = 0; var f = function(a) { t = @a }; var b = []; f(b); push(t, 5); return b;").equals("[]"); code_v10("var t = 0; var f = function(@a) { t = @a }; var b = []; f(b); push(t, 5); return b;").equals("[5]"); code_v10("var t = 0; var f = function(a) { t; }; f(t); return 'ok';").equals("ok"); - code_v10("function ref() { var a = 2; return @a; } return 1 / ref();").equals("0.5"); + code_v10("function ref() { var a = 2; return @a; } return 1 / ref();").equals("0,5"); code_v10("var a = @[1, 2, 3]; var b = @a; return (@(b));").equals("[1, 2, 3]"); code_v10("var count = count([1, 2, 3]) return count").equals("3"); code_v10("var a = 12; var b = @a; a++; return [a, b]").equals("[13, 12]"); From ae361de0f16ddc275d0b3ca185daf307562fe5e0 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 164/319] [function] Improve min, max, sqrt, sum, average functions in 1.1 --- .../java/leekscript/runner/LeekFunctions.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 1ff4238c..a74d52e9 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -38,7 +38,10 @@ public int[] parameters() { min(2) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekDoubleValue(Math.min(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); + if (parameters[0] instanceof DoubleLeekValue || parameters[1] instanceof DoubleLeekValue) { + return LeekValueManager.getLeekDoubleValue(Math.min(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); + } + return LeekValueManager.getLeekIntValue(Math.min(parameters[0].getInt(leekIA), parameters[1].getInt(leekIA))); } @Override @@ -49,7 +52,10 @@ public int[] parameters() { max(2) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekDoubleValue(Math.max(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); + if (parameters[0] instanceof DoubleLeekValue || parameters[1] instanceof DoubleLeekValue) { + return LeekValueManager.getLeekDoubleValue(Math.max(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); + } + return LeekValueManager.getLeekIntValue(Math.max(parameters[0].getInt(leekIA), parameters[1].getInt(leekIA))); } @Override @@ -192,7 +198,7 @@ public int[] parameters() { sqrt(1) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekDoubleValue(Math.sqrt(parameters[0].getDouble(leekIA))); + return new DoubleLeekValue(Math.sqrt(parameters[0].getDouble(leekIA))); } @Override @@ -916,6 +922,9 @@ public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue p sum(1) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { + if (parameters[0].getArray().size() == 0) { + return new DoubleLeekValue(0.0); + } double somme = 0; for (AbstractLeekValue val : parameters[0].getArray()) { somme += val.getDouble(leekIA); @@ -936,11 +945,14 @@ public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue p average(1) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { + if (parameters[0].getArray().size() == 0) { + return new DoubleLeekValue(0.0); + } double average = 0; for (AbstractLeekValue val : parameters[0].getArray()) { average += val.getDouble(leekIA); } - if (average == 0) + if (average == 0 && leekIA.getVersion() == 10) return LeekValueManager.getLeekIntValue(0); return LeekValueManager.getLeekDoubleValue(average / parameters[0].getArray().size()); } From 824ff50380fb0866a5b6bc50b817e5aec55ada83 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 165/319] [number] Don't use integer if number contains a dot --- src/main/java/leekscript/compiler/WordCompiler.java | 7 ++++--- .../leekscript/compiler/expression/LeekNumber.java | 11 ++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 8bacb9f3..4214d63b 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -933,9 +933,10 @@ public AbstractExpression readExpression() throws LeekCompilerException { } else break; } else { - if (word.getType() == WordParser.T_NUMBER) - retour.addExpression(new LeekNumber(Double.parseDouble(word.getWord()))); - else if (word.getType() == WordParser.T_VAR_STRING) { + if (word.getType() == WordParser.T_NUMBER) { + boolean floating = word.getWord().contains("."); + retour.addExpression(new LeekNumber(Double.parseDouble(word.getWord()), floating)); + } else if (word.getType() == WordParser.T_VAR_STRING) { retour.addExpression(new LeekString(word.getWord())); } else if (word.getType() == WordParser.T_BRACKET_LEFT) { // Déclaration d'un tableau diff --git a/src/main/java/leekscript/compiler/expression/LeekNumber.java b/src/main/java/leekscript/compiler/expression/LeekNumber.java index 29f09e38..95a5b73a 100644 --- a/src/main/java/leekscript/compiler/expression/LeekNumber.java +++ b/src/main/java/leekscript/compiler/expression/LeekNumber.java @@ -7,9 +7,11 @@ public class LeekNumber extends AbstractExpression { private final double mValue; + private final boolean floating; - public LeekNumber(double value) { + public LeekNumber(double value, boolean floating) { mValue = value; + this.floating = floating; } @Override @@ -30,11 +32,10 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if(mValue == (int) mValue){ - writer.addCode("LeekValueManager.getLeekIntValue(" + ((int) mValue) + ")"); - } - else{ + if (floating || mValue != (int) mValue) { writer.addCode("new DoubleLeekValue(" + mValue + ")"); + } else { + writer.addCode("LeekValueManager.getLeekIntValue(" + ((int) mValue) + ")"); } } From b4d79de139964211f6b2c9a91240e2ba4c7aa6fa Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 166/319] [parser] Fix comments --- src/main/java/leekscript/compiler/WordParser.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index 3bff2554..4f586556 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -125,13 +125,15 @@ else if(type == T_VAR_STRING && opener == c){ i++; continue; } - if(comment_line || comment_block) continue; - if(c == '/' && length > i + 1 && code.charAt(i + 1) == '/'){ + if (comment_line || comment_block) continue; + if (c == '/' && length > i + 1 && code.charAt(i + 1) == '/') { comment_line = true; + i++; continue; } - else if(c == '/' && length > i + 1 && code.charAt(i + 1) == '*'){ + else if (c == '/' && length > i + 1 && code.charAt(i + 1) == '*') { comment_block = true; + i++; continue; } if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_'){ From b94666d0c30a8f41361f4c6c7252ccc27e1da28e Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 167/319] [test] Remove old tests --- src/test/java/test/TestAdvancedFunctions.java | 379 ------------ src/test/java/test/TestFunctions.java | 575 ------------------ src/test/java/test/TestGeneral | 278 --------- src/test/java/test/TestWithFile | 65 -- src/test/java/test/TestWithFile.java | 65 -- 5 files changed, 1362 deletions(-) delete mode 100644 src/test/java/test/TestAdvancedFunctions.java delete mode 100644 src/test/java/test/TestFunctions.java delete mode 100644 src/test/java/test/TestGeneral delete mode 100644 src/test/java/test/TestWithFile delete mode 100644 src/test/java/test/TestWithFile.java diff --git a/src/test/java/test/TestAdvancedFunctions.java b/src/test/java/test/TestAdvancedFunctions.java deleted file mode 100644 index 92088b9e..00000000 --- a/src/test/java/test/TestAdvancedFunctions.java +++ /dev/null @@ -1,379 +0,0 @@ -package test; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import leekscript.LSException; -import leekscript.compiler.LeekScript; -import leekscript.compiler.exceptions.LeekCompilerException; -import leekscript.runner.AI; -import leekscript.runner.values.AbstractLeekValue; -import leekscript.runner.values.ArrayLeekValue; -import leekscript.runner.values.BooleanLeekValue; -import leekscript.runner.values.DoubleLeekValue; -import leekscript.runner.values.IntLeekValue; -import leekscript.runner.values.NullLeekValue; -import leekscript.runner.values.StringLeekValue; - -public class TestAdvancedFunctions { - - private AI ai; - - @Before - public void init() throws Exception { - ai = new TestAI(); - } - - // Test de retour sur des structures du leekscript - @Test - public void whileReturnTest() throws Exception { - // Test AI - Assert.assertTrue(LeekScript.testScript("var t = 0; while(t<5){ t++; return t;}", new IntLeekValue(1))); - Assert.assertTrue(LeekScript.testScript("var t = 0; while(t<5){ t++; return t;} return 0;", new IntLeekValue(1))); - } - - @Test - public void doWhileReturnTest() throws Exception { - // Test AI - Assert.assertTrue(LeekScript.testScript("var t = 0; do{ t++; return t;}while(t<5);", new IntLeekValue(1))); - try { - LeekScript.testScript("var t = 0; do{ t++; return t;}while(t<5); return 2;", new IntLeekValue(1)); - Assert.fail("Compilation validée..."); - } catch (LeekCompilerException e) { - return; - } catch (Exception e) { - Assert.fail("Compilation validée..."); - } - } - - @Test - public void forReturnTest() throws Exception { - // Test AI - Assert.assertTrue(LeekScript.testScript("for(var i=0;i<3;i++){ return i; }", new IntLeekValue(0))); - Assert.assertTrue(LeekScript.testScript("for(var i=0;i<3;i++){ return i; } return 2;", new IntLeekValue(0))); - } - - @Test - public void anonymousTest() throws Exception { - // Test AI - Assert.assertTrue(LeekScript.testScript("function te(a){ return function(){ return a**2; }; } return te(2)();", new IntLeekValue(4))); - } - - @Test - public void anonymous2Test() throws Exception { - // Test AI - Assert.assertTrue(LeekScript.testScript("function te(a){ return function(b){ return function(c){return a*b*c;}; }; } return te(2)(1)(2);", new IntLeekValue(4))); - } - - @Test - public void anonymous3Test() throws Exception { - // Test AI - Assert.assertTrue(LeekScript.testScript("var tab = [2,3,4,5,6];var r = [];for(var i: var j in tab){ r[i] = function(){ return j; };}return 4;", new IntLeekValue(4))); - } - - @Test - public void conditionalTest() throws Exception { - // Test AI - Assert.assertTrue(LeekScript.testScript("var test = 0; if(false) if(true) test = 3; else test = 1; return test;", new IntLeekValue(0))); - } - - @Test - public void forEachReturnTest() throws Exception { - // Test AI - Assert.assertTrue(LeekScript.testScript("var tab = [0,1,2,3]; for(var i in tab){ return i; }", new IntLeekValue(0))); - Assert.assertTrue(LeekScript.testScript("var tab = [0,1,2,3]; for(var i in tab){ return i; } return 5;", new IntLeekValue(0))); - } - - @Test - public void forEachKeyReturnTest() throws Exception { - // Test AI - Assert.assertTrue(LeekScript.testScript("var tab = [1:0,2:1,3:2,4:3]; for(var i : var j in tab){ return i; } ", new IntLeekValue(1))); - Assert.assertTrue(LeekScript.testScript("var tab = [1:0,2:1,3:2,4:3]; for(var i : var j in tab){ return i; } return 0;", new IntLeekValue(1))); - } - - @Test - public void divisionByZeroTest() throws Exception { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - // Test nombre - codes.add("8/0"); - values.add(null); - - // Test nombre - codes.add("8/null"); - values.add(null); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - - - - @Test - public void arrayMapTest() throws Exception { - - // On lance le test - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("arrayMap([1,2,3,4,5],function(e){ return e*2; })"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(2), new IntLeekValue(4), new IntLeekValue(6), new IntLeekValue(8), new IntLeekValue(10) })); - - codes.add("arrayMap([4,9,16],sqrt)"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(2), new IntLeekValue(3), new IntLeekValue(4) })); - - codes.add("arrayMap(['a':1,'b':2],function(k,v){ return k+v;})"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new StringLeekValue("a"), new StringLeekValue("a1"), - new StringLeekValue("b"), new StringLeekValue("b2") }, true)); - - codes.add("function(){ var t = ['a':1,'b':2]; arrayMap(t,function(@k,@v){ v='tomate';k='ctus'; return 3;}); return t;}()"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { new StringLeekValue("a"), - new StringLeekValue("tomate"), - new StringLeekValue("b"), - new StringLeekValue("tomate") }, true)); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void arrayFilterTest() throws Exception { - - // On lance le test - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("arrayFilter([1,2,3,4,5,6,7,8,9],function(e){ return e>5; })"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(6), - new IntLeekValue(7), - new IntLeekValue(8), - new IntLeekValue(9) - })); - - codes.add("arrayFilter([4,5,6,'test',8,9],function(e){ return e=='test'; })"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new StringLeekValue("test") - })); - - codes.add("string(arrayFilter(['a','b','c','d'],function(k,v){ return k==3; }))"); - values.add("[d]"); - - codes.add("string(function(){ var t = ['a','b','c','d']; arrayFilter(t,function(k,@v){ v=4; return k==3; }); return t;}())"); - values.add("[4, 4, 4, 4]"); - - codes.add("string(arrayFilter(['a','b','c','d'],function(k,@v){ v=4; return k==3; }))"); - values.add("[4]"); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void arrayFlatten() throws Exception { - - // On lance le test - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("arrayFlatten([6,7,[8,9]],99)"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(6), new IntLeekValue(7), new IntLeekValue(8), new IntLeekValue(9) })); - - codes.add("arrayFlatten([6,[[7]],[8,9]],2)"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(6), new IntLeekValue(7), new IntLeekValue(8), new IntLeekValue(9) })); - - codes.add("arrayFlatten([6,[[7]],[8,9]])"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new IntLeekValue(6), new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(7) }), - new IntLeekValue(8), new IntLeekValue(9) })); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void arrayFoldLeft() throws Exception { - - // On lance le test - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("arrayFoldLeft([6,7,8,9], function(a,b){return a+b;},0)"); - values.add(30); - - codes.add("arrayFoldLeft([1,0,1,2,5,7,9], function(a,b){return a+','+b;},'')"); - values.add(",1,0,1,2,5,7,9"); - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void arrayFoldRight() throws Exception { - - // On lance le test - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("arrayFoldRight([6,7,8,9], function(a,b){return a+b;},0)"); - values.add(30); - - codes.add("arrayFoldRight([1,0,1,2,5,7,9], function(a,b){return a+','+b;},'')"); - values.add("1,0,1,2,5,7,9,"); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void arrayPartition() throws Exception { - - // On lance le test - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("arrayPartition([6,7,8,9], function(a){return a&1;})"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { - new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(1), new IntLeekValue(7), new IntLeekValue(3), new IntLeekValue(9) }, true), - new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(0), new IntLeekValue(6), new IntLeekValue(2), new IntLeekValue(8) }, true) })); - - codes.add("string(arrayPartition([6,7,8,9], function(k,v){return k;}))"); - values.add("[[1 : 7, 2 : 8, 3 : 9], [6]]"); - - codes.add("string(arrayPartition([4,3,2,1], function(k,v){return k codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("string([0]+[1,2])"); - values.add("[0, 1, 2]"); - - codes.add("function(){ var a = [0,1]; a+= [3]; return string(a);}()"); - values.add("[0, 1, 3]"); - - codes.add("string(arrayConcat([0],[1,2]))"); - values.add("[0, 1, 2]"); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void arrayIter() throws Exception { - - // On lance le test - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("string(function(){ var t = [1,2,3,4]; arrayIter(t, function(v){ v=2; }); return t; }())"); - values.add("[1, 2, 3, 4]"); - - codes.add("string(function(){ var t = [1,2,3,4]; arrayIter(t, function(@v){ v=2; }); return t; }())"); - values.add("[2, 2, 2, 2]"); - - codes.add("string(function(){ var t = [1,2,3,4]; arrayIter(t, function(k, @v){ v=k; }); return t; }())"); - values.add("[0, 1, 2, 3]"); - - codes.add("string(function(){ var t = [1,2,3,4]; arrayIter(t, function(k, v){ v=k; }); return t; }())"); - values.add("[1, 2, 3, 4]"); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void arraySort() throws Exception { - - // On lance le test - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - // codes.add("string(arraySort([0,1,2,3], function(e, f){return - // e>f;}))"); - codes.add("string(function(){var t = [0,1,2]; return arraySort(t,function(e, f){return (e>f)?(-1):(ek2)?(-1):(k1k2)?(-1):(k1 mCodes, List mValues) throws Exception { - String leekscript = "return ["; - AbstractLeekValue[] values = new AbstractLeekValue[mValues.size()]; - - for (int i = 0; i < mValues.size(); i++) { - if (i != 0) - leekscript += ","; - leekscript += mCodes.get(i); - Object c = mValues.get(i); - if (c instanceof Integer) - values[i] = new IntLeekValue(((Integer) mValues.get(i))); - else if (c instanceof Double) - values[i] = new DoubleLeekValue(((Double) mValues.get(i))); - else if (c instanceof String) - values[i] = new StringLeekValue(((String) mValues.get(i))); - else if (c instanceof Boolean) - values[i] = new BooleanLeekValue(((Boolean) mValues.get(i))); - else if (c instanceof AbstractLeekValue) - values[i] = (AbstractLeekValue) mValues.get(i); - else - values[i] = new NullLeekValue(); - } - - leekscript += "];"; - try { - return LeekScript.testScript(leekscript, new ArrayLeekValue(ai, values)); - } catch (LSException e) { - int i = e.getIndex(); - System.err.println("Erreur :\n" + mCodes.get(i)); - System.err.println("Valeur attendue :\n" + e.getThe().getString(ai)); - System.err.println("Valeur renvoyée :\n" + e.getRun().getString(ai)); - return false; - } - } -} diff --git a/src/test/java/test/TestFunctions.java b/src/test/java/test/TestFunctions.java deleted file mode 100644 index fd6f1ec3..00000000 --- a/src/test/java/test/TestFunctions.java +++ /dev/null @@ -1,575 +0,0 @@ -package test; - -import java.util.ArrayList; -import java.util.List; - -import leekscript.ErrorManager; -import leekscript.LSException; -import leekscript.compiler.LeekScript; -import leekscript.runner.AI; -import leekscript.runner.LeekConstants; -import leekscript.runner.values.AbstractLeekValue; -import leekscript.runner.values.ArrayLeekValue; -import leekscript.runner.values.BooleanLeekValue; -import leekscript.runner.values.DoubleLeekValue; -import leekscript.runner.values.IntLeekValue; -import leekscript.runner.values.NullLeekValue; -import leekscript.runner.values.StringLeekValue; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class TestFunctions { - - private AI ai; - - @Before - public void init() throws Exception { - ai = new TestAI(); - } - - @Test - public void MathFunctionsTest() throws Exception { - - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - // Test abs - codes.add("abs(-5)"); - values.add(5); - codes.add("abs(8)"); - values.add(8); - - // Test min - codes.add("min(8,5)"); - values.add(5); - codes.add("min(8,88)"); - values.add(8); - - // Test max - codes.add("max(8,5)"); - values.add(8); - codes.add("max(8,88)"); - values.add(88); - - // Test cos - codes.add("cos(0)"); - values.add(1); - codes.add("cos(2.5)"); - values.add(Math.cos(2.5)); - - // Test sin - codes.add("sin(0)"); - values.add(0); - codes.add("sin(2.5)"); - values.add(Math.sin(2.5)); - - // Test tan - codes.add("tan(0)"); - values.add(0); - codes.add("tan(2.5)"); - values.add(Math.tan(2.5)); - - // Test toRadians - codes.add("toRadians(180)"); - values.add(Math.PI); - - // Test toDegrees - codes.add("toDegrees(PI)"); - values.add(180); - - // Test acos - codes.add("acos(1)"); - values.add(0); - - // Test asin - codes.add("asin(0)"); - values.add(0); - - // Test atan - codes.add("atan(0)"); - values.add(0); - - // Test ceil - codes.add("ceil(1.897)"); - values.add(2); - codes.add("ceil(3.01)"); - values.add(4); - - // Test floor - codes.add("floor(1.897)"); - values.add(1); - codes.add("floor(3.01)"); - values.add(3); - - // Test round - codes.add("round(1.897)"); - values.add(2); - codes.add("round(3.01)"); - values.add(3); - - // Test sqrt - codes.add("sqrt(16)"); - values.add(4); - codes.add("sqrt(25)"); - values.add(5); - - // Test cqrt - codes.add("cbrt(1000)"); - values.add(10); - codes.add("cbrt(125)"); - values.add(5); - - // Test log - codes.add("log(1)"); - values.add(0); - codes.add("log(E)"); - values.add(1); - - // Test log10 - codes.add("log10(10)"); - values.add(1); - - // Test exp - codes.add("exp(1)"); - values.add(Math.E); - - // Test pow - codes.add("pow(5,3)"); - values.add(125); - - // Test signum - codes.add("signum(85)"); - values.add(1); - codes.add("signum(-0.5)"); - values.add(-1); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void StringFunctionsTest() throws Exception { - // Test AI - - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - // Test charAt - codes.add("charAt('bonjour', 1)"); - values.add("o"); - - // Test length - codes.add("length('bonjour')"); - values.add(7); - - // Test substring - codes.add("substring('bonjour',2,3)"); - values.add("njo"); - - // Test replace - codes.add("replace('bonjour','onj','pro')"); - values.add("bproour"); - - // Test indexOf - codes.add("indexOf('bonjour','o')"); - values.add(1); - codes.add("indexOf('bonjour','o',2)"); - values.add(4); - - // Test split - codes.add("string(split('1:2:3:4:5',':'))"); - values.add("[1, 2, 3, 4, 5]"); - codes.add("string(split('1:2:3:4:5',':',2))"); - values.add("[1, 2:3:4:5]"); - - // Test toLower - codes.add("toLower('AbCDefgh')"); - values.add("abcdefgh"); - - // Test toUpper - codes.add("toUpper('AbCDefgh')"); - values.add("ABCDEFGH"); - - // Test startsWith - codes.add("startsWith('bonjour','bon')"); - values.add(true); - codes.add("startsWith('bonjour','jour')"); - values.add(false); - - // Test endsWith - codes.add("endsWith('bonjour','bon')"); - values.add(false); - codes.add("endsWith('bonjour','jour')"); - values.add(true); - - // Test contains - codes.add("contains('bonjour','bon')"); - values.add(true); - codes.add("contains('bonjour','jour')"); - values.add(true); - codes.add("contains('bonjour','jourr')"); - values.add(false); - - // Test number - codes.add("contains('bonjour','bon')"); - values.add(true); - codes.add("contains('bonjour','jour')"); - values.add(true); - codes.add("contains('bonjour','jourr')"); - values.add(false); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void ArrayFunctionsTest() throws Exception { - // Test AI - - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - // Test remove - codes.add("function(){ var r = ['a','b','c','d','e']; return remove(r,1); }()"); - values.add("b"); - codes.add("function(){ var r = ['a','b','c','d','e']; return remove(r,55); }()"); - values.add(null); - codes.add("function(){ var r = ['a','b','c','d','e']; remove(r,1); return string(r);}()"); - values.add("[a, c, d, e]"); - - // Test count - codes.add("count(['a','b','c','d','e'])"); - values.add(5); - - // Test join - codes.add("join(['a','b','c','d','e'],'_')"); - values.add("a_b_c_d_e"); - codes.add("join(['a','b','c','d','e'],'_-')"); - values.add("a_-b_-c_-d_-e"); - - // Test insert - codes.add("function(){ var a = ['a','b','c','d']; insert(a, 'b', 1); return string(a); }()"); - values.add("[a, b, b, c, d]"); - - // Test push - codes.add("function(){ var a = ['a','b','c','d']; push(a, 'b'); return string(a); }()"); - values.add("[a, b, c, d, b]"); - - // Test unshift - codes.add("function(){ var a = ['a','b','c','d']; unshift(a, 'b'); return string(a); }()"); - values.add("[b, a, b, c, d]"); - - // Test shift - codes.add("function(){ var a = ['a','b','c','d']; shift(a); return string(a); }()"); - values.add("[b, c, d]"); - - // Test pop - codes.add("function(){ var a = ['a','b','c','d']; pop(a); return string(a); }()"); - values.add("[a, b, c]"); - - // Test removeElement - codes.add("function(){ var a = ['a','b','c','d']; removeElement(a,'c'); return string(a); }()"); - values.add("[0 : a, 1 : b, 3 : d]"); - - // Test removeKey - codes.add("function(){ var a = ['a':'va','b':'vb','c':'vc','d':'vd']; removeKey(a,'a'); return string(a); }()"); - values.add("[b : vb, c : vc, d : vd]"); - - // Test sort - codes.add("function(){ var a = [8,6,2,3,7,1,0]; sort(a); return string(a); }()"); - values.add("[0, 1, 2, 3, 6, 7, 8]"); - codes.add("function(){ var a = [8,6,2,3,7,1,0]; sort(a, SORT_ASC); return string(a); }()"); - values.add("[0, 1, 2, 3, 6, 7, 8]"); - codes.add("function(){ var a = [8,6,2,3,7,1,0]; sort(a, SORT_DESC); return string(a); }()"); - values.add("[8, 7, 6, 3, 2, 1, 0]"); - - // Test assocSort - codes.add("function(){ var a = ['b':'vb','c':'vc','a':'va','d':'vd']; assocSort(a); return string(a); }()"); - values.add("[a : va, b : vb, c : vc, d : vd]"); - codes.add("function(){ var a = ['b':'vb','c':'vc','a':'va','d':'vd']; assocSort(a, SORT_DESC); return string(a); }()"); - values.add("[d : vd, c : vc, b : vb, a : va]"); - codes.add("function(){ var a = [8,6,2,3,7,1,0]; assocSort(a); return string(a); }()"); - values.add("[6 : 0, 5 : 1, 2 : 2, 3 : 3, 1 : 6, 4 : 7, 0 : 8]"); - - // Test keySort - codes.add("function(){ var a = ['b':'vb','c':'vc','a':'va','d':'vd']; keySort(a); return string(a); }()"); - values.add("[a : va, b : vb, c : vc, d : vd]"); - codes.add("function(){ var a = ['b':'vb','c':'vc','a':'va','d':'vd']; keySort(a, SORT_DESC); return string(a); }()"); - values.add("[d : vd, c : vc, b : vb, a : va]"); - codes.add("function(){ var a = [6 : 0, 5 : 1, 2 : 2, 3 : 3, 1 : 6, 4 : 7, 0 : 8]; keySort(a); return string(a); }()"); - values.add("[8, 6, 2, 3, 7, 1, 0]"); - - // Test search - codes.add("function(){ var a = ['a','b','c','d']; return search(a,'c'); }()"); - values.add(2); - codes.add("function(){ var a = ['cle1':'a','cle2':'b','cle3':'c','cle4':'d']; return search(a,'c'); }()"); - values.add("cle3"); - codes.add("function(){ var a = ['cle1':'a','cle2':'b','cle3':'c','cle4':'d']; return search(a,'454'); }()"); - values.add(null); - - // Test inArray - codes.add("function(){ var a = ['a','b','c','d']; return inArray(a,'c'); }()"); - values.add(true); - codes.add("function(){ var a = ['cle1':'a','cle2':'b','cle3':'c','cle4':'d']; return inArray(a,'c'); }()"); - values.add(true); - codes.add("function(){ var a = ['cle1':'a','cle2':'b','cle3':'c','cle4':'d']; return inArray(a,'cle3'); }()"); - values.add(false); - codes.add("function(){ var a = ['cle1':'a','cle2':'b','cle3':'c','cle4':'d']; return inArray(a,'454'); }()"); - values.add(false); - - // Test reverse - codes.add("function(){ var a = ['a','b','c','d']; reverse(a); return string(a); }()"); - values.add("[d, c, b, a]"); - - // Test arrayMin - codes.add("arrayMin([8,4,3,-1,8,44])"); - values.add(-1); - codes.add("arrayMin([0:7,8:9,'a':2])"); - values.add(2); - - // Test arrayMax - codes.add("arrayMax([8,4,3,-1,8,44])"); - values.add(44); - codes.add("arrayMax([0:7,8:9,'a':2])"); - values.add(9); - - // Test sum - codes.add("sum([1,5,7])"); - values.add(13); - codes.add("sum([0:1,'a':5,'test':7])"); - values.add(13); - codes.add("sum([])"); - values.add(0); - - // Test average - codes.add("average([2,4,6])"); - values.add(4); - codes.add("average([0:2,'a':4,'test':6])"); - values.add(4); - codes.add("average([])"); - values.add(0); - - // Test fill - codes.add("function(){ var a = [1,2,3]; fill(a, 'a'); return string(a); }()"); - values.add("[a, a, a]"); - codes.add("function(){ var a = [1,2,3]; fill(a, 'a',2); return string(a); }()"); - values.add("[a, a, 3]"); - codes.add("function(){ var a = []; fill(a, 'a',2); return string(a); }()"); - values.add("[a, a]"); - - // Test isEmpty - codes.add("isEmpty([2,4,6])"); - values.add(false); - codes.add("isEmpty([2:8])"); - values.add(false); - codes.add("isEmpty([])"); - values.add(true); - - // Test subArray - codes.add("string(subArray([1,2,3,4,5,6,7,8],1,3))"); - values.add("[2, 3, 4]"); - codes.add("string(subArray([1,2,3,4,5,6,7,8],3,3))"); - values.add("[4]"); - - // Test pushAll - codes.add("function(){ var a = [1,2,3]; pushAll(a, [5,6,7]); return string(a); }()"); - values.add("[1, 2, 3, 5, 6, 7]"); - - // Test assocReverse - codes.add("function(){ var a = [1,2,3]; assocReverse(a); return string(a); }()"); - values.add("[2 : 3, 1 : 2, 0 : 1]"); - - // Test large array - codes.add("function(){ var a = []; for (var i = 0; i < 100000; ++i) { push(a, i); } return a[91212]; }()"); - values.add("91212"); - - // Test arrayMap et suivant => plus loin - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void typeOfTest() throws Exception { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - // Test nombre - codes.add("typeOf(255)"); - values.add(LeekConstants.TYPE_NUMBER.getIntValue()); - codes.add("typeOf(255.8)"); - values.add(LeekConstants.TYPE_NUMBER.getIntValue()); - // Test string - codes.add("typeOf('coucou')"); - values.add(LeekConstants.TYPE_STRING.getIntValue()); - // Test boolean - codes.add("typeOf(false)"); - values.add(LeekConstants.TYPE_BOOLEAN.getIntValue()); - // Test array - codes.add("typeOf([1,false])"); - values.add(LeekConstants.TYPE_ARRAY.getIntValue()); - // Test fonction - codes.add("typeOf(function(){ return null; })"); - values.add(LeekConstants.TYPE_FUNCTION.getIntValue()); - // Test null - codes.add("typeOf(null)"); - values.add(LeekConstants.TYPE_NULL.getIntValue()); - // Test piège - codes.add("typeOf(function(){ return 4; }())"); - values.add(LeekConstants.TYPE_NUMBER.getIntValue()); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void colorTest() throws Exception { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - // Test color - codes.add("color(255,0,255)"); - values.add(0xFF00FF); - // Test color - codes.add("color(255,255,0)"); - values.add(0xFFFF00); - // Test color - codes.add("color(0,255,255)"); - values.add(0x00FFFF); - - // Red - codes.add("getRed(" + 0xAE0000 + ")"); - values.add(174); - // Green - codes.add("getGreen(" + 0xAF00 + ")"); - values.add(175); - // Blue - codes.add("getBlue(" + 0xAD + ")"); - values.add(173); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void sortTest() throws Exception { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - // Test sort - codes.add("function(){ var t =[null,null,4,8,9]; sort(t); return t;}()"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(4), new IntLeekValue(8), new IntLeekValue(9), new NullLeekValue(), new NullLeekValue() })); - - // Test sort - codes.add("function(){ var t =[4, null, 4, null, 4]; sort(t); return t;}()"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { new IntLeekValue(4), new IntLeekValue(4), new IntLeekValue(4), new NullLeekValue(), new NullLeekValue() })); - - // Test sort desc - codes.add("function(){ var t =[4, null, 5, null, 8]; sort(t,SORT_DESC); return t;}()"); - values.add(new ArrayLeekValue(ai, new AbstractLeekValue[] { new NullLeekValue(), new NullLeekValue(), new IntLeekValue(8), new IntLeekValue(5), new IntLeekValue(4) })); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } - - @Test - public void testReference() throws Exception { - String leekscript = "var t = [3,4,5]; t[3]=[1,2,3,4]; var r = @t[3]; r[4] ='prou3t'; return t;"; - LeekScript.testScript(leekscript, new NullLeekValue()); - } - - @Test - public void testAnonymousFunctioNSelfAccess() { - String leekscript = "var t = function(){ return t; };"; - try { - LeekScript.testScript(leekscript, new NullLeekValue()); - } catch (Exception e) { - - ErrorManager.exception(e); - } - } - - @Test - public void testIfIfNot() { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("function(){ var a = 1; if(a is 1) return 2; else return 0;}()"); - values.add(2); - - codes.add("function(){ var a = 1; if(a is 2) return 2; else return 0;}()"); - values.add(0); - - codes.add("function(){ var a = 1; if(a is not 2) return 2; else return 0;}()"); - values.add(2); - - codes.add("function(){ var a = 1; if(a is not 1) return 2; else return 0;}()"); - values.add(0); - - codes.add("function(){ var a = true; if(not a) return 2; else return 0;}()"); - values.add(0); - - // Test AI - try { - Assert.assertTrue(testAI(codes, values)); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(); - } - } - - @Test - public void testOperators() { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - codes.add("function(){ var a = 1; var result = -10 + (1- (a-1)); return result;}()"); - values.add(-9); - - codes.add("function(){ var a = 1; var result = 0; result = -10 + (1- (a-1)); return result;}()"); - values.add(-9); - // Test AI - try { - Assert.assertTrue(testAI(codes, values)); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail(); - } - } - - private boolean testAI(List mCodes, List mValues) throws Exception { - String leekscript = "return ["; - AbstractLeekValue[] values = new AbstractLeekValue[mValues.size()]; - - for (int i = 0; i < mValues.size(); i++) { - if (i != 0) - leekscript += ","; - leekscript += mCodes.get(i); - Object c = mValues.get(i); - if (c == null) - values[i] = new NullLeekValue(); - else if (c instanceof Integer) - values[i] = new IntLeekValue(((Integer) mValues.get(i))); - else if (c instanceof Double) - values[i] = new DoubleLeekValue(((Double) mValues.get(i))); - else if (c instanceof String) - values[i] = new StringLeekValue(((String) mValues.get(i))); - else if (c instanceof Boolean) - values[i] = new BooleanLeekValue(((Boolean) mValues.get(i))); - else if (c instanceof AbstractLeekValue) - values[i] = (AbstractLeekValue) mValues.get(i); - } - leekscript += "];"; - try { - return LeekScript.testScript(leekscript, new ArrayLeekValue(ai, values)); - } catch (LSException e) { - int i = e.getIndex(); - System.err.println("Erreur :\n" + mCodes.get(i)); - System.err.println("Valeur attendue :\n" + e.getThe().getString(ai)); - System.err.println("Valeur renvoyée :\n" + e.getRun().getString(ai)); - return false; - } - } -} diff --git a/src/test/java/test/TestGeneral b/src/test/java/test/TestGeneral deleted file mode 100644 index 748d0901..00000000 --- a/src/test/java/test/TestGeneral +++ /dev/null @@ -1,278 +0,0 @@ -package test; - -import leekscript.LSException; -import leekscript.compiler.LeekScript; -import leekscript.compiler.exceptions.LeekCompilerException; -import leekscript.functions.VariableOperations; -import leekscript.runner.LeekConstants; -import leekscript.runner.values.ArrayLeekValue; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.alibaba.fastjson.JSONObject; - -public class TestGeneral { - - TestAI ai; - - @Before - public void init() throws Exception { - ai = new TestAI(); - } - - @Test - public void lsOperationsTest() throws Exception { - VariableOperations op = new VariableOperations(JSONObject.parseObject("{\"1\":\"50\",\"10\":\"100\",\"50\":\"1000\",\"100\":\"5000\"}")); - System.out.println(op.getOperations(501)); - } - - @Test - public void ternaireBisTest() throws Exception { - Assert.assertFalse(LeekScript.testScript("return (1 & 2 ? 'coucou');", false)); - } - - @Test - public void incrementTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var u=0; return 1*u++ +2-2;", 0)); - } - - @Test - public void decrementTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var u=2; return 1*u--+2-2;", 2)); - } - - @Test - public void preIncrementTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var u=0; return 1*++u+2-2;", 1)); - } - - @Test - public void preDecrementTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var u=2; return 1*--u+2-2;", 1)); - } - - @Test - public void tripleEqualsTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("return 1 === true;", false)); - } - - @Test - public void ternaireTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var t = true; return t === 2?6:2*4;", 8)); - } - - @Test - public void anonymousFunctionTest() throws Exception { - Assert.assertTrue(LeekScript.testScript(10, "var test = function(@a) { a = 8; }; var test2 = function(b, d) { var c = 1; d(c); return c; }; return test2(1, test);", 8)); - } - - @Test - public void conditionTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var test = 8; if(test == 7) return 1; else if(test == 8) return 2; else return 3;", 2)); - } - - @Test - public void foreachTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var test = [0,1,2,3,4,5]; var retour = \"\"; for(var i in test){ retour += i; } return retour;", - "012345")); - } - - @Test - public void foreachGlobalTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("global i; var test = [0,1,2,3,4,5]; var retour = \"\"; for(i in test){ retour += i; } return retour;", - "012345")); - } - - @Test - public void foreachkeyvalTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var test = ['a':5,'b':8,'c':8,9:'p']; var retour = \"\"; for(var i : var j in test){ retour += i+':'+j; } return retour;", - "a:5b:8c:89:p")); - } - - @Test - public void foreachkeyvalGlobalTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("global i,j; var test = ['a':5,'b':8,'c':8,9:'p']; var retour = \"\"; for(i : j in test){ retour += i+':'+j; } return retour;", - "a:5b:8c:89:p")); - } - - @Test - public void forTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("for(var i=0;i<1000;i++){}", null)); - } -/* - @Test - public void forGlobalTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("global i; for(i=0;i<1000;i++){}", null)); - } -*/ - - @Test - public void functionGlobalTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("function testi() { var tab=[1,5]; for (i in tab) debug(i); } global i;", null)); - } - - @Test - public void foreach() throws Exception { - Assert.assertTrue(LeekScript.testScript( - "var a = [1, 2, 3, 4, 5] var s = 0 for (var i in a) { s += i } return s;", 15)); - - Assert.assertTrue(LeekScript.testScript(10, - "var a = [1, 2, 3, 4, 5] var s = 0 for (var i in a) { s += i } return s;", 15)); - - // Assert.assertTrue(LeekScript.testScript(10, "var a = [1, 2, 3, 4, 5] var i var s = 0 for (i in a) { s += i } return s;", 15)); - - Assert.assertTrue(LeekScript.testScript(10, - "var a = [1, 2, 3, 4, 5] var s = 0 for (var i : var j in a) { s += i * j } return s;", 40)); - - Assert.assertTrue(LeekScript.testScript(10, - "var a = [[1], [2], [3], [4], [5]] var s = 0 for (var i : var j in a) { s += i } return s;", 10)); - - Assert.assertTrue(LeekScript.testScript(10, - "var a = [[1], [2], [3], [4], [5]] var s = 0 for (var i : var j in a) { push(j, 12) s += i * count(j) } return s;", 20)); - - Assert.assertTrue(LeekScript.testScript(10, - "var a = [[1], [2], [3], [4], [5]] var s = 0 for (var i in a) { push(i, 12) s += count(i) } return s;", 10)); - } - - @Test - public void whileTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var i = 0; while(i<1000){ i++; }", null)); - } - - // Test simples d'opérateurs - @Test - public void additionTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var test = 1 + 8; test += 3; test++; var a = 7; var b = 1; return [test, a+b, (1+1)+9.5, 'test'+8];", - new ArrayLeekValue(ai, new Object[] { 13, 8, 11.5, "test8" }))); - } - - @Test - public void soustractionTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var test = 20 - 8; test -= 3; test--; var a = 7; var b = 1; return [test, a-b, (1-1)-9.5];", - new ArrayLeekValue(ai, new Object[] { - 8, 6, -9.5 }))); - } - - @Test - public void multiplicationTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var test = 4; test *= 3; var c = 7;return [test, 8*9, 2*c];", - new ArrayLeekValue(ai, new Object[] { 12, 72, 14 }))); - } - - @Test - public void modulusTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var test = 4; test %= 3; var c = 7;return [test, 8%9, 8%c];", - new ArrayLeekValue(ai, new Object[] { 1, - 8, 1 }))); - } - - @Test - public void divisionTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var test = 7; test /= 2; var c = 7;return [test, 12/6, 14/c];", - new ArrayLeekValue(ai, new Object[] { 3.5, 2, 2 }))); - } - - @Test - public void operatorsTest() throws Exception { - Object[] values = new Object[] { true, false, true, false, false, true, false }; - Assert.assertTrue(LeekScript.testScript("return [true && true, true && false, true || false, false || false, 1 > 3, 1 < 3, 4 == 7];", - new ArrayLeekValue(ai, values))); - } - - @Test - public void prioritiesTest() throws Exception { - Object[] values = new Object[] { - // 1+6*2 - 3*2 - 7, - // 7*8 - 1 - 55, - // 3*3 - 8 > 0 - true, - // 7*8 == 56 && 33 -8 - true }; - Assert.assertTrue(LeekScript.testScript("return [1+6*2-3*2,7*8-1, 3*3-8>0, 7*8 == 56 && 33-8 ];", - new ArrayLeekValue(ai, values))); - } - - // Test un peu plus poussés - @Test - public void functionTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("function test(a){ return a+2; } return test(7);", 9)); - } - - @Test - public void divisionByZeroTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("return 8/0;", null)); - Assert.assertTrue(LeekScript.testScript("return 8/null;", null)); - } - - @Test - public void whileReturnTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var t = 0; while(t<5){ t++; return t;}", 1)); - Assert.assertTrue(LeekScript.testScript("var t = 0; while(t<5){ t++; return t;} return 0;", 1)); - } - - @Test - public void doWhileReturnTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var t = 0; do { t++; return t; } while (t < 5);", 1)); - Assert.assertFalse(LeekScript.testScript("var t = 0; do { t++; return t; } while (t < 5); return 2;", 1)); - } - - @Test - public void forReturnTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("for(var i=0;i<3;i++){ return i; }", 0)); - Assert.assertTrue(LeekScript.testScript("for(var i=0;i<3;i++){ return i; } return 2;", 0)); - } - - @Test - public void anonymousTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("function te(a){ return function(){ return a**2; }; } return te(2)();", 4)); - } - - @Test - public void anonymous2Test() throws Exception { - Assert.assertTrue(LeekScript.testScript("function te(a){ return function(b){ return function(c){return a*b*c;}; }; } return te(2)(1)(2);", 4)); - } - - @Test - public void conditionalTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var test = 0; if(false) if(true) test = 3; else test = 1; return test;", 0)); - } - - @Test - public void forEachReturnTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var tab = [0,1,2,3]; for(var i in tab){ return i; }", 0)); - Assert.assertTrue(LeekScript.testScript("var tab = [0,1,2,3]; for(var i in tab){ return i; } return 5;", 0)); - } - - @Test - public void forEachKeyReturnTest() throws Exception { - Assert.assertTrue(LeekScript.testScript("var tab = [1:0,2:1,3:2,4:3]; for(var i : var j in tab){ return i; } ", 1)); - Assert.assertTrue(LeekScript.testScript("var tab = [1:0,2:1,3:2,4:3]; for(var i : var j in tab){ return i; } return 0;", 1)); - } - - - @Test - public void testAnonymousFunctioNSelfAccess() throws Exception { - String leekscript = "var t = function(){ return t; };"; - LeekScript.testScript(leekscript, null); - } - - @Test - public void stringTest() throws Exception { - ArrayList codes = new ArrayList(); - ArrayList values = new ArrayList(); - - // Test nombre - codes.add("'\\\\'"); - values.add("\\"); - - // Test AI - Assert.assertTrue(testAI(codes, values)); - } -} diff --git a/src/test/java/test/TestWithFile b/src/test/java/test/TestWithFile deleted file mode 100644 index 4c8974ea..00000000 --- a/src/test/java/test/TestWithFile +++ /dev/null @@ -1,65 +0,0 @@ -package test; - -import leekscript.compiler.AIFile; -import leekscript.compiler.LeekScript; -import leekscript.compiler.resolver.ResolverContext; -import leekscript.compiler.resolver.Resolver; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -public class TestWithFile { - - @Test - public void testBasicFile() throws Exception { - assertEquals("bonjour", LeekScript.runFile("ai/bonjour.leek")); - } - - @Test - public void testLargeFile() throws Exception { - assertEquals("cent-vingt-trois millions quatre-cent-cinquante-six-mille-sept-cent-quatre-vingt-neuf", LeekScript.runFile("ai/french.leek")); - } - - @Test - public void testInclude() throws Exception { - assertEquals("[a, b, KEY]", LeekScript.runFile("ai/array_keys.leek")); - } - - @Test - public void testIncludeMultiple() throws Exception { - assertEquals("[a, b, KEY]", LeekScript.runFile("ai/include_multiple.leek")); - } - - @Test - public void testCustomResolver() throws Exception { - class CustomContext extends ResolverContext {} - LeekScript.setResolver(new Resolver() { - @Override - public AIFile resolve(String path, ResolverContext context) { - return new AIFile(path, "return 'generated';", System.currentTimeMillis(), 11, new CustomContext()); - } - @Override - public ResolverContext createContext(int parameter1, int parameter2, int parameter3) { - return null; - } - }); - assertEquals("generated", LeekScript.runFile("whatever")); - LeekScript.resetResolver(); - } - - @Test - public void testSubFolder() throws Exception { - assertEquals("sub", LeekScript.runFile("ai/include_sub.leek")); - } - - @Test - public void testRelativePath() throws Exception { - assertEquals("cent-vingt-trois millions quatre-cent-cinquante-six-mille-sept-cent-quatre-vingt-neuf", LeekScript.runFile("ai/subfolder/include_parent.leek")); - } - - @Test - public void testMultipleInclude() throws Exception { - assertEquals("bonjour", LeekScript.runFile("ai/multiple_includes.leek")); - } -} diff --git a/src/test/java/test/TestWithFile.java b/src/test/java/test/TestWithFile.java deleted file mode 100644 index 08919ec9..00000000 --- a/src/test/java/test/TestWithFile.java +++ /dev/null @@ -1,65 +0,0 @@ -package test; - -import leekscript.compiler.AIFile; -import leekscript.compiler.LeekScript; -import leekscript.compiler.resolver.ResolverContext; -import leekscript.compiler.resolver.Resolver; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -public class TestWithFile { - - @Test - public void testBasicFile() throws Exception { - assertEquals("bonjour", LeekScript.runFile("test/ai/bonjour.leek")); - } - - @Test - public void testLargeFile() throws Exception { - assertEquals("cent-vingt-trois millions quatre-cent-cinquante-six-mille-sept-cent-quatre-vingt-neuf", LeekScript.runFile("test/ai/french.leek")); - } - - @Test - public void testInclude() throws Exception { - assertEquals("[a, b, KEY]", LeekScript.runFile("test/ai/array_keys.leek")); - } - - @Test - public void testIncludeMultiple() throws Exception { - assertEquals("[a, b, KEY]", LeekScript.runFile("test/ai/include_multiple.leek")); - } - - @Test - public void testCustomResolver() throws Exception { - class CustomContext extends ResolverContext {} - LeekScript.setResolver(new Resolver() { - @Override - public AIFile resolve(String path, ResolverContext context) { - return new AIFile(path, "return 'generated';", System.currentTimeMillis(), 11, new CustomContext()); - } - @Override - public ResolverContext createContext(int parameter1, int parameter2, int parameter3) { - return null; - } - }); - assertEquals("generated", LeekScript.runFile("whatever")); - LeekScript.resetResolver(); - } - - @Test - public void testSubFolder() throws Exception { - assertEquals("sub", LeekScript.runFile("test/ai/include_sub.leek")); - } - - @Test - public void testRelativePath() throws Exception { - assertEquals("cent-vingt-trois millions quatre-cent-cinquante-six-mille-sept-cent-quatre-vingt-neuf", LeekScript.runFile("test/ai/subfolder/include_parent.leek")); - } - - @Test - public void testMultipleInclude() throws Exception { - assertEquals("bonjour", LeekScript.runFile("test/ai/multiple_includes.leek")); - } -} From c3675e645d9d51008f1e248d2889fb6b8921fd2d Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 24 May 2021 18:48:48 +0200 Subject: [PATCH 168/319] [compiler] Fix comments only in LS1.1 --- src/main/java/leekscript/compiler/WordParser.java | 4 ++-- src/test/java/test/TestComments.java | 3 ++- src/test/java/test/TestCommon.java | 11 ++++++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index 4f586556..fffe3869 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -128,12 +128,12 @@ else if(type == T_VAR_STRING && opener == c){ if (comment_line || comment_block) continue; if (c == '/' && length > i + 1 && code.charAt(i + 1) == '/') { comment_line = true; - i++; + if (version >= 11) i++; continue; } else if (c == '/' && length > i + 1 && code.charAt(i + 1) == '*') { comment_block = true; - i++; + if (version >= 11) i++; continue; } if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_'){ diff --git a/src/test/java/test/TestComments.java b/src/test/java/test/TestComments.java index ca02d0c1..a2732d0c 100644 --- a/src/test/java/test/TestComments.java +++ b/src/test/java/test/TestComments.java @@ -9,6 +9,7 @@ public void run() throws Exception { section("Comments"); code("// basic; return 12;").equals("null"); code("/* basic; */ return 12;").equals("12"); - code("/*// basic; */ return 12;").equals("12"); + code_v10("/*// basic; */ return 12;").error(); + code_v11("/*// basic; */ return 12;").equals("12"); } } diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index c8e7a692..e4779be4 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -55,6 +55,15 @@ public boolean check(Result result) { }); } + public void error() { + run(version, new Checker() { + public boolean check(Result result) { + return result.result.equals("error"); + } + public String getExpected() { return "error"; } + }); + } + public void almost(double expected) { almost(expected, 1e-10); } @@ -116,7 +125,7 @@ public void run_version(int version, Checker checker) { } catch (Exception e) { e.printStackTrace(); - result = new Result("", 0, 0); + result = new Result("error", 0, 0); } if (checker.check(result)) { From 21cc27119fd29daafac2a6afd0f7883e6336b360 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 25 May 2021 18:51:29 +0200 Subject: [PATCH 169/319] [build] Fix jar --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f435f102..1830fa47 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ jar { attributes "Main-Class": "leekscript.TopLevel" } from { - configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } } From d3c343efa899cba587ad010d59f4362e414a4287 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 6 Jun 2021 12:45:11 +0200 Subject: [PATCH 170/319] [variable-declaration] Use simple constructor --- .../LeekVariableDeclarationInstruction.java | 11 +++++------ .../runner/values/VariableLeekValue.java | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index 7b38e42d..af63c63c 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -50,15 +50,14 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if(!mMustSepare){ + if (!mMustSepare) { writer.addCode("final VariableLeekValue user_" + token.getWord() + " = new VariableLeekValue(mUAI, "); - if(mValue != null) mValue.writeJavaCode(mainblock, writer); + if (mValue != null) mValue.writeJavaCode(mainblock, writer); else writer.addCode("LeekValueManager.NULL"); writer.addLine(");", mLine, mAI); - } - else{ - writer.addCode("final VariableLeekValue user_" + token.getWord() + " = new VariableLeekValue(mUAI, LeekValueManager.NULL); user_" + token.getWord() + ".set(mUAI, "); - if(mValue != null) mValue.writeJavaCode(mainblock, writer); + } else { + writer.addCode("final VariableLeekValue user_" + token.getWord() + " = new VariableLeekValue(mUAI); user_" + token.getWord() + ".init(mUAI, "); + if (mValue != null) mValue.writeJavaCode(mainblock, writer); else writer.addCode("LeekValueManager.NULL"); writer.addLine(");", mLine, mAI); } diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index 259a5664..64dcdd2d 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -33,6 +33,21 @@ public VariableLeekValue(AI ai, AbstractLeekValue value) throws LeekRunException } } + public void init(AI ai, AbstractLeekValue value) throws LeekRunException { + ai.addOperations(1); + if (ai.getVersion() >= 11) { + mValue = LeekOperations.clonePrimitive(ai, value.getValue()); + } else { + if (!(value instanceof VariableLeekValue)) + mValue = value.getValue(); + else + if (value.isReference()) + mValue = value.getValue(); + else + mValue = LeekOperations.clone(ai, value.getValue()); + } + } + @Override public int getInt(AI ai) throws LeekRunException { return mValue.getInt(ai); From 69c6cb1ce7cc91497abf9f98fa4edaf3fb3adbef Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 6 Jun 2021 12:45:11 +0200 Subject: [PATCH 171/319] [loop] Fix foreach variables check --- .../leekscript/compiler/WordCompiler.java | 68 +++++++------------ .../compiler/bloc/AnonymousFunctionBlock.java | 7 ++ .../compiler/bloc/ForeachBlock.java | 17 ++++- .../compiler/bloc/ForeachKeyBlock.java | 47 ++++++++++--- src/test/java/test/TestFunction.java | 2 + src/test/java/test/TestLoops.java | 4 ++ src/test/java/test/TestNumber.java | 2 +- 7 files changed, 92 insertions(+), 55 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 4214d63b..bf273f43 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -1,5 +1,6 @@ package leekscript.compiler; +import java.util.HashSet; import java.util.Set; import java.util.TreeSet; @@ -104,15 +105,19 @@ public void readCode() throws LeekCompilerException { throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_PARENTHESIS_EXPECTED); } int param_count = 0; + var parameters = new HashSet(); while (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("@")) { mCompiler.skipWord(); } - if (mCompiler.getWord().getType() != WordParser.T_STRING) + if (mCompiler.getWord().getType() != WordParser.T_STRING) { throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_EXPECTED); - // if (!isAvailable(mCompiler.getWord().getWord(), true)) - // throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_UNAVAILABLE); - mCompiler.skipWord(); + } + var parameter = mCompiler.readWord(); + if (parameters.contains(parameter.getWord())) { + throw new LeekCompilerException(parameter, Error.PARAMETER_NAME_UNAVAILABLE); + } + parameters.add(parameter.getWord()); param_count++; if (mCompiler.getWord().getType() == WordParser.T_VIRG) @@ -381,27 +386,12 @@ private void forBlock() throws LeekCompilerException { if (mCompiler.getWord().getType() != WordParser.T_STRING) throw new LeekCompilerException(mCompiler.getWord(), Error.VARIABLE_NAME_EXPECTED); IAWord varName = mCompiler.readWord(); - // Si c'est une déclaration on vérifie que le nom est disponnible - /* - if (isDeclaration) { - if (!isAvailable(varName, true)) - throw new LeekCompilerException(mCompiler.lastWord(), Error.VARIABLE_NAME_UNAVAILABLE); - } else { - // Sinon on vérifie que la variable existe - if (!mCurentBlock.hasVariable(varName) && !mMain.hasGlobal(varName)) - throw new LeekCompilerException(mCompiler.lastWord(), Error.VARIABLE_NOT_EXISTS); - } - */ - // Maintenant on va savoir si on a affaire à un for(i in array) ou à un - // for(i=0;i<... - if (mCompiler.getWord().getWord().equals(":")) {// C'est un - // for(key:value in - // array) + + // Maintenant on va savoir si on a affaire à un for (i in array) ou à un for(i=0;i<... + if (mCompiler.getWord().getWord().equals(":")) { // C'est un for (key:value in array) mCompiler.skipWord(); boolean isValueDeclaration = false; - if (mCompiler.getWord().getWord().equals("var")) {// Il y a - // déclaration - // de la valeur + if (mCompiler.getWord().getWord().equals("var")) { // Il y a déclaration de la valeur isValueDeclaration = true; mCompiler.skipWord(); } @@ -418,16 +408,7 @@ private void forBlock() throws LeekCompilerException { if (mCompiler.getWord().getType() != WordParser.T_STRING) throw new LeekCompilerException(mCompiler.getWord(), Error.VARIABLE_NAME_EXPECTED); IAWord valueVarName = mCompiler.readWord(); - /* - if (isValueDeclaration) { - if (!isAvailable(valueVarName, true)) - throw new LeekCompilerException(mCompiler.lastWord(), Error.VARIABLE_NAME_UNAVAILABLE); - } else { - // Sinon on vérifie que la variable existe - if (!mCurentBlock.hasVariable(valueVarName) && !mMain.hasGlobal(valueVarName)) - throw new LeekCompilerException(mCompiler.lastWord(), Error.VARIABLE_NOT_EXISTS); - } - */ + if (!mCompiler.readWord().getWord().equals("in")) throw new LeekCompilerException(mCompiler.getWord(), Error.KEYWORD_IN_EXPECTED); @@ -443,9 +424,7 @@ private void forBlock() throws LeekCompilerException { block.setValueIterator(valueVarName, isValueDeclaration); forBlock = block; - } else if (mCompiler.getWord().getWord().equals("in")) {// C'est un - // for(i in - // array) + } else if (mCompiler.getWord().getWord().equals("in")) { // C'est un for (i in array) mCompiler.skipWord(); ForeachBlock block = new ForeachBlock(mCurentBlock, mMain, isDeclaration, mLine, mAI, reference1); @@ -458,8 +437,7 @@ private void forBlock() throws LeekCompilerException { block.setIterator(varName, isDeclaration); forBlock = block; - } else if (mCompiler.getWord().getWord().equals("=")) {// C'est un - // for(i=0;i<1;i++) + } else if (mCompiler.getWord().getWord().equals("=")) { // C'est un for (i=0;i<1;i++) mCompiler.skipWord(); ForBlock block = new ForBlock(mCurentBlock, mMain, mLine, mAI); @@ -487,8 +465,7 @@ private void forBlock() throws LeekCompilerException { // } AbstractExpression incrementation = readExpression(); - // Attention si l'incrémentation n'est pas une expression Java fait - // la gueule ! + // Attention si l'incrémentation n'est pas une expression Java fait la gueule ! if (incrementation != null && (incrementation instanceof LeekVariable || (incrementation instanceof LeekExpression && ((LeekExpression) incrementation).getOperator() == -1))) { throw new LeekCompilerException(mCompiler.lastWord(), Error.UNCOMPLETE_EXPRESSION); @@ -1077,11 +1054,14 @@ private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerExcepti } mCompiler.skipWord(); } - if (mCompiler.getWord().getType() != WordParser.T_STRING) + if (mCompiler.getWord().getType() != WordParser.T_STRING) { throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_EXPECTED); - // if (!isAvailable(mCompiler.getWord().getWord(), true)) - // throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_UNAVAILABLE); - block.addParameter(mCompiler.readWord(), is_reference); + } + var parameter = mCompiler.readWord(); + if (block.hasParameter(parameter.getWord())) { + throw new LeekCompilerException(parameter, Error.PARAMETER_NAME_UNAVAILABLE); + } + block.addParameter(parameter, is_reference); if (mCompiler.getWord().getType() == WordParser.T_VIRG) mCompiler.skipWord(); } diff --git a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java index d4f03469..23aff421 100644 --- a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java @@ -46,6 +46,13 @@ public void addParameter(IAWord token, boolean is_reference) { addVariable(new LeekVariable(token, VariableType.ARGUMENT)); } + public boolean hasParameter(String name) { + for (var parameter : mParameters) { + if (parameter.equals(name)) return true; + } + return false; + } + @Override public String getCode() { String str = "function anonymous" + mId + "("; diff --git a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java index 56b80940..f891eba2 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java @@ -1,12 +1,15 @@ package leekscript.compiler.bloc; import leekscript.compiler.AIFile; +import leekscript.compiler.AnalyzeError; import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; +import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.common.Error; public class ForeachBlock extends AbstractLeekBlock { @@ -22,7 +25,7 @@ public ForeachBlock(AbstractLeekBlock parent, MainLeekBlock main, boolean isDecl } public void setIterator(IAWord iterator, boolean declaration) { - if (declaration) addVariable(new LeekVariable(iterator, VariableType.LOCAL)); + // if (declaration) addVariable(new LeekVariable(iterator, VariableType.LOCAL)); mIterator = iterator; } @@ -73,8 +76,18 @@ public int getEndBlock() { public void analyze(WordCompiler compiler) { AbstractLeekBlock initialBlock = compiler.getCurrentBlock(); compiler.setCurrentBlock(this); + // Si c'est une déclaration on vérifie que le nom est disponnible if (mIsDeclaration) { - this.addVariable(new LeekVariable(mIterator, VariableType.LOCAL)); + if ((compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(mIterator.getWord()) || compiler.getMainBlock().hasUserFunction(mIterator.getWord(), true))) || compiler.getCurrentBlock().hasVariable(mIterator.getWord())) { + compiler.addError(new AnalyzeError(mIterator, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); + } else { + this.addVariable(new LeekVariable(mIterator, VariableType.LOCAL)); + } + } else { + var v = compiler.getCurrentBlock().getVariable(mIterator.getWord(), true); + if (v == null) { + compiler.addError(new AnalyzeError(mIterator, AnalyzeErrorLevel.ERROR, Error.UNKNOWN_VARIABLE_OR_FUNCTION)); + } } mArray.analyze(compiler); compiler.setCurrentBlock(initialBlock); diff --git a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java index 1214fe49..a48c9f0e 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java @@ -1,20 +1,23 @@ package leekscript.compiler.bloc; import leekscript.compiler.AIFile; +import leekscript.compiler.AnalyzeError; import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; +import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.common.Error; public class ForeachKeyBlock extends AbstractLeekBlock { - private String mIterator; + private IAWord mIterator; private AbstractExpression mArray; private boolean mIsDeclaration = false; - private String mKeyIterator = null; + private IAWord mKeyIterator = null; private boolean mIsKeyDeclaration = false; private boolean mKeyReference = false; private boolean mValueReference = false; @@ -28,13 +31,13 @@ public ForeachKeyBlock(AbstractLeekBlock parent, MainLeekBlock main, boolean isK } public void setValueIterator(IAWord iterator, boolean declaration) { - if(declaration) addVariable(new LeekVariable(iterator, VariableType.LOCAL)); - mIterator = iterator.getWord(); + // if(declaration) addVariable(new LeekVariable(iterator, VariableType.LOCAL)); + mIterator = iterator; } public void setKeyIterator(IAWord iterator, boolean declaration) { - if(declaration) addVariable(new LeekVariable(iterator, VariableType.LOCAL)); - mKeyIterator = iterator.getWord(); + // if(declaration) addVariable(new LeekVariable(iterator, VariableType.LOCAL)); + mKeyIterator = iterator; } public void setArray(AbstractExpression exp) { @@ -53,8 +56,8 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { String var = "i" + block_count; String ar = "ar" + block_count; - String key_iterator = mainblock.hasGlobal(mKeyIterator) ? ("globale_" + mKeyIterator) : ("user_" + mKeyIterator); - String val_iterator = mainblock.hasGlobal(mIterator) ? ("globale_" + mIterator) : ("user_" + mIterator); + String key_iterator = mainblock.hasGlobal(mKeyIterator.getWord()) ? ("globale_" + mKeyIterator) : ("user_" + mKeyIterator); + String val_iterator = mainblock.hasGlobal(mIterator.getWord()) ? ("globale_" + mIterator) : ("user_" + mIterator); writer.addCode("final AbstractLeekValue " + ar + " = "); mArray.writeJavaCode(mainblock, writer); writer.addCode(".getValue();"); @@ -104,6 +107,34 @@ public int getEndBlock() { public void analyze(WordCompiler compiler) { AbstractLeekBlock initialBlock = compiler.getCurrentBlock(); compiler.setCurrentBlock(this); + + // Si c'est une déclaration on vérifie que le nom est disponnible + if (mIsKeyDeclaration) { + if ((compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(mKeyIterator.getWord()) || compiler.getMainBlock().hasUserFunction(mKeyIterator.getWord(), true))) || compiler.getCurrentBlock().hasVariable(mKeyIterator.getWord())) { + compiler.addError(new AnalyzeError(mKeyIterator, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); + } else { + this.addVariable(new LeekVariable(mKeyIterator, VariableType.LOCAL)); + } + } else { + var v = compiler.getCurrentBlock().getVariable(mKeyIterator.getWord(), true); + if (v == null) { + compiler.addError(new AnalyzeError(mKeyIterator, AnalyzeErrorLevel.ERROR, Error.UNKNOWN_VARIABLE_OR_FUNCTION)); + } + } + // Si c'est une déclaration on vérifie que le nom est disponnible + if (mIsDeclaration) { + if ((compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(mIterator.getWord()) || compiler.getMainBlock().hasUserFunction(mIterator.getWord(), true))) || compiler.getCurrentBlock().hasVariable(mIterator.getWord())) { + compiler.addError(new AnalyzeError(mIterator, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); + } else { + this.addVariable(new LeekVariable(mIterator, VariableType.LOCAL)); + } + } else { + var v = compiler.getCurrentBlock().getVariable(mIterator.getWord(), true); + if (v == null) { + compiler.addError(new AnalyzeError(mIterator, AnalyzeErrorLevel.ERROR, Error.UNKNOWN_VARIABLE_OR_FUNCTION)); + } + } + mArray.analyze(compiler); compiler.setCurrentBlock(initialBlock); super.analyze(compiler); diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index 3b862a7b..4e46ac02 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -45,5 +45,7 @@ public void run() { section("Modify argument"); code("function test(x) { x += 10 return x } return test(5)").equals("15"); code("var a = [1, 2, 3] function test(x) { push(x, 10) return x } return [a, test([])]").equals("[[1, 2, 3], [10]]"); + + code("function f(arg, arg) { return arg } return f(1, 2)").equals("1"); } } diff --git a/src/test/java/test/TestLoops.java b/src/test/java/test/TestLoops.java index 95807270..9f4dc3cd 100644 --- a/src/test/java/test/TestLoops.java +++ b/src/test/java/test/TestLoops.java @@ -113,6 +113,7 @@ public void run() { code("var s = 0 for (var i = 0; i < 10; i += 1) { var j = [] while (count(j) < 10) { push(j, 'a') s++ }} return s;").equals("100"); code("var s = [] var i = 3 while (i--) { for (var j = 0; j < 2; ++j) { push(s, j) }} return s;").equals("[0, 1, 0, 1, 0, 1]"); code("var s = [] var i = 3 var j while (i--) { for (j = 0; j < 2; ++j) { push(s, j) }} return s;").equals("[0, 1, 0, 1, 0, 1]"); + code("for (var x in [1, 2, 3]) { for (var x = 0; x < 10; ++x) { } }").equals("null"); header("Foreach loops"); section("Empty containers"); @@ -159,6 +160,9 @@ public void run() { section("Foreach - double"); code("var r = [] for (var x in [1, 2, 3]) { for (var y in [4, 5, 6]) { push(r, x * y) }} return r;").equals("[4, 5, 6, 8, 10, 12, 12, 15, 18]"); // code("var r = [] for x in ['a', 'b', 'c'] { for y in [4, 5, 6] { r += x * y }} r").equals("['aaaa', 'aaaaa', 'aaaaaa', 'bbbb', 'bbbbb', 'bbbbbb', 'cccc', 'ccccc', 'cccccc']"); + code("for (var x in [1, 2, 3]) { for (var x in [4, 5, 6]) { } }").equals("null"); + code("for (var x : var y1 in [1, 2, 3]) { for (var x : var y2 in [4, 5, 6]) { } }").equals("null"); + code("for (var x1 : var y in [1, 2, 3]) { for (var x2 : var y in [4, 5, 6]) { } }").equals("null"); section("Foreach - mix"); // code("var n = 3 while (n--) { var r = [] for x in [1, 2, 3] { r += x } print(r) }").output("[1, 2, 3]\n[1, 2, 3]\n[1, 2, 3]\n"); diff --git a/src/test/java/test/TestNumber.java b/src/test/java/test/TestNumber.java index fbeb5b3c..d3b58d14 100644 --- a/src/test/java/test/TestNumber.java +++ b/src/test/java/test/TestNumber.java @@ -608,7 +608,7 @@ public void run() throws Exception { section("Not a statement errors"); code("null; return null;").equals("null"); code("(null); return null;").equals("null"); - code("((null)); return null;").equals("null"); + DISABLED_code("((null)); return null;").equals("null"); code("true; return null;").equals("null"); code("false; return null;").equals("null"); code("'salut'; return null;").equals("null"); From dc899e06bd099df6e94e073916d3830060e27eb2 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 12 Jun 2021 11:35:21 +0200 Subject: [PATCH 172/319] [error] Test errors --- src/main/java/leekscript/common/Error.java | 2 +- src/test/java/test/TestComments.java | 4 ++- src/test/java/test/TestCommon.java | 32 +++++++++++++++------- src/test/java/test/TestFunction.java | 4 ++- src/test/java/test/TestLoops.java | 10 ++++--- 5 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/main/java/leekscript/common/Error.java b/src/main/java/leekscript/common/Error.java index 0e4e4287..f4be8605 100644 --- a/src/main/java/leekscript/common/Error.java +++ b/src/main/java/leekscript/common/Error.java @@ -1,7 +1,7 @@ package leekscript.common; public enum Error { - UNKNOWN, + NONE, FUNCTION_NAME_UNAVAILABLE, // 1 PARAMETER_NAME_UNAVAILABLE, // 2 OPENING_PARENTHESIS_EXPECTED, // 3 diff --git a/src/test/java/test/TestComments.java b/src/test/java/test/TestComments.java index a2732d0c..80a3e713 100644 --- a/src/test/java/test/TestComments.java +++ b/src/test/java/test/TestComments.java @@ -2,6 +2,8 @@ package test; +import leekscript.common.Error; + public class TestComments extends TestCommon { public void run() throws Exception { @@ -9,7 +11,7 @@ public void run() throws Exception { section("Comments"); code("// basic; return 12;").equals("null"); code("/* basic; */ return 12;").equals("12"); - code_v10("/*// basic; */ return 12;").error(); + code_v10("/*// basic; */ return 12;").error(Error.OPERATOR_UNEXPECTED); code_v11("/*// basic; */ return 12;").equals("12"); } } diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index e4779be4..56c6ed2e 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -4,12 +4,13 @@ import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Locale; import leekscript.compiler.LeekScript; +import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.runner.AI; +import leekscript.common.Error; public class TestCommon { @@ -52,15 +53,17 @@ public boolean check(Result result) { return result.result.equals(expected); } public String getExpected() { return expected; } + public String getResult(Result result) { return result.result; } }); } - public void error() { + public void error(Error type) { run(version, new Checker() { public boolean check(Result result) { - return result.result.equals("error"); + return result.error == type; } - public String getExpected() { return "error"; } + public String getExpected() { return type.name(); } + public String getResult(Result result) { return result.error.name(); } }); } @@ -79,6 +82,7 @@ public boolean check(Result result) { } } public String getExpected() { return String.valueOf(expected); } + public String getResult(Result result) { return result.result; } }); } @@ -121,18 +125,22 @@ public void run_version(int version, Checker checker) { TestCommon.execution_time += exec_time / 1000; var vs = v.getString(ai); - result = new Result(vs, (int) ai.getOperations(), exec_time); + result = new Result(vs, Error.NONE, (int) ai.getOperations(), exec_time); + } catch (LeekCompilerException e) { + // e.printStackTrace(); + // System.out.println("Error = " + e.getError()); + result = new Result("error", e.getError(), 0, 0); } catch (Exception e) { - e.printStackTrace(); - result = new Result("error", 0, 0); + // e.printStackTrace(); + result = new Result("error", Error.NONE, 0, 0); } if (checker.check(result)) { - System.out.println(GREEN_BOLD + " [OK] " + END_COLOR + "[v" + version + "] " + code + " === " + result.result + " " + C_GREY + compile_time + "ms + " + fn(result.exec_time) + "µs" + ", " + fn(result.operations) + " ops" + END_COLOR); + System.out.println(GREEN_BOLD + " [OK] " + END_COLOR + "[v" + version + "] " + code + " === " + checker.getResult(result) + " " + C_GREY + compile_time + "ms + " + fn(result.exec_time) + "µs" + ", " + fn(result.operations) + " ops" + END_COLOR); success++; } else { - var err = C_RED + "[FAIL] " + END_COLOR + "[v" + version + "] " + code + " =/= " + checker.getExpected() + " got " + result.result + "\n" + + var err = C_RED + "[FAIL] " + END_COLOR + "[v" + version + "] " + code + " =/= " + checker.getExpected() + " got " + checker.getResult(result) + "\n" + "/home/pierre/dev/leek-wars/server/daemon/generator-v1/leekscript-v1/ai/AI_" + aiID + ".java"; System.out.println(err); failedTests.add(err); @@ -142,19 +150,23 @@ public void run_version(int version, Checker checker) { public static class Result { String result; + Error error; int operations; long exec_time; - public Result(String result, int operations, long exec_time) { + public Result(String result, Error error, int operations, long exec_time) { this.result = result; this.operations = operations; this.exec_time = exec_time; + this.error = error; } } public static interface Checker { public boolean check(Result result); + public String getResult(Result result); + public String getExpected(); } diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index 4e46ac02..8297b170 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -1,5 +1,7 @@ package test; +import leekscript.common.Error; + public class TestFunction extends TestCommon { public void run() { @@ -46,6 +48,6 @@ public void run() { code("function test(x) { x += 10 return x } return test(5)").equals("15"); code("var a = [1, 2, 3] function test(x) { push(x, 10) return x } return [a, test([])]").equals("[[1, 2, 3], [10]]"); - code("function f(arg, arg) { return arg } return f(1, 2)").equals("1"); + code("function f(arg, arg) { return arg } return f(1, 2)").error(Error.PARAMETER_NAME_UNAVAILABLE); } } diff --git a/src/test/java/test/TestLoops.java b/src/test/java/test/TestLoops.java index 9f4dc3cd..d11623dc 100644 --- a/src/test/java/test/TestLoops.java +++ b/src/test/java/test/TestLoops.java @@ -1,5 +1,7 @@ package test; +import leekscript.common.Error; + public class TestLoops extends TestCommon { public void run() { @@ -113,7 +115,7 @@ public void run() { code("var s = 0 for (var i = 0; i < 10; i += 1) { var j = [] while (count(j) < 10) { push(j, 'a') s++ }} return s;").equals("100"); code("var s = [] var i = 3 while (i--) { for (var j = 0; j < 2; ++j) { push(s, j) }} return s;").equals("[0, 1, 0, 1, 0, 1]"); code("var s = [] var i = 3 var j while (i--) { for (j = 0; j < 2; ++j) { push(s, j) }} return s;").equals("[0, 1, 0, 1, 0, 1]"); - code("for (var x in [1, 2, 3]) { for (var x = 0; x < 10; ++x) { } }").equals("null"); + code("for (var x in [1, 2, 3]) { for (var x = 0; x < 10; ++x) { } }").error(Error.VARIABLE_NAME_UNAVAILABLE); header("Foreach loops"); section("Empty containers"); @@ -160,9 +162,9 @@ public void run() { section("Foreach - double"); code("var r = [] for (var x in [1, 2, 3]) { for (var y in [4, 5, 6]) { push(r, x * y) }} return r;").equals("[4, 5, 6, 8, 10, 12, 12, 15, 18]"); // code("var r = [] for x in ['a', 'b', 'c'] { for y in [4, 5, 6] { r += x * y }} r").equals("['aaaa', 'aaaaa', 'aaaaaa', 'bbbb', 'bbbbb', 'bbbbbb', 'cccc', 'ccccc', 'cccccc']"); - code("for (var x in [1, 2, 3]) { for (var x in [4, 5, 6]) { } }").equals("null"); - code("for (var x : var y1 in [1, 2, 3]) { for (var x : var y2 in [4, 5, 6]) { } }").equals("null"); - code("for (var x1 : var y in [1, 2, 3]) { for (var x2 : var y in [4, 5, 6]) { } }").equals("null"); + code("for (var x in [1, 2, 3]) { for (var x in [4, 5, 6]) { } }").error(Error.VARIABLE_NAME_UNAVAILABLE); + code("for (var x : var y1 in [1, 2, 3]) { for (var x : var y2 in [4, 5, 6]) { } }").error(Error.VARIABLE_NAME_UNAVAILABLE); + code("for (var x1 : var y in [1, 2, 3]) { for (var x2 : var y in [4, 5, 6]) { } }").error(Error.VARIABLE_NAME_UNAVAILABLE); section("Foreach - mix"); // code("var n = 3 while (n--) { var r = [] for x in [1, 2, 3] { r += x } print(r) }").output("[1, 2, 3]\n[1, 2, 3]\n[1, 2, 3]\n"); From b15a311d74fd80da55a14129dcb1c955077b8ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Wed, 23 Jun 2021 11:05:00 +0200 Subject: [PATCH 173/319] Update build.yml --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c68fb341..6bd801f5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,4 +22,6 @@ jobs: java-version: '11' distribution: 'adopt' - name: Build - run: gradle build + run: | + export LANG=fr_FR.utf8 + gradle build From 08d472de81056e18b1c25af407cf56173617c509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Wed, 23 Jun 2021 11:09:56 +0200 Subject: [PATCH 174/319] Update build.yml --- .github/workflows/build.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6bd801f5..e4fec08f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,10 @@ jobs: with: java-version: '11' distribution: 'adopt' - - name: Build + - name: Setup locale run: | - export LANG=fr_FR.utf8 - gradle build + locale-gen fr_FR + locale-gen fr_FR.UTF-8 + update-locale + - name: Build + run: gradle build From 04f4f53c7cbf3175cb676c897b16b57f57dd6d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Wed, 23 Jun 2021 11:10:38 +0200 Subject: [PATCH 175/319] Update build.yml --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e4fec08f..d2b7f237 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,8 +23,8 @@ jobs: distribution: 'adopt' - name: Setup locale run: | - locale-gen fr_FR - locale-gen fr_FR.UTF-8 - update-locale + sudo locale-gen fr_FR + sudo locale-gen fr_FR.UTF-8 + sudo update-locale - name: Build run: gradle build From 369e328d5ed1e6a13b31a3586a0de7fad84406c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Wed, 23 Jun 2021 11:12:14 +0200 Subject: [PATCH 176/319] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d2b7f237..72d2aa0e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,8 +23,8 @@ jobs: distribution: 'adopt' - name: Setup locale run: | - sudo locale-gen fr_FR sudo locale-gen fr_FR.UTF-8 sudo update-locale + export LANG=fr_FR.utf8 - name: Build run: gradle build From f790481debb33d1b5cbf7e8f25cc0191c50f9c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Wed, 23 Jun 2021 11:14:43 +0200 Subject: [PATCH 177/319] Update build.yml --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 72d2aa0e..ff1a8511 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,5 +26,6 @@ jobs: sudo locale-gen fr_FR.UTF-8 sudo update-locale export LANG=fr_FR.utf8 + export JAVA_TOOL_OPTIONS=-Duser.language=fr-FR - name: Build run: gradle build From f7c8bc9eba1a6e3f4be11b6d41bb0c4852ab8d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Wed, 23 Jun 2021 11:16:55 +0200 Subject: [PATCH 178/319] Update build.yml --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ff1a8511..fd17fc94 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,5 +27,6 @@ jobs: sudo update-locale export LANG=fr_FR.utf8 export JAVA_TOOL_OPTIONS=-Duser.language=fr-FR + export _JAVA_OPTIONS=-Duser.language=fr - name: Build run: gradle build From 7fe5ae13080531851d49d5d730ca762b511301cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Wed, 23 Jun 2021 11:20:44 +0200 Subject: [PATCH 179/319] Update build.yml --- .github/workflows/build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fd17fc94..cb69b974 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,8 @@ jobs: sudo locale-gen fr_FR.UTF-8 sudo update-locale export LANG=fr_FR.utf8 - export JAVA_TOOL_OPTIONS=-Duser.language=fr-FR - export _JAVA_OPTIONS=-Duser.language=fr + export JAVA_TOOL_OPTIONS=-Duser.language=fr -Duser.region=FR + export _JAVA_OPTIONS=-Duser.language=fr -Duser.region=FR + export JAVA_ARGS=-Duser.language=fr -Duser.region=FR - name: Build run: gradle build From 2125298f3bbc61af0cba0ba98705c8b6318d3f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Wed, 23 Jun 2021 11:21:25 +0200 Subject: [PATCH 180/319] Update build.yml --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cb69b974..ca77d1df 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,8 +26,8 @@ jobs: sudo locale-gen fr_FR.UTF-8 sudo update-locale export LANG=fr_FR.utf8 - export JAVA_TOOL_OPTIONS=-Duser.language=fr -Duser.region=FR - export _JAVA_OPTIONS=-Duser.language=fr -Duser.region=FR - export JAVA_ARGS=-Duser.language=fr -Duser.region=FR + export JAVA_TOOL_OPTIONS="-Duser.language=fr -Duser.region=FR" + export _JAVA_OPTIONS="-Duser.language=fr -Duser.region=FR" + export JAVA_ARGS="-Duser.language=fr -Duser.region=FR" - name: Build run: gradle build From 3ed32e3014cf3800144974dd091950cc86e6c811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20Laupr=C3=AAtre?= Date: Wed, 23 Jun 2021 11:22:24 +0200 Subject: [PATCH 181/319] Update build.yml --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ca77d1df..23d5f8c9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,5 +29,6 @@ jobs: export JAVA_TOOL_OPTIONS="-Duser.language=fr -Duser.region=FR" export _JAVA_OPTIONS="-Duser.language=fr -Duser.region=FR" export JAVA_ARGS="-Duser.language=fr -Duser.region=FR" + locale - name: Build run: gradle build From b19a56005e4cdf57216d8833eec84b814848d603 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 23 Jun 2021 11:33:42 +0200 Subject: [PATCH 182/319] set locale --- src/test/java/test/TestMain.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/java/test/TestMain.java b/src/test/java/test/TestMain.java index d110d2ee..86103ab6 100644 --- a/src/test/java/test/TestMain.java +++ b/src/test/java/test/TestMain.java @@ -1,10 +1,24 @@ package test; +import java.util.Locale; + import org.junit.Assert; public class TestMain { public static void main(String[] args) throws Exception { + + Locale.setDefault(Locale.FRENCH); + + Locale currentLocale = Locale.getDefault(); + System.out.println("Locale = "); + System.out.println(currentLocale.getDisplayLanguage()); + System.out.println(currentLocale.getDisplayCountry()); + System.out.println(currentLocale.getLanguage()); + System.out.println(currentLocale.getCountry()); + System.out.println(System.getProperty("user.country")); + System.out.println(System.getProperty("user.language")); + System.out.println("Start tests..."); // new TestCommon().code_v11("return 5 + 5;").equals("10"); From 37092713cc190a6eb727041b40fbe4d0d1be20ea Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 6 Apr 2021 22:51:56 +0200 Subject: [PATCH 183/319] [compiler] Formatting --- .../java/leekscript/compiler/WordParser.java | 42 +++++++++---------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index fffe3869..f57a0eb7 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -71,9 +71,9 @@ public void compile(WordCompiler compiler) throws LeekCompilerException { int length = code.length(); for(int i = 0; i < code.length(); i++){ c = code.charAt(i); - if(c == '\r') continue; + if (c == '\r') continue; // Compteur caractères/lignes - if(c == '\n') { + if (c == '\n') { if (type != T_NOTHING) { newWord(word, type); type = T_NOTHING; @@ -84,30 +84,29 @@ public void compile(WordCompiler compiler) throws LeekCompilerException { comment_line = false; } else char_counter++; - if((c == '"' || c == '\'') && !comment_block && !comment_line){ - if(type == T_NOTHING){ + if ((c == '"' || c == '\'') && !comment_block && !comment_line) { + if (type == T_NOTHING) { word = ""; type = T_VAR_STRING; opener = c; } - else if(type == T_VAR_STRING && opener == c){ + else if (type == T_VAR_STRING && opener == c) { boolean isEscaped = false; - for(int j = word.length() - 1; j >= 0; j--){ + for (int j = word.length() - 1; j >= 0; j--) { if(word.charAt(j) == '\\') isEscaped = !isEscaped; else break; } - if(isEscaped){ + if (isEscaped) { word = word.substring(0, word.length() - 1); word += c; - } - else{ + } else { newWord(word, type); word = ""; type = T_NOTHING; } } - else if(type == T_VAR_STRING) word += c; - else{ + else if (type == T_VAR_STRING) word += c; + else { newWord(word, type); word = ""; opener = c; @@ -115,7 +114,7 @@ else if(type == T_VAR_STRING && opener == c){ } continue; } - if(type == T_VAR_STRING){ + if (type == T_VAR_STRING) { word += c; continue; } @@ -136,21 +135,18 @@ else if (c == '/' && length > i + 1 && code.charAt(i + 1) == '*') { if (version >= 11) i++; continue; } - if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_'){ - if(type == T_NOTHING){ + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') { + if (type == T_NOTHING) { word += c; type = T_STRING; - } - else if(type == T_STRING || type == T_VAR_STRING){ + } else if (type == T_STRING || type == T_VAR_STRING) { word += c; - } - else{ - if(type == T_OPERATOR){ + } else { + if (type == T_OPERATOR) { newWord(word, type); word = "" + c; type = T_STRING; - } - else if(type == T_NUMBER){ + } else if (type == T_NUMBER) { throw new LeekCompilerException(mAI, line_counter, char_counter, word, Error.INVALID_NUMBER); } } @@ -175,7 +171,7 @@ else if(c == ':'){ word = ""; type = T_NOTHING; } - else if(c == '.'){ + else if(c == '.') { if (type == T_VAR_STRING) { word += c; } else if (type == T_NUMBER) { @@ -344,7 +340,7 @@ else if(c == ','){ } newWord(",", T_VIRG); } - else{ + else { // Tout autre caractère if(type == T_VAR_STRING){ word += c; From dc686b3b0dd1255fec511ab2946b4f891b469bbc Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 25 May 2021 21:43:52 +0200 Subject: [PATCH 184/319] [error] Add invalid operator error --- src/main/java/leekscript/common/Error.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/leekscript/common/Error.java b/src/main/java/leekscript/common/Error.java index f4be8605..499519e9 100644 --- a/src/main/java/leekscript/common/Error.java +++ b/src/main/java/leekscript/common/Error.java @@ -78,4 +78,5 @@ public enum Error { INSTANCEOF_MUST_BE_CLASS, // 74 NOT_ITERABLE, // 75 STACKOVERFLOW, // 76 + INVALID_OPERATOR // 77 } \ No newline at end of file From 63a78636979dfe84d37f11ed96e31b3e27c82bb9 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 25 May 2021 21:46:23 +0200 Subject: [PATCH 185/319] [compiler] Improve Java compilation --- .../java/leekscript/compiler/IALoader.java | 33 ---- .../leekscript/compiler/JavaCompiler.java | 43 ----- .../java/leekscript/compiler/LeekScript.java | 177 ++++++++++++------ .../leekscript/compiler/SimpleClassFile.java | 32 ++++ .../compiler/SimpleFileManager.java | 36 ++++ .../leekscript/compiler/SimpleSourceFile.java | 20 ++ .../compiler/bloc/MainLeekBlock.java | 3 +- src/main/java/leekscript/runner/AI.java | 5 +- src/test/java/test/TestAI.java | 2 +- 9 files changed, 211 insertions(+), 140 deletions(-) delete mode 100644 src/main/java/leekscript/compiler/IALoader.java delete mode 100644 src/main/java/leekscript/compiler/JavaCompiler.java create mode 100644 src/main/java/leekscript/compiler/SimpleClassFile.java create mode 100644 src/main/java/leekscript/compiler/SimpleFileManager.java create mode 100644 src/main/java/leekscript/compiler/SimpleSourceFile.java diff --git a/src/main/java/leekscript/compiler/IALoader.java b/src/main/java/leekscript/compiler/IALoader.java deleted file mode 100644 index 37c597f1..00000000 --- a/src/main/java/leekscript/compiler/IALoader.java +++ /dev/null @@ -1,33 +0,0 @@ -package leekscript.compiler; - -import java.io.File; -import java.net.URL; -import java.net.URLClassLoader; - -import leekscript.ErrorManager; -import leekscript.runner.AI; - -public class IALoader { - - @SuppressWarnings("resource") - public static AI loadAI(String file, String classname) { - - File f = new File(file); - if (!f.exists()) - return null; - - URLClassLoader loader = null; - try { - // Not closed because we need to load internal classes, like Class$1.class etc. - loader = new URLClassLoader(new URL[] { f.toURI().toURL() }, new ClassLoader() {}); - - if (loader != null) { - Class c = loader.loadClass(classname); - return (AI) c.getDeclaredConstructor().newInstance(); - } - } catch (Exception e) { - ErrorManager.exception(e); - } - return null; - } -} diff --git a/src/main/java/leekscript/compiler/JavaCompiler.java b/src/main/java/leekscript/compiler/JavaCompiler.java deleted file mode 100644 index 54c506f9..00000000 --- a/src/main/java/leekscript/compiler/JavaCompiler.java +++ /dev/null @@ -1,43 +0,0 @@ -package leekscript.compiler; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; - -import javax.tools.ToolProvider; - -public class JavaCompiler { - - public final static int INIT = 0; - public final static int RUNNING = 1; - public final static int END = 2; - public final static int ERROR = 3; - private final File mInput; - private int mStatus = 0; - - public JavaCompiler(File input) { - mInput = input; - } - - public void compile() throws Exception { - if (mStatus != INIT) - return; - mStatus = RUNNING; - if (!mInput.exists()) { - mStatus = ERROR; - return; - } - - javax.tools.JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - String classpath = JavaCompiler.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath(); - - compiler.run(null, System.out, System.out, "-encoding", "utf8", "-classpath", classpath, mInput.getPath()); - // System.out.println("Javac result = " + result); - } - - public static int getStatus() { - return 0; - } -} diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index b1de64f3..e4aa45d5 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -1,13 +1,24 @@ package leekscript.compiler; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.StringWriter; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLClassLoader; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; import java.util.Random; -import leekscript.LSException; +import javax.tools.JavaCompiler; +import javax.tools.ToolProvider; + import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.compiler.resolver.FileSystemContext; import leekscript.compiler.resolver.FileSystemResolver; @@ -15,7 +26,6 @@ import leekscript.compiler.resolver.ResolverContext; import leekscript.runner.AI; import leekscript.runner.values.AbstractLeekValue; -import leekscript.runner.values.ArrayLeekValue; public class LeekScript { @@ -24,6 +34,25 @@ public class LeekScript { private static Resolver defaultResolver = new FileSystemResolver(); private static Resolver customResolver = null; + private static String classpath; + private static List arguments = new ArrayList<>(); + private static JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + private static SimpleFileManager fileManager = new SimpleFileManager(compiler.getStandardFileManager(null, null, null)); + private static URLClassLoader urlLoader; + private static HashMap> aiCache = new HashMap<>(); + static { + try { + classpath = LeekScript.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath(); + arguments.addAll(Arrays.asList("-classpath", classpath, "-nowarn")); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + try { + urlLoader = new URLClassLoader(new URL[] { new File("ai").toURI().toURL() }, new ClassLoader() {}); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } private static RandomGenerator defaultRandomGenerator = new RandomGenerator() { private Random random = new Random(); @@ -46,9 +75,9 @@ public double getDouble() { } }; - public static AI compileFile(String filepath, String AIClass, boolean nocache) throws LeekScriptException, LeekCompilerException, IOException { + public static AI compileFile(String filepath, String AIClass, boolean useClassCache) throws LeekScriptException, LeekCompilerException, IOException { AIFile ai = getResolver().resolve(filepath, null); - return compile(ai, AIClass, nocache); + return compile(ai, AIClass, useClassCache); } public static AI compileFile(String filepath, String AIClass, int version) throws LeekScriptException, LeekCompilerException, IOException { @@ -57,51 +86,26 @@ public static AI compileFile(String filepath, String AIClass, int version) throw return compile(ai, AIClass, true); } - public static AI compileFileContext(String filepath, String AIClass, ResolverContext context, boolean nocache) throws LeekScriptException, LeekCompilerException, IOException { + public static AI compileFileContext(String filepath, String AIClass, ResolverContext context, boolean useClassCache) throws LeekScriptException, LeekCompilerException, IOException { AIFile ai = getResolver().resolve(filepath, context); - return compile(ai, AIClass, nocache); + return compile(ai, AIClass, useClassCache); } public static AI compileSnippet(String snippet, String AIClass) throws LeekScriptException, LeekCompilerException, IOException { - AIFile ai = new AIFile("", snippet, System.currentTimeMillis(), 11, null); - return compile(ai, AIClass, false); + return compileSnippet(snippet, AIClass, 11); } public static AI compileSnippet(String snippet, String AIClass, int version) throws LeekScriptException, LeekCompilerException, IOException { - AIFile ai = new AIFile("", snippet, System.currentTimeMillis(), version, null); + long ai_id = id++; + AIFile ai = new AIFile("", snippet, System.currentTimeMillis(), version, null, (int) ai_id); return compile(ai, AIClass, false); } - public static boolean testScript(String leek, String script, AbstractLeekValue s, String AIClass, boolean nocache) throws Exception { - AI ai = LeekScript.compileSnippet(script, AIClass); - AbstractLeekValue v = ai.runIA(); - if (v.equals(ai, s)) - return true; - ArrayLeekValue tab1 = v.getArray(); - ArrayLeekValue tab2 = s.getArray(); - if (tab1 != null && tab2 != null && tab1.size() == tab2.size()) { - int i = 0; - for (i = 0; i < tab1.size(); i++) { - if (!tab1.get(ai, i).equals(ai, tab2.get(ai, i))) { - throw new LSException(i, tab1.get(ai, i), tab2.get(ai, i)); - } - } - } else - System.out.println(v.getString(ai) + " -- " + s.getString(ai)); - return false; - } public static AbstractLeekValue runScript(String script, boolean nocache) throws Exception { return LeekScript.compileSnippet(script, "AI").runIA(); } - public static boolean testScript(String script, AbstractLeekValue s) throws Exception { - AI ai = LeekScript.compileSnippet(script, "AI"); - AbstractLeekValue v = ai.runIA(); - System.out.println(v.getString(ai)); - return v.equals(ai, s); - } - public static String runFile(String filename) throws Exception { AI ai = LeekScript.compileFile(filename, "AI", true); AbstractLeekValue v = ai.runIA(); @@ -125,45 +129,98 @@ public static RandomGenerator getRandom() { return defaultRandomGenerator; } - public static AI compile(AIFile file, String AIClass, boolean nocache) throws LeekScriptException, LeekCompilerException, IOException { + public static AI compile(AIFile file, String AIClass, boolean useClassCache) throws LeekScriptException, LeekCompilerException, IOException { new File(IA_PATH).mkdir(); String javaClassName = "AI_" + file.getId(); - String error = ""; + String fileName = javaClassName + ".java"; File compiled = new File(IA_PATH + javaClassName + ".class"); File java = new File(IA_PATH + javaClassName + ".java"); - if (!compiled.exists() || compiled.length() == 0 || compiled.lastModified() < file.getTimestamp() || nocache) { + // Utilisation du cache de class + if (useClassCache && compiled.exists() && compiled.length() != 0 && compiled.lastModified() > file.getTimestamp()) { + try { + var clazz = aiCache.get(javaClassName); + if (clazz == null) { + clazz = urlLoader.loadClass(javaClassName); + aiCache.put(javaClassName, clazz); + } + var ai = (AI) clazz.getDeclaredConstructor().newInstance(); + ai.setId(file.getId()); + return ai; + } catch (Exception e) { + e.printStackTrace(); + } + } - // On commence par la conversion LS->Java - String compiledJava = new IACompiler().compile(file, javaClassName, AIClass); + // On commence par la conversion LS->Java + long t = System.nanoTime(); + String compiledJava = new IACompiler().compile(file, javaClassName, AIClass); + long analyze_time = System.nanoTime() - t; - if (compiledJava.isEmpty()) { // Rien ne compile, pas normal - throw new LeekScriptException(LeekScriptException.CANT_COMPILE, "No java generated!"); + if (compiledJava.isEmpty()) { // Rien ne compile, pas normal + throw new LeekScriptException(LeekScriptException.CANT_COMPILE, "No java generated!"); + } + + // System.out.println(compiledJava); + + // Sauvegarde du code java + FileOutputStream javaOutput = new FileOutputStream(java); + javaOutput.write(compiledJava.getBytes(StandardCharsets.UTF_8)); + javaOutput.close(); + + try { + + t = System.nanoTime(); + fileManager.clear(); + var output = new StringWriter(); + var compilationUnits = Collections.singletonList(new SimpleSourceFile(fileName, compiledJava)); + var task = compiler.getTask(output, fileManager, null, arguments, null, compilationUnits); + + boolean result = task.call(); + long compile_time = System.nanoTime() - t; + + if (!result) { // Java compilation failed + throw new LeekScriptException(LeekScriptException.CANT_COMPILE, output.toString()); } - // Si on a maintenant du code java - FileOutputStream output = new FileOutputStream(java); - output.write(compiledJava.getBytes(StandardCharsets.UTF_8)); - output.close(); - // On va compiler le java maintenant - JavaCompiler compiler = new JavaCompiler(java); - int status = JavaCompiler.INIT; + t = System.nanoTime(); + ClassLoader classLoader = new ClassLoader() { + @Override + protected Class findClass(String name) throws ClassNotFoundException { + var bytes = fileManager.get(name).getCompiledBinaries(); + return defineClass(name, bytes, 0, bytes.length); + } + }; - try { - compiler.compile(); - status = JavaCompiler.getStatus(); - } catch (Exception e) { - error = e.getMessage(); - status = JavaCompiler.ERROR; + // Load inner classes before + for (var compiledClass : fileManager.getCompiled().values()) { + + if (useClassCache) { // Save bytecode + var classFile = new FileOutputStream(IA_PATH + compiledClass.getName() + ".class"); + classFile.write(compiledClass.getCompiledBinaries()); + classFile.close(); + } + + if (compiledClass.getName().equals(javaClassName)) continue; + classLoader.loadClass(compiledClass.getName()); } - if (status == JavaCompiler.ERROR) { - throwException(error); + + // Load the main class + var clazz = classLoader.loadClass(javaClassName); + var ai = (AI) clazz.getDeclaredConstructor().newInstance(); + long load_time = System.nanoTime() - t; + + ai.setId(file.getId()); + + if (useClassCache) { + aiCache.put(javaClassName, clazz); } + return ai; + + } catch (Exception e) { + throw new LeekScriptException(LeekScriptException.CANT_COMPILE, e.getMessage()); } - AI ai = IALoader.loadAI(IA_PATH, javaClassName); - ai.setId(file.getId()); - return ai; } public static void throwException(String error) throws LeekScriptException { diff --git a/src/main/java/leekscript/compiler/SimpleClassFile.java b/src/main/java/leekscript/compiler/SimpleClassFile.java new file mode 100644 index 00000000..112df267 --- /dev/null +++ b/src/main/java/leekscript/compiler/SimpleClassFile.java @@ -0,0 +1,32 @@ +package leekscript.compiler; + +import javax.tools.SimpleJavaFileObject; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; + +/** Holds compiled byte code in a byte array */ +public class SimpleClassFile extends SimpleJavaFileObject { + + private ByteArrayOutputStream out; + private String name; + + public SimpleClassFile(String name) { + super(URI.create(name), Kind.CLASS); + this.name = name; + } + + @Override + public OutputStream openOutputStream() throws IOException { + return out = new ByteArrayOutputStream(); + } + + public byte[] getCompiledBinaries() { + return out.toByteArray(); + } + + public String getName() { + return name; + } +} \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/SimpleFileManager.java b/src/main/java/leekscript/compiler/SimpleFileManager.java new file mode 100644 index 00000000..257689b6 --- /dev/null +++ b/src/main/java/leekscript/compiler/SimpleFileManager.java @@ -0,0 +1,36 @@ +package leekscript.compiler; + +import java.util.HashMap; + +import javax.tools.FileObject; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +public class SimpleFileManager extends ForwardingJavaFileManager { + + private final HashMap compiled = new HashMap<>(); + + public SimpleFileManager(StandardJavaFileManager delegate) { + super(delegate); + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) { + var result = new SimpleClassFile(className); + compiled.put(className, result); + return result; + } + + public SimpleClassFile get(String name) { + return compiled.get(name); + } + + public void clear() { + compiled.clear(); + } + + public HashMap getCompiled() { + return compiled; + } +} \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/SimpleSourceFile.java b/src/main/java/leekscript/compiler/SimpleSourceFile.java new file mode 100644 index 00000000..59067236 --- /dev/null +++ b/src/main/java/leekscript/compiler/SimpleSourceFile.java @@ -0,0 +1,20 @@ +package leekscript.compiler; + +import javax.tools.SimpleJavaFileObject; +import java.net.URI; + +/** Exposes given test source to the compiler. */ +public class SimpleSourceFile extends SimpleJavaFileObject { + + private final String content; + + public SimpleSourceFile(String qualifiedClassName, String testSource) { + super(URI.create(qualifiedClassName), Kind.SOURCE); + content = testSource; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return content; + } +} \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index d7a02e28..9215f00e 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -186,8 +186,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { } // Constructor writer.addLine("public " + className + "() throws LeekRunException {"); - writer.addLine("super();"); - writer.addLine("mInstructions = " + mInstructions.size() + ";"); + writer.addLine("super(" + mInstructions.size() + ", " + mCompiler.getCurrentAI().getVersion() + ");"); for (var clazz : mUserClasses.values()) { clazz.createJava(this, writer); diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 019f4d6f..04fe10ee 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -32,13 +32,16 @@ public abstract class AI { protected String thisObject = null; protected int id; + protected int version; protected AILog logs; protected AI mUAI; protected int mInstructions; protected RandomGenerator randomGenerator; + public AI(int instructions, int version) { + this.mInstructions = instructions; + this.version = version; - public AI() { mUAI = this; logs = new AILog(); randomGenerator = LeekScript.getRandom(); diff --git a/src/test/java/test/TestAI.java b/src/test/java/test/TestAI.java index dff88303..493d3d38 100644 --- a/src/test/java/test/TestAI.java +++ b/src/test/java/test/TestAI.java @@ -7,7 +7,7 @@ public class TestAI extends AI { public TestAI() throws Exception { - super(); + super(0, 11); } @Override From a272080f70873dbf82a781d0f88def4a1e75be45 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 25 May 2021 21:58:53 +0200 Subject: [PATCH 186/319] [type] Add types and getOperations() --- src/main/java/leekscript/common/Type.java | 43 ++++++ .../java/leekscript/compiler/IACompiler.java | 4 +- .../java/leekscript/compiler/JavaWriter.java | 4 +- .../leekscript/compiler/WordCompiler.java | 75 +++++++---- .../compiler/bloc/AbstractLeekBlock.java | 7 +- .../compiler/bloc/AnonymousFunctionBlock.java | 23 +++- .../compiler/bloc/ClassMethodBlock.java | 5 + .../compiler/bloc/ConditionalBloc.java | 12 +- .../leekscript/compiler/bloc/ForBlock.java | 7 +- .../compiler/bloc/ForeachBlock.java | 10 +- .../compiler/bloc/ForeachKeyBlock.java | 25 +++- .../compiler/bloc/FunctionBlock.java | 18 ++- .../compiler/bloc/MainLeekBlock.java | 16 +++ .../expression/AbstractExpression.java | 15 ++- .../expression/LeekAnonymousFunction.java | 11 +- .../compiler/expression/LeekArray.java | 10 +- .../compiler/expression/LeekBoolean.java | 8 +- .../compiler/expression/LeekExpression.java | 126 ++++++++++++++---- .../expression/LeekExpressionFunction.java | 54 +++++++- .../compiler/expression/LeekGlobal.java | 46 ------- .../compiler/expression/LeekNull.java | 8 +- .../compiler/expression/LeekNumber.java | 16 ++- .../compiler/expression/LeekObjectAccess.java | 15 ++- .../compiler/expression/LeekParenthesis.java | 15 ++- .../compiler/expression/LeekString.java | 8 +- .../compiler/expression/LeekTabularValue.java | 20 ++- .../compiler/expression/LeekTernaire.java | 41 ++++-- .../compiler/expression/LeekVariable.java | 67 +++++++++- .../compiler/expression/Operators.java | 12 +- .../instruction/BlankInstruction.java | 5 + .../ClassDeclarationInstruction.java | 16 +++ .../instruction/LeekBreakInstruction.java | 5 + .../instruction/LeekContinueInstruction.java | 5 + .../LeekExpressionInstruction.java | 5 + .../LeekGlobalDeclarationInstruction.java | 7 +- .../compiler/instruction/LeekInstruction.java | 2 + .../instruction/LeekReturnInstruction.java | 5 + .../LeekVariableDeclarationInstruction.java | 60 +++++++-- .../leekscript/runner/CallableVersion.java | 14 ++ .../java/leekscript/runner/ILeekConstant.java | 4 +- .../java/leekscript/runner/ILeekFunction.java | 3 + .../java/leekscript/runner/LeekConstants.java | 48 ++++--- .../java/leekscript/runner/LeekFunctions.java | 15 +++ .../leekscript/runner/values/LeekValue.java | 54 ++++++++ src/test/java/test/TestFunction.java | 4 + 45 files changed, 769 insertions(+), 204 deletions(-) create mode 100644 src/main/java/leekscript/common/Type.java delete mode 100644 src/main/java/leekscript/compiler/expression/LeekGlobal.java create mode 100644 src/main/java/leekscript/runner/CallableVersion.java create mode 100644 src/main/java/leekscript/runner/values/LeekValue.java diff --git a/src/main/java/leekscript/common/Type.java b/src/main/java/leekscript/common/Type.java new file mode 100644 index 00000000..3118027d --- /dev/null +++ b/src/main/java/leekscript/common/Type.java @@ -0,0 +1,43 @@ +package leekscript.common; + +public class Type { + + public static Type ANY = new Type("any", '?'); + public static Type NULL = new Type("null", 'u'); + public static Type BOOL = new Type("bool", 'b'); + public static Type NUMBER = new Type("number", 'n'); + public static Type INT = new Type("int", 'i'); + public static Type REAL = new Type("real", 'r'); + public static Type STRING = new Type("string", 's'); + public static Type ARRAY = new Type("array", 'a'); + public static Type FUNCTION = new Type("function", 'f'); + + public String name; + public char signature; + + public Type(String name, char signature) { + this.name = name; + this.signature = signature; + } + + public boolean accepts(Type type) { + if (type == this) return true; + if (this == ANY) return true; + if (this == NUMBER) { + if (type == BOOL || type == INT || type == REAL) return true; + } + if (this == REAL) { + if (type == INT) return true; + } + if (this == BOOL) return true; + return false; + } + + public boolean isNumber() { + return this == NUMBER || this == INT || this == REAL; + } + + public char getSignature() { + return signature; + } +} diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index 85a05144..0b394734 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -46,6 +46,7 @@ public AnalyzeResult analyze(AIFile ai) throws LeekCompilerException { // Si on est là c'est qu'on a une liste de words correcte, on peut commencer à lire MainLeekBlock main = new MainLeekBlock(this, ai); WordCompiler compiler = new WordCompiler(parser, main, ai, ai.getVersion()); + main.setWordCompiler(compiler); compiler.readCode(); compiler.analyze(); @@ -68,13 +69,14 @@ public AnalyzeResult analyze(AIFile ai) throws LeekCompilerException { } public String compile(AIFile ai, String javaClassName, String AIClass) throws LeekCompilerException { - JavaWriter writer = new JavaWriter(true); + JavaWriter writer = new JavaWriter(true, javaClassName); try { // On lance la compilation du code de l'IA WordParser parser = new WordParser(ai, ai.getVersion()); // Si on est là c'est qu'on a une liste de words correcte, on peut commencer à lire MainLeekBlock main = new MainLeekBlock(this, ai); WordCompiler compiler = new WordCompiler(parser, main, ai, ai.getVersion()); + main.setWordCompiler(compiler); compiler.readCode(); compiler.analyze(); // System.out.println("errors " + compiler.getErrors().size()); diff --git a/src/main/java/leekscript/compiler/JavaWriter.java b/src/main/java/leekscript/compiler/JavaWriter.java index 9089f17c..08854a88 100644 --- a/src/main/java/leekscript/compiler/JavaWriter.java +++ b/src/main/java/leekscript/compiler/JavaWriter.java @@ -14,6 +14,7 @@ public class JavaWriter { private final HashMap, Integer> mFiles = new HashMap<>(); private final ArrayList> mFilesList = new ArrayList<>(); private final boolean mWithDebug; + private final String className; private class Line { private final int mJavaLine; @@ -27,10 +28,11 @@ public Line(int java_line, int code_line, int ai) { } } - public JavaWriter(boolean debug) { + public JavaWriter(boolean debug, String className) { mCode = new StringBuilder(); mLine = 1; mWithDebug = debug; + this.className = className; } public boolean hasDebug() { diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index bf273f43..3cf02fdf 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -5,6 +5,7 @@ import java.util.TreeSet; import leekscript.common.Error; +import leekscript.common.Type; import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.AbstractLeekBlock; import leekscript.compiler.bloc.AnonymousFunctionBlock; @@ -25,7 +26,6 @@ import leekscript.compiler.expression.LeekExpression; import leekscript.compiler.expression.LeekExpressionException; import leekscript.compiler.expression.LeekExpressionFunction; -import leekscript.compiler.expression.LeekGlobal; import leekscript.compiler.expression.LeekNull; import leekscript.compiler.expression.LeekNumber; import leekscript.compiler.expression.LeekParenthesis; @@ -47,6 +47,7 @@ public class WordCompiler { private final MainLeekBlock mMain; private AbstractLeekBlock mCurentBlock; + private AbstractLeekBlock mCurrentFunction; private ClassDeclarationInstruction mCurrentClass; private final WordParser mCompiler; private int mLine; @@ -58,6 +59,7 @@ public WordCompiler(WordParser cmp, MainLeekBlock main, AIFile ai, int versio mCompiler = cmp; mMain = main; mCurentBlock = main; + mCurrentFunction = main; mAI = ai; this.version = version; } @@ -150,8 +152,7 @@ public void readCode() throws LeekCompilerException { // Puis on lit l'instruction compileWord(); } - int i = 0; - while (i++ < 100 && mCurentBlock.getParent() != null && !mCurentBlock.hasAccolade()) { + while (mCurentBlock.getParent() != null && !mCurentBlock.hasAccolade()) { if (mCurentBlock instanceof DoWhileBlock) { DoWhileBlock do_block = (DoWhileBlock) mCurentBlock; mCurentBlock = mCurentBlock.endInstruction(); @@ -172,6 +173,7 @@ public void readCode() throws LeekCompilerException { public void analyze() { // Analyse sémantique mCurentBlock = mMain; + mCurrentFunction = mMain; mMain.analyze(this); } @@ -180,7 +182,7 @@ private void compileWord() throws LeekCompilerException { mMain.addInstruction(); IAWord word = mCompiler.getWord(); if (word.getType() == WordParser.T_END_INSTRUCTION) { - mCurentBlock.addInstruction(this, new BlankInstruction()); + // mCurentBlock.addInstruction(this, new BlankInstruction()); mCompiler.skipWord(); return; } else if (word.getType() == WordParser.T_ACCOLADE_RIGHT) { @@ -329,8 +331,10 @@ private void functionBlock() throws LeekCompilerException { throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_PARENTHESIS_EXPECTED); } + var previousFunction = mCurrentFunction; FunctionBlock block = new FunctionBlock(mCurentBlock, mMain, mLine, mAI, funcName); mCurentBlock = block; + mCurrentFunction = block; while (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { boolean is_reference = false; if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("@")) { @@ -344,7 +348,7 @@ private void functionBlock() throws LeekCompilerException { throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_EXPECTED); // if (!isAvailable(mCompiler.getWord().getWord(), true)) // throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_UNAVAILABLE); - block.addParameter(mCompiler.readWord(), is_reference); + block.addParameter(this, mCompiler.readWord(), is_reference); if (mCompiler.getWord().getType() == WordParser.T_VIRG) mCompiler.skipWord(); } @@ -356,6 +360,7 @@ private void functionBlock() throws LeekCompilerException { if (mCompiler.readWord().getType() != WordParser.T_ACCOLADE_LEFT) throw new LeekCompilerException(mCompiler.lastWord(), Error.OPENING_CURLY_BRACKET_EXPECTED); mMain.addFunction(block); + mCurrentFunction = previousFunction; } private void forBlock() throws LeekCompilerException { @@ -420,8 +425,8 @@ private void forBlock() throws LeekCompilerException { // On lit le array (ou liste de valeurs) AbstractExpression array = readExpression(); block.setArray(array); - block.setKeyIterator(varName, isDeclaration); - block.setValueIterator(valueVarName, isValueDeclaration); + block.setKeyIterator(this, varName, isDeclaration); + block.setValueIterator(this, valueVarName, isValueDeclaration); forBlock = block; } else if (mCompiler.getWord().getWord().equals("in")) { // C'est un for (i in array) @@ -434,7 +439,7 @@ private void forBlock() throws LeekCompilerException { // On lit le array (ou liste de valeurs) AbstractExpression array = readExpression(); block.setArray(array); - block.setIterator(varName, isDeclaration); + block.setIterator(this, varName); forBlock = block; } else if (mCompiler.getWord().getWord().equals("=")) { // C'est un for (i=0;i<1;i++) @@ -471,7 +476,7 @@ private void forBlock() throws LeekCompilerException { throw new LeekCompilerException(mCompiler.lastWord(), Error.UNCOMPLETE_EXPRESSION); } - block.setInitialisation(varName, initValue, isDeclaration, block.hasGlobal(varName.getWord())); + block.setInitialisation(this, varName, initValue, isDeclaration, block.hasGlobal(varName.getWord())); block.setCondition(condition); block.setIncrementation(incrementation); @@ -502,8 +507,13 @@ private void whileBlock() throws LeekCompilerException { bloc.setCondition(exp); if (mCompiler.getWord().getType() == WordParser.T_ACCOLADE_LEFT) { mCompiler.skipWord(); - } else + } else if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) { + mCompiler.skipWord(); + bloc.addInstruction(this, new BlankInstruction()); + bloc.noAccolade(); + } else { bloc.noAccolade(); + } mCurentBlock.addInstruction(this, bloc); mCurentBlock = bloc; } @@ -573,6 +583,10 @@ private void ifBlock() throws LeekCompilerException { bloc.setCondition(exp); if (mCompiler.getWord().getType() == WordParser.T_ACCOLADE_LEFT) { mCompiler.skipWord(); + } else if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) { + mCompiler.skipWord(); + bloc.addInstruction(this, new BlankInstruction()); + bloc.noAccolade(); } else bloc.noAccolade(); mCurentBlock.addInstruction(this, bloc); @@ -627,16 +641,12 @@ private void variableDeclaration() throws LeekCompilerException { throw new LeekCompilerException(word, Error.VAR_NAME_EXPECTED); // if (!isAvailable(word.getWord(), true)) // throw new LeekCompilerException(word, Error.VARIABLE_NAME_UNAVAILABLE); - LeekVariableDeclarationInstruction variable = new LeekVariableDeclarationInstruction(word, mLine, mAI); + LeekVariableDeclarationInstruction variable = new LeekVariableDeclarationInstruction(this, word, mLine, mAI, getCurrentFunction()); // On regarde si une valeur est assignée if (mCompiler.getWord().getWord().equals("=")) { mCompiler.skipWord(); // Si oui on récupère la valeur en question - mCurentBlock.setDeclaringVariable(variable.getToken()); variable.setValue(readExpression()); - if (mCurentBlock.isDeclaringBariableUsed()) - variable.mustSepare(); - mCurentBlock.setDeclaringVariable(null); } mCurentBlock.addInstruction(this, variable); while (mCompiler.getWord().getType() == WordParser.T_VIRG) { @@ -647,7 +657,7 @@ private void variableDeclaration() throws LeekCompilerException { throw new LeekCompilerException(word, Error.VAR_NAME_EXPECTED); // if (!isAvailable(word.getWord(), true)) // throw new LeekCompilerException(word, Error.VARIABLE_NAME_UNAVAILABLE); - variable = new LeekVariableDeclarationInstruction(word, mLine, mAI); + variable = new LeekVariableDeclarationInstruction(this, word, mLine, mAI, getCurrentFunction()); // On regarde si une valeur est assignée if (mCompiler.getWord().getWord().equals("=")) { mCompiler.skipWord(); @@ -911,8 +921,14 @@ public AbstractExpression readExpression() throws LeekCompilerException { break; } else { if (word.getType() == WordParser.T_NUMBER) { - boolean floating = word.getWord().contains("."); - retour.addExpression(new LeekNumber(Double.parseDouble(word.getWord()), floating)); + var s = word.getWord(); + var type = s.contains(".") ? Type.REAL : Type.INT; + try { + Integer.parseInt(s); + } catch (NumberFormatException e) { + type = Type.REAL; + } + retour.addExpression(new LeekNumber(Double.parseDouble(word.getWord()), type)); } else if (word.getType() == WordParser.T_VAR_STRING) { retour.addExpression(new LeekString(word.getWord())); } else if (word.getType() == WordParser.T_BRACKET_LEFT) { @@ -947,7 +963,7 @@ else if (type == 2) retour.addExpression(array); } else if (word.getType() == WordParser.T_STRING) { if (mMain.hasGlobal(word.getWord())) { - retour.addExpression(new LeekGlobal(word)); + retour.addExpression(new LeekVariable(this, word, VariableType.GLOBAL)); } else if (word.getWord().equalsIgnoreCase("function")) { retour.addExpression(readAnonymousFunction()); } else if (word.getWord().equalsIgnoreCase("true")) @@ -970,7 +986,7 @@ else if (getVersion() >= 11 && word.getWord().equalsIgnoreCase("new")) { } retour.addExpression(new LeekVariable(word, VariableType.SUPER, ((ClassMethodBlock) mCurentBlock).getClassDeclaration())); } else { - retour.addExpression(new LeekVariable(word, VariableType.LOCAL)); + retour.addExpression(new LeekVariable(this, word, VariableType.LOCAL)); // throw new LeekCompilerException(word, Error.UNKNOWN_VARIABLE_OR_FUNCTION); } } else if (word.getType() == WordParser.T_PAR_LEFT) { @@ -1016,7 +1032,7 @@ else if (operator == Operators.INCREMENT) var expr = (LeekExpression) result; if (expr.getOperator() == Operators.NOT && expr.getExpression2() == null) { // Un "not" tout seul est valide en LS 1.0 - result = new LeekVariable(expr.getOperatorToken(), VariableType.LOCAL); + result = new LeekVariable(this, expr.getOperatorToken(), VariableType.LOCAL); } } if (result == null) { @@ -1037,12 +1053,14 @@ private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerExcepti } // On enregistre les block actuels AbstractLeekBlock initialBlock = mCurentBlock; + var previousFunction = mCurrentFunction; int initialLine = mLine; AIFile initialAI = mAI; AnonymousFunctionBlock block = new AnonymousFunctionBlock(mCurentBlock, mMain, mLine, mAI); - if (initialBlock.getDeclaringVariable() != null) - block.addVariable(new LeekVariable(initialBlock.getDeclaringVariable(), VariableType.LOCAL)); + // if (initialBlock.getDeclaringVariable() != null) + // block.addVariable(new LeekVariable(initialBlock.getDeclaringVariable(), VariableType.LOCAL)); mCurentBlock = block; + mCurrentFunction = block; // Lecture des paramètres while (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { @@ -1061,7 +1079,7 @@ private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerExcepti if (block.hasParameter(parameter.getWord())) { throw new LeekCompilerException(parameter, Error.PARAMETER_NAME_UNAVAILABLE); } - block.addParameter(parameter, is_reference); + block.addParameter(this, parameter, is_reference); if (mCompiler.getWord().getType() == WordParser.T_VIRG) mCompiler.skipWord(); } @@ -1101,6 +1119,7 @@ private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerExcepti mCurentBlock = initialBlock; mLine = initialLine; mAI = initialAI; + mCurrentFunction = previousFunction; return new LeekAnonymousFunction(block); } @@ -1142,6 +1161,10 @@ public AbstractLeekBlock getCurrentBlock() { return mCurentBlock; } + public AbstractLeekBlock getCurrentFunction() { + return mCurrentFunction; + } + public void addError(AnalyzeError error) { this.errors.add(error); } @@ -1173,4 +1196,8 @@ public ClassDeclarationInstruction getCurrentClass() { public void setCurrentClass(ClassDeclarationInstruction clazz) { this.mCurrentClass = clazz; } + + public void setCurrentFunction(AbstractLeekBlock block) { + this.mCurrentFunction = block; + } } diff --git a/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java b/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java index 21ce3c83..d182d25b 100644 --- a/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java @@ -86,7 +86,7 @@ public IAWord getDeclaringVariable() { return mDeclaringVariable; } - public boolean isDeclaringBariableUsed() { + public boolean isDeclaringVariableUsed() { return mDeclaringVariableUsed; } @@ -157,6 +157,11 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } } + @Override + public int getOperations() { + return 0; + } + public int countInstructions() { return mInstructions.size() == 0 ? 1 : mInstructions.size(); } diff --git a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java index 23aff421..e133a4ce 100644 --- a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java @@ -5,12 +5,15 @@ import leekscript.compiler.AIFile; import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.compiler.instruction.LeekVariableDeclarationInstruction; public class AnonymousFunctionBlock extends AbstractLeekBlock { private final ArrayList mParameters = new ArrayList(); + private final ArrayList mParameterDeclarations = new ArrayList<>(); private final ArrayList mReferences = new ArrayList(); private int mId = 0; @@ -40,10 +43,12 @@ public String referenceArray() { return str + "}"; } - public void addParameter(IAWord token, boolean is_reference) { + public void addParameter(WordCompiler compiler, IAWord token, boolean is_reference) { mParameters.add(token.getWord()); mReferences.add(is_reference); - addVariable(new LeekVariable(token, VariableType.ARGUMENT)); + var declaration = new LeekVariableDeclarationInstruction(compiler, token, token.getLine(), token.getAI(), this); + mParameterDeclarations.add(declaration); + addVariable(new LeekVariable(token, VariableType.ARGUMENT, declaration)); } public boolean hasParameter(String name) { @@ -64,6 +69,14 @@ public String getCode() { return str + "){\n" + super.getCode() + "}\n"; } + @Override + public void analyze(WordCompiler compiler) { + var initialFunction = compiler.getCurrentFunction(); + compiler.setCurrentFunction(this); + super.analyze(compiler); + compiler.setCurrentFunction(initialFunction); + } + @Override public void checkEndBlock() { @@ -93,4 +106,10 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { public boolean isReference(int i) { return mReferences.get(i); } + + @Override + public int getOperations() { + // TODO Auto-generated method stub + return 0; + } } diff --git a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java index 4c6b460a..cd65d18f 100644 --- a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java @@ -1,6 +1,7 @@ package leekscript.compiler.bloc; import java.util.ArrayList; +import java.util.List; import leekscript.compiler.AIFile; import leekscript.compiler.IAWord; @@ -113,4 +114,8 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { public ClassDeclarationInstruction getClassDeclaration() { return this.clazz; } + + public List getParameters() { + return mParameters; + } } diff --git a/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java b/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java index d2042610..574e92af 100644 --- a/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java +++ b/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java @@ -61,10 +61,10 @@ else if(mCondition != null){ } public int getConditionEndBlock() { - if(mEndInstruction == 0) return 0; - if(mParentCondition != null){ + if (mEndInstruction == 0) return 0; + if (mParentCondition != null) { int parent = mParentCondition.getConditionEndBlock(); - if(parent == 0) return 0; + if (parent == 0) return 0; return parent | mEndInstruction; } return mEndInstruction; @@ -72,9 +72,9 @@ public int getConditionEndBlock() { @Override public int getEndBlock() { - if(mCondition == null){ + if (mCondition == null) { int r = getConditionEndBlock(); - if(r != 0) setPutCounterBefore(true); + if (r != 0) setPutCounterBefore(true); return r; } return 0; @@ -86,7 +86,7 @@ public boolean putCounterBefore() { } private void setPutCounterBefore(boolean value) { - if(mParentCondition != null) mParentCondition.setPutCounterBefore(value); + if (mParentCondition != null) mParentCondition.setPutCounterBefore(value); else mPutCounterBefore = value; } diff --git a/src/main/java/leekscript/compiler/bloc/ForBlock.java b/src/main/java/leekscript/compiler/bloc/ForBlock.java index ee7dc97d..25ea1cea 100644 --- a/src/main/java/leekscript/compiler/bloc/ForBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForBlock.java @@ -6,7 +6,6 @@ import leekscript.compiler.WordCompiler; import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekExpression; -import leekscript.compiler.expression.LeekGlobal; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.Operators; import leekscript.compiler.expression.LeekVariable.VariableType; @@ -24,14 +23,14 @@ public ForBlock(AbstractLeekBlock parent, MainLeekBlock main, int line, AIFile ai, boolean reference) { super(parent, main, line, ai); @@ -24,9 +26,11 @@ public ForeachBlock(AbstractLeekBlock parent, MainLeekBlock main, boolean isDecl mReference = reference; } - public void setIterator(IAWord iterator, boolean declaration) { - // if (declaration) addVariable(new LeekVariable(iterator, VariableType.LOCAL)); + public void setIterator(WordCompiler compiler, IAWord iterator) { mIterator = iterator; + if (mIsDeclaration) { + declaration = new LeekVariableDeclarationInstruction(compiler, iterator, iterator.getLine(), iterator.getAI(), compiler.getCurrentFunction()); + } } public void setArray(AbstractExpression exp) { diff --git a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java index a48c9f0e..d249dffa 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java @@ -10,6 +10,7 @@ import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; import leekscript.common.Error; +import leekscript.compiler.instruction.LeekVariableDeclarationInstruction; public class ForeachKeyBlock extends AbstractLeekBlock { @@ -21,6 +22,8 @@ public class ForeachKeyBlock extends AbstractLeekBlock { private boolean mIsKeyDeclaration = false; private boolean mKeyReference = false; private boolean mValueReference = false; + private LeekVariableDeclarationInstruction iteratorDeclaration; + private LeekVariableDeclarationInstruction iteratorKeyDeclaration; public ForeachKeyBlock(AbstractLeekBlock parent, MainLeekBlock main, boolean isKeyDeclaration, boolean isValueDeclaration, int line, AIFile ai, boolean keyReference, boolean valueReference) { super(parent, main, line, ai); @@ -30,14 +33,20 @@ public ForeachKeyBlock(AbstractLeekBlock parent, MainLeekBlock main, boolean isK mValueReference = valueReference; } - public void setValueIterator(IAWord iterator, boolean declaration) { - // if(declaration) addVariable(new LeekVariable(iterator, VariableType.LOCAL)); - mIterator = iterator; + public void setValueIterator(WordCompiler compiler, IAWord iterator, boolean declaration) { + if (declaration) { + iteratorDeclaration = new LeekVariableDeclarationInstruction(compiler, iterator, 0, null, compiler.getCurrentFunction()); + addVariable(new LeekVariable(iterator, VariableType.ITERATOR, iteratorDeclaration)); + } + mIterator = iterator.getWord(); } - public void setKeyIterator(IAWord iterator, boolean declaration) { - // if(declaration) addVariable(new LeekVariable(iterator, VariableType.LOCAL)); - mKeyIterator = iterator; + public void setKeyIterator(WordCompiler compiler, IAWord iterator, boolean declaration) { + if (declaration) { + iteratorKeyDeclaration = new LeekVariableDeclarationInstruction(compiler, iterator, 0, null, compiler.getCurrentFunction()); + addVariable(new LeekVariable(iterator, VariableType.ITERATOR, iteratorKeyDeclaration)); + } + mKeyIterator = iterator.getWord(); } public void setArray(AbstractExpression exp) { @@ -134,6 +143,10 @@ public void analyze(WordCompiler compiler) { compiler.addError(new AnalyzeError(mIterator, AnalyzeErrorLevel.ERROR, Error.UNKNOWN_VARIABLE_OR_FUNCTION)); } } + if (iteratorDeclaration != null) + iteratorDeclaration.setFunction(compiler.getCurrentFunction()); + if (iteratorKeyDeclaration != null) + iteratorKeyDeclaration.setFunction(compiler.getCurrentFunction()); mArray.analyze(compiler); compiler.setCurrentBlock(initialBlock); diff --git a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java index 7cbfb2f3..3dde0260 100644 --- a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java @@ -8,12 +8,14 @@ import leekscript.compiler.WordCompiler; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.compiler.instruction.LeekVariableDeclarationInstruction; public class FunctionBlock extends AbstractLeekBlock { private IAWord token; private int mId; private final ArrayList mParameters = new ArrayList(); + private final ArrayList mParameterDeclarations = new ArrayList<>(); private final ArrayList mReferences = new ArrayList(); public FunctionBlock(AbstractLeekBlock parent, MainLeekBlock main, int line, AIFile ai, IAWord token) { @@ -47,10 +49,12 @@ public String referenceArray() { return str + "}"; } - public void addParameter(IAWord parameter, boolean is_reference) { + public void addParameter(WordCompiler compiler, IAWord parameter, boolean is_reference) { mParameters.add(parameter.getWord()); mReferences.add(is_reference); - addVariable(new LeekVariable(parameter, VariableType.ARGUMENT)); + var declaration = new LeekVariableDeclarationInstruction(compiler, parameter, parameter.getLine(), parameter.getAI(), this); + mParameterDeclarations.add(declaration); + addVariable(new LeekVariable(parameter, VariableType.ARGUMENT, declaration)); } @Override @@ -66,7 +70,15 @@ public String getCode() { str += ", "; str += mParameters.get(i); } - return str + "){\n" + super.getCode() + "}\n"; + return str + ") {\n" + super.getCode() + "}\n"; + } + + @Override + public void analyze(WordCompiler compiler) { + var initialFunction = compiler.getCurrentFunction(); + compiler.setCurrentFunction(this); + super.analyze(compiler); + compiler.setCurrentFunction(initialFunction); } @Override diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 9215f00e..2ed31602 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -38,6 +38,8 @@ public class MainLeekBlock extends AbstractLeekBlock { private int mCountInstruction = 0; private final IACompiler mCompiler; private String mAIName; + private String className; + private WordCompiler wordCompiler; @Override public int getCount() { @@ -175,6 +177,8 @@ public String getCode() { } public void writeJavaCode(JavaWriter writer, String className, String AIClass) { + this.className = className; + writer.addLine("import leekscript.runner.*;"); writer.addLine("import leekscript.runner.values.*;"); writer.addLine(); @@ -361,4 +365,16 @@ public void analyze(WordCompiler compiler) { } super.analyze(compiler); } + + public String getClassName() { + return className; + } + + public void setWordCompiler(WordCompiler compiler) { + this.wordCompiler = compiler; + } + + public WordCompiler getWordCompiler() { + return this.wordCompiler; + } } diff --git a/src/main/java/leekscript/compiler/expression/AbstractExpression.java b/src/main/java/leekscript/compiler/expression/AbstractExpression.java index b5626fa1..9243f28f 100644 --- a/src/main/java/leekscript/compiler/expression/AbstractExpression.java +++ b/src/main/java/leekscript/compiler/expression/AbstractExpression.java @@ -1,5 +1,6 @@ package leekscript.compiler.expression; +import leekscript.common.Type; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; @@ -19,7 +20,11 @@ public abstract class AbstractExpression { public final static int OBJECT = 11; public final static int OBJECT_ACCESS = 12; - public abstract int getType(); + protected int operations = 0; + + public abstract int getNature(); + + public abstract Type getType(); public abstract String getString(); @@ -35,5 +40,13 @@ public boolean isLeftValue() { return false; } + public boolean nullable() { + return true; + } + public abstract void analyze(WordCompiler compiler); + + public int getOperations() { + return operations; + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekAnonymousFunction.java b/src/main/java/leekscript/compiler/expression/LeekAnonymousFunction.java index 877b1d6b..4e406128 100644 --- a/src/main/java/leekscript/compiler/expression/LeekAnonymousFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekAnonymousFunction.java @@ -1,5 +1,6 @@ package leekscript.compiler.expression; +import leekscript.common.Type; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.AnonymousFunctionBlock; @@ -14,10 +15,15 @@ public LeekAnonymousFunction(AnonymousFunctionBlock block) { } @Override - public int getType() { + public int getNature() { return FUNCTION; } + @Override + public Type getType() { + return Type.FUNCTION; + } + @Override public String getString() { return "#Anonymous" + mBlock.getId(); @@ -37,6 +43,9 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { @Override public void analyze(WordCompiler compiler) { + var previousFunction = compiler.getCurrentFunction(); + compiler.setCurrentFunction(mBlock); mBlock.analyze(compiler); + compiler.setCurrentFunction(previousFunction); } } diff --git a/src/main/java/leekscript/compiler/expression/LeekArray.java b/src/main/java/leekscript/compiler/expression/LeekArray.java index 89236816..3ca522a1 100644 --- a/src/main/java/leekscript/compiler/expression/LeekArray.java +++ b/src/main/java/leekscript/compiler/expression/LeekArray.java @@ -2,6 +2,7 @@ import java.util.ArrayList; +import leekscript.common.Type; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; @@ -23,10 +24,15 @@ public void addValue(AbstractExpression key, AbstractExpression value) { } @Override - public int getType() { + public int getNature() { return ARRAY; } + @Override + public Type getType() { + return Type.ARRAY; + } + @Override public String getString() { String str = "["; @@ -60,8 +66,10 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { @Override public void analyze(WordCompiler compiler) { + operations = 0; for (var value : mValues) { value.analyze(compiler); + operations += value.getOperations(); } } } diff --git a/src/main/java/leekscript/compiler/expression/LeekBoolean.java b/src/main/java/leekscript/compiler/expression/LeekBoolean.java index 6264b584..55e6e21e 100644 --- a/src/main/java/leekscript/compiler/expression/LeekBoolean.java +++ b/src/main/java/leekscript/compiler/expression/LeekBoolean.java @@ -1,5 +1,6 @@ package leekscript.compiler.expression; +import leekscript.common.Type; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; @@ -13,10 +14,15 @@ public LeekBoolean(boolean value) { } @Override - public int getType() { + public int getNature() { return BOOLEAN; } + @Override + public Type getType() { + return Type.BOOL; + } + @Override public String getString() { return mValue ? "true" : "false"; diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index 6b725510..70a06fec 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -7,7 +7,9 @@ import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.runner.values.LeekValue; import leekscript.common.Error; +import leekscript.common.Type; public class LeekExpression extends AbstractExpression { @@ -15,17 +17,25 @@ public class LeekExpression extends AbstractExpression { private IAWord mOperatorToken; protected AbstractExpression mExpression1 = null; protected AbstractExpression mExpression2 = null; - protected LeekExpression mParent = null; + private Type type = Type.ANY; + + public LeekExpression() {} + + public LeekExpression(AbstractExpression x, int operator, AbstractExpression y) { + mExpression1 = x; + mOperator = operator; + mExpression2 = y; + } public void setParent(LeekExpression parent) { mParent = parent; } public boolean hasTernaire() { - if (mExpression1 != null && mExpression1.getType() == EXPRESSION && ((LeekExpression) mExpression1).hasTernaire()) + if (mExpression1 != null && mExpression1.getNature() == EXPRESSION && ((LeekExpression) mExpression1).hasTernaire()) return true; - if (mExpression2 != null && mExpression2.getType() == EXPRESSION && ((LeekExpression) mExpression2).hasTernaire()) + if (mExpression2 != null && mExpression2.getNature() == EXPRESSION && ((LeekExpression) mExpression2).hasTernaire()) return true; return false; } @@ -88,13 +98,13 @@ public void setOperator(int operator, IAWord operatorToken) { public boolean needOperator() { if (mExpression1 != null) { - if (mExpression1.getType() == EXPRESSION && !((LeekExpression) mExpression1).complete()) + if (mExpression1.getNature() == EXPRESSION && !((LeekExpression) mExpression1).complete()) return ((LeekExpression) mExpression1).needOperator(); if (mOperator == -1) return true; } if (mExpression2 != null) { - if (mExpression2.getType() == EXPRESSION) + if (mExpression2.getNature() == EXPRESSION) return ((LeekExpression) mExpression2).needOperator(); return true; } @@ -102,17 +112,22 @@ public boolean needOperator() { } public LeekExpression lastExpression() { - if (mExpression2 != null && mExpression2.getType() == EXPRESSION) + if (mExpression2 != null && mExpression2.getNature() == EXPRESSION) return ((LeekExpression) mExpression2).lastExpression(); else return this; } @Override - public int getType() { + public int getNature() { return AbstractExpression.EXPRESSION; } + @Override + public Type getType() { + return type; + } + public boolean complete(int operator) { return complete(); } @@ -120,9 +135,9 @@ public boolean complete(int operator) { public boolean complete() { if (mExpression1 == null || mExpression2 == null) return false; - if (mExpression1.getType() == EXPRESSION && !((LeekExpression) mExpression1).complete()) + if (mExpression1.getNature() == EXPRESSION && !((LeekExpression) mExpression1).complete()) return false; - if (mExpression2.getType() == EXPRESSION && !((LeekExpression) mExpression2).complete()) + if (mExpression2.getNature() == EXPRESSION && !((LeekExpression) mExpression2).complete()) return false; return true; } @@ -130,7 +145,7 @@ public boolean complete() { public void addExpression(AbstractExpression expression) { if (mExpression1 == null) mExpression1 = expression; - else if (mExpression1.getType() == EXPRESSION && !((LeekExpression) mExpression1).complete()) { + else if (mExpression1.getNature() == EXPRESSION && !((LeekExpression) mExpression1).complete()) { ((LeekExpression) mExpression1).addExpression(expression); } else { @@ -155,7 +170,7 @@ public void addUnaryPrefix(int operator, IAWord operatorToken) { public void addBracket(AbstractExpression casevalue) { // On doit ajouter ce crochet au dernier élément ajouté if (mExpression1 != null && mExpression2 == null) { - if (mExpression1.getType() == EXPRESSION) + if (mExpression1.getNature() == EXPRESSION) ((LeekExpression) mExpression1).addBracket(casevalue); else { // On doit ajouter à l'élément mExpression1 @@ -166,7 +181,7 @@ public void addBracket(AbstractExpression casevalue) { } } else if (mExpression2 != null) { - if (mExpression2.getType() == EXPRESSION) + if (mExpression2.getNature() == EXPRESSION) ((LeekExpression) mExpression2).addBracket(casevalue); else { // On doit ajouter à l'élément mExpression2 @@ -180,13 +195,13 @@ else if (mExpression2 != null) { public void addObjectAccess(IAWord name) { if (mExpression1 != null && mExpression2 == null) { - if (mExpression1.getType() == EXPRESSION) + if (mExpression1.getNature() == EXPRESSION) ((LeekExpression) mExpression1).addObjectAccess(name); else { mExpression1 = new LeekObjectAccess(mExpression1, name); } } else if (mExpression2 != null) { - if (mExpression2.getType() == EXPRESSION) + if (mExpression2.getNature() == EXPRESSION) ((LeekExpression) mExpression2).addObjectAccess(name); else { mExpression2 = new LeekObjectAccess(mExpression2, name); @@ -197,7 +212,7 @@ public void addObjectAccess(IAWord name) { public void addFunction(LeekExpressionFunction function) { // On doit ajouter ce crochet au dernier élément ajouté if (mExpression1 != null && mExpression2 == null) { - if (mExpression1.getType() == EXPRESSION) + if (mExpression1.getNature() == EXPRESSION) ((LeekExpression) mExpression1).addFunction(function); else { // On doit ajouter à l'élément mExpression1 @@ -206,7 +221,7 @@ public void addFunction(LeekExpressionFunction function) { } } else if (mExpression2 != null) { - if (mExpression2.getType() == EXPRESSION) + if (mExpression2.getNature() == EXPRESSION) ((LeekExpression) mExpression2).addFunction(function); else { // On doit ajouter à l'élément mExpression2 @@ -219,7 +234,7 @@ else if (mExpression2 != null) { public void addUnarySuffix(int suffix, IAWord token) { // On doit ajouter ce suffix au dernier élément ajouté if (mExpression1 != null && mExpression2 == null) { - if (mExpression1.getType() == EXPRESSION) + if (mExpression1.getNature() == EXPRESSION) ((LeekExpression) mExpression1).addUnarySuffix(suffix, token); else { // On doit ajouter à l'élément mExpression1 @@ -232,7 +247,7 @@ public void addUnarySuffix(int suffix, IAWord token) { } } else if (mExpression2 != null) { - if (mExpression2.getType() == EXPRESSION) + if (mExpression2.getNature() == EXPRESSION) ((LeekExpression) mExpression2).addUnarySuffix(suffix, token); else { // On doit ajouter à l'élément mExpression2 @@ -278,7 +293,7 @@ public void addTernaire() { mExpression2 = null; mOperator = -1; } - else if (mExpression2.getType() != EXPRESSION) { + else if (mExpression2.getNature() != EXPRESSION) { // On doit englober l'expression de droite LeekTernaire ternaire = new LeekTernaire(); ternaire.addExpression(mExpression2); @@ -293,12 +308,12 @@ else if (mExpression2.getType() != EXPRESSION) { public void replaceExpression(AbstractExpression base, AbstractExpression replacement) { if (mExpression1 == base) { - if (replacement.getType() == EXPRESSION) + if (replacement.getNature() == EXPRESSION) ((LeekExpression) replacement).setParent(this); mExpression1 = replacement; } else if (mExpression2 == base) { - if (replacement.getType() == EXPRESSION) + if (replacement.getNature() == EXPRESSION) ((LeekExpression) replacement).setParent(this); mExpression2 = replacement; } @@ -315,13 +330,13 @@ public void addOperator(int operator, IAWord token) { * mExpression1.getType() == EXPRESSION) ((LeekExpression) * mExpression1).addOperator(operator); } else */ - if (mExpression1 != null && mExpression1.getType() == EXPRESSION && !((LeekExpression) mExpression1).complete(operator)) { + if (mExpression1 != null && mExpression1.getNature() == EXPRESSION && !((LeekExpression) mExpression1).complete(operator)) { ((LeekExpression) mExpression1).addOperator(operator, token); } else if (mOperator == -1) { if (operator == Operators.TERNAIRE) { LeekTernaire trn = new LeekTernaire(); - if (mExpression1.getType() == EXPRESSION) + if (mExpression1.getNature() == EXPRESSION) ((LeekExpression) mExpression1).setParent(trn); trn.addExpression(mExpression1); trn.addOperator(operator, token); @@ -349,7 +364,7 @@ else if (mOperator == -1) { new_e.setOperator(mOperator, token); if (operator == Operators.TERNAIRE) { LeekTernaire trn = new LeekTernaire(); - if (mExpression1.getType() == EXPRESSION) + if (mExpression1.getNature() == EXPRESSION) ((LeekExpression) mExpression1).setParent(trn); trn.addExpression(new_e); trn.addOperator(operator, token); @@ -368,7 +383,7 @@ else if (mOperator == -1) { mOperator = operator; } } - else if (mExpression2.getType() != EXPRESSION) { + else if (mExpression2.getNature() != EXPRESSION) { // On doit englober l'expression de droite if (operator == Operators.TERNAIRE) { LeekTernaire trn = new LeekTernaire(); @@ -516,7 +531,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { mExpression2.writeJavaCode(mainblock, writer); writer.addCode(")"); return; - case Operators.ROTATE_RIGHT: + case Operators.SHIFT_UNSIGNED_RIGHT: writer.addCode("LeekOperations.brotate(mUAI, "); mExpression1.writeJavaCode(mainblock, writer); writer.addCode(", "); @@ -704,7 +719,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { mExpression2.writeJavaCode(mainblock, writer); writer.addCode(")"); return; - case Operators.ROTATE_RIGHT_ASSIGN: + case Operators.SHIFT_UNSIGNED_RIGHT_ASSIGN: mExpression1.writeJavaCode(mainblock, writer); writer.addCode(".brotate(mUAI, "); mExpression2.writeJavaCode(mainblock, writer); @@ -743,7 +758,7 @@ public void analyze(WordCompiler compiler) { // Si on a affaire à une assignation, incrémentation ou autre du genre // on doit vérifier qu'on a bien une variable (l-value) - if (mOperator == Operators.ADDASSIGN || mOperator == Operators.MINUSASSIGN || mOperator == Operators.DIVIDEASSIGN || mOperator == Operators.ASSIGN || mOperator == Operators.MODULUSASSIGN || mOperator == Operators.MULTIPLIEASSIGN || mOperator == Operators.POWERASSIGN || mOperator == Operators.BITOR_ASSIGN || mOperator == Operators.BITAND_ASSIGN || mOperator == Operators.BITXOR_ASSIGN || mOperator == Operators.SHIFT_LEFT_ASSIGN || mOperator == Operators.SHIFT_RIGHT_ASSIGN || mOperator == Operators.ROTATE_RIGHT_ASSIGN) { + if (mOperator == Operators.ADDASSIGN || mOperator == Operators.MINUSASSIGN || mOperator == Operators.DIVIDEASSIGN || mOperator == Operators.ASSIGN || mOperator == Operators.MODULUSASSIGN || mOperator == Operators.MULTIPLIEASSIGN || mOperator == Operators.POWERASSIGN || mOperator == Operators.BITOR_ASSIGN || mOperator == Operators.BITAND_ASSIGN || mOperator == Operators.BITXOR_ASSIGN || mOperator == Operators.SHIFT_LEFT_ASSIGN || mOperator == Operators.SHIFT_RIGHT_ASSIGN || mOperator == Operators.SHIFT_UNSIGNED_RIGHT_ASSIGN) { if (!mExpression1.isLeftValue()) compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.ERROR, Error.CANT_ASSIGN_VALUE)); // throw new LeekExpressionException(mExpression1, LeekCompilerException.CANT_ASSIGN_VALUE); @@ -770,5 +785,60 @@ public void analyze(WordCompiler compiler) { if (mExpression2 instanceof LeekTabularValue) ((LeekTabularValue) mExpression2).setLeftValue(true); } + + if (mOperator == Operators.NOT || mOperator == Operators.EQUALS_EQUALS || mOperator == Operators.LESS || mOperator == Operators.MORE || mOperator == Operators.MOREEQUALS || mOperator == Operators.LESSEQUALS || mOperator == Operators.EQUALS || mOperator == Operators.AND || mOperator == Operators.OR || mOperator == Operators.NOTEQUALS || mOperator == Operators.NOT_EQUALS_EQUALS || mOperator == Operators.INSTANCEOF) { + type = Type.BOOL; + } + if (mOperator == Operators.BITAND || mOperator == Operators.BITNOT || mOperator == Operators.BITOR || mOperator == Operators.BITXOR || mOperator == Operators.SHIFT_LEFT || mOperator == Operators.SHIFT_RIGHT || mOperator == Operators.SHIFT_UNSIGNED_RIGHT) { + type = Type.INT; + } + if (mOperator == Operators.ADD && ((mExpression1.getType() == Type.STRING || mExpression2.getType() == Type.STRING))) { + type = Type.STRING; + } + if (mOperator == Operators.ADD || mOperator == Operators.MINUS) { + if (mExpression1.getType() == Type.INT) { + if (mExpression2.getType() == Type.INT) type = Type.INT; + if (mExpression2.getType() == Type.REAL) type = Type.REAL; + } + else if (mExpression1.getType() == Type.REAL) { + if (mExpression2.getType() == Type.INT || mExpression2.getType() == Type.REAL) type = Type.REAL; + } + } + if (mOperator == Operators.MULTIPLIE) { + if (mExpression1.getType().isNumber() && mExpression2.getType().isNumber()) { + if (mExpression1.getType() == Type.INT && mExpression2.getType() == Type.INT) { + type = Type.INT; + } else { + type = Type.REAL; + } + } + } + // if (mOperator == Operators.DIVIDE) { + // type = Type.REAL; + // } + if (mOperator == Operators.UNARY_MINUS) { + type = mExpression2.getType(); + } + // if (mOperator == Operators.POWER) { + // type = Type.REAL; + // } + + // Opérations + operations = (mExpression1 != null ? mExpression1.getOperations() : 0) + (mExpression2 != null ? mExpression2.getOperations() : 0); + if (mOperator == Operators.POWER || mOperator == Operators.POWERASSIGN) { + operations += LeekValue.POW_COST; + } else if (mOperator == Operators.MULTIPLIE || mOperator == Operators.MULTIPLIEASSIGN) { + operations += LeekValue.MUL_COST; + } else if (mOperator == Operators.DIVIDE || mOperator == Operators.DIVIDEASSIGN) { + operations += LeekValue.DIV_COST; + } else if (mOperator == Operators.MODULUS || mOperator == Operators.MODULUSASSIGN) { + operations += LeekValue.MOD_COST; + } else { + operations += 1; + } + } + + public boolean needsWrapper() { + return mOperator == Operators.OR || mOperator == Operators.AND || mOperator == Operators.ADD || mOperator == Operators.MINUS || mOperator == Operators.MULTIPLIE || mOperator == Operators.DIVIDE || mOperator == Operators.MODULUS || mOperator == Operators.POWER || mOperator == Operators.SHIFT_LEFT || mOperator == Operators.SHIFT_RIGHT || mOperator == Operators.BITAND || mOperator == Operators.BITOR || mOperator == Operators.BITXOR || mOperator == Operators.LESS || mOperator == Operators.MORE || mOperator == Operators.LESSEQUALS || mOperator == Operators.MOREEQUALS || mOperator == Operators.EQUALS || mOperator == Operators.EQUALS_EQUALS || mOperator == Operators.NOTEQUALS || mOperator == Operators.NOT_EQUALS_EQUALS; } } diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index ccbfb434..0e3d6a89 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -10,15 +10,18 @@ import leekscript.compiler.bloc.FunctionBlock; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.runner.CallableVersion; import leekscript.runner.ILeekFunction; import leekscript.runner.LeekFunctions; import leekscript.common.Error; +import leekscript.common.Type; public class LeekExpressionFunction extends AbstractExpression { private IAWord openParenthesis = null; private final ArrayList mParameters = new ArrayList(); private AbstractExpression mExpression = null; + private Type type = Type.ANY; public LeekExpressionFunction(IAWord openParenthesis) { this.openParenthesis = openParenthesis; @@ -33,10 +36,15 @@ public void addParameter(AbstractExpression param) { } @Override - public int getType() { + public int getNature() { return FUNCTION; } + @Override + public Type getType() { + return type; + } + @Override public String getString() { String str = mExpression.getString() + "("; @@ -139,9 +147,12 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { @Override public void analyze(WordCompiler compiler) { + operations = 1; mExpression.analyze(compiler); + operations += mExpression.getOperations(); for (AbstractExpression parameter : mParameters) { parameter.analyze(compiler); + operations += parameter.getOperations(); } if (mExpression instanceof LeekVariable) { @@ -155,8 +166,18 @@ public void analyze(WordCompiler compiler) { } } else { var f = LeekFunctions.getValue(v.getName()); - if (mParameters.size() > nb_params || mParameters.size() < f.getArgumentsMin()) + if (mParameters.size() > nb_params || mParameters.size() < f.getArgumentsMin()) { compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.INVALID_PARAMETER_COUNT)); + } + var version = checkArgumentsStatically(f); + if (version != null) { + type = version.return_type; + } + } + } else if (v.getVariableType() == VariableType.SYSTEM_FUNCTION) { + var system_function = LeekFunctions.getValue(v.getName()); + if (system_function.getReturnType() != null) { + type = system_function.getReturnType(); } } else if (v.getVariableType() == VariableType.CLASS) { @@ -179,4 +200,33 @@ public void analyze(WordCompiler compiler) { } } } + + CallableVersion checkArgumentsStatically(ILeekFunction function) { + var versions = function.getVersions(); + if (versions == null) return null; + + for (var version : versions) { + if (checkArgumentsStatically(version)) { + return version; + } + } + return null; + } + + private boolean checkArgumentsStatically(CallableVersion version) { + for (int i = 0; i < version.arguments.length; ++i) { + if (!version.arguments[i].accepts(mParameters.get(i).getType())) { + return false; + } + } + return true; + } + + private String buildTypesSignature(Type[] types) { + var s = new StringBuilder(); + for (var type : types) { + s.append(type.getSignature()); + } + return s.toString(); + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekGlobal.java b/src/main/java/leekscript/compiler/expression/LeekGlobal.java deleted file mode 100644 index 583b6886..00000000 --- a/src/main/java/leekscript/compiler/expression/LeekGlobal.java +++ /dev/null @@ -1,46 +0,0 @@ -package leekscript.compiler.expression; - -import leekscript.compiler.IAWord; -import leekscript.compiler.JavaWriter; -import leekscript.compiler.WordCompiler; -import leekscript.compiler.bloc.MainLeekBlock; - -public class LeekGlobal extends AbstractExpression { - - private final IAWord token; - - public LeekGlobal(IAWord token) { - this.token = token; - } - - @Override - public int getType() { - return GLOBAL; - } - - @Override - public String getString() { - return token.getWord(); - } - - @Override - public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { - // Pour une globale, la vérification est faite avant l'ajout donc pas besoin de refaire - return true; - } - - @Override - public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addCode("globale_" + token.getWord()); - } - - @Override - public boolean isLeftValue() { - return true; - } - - @Override - public void analyze(WordCompiler compiler) { - - } -} diff --git a/src/main/java/leekscript/compiler/expression/LeekNull.java b/src/main/java/leekscript/compiler/expression/LeekNull.java index 44e13f97..c50e1e41 100644 --- a/src/main/java/leekscript/compiler/expression/LeekNull.java +++ b/src/main/java/leekscript/compiler/expression/LeekNull.java @@ -1,5 +1,6 @@ package leekscript.compiler.expression; +import leekscript.common.Type; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; @@ -7,10 +8,15 @@ public class LeekNull extends AbstractExpression { @Override - public int getType() { + public int getNature() { return NULL; } + @Override + public Type getType() { + return Type.NULL; + } + @Override public String getString() { return "null"; diff --git a/src/main/java/leekscript/compiler/expression/LeekNumber.java b/src/main/java/leekscript/compiler/expression/LeekNumber.java index 95a5b73a..ef4c690a 100644 --- a/src/main/java/leekscript/compiler/expression/LeekNumber.java +++ b/src/main/java/leekscript/compiler/expression/LeekNumber.java @@ -1,5 +1,6 @@ package leekscript.compiler.expression; +import leekscript.common.Type; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; @@ -7,18 +8,23 @@ public class LeekNumber extends AbstractExpression { private final double mValue; - private final boolean floating; + private Type type; - public LeekNumber(double value, boolean floating) { + public LeekNumber(double value, Type type) { mValue = value; - this.floating = floating; + this.type = type; } @Override - public int getType() { + public int getNature() { return NUMBER; } + @Override + public Type getType() { + return type; + } + @Override public String getString() { return String.valueOf(mValue); @@ -32,7 +38,7 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if (floating || mValue != (int) mValue) { + if (type == Type.REAL) { writer.addCode("new DoubleLeekValue(" + mValue + ")"); } else { writer.addCode("LeekValueManager.getLeekIntValue(" + ((int) mValue) + ")"); diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index 02abfc9c..bbaee47d 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -8,6 +8,7 @@ import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.LeekVariable.VariableType; import leekscript.common.Error; +import leekscript.common.Type; public class LeekObjectAccess extends AbstractExpression { @@ -20,10 +21,15 @@ public LeekObjectAccess(AbstractExpression object, IAWord field) { } @Override - public int getType() { + public int getNature() { return OBJECT_ACCESS; } + @Override + public Type getType() { + return Type.ANY; + } + @Override public String getString() { return object.getString() + "." + field.getWord(); @@ -49,10 +55,17 @@ public boolean isLeftValue() { return true; } + @Override + public boolean nullable() { + return object.nullable(); + } + @Override public void analyze(WordCompiler compiler) { // System.out.println("oa " + getString()); object.analyze(compiler); + operations = 1 + object.operations; + if (object instanceof LeekVariable) { var v = (LeekVariable) object; if (v.getName().equals("this")) { diff --git a/src/main/java/leekscript/compiler/expression/LeekParenthesis.java b/src/main/java/leekscript/compiler/expression/LeekParenthesis.java index e3fed26b..61c4ab03 100644 --- a/src/main/java/leekscript/compiler/expression/LeekParenthesis.java +++ b/src/main/java/leekscript/compiler/expression/LeekParenthesis.java @@ -1,5 +1,6 @@ package leekscript.compiler.expression; +import leekscript.common.Type; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; @@ -12,14 +13,23 @@ public LeekParenthesis(AbstractExpression exp) { mExpression = exp; } + public AbstractExpression getExpression() { + return mExpression; + } + @Override - public int getType() { + public int getNature() { return 0; } + @Override + public Type getType() { + return mExpression.getType(); + } + @Override public AbstractExpression trim() { - return mExpression; + return mExpression.trim(); } @Override @@ -40,5 +50,6 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void analyze(WordCompiler compiler) { mExpression.analyze(compiler); + operations = mExpression.getOperations(); } } diff --git a/src/main/java/leekscript/compiler/expression/LeekString.java b/src/main/java/leekscript/compiler/expression/LeekString.java index 1a1989eb..cff4fb59 100644 --- a/src/main/java/leekscript/compiler/expression/LeekString.java +++ b/src/main/java/leekscript/compiler/expression/LeekString.java @@ -1,5 +1,6 @@ package leekscript.compiler.expression; +import leekscript.common.Type; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; @@ -13,10 +14,15 @@ public LeekString(String str) { } @Override - public int getType() { + public int getNature() { return STRING; } + @Override + public Type getType() { + return Type.STRING; + } + @Override public String getString() { return "\"" + mString + "\""; diff --git a/src/main/java/leekscript/compiler/expression/LeekTabularValue.java b/src/main/java/leekscript/compiler/expression/LeekTabularValue.java index adb0948d..7926ba73 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTabularValue.java +++ b/src/main/java/leekscript/compiler/expression/LeekTabularValue.java @@ -1,5 +1,6 @@ package leekscript.compiler.expression; +import leekscript.common.Type; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; @@ -27,10 +28,15 @@ public AbstractExpression getCase() { } @Override - public int getType() { + public int getNature() { return TABULAR_VALUE; } + @Override + public Type getType() { + return Type.ANY; + } + @Override public String getString() { return (mTabular == null ? "null" : mTabular.getString()) + "[" + (mCase == null ? "null" : mCase.getString()) + "]"; @@ -38,13 +44,13 @@ public String getString() { @Override public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { - //On doit vérifier qu'on a affaire : soit à une expression tabulaire, soit à une variable, soit à une globale - //throw new LeekExpressionException(this, "Ce n'est pas un tableau valide"); + // On doit vérifier qu'on a affaire : soit à une expression tabulaire, soit à une variable, soit à une globale + // throw new LeekExpressionException(this, "Ce n'est pas un tableau valide"); if (!mTabular.isLeftValue()) { mLeftValue = false; } - //Sinon on valide simplement les deux expressions + // Sinon on valide simplement les deux expressions mTabular.validExpression(compiler, mainblock); mCase.validExpression(compiler, mainblock); return true; @@ -74,9 +80,15 @@ public boolean isLeftValue() { return true; } + @Override + public boolean nullable() { + return true; + } + @Override public void analyze(WordCompiler compiler) { mTabular.analyze(compiler); mCase.analyze(compiler); + operations = mTabular.getOperations() + mCase.getOperations(); } } diff --git a/src/main/java/leekscript/compiler/expression/LeekTernaire.java b/src/main/java/leekscript/compiler/expression/LeekTernaire.java index 28fce1ca..2c17d98e 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTernaire.java +++ b/src/main/java/leekscript/compiler/expression/LeekTernaire.java @@ -5,12 +5,14 @@ import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.common.Error; +import leekscript.common.Type; public class LeekTernaire extends LeekExpression { private AbstractExpression mCondition; private int mOperator = 0; + private Type type = Type.ANY; public LeekTernaire() { mCondition = null; @@ -21,19 +23,19 @@ public LeekTernaire() { @Override public boolean needOperator() { if(mCondition != null && mOperator == 0){ - if(mCondition.getType() == EXPRESSION){ + if(mCondition.getNature() == EXPRESSION){ return ((LeekExpression) mCondition).needOperator(); } return true; } if(mExpression1 != null && mOperator == 1){ - if(mExpression1.getType() == EXPRESSION){ + if(mExpression1.getNature() == EXPRESSION){ return ((LeekExpression) mExpression1).needOperator(); } return true; } if(mExpression2 != null && mOperator == 2){ - if(mExpression2.getType() == EXPRESSION){ + if(mExpression2.getNature() == EXPRESSION){ return ((LeekExpression) mExpression2).needOperator(); } return true; @@ -47,10 +49,14 @@ public boolean hasTernaire() { } @Override - public int getType() { + public int getNature() { return EXPRESSION; } + public Type getType() { + return type; + } + @Override public String getString() { String retour = "("; @@ -89,7 +95,7 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void addExpression(AbstractExpression expression) { if(mCondition == null) mCondition = expression; - else if(mCondition.getType() == EXPRESSION && !((LeekExpression) mCondition).complete()){ + else if(mCondition.getNature() == EXPRESSION && !((LeekExpression) mCondition).complete()){ ((LeekExpression) mCondition).addExpression(expression); } else if(mOperator == 1){ @@ -107,7 +113,7 @@ else if(mOperator == 2){ public void addUnarySuffix(int suffix, IAWord token) { //On doit ajouter ce suffix au dernier élément ajouté if(mCondition != null && mExpression1 == null && mExpression2 == null){ - if(mCondition.getType() == EXPRESSION) ((LeekExpression) mCondition).addUnarySuffix(suffix, token); + if(mCondition.getNature() == EXPRESSION) ((LeekExpression) mCondition).addUnarySuffix(suffix, token); else{ //On doit ajouter à l'élément mExpression1 LeekExpression exp = new LeekExpression(); @@ -119,7 +125,7 @@ public void addUnarySuffix(int suffix, IAWord token) { } } else if(mExpression1 != null && mExpression2 == null){ - if(mExpression1.getType() == EXPRESSION) ((LeekExpression) mExpression1).addUnarySuffix(suffix, token); + if(mExpression1.getNature() == EXPRESSION) ((LeekExpression) mExpression1).addUnarySuffix(suffix, token); else{ //On doit ajouter à l'élément mExpression1 LeekExpression exp = new LeekExpression(); @@ -131,7 +137,7 @@ else if(mExpression1 != null && mExpression2 == null){ } } else if(mExpression2 != null){ - if(mExpression2.getType() == EXPRESSION) ((LeekExpression) mExpression2).addUnarySuffix(suffix, token); + if(mExpression2.getNature() == EXPRESSION) ((LeekExpression) mExpression2).addUnarySuffix(suffix, token); else{ //On doit ajouter à l'élément mExpression2 LeekExpression exp = new LeekExpression(); @@ -155,7 +161,7 @@ public boolean complete(int operator) { public boolean complete() { if(!super.complete()) return false; if(mCondition == null) return false; - if(mCondition.getType() == EXPRESSION && !((LeekExpression) mCondition).complete()) return false; + if(mCondition.getNature() == EXPRESSION && !((LeekExpression) mCondition).complete()) return false; return true; } @@ -165,13 +171,13 @@ public void addOperator(int operator, IAWord token) { if(mOperator == 0 && operator == Operators.TERNAIRE){ mOperator = 1; } - else if(mExpression1.getType() == EXPRESSION && !((LeekExpression) mExpression1).complete()) ((LeekExpression) mExpression1).addOperator(operator, token); + else if(mExpression1.getNature() == EXPRESSION && !((LeekExpression) mExpression1).complete()) ((LeekExpression) mExpression1).addOperator(operator, token); else if(mOperator == 1 && operator == Operators.DOUBLE_POINT){ mOperator = 2; } else{ if(mOperator == 0){ - if(mCondition.getType() == EXPRESSION) ((LeekExpression) mCondition).addOperator(operator, token); + if(mCondition.getNature() == EXPRESSION) ((LeekExpression) mCondition).addOperator(operator, token); else{ LeekExpression new_e = new LeekExpression(); new_e.setParent(this); @@ -181,7 +187,7 @@ else if(mOperator == 1 && operator == Operators.DOUBLE_POINT){ } } else if(mOperator == 1){ - if(mExpression1.getType() == EXPRESSION) ((LeekExpression) mExpression1).addOperator(operator, token); + if(mExpression1.getNature() == EXPRESSION) ((LeekExpression) mExpression1).addOperator(operator, token); else{ if(operator == Operators.TERNAIRE){ LeekTernaire new_e = new LeekTernaire(); @@ -200,7 +206,7 @@ else if(mOperator == 1){ } } else{ - if(mExpression2.getType() == EXPRESSION) ((LeekExpression) mExpression2).addOperator(operator, token); + if(mExpression2.getNature() == EXPRESSION) ((LeekExpression) mExpression2).addOperator(operator, token); else{ if(operator == Operators.TERNAIRE){ LeekTernaire new_e = new LeekTernaire(); @@ -223,8 +229,15 @@ else if(mOperator == 1){ @Override public void analyze(WordCompiler compiler) { - if (mCondition != null) mCondition.analyze(compiler); + if (mCondition != null) { + mCondition.analyze(compiler); + operations = mCondition.getOperations(); + } if (mExpression1 != null) mExpression1.analyze(compiler); if (mExpression2 != null) mExpression2.analyze(compiler); + + if (mExpression1 != null && mExpression2 != null && mExpression1.getType() == mExpression2.getType()) { + type = mExpression1.getType(); + } } } diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index 24419d20..b542019e 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -8,37 +8,74 @@ import leekscript.compiler.bloc.FunctionBlock; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.instruction.ClassDeclarationInstruction; +import leekscript.compiler.instruction.LeekVariableDeclarationInstruction; import leekscript.runner.LeekConstants; import leekscript.runner.LeekFunctions; import leekscript.common.Error; +import leekscript.common.Type; public class LeekVariable extends AbstractExpression { public static enum VariableType { - LOCAL, GLOBAL, ARGUMENT, FIELD, STATIC_FIELD, THIS, THIS_CLASS, CLASS, SUPER, METHOD, STATIC_METHOD, SYSTEM_CONSTANT, SYSTEM_FUNCTION, FUNCTION + LOCAL, GLOBAL, ARGUMENT, FIELD, STATIC_FIELD, THIS, THIS_CLASS, CLASS, SUPER, METHOD, STATIC_METHOD, SYSTEM_CONSTANT, SYSTEM_FUNCTION, FUNCTION, ITERATOR } private final IAWord token; private VariableType type; + private Type variableType = Type.ANY; + private LeekVariableDeclarationInstruction declaration; private ClassDeclarationInstruction classDeclaration; + private boolean box; public LeekVariable(IAWord token, VariableType type) { this.token = token; this.type = type; + this.declaration = null; this.classDeclaration = null; + this.box = false; + } + + public LeekVariable(WordCompiler compiler, IAWord token, VariableType type) { + this.token = token; + this.type = type; + this.declaration = null; + this.classDeclaration = null; + this.box = compiler.getVersion() <= 10; + } + + public LeekVariable(IAWord token, VariableType type, boolean box) { + this.token = token; + this.type = type; + this.declaration = null; + this.classDeclaration = null; + this.box = box; + } + + public LeekVariable(IAWord token, VariableType type, LeekVariableDeclarationInstruction declaration) { + this.token = token; + this.type = type; + this.declaration = declaration; + this.classDeclaration = null; + this.box = declaration.isCaptured(); } public LeekVariable(IAWord token, VariableType type, ClassDeclarationInstruction classDeclaration) { this.token = token; this.type = type; this.classDeclaration = classDeclaration; + this.box = false; } @Override - public int getType() { + public int getNature() { return VARIABLE; } + @Override + public Type getType() { + return variableType; + } + @Override public String getString() { return token.getWord(); @@ -70,8 +107,8 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); } else if (type == VariableType.SYSTEM_CONSTANT) { var constant = LeekConstants.get(token.getWord()); - if (constant.getType() == LeekFunctions.INT) writer.addCode("LeekValueManager.getLeekIntValue(" + constant.getIntValue() + ")"); - else if (constant.getType() == LeekFunctions.DOUBLE) writer.addCode("new DoubleLeekValue(" + constant.getValue() + ")"); + if (constant.getType() == Type.INT) writer.addCode("LeekValueManager.getLeekIntValue(" + constant.getIntValue() + ")"); + else if (constant.getType() == Type.REAL) writer.addCode("new DoubleLeekValue(" + constant.getValue() + ")"); else writer.addCode("LeekValueManager.NULL"); } else if (type == VariableType.SYSTEM_FUNCTION) { FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); @@ -110,7 +147,12 @@ public void analyze(WordCompiler compiler) { var v = compiler.getCurrentBlock().getVariable(token.getWord(), true); if (v != null) { this.type = v.getVariableType(); + this.declaration = v.getDeclaration(); this.classDeclaration = v.getClassDeclaration(); + this.box = v.box; + if (v.getDeclaration() != null && v.getDeclaration().getFunction() != compiler.getCurrentFunction()) { + v.getDeclaration().setCaptured(); + } return; } // Global user functions @@ -119,8 +161,10 @@ public void analyze(WordCompiler compiler) { return; } // LS constants - if (LeekConstants.get(token.getWord()) != null) { + var constant = LeekConstants.get(token.getWord()); + if (constant != null) { this.type = VariableType.SYSTEM_CONSTANT; + this.variableType = constant.getType(); return; } // LS functions @@ -135,7 +179,20 @@ public ClassDeclarationInstruction getClassDeclaration() { return classDeclaration; } + public LeekVariableDeclarationInstruction getDeclaration() { + return declaration; + } + public IAWord getToken() { return token; } + + public boolean isBox() { + return this.box || (declaration != null && declaration.isBox()); + } + + public boolean isWrapper() { + return declaration != null && declaration.isWrapper(); + } + } diff --git a/src/main/java/leekscript/compiler/expression/Operators.java b/src/main/java/leekscript/compiler/expression/Operators.java index 4d1c0e99..9fb5de6b 100644 --- a/src/main/java/leekscript/compiler/expression/Operators.java +++ b/src/main/java/leekscript/compiler/expression/Operators.java @@ -33,13 +33,13 @@ public class Operators { public final static int EQUALS_EQUALS = 30; public final static int NOT_EQUALS_EQUALS = 31; public final static int SHIFT_LEFT = 32; - public final static int ROTATE_RIGHT = 33; + public final static int SHIFT_UNSIGNED_RIGHT = 33; public final static int SHIFT_RIGHT = 34; public final static int BITXOR = 35; public final static int BITAND = 36; public final static int BITOR = 37; public final static int SHIFT_LEFT_ASSIGN = 38; - public final static int ROTATE_RIGHT_ASSIGN = 39; + public final static int SHIFT_UNSIGNED_RIGHT_ASSIGN = 39; public final static int SHIFT_RIGHT_ASSIGN = 40; public final static int BITXOR_ASSIGN = 41; public final static int BITAND_ASSIGN = 42; @@ -97,12 +97,12 @@ public final static int getOperator(String operator, int version) { if(operator.equals("~")) return BITNOT; if(operator.equals("<<")) return SHIFT_LEFT; if(operator.equals(">>")) return SHIFT_RIGHT; - if(operator.equals(">>>")) return ROTATE_RIGHT; + if(operator.equals(">>>")) return SHIFT_UNSIGNED_RIGHT; if(operator.equals("&=")) return BITAND_ASSIGN; if(operator.equals("|=")) return BITOR_ASSIGN; if(operator.equals("<<=")) return SHIFT_LEFT_ASSIGN; if(operator.equals(">>=")) return SHIFT_RIGHT_ASSIGN; - if(operator.equals(">>>=")) return ROTATE_RIGHT_ASSIGN; + if(operator.equals(">>>=")) return SHIFT_UNSIGNED_RIGHT_ASSIGN; if(operator.equals("@")) return REFERENCE; if(operator.equals("new")) return NEW; if(operator.equals(".")) return DOT; @@ -138,7 +138,7 @@ public static int getPriority(int operator) { return 10; case SHIFT_LEFT: case SHIFT_RIGHT: - case ROTATE_RIGHT: + case SHIFT_UNSIGNED_RIGHT: return 9; case LESS: case LESSEQUALS: @@ -173,7 +173,7 @@ public static int getPriority(int operator) { case POWERASSIGN: case SHIFT_LEFT_ASSIGN: case SHIFT_RIGHT_ASSIGN: - case ROTATE_RIGHT_ASSIGN: + case SHIFT_UNSIGNED_RIGHT_ASSIGN: case BITAND_ASSIGN: case BITOR_ASSIGN: case BITXOR_ASSIGN: diff --git a/src/main/java/leekscript/compiler/instruction/BlankInstruction.java b/src/main/java/leekscript/compiler/instruction/BlankInstruction.java index bce69693..3d013c85 100644 --- a/src/main/java/leekscript/compiler/instruction/BlankInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/BlankInstruction.java @@ -29,4 +29,9 @@ public boolean putCounterBefore() { public void analyze(WordCompiler compiler) { } + + @Override + public int getOperations() { + return 0; + } } diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 286f0d15..585578cd 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -339,4 +339,20 @@ public LeekVariable getStaticMember(String token) { } return null; } + + public String getMethodName(String name, int argumentCount) { + var versions = methods.get(name); + if (versions != null) { + if (versions.containsKey(argumentCount)) return getName() + "_" + name + "_" + argumentCount; + } + if (parent != null) { + return parent.getMethodName(name, argumentCount); + } + return null; + } + + @Override + public int getOperations() { + return 0; + } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekBreakInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekBreakInstruction.java index 1d412039..14e5fcb5 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekBreakInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekBreakInstruction.java @@ -42,4 +42,9 @@ public boolean putCounterBefore() { public void analyze(WordCompiler compiler) { } + + @Override + public int getOperations() { + return 0; + } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekContinueInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekContinueInstruction.java index 8d8973cd..4fa4c728 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekContinueInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekContinueInstruction.java @@ -42,4 +42,9 @@ public boolean putCounterBefore() { public void analyze(WordCompiler compiler) { } + + @Override + public int getOperations() { + return 0; + } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java index 030291b8..6d7879e1 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java @@ -59,4 +59,9 @@ public boolean putCounterBefore() { public void analyze(WordCompiler compiler) { mExpression.analyze(compiler); } + + @Override + public int getOperations() { + return 0; + } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java index 151749bd..1430dea7 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java @@ -56,7 +56,7 @@ public boolean putCounterBefore() { public void declare(WordCompiler compiler) { // On ajoute la variable - compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.GLOBAL)); + compiler.getCurrentBlock().addVariable(new LeekVariable(compiler, token, VariableType.GLOBAL)); } @Override @@ -65,4 +65,9 @@ public void analyze(WordCompiler compiler) { mValue.analyze(compiler); } } + + @Override + public int getOperations() { + return 0; + } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekInstruction.java index 85da0980..d3560255 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekInstruction.java @@ -15,4 +15,6 @@ public interface LeekInstruction { public boolean putCounterBefore(); public void analyze(WordCompiler compiler); + + public int getOperations(); } diff --git a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java index 772d809f..d5143e81 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java @@ -50,4 +50,9 @@ public void analyze(WordCompiler compiler) { mExpression.analyze(compiler); } } + + @Override + public int getOperations() { + return 0; + } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index af63c63c..7753a45e 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -6,11 +6,14 @@ import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; +import leekscript.compiler.bloc.AbstractLeekBlock; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.AbstractExpression; +import leekscript.compiler.expression.LeekAnonymousFunction; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; import leekscript.common.Error; +import leekscript.common.Type; public class LeekVariableDeclarationInstruction implements LeekInstruction { @@ -18,16 +21,16 @@ public class LeekVariableDeclarationInstruction implements LeekInstruction { private final int mLine; private final AIFile mAI; private AbstractExpression mValue = null; - private boolean mMustSepare = false; + private boolean captured = false; + private AbstractLeekBlock function; + private boolean box = false; - public LeekVariableDeclarationInstruction(IAWord token, int line, AIFile ai) { + public LeekVariableDeclarationInstruction(WordCompiler compiler, IAWord token, int line, AIFile ai, AbstractLeekBlock function) { this.token = token; mLine = line; mAI = ai; - } - - public void mustSepare() { - mMustSepare = true; + this.function = function; + this.box = compiler.getVersion() <= 10; } public void setValue(AbstractExpression value) { @@ -42,15 +45,23 @@ public IAWord getToken() { return this.token; } + public boolean isBox() { + return this.box || this.captured; + } + + public boolean isWrapper() { + return this.captured; + } + @Override public String getCode() { - if(mValue == null) return "var " + token.getWord(); + if (mValue == null) return "var " + token.getWord(); return "var " + token.getWord() + " = " + mValue.getString(); } @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if (!mMustSepare) { + if (!captured || !(mValue instanceof LeekAnonymousFunction)) { writer.addCode("final VariableLeekValue user_" + token.getWord() + " = new VariableLeekValue(mUAI, "); if (mValue != null) mValue.writeJavaCode(mainblock, writer); else writer.addCode("LeekValueManager.NULL"); @@ -68,6 +79,14 @@ public int getEndBlock() { return 0; } + public AbstractLeekBlock getFunction() { + return this.function; + } + + public boolean isCaptured() { + return captured; + } + @Override public boolean putCounterBefore() { return false; @@ -75,9 +94,17 @@ public boolean putCounterBefore() { @Override public void analyze(WordCompiler compiler) { - if (mValue != null) { + function = compiler.getCurrentFunction(); + if (mValue != null && mValue.getType() == Type.FUNCTION) { + registerVariable(compiler); mValue.analyze(compiler); + } else { + if (mValue != null) mValue.analyze(compiler); + registerVariable(compiler); } + } + + private void registerVariable(WordCompiler compiler) { // Variables interdites if (compiler.getVersion() >= 11 && token.getWord().equals("this")) { compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, Error.THIS_NOT_ALLOWED_HERE)); @@ -87,8 +114,21 @@ public void analyze(WordCompiler compiler) { compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); } else { // On ajoute la variable - compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.LOCAL)); + compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.LOCAL, this)); } } } + + public void setCaptured() { + this.captured = true; + } + + public void setFunction(AbstractLeekBlock function) { + this.function = function; + } + + @Override + public int getOperations() { + return 0; + } } diff --git a/src/main/java/leekscript/runner/CallableVersion.java b/src/main/java/leekscript/runner/CallableVersion.java new file mode 100644 index 00000000..a7fbc3ed --- /dev/null +++ b/src/main/java/leekscript/runner/CallableVersion.java @@ -0,0 +1,14 @@ +package leekscript.runner; + +import leekscript.common.Type; + +public class CallableVersion { + + public Type return_type; + public Type[] arguments; + + public CallableVersion(Type return_type, Type[] arguments) { + this.return_type = return_type; + this.arguments = arguments; + } +} diff --git a/src/main/java/leekscript/runner/ILeekConstant.java b/src/main/java/leekscript/runner/ILeekConstant.java index 6884609f..33a7f807 100644 --- a/src/main/java/leekscript/runner/ILeekConstant.java +++ b/src/main/java/leekscript/runner/ILeekConstant.java @@ -1,7 +1,9 @@ package leekscript.runner; +import leekscript.common.Type; + public interface ILeekConstant { abstract public double getValue(); abstract public int getIntValue(); - abstract public int getType(); + abstract public Type getType(); } diff --git a/src/main/java/leekscript/runner/ILeekFunction.java b/src/main/java/leekscript/runner/ILeekFunction.java index a92ac29a..ee1b454d 100644 --- a/src/main/java/leekscript/runner/ILeekFunction.java +++ b/src/main/java/leekscript/runner/ILeekFunction.java @@ -1,5 +1,6 @@ package leekscript.runner; +import leekscript.common.Type; import leekscript.runner.values.AbstractLeekValue; public interface ILeekFunction { @@ -11,4 +12,6 @@ public interface ILeekFunction { abstract public int[] parameters(); abstract public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException; abstract public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException; + abstract public Type getReturnType(); + abstract public CallableVersion[] getVersions(); } diff --git a/src/main/java/leekscript/runner/LeekConstants.java b/src/main/java/leekscript/runner/LeekConstants.java index 3627c43f..3c713979 100644 --- a/src/main/java/leekscript/runner/LeekConstants.java +++ b/src/main/java/leekscript/runner/LeekConstants.java @@ -2,39 +2,41 @@ import java.util.HashMap; +import leekscript.common.Type; + public enum LeekConstants implements ILeekConstant { - PI(Math.PI, LeekFunctions.DOUBLE), - E(Math.E, LeekFunctions.DOUBLE), + PI(Math.PI, Type.REAL), + E(Math.E, Type.REAL), - INSTRUCTIONS_LIMIT(300000, LeekFunctions.INT), - OPERATIONS_LIMIT(20000000, LeekFunctions.INT), + INSTRUCTIONS_LIMIT(300000, Type.INT), + OPERATIONS_LIMIT(20000000, Type.INT), - SORT_ASC(0, LeekFunctions.INT), - SORT_DESC(1, LeekFunctions.INT), + SORT_ASC(0, Type.INT), + SORT_DESC(1, Type.INT), - CELL_EMPTY(0, LeekFunctions.INT), - CELL_PLAYER(1, LeekFunctions.INT), - CELL_OBSTACLE(2, LeekFunctions.INT), + CELL_EMPTY(0, Type.INT), + CELL_PLAYER(1, Type.INT), + CELL_OBSTACLE(2, Type.INT), - COLOR_RED(0xFF0000, LeekFunctions.INT), - COLOR_GREEN(0x00FF00, LeekFunctions.INT), - COLOR_BLUE(0x0000FF, LeekFunctions.INT), + COLOR_RED(0xFF0000, Type.INT), + COLOR_GREEN(0x00FF00, Type.INT), + COLOR_BLUE(0x0000FF, Type.INT), - TYPE_NULL(0, LeekFunctions.INT), - TYPE_NUMBER(1, LeekFunctions.INT), - TYPE_BOOLEAN(2, LeekFunctions.INT), - TYPE_STRING(3, LeekFunctions.INT), - TYPE_ARRAY(4, LeekFunctions.INT), - TYPE_FUNCTION(5, LeekFunctions.INT), - TYPE_OBJECT(6, LeekFunctions.INT); + TYPE_NULL(0, Type.INT), + TYPE_NUMBER(1, Type.INT), + TYPE_BOOLEAN(2, Type.INT), + TYPE_STRING(3, Type.INT), + TYPE_ARRAY(4, Type.INT), + TYPE_FUNCTION(5, Type.INT), + TYPE_OBJECT(6, Type.INT); private static HashMap extraConstants = new HashMap(); private double value; - private int type; + private Type type; - LeekConstants(double value, int type) { + LeekConstants(double value, Type type) { this.value = value; this.type = type; } @@ -43,12 +45,14 @@ public enum LeekConstants implements ILeekConstant { public double getValue() { return value; } + @Override public int getIntValue() { return (int) value; } + @Override - public int getType() { + public Type getType() { return type; } diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index a74d52e9..7aa70083 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -14,6 +14,7 @@ import leekscript.runner.values.NullLeekValue; import leekscript.runner.values.StringLeekValue; import leekscript.common.Error; +import leekscript.common.Type; public enum LeekFunctions implements ILeekFunction { // Fonctions mathématiques @@ -1319,6 +1320,7 @@ public AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue[] private int mArgumentsMin; private int mOperations = 1; protected VariableOperations mVariableOperations = null; + private int[] parameters; public static final int DOUBLE = 1; public static final int INT = 2; @@ -1328,15 +1330,28 @@ public AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue[] public static final int ARRAY = 6; public static final int NUMBER = 7; public static final int FUNCTION = 8; + private Type return_type; + private CallableVersion[] versions; + private boolean direct = false; LeekFunctions(int arguments) { mArgumentsMin = arguments; mArguments = arguments; + this.parameters = new int[0]; } LeekFunctions(int arguments, int arguments_max) { mArgumentsMin = arguments; mArguments = arguments_max; + this.parameters = new int[0]; + } + + public Type getReturnType() { + return return_type; + } + + public CallableVersion[] getVersions() { + return versions; } public static void setExtraFunctions(String extraFunctions) { diff --git a/src/main/java/leekscript/runner/values/LeekValue.java b/src/main/java/leekscript/runner/values/LeekValue.java new file mode 100644 index 00000000..fd9768c9 --- /dev/null +++ b/src/main/java/leekscript/runner/values/LeekValue.java @@ -0,0 +1,54 @@ +package leekscript.runner.values; + +public class LeekValue { + + public final static int NUMBER_V10 = 1; + public final static int BOOLEAN_V10 = 2; + public final static int ARRAY_V10 = 3; + public final static int NULL_V10 = 4; + public final static int STRING_V10 = 5; + public final static int FUNCTION_V10 = 6; + public final static int CLASS_V10 = 7; + public final static int OBJECT_V10 = 8; + + public final static int NULL = 0; + public final static int NUMBER = 1; + public final static int BOOLEAN = 2; + public final static int STRING = 3; + public final static int ARRAY = 4; + public final static int FUNCTION = 5; + public final static int CLASS = 6; + public final static int OBJECT = 7; + + public final static int ADD_COST = 1; + public final static int MUL_COST = 5; + public final static int DIV_COST = 5; + public final static int MOD_COST = 5; + public final static int POW_COST = 140; + + public static String getParamString(Object[] parameters) { + String ret = ""; + for (int j = 0; j < parameters.length; j++) { + if (j != 0) + ret += ", "; + var v = parameters[j]; + if (v == null) + ret += "null"; + else if (v instanceof Number) + ret += "number"; + else if (v instanceof Boolean) + ret += "boolean"; + else if (v instanceof String) + ret += "string"; + else if (v instanceof ArrayLeekValue) + ret += "array"; + else if (v instanceof FunctionLeekValue) + ret += "function"; + else if (v instanceof ObjectLeekValue) + ret += "object"; + else + ret += "?"; + } + return ret; + } +} diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index 8297b170..ea11fe03 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -37,6 +37,10 @@ public void run() { code_v10("var f = function(@a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("12"); code_v11("var f = function(a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("10"); + section("Capture loop variable"); + code("var sum = 0 for (var i = 0; i < 10; ++i) { sum += (function() { return i })() } return sum").equals("45"); + + section("Misc"); code("function f(x) { var s = 0 s |= 12 return s } f(12);").equals("null"); code("function te(a){ return function(){ return a**2; }; } return te(2)();").equals("4"); code("function te(a){ return function(b){ return function(c){return a*b*c;}; }; } return te(2)(1)(2);").equals("4"); From 15d2db2b69ac1b842381df5a013f213c8792df95 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 25 May 2021 21:58:53 +0200 Subject: [PATCH 187/319] [leekscript] Fixes --- src/main/java/leekscript/LSException.java | 12 +++++------- src/main/java/leekscript/TopLevel.java | 5 ++--- src/main/java/leekscript/compiler/JavaWriter.java | 2 +- src/main/java/leekscript/compiler/LeekScript.java | 6 ++---- src/main/java/leekscript/runner/AI.java | 4 ++-- src/test/java/test/TestAI.java | 2 +- 6 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/main/java/leekscript/LSException.java b/src/main/java/leekscript/LSException.java index 228cb0e2..8462bf8c 100644 --- a/src/main/java/leekscript/LSException.java +++ b/src/main/java/leekscript/LSException.java @@ -1,16 +1,14 @@ package leekscript; -import leekscript.runner.values.AbstractLeekValue; - public class LSException extends Exception { private static final long serialVersionUID = -8672880192298794957L; private final int mIndex; - private final AbstractLeekValue mRun; - private final AbstractLeekValue mThe; + private final Object mRun; + private final Object mThe; - public LSException(int i, AbstractLeekValue run, AbstractLeekValue the) { + public LSException(int i, Object run, Object the) { mIndex = i; mRun = run; mThe = the; @@ -20,11 +18,11 @@ public int getIndex() { return mIndex; } - public AbstractLeekValue getRun() { + public Object getRun() { return mRun; } - public AbstractLeekValue getThe() { + public Object getThe() { return mThe; } diff --git a/src/main/java/leekscript/TopLevel.java b/src/main/java/leekscript/TopLevel.java index 29751ce4..9a39b8bd 100644 --- a/src/main/java/leekscript/TopLevel.java +++ b/src/main/java/leekscript/TopLevel.java @@ -5,7 +5,6 @@ import leekscript.compiler.LeekScript; import leekscript.runner.AI; -import leekscript.runner.values.AbstractLeekValue; public class TopLevel { @@ -37,7 +36,7 @@ private static void executeSnippet(String code) { long compileTime = System.currentTimeMillis() - ct; long et = System.currentTimeMillis(); - AbstractLeekValue v = ai.runIA(); + var v = ai.runIA(); long executionTime = System.currentTimeMillis() - et; String result = v.getString(ai); @@ -58,7 +57,7 @@ private static void executeFile(File file) { long compileTime = System.currentTimeMillis() - ct; long et = System.currentTimeMillis(); - AbstractLeekValue v = ai.runIA(); + var v = ai.runIA(); long executionTime = System.currentTimeMillis() - et; String result = v.getString(ai); diff --git a/src/main/java/leekscript/compiler/JavaWriter.java b/src/main/java/leekscript/compiler/JavaWriter.java index 08854a88..51579c91 100644 --- a/src/main/java/leekscript/compiler/JavaWriter.java +++ b/src/main/java/leekscript/compiler/JavaWriter.java @@ -86,7 +86,7 @@ public void writeErrorFunction(IACompiler comp, String ai) { mCode.append(", "); // System.out.println(l.mAI.getPath() + ":" + l.mCodeLine + " -> " + l.mJavaLine); } - mCode.append("};}\nprotected String getAItring() { return "); + mCode.append("};}\nprotected String getAIString() { return "); mCode.append(aiJson); mCode.append(";}\n"); diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index e4aa45d5..fb2dd876 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -25,7 +25,6 @@ import leekscript.compiler.resolver.Resolver; import leekscript.compiler.resolver.ResolverContext; import leekscript.runner.AI; -import leekscript.runner.values.AbstractLeekValue; public class LeekScript { @@ -101,14 +100,13 @@ public static AI compileSnippet(String snippet, String AIClass, int version) thr return compile(ai, AIClass, false); } - - public static AbstractLeekValue runScript(String script, boolean nocache) throws Exception { + public static Object runScript(String script, boolean nocache) throws Exception { return LeekScript.compileSnippet(script, "AI").runIA(); } public static String runFile(String filename) throws Exception { AI ai = LeekScript.compileFile(filename, "AI", true); - AbstractLeekValue v = ai.runIA(); + var v = ai.runIA(); System.out.println(v.getString(ai)); return v.getString(ai); } diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 04fe10ee..dbef274c 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -121,7 +121,7 @@ protected String getErrorLocalisation(int line) { for (String error : getErrorString()) { mErrorObject.add(JSON.parseArray(error)); } - thisObject = getAItring(); + thisObject = getAIString(); } int value = 0; for (int i = 0; i < mErrorObject.size(); i++) { @@ -388,7 +388,7 @@ else if (type == AILog.STANDARD) protected abstract String[] getErrorFiles(); - protected abstract String getAItring(); + protected String getAIString() { return ""; } public abstract AbstractLeekValue runIA() throws LeekRunException; diff --git a/src/test/java/test/TestAI.java b/src/test/java/test/TestAI.java index 493d3d38..cf73785e 100644 --- a/src/test/java/test/TestAI.java +++ b/src/test/java/test/TestAI.java @@ -16,7 +16,7 @@ protected String[] getErrorString() { } @Override - protected String getAItring() { + protected String getAIString() { return null; } From 4ee187993fdc9804a0277a2cf39ee6595e1a3e38 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 188/319] =?UTF-8?q?[test]=20Output=20op=C3=A9rations=20res?= =?UTF-8?q?ults?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/test/TestCommon.java | 16 ++++++++++++++++ src/test/java/test/TestMain.java | 2 ++ 2 files changed, 18 insertions(+) diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index 56c6ed2e..cbc58127 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -1,5 +1,8 @@ package test; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; @@ -27,6 +30,7 @@ public class TestCommon { private static long compile_time = 0; private static long load_time = 0; private static long execution_time = 0; + private static ArrayList operations = new ArrayList<>(); private static List failedTests = new ArrayList(); private static List disabledTests = new ArrayList(); @@ -230,4 +234,16 @@ public static String fn(long n) { formatter.setDecimalFormatSymbols(symbols); return formatter.format(n); } + public static void ouputOperationsFile() { + try { + FileWriter myWriter = new FileWriter("opérations.txt"); + for (Long ops : operations) { + myWriter.write(String.valueOf(ops) + "\n"); + } + myWriter.close(); + } catch (IOException e) { + System.out.println("An error occurred."); + e.printStackTrace(); + } + } } diff --git a/src/test/java/test/TestMain.java b/src/test/java/test/TestMain.java index 86103ab6..44c4c36c 100644 --- a/src/test/java/test/TestMain.java +++ b/src/test/java/test/TestMain.java @@ -37,5 +37,7 @@ public static void main(String[] args) throws Exception { new TestEuler().run(); Assert.assertTrue(TestCommon.summary()); + + TestCommon.ouputOperationsFile(); } } From ca969f0d01d8f9dce8091eacdbf806f7c0b39591 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 189/319] [leekscript] Don't use cache for file --- src/main/java/leekscript/compiler/LeekScript.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index fb2dd876..0c4b9e0c 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -82,7 +82,7 @@ public static AI compileFile(String filepath, String AIClass, boolean useClassCa public static AI compileFile(String filepath, String AIClass, int version) throws LeekScriptException, LeekCompilerException, IOException { AIFile ai = getResolver().resolve(filepath, null); ai.setVersion(version); - return compile(ai, AIClass, true); + return compile(ai, AIClass, false); } public static AI compileFileContext(String filepath, String AIClass, ResolverContext context, boolean useClassCache) throws LeekScriptException, LeekCompilerException, IOException { From 66f5efbc2304764d76e25b74ac71a59ded20d343 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 190/319] =?UTF-8?q?[ops]=20No=20op=C3=A9ration=20for=20clo?= =?UTF-8?q?ning=20primitive?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/leekscript/runner/LeekOperations.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index aa483969..3b0edff1 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -220,16 +220,12 @@ public static AbstractLeekValue moreequals(AI ai, AbstractLeekValue v1, Abstract public static AbstractLeekValue clonePrimitive(AI ai, AbstractLeekValue value) throws LeekRunException { AbstractLeekValue v = value.getValue(); if (v instanceof StringLeekValue) { - ai.addOperations(1); return new StringLeekValue(v.getString(ai)); } else if (v instanceof BooleanLeekValue) { - ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(v.getBoolean()); } else if (v instanceof IntLeekValue) { - ai.addOperations(1); return LeekValueManager.getLeekIntValue(v.getInt(ai)); } else if (v instanceof DoubleLeekValue) { - ai.addOperations(1); return new DoubleLeekValue(v.getDouble(ai)); } else { return value; @@ -242,7 +238,6 @@ public static AbstractLeekValue clone(AI ai, AbstractLeekValue value) throws Lee public static AbstractLeekValue clone(AI ai, AbstractLeekValue value, int level) throws LeekRunException { value = value.getValue(); - ai.addOperations(1); if (value instanceof StringLeekValue) return new StringLeekValue(value.getString(ai)); else if (value instanceof FunctionLeekValue) @@ -255,12 +250,14 @@ else if (value instanceof DoubleLeekValue) return new DoubleLeekValue(value.getDouble(ai)); else if (value instanceof ArrayLeekValue) { if (level == 0) return value; + ai.addOperations(1); if (value.getArray().size() > 0) { ai.addOperations(value.getArray().size() * (ArrayLeekValue.ARRAY_CELL_CREATE_OPERATIONS)); } return new ArrayLeekValue(ai, value.getArray(), level); } else if (value instanceof ObjectLeekValue) { if (level == 0) return value; + ai.addOperations(1); return new ObjectLeekValue(ai, (ObjectLeekValue) value, level); } else if (value instanceof ClassLeekValue) { return value; From 79d6d1c38298387e9b6527fcb8407e230e8cf0a2 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 191/319] [test] Fix ops --- src/test/java/test/TestCommon.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index cbc58127..e601b480 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -128,6 +128,9 @@ public void run_version(int version, Checker checker) { long exec_time = (System.nanoTime() - t) / 1000; TestCommon.execution_time += exec_time / 1000; + long ops = ai.getOperations(); + operations.add(ops); + var vs = v.getString(ai); result = new Result(vs, Error.NONE, (int) ai.getOperations(), exec_time); From 6ba08cc7979a655db638dc4bef4bb8e9451fdb2f Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 192/319] [operator] Fix ops --- src/main/java/leekscript/runner/values/IntLeekValue.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/runner/values/IntLeekValue.java b/src/main/java/leekscript/runner/values/IntLeekValue.java index 8a5a687f..39aac301 100644 --- a/src/main/java/leekscript/runner/values/IntLeekValue.java +++ b/src/main/java/leekscript/runner/values/IntLeekValue.java @@ -68,16 +68,20 @@ public AbstractLeekValue pre_decrement(AI ai) throws LeekRunException { @Override public boolean less(AI ai, AbstractLeekValue comp) throws LeekRunException { comp = comp.getValue(); - if (comp instanceof DoubleLeekValue) + if (comp instanceof DoubleLeekValue) { + ai.addOperations(1); return getDouble(ai) < comp.getDouble(ai); + } return super.less(ai, comp); } @Override public boolean more(AI ai, AbstractLeekValue comp) throws LeekRunException { comp = comp.getValue(); - if (comp instanceof DoubleLeekValue) + if (comp instanceof DoubleLeekValue) { + ai.addOperations(1); return getDouble(ai) > comp.getDouble(ai); + } return super.more(ai, comp); } @@ -157,7 +161,6 @@ public AbstractLeekValue brotate(AI ai, AbstractLeekValue value) throws LeekRunE @Override public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { - ai.addOperations(DIV_COST); return LeekOperations.divide(ai, this, val); } From 97cf2fe999f57e044ae010642eb141bcc554aebc Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 193/319] [test] Fix ops --- src/test/java/test/TestCommon.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index e601b480..c24f84f9 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -110,6 +110,7 @@ public void run_version(int version, Checker checker) { int aiID = 0; Result result; long compile_time = 0; + long ops = 0; try { boolean is_file = code.contains(".leek"); @@ -128,8 +129,7 @@ public void run_version(int version, Checker checker) { long exec_time = (System.nanoTime() - t) / 1000; TestCommon.execution_time += exec_time / 1000; - long ops = ai.getOperations(); - operations.add(ops); + ops = ai.getOperations(); var vs = v.getString(ai); result = new Result(vs, Error.NONE, (int) ai.getOperations(), exec_time); @@ -143,6 +143,8 @@ public void run_version(int version, Checker checker) { result = new Result("error", Error.NONE, 0, 0); } + operations.add(ops); + if (checker.check(result)) { System.out.println(GREEN_BOLD + " [OK] " + END_COLOR + "[v" + version + "] " + code + " === " + checker.getResult(result) + " " + C_GREY + compile_time + "ms + " + fn(result.exec_time) + "µs" + ", " + fn(result.operations) + " ops" + END_COLOR); success++; From 489cdecf2203408c0166caae2e62d513d8f11d95 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 194/319] [operator] Fix ops --- src/main/java/leekscript/runner/LeekFunctions.java | 9 +++++++-- .../java/leekscript/runner/values/AbstractLeekValue.java | 6 +++++- .../java/leekscript/runner/values/ArrayLeekValue.java | 1 + .../java/leekscript/runner/values/StringLeekValue.java | 2 -- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 7aa70083..d6074e0d 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -1034,9 +1034,14 @@ public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue p @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { ArrayLeekValue array = parameters[0].getArray(); - ArrayLeekValue source = LeekOperations.clone(leekIA, parameters[1]).getArray(); + ArrayLeekValue source = parameters[1].getArray(); + // ArrayLeekValue source = LeekOperations.clone(leekIA, parameters[1]).getArray(); for (AbstractLeekValue value : source) { - array.push(leekIA, value.getValue()); + if (leekIA.getVersion() >= 11) { + array.push(leekIA, LeekOperations.clonePrimitive(leekIA, value.getValue())); + } else { + array.push(leekIA, LeekOperations.clone(leekIA, value.getValue())); + } leekIA.addOperations(1); } return LeekValueManager.NULL; diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 9b7f1f08..8b1dbef2 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -100,19 +100,23 @@ public AbstractLeekValue getValue() { return this; } - public AbstractLeekValue not(AI ai) { + public AbstractLeekValue not(AI ai) throws LeekRunException { + ai.addOperations(1); return LeekValueManager.getLeekBooleanValue(!getBoolean()); } public AbstractLeekValue bnot(AI ai) throws LeekRunException { + ai.addOperations(1); return LeekValueManager.getLeekIntValue(~getInt(ai)); } public AbstractLeekValue opposite(AI ai) throws LeekRunException { + ai.addOperations(1); return LeekValueManager.getLeekIntValue(-getInt(ai)); } public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunException { + ai.addOperations(1); return this; } public AbstractLeekValue setRef(AI ai, AbstractLeekValue value) throws LeekRunException { diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index 0ed37dc4..de96b27b 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -277,6 +277,7 @@ public AbstractLeekValue add(AI ai, AbstractLeekValue value) throws LeekRunExcep value = value.getValue(); if (value instanceof ArrayLeekValue) { // mValues.reindex(ai); + ai.addOperations(1); ArrayIterator iterator = value.getArray().getArrayIterator(); while (!iterator.ended()) { if (iterator.key() instanceof String || iterator.key() instanceof ObjectLeekValue) diff --git a/src/main/java/leekscript/runner/values/StringLeekValue.java b/src/main/java/leekscript/runner/values/StringLeekValue.java index f4de2183..325f8f18 100644 --- a/src/main/java/leekscript/runner/values/StringLeekValue.java +++ b/src/main/java/leekscript/runner/values/StringLeekValue.java @@ -26,7 +26,6 @@ public boolean getBoolean() { @Override public int getInt(AI ai) throws LeekRunException { - ai.addOperations(2); if (mValue.isEmpty()) return 0; if (mValue.equals("true")) @@ -43,7 +42,6 @@ public int getInt(AI ai) throws LeekRunException { @Override public double getDouble(AI ai) throws LeekRunException { - ai.addOperations(2); if (mValue.equals("true")) return 1; if (mValue.equals("false")) From 06ff005d77728f31b7ea5566da94304f05a4c9c3 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 195/319] [filter] Optimize --- src/main/java/leekscript/runner/AI.java | 12 ++++++------ src/main/java/leekscript/runner/PhpArray.java | 4 ++++ .../leekscript/runner/values/ArrayLeekValue.java | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index dbef274c..02ad0141 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -240,12 +240,12 @@ public ArrayLeekValue arrayFilter(ArrayLeekValue array, AbstractLeekValue functi if (nb != 1 && nb != 2) return retour; boolean b; - VariableLeekValue value = new VariableLeekValue(this, LeekValueManager.NULL); + // VariableLeekValue value = new VariableLeekValue(this, LeekValueManager.NULL); while (!iterator.ended()) { - value.set(this, iterator.getValueReference()); + // value.set(this, iterator.getValueReference()); if (nb == 1) { - b = function.executeFunction(this, new AbstractLeekValue[] { value }).getBoolean(); - iterator.setValue(this, value); + b = function.executeFunction(this, new AbstractLeekValue[] { iterator.getValueReference() }).getBoolean(); + // iterator.setValue(this, value); if (b) { if (getVersion() >= 11) retour.push(this, iterator.getValue(this).getValue()); @@ -254,8 +254,8 @@ public ArrayLeekValue arrayFilter(ArrayLeekValue array, AbstractLeekValue functi retour.getOrCreate(this, iterator.getKey(this).getValue()).set(this, iterator.getValue(this).getValue()); } } else { - b = function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), value }).getBoolean(); - iterator.setValue(this, value); + b = function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), iterator.getValueReference() }).getBoolean(); + // iterator.setValue(this, value); if (b) if (getVersion() >= 11) retour.push(this, iterator.getValue(this).getValue()); diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 00b3a490..63bed0fe 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -245,6 +245,10 @@ public AbstractLeekValue value() { return value.getValue(); } + public AbstractLeekValue valueRef() { + return value; + } + public void setValue(AI ai, AbstractLeekValue v) throws LeekRunException { value.set(ai, v.getValue()); } diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index de96b27b..4cbb1a9f 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -68,7 +68,7 @@ public AbstractLeekValue getKeyReference() throws LeekRunException { } public AbstractLeekValue getValueReference() throws LeekRunException { - return mElement.value(); + return mElement.valueRef(); } public void setValue(AI ai, VariableLeekValue value) throws LeekRunException { From 8684996d3f5e2d4d57801100782811fa75d681e3 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 196/319] [array] Fix set ops --- src/main/java/leekscript/runner/AI.java | 40 +++++++++---------- .../java/leekscript/runner/LeekFunctions.java | 2 +- .../leekscript/runner/LeekOperations.java | 4 +- .../leekscript/runner/LeekValueManager.java | 2 +- .../runner/values/AbstractLeekValue.java | 5 +++ .../runner/values/ArrayLeekValue.java | 4 +- .../values/PhpArrayVariableLeekValue.java | 7 ++++ .../runner/values/VariableLeekValue.java | 12 ++++++ 8 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 02ad0141..63aa10e6 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -198,17 +198,17 @@ public AbstractLeekValue arrayPartition(ArrayLeekValue array, AbstractLeekValue int nb = function.getArgumentsCount(this); if (nb != 1 && nb != 2) return new ArrayLeekValue(); - VariableLeekValue value = new VariableLeekValue(this, LeekValueManager.NULL); + // VariableLeekValue value = new VariableLeekValue(this, LeekValueManager.NULL); ArrayIterator iterator = array.getArrayIterator(); boolean b; while (!iterator.ended()) { - value.set(this, iterator.getValueReference()); + // value.setNoOps(this, iterator.getValueReference()); if (nb == 1) - b = function.executeFunction(this, new AbstractLeekValue[] { value }).getBoolean(); + b = function.executeFunction(this, new AbstractLeekValue[] { iterator.getValueReference() }).getBoolean(); else - b = function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), value }).getBoolean(); - iterator.setValue(this, value); - (b ? list1 : list2).getOrCreate(this, iterator.getKey(this)).set(this, iterator.getValue(this)); + b = function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), iterator.getValueReference() }).getBoolean(); + // iterator.setValue(this, value); + (b ? list1 : list2).getOrCreate(this, iterator.getKey(this)).setNoOps(this, iterator.getValue(this)); iterator.next(); } return new ArrayLeekValue(this, new AbstractLeekValue[] { list1, list2 }, false); @@ -220,14 +220,14 @@ public ArrayLeekValue arrayMap(ArrayLeekValue array, AbstractLeekValue function) int nb = function.getArgumentsCount(this); if (nb != 1 && nb != 2) return retour; - VariableLeekValue value = new VariableLeekValue(this, LeekValueManager.NULL); + // VariableLeekValue value = new VariableLeekValue(this, LeekValueManager.NULL); while (!iterator.ended()) { - value.set(this, iterator.getValueReference()); + // value.setNoOps(this, iterator.getValueReference()); if (nb == 1) - retour.getOrCreate(this, iterator.getKey(this).getValue()).set(this, function.executeFunction(this, new AbstractLeekValue[] { value })); + retour.getOrCreate(this, iterator.getKey(this).getValue()).setNoOps(this, function.executeFunction(this, new AbstractLeekValue[] { iterator.getValueReference() })); else - retour.getOrCreate(this, iterator.getKey(this).getValue()).set(this, function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), value })); - iterator.setValue(this, value); + retour.getOrCreate(this, iterator.getKey(this).getValue()).setNoOps(this, function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), iterator.getValueReference() })); + // iterator.setValue(this, value); iterator.next(); } return retour; @@ -240,27 +240,23 @@ public ArrayLeekValue arrayFilter(ArrayLeekValue array, AbstractLeekValue functi if (nb != 1 && nb != 2) return retour; boolean b; - // VariableLeekValue value = new VariableLeekValue(this, LeekValueManager.NULL); while (!iterator.ended()) { - // value.set(this, iterator.getValueReference()); if (nb == 1) { b = function.executeFunction(this, new AbstractLeekValue[] { iterator.getValueReference() }).getBoolean(); - // iterator.setValue(this, value); if (b) { if (getVersion() >= 11) retour.push(this, iterator.getValue(this).getValue()); else // In LeekScript < 1.0, arrayFilter had a bug, the result array was not reindexed - retour.getOrCreate(this, iterator.getKey(this).getValue()).set(this, iterator.getValue(this).getValue()); + retour.getOrCreate(this, iterator.getKey(this).getValue()).setNoOps(this, iterator.getValue(this).getValue()); } } else { b = function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), iterator.getValueReference() }).getBoolean(); - // iterator.setValue(this, value); if (b) if (getVersion() >= 11) retour.push(this, iterator.getValue(this).getValue()); else - retour.getOrCreate(this, iterator.getKey(this).getValue()).set(this, iterator.getValue(this).getValue()); + retour.getOrCreate(this, iterator.getKey(this).getValue()).setNoOps(this, iterator.getValue(this).getValue()); } iterator.next(); } @@ -272,14 +268,14 @@ public AbstractLeekValue arrayIter(ArrayLeekValue array, AbstractLeekValue funct int nb = function.getArgumentsCount(this); if (nb != 1 && nb != 2) return LeekValueManager.NULL; - VariableLeekValue value = new VariableLeekValue(this, LeekValueManager.NULL); + // VariableLeekValue value = new VariableLeekValue(this, LeekValueManager.NULL); while (!iterator.ended()) { - value.set(this, iterator.getValueReference()); + // value.setNoOps(this, iterator.getValueReference()); if (nb == 1) - function.executeFunction(this, new AbstractLeekValue[] { value }); + function.executeFunction(this, new AbstractLeekValue[] { iterator.getValueReference() }); else - function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), value }); - iterator.setValue(this, value); + function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), iterator.getValueReference() }); + // iterator.setValue(this, value); iterator.next(); } return LeekValueManager.NULL; diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index d6074e0d..cb2926df 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -977,7 +977,7 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu size = parameters[2].getInt(leekIA); AbstractLeekValue copy = LeekOperations.clone(leekIA, parameters[1].getValue()); for (int i = 0; i < size; i++) { - array.get(leekIA, i).set(leekIA, copy); + array.get(leekIA, i).setNoOps(leekIA, copy); leekIA.addOperations(3); } return LeekValueManager.NULL; diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index 3b0edff1..2bc2bc7d 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -39,7 +39,7 @@ public static AbstractLeekValue add(AI ai, AbstractLeekValue v1, AbstractLeekVal while (!iterator.ended()) { if (iterator.key() instanceof String) { - retour.getOrCreate(ai, iterator.getKey(ai)).set(ai, iterator.getValue(ai)); + retour.getOrCreate(ai, iterator.getKey(ai)).setNoOps(ai, iterator.getValue(ai)); } else { retour.push(ai, iterator.getValue(ai)); } @@ -48,7 +48,7 @@ public static AbstractLeekValue add(AI ai, AbstractLeekValue v1, AbstractLeekVal iterator = v2.getArray().getArrayIterator(); while (!iterator.ended()) { if (iterator.key() instanceof String) { - retour.getOrCreate(ai, iterator.getKey(ai)).set(ai, iterator.getValue(ai)); + retour.getOrCreate(ai, iterator.getKey(ai)).setNoOps(ai, iterator.getValue(ai)); } else { retour.push(ai, iterator.getValue(ai)); } diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index f89a3bcd..62fd4c94 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -126,7 +126,7 @@ public static AbstractLeekValue parseJSON(Object o, AI ai) throws LeekRunExcepti JSONObject a = (JSONObject) o; ArrayLeekValue array = new ArrayLeekValue(); for (String key : a.keySet()) { - array.getOrCreate(ai, new StringLeekValue(key)).set(ai, parseJSON(a.get(key), ai)); + array.getOrCreate(ai, new StringLeekValue(key)).setNoOps(ai, parseJSON(a.get(key), ai)); } return array; } diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 8b1dbef2..84db71d8 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -119,6 +119,11 @@ public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunExcep ai.addOperations(1); return this; } + + public AbstractLeekValue setNoOps(AI ai, AbstractLeekValue value) throws LeekRunException { + return this; + } + public AbstractLeekValue setRef(AI ai, AbstractLeekValue value) throws LeekRunException { return this; } diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index 4cbb1a9f..f1ecf31b 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -89,7 +89,7 @@ public ArrayLeekValue(AI ai, AbstractLeekValue values[], boolean isKeyValue) thr if (isKeyValue) { int i = 0; while (i < values.length) { - getOrCreate(ai, values[i].getValue()).set(ai, values[i + 1].getValue()); + getOrCreate(ai, values[i].getValue()).setNoOps(ai, values[i + 1].getValue()); i += 2; } } else { @@ -281,7 +281,7 @@ public AbstractLeekValue add(AI ai, AbstractLeekValue value) throws LeekRunExcep ArrayIterator iterator = value.getArray().getArrayIterator(); while (!iterator.ended()) { if (iterator.key() instanceof String || iterator.key() instanceof ObjectLeekValue) - mValues.getOrCreate(ai, iterator.getKey(ai).getString(ai)).set(ai, iterator.getValue(ai)); + mValues.getOrCreate(ai, iterator.getKey(ai).getString(ai)).setNoOps(ai, iterator.getValue(ai)); else mValues.push(ai, iterator.getValue(ai)); iterator.next(); diff --git a/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java b/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java index 20d7d093..0484b9b5 100644 --- a/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java @@ -16,4 +16,11 @@ public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunExcep super.set(ai, value); return mValue; } + + @Override + public AbstractLeekValue setNoOps(AI ai, AbstractLeekValue value) throws LeekRunException { + value = value.getValue(); + super.setNoOps(ai, value); + return mValue; + } } diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index 64dcdd2d..c4a1cea0 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -107,6 +107,18 @@ public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunExcep } } + @Override + public AbstractLeekValue setNoOps(AI ai, AbstractLeekValue value) throws LeekRunException { + if (ai.getVersion() >= 11) { + return mValue = LeekOperations.clonePrimitive(ai, value.getValue()); + } else { + if (value.isReference()) + return mValue = value.getValue(); + else + return mValue = LeekOperations.clone(ai, value.getValue()); + } + } + @Override public AbstractLeekValue setRef(AI ai, AbstractLeekValue value) throws LeekRunException { return mValue = value.getValue(); From 1416ded558cf9e63efc160bb6e5782b8d76c8340 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 197/319] [test] Add array tests --- src/test/java/test/TestArray.java | 94 ++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 8 deletions(-) diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index 3a7357f0..b6e98478 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -18,7 +18,7 @@ public void run() throws Exception { code_v11("return [1.21, -5, 4.55, 12, -6.7];").equals("[1.21, -5, 4.55, 12, -6.7]"); code("return [true, false, true];").equals("[true, false, true]"); // DISABLED_code("[23, true, '', {}, 123]").equals("[23, true, '', {}, 123]"); - // DISABLED_code("let a = x -> x [1, 2, a]").equals("[1, 2, ]"); + // DISABLED_code("var a = x -> x [1, 2, a]").equals("[1, 2, ]"); // DISABLED_code("[1m, 34324234m, 231232131232132134379897874534243257343341432423m]").equals("[1, 34324234, 231232131232132134379897874534243257343341432423]"); // DISABLED_code("[true, 'hello', 231232131232132134379897874534243257343341432423m]").equals("[true, 'hello', 231232131232132134379897874534243257343341432423]"); @@ -60,13 +60,13 @@ public void run() throws Exception { code("var a = [5] var b = ['b'] return a + b;").equals("[5, b]"); code("var a = ['a'] return a + ['b'];").equals("[a, b]"); // DISABLED_code("[1, 2] + {};").equals("[1, 2, {}]"); - // DISABLED_code("let a = [1, 2] a + {};").equals("[1, 2, {}]"); + // DISABLED_code("var a = [1, 2] a + {};").equals("[1, 2, {}]"); // DISABLED_code("['a', 'b'] + {};").equals("['a', 'b', {}]"); - // DISABLED_code("let a = ['a', 'b'] a + {}").equals("['a', 'b', {}]"); + // DISABLED_code("var a = ['a', 'b'] a + {}").equals("['a', 'b', {}]"); // DISABLED_code("return ['a', 'b'] + (x -> x)").equals("['a', 'b', ]"); - // DISABLED_code("let a = ['a', 'b'] a + (x -> x)").equals("['a', 'b', ]"); + // DISABLED_code("var a = ['a', 'b'] a + (x -> x)").equals("['a', 'b', ]"); // DISABLED_code("['a', 'b'] + Number").equals("['a', 'b', ]"); - // DISABLED_code("let a = ['a', 'b'] a + Number").equals("['a', 'b', ]"); + // DISABLED_code("var a = ['a', 'b'] a + Number").equals("['a', 'b', ]"); // DISABLED_code("var a = [1, 2] return a + [3, 4];").equals("[1, 2, 3, 4]"); // DISABLED_code("var a = ['a'] return [3.5, 4.6] + a;").equals("[3.5, 4.6, 'a']"); // DISABLED_code("var pq = [] pq = pq + 1 return pq;").equals("[1]"); @@ -78,6 +78,84 @@ public void run() throws Exception { code("var a = null return a['a']").equals("null"); code("var a = null return a[1] = 12").equals("null"); + section("Array.operator []"); + code("return [1, 2, 3][1]").equals("2"); + code("var a = [1, 2, 3] return a[0]").equals("1"); + code_v10("var a = [1.6, 2.5, 3.4] return a[0]").equals("1,6"); + code_v11("var a = [1.6, 2.5, 3.4] return a[0]").equals("1.6"); + code("var a = [1, 2, 3] a[0] = 5 return a[0]").equals("5"); + // code("var a = [23, 23, true, '', [], 123]; return |a|").equals("6"); + code("var a = [] return !a").equals("true"); + code("var a = [1, 2, 3] a[1] = 12 return a").equals("[1, 12, 3]"); + code_v10("return [1.2, 321.42, 23.15]").equals("[1,2, 321,42, 23,15]"); + code_v11("return [1.2, 321.42, 23.15]").equals("[1.2, 321.42, 23.15]"); + // code("return [1, 2, 3, 4, 5][1:3]").equals("[2, 3, 4]"); + code("var a = [5, 'yolo', 12] return a[1]").equals("yolo"); + code("var a = [12]; a[0]++; return a").equals("[13]"); + // code("[1, 2, 'a'][['salut', 2][0]]").exception(ls::vm::Exception::ARRAY_KEY_IS_NOT_NUMBER); + code("return ['a', 'b', 'c'][[2, ''][0]]").equals("c"); + code("var a = [[12], ''][0]; a[0]++; return a").equals("[13]"); + // code("var a = [[12], ''][0] a[a]++ a").exception(ls::vm::Exception::ARRAY_KEY_IS_NOT_NUMBER); + code_v10("var a = [[12], [5.5], ['a']] a[0][0] += 1 a[1][0] += 1 a[2][0] += 1 return a").equals("[[13], [6,5], [a1]]"); + code_v11("var a = [[12], [5.5], ['a']] a[0][0] += 1 a[1][0] += 1 a[2][0] += 1 return a").equals("[[13], [6.5], [a1]]"); + // code("var a = [1, 2, 3] return a[0l]").equals("1"); + // code("var a = [1, 2, 3] return a[1l]").equals("2"); + // code("var a = [1, 2, 3] return a[2m]").equals("3"); + code("var a = ['a', 'b', 'c'] return a[0.5]").equals("a"); + code("var a = ['a', 'b', 'c'] return a[1.9]").equals("b"); + code("return ['', [2][0]]").equals("[, 2]"); + code_v10("return ['', [2.5][0]]").equals("[, 2,5]"); + code_v11("return ['', [2.5][0]]").equals("[, 2.5]"); + code("var a = [1, 2, 3] return a[true]").equals("2"); + code_v10("return [1, 2.5][1]").equals("2,5"); + code_v11("return [1, 2.5][1]").equals("2.5"); + code("return [1, true][0]").equals("1"); + code("return [1, true][1]").equals("true"); + // code("return [5l, 7l, 9l][2l]").equals("9"); + + section("[] operator on unknown arrays"); + code("var v = [['a', 'b'], 12] return v[0][0]").equals("a"); + code("var v = [['a', 'b'], 12] return v[0][1]").equals("b"); + code("var v = [['a', 'b'], 12] return v[0][true]").equals("b"); + // code("[['a', 'b'], 12][0][['yolo', 1][0]]").exception(ls::vm::Exception::ARRAY_KEY_IS_NOT_NUMBER); + code("return [['a', 'b'], 12][0][2]").equals("null"); + code("var v = [['a', 'b'], 12] v[0][0] = 5 return v").equals("[[5, b], 12]"); + code("var v = [['a', 'b'], 12] v[0][2] = 5 return v").equals("[[a, b, 5], 12]"); + // code("var a = [[12], [1..10]][1] return a[5]").equals("6"); + + section("Out of bounds exception"); + code("return [][1]").equals("null"); + code("return [1, 2, 3][100]").equals("null"); + code("var a = [1, 2, 3] return a[10]").equals("null"); + code("return [5.6, 7.2][-5]").equals("null"); + code("return ['hello', true][2]").equals("null"); + code("var a = [1, 2, 3] return a[100] = 12").equals("12"); + code("var a = [1, 2, 3] return a[-100] = 12").equals("12"); + // code("var a = [[12], ''][0]; a[100]++; return a").equals("null"); + // code("var a = [5] var e = a[1] !? 5 return e").equals("5"); + + section("Access with booleans"); + code("return [1, 2, 3][false]").equals("1"); + code("return [1, 2, 3][true]").equals("2"); + code("return ['1', '2', '3'][false]").equals("1"); + code_v10("return [1.5, 2.5, 3.5][true]").equals("2,5"); + code_v11("return [1.5, 2.5, 3.5][true]").equals("2.5"); + + // section("Push with empty array access"); + // code("var a = [] a[] = 12 return a").equals("[12]"); + // code("var a = [1, 2] a[] = 3 return a").equals("[1, 2, 3]"); + // code("var a = [1, 2] a[] = 3 return a").equals("[1, 2, 3]"); + // code("var a = [] a[] = 'a' return a").equals("[a]"); + // code("var a = ['a', 'b'] a[] = 'c' return a").equals("[a, b, c]"); + // code("var a = [1, 'b', true] a[] = function(x) { return x } return a").equals("[1, b, true, ]"); + // code("var a = ['a', 'b', 'c'] a[] = ['d'][0] return a").equals("[a, b, c, d]"); + + section("Methods calls on unknown array"); + code("var a = [1, [1, 2]] return count(a[1])").equals("2"); + code("var a = [1, [1, 2]] push(a[1], 3) return a[1]").equals("[1, 2, 3]"); + code("var a = [1, ['a', 'b']] push(a[1], 'c') return a[1]").equals("[a, b, c]"); + code("var a = [[], ['a']] push(a[1], 'b') return a").equals("[[], [a, b]]"); + section("Array.operator +="); // DISABLED_code("var a = [1.55] a += 12.9 return a;").equals("[1.55]"); // DISABLED_code("var a = ['a'] a += 'b' return a;").equals("['a', 'b']"); @@ -122,9 +200,9 @@ public void run() throws Exception { code("var a = [] a[0] += 1 return a;").equals("[1]"); section("Array.operator ++ on element"); - code("var a = [5] a[0]++ return a;").equals("[6]"); - code("var a = [5, 6, 7] a[0]++ a[1]++ return a;").equals("[6, 7, 7]"); - code("var a = [[5]] a[0][0]++ return a;").equals("[[6]]"); + code("var a = [5]; a[0]++; return a;").equals("[6]"); + code("var a = [5, 6, 7]; a[0]++; a[1]++; return a;").equals("[6, 7, 7]"); + code("var a = [[5]]; a[0][0]++; return a;").equals("[[6]]"); section("Array.operator -- on element"); code("var a = [5] a[0]-- return a;").equals("[4]"); From 0a5554ea8636ffcc7c83852c46ff35e10bfe158c Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 198/319] [parser] Support non-breakable spaces --- src/main/java/leekscript/compiler/WordParser.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index f57a0eb7..5d50ada3 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -314,7 +314,7 @@ else if(c == '{' || c == '}'){ if(c == '{') newWord("{", T_ACCOLADE_LEFT); else newWord("}", T_ACCOLADE_RIGHT); } - else if(c == ' ' || c == '\n' || c == '\t'){ + else if(c == ' ' || c == '\n' || c == '\t' || c == 160 /* NBSP */){ if(type == T_VAR_STRING){ word += c; } @@ -339,13 +339,11 @@ else if(c == ','){ type = T_NOTHING; } newWord(",", T_VIRG); - } - else { + } else { // Tout autre caractère - if(type == T_VAR_STRING){ + if (type == T_VAR_STRING) { word += c; - } - else{ + } else { throw new LeekCompilerException(mAI, line_counter, char_counter, "" + c, Error.INVALID_CHAR); } } From a8cf9fa979bd8cc8d2a9cc25a8a066dbfd77dce2 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 199/319] [test] Add general tests --- src/test/java/test/TestGeneral.java | 70 +++++++++++++++++++++++++ src/test/resources/ai/code/trivial.leek | 2 +- 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index 2ec56e0d..10a4b936 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -34,5 +34,75 @@ public void run() { code("return getGreen(" + 0xAF00 + ")").equals("175"); // Blue code("return getBlue(" + 0xAD + ")").equals("173"); + + section("Type changes"); + code("var a return a = 12").equals("12"); + code("var a a = 12 return a").equals("12"); + code_v10("var a return a = 12.5").equals("12,5"); + code_v11("var a return a = 12.5").equals("12.5"); + code_v10("var a a = 12.5 return a").equals("12,5"); + code_v11("var a a = 12.5 return a").equals("12.5"); + code("var a return a = 'a'").equals("a"); + code("var a a = 'a' return a").equals("a"); + // code("var a return a = 12m").equals("12"); + // code("var a a = 12m return a").equals("12"); + code("var a = 2 return a = 'hello'").equals("hello"); + code("var a = 'hello' return a = 2").equals("2"); + code("var a = 2 a = 'hello' return a").equals("hello"); + code("var a = 2 a = [1, 2] return a").equals("[1, 2]"); + // code("var a = 5.5 a = {} a").equals("{}"); + // code("var a = [5, 7] a = 7 System.print(a)").output("7\n"); + // code("var a = 7 a = [5, 12] a").equals("[5, 12]"); + // code("var a = 7 System.print(a) a = <5, 12> System.print(a)").output("7\n<5, 12>\n"); + // code("var a = 5 a = 200l").equals("200"); + // code("var a = 5 a = 200l a").equals("200"); + // code("var a = 200l a = 5").equals("5"); + // code("var a = 200l a = 5 a").equals("5"); + // code("var a = 5.5 a = 200l a").equals("200"); + code("var a = 5.5 return a = 2").equals("2"); + // code("var a = 5.5 a = 1000m").equals("1000"); + // code("var a = 5.5 a = 2m ** 100").equals("1267650600228229401496703205376"); + // code("var a = 2m return a = 5").equals("5"); + // code("var a = 5.5 System.print(a) a = 2 System.print(a) a = 200l System.print(a) a = 1000m System.print(a) a = 'hello' System.print(a)").output("5.5\n2\n200\n1000\nhello\n"); + // code("var a = [] a = 5m").equals("5"); + + // section("Value.copy()"); + // code("2.copy()").equals("2"); + // code("2.5.copy()").equals("2.5"); + // code("12l.copy()").equals("12"); + // code("100m").equals("100"); + // code("'abc'.copy()").equals("'abc'"); + // code("[].copy()").equals("[]"); + // code("[1, 2, 3].copy()").equals("[1, 2, 3]"); + // code("[1.5, 2.5, 3.5].copy()").equals("[1.5, 2.5, 3.5]"); + // code("[1..1000].copy()").equals("[1..1000]"); + // code("[:].copy()").equals("[:]"); + // code("{}.copy()").equals("{}"); + // code("(x -> x).copy()").equals(""); + // code("Number.copy()").equals(""); + + section("Assignments"); + // code("var b = 0 { b = 12 } return b").equals("12"); + // code("var i = 12 { i = 'salut' } return i").equals("salut"); + // code("var i = 12 {{{ i = 'salut' }}} return i").equals("salut"); + code("var b = 5 if (1) { b = 'salut' } return b").equals("salut"); + code("var b = 5 if (0) { b = 'salut' } return b").equals("5"); + code("var a = 12 if (1) { a = 5 a++ } else { a = 3 } return a").equals("6"); + code_v10("var a = 12 if (0) { a = 5 a++ } else { a = 5.5 } return a").equals("5,5"); + code_v11("var a = 12 if (0) { a = 5 a++ } else { a = 5.5 } return a").equals("5.5"); + // code("var a = 12 if (0) { a = 5 a++ } else { a = 7l } return a").equals("7"); + code("var b = 5 if (1) {} else { b = 'salut' } return b").equals("5"); + code("var b = 5 if (0) {} else { b = 'salut' } return b").equals("salut"); + code("var x = 5 if (true) if (true) x = 'a' return x").equals("a"); + code("var x = 5 if (true) if (true) if (true) if (true) if (true) x = 'a' return x").equals("a"); + // code("var x = 2 var y = { if (x == 0) { return 'error' } 7 * x } return y").equals("14"); + code("var y if (false) { if (true) {;} else { y = 2 } } else { y = 5 } return y").equals("5"); + + section("Assignments with +="); + code_v10("var a = 10 a += 0.5 return a").equals("10,5"); + code_v11("var a = 10 a += 0.5 return a").equals("10.5"); + + section("File"); + file("ai/code/trivial.leek").equals("2"); } } diff --git a/src/test/resources/ai/code/trivial.leek b/src/test/resources/ai/code/trivial.leek index d8263ee9..ce4cc792 100644 --- a/src/test/resources/ai/code/trivial.leek +++ b/src/test/resources/ai/code/trivial.leek @@ -1 +1 @@ -2 \ No newline at end of file +return 2 \ No newline at end of file From 0534f86237dc9af7da927e20e64d12eb71ad77fb Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 200/319] [time] Add times --- .../java/leekscript/compiler/LeekScript.java | 3 +++ src/main/java/leekscript/runner/AI.java | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 0c4b9e0c..81b3d95f 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -210,6 +210,9 @@ protected Class findClass(String name) throws ClassNotFoundException { long load_time = System.nanoTime() - t; ai.setId(file.getId()); + ai.setAnalyzeTime(analyze_time); + ai.setCompileTime(compile_time); + ai.setLoadTime(load_time); if (useClassCache) { aiCache.put(javaClassName, clazz); diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 63aa10e6..0ed9de8b 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -37,6 +37,9 @@ public abstract class AI { protected AI mUAI; protected int mInstructions; protected RandomGenerator randomGenerator; + private long analyzeTime; + private long compileTime; + private long loadTime; public AI(int instructions, int version) { this.mInstructions = instructions; @@ -403,4 +406,28 @@ public RandomGenerator getRandom() { } public abstract int getVersion(); + + public long getLoadTime() { + return loadTime; + } + + public void setLoadTime(long loadTime) { + this.loadTime = loadTime; + } + + public long getCompileTime() { + return compileTime; + } + + public void setCompileTime(long compileTime) { + this.compileTime = compileTime; + } + + public long getAnalyzeTime() { + return analyzeTime; + } + + public void setAnalyzeTime(long analyzeTime) { + this.analyzeTime = analyzeTime; + } } From 2dabfa4655128232cc0cf2f5d33461093268f36f Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 201/319] [test] Add more tests --- src/test/java/test/TestFunction.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index ea11fe03..4373de0c 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -53,5 +53,15 @@ public void run() { code("var a = [1, 2, 3] function test(x) { push(x, 10) return x } return [a, test([])]").equals("[[1, 2, 3], [10]]"); code("function f(arg, arg) { return arg } return f(1, 2)").error(Error.PARAMETER_NAME_UNAVAILABLE); + section("Knapsack variants"); + code("var items = [[37, 3], [47, 10], [28, 5]] var all = []; return count(all);").equals("0"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) {}; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var cost = item[1]; if (cost > tp) continue; var copy = current; push(copy[1], @[item, cost, 1]); } }; aux([0, []], 0, 25); return count(all);").equals("0"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var cost = item[1]; if (cost > tp) continue; var copy = current; push(copy[1], @[item, cost, 1]); aux(copy, j, tp - cost); } }; aux([0, []], 0, 25); return count(all);").equals("44"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { var new_added = added; new_added[1] = true; }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var new_added = added; new_added[1] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var new_added = added; new_added[item_id] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; push(copy[1], @[item, cost, 1]); copy[0] += cost; aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("44"); } } From 9ced6ec7e3e74a909ace0d2431d64de31d3869bd Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 202/319] [array] Fix ops --- src/main/java/leekscript/runner/PhpArray.java | 6 ++++-- src/test/java/test/TestArray.java | 2 ++ src/test/java/test/TestFunction.java | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 63bed0fe..25666d63 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -856,11 +856,13 @@ private void destroyElement(Element e) throws LeekRunException { } private Element getElement(AI ai, Object key) throws LeekRunException { + + int operations = ArrayLeekValue.ARRAY_CELL_ACCESS_OPERATIONS; + ai.addOperationsNoCheck(operations); + if (mTable == null) { return null; // empty array } - int operations = ArrayLeekValue.ARRAY_CELL_ACCESS_OPERATIONS; - ai.addOperationsNoCheck(operations); int hash = key.hashCode(); int index = getIndex(hash); diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index b6e98478..8d3761dd 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -131,6 +131,8 @@ public void run() throws Exception { code("return ['hello', true][2]").equals("null"); code("var a = [1, 2, 3] return a[100] = 12").equals("12"); code("var a = [1, 2, 3] return a[-100] = 12").equals("12"); + code("var a = [] a[100] = true return a").equals("[100 : true]"); + code("var a = [1, 2, 3] a[100] = true return a").equals("[0 : 1, 1 : 2, 2 : 3, 100 : true]"); // code("var a = [[12], ''][0]; a[100]++; return a").equals("null"); // code("var a = [5] var e = a[1] !? 5 return e").equals("5"); diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index 4373de0c..b6c4b35a 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -58,6 +58,9 @@ public void run() { code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) {}; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var cost = item[1]; if (cost > tp) continue; var copy = current; push(copy[1], @[item, cost, 1]); } }; aux([0, []], 0, 25); return count(all);").equals("0"); code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var cost = item[1]; if (cost > tp) continue; var copy = current; push(copy[1], @[item, cost, 1]); aux(copy, j, tp - cost); } }; aux([0, []], 0, 25); return count(all);").equals("44"); + code_v10("var added = [] added[1] = true;").equals("null"); + code_v10("var added = [] var new_added = added;").equals("null"); + code_v10("var added = [] var new_added = added; new_added[1] = true;").equals("null"); code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { var new_added = added; new_added[1] = true; }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var new_added = added; new_added[1] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var new_added = added; new_added[item_id] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); From 6528f0bdda7a02c033e1280f3149e03725a725c6 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 203/319] [array] Optimize array growth --- src/main/java/leekscript/runner/PhpArray.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 25666d63..5711e0e9 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -679,13 +679,12 @@ public void set(AI ai, Object key, AbstractLeekValue value) throws LeekRunExcept public AbstractLeekValue getOrCreate(AI ai, Object key) throws LeekRunException { Element e = getElement(ai, key); if (e == null) { - e = createElement(ai, key, LeekValueManager.NULL); - pushElement(e); - mSize++; - if (mSize > capacity) { + if (mSize + 1 > capacity) { growCapacity(ai); - e = getElement(ai, key); } + mSize++; + e = createElement(ai, key, LeekValueManager.NULL); + pushElement(e); } return e.value; } From ab9fb9dc31cc9e6720d484b5beb8e5da3138146a Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 204/319] [array] Optimize size --- src/main/java/leekscript/runner/PhpArray.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 5711e0e9..86bbf628 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -17,7 +17,7 @@ public class PhpArray implements Iterable { - private final static int START_CAPACITY = 16; + private final static int START_CAPACITY = 8; private final static int MAX_CAPACITY = 32000; public final static int ASC = 1; @@ -264,7 +264,9 @@ public void setValue(AI ai, AbstractLeekValue v) throws LeekRunException { public PhpArray() {} public PhpArray(AI ai, int capacity) throws LeekRunException { - initTable(ai, capacity); + if (capacity > 0) { + initTable(ai, capacity); + } } public PhpArray(AI ai, PhpArray phpArray, int level) throws LeekRunException { @@ -287,9 +289,10 @@ public PhpArray(AI ai, PhpArray phpArray, int level) throws LeekRunException { } private void initTable(AI ai, int capacity) throws LeekRunException { - ai.addOperationsNoCheck(capacity / 5); - this.capacity = capacity; - mTable = new Element[capacity]; + int realCapacity = Math.max(START_CAPACITY, capacity); + ai.addOperationsNoCheck(realCapacity / 5); + this.capacity = realCapacity; + mTable = new Element[realCapacity]; } private void growCapacity(AI ai) throws LeekRunException { @@ -297,7 +300,7 @@ private void growCapacity(AI ai) throws LeekRunException { if (capacity == MAX_CAPACITY) return; // Copy in a new array - int new_capacity = Math.min(capacity * 2, MAX_CAPACITY); + int new_capacity = Math.min(Math.max(START_CAPACITY, capacity * 2), MAX_CAPACITY); PhpArray newArray = new PhpArray(ai, new_capacity); Element e = mHead; while (e != null) { @@ -679,7 +682,7 @@ public void set(AI ai, Object key, AbstractLeekValue value) throws LeekRunExcept public AbstractLeekValue getOrCreate(AI ai, Object key) throws LeekRunException { Element e = getElement(ai, key); if (e == null) { - if (mSize + 1 > capacity) { + if (mSize >= capacity) { growCapacity(ai); } mSize++; From a5c066ad2d86e8af47bf312f397ceb306c786f77 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 205/319] [function] Add tests --- src/test/java/test/TestFunction.java | 25 ++++++ src/test/java/test/TestMain.java | 1 + src/test/java/test/TestMap.java | 127 +++++++++++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 src/test/java/test/TestMap.java diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index b6c4b35a..287e1b8a 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -55,6 +55,11 @@ public void run() { code("function f(arg, arg) { return arg } return f(1, 2)").error(Error.PARAMETER_NAME_UNAVAILABLE); section("Knapsack variants"); code("var items = [[37, 3], [47, 10], [28, 5]] var all = []; return count(all);").equals("0"); + code_v10("var aux; aux = function() {}; aux();").equals("null"); + code_v10("var aux = function(current) {}; aux([0, []]);").equals("null"); + code_v10("var aux = function(@current) {}; aux([0, []]);").equals("null"); + code_v10("var aux; aux = function(current, i, tp, added, last) {}; aux([0, []], 0, 25, [], -1);").equals("null"); + code_v10("var aux; aux = function(@current, i, tp, added, last) {}; aux([0, []], 0, 25, [], -1);").equals("null"); code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) {}; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var cost = item[1]; if (cost > tp) continue; var copy = current; push(copy[1], @[item, cost, 1]); } }; aux([0, []], 0, 25); return count(all);").equals("0"); code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var cost = item[1]; if (cost > tp) continue; var copy = current; push(copy[1], @[item, cost, 1]); aux(copy, j, tp - cost); } }; aux([0, []], 0, 25); return count(all);").equals("44"); @@ -65,6 +70,26 @@ public void run() { code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var new_added = added; new_added[1] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var new_added = added; new_added[item_id] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var aux; aux = function(@current, i, tp, added) { for (var j = i; j < 3; ++j) { if (tp < 0) continue; var new_added = added; new_added[2] = true; var copy = current; } }; aux([0, []], 0, 25, []);").equals("null"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { for (var j = i; j < 3; ++j) { if (tp < 0) continue; var new_added = added; new_added[2] = true; var copy = current; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var aux; aux = function(@current, i, tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; }; aux([0, []], 0, 25, []);").equals("null"); + code_v10("var add = [2: 2] var copy = add;").equals("null"); + code_v10("var add = [2: true] var copy = add;").equals("null"); + code_v10("var add = [] add[2] = true; add[2] = true;").equals("null"); + code_v10("var add = [] add[2] = true; var copy = add;").equals("null"); + code_v10("var aux = function(tp, add) { if (tp < 0) return; aux(tp - 5, add); }; aux(25, []);").equals("null"); + code_v10("var aux = function(tp, add) { if (tp < 0) return; aux(tp - 5, add); }; aux(25, [1, 2, 3]);").equals("null"); + code_v10("var aux = function(tp, add) { if (tp < 0) return; push(add, 2); aux(tp - 5, add); }; aux(25, []);").equals("null"); + code_v10("var aux = function(tp, add) { if (tp < 0) return; add[2] = true; aux(tp - 5, add); }; aux(25, []);").equals("null"); + code_v10("var aux = function(tp, add) { if (tp < 0) return; var new_add = add; aux(tp - 5, new_add); }; aux(25, []);").equals("null"); + code_v10("var aux = function(tp, add) { if (tp < 0) return; var new_add = add; new_add[2] = true; aux(tp - 5, new_add); }; aux(25, []);").equals("null"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var aux; aux = function(tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; aux(tp - 5, new_added); }; aux(25, []);").equals("null"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var aux; aux = function(@current, i, tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; aux([], i, tp - 5, new_added); }; aux([0, []], 0, 25, []);").equals("null"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; aux([], i, tp - 5, new_added); }; aux([0, []], 0, 25, []); return count(all);").equals("0"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; var copy = current; aux(copy, i, tp - 5, new_added); }; aux([0, []], 0, 25, []); return count(all);").equals("0"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { for (var j = i; j < 3; ++j) { if (tp < 0) continue; var new_added = added; new_added[2] = true; var copy = current; aux(copy, j, tp - 5, new_added, 1); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; push(copy[1], @[item, cost, 1]); aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("44"); code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; push(copy[1], @[item, cost, 1]); copy[0] += cost; aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("44"); } } diff --git a/src/test/java/test/TestMain.java b/src/test/java/test/TestMain.java index 44c4c36c..3a5de999 100644 --- a/src/test/java/test/TestMain.java +++ b/src/test/java/test/TestMain.java @@ -26,6 +26,7 @@ public static void main(String[] args) throws Exception { new TestNumber().run(); new TestString().run(); new TestArray().run(); + new TestMap().run(); new TestComments().run(); new TestOperators().run(); new TestReference().run(); diff --git a/src/test/java/test/TestMap.java b/src/test/java/test/TestMap.java new file mode 100644 index 00000000..ee83ad52 --- /dev/null +++ b/src/test/java/test/TestMap.java @@ -0,0 +1,127 @@ +package test; + +public class TestMap extends TestCommon { + + public void run() { + header("Map"); + + section("Constructor"); + // code("[:]").equals("[:]"); + code("return []").equals("[]"); + code("return [1: 1, 2: 2]").equals("[1 : 1, 2 : 2]"); + code("return [1: 1, 2: 'a']").equals("[1 : 1, 2 : a]"); + code("return ['1': 'a', '1': 'b', '1': 'c']").equals("[1 : c]"); + + section("Map::to_bool()"); + // code("![:]").equals("true"); + code("return ![]").equals("true"); + code("return ![2: 2]").equals("false"); + code("if ([2: 2]) { return 12 } else { return 5 }").equals("12"); + + section("Array of maps"); + code("return [[], [1: 1], [1: 2]]").equals("[[], [1 : 1], [1 : 2]]"); + // code("return [[:], [1: 1], [1: 2]]").equals("[[:], [1: 1], [1: 2]]"); + code("var m = ['a': 'b'] return [m]").equals("[[a : b]]"); + + /* + * Operators + */ + var maps = new String[] {"[5: 5]", "[5: 9.99]", "[5: 'abc']", "[9.99: 5]", "[9.99: 9.99]", "[9.99: 'abc']", "['abc': 5]", "['abc': 9.99]", "['abc': 'abc']"}; + + section("Map.operator =="); + code("return ['a': 'b'] == [1: 1]").equals("false"); + code("return ['a': 'b'] == ['a': 'b']").equals("true"); + code("return ['a': 'b'] == ['a': 'b', 'c': 'd']").equals("false"); + // code("var x = ['a' : 'b'] var y = [1 : 1] return x.clear() == y.clear()").equals("true"); + for (var m1 : maps) + for (var m2 : maps) + code("return " + m1 + " == " + m2).equals(m1 == m2 ? "true" : "false"); + code("return [12.5: 9.99] == 'hello'").equals("false"); + + // section("Map.operator <"); + // code("return ['a': 1, 'b': 2] < ['a': 1, 'b': 3]").equals("true"); + // code("return [1: 1, 2: 0] < [1: 1, 2: true]").equals("false"); + // code("return [1: 1, 2: 0.5] < [1: 1, 2: true]").equals("false"); + // code("return [1: 1, 2: 'a'] < [1: 1.5, 2: 5.5]").equals("true"); + // for (var i = 0; i < maps.length; ++i) + // for (var j = 0; j < maps.length; ++j) + // code("return " + maps[i] + " < " + maps[j]).equals(i < j ? "true" : "false"); + + // section("Map.operator in"); + // code("var m = ['salut': 12] return 'salut' in m").equals("true"); + // code("var m = ['salut': 12] return 'salum' in m").equals("false"); + // code("var m = ['salut': 12] return 12 in m.values()").equals("true"); + + section("Map.operator []"); + code("var m = [1: 1] return m[1]").equals("1"); + code("var m = ['a': 'b'] return m['a']").equals("b"); + code("var m = [5: 12] return m[5]").equals("12"); + code_v10("var m = [5: 12.5] return m[5]").equals("12,5"); + code_v11("var m = [5: 12.5] return m[5]").equals("12.5"); + code("var m = [5.5: 12] return m[5.5]").equals("12"); + code_v10("var m = [5.5: 12.5] return m[5.5]").equals("12,5"); + code_v11("var m = [5.5: 12.5] return m[5.5]").equals("12.5"); + code("var m = ['salut': 12] return m['salut']").equals("12"); + code_v10("var m = ['salut': 12.5] return m['salut']").equals("12,5"); + code_v11("var m = ['salut': 12.5] return m['salut']").equals("12.5"); + code("var m = ['salut': 'yolo'] return m['salut']").equals("yolo"); + code("var m = ['a': 'b'] m['a'] = 'c' return m").equals("[a : c]"); + code("var m = ['salut': 12] m['salut'] = 13 return m['salut']").equals("13"); + code("var m = ['salut': 'yo'] m['salut'] = 'ya' return m['salut']").equals("ya"); + code("var m = [5: 12] return m[5.7]").equals("12"); + // code("var m = [5: 12] m['salut']").error(ls::Error::INVALID_MAP_KEY, {"'salut'", "m", env.tmp_string->to_string()}); + // code("var m = [5.7: 'hello'] m['salut']").error(ls::Error::INVALID_MAP_KEY, {"'salut'", "m", env.tmp_string->to_string()}); + code("var m = [1: 'a', 2: 'b'] m[2] = 'B' return m").equals("[1 : a, 2 : B]"); + // code("var m = [1: 'a', 2: 'b'] m[3]").exception(ls::vm::Exception::ARRAY_OUT_OF_BOUNDS); + code("var m = [1: 2, 3: 4] m[5] = 6 return m").equals("[1 : 2, 3 : 4, 5 : 6]"); + code("var m = ['a': 2, 'b': 4] m['c'] = 6 return m").equals("[a : 2, b : 4, c : 6]"); + code_v10("var m = ['a': 2.5, 'b': 4.8] m['c'] = 6.9 return m").equals("[a : 2,5, b : 4,8, c : 6,9]"); + code_v11("var m = ['a': 2.5, 'b': 4.8] m['c'] = 6.9 return m").equals("[a : 2.5, b : 4.8, c : 6.9]"); + code("var m = [1: 'a', 2: 'b'] m[3] = 'c' return m").equals("[1 : a, 2 : b, 3 : c]"); + code("var m = ['a': '2', 'b': '4'] m['c'] = '6' return m").equals("[a : 2, b : 4, c : 6]"); + code("var m = [1: 2, 3: 4] m[3] = 6 return m").equals("[1 : 2, 3 : 6]"); + code_v10("var m = [1: 2.5, 3: 4.5] m[3] = 6.5 return m").equals("[1 : 2,5, 3 : 6,5]"); + code_v11("var m = [1: 2.5, 3: 4.5] m[3] = 6.5 return m").equals("[1 : 2.5, 3 : 6.5]"); + // code_v10("var m = [1.5: 2, 3.5: 4] m[3.5] = 6 return m").equals("[1,5 : 2, 3,5 : 6]"); + // code_v11("var m = [1.5: 2, 3.5: 4] m[3.5] = 6 return m").equals("[1.5 : 2, 3.5 : 6]"); + // code_v10("var m = [1.5: 2.5, 3.5: 4.5] m[3.5] = 6.5 return m").equals("[1,5 : 2,5, 3,5 : 6,5]"); + // code_v11("var m = [1.5: 2.5, 3.5: 4.5] m[3.5] = 6.5 return m").equals("[1.5 : 2.5, 3.5 : 6.5]"); + code("var m = ['1': 2, '3': 4] m['3'] = 6 return m").equals("[1 : 2, 3 : 6]"); + // code_v10("var m = [1.5: 'a', 2.5: 'b'] m[2.5] = 'c' return m").equals("[1,5 : a, 2,5 : c]"); + // code_v11("var m = [1.5: 'a', 2.5: 'b'] m[2.5] = 'c' return m").equals("[1.5 : a, 2.5 : c]"); + code("return ['', [1: 2][1]]").equals("[, 2]"); + code_v10("return ['', [1: 2.5][1]]").equals("[, 2,5]"); + code_v11("return ['', [1: 2.5][1]]").equals("[, 2.5]"); + code("var m = [] var ns = '01234566' return m[ns] = 1").equals("1"); + + section("Map.operator [] left-value"); + code("var m = [1: 2] m[1]++ return m").equals("[1 : 3]"); + code("var m = ['a': 2] m['a']++ return m").equals("[a : 3]"); + code("var k = ['a', 12][0] var m = ['a': 2] m[k]++ return m").equals("[a : 3]"); + + // section("Map.operator [] on unknown maps"); + // code("var m = ptr(['a': '2']) m['c'] = '6' return m").equals("['a': '2', 'c': '6']"); + // code("var m = ptr([2: 'a']) m[3] = 'b' return m").equals("[2: 'a', 3: 'b']"); + // code("var m = ptr([2.5: 'a']) m[3.6] = 'b' return m").equals("[2.5: 'a', 3.6: 'b']"); + // code("var m = ptr(['a': 2]) m['c'] = 6 m").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var m = ptr(['a': 2.2]) m['c'] = 6.6 m").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var m = ptr([2: 2]) m[3] = 6 m").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var m = ptr([2.5: 2]) m[3.5] = 6 m").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var m = ptr([2.5: 2.8]) m[3.5] = 6 m").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var m = ptr([2: 2.8]) m[3] = 6 m").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var m = ptr([2: 'a']) m['toto'] = 'b' m").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + // code("var m = ptr([2.5: 'a']) m['toto'] = 'b' m").exception(ls::vm::Exception::NO_SUCH_OPERATOR); + + /* + * Iteration + */ + // section("Map iteration"); + // code("for k, v in [:] { System.print(k + ' ' + v) }").output(""); + // code("for k, v in [1:2] { System.print(k + ' ' + v) }").output("1 2\n"); + // code("for k, v in [1:2,3:4] { System.print(k + ' ' + v) }").output("1 2\n3 4\n"); + // code("for k, v in [1:2,3:4,5:6] { System.print(k + ' ' + v) }").output("1 2\n3 4\n5 6\n"); + // code("for k, v in ['a':'b'] { System.print(k + ' ' + v) }").output("a b\n"); + // code("for k, v in ['a':'b','c':'d'] { System.print(k + ' ' + v) }").output("a b\nc d\n"); + // code("for k, v in ['a':'b','c':'d','e':'f'] { System.print(k + ' ' + v) }").output("a b\nc d\ne f\n"); + } +} From 2f5ff460c4c54fb78f4e6714a8e88f13996d6138 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 206/319] [random] Seed random --- src/test/java/test/TestCommon.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index c24f84f9..17561fbf 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -111,6 +111,7 @@ public void run_version(int version, Checker checker) { Result result; long compile_time = 0; long ops = 0; + LeekScript.getRandom().seed(123456789); try { boolean is_file = code.contains(".leek"); From 8f0611d99d2314127728ddcdc3321eaa93b744af Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 207/319] [variable] Fix variables --- .../runner/values/FunctionLeekValue.java | 2 +- .../runner/values/VariableLeekValue.java | 30 ++++++++----------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index 52a7673f..4ab0b28d 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -78,7 +78,7 @@ public int getType() { private AbstractLeekValue[] copyValues(AI uai, AbstractLeekValue[] values, boolean[] references) throws LeekRunException { AbstractLeekValue[] copy = new AbstractLeekValue[values.length]; for (int i = 0; i < values.length; i++) { - if (!references[i]) + if (!references[i] && values[i] instanceof VariableLeekValue) copy[i] = LeekOperations.clone(uai, values[i]); else copy[i] = values[i]; diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index c4a1cea0..87c3f672 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -23,13 +23,10 @@ public VariableLeekValue(AI ai, AbstractLeekValue value) throws LeekRunException if (ai.getVersion() >= 11) { mValue = LeekOperations.clonePrimitive(ai, value.getValue()); } else { - if (!(value instanceof VariableLeekValue)) - mValue = value.getValue(); + if (value instanceof VariableLeekValue) + mValue = LeekOperations.clone(ai, value.getValue()); else - if (value.isReference()) - mValue = value.getValue(); - else - mValue = LeekOperations.clone(ai, value.getValue()); + mValue = value.getValue(); } } @@ -38,13 +35,10 @@ public void init(AI ai, AbstractLeekValue value) throws LeekRunException { if (ai.getVersion() >= 11) { mValue = LeekOperations.clonePrimitive(ai, value.getValue()); } else { - if (!(value instanceof VariableLeekValue)) - mValue = value.getValue(); + if (value instanceof VariableLeekValue) + mValue = LeekOperations.clone(ai, value.getValue()); else - if (value.isReference()) - mValue = value.getValue(); - else - mValue = LeekOperations.clone(ai, value.getValue()); + mValue = value.getValue(); } } @@ -100,10 +94,10 @@ public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunExcep if (ai.getVersion() >= 11) { return mValue = LeekOperations.clonePrimitive(ai, value.getValue()); } else { - if (value.isReference()) - return mValue = value.getValue(); - else + if (value instanceof VariableLeekValue) return mValue = LeekOperations.clone(ai, value.getValue()); + else + return mValue = value.getValue(); } } @@ -112,10 +106,10 @@ public AbstractLeekValue setNoOps(AI ai, AbstractLeekValue value) throws LeekRun if (ai.getVersion() >= 11) { return mValue = LeekOperations.clonePrimitive(ai, value.getValue()); } else { - if (value.isReference()) - return mValue = value.getValue(); - else + if (value instanceof VariableLeekValue) return mValue = LeekOperations.clone(ai, value.getValue()); + else + return mValue = value.getValue(); } } From 6d1b3656cd4f84b1ed39c9a4a8c68fb2bbfbd758 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 208/319] [test] Add tests --- src/test/java/test/TestFiles.java | 11 ++++++ src/test/java/test/TestFunction.java | 38 +++++++++++++++++++ src/test/java/test/TestReference.java | 3 ++ .../ai/code/reachable_cells_variant_1.leek | 38 +++++++++++++++++++ .../ai/code/reachable_cells_variant_10.leek | 6 +++ .../ai/code/reachable_cells_variant_2.leek | 35 +++++++++++++++++ .../ai/code/reachable_cells_variant_3.leek | 20 ++++++++++ .../ai/code/reachable_cells_variant_4.leek | 19 ++++++++++ .../ai/code/reachable_cells_variant_5.leek | 29 ++++++++++++++ .../ai/code/reachable_cells_variant_6.leek | 13 +++++++ .../ai/code/reachable_cells_variant_7.leek | 25 ++++++++++++ .../ai/code/reachable_cells_variant_8.leek | 18 +++++++++ .../ai/code/reachable_cells_variant_9.leek | 15 ++++++++ 13 files changed, 270 insertions(+) create mode 100644 src/test/resources/ai/code/reachable_cells_variant_1.leek create mode 100644 src/test/resources/ai/code/reachable_cells_variant_10.leek create mode 100644 src/test/resources/ai/code/reachable_cells_variant_2.leek create mode 100644 src/test/resources/ai/code/reachable_cells_variant_3.leek create mode 100644 src/test/resources/ai/code/reachable_cells_variant_4.leek create mode 100644 src/test/resources/ai/code/reachable_cells_variant_5.leek create mode 100644 src/test/resources/ai/code/reachable_cells_variant_6.leek create mode 100644 src/test/resources/ai/code/reachable_cells_variant_7.leek create mode 100644 src/test/resources/ai/code/reachable_cells_variant_8.leek create mode 100644 src/test/resources/ai/code/reachable_cells_variant_9.leek diff --git a/src/test/java/test/TestFiles.java b/src/test/java/test/TestFiles.java index a7e6baee..88a1dc75 100644 --- a/src/test/java/test/TestFiles.java +++ b/src/test/java/test/TestFiles.java @@ -12,6 +12,17 @@ public void run() { file("ai/code/gcd.leek").equals("151"); file("ai/code/strings.leek").equals("true"); file("ai/code/reachable_cells.leek").equals("383"); + file("ai/code/reachable_cells.leek").equals("383"); + file("ai/code/reachable_cells_variant_1.leek").equals("400"); + file("ai/code/reachable_cells_variant_2.leek").equals("481"); + file("ai/code/reachable_cells_variant_3.leek").equals("16"); + file("ai/code/reachable_cells_variant_4.leek").equals("2"); + file("ai/code/reachable_cells_variant_5.leek").equals("5"); + file("ai/code/reachable_cells_variant_6.leek").equals("4"); + file("ai/code/reachable_cells_variant_7.leek").equals("5"); + file("ai/code/reachable_cells_variant_8.leek").equals("null"); + file("ai/code/reachable_cells_variant_9.leek").equals("null"); + file("ai/code/reachable_cells_variant_10.leek").equals("null"); file("ai/code/french.leek").equals("cent-soixante-huit millions quatre-cent-quatre-vingt-neuf-mille-neuf-cent-quatre-vingt-dix-neuf"); // DISABLED_file("test/code/break_and_continue.leek").equals("2504"); file("ai/code/french.min.leek").equals("neuf-cent-quatre-vingt-sept milliards six-cent-cinquante-quatre millions trois-cent-vingt-et-un-mille-douze"); diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index 287e1b8a..cb81a357 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -40,6 +40,15 @@ public void run() { section("Capture loop variable"); code("var sum = 0 for (var i = 0; i < 10; ++i) { sum += (function() { return i })() } return sum").equals("45"); + section("Return reference"); + code_v10("global x = 10 function f() { return @x } var a = f() a += 5 return x").equals("10"); + code("global x = 10 function f() { return x } var a = f() a += 5 return x").equals("10"); + code_v10("var x = 10 var f = function() { return @x } var a = f() a += 5 return x").equals("10"); + code("var x = 10 var f = function() { return x } var a = f() a += 5 return x").equals("10"); + code_v10("var x = [] var f = function() { return @x } var a = f() push(a, 5) return x").equals("[5]"); + code_v10("var x = [] var f = function() { return x } var a = f() push(a, 5) return x").equals("[]"); + code_v11("var x = [] var f = function() { return x } var a = f() push(a, 5) return x").equals("[5]"); + section("Misc"); code("function f(x) { var s = 0 s |= 12 return s } f(12);").equals("null"); code("function te(a){ return function(){ return a**2; }; } return te(2)();").equals("4"); @@ -47,6 +56,8 @@ public void run() { code("var tab = [2, 3, 4, 5, 6]; var r = []; for (var i : var j in tab) { r[i] = function() { return j; }; } return 4;").equals("4"); code_v10("var retour = [];for(var i=0;i<5;i++){if(i&1){var sqrt=function(e){return 1;}; push(retour, sqrt(4));}else{push(retour, sqrt(4));}}return string(retour);").equals("[2, 1, 2, 1, 2]"); code_v11("var retour = [];for(var i=0;i<5;i++){if(i&1){var sqrt=function(e){return 1;}; push(retour, sqrt(4));}else{push(retour, sqrt(4));}}return string(retour);").equals("[2.0, 1, 2.0, 1, 2.0]"); + code_v10("var r = [1, 2, 3] var f = function() { return r } var x = f() push(x, 12) return r").equals("[1, 2, 3]"); + code_v11("var r = [1, 2, 3] var f = function() { return r } var x = f() push(x, 12) return r").equals("[1, 2, 3, 12]"); section("Modify argument"); code("function test(x) { x += 10 return x } return test(5)").equals("15"); @@ -91,5 +102,32 @@ public void run() { code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; push(copy[1], @[item, cost, 1]); aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("44"); code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; push(copy[1], @[item, cost, 1]); copy[0] += cost; aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("44"); + + section("strings.leek variations"); + code("var m = ['A', 'T', 'C', 'G'];").equals("null"); + code("var m = ['A', 'T', 'C', 'G'] var count = 0 var tests = 500 for (var k = 0; k < tests; k++) {} return abs(100 * (count / tests) - 52) < 12;").equals("false"); + code("var m = ['A', 'T', 'C', 'G'] var count = 0 var tests = 500 for (var k = 0; k < tests; k++) { var adn = '' for (var j = 0; j < 200; j++) {} } return abs(100 * (count / tests) - 52) < 12;").equals("false"); + code("var m = ['A', 'T', 'C', 'G'] var count = 0 var tests = 500 for (var k = 0; k < tests; k++) { var adn = '' for (var j = 0; j < 200; j++) {} var c = contains(adn, 'GAGA'); if (c) count++ } return abs(100 * (count / tests) - 52) < 12;").equals("false"); + code("var m = ['A', 'T', 'C', 'G'] var adn = '' adn += m[randInt(0, 4)];").equals("null"); + code("var m = ['A', 'T', 'C', 'G'] var adn = '' for (var j = 0; j < 200; j++) { adn += m[randInt(0, 4)] }").equals("null"); + code("var adn = 'testtest' contains(adn, 'GAGA');").equals("null"); + code("var m = ['A', 'T', 'C', 'G'] var adn = 'testtest' adn += m[randInt(0, 4)]").equals("null"); + code("var m = ['A', 'T', 'C', 'G'] var adn = 'testtest' adn += m[randInt(0, 4)] contains(adn, 'GAGA');").equals("null"); + code("var adn = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' var c = contains(adn, 'GAGA');").equals("null"); + code("var adn = '' for (var j = 0; j < 200; j++) { adn += 'A' } var c = contains(adn, 'GAGA');").equals("null"); + code("var count = 0 var adn = '' for (var j = 0; j < 200; j++) { adn += 'A' } var c = contains(adn, 'GAGA'); if (c) count++").equals("null"); + code("var m = ['A', 'T', 'C', 'G'] var count = 0 var adn = '' for (var j = 0; j < 200; j++) { adn += m[randInt(0, 4)] } var c = contains(adn, 'GAGA');").equals("null"); + code("var m = ['A', 'T', 'C', 'G'] var count = 0 var adn = '' for (var j = 0; j < 200; j++) { adn += m[randInt(0, 4)] }").equals("null"); + code("var count = 0 var adn = '' for (var j = 0; j < 200; j++) { adn += 'A' } var c = contains(adn, 'GAGA'); if (c) count++").equals("null"); + code("var count = 0 var m = ['A', 'T', 'C', 'G'] var adn = '' for (var j = 0; j < 200; j++) { adn += m[0] } var c = false if (c) count++").equals("null"); + code("var count = 0 var m = ['A', 'T', 'C', 'G'] var adn = '' adn += m[0] var c = contains(adn, 'GAGA'); if (c) count++").equals("null"); + code("var count = 0 var m = ['A', 'T', 'C', 'G'] var adn = '' for (var j = 0; j < 200; j++) { adn += m[0] } var c = contains(adn, 'GAGA'); if (c) count++").equals("null"); + code("var m = ['A', 'T', 'C', 'G'] var count = 0 var adn = '' for (var j = 0; j < 50; j++) { adn += m[randInt(0, 4)] } var c = true; if (c) count++").equals("null"); + code("var m = ['A', 'T', 'C', 'G'] var count = 0 var adn = '' for (var j = 0; j < 50; j++) { adn += m[randInt(0, 4)] } var c = false; if (c) count++").equals("null"); + code("var m = ['A', 'T', 'C', 'G'] var count = 0 var adn = '' for (var j = 0; j < 50; j++) { adn += m[randInt(0, 4)] } var c = contains(adn, 'GAGA'); if (c) count++").equals("null"); + code("var m = ['A', 'T', 'C', 'G'] var count = 0 var adn = '' for (var j = 0; j < 100; j++) { adn += m[randInt(0, 4)] } var c = contains(adn, 'GAGA'); if (c) count++").equals("null"); + code("var m = ['A', 'T', 'C', 'G'] var count = 0 var adn = '' for (var j = 0; j < 200; j++) { adn += m[randInt(0, 4)] } var c = contains(adn, 'GAGA'); if (c) count++").equals("null"); + code("var m = ['A', 'T', 'C', 'G'] var count = 0 var tests = 500 for (var k = 0; k < tests; k++) { var adn = '' for (var j = 0; j < 200; j++) { adn += m[randInt(0, 4)] } var c = contains(adn, 'GAGA'); if (c) count++ }").equals("null"); + code("var m = ['A', 'T', 'C', 'G'] var count = 0 var tests = 500 for (var k = 0; k < tests; k++) { var adn = '' for (var j = 0; j < 200; j++) { adn += m[randInt(0, 4)] } var c = contains(adn, 'GAGA'); if (c) count++ } return abs(100 * (count / tests) - 52) < 12;").equals("true"); } } diff --git a/src/test/java/test/TestReference.java b/src/test/java/test/TestReference.java index d8da7de4..84b15b6a 100644 --- a/src/test/java/test/TestReference.java +++ b/src/test/java/test/TestReference.java @@ -9,6 +9,9 @@ public void run() throws Exception { section("Références"); code_v10("var t = [3, 4, 5]; var a = @t[1] a++ return t;").equals("[3, 4, 5]"); code_v10("var t = [3, 4, 5]; var a = null a = @t[1] a++ return t;").equals("[3, 4, 5]"); + code_v10("var t = 0; var f = function(a) { t = a }; f([]);").equals("null"); + code_v10("var t = 0; var f = function(a) { t = a }; var b = []; f(b);").equals("null"); + code_v10("var t = 0; var f = function(a) { t = a }; var b = []; f(b); push(t, 5);").equals("null"); code_v10("var t = 0; var f = function(a) { t = a }; var b = []; f(b); push(t, 5); return [t, b];").equals("[[5], []]"); code_v10("var t = 0; var f = function(a) { t = @a }; var b = []; f(b); push(t, 5); return b;").equals("[]"); code_v10("var t = 0; var f = function(@a) { t = @a }; var b = []; f(b); push(t, 5); return b;").equals("[5]"); diff --git a/src/test/resources/ai/code/reachable_cells_variant_1.leek b/src/test/resources/ai/code/reachable_cells_variant_1.leek new file mode 100644 index 00000000..4b366817 --- /dev/null +++ b/src/test/resources/ai/code/reachable_cells_variant_1.leek @@ -0,0 +1,38 @@ +var obstacles = [100 118 136 151 153 154 169 170 172 185 187 202 205 219 223 236 237 253 255 273 291 321 322 339 340 341 356 358 359 374 375 389 392 406 407 409 423 425 427 441 442 459 477 495] + +function reachable_cells(start, mp, obstacles) { + + var neighbours = function(c, obstacles) { + + var n = [] + var n1 = c + 17 + if (!inArray(obstacles, n1)) { push(n, n1) } + var n2 = c + 18 + if (!inArray(obstacles, n2)) { push(n, n2) } + var n3 = c - 17 + if (!inArray(obstacles, n3)) { push(n, n3) } + var n4 = c - 18 + if (!inArray(obstacles, n4)) { push(n, n4) } + return n + } + + var cells = [start] + var grow = [start] + + while (mp--) { + var res = [] + for (var cell in grow) { + var n = neighbours(cell, obstacles) + for (var c in n) { + if (!inArray(cells, c) and !inArray(res, c)) { + push(res, c) + } + } + } + grow = res + pushAll(cells, res) + } + return cells +} + +return count(reachable_cells(306, 15, obstacles)); \ No newline at end of file diff --git a/src/test/resources/ai/code/reachable_cells_variant_10.leek b/src/test/resources/ai/code/reachable_cells_variant_10.leek new file mode 100644 index 00000000..b2df1f09 --- /dev/null +++ b/src/test/resources/ai/code/reachable_cells_variant_10.leek @@ -0,0 +1,6 @@ +var neighbours = function(c) { + var r = [c + 17] + return r +} + +var n = neighbours(306); \ No newline at end of file diff --git a/src/test/resources/ai/code/reachable_cells_variant_2.leek b/src/test/resources/ai/code/reachable_cells_variant_2.leek new file mode 100644 index 00000000..3fc17158 --- /dev/null +++ b/src/test/resources/ai/code/reachable_cells_variant_2.leek @@ -0,0 +1,35 @@ +function reachable_cells(start, mp) { + + var neighbours = function(c) { + var n = [] + var n1 = c + 17 + push(n, n1) + var n2 = c + 18 + push(n, n2) + var n3 = c - 17 + push(n, n3) + var n4 = c - 18 + push(n, n4) + return n + } + + var cells = [start] + var grow = [start] + + while (mp--) { + var res = [] + for (var cell in grow) { + var n = neighbours(cell) + for (var c in n) { + if (!inArray(cells, c) and !inArray(res, c)) { + push(res, c) + } + } + } + grow = res + pushAll(cells, res) + } + return cells +} + +return count(reachable_cells(306, 15)); \ No newline at end of file diff --git a/src/test/resources/ai/code/reachable_cells_variant_3.leek b/src/test/resources/ai/code/reachable_cells_variant_3.leek new file mode 100644 index 00000000..738d8de6 --- /dev/null +++ b/src/test/resources/ai/code/reachable_cells_variant_3.leek @@ -0,0 +1,20 @@ +function reachable_cells(start, mp) { + + var cells = [start] + var grow = [start] + + while (mp--) { + var res = [] + for (var cell in grow) { + var c = cell + 17 + if (!inArray(cells, c) and !inArray(res, c)) { + push(res, c) + } + } + grow = res + pushAll(cells, res) + } + return cells +} + +return count(reachable_cells(306, 15)); \ No newline at end of file diff --git a/src/test/resources/ai/code/reachable_cells_variant_4.leek b/src/test/resources/ai/code/reachable_cells_variant_4.leek new file mode 100644 index 00000000..b558e3ef --- /dev/null +++ b/src/test/resources/ai/code/reachable_cells_variant_4.leek @@ -0,0 +1,19 @@ +function reachable_cells(start) { + + var cells = [start] + var grow = [start] + + var res = [] + for (var cell in grow) { + var c = cell + 17 + if (!inArray(cells, c) and !inArray(res, c)) { + push(res, c) + } + } + grow = res + pushAll(cells, res) + + return cells +} + +return count(reachable_cells(306)); \ No newline at end of file diff --git a/src/test/resources/ai/code/reachable_cells_variant_5.leek b/src/test/resources/ai/code/reachable_cells_variant_5.leek new file mode 100644 index 00000000..5ab6d0ad --- /dev/null +++ b/src/test/resources/ai/code/reachable_cells_variant_5.leek @@ -0,0 +1,29 @@ +var neighbours = function(c) { + var n = [] + var n1 = c + 17 + push(n, n1) + var n2 = c + 18 + push(n, n2) + var n3 = c - 17 + push(n, n3) + var n4 = c - 18 + push(n, n4) + return n +} + +var start = 306 +var cells = [start] +var grow = [start] + +var res = [] +for (var cell in grow) { + var n = neighbours(cell) + for (var c in n) { + if (!inArray(cells, c) and !inArray(res, c)) { + push(res, c) + } + } +} +grow = res +pushAll(cells, res) +return count(cells) \ No newline at end of file diff --git a/src/test/resources/ai/code/reachable_cells_variant_6.leek b/src/test/resources/ai/code/reachable_cells_variant_6.leek new file mode 100644 index 00000000..a000e5bf --- /dev/null +++ b/src/test/resources/ai/code/reachable_cells_variant_6.leek @@ -0,0 +1,13 @@ +var neighbours = function(c) { + return [c + 17, c + 18, c - 17, c - 18] +} + +var cell = 306 + +var res = [] +for (var c in neighbours(cell)) { + if (!inArray(res, c)) { + push(res, c) + } +} +return count(res) \ No newline at end of file diff --git a/src/test/resources/ai/code/reachable_cells_variant_7.leek b/src/test/resources/ai/code/reachable_cells_variant_7.leek new file mode 100644 index 00000000..fefa2dde --- /dev/null +++ b/src/test/resources/ai/code/reachable_cells_variant_7.leek @@ -0,0 +1,25 @@ +var neighbours = function(c) { + var n = [] + var n1 = c + 17 + push(n, n1) + var n2 = c + 18 + push(n, n2) + var n3 = c - 17 + push(n, n3) + var n4 = c - 18 + push(n, n4) + return n +} + +var cell = 306 +var cells = [cell] + +var res = [] +var n = neighbours(cell) +for (var c in n) { + if (!inArray(res, c)) { + push(res, c) + } +} +pushAll(cells, res) +return count(cells) \ No newline at end of file diff --git a/src/test/resources/ai/code/reachable_cells_variant_8.leek b/src/test/resources/ai/code/reachable_cells_variant_8.leek new file mode 100644 index 00000000..3807ca73 --- /dev/null +++ b/src/test/resources/ai/code/reachable_cells_variant_8.leek @@ -0,0 +1,18 @@ +var neighbours = function(c) { + var n = [] + var n1 = c + 17 + push(n, n1) + var n2 = c + 18 + push(n, n2) + var n3 = c - 17 + push(n, n3) + var n4 = c - 18 + push(n, n4) + return n +} + +var cell = 306 +var cells = [cell] + +var res = [] +var n = neighbours(cell); \ No newline at end of file diff --git a/src/test/resources/ai/code/reachable_cells_variant_9.leek b/src/test/resources/ai/code/reachable_cells_variant_9.leek new file mode 100644 index 00000000..e7b2ca86 --- /dev/null +++ b/src/test/resources/ai/code/reachable_cells_variant_9.leek @@ -0,0 +1,15 @@ +var neighbours = function(c) { + var n = [] + var n1 = c + 17 + push(n, n1) + var n2 = c + 18 + push(n, n2) + var n3 = c - 17 + push(n, n3) + var n4 = c - 18 + push(n, n4) + return n +} + +var cell = 306 +var n = neighbours(cell); \ No newline at end of file From 101d19462ff63dcc86c93ece93e752e7d2c36d46 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 209/319] [function] Fix substring --- src/main/java/leekscript/runner/LeekFunctions.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index cb2926df..251ae5df 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -358,10 +358,7 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu String string = parameters[0].getString(leekIA); int index = parameters[1].getInt(leekIA); int length = parameters[2].getInt(leekIA); - if (string.length() <= index || index < 0) { - return LeekValueManager.NULL; - } - if (index + length > string.length()) { + if (string.length() <= index || index < 0 || length < 0 || index + length > string.length()) { return LeekValueManager.NULL; } return new StringLeekValue(string.substring(index, index + length)); From f10be518c482579de730a2a88649dfbe8e3c3a43 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 210/319] [array] Fix ops --- src/main/java/leekscript/runner/PhpArray.java | 43 +++++++++---------- .../runner/values/ArrayLeekValue.java | 6 ++- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 86bbf628..cc418819 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -627,13 +627,13 @@ public void removeObject(AI ai, AbstractLeekValue value) throws LeekRunException * @throws LeekRunException */ public void push(AI ai, AbstractLeekValue value) throws LeekRunException { + if (mSize >= capacity) { + growCapacity(ai); + } + mSize++; Integer key = Integer.valueOf(mIndex); Element e = createElement(ai, key, value); pushElement(e); - mSize++; - if (mSize > capacity) { - growCapacity(ai); - } } /** @@ -644,14 +644,14 @@ public void push(AI ai, AbstractLeekValue value) throws LeekRunException { * @throws LeekRunException */ public void unshift(AI ai, AbstractLeekValue value) throws LeekRunException { + if (mSize >= capacity) { + growCapacity(ai); + } + mSize++; Integer key = 0; Element e = createElement(ai, key, value); unshiftElement(e); reindex(ai); - mSize++; - if (mSize > capacity) { - growCapacity(ai); - } } /** @@ -668,12 +668,12 @@ public void set(AI ai, Object key, AbstractLeekValue value) throws LeekRunExcept Element e = getElement(ai, key); // Si l'élément n'existe pas on le crée if (e == null) { - e = createElement(ai, key, value); - pushElement(e); - mSize++; - if (mSize > capacity) { + if (mSize >= capacity) { growCapacity(ai); } + mSize++; + e = createElement(ai, key, value); + pushElement(e); } else { e.value.set(ai, value); } @@ -712,6 +712,10 @@ public void insert(AI ai, int position, AbstractLeekValue value) throws LeekRunE } else if (position == 0) { unshift(ai, value); } else { + if (mSize >= capacity) { + growCapacity(ai); + } + mSize++; // On crée notre nouvel élément Element e = createElement(ai, Integer.valueOf(mIndex), value); // On va rechercher l'élément avant lequel insérer @@ -727,11 +731,6 @@ public void insert(AI ai, int position, AbstractLeekValue value) throws LeekRunE // On réindexe reindex(ai); - - mSize++; - if (mSize > capacity) { - growCapacity(ai); - } } } @@ -763,11 +762,11 @@ public void reindex(AI ai) throws LeekRunException { mIndex = new_index; } - private void unshiftElement(Element e) {// Ajouter un élément au début - if (mHead == null) {// Tableau vide + private void unshiftElement(Element e) { // Ajouter un élément au début + if (mHead == null) { // Tableau vide mHead = e; mEnd = e; - } else {// Ajouter au début + } else { // Ajouter au début mHead.prev = e; e.next = mHead; mHead = e; @@ -775,10 +774,10 @@ private void unshiftElement(Element e) {// Ajouter un élément au début } private void pushElement(Element e) {// Ajouter un élément à la fin - if (mEnd == null) {// Tableau vide + if (mEnd == null) { // Tableau vide mHead = e; mEnd = e; - } else {// Sinon on ajoute à la fin + } else { // Sinon on ajoute à la fin mEnd.next = e; e.prev = mEnd; mEnd = e; diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index f1ecf31b..9fee5c76 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -135,6 +135,10 @@ public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws Leek return mValues.getOrCreate(ai, key); } + public void put(AI ai, Object key, AbstractLeekValue value) throws LeekRunException { + mValues.set(ai, key, value); + } + @Override public AbstractLeekValue get(AI ai, int value) throws LeekRunException { return mValues.getOrCreate(ai, Integer.valueOf(value)); @@ -275,9 +279,9 @@ else if (comp.getString(ai).isEmpty() && mValues.size() == 0) @Override public AbstractLeekValue add(AI ai, AbstractLeekValue value) throws LeekRunException { value = value.getValue(); + ai.addOperations(1); if (value instanceof ArrayLeekValue) { // mValues.reindex(ai); - ai.addOperations(1); ArrayIterator iterator = value.getArray().getArrayIterator(); while (!iterator.ended()) { if (iterator.key() instanceof String || iterator.key() instanceof ObjectLeekValue) From f0ef288f12b70b9ba77e0a23437edb541cbb82d3 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 211/319] [test] Add tests --- src/test/java/test/TestArray.java | 2 ++ src/test/java/test/TestCommon.java | 1 - src/test/java/test/TestFunction.java | 7 +++++++ src/test/java/test/TestLoops.java | 9 +++++++++ src/test/java/test/TestReference.java | 2 ++ 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index 8d3761dd..750d3374 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -194,6 +194,8 @@ public void run() throws Exception { // DISABLED_code("var a = [] if (true) a += 12 return a;").equals("[12]"); // DISABLED_code("var a = [1] if (true) a += 12 return a;").equals("[1, 12]"); // DISABLED_code("var a = ['a'] if (true) a += 12 return a;").equals("['a', 12]"); + code_v10("var a = [1.55]; a += 12.9; return a").equals("[1,55]"); + code_v11("var a = [1.55]; a += 12.9; return a").equals("[1.55]"); section("Array.operator += on element"); code("var a = [5] a[0] += 1 return a;").equals("[6]"); diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index 17561fbf..6225d06b 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -1,6 +1,5 @@ package test; -import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.text.DecimalFormat; diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index cb81a357..d94759f7 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -58,6 +58,13 @@ public void run() { code_v11("var retour = [];for(var i=0;i<5;i++){if(i&1){var sqrt=function(e){return 1;}; push(retour, sqrt(4));}else{push(retour, sqrt(4));}}return string(retour);").equals("[2.0, 1, 2.0, 1, 2.0]"); code_v10("var r = [1, 2, 3] var f = function() { return r } var x = f() push(x, 12) return r").equals("[1, 2, 3]"); code_v11("var r = [1, 2, 3] var f = function() { return r } var x = f() push(x, 12) return r").equals("[1, 2, 3, 12]"); + code("function f() { return [1, 2, 3] } var x = f();").equals("null"); + code("var x = arrayMap([1, 2, 3], function(x) { return x });").equals("null"); + code("var x = arrayMap([1, 2, 3], function(x) { return x }); debug(x);").equals("null"); + code("var toto = 12; var f = function() { toto = 'salut'; }; [true, 12, f][2](); return toto").equals("salut"); + code("var toto = 12; var f = function() { toto = 'salut'; }; var g = function() { return f; }; g()() return toto").equals("salut"); + code_v10("function Coordonate(@par_x, @par_y) { var x = par_x; var y = par_y; var getX = function(){ return x; }; var getY = function(){ return y; };return @(function(@method) { if(method === 'getX'){ return getX; } if(method === 'getY'){ return getY; } }); } var c = Coordonate(5, 12) return [c('getX')(), c('getY')()]").equals("[5, 12]"); + code_v11("function Coordonate(par_x, par_y) { var x = par_x; var y = par_y; var getX = function(){ return x; }; var getY = function(){ return y; };return (function(method) { if(method === 'getX'){ return getX; } if(method === 'getY'){ return getY; } }); } var c = Coordonate(5, 12) return [c('getX')(), c('getY')()]").equals("[5, 12]"); section("Modify argument"); code("function test(x) { x += 10 return x } return test(5)").equals("15"); diff --git a/src/test/java/test/TestLoops.java b/src/test/java/test/TestLoops.java index d11623dc..d2526487 100644 --- a/src/test/java/test/TestLoops.java +++ b/src/test/java/test/TestLoops.java @@ -108,6 +108,15 @@ public void run() { // DISABLED_code("var s = 0 for (var i = 0; i < 10; i += 1) { var j = 0 for (; j < 10; j += 1) { s++ }} return s;").equals("100"); // file("test/code/loops/lot_of_fors_int.leek").equals("15015"); // file("test/code/loops/lot_of_fors_array.leek").equals("15015"); + code("var tabmulti=[]; for (var i = 0; i < 8; ++i) tabmulti[i]=1; return tabmulti").equals("[1, 1, 1, 1, 1, 1, 1, 1]"); + code("var tabmulti=[]; for (var i = 0; i < 9; ++i) tabmulti[i]=1; return tabmulti").equals("[1, 1, 1, 1, 1, 1, 1, 1, 1]"); + code("var tabmulti=[]; for (var i = 0; i < 50; ++i) tabmulti[i]=1; return tabmulti").equals("[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]"); + code("var tabmulti=[[],[],[],[],[]]; var i = 3, j = -2 tabmulti[i][j]=i*j; return tabmulti").equals("[[], [], [], [-2 : -6], []]"); + code("var tabmulti=[[],[],[],[],[]]; var vPM=4; for(var i=0;i<=vPM;i++){ for(var j=-vPM;j<=vPM;j++){ }} return tabmulti").equals("[[], [], [], [], []]"); + code("var tabmulti=[[],[],[],[],[]]; var vPM=1; for(var i=0;i<=vPM;i++){ for(var j=-vPM;j<=vPM;j++){ tabmulti[i][j]=i*j;}} return tabmulti").equals("[[-1 : 0, 0 : 0, 1 : 0], [-1 : -1, 0 : 0, 1 : 1], [], [], []]"); + code("var tabmulti=[[],[],[],[],[]]; var vPM=2; for(var i=0;i<=vPM;i++){ for(var j=-vPM;j<=vPM;j++){ tabmulti[i][j]=i*j;}} return tabmulti").equals("[[-2 : 0, -1 : 0, 0 : 0, 1 : 0, 2 : 0], [-2 : -2, -1 : -1, 0 : 0, 1 : 1, 2 : 2], [-2 : -4, -1 : -2, 0 : 0, 1 : 2, 2 : 4], [], []]"); + code("var tabmulti=[[],[],[],[],[]]; var vPM=3; for(var i=0;i<=vPM;i++){ for(var j=-vPM;j<=vPM;j++){ tabmulti[i][j]=i*j;}} return tabmulti").equals("[[-3 : 0, -2 : 0, -1 : 0, 0 : 0, 1 : 0, 2 : 0, 3 : 0], [-3 : -3, -2 : -2, -1 : -1, 0 : 0, 1 : 1, 2 : 2, 3 : 3], [-3 : -6, -2 : -4, -1 : -2, 0 : 0, 1 : 2, 2 : 4, 3 : 6], [-3 : -9, -2 : -6, -1 : -3, 0 : 0, 1 : 3, 2 : 6, 3 : 9], []]"); + code("var tabmulti=[[],[],[],[],[]]; var vPM=4; for(var i=0;i<=vPM;i++){ for(var j=-vPM;j<=vPM;j++){ tabmulti[i][j]=i*j;}} return tabmulti").equals("[[-4 : 0, -3 : 0, -2 : 0, -1 : 0, 0 : 0, 1 : 0, 2 : 0, 3 : 0, 4 : 0], [-4 : -4, -3 : -3, -2 : -2, -1 : -1, 0 : 0, 1 : 1, 2 : 2, 3 : 3, 4 : 4], [-4 : -8, -3 : -6, -2 : -4, -1 : -2, 0 : 0, 1 : 2, 2 : 4, 3 : 6, 4 : 8], [-4 : -12, -3 : -9, -2 : -6, -1 : -3, 0 : 0, 1 : 3, 2 : 6, 3 : 9, 4 : 12], [-4 : -16, -3 : -12, -2 : -8, -1 : -4, 0 : 0, 1 : 4, 2 : 8, 3 : 12, 4 : 16]]"); section("Mix for and while loops"); code("var s = 0 for (var i = 0; i < 10; i += 1) { var j = 10 while (j--) { s++ }} return s;").equals("100"); diff --git a/src/test/java/test/TestReference.java b/src/test/java/test/TestReference.java index 84b15b6a..104e5315 100644 --- a/src/test/java/test/TestReference.java +++ b/src/test/java/test/TestReference.java @@ -22,5 +22,7 @@ public void run() throws Exception { code_v10("var a = 12; var b = @a; a++; return [a, b]").equals("[13, 12]"); code_v10("var a = 12; var b = @a; var c = @b; a++; return [a, b, c]").equals("[13, 12, 12]"); code_v10("var a = [12]; var b = @a[0]; a[0]++; return [a, b]").equals("[[13], 12]"); + code_v10("var a = @[1, 2, 3]; var b = @a; (@(b));").equals("null"); + code_v10("var a = @[1, 2, 3]; var b = @a; return (@(b));").equals("[1, 2, 3]"); } } From c152f28ee2f8aa6b37ff654887e652e5d0e44851 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 212/319] [test] Add more tests --- src/test/java/test/TestArray.java | 9 ++ src/test/java/test/TestFunction.java | 6 ++ src/test/java/test/TestGeneral.java | 2 + src/test/java/test/TestGlobals.java | 8 ++ src/test/java/test/TestIf.java | 8 ++ src/test/java/test/TestLoops.java | 4 +- src/test/java/test/TestMain.java | 1 + src/test/java/test/TestNumber.java | 2 +- src/test/java/test/TestObject.java | 125 +++++++++++++++++++++++ src/test/java/test/TestOperators.java | 139 ++++++++++++++++++++------ 10 files changed, 268 insertions(+), 36 deletions(-) create mode 100644 src/test/java/test/TestObject.java diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index 750d3374..e8ce94eb 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -112,6 +112,10 @@ public void run() throws Exception { code("return [1, true][0]").equals("1"); code("return [1, true][1]").equals("true"); // code("return [5l, 7l, 9l][2l]").equals("9"); + code("var a = [12: 5] return a[5] = 7").equals("7"); + code("var a = [12: 5] var b = 7 return a[5] = b").equals("7"); + code("var a = [] return a[0] + 2").equals("2"); + code("var a = 5 return a[0] + 2").equals("2"); section("[] operator on unknown arrays"); code("var v = [['a', 'b'], 12] return v[0][0]").equals("a"); @@ -288,6 +292,11 @@ public void run() throws Exception { code_v10("var t = [3, 4, 5]; var a = null a = @t[1] a++ return t;").equals("[3, 4, 5]"); code_v10("var t = [3, 4, 5]; t[3] = [1, 2, 3, 4]; var r = @t[3]; r[4] = 'coucou'; return t;").equals("[3, 4, 5, [1, 2, 3, 4, coucou]]"); + section("Array.map()"); + code("return arrayMap([1, 2, 3], function(v) { var r = [] return r })").equals("[[], [], []]"); + code("return arrayMap([1, 2, 3], function(v) { var r = [1, 2, 3] return r })").equals("[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"); + code("var r = [] var a = arrayMap([1, 2, 3], function(v) { return r }) push(r, 1) return a").equals("[[1], <...>, <...>]"); + section("Array.map() v1.0"); code_v10("return arrayMap([1, 2, 3, 4, 5], function(e) { return e * 2; });").equals("[2, 4, 6, 8, 10]"); code_v10("return arrayMap([4, 9, 16], sqrt);").equals("[2, 3, 4]"); diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index d94759f7..f6f2d634 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -19,6 +19,7 @@ public void run() { // code("function test() { var fact = x -> if x == 1 { 1 } else { fact(x - 1) * x } fact(8) } test()").equals("40320"); file_v10("ai/code/knapsack.leek").equals("761"); file_v11("ai/code/knapsack_11.leek").equals("761"); + code("function cellsInRange(i) { var areaInRange = []; if (i == 0) { return cellsInRange(10); } else { return areaInRange; } } var myRange = cellsInRange(0); return myRange").equals("[]"); section("Redefinition"); code("var count = count([1, 2, 3]) return count;").equals("3"); @@ -65,6 +66,11 @@ public void run() { code("var toto = 12; var f = function() { toto = 'salut'; }; var g = function() { return f; }; g()() return toto").equals("salut"); code_v10("function Coordonate(@par_x, @par_y) { var x = par_x; var y = par_y; var getX = function(){ return x; }; var getY = function(){ return y; };return @(function(@method) { if(method === 'getX'){ return getX; } if(method === 'getY'){ return getY; } }); } var c = Coordonate(5, 12) return [c('getX')(), c('getY')()]").equals("[5, 12]"); code_v11("function Coordonate(par_x, par_y) { var x = par_x; var y = par_y; var getX = function(){ return x; }; var getY = function(){ return y; };return (function(method) { if(method === 'getX'){ return getX; } if(method === 'getY'){ return getY; } }); } var c = Coordonate(5, 12) return [c('getX')(), c('getY')()]").equals("[5, 12]"); + code("function test() { var r = [1, 2, 3] return (r); } return test()").equals("[1, 2, 3]"); + code("function test() { var r = [1, 2, 3] return (r); } var a = test() return a").equals("[1, 2, 3]"); + code("function t(a) {} t([ [12], [12] ])").equals("null"); + code_v10("function t(@a) {} t([ [12], [12] ])").equals("null"); + code_v10("function t() { var a = 12 return @a } return t() + 2").equals("14"); section("Modify argument"); code("function test(x) { x += 10 return x } return test(5)").equals("15"); diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index 10a4b936..31e65fa4 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -97,6 +97,8 @@ public void run() { code("var x = 5 if (true) if (true) if (true) if (true) if (true) x = 'a' return x").equals("a"); // code("var x = 2 var y = { if (x == 0) { return 'error' } 7 * x } return y").equals("14"); code("var y if (false) { if (true) {;} else { y = 2 } } else { y = 5 } return y").equals("5"); + code_v10("PI = PI + 12; return PI").equals("3,142"); + code_v11("PI = PI + 12; return PI").equals("3.141592653589793"); section("Assignments with +="); code_v10("var a = 10 a += 0.5 return a").equals("10,5"); diff --git a/src/test/java/test/TestGlobals.java b/src/test/java/test/TestGlobals.java index 8029e477..79955ee6 100644 --- a/src/test/java/test/TestGlobals.java +++ b/src/test/java/test/TestGlobals.java @@ -13,6 +13,14 @@ public void run() throws Exception { code("global x; x = [1, 2, 3]; return x;").equals("[1, 2, 3]"); code("var r = x; global x; return r;").equals("null"); code("var r = x; global x = 12; return r;").equals("null"); + code("global r = 2 + 2; return r").equals("4"); + code("global r = [1, 2, 3]; return r").equals("[1, 2, 3]"); + code("global r = 'salut'; return r").equals("salut"); + code("global r = ['a': 12, 'b': 5]; return r").equals("[a : 12, b : 5]"); + code("global r = [] return r[1] = 12").equals("12"); + code("global r = [0] return r[0] += 12").equals("12"); + code("global r = [] return r[5] += 12").equals("12"); + code_v10("global r = 12 r = @null").equals("null"); section("Globals operators"); code("global x = 12; x++; return x;").equals("13"); diff --git a/src/test/java/test/TestIf.java b/src/test/java/test/TestIf.java index d127c088..4816090e 100644 --- a/src/test/java/test/TestIf.java +++ b/src/test/java/test/TestIf.java @@ -52,6 +52,14 @@ public void run() throws Exception { code("var a = 1; if(a is not 1) return 2; else return 0").equals("0"); code("var a = true; if(not a) return 2; else return 0").equals("0"); code("var Bob = 12 if (Bob = 75);").equals("null"); + code("var cell = 1 if (cell != null) return 12").equals("12"); + code("var cell = null if (cell != null) return 12 return 5").equals("5"); + code("function t(c) { var cell = c if (cell!=null ) 1; } return t(300);").equals("null"); + code_v10("function t(@c) { var cell = c if (cell!=null ) 1; } return t(300);").equals("null"); + code_v10("function t(@c) { var cell = c } for (var i = 0; i < 10; ++i) return t(i);").equals("null"); + code_v10("function t(@c) { var cell = c if (cell!=null ) 1; } for (var i = 0; i < 10; ++i) return t(i);").equals("null"); + code_v10("function t(@c) { var cell = c cell != null } for (var i = 0; i < 10; ++i) return t(i);").equals("null"); + code_v10("function t(@c) { var cell = c return cell != null } for (var i = 0; i < 10; ++i) return t(i);").equals("true"); section("Conditions with other types"); code("if (1212) { return 'ok' } else { return 5 }").equals("ok"); diff --git a/src/test/java/test/TestLoops.java b/src/test/java/test/TestLoops.java index d2526487..fdd8e9ab 100644 --- a/src/test/java/test/TestLoops.java +++ b/src/test/java/test/TestLoops.java @@ -133,6 +133,7 @@ public void run() { code("var s = 0; var a; for (a in [1, 2, 3]) { s += a } return s").equals("6"); code("var s = 0; var a; for (var k : a in [1, 2, 3]) { s += a } return s").equals("6"); code("var s = 0; var k; for (k : var a in [1, 2, 3, 4, 5]) { s += k } return s").equals("10"); + DISABLED_code("for (var x in 12) {}").error(); section("Normal containers"); code("for (var v in [1, 2, 3, 4]) {}").equals("null"); @@ -153,8 +154,7 @@ public void run() { // DISABLED_code("var y = '' for k, x in { var x = [1: '2'] x.insert(3, 4) x } { y += k + ':' + x + ' ' } y").equals("'1:2 3:4 '"); // code("var y = 'test' for (var x in 1) { y = x } y").equals("1"); // code("var y = 'test' for (var x in 'salut') { y = x } y").equals("'t'"); - // Working but should error - DISABLED_code("var x = 'test' for (var x in [1]) {} return x;").equals("'test'"); + code("var x = 'test' for (var x in [1]) {} return x;").error(); // code("var y = '' for k, x in { var x = <> x.insert(4) x } { y += k + ':' + x } y").equals("'0:4'"); // DISABLED_code("var fs = [] fs.push(s -> {var sum = 0 for v in s {sum += v} sum}) fs[0](<1, 2>)").equals("3"); // TODO issue #243 // DISABLED_code("var fs = [] fs.push(s -> {[for v in s {v}]}) fs[0](<2,1>)").equals("[1, 2]"); // TODO issue #243 diff --git a/src/test/java/test/TestMain.java b/src/test/java/test/TestMain.java index 3a5de999..fc57908a 100644 --- a/src/test/java/test/TestMain.java +++ b/src/test/java/test/TestMain.java @@ -27,6 +27,7 @@ public static void main(String[] args) throws Exception { new TestString().run(); new TestArray().run(); new TestMap().run(); + new TestObject().run(); new TestComments().run(); new TestOperators().run(); new TestReference().run(); diff --git a/src/test/java/test/TestNumber.java b/src/test/java/test/TestNumber.java index d3b58d14..fbeb5b3c 100644 --- a/src/test/java/test/TestNumber.java +++ b/src/test/java/test/TestNumber.java @@ -608,7 +608,7 @@ public void run() throws Exception { section("Not a statement errors"); code("null; return null;").equals("null"); code("(null); return null;").equals("null"); - DISABLED_code("((null)); return null;").equals("null"); + code("((null)); return null;").equals("null"); code("true; return null;").equals("null"); code("false; return null;").equals("null"); code("'salut'; return null;").equals("null"); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java new file mode 100644 index 00000000..984a5486 --- /dev/null +++ b/src/test/java/test/TestObject.java @@ -0,0 +1,125 @@ +package test; + +public class TestObject extends TestCommon { + + public void run() { + + section("Objects"); + // code("return Object()").equals("{}"); + // code("return new Object").equals("{}"); + // code("return new Object()").equals("{}"); + // code("return {}").equals("{}"); + // code("return {a: 12}").equals("{a: 12}"); + // code("return {a: 12, b: 5}").equals("{a: 12, b: 5}"); + // code("return {a: {}, b: []}").equals("{a: {}, b: []}"); + // code("var a = {} return a").equals("{}"); + // code("var a = {b: 12, c: 5} return a").equals("{b: 12, c: 5}"); + + section("Objects with functions"); + // code("var f = obj -> obj.a return f({a: 'foo'})").equals("'foo'"); + // code("var f = obj -> obj.a return [f({a: 'foo'}), f({a: 'bar'})]").equals("['foo', 'bar']"); + // code("var f = obj -> obj.a [f(12), f({a: 'bar'})]").error(ls::Error::NO_SUCH_ATTRIBUTE, {"a", "Number"}); + + section("No commas"); + // code("return {a: 12 b: 5}").equals("{a: 12, b: 5}"); + // code("return {a: 12 - 2 yo: -6}").equals("{a: 10, yo: -6}"); + // code("return {a: 12 b: 'yo' c: true d: [1 2 3]}").equals("{a: 12, b: 'yo', c: true, d: [1, 2, 3]}"); + + section("Classes"); + code_v11("class A { } return new A();").equals("A {}"); + code_v11("class A { a = 10 } var a = new A(); return --a.a").equals("9"); + code_v11("class A { a = 10 } var a = new A(); a.a-- return a.a").equals("9"); + code_v11("class A { a = 10 } var a = new A(); return ++a.a").equals("11"); + code_v11("class A { a = 10 } var a = new A(); a.a++ return a.a").equals("11"); + + /* + * Operators + */ + section("Object.operator !"); + // code("return !{}").equals("true"); + // code("return !{a: 32}").equals("false"); + + section("Object.operator | |"); + // code("var a = {a: 32, b: 'toto', c: false}; return |a|").equals("3"); + + section("Object.operator in ()"); + // code("return 12 in {x: 5, y: 12}").equals("true"); + // code("return 12 in {x: 5, y: 'yo'}").equals("false"); + + section("Object.operator . ()"); + // code("return { v: 12 }.v").equals("12"); + // code("var a = {b: 12, c: 5} return a.b").equals("12"); + // code("var a = {v: 5} return a.v = 12").equals("12"); + // code("var a = {v: 5} a.v = 12 return a").equals("{v: 12}"); + // code("var a = {v: 5} return a.v = 'salut'").equals("'salut'"); + // code("var a = {v: 5} a.v = 'salut' return a").equals("{v: 'salut'}"); + // code("var a = {b: 12} return a.b += 10").equals("22"); + // code("var a = {b: 12} return a.b -= 10").equals("2"); + // code("var a = {b: 12} return a.b *= 10").equals("120"); + // code("var a = {b: 12} return a.b /= 10").almost(1.2); + // code("var a = {b: 12} return a.b %= 10").equals("2"); + // code("var o = {} o.new_val = 12 return o").equals("{new_val: 12}"); + // code("var o = {a: 'a'} o.b = 'b' return o").equals("{a: 'a', b: 'b'}"); + // DISABLED_code("Object.readonly.v = 5").exception(ls::vm::Exception::CANT_MODIFY_READONLY_OBJECT); + // code("var o = [{}, ''][0] return o.values").equals(""); + // code("var pq = [{p: 22, v: 55}] return pq[0].p").equals("22"); + // code("var pq = [{p: 22, v: 55}] var o = pq[0] return o.v").equals("55"); + + section("Object.operator =="); + // code("class A {} return {} == new A").equals("false"); + code_v11("class A { }; class B { }; return new A() == new B();").equals("false"); + // code("class A {} return new A == new A").equals("true"); + // code("return {a: 2} == {}").equals("false"); + // code("return {a: 2} == {a: 1}").equals("false"); + // code("return {a: 2} == {b: 2}").equals("false"); + // code("return {a: 2} == {a: 2}").equals("true"); + + section("Object.operator <"); + // code("return {} < {}").equals("false"); + // code("return {a: 2} < {a: 3}").equals("true"); + // code("return {a: 2} < {a: 1}").equals("false"); + // code("return {a: 'b'} < {a: 'c'}").equals("true"); + // code("return {a: 'b'} < {a: 'a'}").equals("false"); + // code("return {b: 2} < {c: 2}").equals("true"); + // code("return {b: 2} < {a: 2}").equals("false"); + // code("return {a: 1} < {a: 1, b: 2}").equals("true"); + // code("return {a: 1, b: 2} < {a: 1}").equals("false"); + // code("return {a: 0, b: 2} < {a: 1}").equals("true"); + // code("class A {} class B {} return new A < new B").equals("true"); + // code("class A {} class B {} return new B < new A").equals("false"); + // code("class A {} return {} < new A").equals("true"); + // code("class A {} return new A < {}").equals("false"); + + /* + * Iteration + */ + // code("var s = '' for v in {a: 5, b: 'hello'} { s += v } s").error(ls::Error::Type::VALUE_NOT_ITERABLE, {"{a: 5, b: 'hello'}", env.tmp_object->to_string()}); // TODO .equals("'5hello'"); + + /* + * Methods + */ + section("Object.keys()"); + // code("return {}.keys()").equals("[]"); + // code("return {a: 5, b: 'toto', c: true, d: -> 5}.keys()").equals("['a', 'b', 'c', 'd']"); + // code("return 'x' in {x: 5, y: 'yo'}.keys()").equals("true"); + // code("return 'x' in {a: 5, y: 'yo'}.keys()").equals("false"); + + section("Object.values()"); + // code("return {}.values()").equals("[]"); + // code("return {a: 1}.values()").equals("[1]"); + // code("return {a: 1, b: 1}.values()").equals("[1, 1]"); + // code("return {a: 5, b: 'toto', c: true, d: -> 5}.values()").equals("[5, 'toto', true, ]"); + + section("Object.isTrue()"); + // code("if ({x: 12}) { return 5 } else { return 12 }").equals("5"); + // code("if ({}) { return 5 } else { return 12 }").equals("12"); + + section("Object.clone()"); + // code("var a = {v: 12} return [a]").equals("[{v: 12}]"); + + section("Object.map()"); + // code("return {}.map(x -> x + 1)").equals("{}"); + // code("return {x: 12, y: 5}.map(x -> x + 1)").equals("{x: 13, y: 6}"); + // code("return {x: 'a', y: 'b'}.map(x -> x + ' !')").equals("{x: 'a !', y: 'b !'}"); + } +} diff --git a/src/test/java/test/TestOperators.java b/src/test/java/test/TestOperators.java index 1727ac1c..3dd5ba7d 100644 --- a/src/test/java/test/TestOperators.java +++ b/src/test/java/test/TestOperators.java @@ -4,59 +4,122 @@ public class TestOperators extends TestCommon { public void run() throws Exception { - code("return 'Chaine1' == 'Chaine1'").equals("true"); - code("return 'Chaine1' == 'Chaine2'").equals("false"); + section("Operator =="); + code("return null == null").equals("true"); + code("return false == false").equals("true"); code("return true == true").equals("true"); code("return false == true").equals("false"); code("return true == false").equals("false"); + code("return true == 'true'").equals("true"); + code("return false == 'false'").equals("true"); + code("return true == 'false'").equals("false"); + code("return false == 'true'").equals("false"); + code("return false == []").equals("true"); + code("return false == 0").equals("true"); + code("return true == 1").equals("true"); + code("return false != 0").equals("false"); + code("return true != 1").equals("false"); + code("return false == ''").equals("true"); + code("return false == '0'").equals("true"); + code("return false == []").equals("true"); + code("return false == [0]").equals("true"); + code("return true == 12").equals("true"); + code("return true == '1'").equals("true"); + code("return true == '12'").equals("true"); + code("return true == 'lama'").equals("true"); + code("return true == [1]").equals("true"); + code("return true == [12]").equals("true"); + code("return true == [1, 2, 3]").equals("true"); + + code("return 0 == false").equals("true"); + code("return 0 == 0").equals("true"); + code("return 0 == ''").equals("true"); + code("return 0 == '0'").equals("true"); + code("return 0 == 'false'").equals("true"); + code("return 0 == []").equals("true"); + code("return 0 == [0]").equals("true"); + code("return 0 != null").equals("true"); + + code("return 1 == true").equals("true"); + code("return 1 == '1'").equals("true"); + code("return 1 == 'true'").equals("true"); + code("return 1 == 'lama'").equals("true"); + code("return 1 == [1]").equals("true"); code("return 1 == 2").equals("false"); + + code("return 12 == true").equals("true"); code("return -1 == -5").equals("false"); code("return 50 == 50").equals("true"); - code("return 0 == 0").equals("true"); - code("return 0 == 0").equals("true"); code("return 5 == 5").equals("true"); code("return 45 == 5").equals("false"); - code("return null == null").equals("true"); + code("return 10 == '10'").equals("true"); + code("return 10 == '10'").equals("true"); + code("return 10 == '15'").equals("false"); + code("return 10 == '15'").equals("false"); + code("return 10.8 == '10.8'").equals("true"); + code("return 10.8 == '10.87'").equals("false"); + code("return 12 == 'true'").equals("true"); + code("return 2 == 'false'").equals("false"); + code("return 12 == [12]").equals("true"); + + code("return 'Chaine1' == 'Chaine1'").equals("true"); + code("return 'Chaine1' == 'Chaine2'").equals("false"); + code("return '1' == 1").equals("true"); + code("return '0' == 0").equals("true"); + code("return '10' == 10").equals("true"); + code("return '15' == 10").equals("false"); + code("return [] == []").equals("true"); code("return [0] == [0]").equals("true"); code("return [0, 1] == [0, 1]").equals("true"); code("return [0, 1] == [0]").equals("false"); code("return ['Chaine1'] == ['Chaine2']").equals("false"); code("return ['Chaine1'] == ['Chaine1']").equals("true"); + code("return function() {} == function() {}").equals("false"); code("return endsWith == function() {}").equals("false"); code("return endsWith == endsWith").equals("true"); - code("return '1' == 1").equals("true"); - code("return '0' == 0").equals("true"); - code("return '10' == 10").equals("true"); - code("return '15' == 10").equals("false"); - code("return 1 == '1'").equals("true"); - code("return 0 == '0'").equals("true"); - code("return 0 == '0'").equals("true"); - code("return 10 == '10'").equals("true"); - code("return 10 == '10'").equals("true"); - code("return 10 == '15'").equals("false"); - code("return 10 == '15'").equals("false"); - code("return 10.8 == '10.8'").equals("true"); - code("return 10.8 == '10.87'").equals("false"); - code("return true == 'true'").equals("true"); - code("return false == 'false'").equals("true"); - code("return true == 'false'").equals("false"); - code("return false == 'true'").equals("false"); - code("return 1 == 'true'").equals("true"); - code("return 0 == 'false'").equals("true"); - code("return 12 == 'true'").equals("true"); - code("return 2 == 'false'").equals("false"); - code("return 0 == [0]").equals("true"); - code("return 1 == [1]").equals("true"); - code("return 0 == []").equals("true"); - code("return false == []").equals("true"); - code("return false == 0").equals("true"); - code("return false != 0").equals("false"); - code("return true != 1").equals("false"); + String[] values1 = new String[] { "false", "true", "0", "1", "12", "''", "'0'", "'1'", "'12'", "'lama'", "'true'", "'false'", + "[]", "[0]", "[1]", "[12]", "[1,2,3]", "null" }; + String[] equalEqual = new String[] { + "X X XX XXX ", // false + " X XX XXXX XXX ", // true + "X X XX XXX ", // 0 + " X X X XX X ", // 1 + " X X X X X ", // 12 + "X X X XX ", // " " + "X X X X ", // "0" + " X X X X ", // "1" + " X X X X ", // "12" + " X X X X ", // "lama" + " X XX X XXX ", // "true" + "X X XXX ", // "false" + "X X X XX ", // [] + "X X XX X X ", // [0] + " X X X XX X ", // [1] + " X X X X X ", // [12] + " X X X ", // [1,2,3] + " X", // null + }; + for (int i = 0; i < values1.length; i++) { + for (int j = 0; j < values1.length; j++) { + code("return " + values1[i] + " == " + values1[j]).equals(String.valueOf(equalEqual[i].charAt(j) == 'X')); + } + } + + section("Other operators"); + code("var sum = 1, ops = 10 return sum < ops * 0.95 || sum > ops").equals("true"); + code("var sum = 9.8, ops = 10 return sum < ops * 0.95 || sum > ops").equals("false"); + code("var sum = 98 var ops = 100 return sum < ops * 0.95 || sum > ops").equals("false"); + code("var sum = 98 var ops = 100 if (sum < ops * 0.95 || sum > ops) {}").equals("null"); + code("var sum = 1 var ops = 10 if (sum < ops * 0.95 || sum > ops) {} return null").equals("null"); + code("var a = [] if (a != []) {}").equals("null"); + code("return !null == 50").equals("true"); + + section("Operator ==="); Object[] values = new Object[] { "0", "1", "12", "13", "false", "true", "null", "'true'", @@ -91,5 +154,15 @@ public void run() throws Exception { code("return 15 > 10 > 11 and 150 < 200 < 250").equals("false"); code("return 15 > 14 > 11 and 150 < 100 < 250").equals("false"); code("return 15 > 10 > 11 and 150 < 100 < 250").equals("false"); + + section("Operator +"); + code("return false + 1").equals("1"); + code("return 1 + false").equals("1"); + code("return true + 1").equals("2"); + code("return 1 + true").equals("2"); + code("return true + null").equals("1"); + code("return null + true").equals("1"); + code("return false + null").equals("0"); + code("return null + false").equals("0"); } } From 8c46c42faca7d55f069391976e2a8ffa15e49b6c Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 213/319] [fun] Fix shuffle --- src/main/java/leekscript/runner/PhpArray.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index cc418819..bf83433b 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -460,7 +460,7 @@ public void sort(AI ai, int comparator) throws LeekRunException { } // Trie de la liste if (comparator == RANDOM) - Collections.shuffle(liste, new Random(LeekScript.getRandom().getInt(0, Integer.MAX_VALUE))); + Collections.shuffle(liste, new Random(ai.getRandom().getInt(0, Integer.MAX_VALUE - 1))); else if (comparator == ASC_K || comparator == DESC_K) { Collections.sort(liste, new KeyComparator( (comparator == ASC_K) ? ElementComparator.SORT_ASC From d786b18d68282420aab81e4f497fa9002a13c787 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 214/319] [test] Add tests --- src/test/java/test/TestGlobals.java | 1 + src/test/java/test/TestJSON.java | 113 ++++++++++++++++++++++++++++ src/test/java/test/TestMain.java | 1 + src/test/java/test/TestObject.java | 4 + 4 files changed, 119 insertions(+) create mode 100644 src/test/java/test/TestJSON.java diff --git a/src/test/java/test/TestGlobals.java b/src/test/java/test/TestGlobals.java index 79955ee6..24c8c5cd 100644 --- a/src/test/java/test/TestGlobals.java +++ b/src/test/java/test/TestGlobals.java @@ -21,6 +21,7 @@ public void run() throws Exception { code("global r = [0] return r[0] += 12").equals("12"); code("global r = [] return r[5] += 12").equals("12"); code_v10("global r = 12 r = @null").equals("null"); + code("global m = [] return m = m").equals("[]"); section("Globals operators"); code("global x = 12; x++; return x;").equals("13"); diff --git a/src/test/java/test/TestJSON.java b/src/test/java/test/TestJSON.java new file mode 100644 index 00000000..2bfc5af2 --- /dev/null +++ b/src/test/java/test/TestJSON.java @@ -0,0 +1,113 @@ +package test; + +public class TestJSON extends TestCommon { + + public void run() throws Exception { + + section("jsonEncode()"); + // code("jsonEncode()").error(ls::Error::Type::WRONG_ARGUMENT_COUNT, {"jsonEncode", "1", "0"}); + // integer + code("return jsonEncode(0)").equals("0"); + code("return jsonEncode(12)").equals("12"); + code("return jsonEncode(-589)").equals("-589"); + // real + code("return jsonEncode(54.123)").equals("54.123"); + code("return jsonEncode(-65.89)").equals("-65.89"); + // long + // code("return jsonEncode(1l)").equals("1"); + // code("return jsonEncode(1234567890987)").equals("1234567890987"); + // mpz + // code("return jsonEncode(1m)").equals("1"); + // code("return jsonEncode(123456789098712345678909871234567890987m)").equals("'123456789098712345678909871234567890987'"); + // code("return jsonEncode(15m ** 5)").equals("'759375'"); + // boolean + code("return jsonEncode(true)").equals("true"); + code("return jsonEncode(false)").equals("false"); + code("return jsonEncode(12 > 5)").equals("true"); + // string + code("return jsonEncode('')").equals("\"\""); + code("return jsonEncode('hello')").equals("\"hello\""); + // array + code("return jsonEncode([])").equals("[]"); + code("return jsonEncode([1, 2, 3])").equals("[1,2,3]"); + // object + // code("return jsonEncode({})").equals("'{}'"); + // code("return jsonEncode({a: 1, b: 2, c: 3})").equals("'{\"a\":1,\"b\":2,\"c\":3}'"); + // code("return jsonEncode({hello: [], b: {d: 12}, ccccc: [1, 2, [], 4]})").equals("'{\"b\":{\"d\":12},\"ccccc\":[1, 2, [], 4],\"hello\":[]}'"); + // function : not transformable into JSON + // code("return jsonEncode(x -> x)").equals("''"); + // code("return jsonEncode([1, x -> x, 3])").equals("'[1, 3]'"); + + // section("Value.json()"); + // // null + // code("null.json()").equals("'null'"); + // // integer + // code("0.json()").equals("'0'"); + // code("12.json()").equals("'12'"); + // code("(-589).json()").equals("'-589'"); + // // real + // code("54.123.json()").equals("'54.123'"); + // code("(-65.89).json()").equals("'-65.89'"); + // // long + // code("(1l).json()").equals("'1'"); + // code("1234567890987.json()").equals("'1234567890987'"); + // // boolean + // code("true.json()").equals("'true'"); + // code("false.json()").equals("'false'"); + // code("(12 > 5).json()").equals("'true'"); + // // string + // code("''.json()").equals("'\"\"'"); + // code("'hello'.json()").equals("'\"hello\"'"); + // // array + // code("[].json()").equals("'[]'"); + // code("[1, 2, 3].json()").equals("'[1, 2, 3]'"); + // code("['a', 'b', 'c'].json()").equals("'[\"a\", \"b\", \"c\"]'"); + // // set + // code("<1, 2, 3>.json()").equals("'[1, 2, 3]'"); + // code("<9.99>.json()").equals("'[9.990000]'"); + // code("<'a', 'b', 'c'>.json()").equals("'[\"a\", \"b\", \"c\"]'"); + // // map + // code("[1: 1].json()").equals("'{\"1\": 1}'"); + // code("['1': 1].json()").equals("'{\"1\": 1}'"); + // code("['a': 'b'].json()").equals("'{\"a\": \"b\"}'"); + // // object + // code("{}.json()").equals("'{}'"); + // code("{a: 1, b: 2, c: 3}.json()").equals("'{\"a\":1,\"b\":2,\"c\":3}'"); + // code("{hello: [], b: {d: 12}, ccccc: [1, 2, [], 4]}.json()").equals("'{\"b\":{\"d\":12},\"ccccc\":[1, 2, [], 4],\"hello\":[]}'"); + // // class + // code("Number.json()").equals("'\"\"'"); + + section("jsonDecode()"); + code("return jsonDecode('')").equals("null"); + code("return jsonDecode('null')").equals("null"); + code("return jsonDecode('true')").equals("true"); + code("return jsonDecode('false')").equals("false"); + + code("return jsonDecode('12')").equals("12"); + code("return jsonDecode('-589')").equals("-589"); + code_v10("return jsonDecode('54.123')").equals("54,123"); + code_v11("return jsonDecode('54.123')").equals("54.123"); + code_v10("return jsonDecode('-65.89')").equals("-65,89"); + code_v11("return jsonDecode('-65.89')").equals("-65.89"); + // code("return jsonDecode('1234567890987')").equals("1234567890987"); + + code("return jsonDecode('\"\"')").equals(""); + code("return jsonDecode('\"hello\"')").equals("hello"); + + code("return jsonDecode('[]')").equals("[]"); + code("return jsonDecode('[1,2,3]')").equals("[1, 2, 3]"); + code_v10("return jsonDecode('[1.6,2.1,3.77]')").equals("[1,6, 2,1, 3,77]"); + code_v11("return jsonDecode('[1.6,2.1,3.77]')").equals("[1.6, 2.1, 3.77]"); + code("return jsonDecode('[\"a\",\"b\",\"c\"]')").equals("[a, b, c]"); + code("return jsonDecode('[[],[[],[]],[]]')").equals("[[], [[], []], []]"); + + // code("return jsonDecode('{}')").equals("{}"); + // code("return jsonDecode('{\"a\":1,\"b\":2,\"c\":3}')").equals("{a: 1, b: 2, c: 3}"); + // code("return jsonDecode('{\"b\":{\"d\":12},\"ccccc\":[1,2,[],4],\"hello\":[]}')").equals("{b: {d: 12}, ccccc: [1, 2, [], 4], hello: []}"); + + section("Combinations"); + code("var v = 'salut' return jsonDecode(jsonEncode(v)) == v").equals("true"); + // code("var v = {b: {d: 12}, cc: [[], 4], h: []} return jsonDecode(jsonEncode(v)) == v").equals("true"); + code("var v = 'salut' return jsonEncode(jsonEncode(v))").equals("\"\\\"salut\\\"\""); + } +} diff --git a/src/test/java/test/TestMain.java b/src/test/java/test/TestMain.java index fc57908a..64f2dc8a 100644 --- a/src/test/java/test/TestMain.java +++ b/src/test/java/test/TestMain.java @@ -35,6 +35,7 @@ public static void main(String[] args) throws Exception { new TestIf().run(); new TestLoops().run(); new TestFunction().run(); + new TestJSON().run(); new TestFiles().run(); new TestEuler().run(); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 984a5486..9b7b1785 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -31,6 +31,10 @@ public void run() { code_v11("class A { a = 10 } var a = new A(); a.a-- return a.a").equals("9"); code_v11("class A { a = 10 } var a = new A(); return ++a.a").equals("11"); code_v11("class A { a = 10 } var a = new A(); a.a++ return a.a").equals("11"); + code_v11("class A { a = 10 } var a = [new A()]; a[0].a++ return a[0].a").equals("11"); + code_v11("class A { a = 10 } var a = [new A()]; a[0].a-- return a[0].a").equals("9"); + code_v11("class A { a = 10 } var a = [new A()]; ++a[0].a return a[0].a").equals("11"); + code_v11("class A { a = 10 } var a = [new A()]; --a[0].a return a[0].a").equals("9"); /* * Operators From 1f212190d6c50fcd3efafdce57324c41b02a5f06 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 215/319] [function] Fix abs() --- src/main/java/leekscript/runner/LeekFunctions.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 251ae5df..c295f985 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -21,9 +21,6 @@ public enum LeekFunctions implements ILeekFunction { abs(1) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - if (leekIA.getVersion() == 10) { - return LeekValueManager.getLeekDoubleValue(Math.abs(parameters[0].getDouble(leekIA))); - } if (parameters[0] instanceof DoubleLeekValue) { return LeekValueManager.getLeekDoubleValue(Math.abs(parameters[0].getDouble(leekIA))); } else { From 27c88448104d3000b06b27352f62ac67851a1ba5 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 216/319] [operator] Fix div --- src/main/java/leekscript/runner/LeekFunctions.java | 5 +++-- src/main/java/leekscript/runner/LeekOperations.java | 5 +---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index c295f985..72469bf1 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -1299,8 +1299,9 @@ public int[] parameters() { }, getOperations(0) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekIntValue((int) leekIA.getOperations()); + public AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { + ai.addOperations(1); + return LeekValueManager.getLeekIntValue((int) ai.getOperations()); } }, clone(1, 2) { diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index 2bc2bc7d..65f4a533 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -124,10 +124,7 @@ public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeek if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { return LeekValueManager.getLeekDoubleValue(v1.getDouble(ai) / v2.getDouble(ai)); } else { - if (ai.getVersion() == 10 && v1.getInt(ai) % v2.getInt(ai) == 0) - return LeekValueManager.getLeekIntValue(v1.getInt(ai) / v2.getInt(ai)); - else - return new DoubleLeekValue(v1.getDouble(ai) / v2.getDouble(ai)); + return new DoubleLeekValue(v1.getDouble(ai) / v2.getDouble(ai)); } } throw new LeekRunException(LeekRunException.INVALID_OPERATOR); From 1a03917c5502c615aeb8aa304d67eb19d84fc781 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 30 May 2021 12:33:30 +0200 Subject: [PATCH 217/319] [double] Fix doubles --- .../java/leekscript/runner/LeekFunctions.java | 14 +++++++------- .../java/leekscript/runner/LeekOperations.java | 16 ++++++---------- .../java/leekscript/runner/LeekValueManager.java | 11 ----------- .../leekscript/runner/values/IntLeekValue.java | 8 ++++---- 4 files changed, 17 insertions(+), 32 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 72469bf1..eef77579 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -22,7 +22,7 @@ public enum LeekFunctions implements ILeekFunction { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { if (parameters[0] instanceof DoubleLeekValue) { - return LeekValueManager.getLeekDoubleValue(Math.abs(parameters[0].getDouble(leekIA))); + return new DoubleLeekValue(Math.abs(parameters[0].getDouble(leekIA))); } else { return LeekValueManager.getLeekIntValue(Math.abs(parameters[0].getInt(leekIA))); } @@ -37,7 +37,7 @@ public int[] parameters() { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { if (parameters[0] instanceof DoubleLeekValue || parameters[1] instanceof DoubleLeekValue) { - return LeekValueManager.getLeekDoubleValue(Math.min(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); + return new DoubleLeekValue(Math.min(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); } return LeekValueManager.getLeekIntValue(Math.min(parameters[0].getInt(leekIA), parameters[1].getInt(leekIA))); } @@ -51,7 +51,7 @@ public int[] parameters() { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { if (parameters[0] instanceof DoubleLeekValue || parameters[1] instanceof DoubleLeekValue) { - return LeekValueManager.getLeekDoubleValue(Math.max(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); + return new DoubleLeekValue(Math.max(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); } return LeekValueManager.getLeekIntValue(Math.max(parameters[0].getInt(leekIA), parameters[1].getInt(leekIA))); } @@ -251,7 +251,7 @@ public int[] parameters() { pow(2) { @Override public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekDoubleValue(Math.pow(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); + return new DoubleLeekValue(Math.pow(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); } @Override @@ -566,7 +566,7 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu return LeekValueManager.NULL; try { if (parameters[0].getString(leekIA).contains(".")) { - return LeekValueManager.getLeekDoubleValue(Double.parseDouble(parameters[0].getString(leekIA))); + return new DoubleLeekValue(Double.parseDouble(parameters[0].getString(leekIA))); } else { return LeekValueManager.getLeekIntValue(Integer.parseInt(parameters[0].getString(leekIA))); } @@ -924,7 +924,7 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu for (AbstractLeekValue val : parameters[0].getArray()) { somme += val.getDouble(leekIA); } - return LeekValueManager.getLeekDoubleValue(somme); + return new DoubleLeekValue(somme); } @Override @@ -949,7 +949,7 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu } if (average == 0 && leekIA.getVersion() == 10) return LeekValueManager.getLeekIntValue(0); - return LeekValueManager.getLeekDoubleValue(average / parameters[0].getArray().size()); + return new DoubleLeekValue(average / parameters[0].getArray().size()); } @Override diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index 65f4a533..841223ec 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -23,7 +23,7 @@ public static AbstractLeekValue add(AI ai, AbstractLeekValue v1, AbstractLeekVal if (v1.isNumeric() && v2.isNumeric()) { ai.addOperations(1); if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { - return LeekValueManager.getLeekDoubleValue(v1.getDouble(ai) + v2.getDouble(ai)); + return new DoubleLeekValue(v1.getDouble(ai) + v2.getDouble(ai)); } else { return LeekValueManager.getLeekIntValue(v1.getInt(ai) + v2.getInt(ai)); } @@ -69,7 +69,7 @@ public static AbstractLeekValue minus(AI ai, AbstractLeekValue v1, AbstractLeekV v2 = v2.getValue(); if (v1.isNumeric() && v2.isNumeric()) { if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) - return LeekValueManager.getLeekDoubleValue(v1.getDouble(ai) - v2.getDouble(ai)); + return new DoubleLeekValue(v1.getDouble(ai) - v2.getDouble(ai)); else return LeekValueManager.getLeekIntValue(v1.getInt(ai) - v2.getInt(ai)); } @@ -85,7 +85,7 @@ public static AbstractLeekValue power(AI ai, AbstractLeekValue v1, AbstractLeekV double result = Math.pow(v1.getDouble(ai), v2.getDouble(ai)); if (Double.isNaN(result)) return LeekValueManager.NULL; - return LeekValueManager.getLeekDoubleValue(result); + return new DoubleLeekValue(result); } else { double result = Math.pow(v1.getInt(ai), v2.getInt(ai)); if (Double.isNaN(result)) @@ -102,7 +102,7 @@ public static AbstractLeekValue multiply(AI ai, AbstractLeekValue v1, AbstractLe v2 = v2.getValue(); if (v1.isNumeric() && v2.isNumeric()) { if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { - return LeekValueManager.getLeekDoubleValue(v1.getDouble(ai) * v2.getDouble(ai)); + return new DoubleLeekValue(v1.getDouble(ai) * v2.getDouble(ai)); } else { return LeekValueManager.getLeekIntValue(v1.getInt(ai) * v2.getInt(ai)); } @@ -121,11 +121,7 @@ public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeek ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); return LeekValueManager.NULL; } - if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { - return LeekValueManager.getLeekDoubleValue(v1.getDouble(ai) / v2.getDouble(ai)); - } else { - return new DoubleLeekValue(v1.getDouble(ai) / v2.getDouble(ai)); - } + return new DoubleLeekValue(v1.getDouble(ai) / v2.getDouble(ai)); } throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } @@ -141,7 +137,7 @@ public static AbstractLeekValue modulus(AI ai, AbstractLeekValue v1, AbstractLee return LeekValueManager.NULL; } if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) - return LeekValueManager.getLeekDoubleValue(v1.getDouble(ai) % v2.getDouble(ai)); + return new DoubleLeekValue(v1.getDouble(ai) % v2.getDouble(ai)); else return LeekValueManager.getLeekIntValue(v1.getInt(ai) % v2.getInt(ai)); } diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index 62fd4c94..a7469e72 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -54,17 +54,6 @@ public static FunctionLeekValue getFunction(ILeekFunction function) { return mFunctions.get(function.toString()); } - public static AbstractLeekValue getLeekDoubleValue(double nb) { - if (nb == 0) - return getLeekIntValue(0); - else if (nb == 1) - return getLeekIntValue(1); - else if (nb == -1) - return getLeekIntValue(-1); - else - return new DoubleLeekValue(nb); - } - public static AbstractLeekValue getLeekIntValue(int nb) { // Si c'est une valeur en cache on la retourne if (MIN_INT <= nb && nb <= MAX_INT) { diff --git a/src/main/java/leekscript/runner/values/IntLeekValue.java b/src/main/java/leekscript/runner/values/IntLeekValue.java index 39aac301..9af7fdef 100644 --- a/src/main/java/leekscript/runner/values/IntLeekValue.java +++ b/src/main/java/leekscript/runner/values/IntLeekValue.java @@ -92,7 +92,7 @@ public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunExcepti ai.addOperations(ADD_COST); val = val.getValue(); if (val instanceof DoubleLeekValue) - return LeekValueManager.getLeekDoubleValue(mValue + val.getDouble(ai)); + return new DoubleLeekValue(mValue + val.getDouble(ai)); return LeekValueManager.getLeekIntValue(ai, mValue + val.getInt(ai), this); } @@ -101,7 +101,7 @@ public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunExcep ai.addOperations(ADD_COST); val = val.getValue(); if (val instanceof DoubleLeekValue) - return LeekValueManager.getLeekDoubleValue(mValue - val.getDouble(ai)); + return new DoubleLeekValue(mValue - val.getDouble(ai)); return LeekValueManager.getLeekIntValue(ai, mValue - val.getInt(ai), this); } @@ -110,7 +110,7 @@ public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunEx ai.addOperations(MUL_COST); val = val.getValue(); if (val instanceof DoubleLeekValue) - return LeekValueManager.getLeekDoubleValue(mValue * val.getDouble(ai)); + return new DoubleLeekValue(mValue * val.getDouble(ai)); return LeekValueManager.getLeekIntValue(ai, mValue * val.getInt(ai), this); } @@ -169,7 +169,7 @@ public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunExc ai.addOperations(MOD_COST); val = val.getValue(); if (val instanceof DoubleLeekValue) - return LeekValueManager.getLeekDoubleValue(mValue % val.getDouble(ai)); + return new DoubleLeekValue(mValue % val.getDouble(ai)); return LeekValueManager.getLeekIntValue(ai, mValue % val.getInt(ai), this); } From 1cded6721db65022c279cad8f7a57867ac23a146 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 218/319] [operator] Fix cost --- src/main/java/leekscript/runner/LeekOperations.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index 841223ec..25023883 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -64,10 +64,10 @@ public static AbstractLeekValue add(AI ai, AbstractLeekValue v1, AbstractLeekVal } public static AbstractLeekValue minus(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); v1 = v1.getValue(); v2 = v2.getValue(); if (v1.isNumeric() && v2.isNumeric()) { + ai.addOperations(1); if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) return new DoubleLeekValue(v1.getDouble(ai) - v2.getDouble(ai)); else @@ -77,10 +77,10 @@ public static AbstractLeekValue minus(AI ai, AbstractLeekValue v1, AbstractLeekV } public static AbstractLeekValue power(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(AbstractLeekValue.POW_COST); v1 = v1.getValue(); v2 = v2.getValue(); if (v1.isNumeric() && v2.isNumeric()) { + ai.addOperations(AbstractLeekValue.POW_COST); if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { double result = Math.pow(v1.getDouble(ai), v2.getDouble(ai)); if (Double.isNaN(result)) @@ -97,10 +97,10 @@ public static AbstractLeekValue power(AI ai, AbstractLeekValue v1, AbstractLeekV } public static AbstractLeekValue multiply(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(AbstractLeekValue.MUL_COST); v1 = v1.getValue(); v2 = v2.getValue(); if (v1.isNumeric() && v2.isNumeric()) { + ai.addOperations(AbstractLeekValue.MUL_COST); if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { return new DoubleLeekValue(v1.getDouble(ai) * v2.getDouble(ai)); } else { @@ -112,11 +112,10 @@ public static AbstractLeekValue multiply(AI ai, AbstractLeekValue v1, AbstractLe public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(AbstractLeekValue.DIV_COST); - v1 = v1.getValue(); v2 = v2.getValue(); if (v1.isNumeric() && v2.isNumeric()) { + ai.addOperations(AbstractLeekValue.DIV_COST); if (v2.getDouble(ai) == 0) { ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); return LeekValueManager.NULL; @@ -128,10 +127,10 @@ public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeek public static AbstractLeekValue modulus(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(AbstractLeekValue.MOD_COST); v1 = v1.getValue(); v2 = v2.getValue(); if (v1.isNumeric() && v2.isNumeric()) { + ai.addOperations(AbstractLeekValue.MOD_COST); if (v2.getDouble(ai) == 0) { ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); return LeekValueManager.NULL; From 6dcb9c30f363594060555d6c4ba58b7c3d4e1c48 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 219/319] [sort] Fix sort --- src/main/java/leekscript/runner/LeekValueComparator.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekValueComparator.java b/src/main/java/leekscript/runner/LeekValueComparator.java index 1073af7d..32b510c0 100644 --- a/src/main/java/leekscript/runner/LeekValueComparator.java +++ b/src/main/java/leekscript/runner/LeekValueComparator.java @@ -34,6 +34,9 @@ else if (mOrder == SORT_DESC) public int compareAsc(AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { if (LeekFunctions.isType(v1, LeekFunctions.BOOLEAN)) { + if (LeekFunctions.isType(v2, LeekFunctions.NULL)) { + return 1; + } if (LeekFunctions.isType(v2, LeekFunctions.BOOLEAN)) { if (v1.getBoolean() == v2.getBoolean()) return 0; @@ -51,14 +54,14 @@ else if (v1.getDouble(ai) < v2.getDouble(ai)) return -1; else return 1; - } else if (LeekFunctions.isType(v2, LeekFunctions.BOOLEAN)) + } else if (LeekFunctions.isType(v2, LeekFunctions.BOOLEAN) || LeekFunctions.isType(v2, LeekFunctions.NULL)) return 1; else return -1; } else if (LeekFunctions.isType(v1, LeekFunctions.STRING)) { if (LeekFunctions.isType(v2, LeekFunctions.STRING)) { return v1.getString(ai).compareTo(v2.getString(ai)); - } else if (LeekFunctions.isType(v2, LeekFunctions.NUMBER) || LeekFunctions.isType(v2, LeekFunctions.BOOLEAN)) + } else if (LeekFunctions.isType(v2, LeekFunctions.NUMBER) || LeekFunctions.isType(v2, LeekFunctions.BOOLEAN) || LeekFunctions.isType(v2, LeekFunctions.NULL)) return 1; else return -1; From 86b7d49f80562d8b7fb69616f0206b0b4d74bb02 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 220/319] [test] Add tests --- src/test/java/test/TestCommon.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index 6225d06b..0a513ff4 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -50,8 +50,8 @@ public Case(String code, boolean enabled, int version) { this.version = version; } - public void equals(String expected) { - run(version, new Checker() { + public String equals(String expected) { + return run(version, new Checker() { public boolean check(Result result) { return result.result.equals(expected); } @@ -60,8 +60,8 @@ public boolean check(Result result) { }); } - public void error(Error type) { - run(version, new Checker() { + public String error(Error type) { + return run(version, new Checker() { public boolean check(Result result) { return result.error == type; } @@ -89,22 +89,22 @@ public boolean check(Result result) { }); } - public void run(int version, Checker checker) { + public String run(int version, Checker checker) { if (!enabled) { disabled++; var s = C_PINK + "[DISA] " + END_COLOR + "[v" + version + "] " + code; System.out.println(s); disabledTests.add(s); - return; + return "disabled"; } if (version == -1) { run_version(10, checker); - run_version(11, checker); + return run_version(11, checker); } else { - run_version(version, checker); + return run_version(version, checker); } } - public void run_version(int version, Checker checker) { + public String run_version(int version, Checker checker) { tests++; int aiID = 0; Result result; @@ -154,6 +154,7 @@ public void run_version(int version, Checker checker) { System.out.println(err); failedTests.add(err); } + return result.result; } } From b875199260207d58465ddc1e02ad166d1ec23ce4 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 221/319] [operator] null operators --- .../leekscript/runner/LeekOperations.java | 147 ++++++++++-------- .../runner/values/ArrayLeekValue.java | 66 ++++++++ .../runner/values/BooleanLeekValue.java | 40 +++++ .../runner/values/DoubleLeekValue.java | 14 +- .../runner/values/IntLeekValue.java | 48 ++++-- .../runner/values/NullLeekValue.java | 29 +++- .../runner/values/StringLeekValue.java | 69 +++++++- .../runner/values/VariableLeekValue.java | 5 +- 8 files changed, 327 insertions(+), 91 deletions(-) diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index 25023883..c936f333 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -20,19 +20,42 @@ public static AbstractLeekValue add(AI ai, AbstractLeekValue v1, AbstractLeekVal v1 = v1.getValue(); v2 = v2.getValue(); - if (v1.isNumeric() && v2.isNumeric()) { - ai.addOperations(1); - if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { - return new DoubleLeekValue(v1.getDouble(ai) + v2.getDouble(ai)); - } else { - return LeekValueManager.getLeekIntValue(v1.getInt(ai) + v2.getInt(ai)); - } + if (v1 instanceof StringLeekValue || v2 instanceof StringLeekValue) { + String v1_string = v1.getString(ai); + String v2_string = v2.getString(ai); + ai.addOperations(1 + v1_string.length() + v2_string.length()); + return new StringLeekValue(v1_string + v2_string); } - // Concatenate arrays - if (v1 instanceof ArrayLeekValue && v2 instanceof ArrayLeekValue) { + if (v1 instanceof ArrayLeekValue) { + if (v2 instanceof ArrayLeekValue) { + + ai.addOperations(1 + (v1.getArray().size() + v2.getArray().size()) * 2); - ai.addOperations(1 + (v1.getArray().size() + v2.getArray().size()) * 2); + ArrayLeekValue retour = new ArrayLeekValue(); + ArrayIterator iterator = v1.getArray().getArrayIterator(); + + while (!iterator.ended()) { + if (iterator.key() instanceof String) { + retour.getOrCreate(ai, iterator.getKey(ai)).setNoOps(ai, iterator.getValue(ai)); + } else { + retour.push(ai, iterator.getValue(ai)); + } + iterator.next(); + } + iterator = v2.getArray().getArrayIterator(); + while (!iterator.ended()) { + if (iterator.key() instanceof String) { + retour.getOrCreate(ai, iterator.getKey(ai)).setNoOps(ai, iterator.getValue(ai)); + } else { + retour.push(ai, iterator.getValue(ai)); + } + iterator.next(); + } + return retour; + } + + ai.addOperations(1 + v1.getArray().size() * 2); ArrayLeekValue retour = new ArrayLeekValue(); ArrayIterator iterator = v1.getArray().getArrayIterator(); @@ -45,7 +68,19 @@ public static AbstractLeekValue add(AI ai, AbstractLeekValue v1, AbstractLeekVal } iterator.next(); } - iterator = v2.getArray().getArrayIterator(); + retour.push(ai, v2); + return retour; + } + + if (v2 instanceof ArrayLeekValue) { + + ai.addOperations(1 + v2.getArray().size() * 2); + + ArrayLeekValue retour = new ArrayLeekValue(); + ArrayIterator iterator = v2.getArray().getArrayIterator(); + + retour.push(ai, v1); + while (!iterator.ended()) { if (iterator.key() instanceof String) { retour.getOrCreate(ai, iterator.getKey(ai)).setNoOps(ai, iterator.getValue(ai)); @@ -57,90 +92,70 @@ public static AbstractLeekValue add(AI ai, AbstractLeekValue v1, AbstractLeekVal return retour; } - String v1_string = v1.getString(ai); - String v2_string = v2.getString(ai); - ai.addOperations(1 + v1_string.length() + v2_string.length()); - return new StringLeekValue(v1_string + v2_string); + ai.addOperations(1); + if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { + return new DoubleLeekValue(v1.getDouble(ai) + v2.getDouble(ai)); + } + return LeekValueManager.getLeekIntValue(v1.getInt(ai) + v2.getInt(ai)); } public static AbstractLeekValue minus(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { v1 = v1.getValue(); v2 = v2.getValue(); - if (v1.isNumeric() && v2.isNumeric()) { - ai.addOperations(1); - if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) - return new DoubleLeekValue(v1.getDouble(ai) - v2.getDouble(ai)); - else - return LeekValueManager.getLeekIntValue(v1.getInt(ai) - v2.getInt(ai)); + ai.addOperations(1); + if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { + return new DoubleLeekValue(v1.getDouble(ai) - v2.getDouble(ai)); + } else { + return LeekValueManager.getLeekIntValue(v1.getInt(ai) - v2.getInt(ai)); } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } - public static AbstractLeekValue power(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { v1 = v1.getValue(); v2 = v2.getValue(); - if (v1.isNumeric() && v2.isNumeric()) { - ai.addOperations(AbstractLeekValue.POW_COST); - if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { - double result = Math.pow(v1.getDouble(ai), v2.getDouble(ai)); - if (Double.isNaN(result)) - return LeekValueManager.NULL; - return new DoubleLeekValue(result); - } else { - double result = Math.pow(v1.getInt(ai), v2.getInt(ai)); - if (Double.isNaN(result)) - return LeekValueManager.NULL; - return LeekValueManager.getLeekIntValue((int) result); - } + ai.addOperations(AbstractLeekValue.POW_COST); + if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { + return new DoubleLeekValue(Math.pow(v1.getDouble(ai), v2.getDouble(ai))); + } else { + return LeekValueManager.getLeekIntValue((int) Math.pow(v1.getInt(ai), v2.getInt(ai))); } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } public static AbstractLeekValue multiply(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { v1 = v1.getValue(); v2 = v2.getValue(); - if (v1.isNumeric() && v2.isNumeric()) { - ai.addOperations(AbstractLeekValue.MUL_COST); - if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { - return new DoubleLeekValue(v1.getDouble(ai) * v2.getDouble(ai)); - } else { - return LeekValueManager.getLeekIntValue(v1.getInt(ai) * v2.getInt(ai)); - } + ai.addOperations(AbstractLeekValue.MUL_COST); + if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { + return new DoubleLeekValue(v1.getDouble(ai) * v2.getDouble(ai)); + } else { + return LeekValueManager.getLeekIntValue(v1.getInt(ai) * v2.getInt(ai)); } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - v1 = v1.getValue(); v2 = v2.getValue(); - if (v1.isNumeric() && v2.isNumeric()) { - ai.addOperations(AbstractLeekValue.DIV_COST); - if (v2.getDouble(ai) == 0) { - ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); - return LeekValueManager.NULL; - } - return new DoubleLeekValue(v1.getDouble(ai) / v2.getDouble(ai)); + ai.addOperations(AbstractLeekValue.DIV_COST); + double y_real = v2.getDouble(ai); + if (ai.getVersion() == 10 && y_real == 0) { + ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); + return LeekValueManager.NULL; } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + return new DoubleLeekValue(v1.getDouble(ai) / y_real); } public static AbstractLeekValue modulus(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - v1 = v1.getValue(); v2 = v2.getValue(); - if (v1.isNumeric() && v2.isNumeric()) { - ai.addOperations(AbstractLeekValue.MOD_COST); - if (v2.getDouble(ai) == 0) { - ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); - return LeekValueManager.NULL; - } - if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) - return new DoubleLeekValue(v1.getDouble(ai) % v2.getDouble(ai)); - else - return LeekValueManager.getLeekIntValue(v1.getInt(ai) % v2.getInt(ai)); + ai.addOperations(AbstractLeekValue.MOD_COST); + if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { + return new DoubleLeekValue(v1.getDouble(ai) % v2.getDouble(ai)); + } + var v2_int = v2.getInt(ai); + if (v2_int == 0) { + ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); + return LeekValueManager.NULL; } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + return LeekValueManager.getLeekIntValue(v1.getInt(ai) % v2_int); } public static AbstractLeekValue and(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index 9fee5c76..fd101d3b 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -108,6 +108,16 @@ public int size() { return mValues.size(); } + @Override + public int getInt(AI ai) throws LeekRunException { + return mValues.size(); + } + + @Override + public double getDouble(AI ai) throws LeekRunException { + return mValues.size(); + } + @Override public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunException { Object key; @@ -290,10 +300,66 @@ public AbstractLeekValue add(AI ai, AbstractLeekValue value) throws LeekRunExcep mValues.push(ai, iterator.getValue(ai)); iterator.next(); } + } else { + mValues.push(ai, value); } return this; } + @Override + public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.minus(ai, this, val); + } + + @Override + public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.multiply(ai, this, val); + } + + @Override + public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.divide(ai, this, val); + } + + @Override + public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.modulus(ai, this, val); + } + + @Override + public AbstractLeekValue power(AI ai, AbstractLeekValue value) throws LeekRunException { + return LeekOperations.power(ai, this, value); + } + + @Override + public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.band(ai, this, val); + } + + @Override + public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bor(ai, this, val); + } + + @Override + public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bxor(ai, this, val); + } + + @Override + public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bleft(ai, this, val); + } + + @Override + public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bright(ai, this, val); + } + + @Override + public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.brotate(ai, this, val); + } public ArrayIterator getArrayIterator() { return new ArrayIterator(mValues.getHeadElement()); } diff --git a/src/main/java/leekscript/runner/values/BooleanLeekValue.java b/src/main/java/leekscript/runner/values/BooleanLeekValue.java index d353ef87..b14011fb 100644 --- a/src/main/java/leekscript/runner/values/BooleanLeekValue.java +++ b/src/main/java/leekscript/runner/values/BooleanLeekValue.java @@ -42,11 +42,21 @@ public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunExcepti return LeekOperations.add(ai, this, val); } + @Override + public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.minus(ai, this, val); + } + @Override public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { return LeekOperations.multiply(ai, this, val); } + @Override + public AbstractLeekValue power(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.power(ai, this, val); + } + @Override public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { return LeekOperations.divide(ai, this, val); @@ -57,6 +67,36 @@ public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunExc return LeekOperations.modulus(ai, this, val); } + @Override + public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.band(ai, this, val); + } + + @Override + public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bor(ai, this, val); + } + + @Override + public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bxor(ai, this, val); + } + + @Override + public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bleft(ai, this, val); + } + + @Override + public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bright(ai, this, val); + } + + @Override + public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.brotate(ai, this, val); + } + @Override public int getV10Type() { return BOOLEAN_V10; diff --git a/src/main/java/leekscript/runner/values/DoubleLeekValue.java b/src/main/java/leekscript/runner/values/DoubleLeekValue.java index 639c8934..6e5465e8 100644 --- a/src/main/java/leekscript/runner/values/DoubleLeekValue.java +++ b/src/main/java/leekscript/runner/values/DoubleLeekValue.java @@ -2,9 +2,12 @@ import java.text.DecimalFormat; +import leekscript.AILog; import leekscript.runner.AI; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; +import leekscript.common.Error; +import leekscript.runner.LeekOperations; public class DoubleLeekValue extends AbstractLeekValue { @@ -87,9 +90,7 @@ public boolean more(AI ai, AbstractLeekValue comp) throws LeekRunException { @Override public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { - ai.addOperations(ADD_COST); - mValue += val.getDouble(ai); - return this; + return LeekOperations.add(ai, this, val); } @Override @@ -109,7 +110,12 @@ public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunEx @Override public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { ai.addOperations(DIV_COST); - mValue /= val.getDouble(ai); + double y_real = val.getDouble(ai); + if (ai.getVersion() == 10 && y_real == 0) { + ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); + return LeekValueManager.NULL; + } + mValue /= y_real; return this; } diff --git a/src/main/java/leekscript/runner/values/IntLeekValue.java b/src/main/java/leekscript/runner/values/IntLeekValue.java index 9af7fdef..b4194f0d 100644 --- a/src/main/java/leekscript/runner/values/IntLeekValue.java +++ b/src/main/java/leekscript/runner/values/IntLeekValue.java @@ -1,9 +1,12 @@ package leekscript.runner.values; +import leekscript.AILog; import leekscript.runner.AI; import leekscript.runner.LeekOperations; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; +import leekscript.runner.LeekOperations; +import leekscript.common.Error; public class IntLeekValue extends AbstractLeekValue { private int mValue; @@ -89,11 +92,7 @@ public boolean more(AI ai, AbstractLeekValue comp) throws LeekRunException { @Override public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { - ai.addOperations(ADD_COST); - val = val.getValue(); - if (val instanceof DoubleLeekValue) - return new DoubleLeekValue(mValue + val.getDouble(ai)); - return LeekValueManager.getLeekIntValue(ai, mValue + val.getInt(ai), this); + return LeekOperations.add(ai, this, val); } @Override @@ -114,6 +113,26 @@ public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunEx return LeekValueManager.getLeekIntValue(ai, mValue * val.getInt(ai), this); } + @Override + public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { + ai.addOperations(MOD_COST); + val = val.getValue(); + if (val instanceof DoubleLeekValue) { + double y_real = val.getDouble(ai); + if (ai.getVersion() == 10 && y_real == 0) { + ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); + return LeekValueManager.NULL; + } + return new DoubleLeekValue(mValue % y_real); + } + int y_int = val.getInt(ai); + if (ai.getVersion() == 10 && y_int == 0) { + ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); + return LeekValueManager.NULL; + } + return LeekValueManager.getLeekIntValue(ai, mValue % y_int, this); + } + @Override public AbstractLeekValue power(AI ai, AbstractLeekValue val) throws LeekRunException { ai.addOperations(POW_COST); @@ -164,15 +183,6 @@ public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunExce return LeekOperations.divide(ai, this, val); } - @Override - public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { - ai.addOperations(MOD_COST); - val = val.getValue(); - if (val instanceof DoubleLeekValue) - return new DoubleLeekValue(mValue % val.getDouble(ai)); - return LeekValueManager.getLeekIntValue(ai, mValue % val.getInt(ai), this); - } - @Override public int getV10Type() { return NUMBER_V10; @@ -195,9 +205,17 @@ else if (comp.getType() == BOOLEAN) { return comp.getBoolean() == getBoolean(); } else if (comp.getType() == STRING) { + if (comp.getString(ai).equals("false") || comp.getString(ai).equals("0") || comp.getString(ai).equals("")) + return mValue == 0; if (comp.getString(ai).equals("true")) return mValue != 0; - return mValue == comp.getInt(ai); + if (comp.getString(ai).equals("1") && mValue == 1) return true; + try { + ai.addOperations(comp.getString(ai).length()); + return mValue == Integer.parseInt(comp.getString(ai)); + } catch (Exception e) { + return false; + } } else if (comp.getType() == ARRAY) { return comp.equals(ai, this); diff --git a/src/main/java/leekscript/runner/values/NullLeekValue.java b/src/main/java/leekscript/runner/values/NullLeekValue.java index b9ab2c19..cbb666a4 100644 --- a/src/main/java/leekscript/runner/values/NullLeekValue.java +++ b/src/main/java/leekscript/runner/values/NullLeekValue.java @@ -51,8 +51,33 @@ public AbstractLeekValue power(AI ai, AbstractLeekValue value) throws LeekRunExc } @Override - public AbstractLeekValue bor(AI ai, AbstractLeekValue value) throws LeekRunException { - return LeekOperations.bor(ai, this, value); + public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.band(ai, this, val); + } + + @Override + public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bor(ai, this, val); + } + + @Override + public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bxor(ai, this, val); + } + + @Override + public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bleft(ai, this, val); + } + + @Override + public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bright(ai, this, val); + } + + @Override + public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.brotate(ai, this, val); } @Override diff --git a/src/main/java/leekscript/runner/values/StringLeekValue.java b/src/main/java/leekscript/runner/values/StringLeekValue.java index 325f8f18..7bfcd22a 100644 --- a/src/main/java/leekscript/runner/values/StringLeekValue.java +++ b/src/main/java/leekscript/runner/values/StringLeekValue.java @@ -2,6 +2,7 @@ import leekscript.runner.AI; import leekscript.runner.LeekRunException; +import leekscript.runner.LeekOperations; public class StringLeekValue extends AbstractLeekValue { @@ -36,7 +37,7 @@ public int getInt(AI ai) throws LeekRunException { try { return Integer.parseInt(mValue); } catch (Exception e) { - return 1; + return mValue.length(); } } @@ -52,7 +53,7 @@ public double getDouble(AI ai) throws LeekRunException { try { return Double.parseDouble(mValue); } catch (Exception e) { - return 1; + return mValue.length(); } } @@ -64,6 +65,61 @@ public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunExcepti return this; } + @Override + public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.minus(ai, this, val); + } + + @Override + public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.multiply(ai, this, val); + } + + @Override + public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.divide(ai, this, val); + } + + @Override + public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.modulus(ai, this, val); + } + + @Override + public AbstractLeekValue power(AI ai, AbstractLeekValue value) throws LeekRunException { + return LeekOperations.power(ai, this, value); + } + + @Override + public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.band(ai, this, val); + } + + @Override + public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bor(ai, this, val); + } + + @Override + public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bxor(ai, this, val); + } + + @Override + public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bleft(ai, this, val); + } + + @Override + public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.bright(ai, this, val); + } + + @Override + public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws LeekRunException { + return LeekOperations.brotate(ai, this, val); + } + @Override public int getV10Type() { return STRING_V10; @@ -78,8 +134,15 @@ public int getType() { @Override public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { if (comp.getType() == NUMBER) { - if (mValue.equals("true")) + if (mValue.equals("false") || mValue.equals("0") || mValue.equals("")) { + return comp.getInt(ai) == 0; + } + if (mValue.equals("true")) { return comp.getDouble(ai) != 0; + } + if (mValue.equals("1") && comp.getDouble(ai) == 1) { + return true; + } if (comp instanceof IntLeekValue) return getInt(ai) == comp.getInt(ai); else diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index 87c3f672..9d3421fb 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -201,7 +201,10 @@ public boolean more(AI ai, AbstractLeekValue comp) throws LeekRunException { @Override public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { - return mValue = mValue.add(ai, val); + if (mValue.getValue() instanceof ArrayLeekValue && !(val.getValue() instanceof StringLeekValue)) { + return mValue = mValue.add(ai, val); + } + return mValue = LeekOperations.add(ai, mValue, val); } @Override From 9344d1f07ac69a53afff284a408f693c74549c9d Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 222/319] [test] Add more tests --- src/test/java/test/TestArray.java | 29 +++++++++++++++-- src/test/java/test/TestFunction.java | 4 +++ src/test/java/test/TestGeneral.java | 1 + src/test/java/test/TestOperators.java | 47 ++++++++++++++++++++++++--- 4 files changed, 75 insertions(+), 6 deletions(-) diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index e8ce94eb..736ea2f6 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -1,5 +1,7 @@ package test; +import leekscript.common.Error; + public class TestArray extends TestCommon { public void run() throws Exception { @@ -78,6 +80,14 @@ public void run() throws Exception { code("var a = null return a['a']").equals("null"); code("var a = null return a[1] = 12").equals("null"); + section("Array misc"); + code("return [1, 2, 3] + null").equals("[1, 2, 3, null]"); + code("var a = [1] return a % 2").equals("1"); + code_v10("var a = [[1], [1]]; return (a[0] + a[2]) / 2").equals("1"); + code_v11("var a = [[1], [1]]; return (a[0] + a[2]) / 2").equals("1.0"); + code_v10("var effects = [[1], [1]];\n\nreturn (effects[0] + effects[2]) /2;").equals("1"); + code_v11("var effects = [[1], [1]];\n\nreturn (effects[0] + effects[2]) /2;").equals("1.0"); + section("Array.operator []"); code("return [1, 2, 3][1]").equals("2"); code("var a = [1, 2, 3] return a[0]").equals("1"); @@ -198,8 +208,8 @@ public void run() throws Exception { // DISABLED_code("var a = [] if (true) a += 12 return a;").equals("[12]"); // DISABLED_code("var a = [1] if (true) a += 12 return a;").equals("[1, 12]"); // DISABLED_code("var a = ['a'] if (true) a += 12 return a;").equals("['a', 12]"); - code_v10("var a = [1.55]; a += 12.9; return a").equals("[1,55]"); - code_v11("var a = [1.55]; a += 12.9; return a").equals("[1.55]"); + code_v10("var a = [1.55]; a += 12.9; return a").equals("[1,55, 12,9]"); + code_v11("var a = [1.55]; a += 12.9; return a").equals("[1.55, 12.9]"); section("Array.operator += on element"); code("var a = [5] a[0] += 1 return a;").equals("[6]"); @@ -401,12 +411,27 @@ public void run() throws Exception { code("var a = ['a','b','c','d']; reverse(a); return a").equals("[d, c, b, a]"); section("Array.arrayMin()"); + code("return arrayMin([])").equals("null"); code("return arrayMin([8,4,3,-1,8,44])").equals("-1"); code("return arrayMin([0:7,8:9,'a':2])").equals("2"); + code("return arrayMin([1, 2, 3, 4, 5, null])").equals("null"); + code("var a = arrayMin([1, 2, 3, 4, 5, null]) return a").equals("null"); + code("return arrayMin([1, 2, 3, 4, 5, null])").equals("null"); + code("return arrayMin([1, 2, 3, null, 4, 5])").equals("null"); + code("return arrayMin([1, null, 5, 3, null, 2])").equals("null"); + code("return arrayMin([null, 3, 4, 5, null, 1])").equals("null"); + code("var a = [560 : null, 595 : null, 601 : 15, 566 : 13, 531 : 13] return arrayMin(a)").equals("null"); section("Array.arrayMax()"); + code("return arrayMax([])").equals("null"); code("return arrayMax([8,4,3,-1,8,44])").equals("44"); code("return arrayMax([0:7,8:9,'a':2])").equals("9"); + code("return arrayMax([1, 2, 3, 4, 5, null])").equals("5"); + code("return arrayMax([1, 2, 3, null, 4, 5])").equals("5"); + code("return arrayMax([1, null, 5, 3, null, 2])").equals("5"); + code("return arrayMax([null, 3, 4, 5, null, 1])").equals("5"); + code("var a = arrayMax([1, 2, 3, 4, 5, null]) return a").equals("5"); + code("var a = [560 : null, 595 : null, 601 : 15, 566 : 13, 531 : 13] return arrayMax(a)").equals("15"); section("Array.sum()"); code_v10("return sum([1,5,7])").equals("13"); diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index f6f2d634..e61ac0be 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -23,6 +23,7 @@ public void run() { section("Redefinition"); code("var count = count([1, 2, 3]) return count;").equals("3"); + code("var d = debug d('salut')").equals("null"); section("System function as argument"); code_v10("function t(@f) { return function(@a) { return arrayMap(a, f); } } return t(sqrt)([1, 4, 9, 16, 25]);").equals("[1, 2, 3, 4, 5]"); @@ -71,6 +72,9 @@ public void run() { code("function t(a) {} t([ [12], [12] ])").equals("null"); code_v10("function t(@a) {} t([ [12], [12] ])").equals("null"); code_v10("function t() { var a = 12 return @a } return t() + 2").equals("14"); + code("function t() { var a = [1, 2, 3] return a } var x = t() var f = function() { return x } return x").equals("[1, 2, 3]"); + code("push = 1 return push").equals("1"); + code_v10("function LamaSwag() {} @LamaSwag();").equals("null"); section("Modify argument"); code("function test(x) { x += 10 return x } return test(5)").equals("15"); diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index 31e65fa4..c7197a21 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -99,6 +99,7 @@ public void run() { code("var y if (false) { if (true) {;} else { y = 2 } } else { y = 5 } return y").equals("5"); code_v10("PI = PI + 12; return PI").equals("3,142"); code_v11("PI = PI + 12; return PI").equals("3.141592653589793"); + code_v10("var grow = []; var n = []; grow = @n; return grow").equals("[]"); section("Assignments with +="); code_v10("var a = 10 a += 0.5 return a").equals("10,5"); diff --git a/src/test/java/test/TestOperators.java b/src/test/java/test/TestOperators.java index 3dd5ba7d..9ca9d70d 100644 --- a/src/test/java/test/TestOperators.java +++ b/src/test/java/test/TestOperators.java @@ -1,5 +1,8 @@ package test; +import java.util.ArrayList; +import java.util.List; + public class TestOperators extends TestCommon { public void run() throws Exception { @@ -44,7 +47,7 @@ public void run() throws Exception { code("return 1 == true").equals("true"); code("return 1 == '1'").equals("true"); code("return 1 == 'true'").equals("true"); - code("return 1 == 'lama'").equals("true"); + code("return 1 == 'lama'").equals("false"); code("return 1 == [1]").equals("true"); code("return 1 == 2").equals("false"); @@ -87,18 +90,18 @@ public void run() throws Exception { "X X XX XXX ", // false " X XX XXXX XXX ", // true "X X XX XXX ", // 0 - " X X X XX X ", // 1 + " X X X X X ", // 1 " X X X X X ", // 12 "X X X XX ", // " " "X X X X ", // "0" " X X X X ", // "1" " X X X X ", // "12" - " X X X X ", // "lama" + " X X ", // "lama" " X XX X XXX ", // "true" "X X XXX ", // "false" "X X X XX ", // [] "X X XX X X ", // [0] - " X X X XX X ", // [1] + " X X X X X ", // [1] " X X X X X ", // [12] " X X X ", // [1,2,3] " X", // null @@ -164,5 +167,41 @@ public void run() throws Exception { code("return null + true").equals("1"); code("return false + null").equals("0"); code("return null + false").equals("0"); + + section("Assignment operators"); + Object[] values2 = new Object[] { + "null", "true", "false", "12", "5.678", "false", "true", "'lama'", "[1, 2, 3, 4, 5]" + }; + Object[] operators = new Object[] { + "+", "-", "*", "/", "%", "&", "^", "|", "<<", ">>", ">>>", "**", + }; + Object[] assignmentOperators = new Object[] { + "+=", "-=", "*=", "/=", "%=", "&=", "^=", "|=", "<<=", ">>=", ">>>=", "**=", + }; + String[] actualResults = new String[] { + "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "12", "-12", "0", "0", "0", "0", "12", "12", "0", "0", "0", "0", "12", "-12", "0", "0", "0", "0", "0", "12", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "nulllama", "-4", "0", "0", "0", "0", "4", "4", "0", "0", "0", "0", "nulllama", "-4", "0", "0", "0", "0", "0", "4", "0", "0", "0", "0", "[null, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "[null, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "2", "0", "1", "1", "0", "1", "0", "1", "2", "0", "0", "1", "2", "0", "1", "1", "0", "1", "1", "1", "2", "0", "0", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "13", "-11", "12", "0,083", "1", "0", "13", "13", "4096", "0", "0", "1", "13", "-11", "12", "0,083", "1", "0", "1", "13", "4096", "0", "0", "1", "6,678", "-4,678", "5,678", "0,176", "1", "1", "4", "5", "32", "0", "0", "1", "6,678", "-4,678", "5,678", "0,176", "1", "1", "1", "5", "32", "0", "0", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "2", "0", "1", "1", "0", "1", "0", "1", "2", "0", "0", "1", "2", "0", "1", "1", "0", "1", "1", "1", "2", "0", "0", "1", "truelama", "-3", "4", "0,25", "1", "0", "5", "5", "16", "0", "0", "1", "truelama", "-3", "4", "0,25", "1", "0", "1", "5", "16", "0", "0", "1", "[true, 1, 2, 3, 4, 5]", "-4", "5", "0,2", "1", "1", "4", "5", "32", "0", "0", "1", "[true, 1, 2, 3, 4, 5]", "-4", "5", "0,2", "1", "1", "1", "5", "32", "0", "0", "1", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "12", "-12", "0", "0", "0", "0", "12", "12", "0", "0", "0", "0", "12", "-12", "0", "0", "0", "0", "0", "12", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "falselama", "-4", "0", "0", "0", "0", "4", "4", "0", "0", "0", "0", "falselama", "-4", "0", "0", "0", "0", "0", "4", "0", "0", "0", "0", "[false, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "[false, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "12", "12", "0", "null", "null", "0", "12", "12", "12", "12", "12", "1", "12", "12", "0", "null", "null", "0", "1", "12", "12", "12", "12", "1", "13", "11", "12", "12", "0", "0", "13", "13", "24", "6", "6", "12", "13", "11", "12", "12", "0", "0", "12", "13", "24", "6", "6", "12", "12", "12", "0", "null", "null", "0", "12", "12", "12", "12", "12", "1", "12", "12", "0", "null", "null", "0", "1", "12", "12", "12", "12", "1", "24", "0", "144", "1", "0", "12", "0", "12", "49152", "0", "0", "2147483647", "24", "0", "144", "1", "0", "12", "2147483647", "12", "49152", "0", "0", "2147483647", "17,678", "6,322", "68,136", "2,113", "0,644", "4", "9", "13", "384", "0", "0", "1 341 501,353", "17,678", "6,322", "68,136", "2,113", "0,644", "4", "1 341 501,353", "13", "384", "0", "0", "1 341 501,353", "12", "12", "0", "null", "null", "0", "12", "12", "12", "12", "12", "1", "12", "12", "0", "null", "null", "0", "1", "12", "12", "12", "12", "1", "13", "11", "12", "12", "0", "0", "13", "13", "24", "6", "6", "12", "13", "11", "12", "12", "0", "0", "12", "13", "24", "6", "6", "12", "12lama", "8", "48", "3", "0", "4", "8", "12", "192", "0", "0", "20736", "12lama", "8", "48", "3", "0", "4", "20736", "12", "192", "0", "0", "20736", "[12, 1, 2, 3, 4, 5]", "7", "60", "2,4", "2", "4", "9", "13", "384", "0", "0", "248832", "[12, 1, 2, 3, 4, 5]", "7", "60", "2,4", "2", "4", "248832", "13", "384", "0", "0", "248832", "5,678", "5,678", "0", "null", "NaN", "0", "5", "5", "5", "5", "5", "1", "5,678", "5,678", "0", "null", "NaN", "0", "1", "5", "5", "5", "5", "1", "6,678", "4,678", "5,678", "5,678", "0,678", "1", "4", "5", "10", "2", "2", "5,678", "6,678", "4,678", "5,678", "5,678", "0,678", "1", "5,678", "5", "10", "2", "2", "5,678", "5,678", "5,678", "0", "null", "NaN", "0", "5", "5", "5", "5", "5", "1", "5,678", "5,678", "0", "null", "NaN", "0", "1", "5", "5", "5", "5", "1", "17,678", "-6,322", "68,136", "0,473", "5,678", "4", "9", "13", "20480", "0", "0", "1 122 909 247,194", "17,678", "-6,322", "68,136", "0,473", "5,678", "4", "1 122 909 247,194", "13", "20480", "0", "0", "1 122 909 247,194", "11,356", "0", "32,24", "1", "0", "5", "0", "5", "160", "0", "0", "19 156,732", "11,356", "0", "32,24", "1", "0", "5", "19 156,732", "5", "160", "0", "0", "19 156,732", "5,678", "5,678", "0", "null", "NaN", "0", "5", "5", "5", "5", "5", "1", "5,678", "5,678", "0", "null", "NaN", "0", "1", "5", "5", "5", "5", "1", "6,678", "4,678", "5,678", "5,678", "0,678", "1", "4", "5", "10", "2", "2", "5,678", "6,678", "4,678", "5,678", "5,678", "0,678", "1", "5,678", "5", "10", "2", "2", "5,678", "5,678lama", "1,678", "22,712", "1,419", "1,678", "4", "1", "5", "80", "0", "0", "1 039,397", "5,678lama", "1,678", "22,712", "1,419", "1,678", "4", "1 039,397", "5", "80", "0", "0", "1 039,397", "[5,678, 1, 2, 3, 4, 5]", "0,678", "28,39", "1,136", "0,678", "5", "0", "5", "160", "0", "0", "5 901,697", "[5,678, 1, 2, 3, 4, 5]", "0,678", "28,39", "1,136", "0,678", "5", "5 901,697", "5", "160", "0", "0", "5 901,697", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "12", "-12", "0", "0", "0", "0", "12", "12", "0", "0", "0", "0", "12", "-12", "0", "0", "0", "0", "0", "12", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "falselama", "-4", "0", "0", "0", "0", "4", "4", "0", "0", "0", "0", "falselama", "-4", "0", "0", "0", "0", "0", "4", "0", "0", "0", "0", "[false, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "[false, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "2", "0", "1", "1", "0", "1", "0", "1", "2", "0", "0", "1", "2", "0", "1", "1", "0", "1", "1", "1", "2", "0", "0", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "13", "-11", "12", "0,083", "1", "0", "13", "13", "4096", "0", "0", "1", "13", "-11", "12", "0,083", "1", "0", "1", "13", "4096", "0", "0", "1", "6,678", "-4,678", "5,678", "0,176", "1", "1", "4", "5", "32", "0", "0", "1", "6,678", "-4,678", "5,678", "0,176", "1", "1", "1", "5", "32", "0", "0", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "2", "0", "1", "1", "0", "1", "0", "1", "2", "0", "0", "1", "2", "0", "1", "1", "0", "1", "1", "1", "2", "0", "0", "1", "truelama", "-3", "4", "0,25", "1", "0", "5", "5", "16", "0", "0", "1", "truelama", "-3", "4", "0,25", "1", "0", "1", "5", "16", "0", "0", "1", "[true, 1, 2, 3, 4, 5]", "-4", "5", "0,2", "1", "1", "4", "5", "32", "0", "0", "1", "[true, 1, 2, 3, 4, 5]", "-4", "5", "0,2", "1", "1", "1", "5", "32", "0", "0", "1", "lamanull", "4", "0", "null", "null", "0", "4", "4", "4", "4", "4", "1", "lamanull", "4", "0", "null", "null", "0", "1", "4", "4", "4", "4", "1", "lamatrue", "3", "4", "4", "0", "0", "5", "5", "8", "2", "2", "4", "lamatrue", "3", "4", "4", "0", "0", "4", "5", "8", "2", "2", "4", "lamafalse", "4", "0", "null", "null", "0", "4", "4", "4", "4", "4", "1", "lamafalse", "4", "0", "null", "null", "0", "1", "4", "4", "4", "4", "1", "lama12", "-8", "48", "0,333", "4", "4", "8", "12", "16384", "0", "0", "16777216", "lama12", "-8", "48", "0,333", "4", "4", "16777216", "12", "16384", "0", "0", "16777216", "lama5,678", "-1,678", "22,712", "0,704", "4", "4", "1", "5", "128", "0", "0", "2 621,179", "lama5,678", "-1,678", "22,712", "0,704", "4", "4", "2 621,179", "5", "128", "0", "0", "2 621,179", "lamafalse", "4", "0", "null", "null", "0", "4", "4", "4", "4", "4", "1", "lamafalse", "4", "0", "null", "null", "0", "1", "4", "4", "4", "4", "1", "lamatrue", "3", "4", "4", "0", "0", "5", "5", "8", "2", "2", "4", "lamatrue", "3", "4", "4", "0", "0", "4", "5", "8", "2", "2", "4", "lamalama", "0", "16", "1", "0", "4", "0", "4", "64", "0", "0", "256", "lamalama", "0", "16", "1", "0", "4", "256", "4", "64", "0", "0", "256", "lama[1, 2, 3, 4, 5]", "-1", "20", "0,8", "4", "4", "1", "5", "128", "0", "0", "1024", "lama[1, 2, 3, 4, 5]", "-1", "20", "0,8", "4", "4", "1024", "5", "128", "0", "0", "1024", "[1, 2, 3, 4, 5, null]", "5", "0", "null", "null", "0", "5", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, null]", "5", "0", "null", "null", "0", "1", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, true]", "4", "5", "5", "0", "1", "4", "5", "10", "2", "2", "5", "[1, 2, 3, 4, 5, true]", "4", "5", "5", "0", "1", "5", "5", "10", "2", "2", "5", "[1, 2, 3, 4, 5, false]", "5", "0", "null", "null", "0", "5", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, false]", "5", "0", "null", "null", "0", "1", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, 12]", "-7", "60", "0,417", "5", "4", "9", "13", "20480", "0", "0", "244140625", "[1, 2, 3, 4, 5, 12]", "-7", "60", "0,417", "5", "4", "244140625", "13", "20480", "0", "0", "244140625", "[1, 2, 3, 4, 5, 5,678]", "-0,678", "28,39", "0,881", "5", "5", "0", "5", "160", "0", "0", "9 305,757", "[1, 2, 3, 4, 5, 5,678]", "-0,678", "28,39", "0,881", "5", "5", "9 305,757", "5", "160", "0", "0", "9 305,757", "[1, 2, 3, 4, 5, false]", "5", "0", "null", "null", "0", "5", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, false]", "5", "0", "null", "null", "0", "1", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, true]", "4", "5", "5", "0", "1", "4", "5", "10", "2", "2", "5", "[1, 2, 3, 4, 5, true]", "4", "5", "5", "0", "1", "5", "5", "10", "2", "2", "5", "[1, 2, 3, 4, 5]lama", "1", "20", "1,25", "1", "4", "1", "5", "80", "0", "0", "625", "[1, 2, 3, 4, 5]lama", "1", "20", "1,25", "1", "4", "625", "5", "80", "0", "0", "625", "[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]", "0", "25", "1", "0", "5", "0", "5", "160", "0", "0", "3125", "[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]", "0", "25", "1", "0", "5", "3125", "5", "160", "0", "0", "3125" + }; + List results = new ArrayList(); + int r = 0; + String result; + for (var value1 : values2) { + for (var value2 : values2) { + for (var operator : operators) { + String expected = actualResults[r++]; + var c = code_v10("var a = " + value1 + " return a " + operator + " " + value2); + if (expected.equals("error")) result = c.error(); + else result = c.equals(expected); + results.add("\"" + result + "\""); + } + for (var operator : assignmentOperators) { + String expected = actualResults[r++]; + var c = code_v10("var a = " + value1 + " a " + operator + " " + value2 + " return a"); + if (expected.equals("error")) result = c.error(); + else result = c.equals(expected); + results.add("\"" + result + "\""); + } + } + } + System.out.println(results); } } From eec42ce0f61d3d24509e95661b50b5fc35d72db2 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 223/319] [operator] Fix [null] == null --- src/main/java/leekscript/runner/values/ArrayLeekValue.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index fd101d3b..b7ae1ff7 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -266,6 +266,10 @@ public boolean getBoolean() { @Override public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { + // In LS1.0, [null] == null, not in 1.1+ + if (ai.getVersion() >= 11 && comp.getType() == NULL) { + return false; + } if (comp.getType() == ARRAY) { return mValues.equals(ai, comp.getArray().mValues); } else if (mValues.size() == 1) { // Si y'a un seul élément dans le tableau From 3be2841581b1111e6ccfb00ccedffa959e0658a4 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 224/319] [function] Remove ops from getOperations --- src/main/java/leekscript/runner/LeekFunctions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index eef77579..4a173707 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -1300,7 +1300,7 @@ public int[] parameters() { getOperations(0) { @Override public AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - ai.addOperations(1); + // ai.addOperations(1); return LeekValueManager.getLeekIntValue((int) ai.getOperations()); } }, From 84c76b63127f7f4167060e00b9ca045087ca9eb7 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 225/319] [function] Add ops --- src/main/java/leekscript/runner/LeekFunctions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 4a173707..eef77579 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -1300,7 +1300,7 @@ public int[] parameters() { getOperations(0) { @Override public AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - // ai.addOperations(1); + ai.addOperations(1); return LeekValueManager.getLeekIntValue((int) ai.getOperations()); } }, From 3b04d1d419640b4f203ec2a942917fe72fdcc468 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 226/319] [code] Improve code generation to LS --- .../java/leekscript/compiler/IACompiler.java | 12 ++++ .../compiler/bloc/AnonymousFunctionBlock.java | 4 +- .../compiler/bloc/ClassMethodBlock.java | 4 +- .../compiler/bloc/ConditionalBloc.java | 6 +- .../leekscript/compiler/bloc/ForBlock.java | 2 +- .../compiler/bloc/ForeachBlock.java | 2 +- .../compiler/bloc/ForeachKeyBlock.java | 2 +- .../compiler/bloc/MainLeekBlock.java | 4 +- .../expression/LeekAnonymousFunction.java | 2 +- .../compiler/expression/LeekArray.java | 6 +- .../compiler/expression/LeekExpression.java | 12 ++-- .../compiler/expression/LeekNumber.java | 14 ++++- .../compiler/expression/LeekParenthesis.java | 2 +- .../compiler/expression/LeekTernaire.java | 4 +- .../compiler/expression/Operators.java | 57 +++++++++++++++++-- .../ClassDeclarationInstruction.java | 47 ++++++++++++++- .../instruction/LeekBreakInstruction.java | 2 +- .../instruction/LeekContinueInstruction.java | 2 +- .../LeekExpressionInstruction.java | 2 +- .../LeekGlobalDeclarationInstruction.java | 6 +- .../instruction/LeekReturnInstruction.java | 2 +- .../LeekVariableDeclarationInstruction.java | 2 +- 22 files changed, 160 insertions(+), 36 deletions(-) diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index 0b394734..de9da8b7 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -95,6 +95,18 @@ public String compile(AIFile ai, String javaClassName, String AIClass) throws return writer.getJavaCode(); } + public String merge(AIFile ai) throws LeekCompilerException { + // System.out.println("Merge ai " + ai); + WordParser parser = new WordParser(ai, ai.getVersion()); + MainLeekBlock main = new MainLeekBlock(this, ai); + WordCompiler compiler = new WordCompiler(parser, main, ai, ai.getVersion()); + main.setWordCompiler(compiler); + compiler.readCode(); + String code = main.getCode(); + // System.out.println("Code = " + code); + return code; + } + public String getInformations() { return mInformations.toJSONString(); } diff --git a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java index e133a4ce..08d02486 100644 --- a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java @@ -60,13 +60,13 @@ public boolean hasParameter(String name) { @Override public String getCode() { - String str = "function anonymous" + mId + "("; + String str = "function("; for (int i = 0; i < mParameters.size(); i++) { if (i != 0) str += ", "; str += mParameters.get(i); } - return str + "){\n" + super.getCode() + "}\n"; + return str + ") {\n" + super.getCode() + "}\n"; } @Override diff --git a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java index cd65d18f..4ce96068 100644 --- a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java @@ -78,13 +78,13 @@ public LeekVariable getVariable(String variable, boolean includeClassMembers) { @Override public String getCode() { - String str = "function method" + mId + "("; + String str = "("; for (int i = 0; i < mParameters.size(); i++) { if (i != 0) str += ", "; str += mParameters.get(i); } - return str + "){\n" + super.getCode() + "}\n"; + return str + ") {\n" + super.getCode() + "}\n"; } @Override diff --git a/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java b/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java index 574e92af..3a1eefbc 100644 --- a/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java +++ b/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java @@ -35,9 +35,9 @@ public AbstractExpression getCondition() { @Override public String getCode() { String str = ""; - if(mParentCondition == null) str = "if(" + mCondition.getString() + "){"; - else if(mCondition != null) str = "elseif(" + mCondition.getString() + "){"; - else str = "else{"; + if(mParentCondition == null) str = "if (" + mCondition.getString() + ") {"; + else if(mCondition != null) str = "else if (" + mCondition.getString() + ") {"; + else str = "else {"; str += "\n" + super.getCode(); return str + "}"; } diff --git a/src/main/java/leekscript/compiler/bloc/ForBlock.java b/src/main/java/leekscript/compiler/bloc/ForBlock.java index 25ea1cea..16fb56bc 100644 --- a/src/main/java/leekscript/compiler/bloc/ForBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForBlock.java @@ -47,7 +47,7 @@ public void setIncrementation(AbstractExpression incrementation) { @Override public String getCode() { - return "for(" + mInitialisation.getCode() + ";" + mCondition.getString() + ";" + mIncrementation.getString() + "){\n" + super.getCode() + "}"; + return "for (" + mInitialisation.getCode() + mCondition.getString() + "; " + mIncrementation.getString() + ") {\n" + super.getCode() + "}"; } @Override diff --git a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java index 50e7a183..2f2299c4 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java @@ -39,7 +39,7 @@ public void setArray(AbstractExpression exp) { @Override public String getCode() { - return "for(" + mIterator + " in " + mArray.getString() + "){\n" + super.getCode() + "}"; + return "for (" + (mIsDeclaration ? "var " : "") + mIterator + " in " + mArray.getString() + ") {\n" + super.getCode() + "}"; } @Override diff --git a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java index d249dffa..f7f93da4 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java @@ -55,7 +55,7 @@ public void setArray(AbstractExpression exp) { @Override public String getCode() { - return "for(" + mIterator + " in " + mArray.getString() + "){\n" + super.getCode() + "}"; + return "for (" + (mIsKeyDeclaration ? "var " : "") + mKeyIterator + " : " + (mIsDeclaration ? "var " : "") + mIterator + " in " + mArray.getString() + ") {\n" + super.getCode() + "}"; } @Override diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 2ed31602..e364a79c 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -170,8 +170,8 @@ public String getCode() { for (LeekInstruction instruction : mFunctions) { str += instruction.getCode() + "\n"; } - for (LeekInstruction instruction : mAnonymousFunctions) { - str += instruction.getCode() + "\n"; + for (var clazz : mUserClasses.values()) { + str += clazz.getCode() + "\n"; } return str + super.getCode(); } diff --git a/src/main/java/leekscript/compiler/expression/LeekAnonymousFunction.java b/src/main/java/leekscript/compiler/expression/LeekAnonymousFunction.java index 4e406128..54d86331 100644 --- a/src/main/java/leekscript/compiler/expression/LeekAnonymousFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekAnonymousFunction.java @@ -26,7 +26,7 @@ public Type getType() { @Override public String getString() { - return "#Anonymous" + mBlock.getId(); + return mBlock.getCode(); } @Override diff --git a/src/main/java/leekscript/compiler/expression/LeekArray.java b/src/main/java/leekscript/compiler/expression/LeekArray.java index 3ca522a1..aab0b829 100644 --- a/src/main/java/leekscript/compiler/expression/LeekArray.java +++ b/src/main/java/leekscript/compiler/expression/LeekArray.java @@ -37,7 +37,11 @@ public Type getType() { public String getString() { String str = "["; for(int i = 0; i < mValues.size(); i++){ - if(i > 0) str += ", "; + if (i > 0) str += ", "; + if (mIsKeyVal) { + str += mValues.get(i).getString() + ": "; + i++; + } str += mValues.get(i).getString(); } return str + "]"; diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index 70a06fec..b3eeb650 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -407,22 +407,22 @@ else if (mExpression2.getNature() != EXPRESSION) { @Override public String getString() { - String retour = "("; + String retour = ""; if (Operators.isUnaryPrefix(mOperator)) { - ; - retour += Operators.getString(mOperator); + retour += Operators.getString(mOperator, mOperatorToken.getAI().getVersion()); + if (mOperator == Operators.NEW) retour += " "; retour += mExpression2 == null ? "null" : mExpression2.getString(); } else if (Operators.isUnarySuffix(mOperator)) { retour += mExpression2 == null ? "null" : mExpression2.getString(); - retour += Operators.getString(mOperator); + retour += Operators.getString(mOperator, mOperatorToken.getAI().getVersion()); } else { retour += mExpression1 == null ? "null" : mExpression1.getString(); - retour += " " + Operators.getString(mOperator) + " "; + retour += " " + Operators.getString(mOperator, mOperatorToken.getAI().getVersion()) + " "; retour += mExpression2 == null ? "null" : mExpression2.getString(); } - return retour + ")"; + return retour + ""; } @Override diff --git a/src/main/java/leekscript/compiler/expression/LeekNumber.java b/src/main/java/leekscript/compiler/expression/LeekNumber.java index ef4c690a..d7fe7d70 100644 --- a/src/main/java/leekscript/compiler/expression/LeekNumber.java +++ b/src/main/java/leekscript/compiler/expression/LeekNumber.java @@ -1,5 +1,9 @@ package leekscript.compiler.expression; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.Locale; + import leekscript.common.Type; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; @@ -27,12 +31,18 @@ public Type getType() { @Override public String getString() { - return String.valueOf(mValue); + if (type == Type.REAL) { + var formatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US); + formatter.setMaximumFractionDigits(15); + return formatter.format(mValue); + } else { + return String.valueOf((int) mValue); + } } @Override public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { - //Pour un nombre pas de soucis + // Pour un nombre pas de soucis return true; } diff --git a/src/main/java/leekscript/compiler/expression/LeekParenthesis.java b/src/main/java/leekscript/compiler/expression/LeekParenthesis.java index 61c4ab03..abb7f187 100644 --- a/src/main/java/leekscript/compiler/expression/LeekParenthesis.java +++ b/src/main/java/leekscript/compiler/expression/LeekParenthesis.java @@ -34,7 +34,7 @@ public AbstractExpression trim() { @Override public String getString() { - return mExpression.getString(); + return "(" + mExpression.getString() + ")"; } @Override diff --git a/src/main/java/leekscript/compiler/expression/LeekTernaire.java b/src/main/java/leekscript/compiler/expression/LeekTernaire.java index 2c17d98e..2f7eae2f 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTernaire.java +++ b/src/main/java/leekscript/compiler/expression/LeekTernaire.java @@ -59,13 +59,13 @@ public Type getType() { @Override public String getString() { - String retour = "("; + String retour = ""; retour += mCondition == null ? "null" : mCondition.getString(); retour += " ? "; retour += mExpression1 == null ? "null" : mExpression1.getString(); retour += " : "; retour += mExpression2 == null ? "null" : mExpression2.getString(); - return retour + ")"; + return retour; } @Override diff --git a/src/main/java/leekscript/compiler/expression/Operators.java b/src/main/java/leekscript/compiler/expression/Operators.java index 9fb5de6b..f65d5966 100644 --- a/src/main/java/leekscript/compiler/expression/Operators.java +++ b/src/main/java/leekscript/compiler/expression/Operators.java @@ -210,16 +210,25 @@ public static boolean isUnarySuffix(int operator) { return false; } - public static String getString(int operator) { - switch(operator) { + public static String getString(int operator, int version) { + switch (operator) { case ADD: return "+"; + case ADDASSIGN: + return "+="; case MINUS: + case UNARY_MINUS: return "-"; + case MINUSASSIGN: + return "-="; case MULTIPLIE: return "*"; + case MULTIPLIEASSIGN: + return "*="; case DIVIDE: return "/"; + case DIVIDEASSIGN: + return "/="; case MODULUS: return "%"; case ASSIGN: @@ -228,22 +237,62 @@ public static String getString(int operator) { return "&&"; case OR: return "||"; + case LESS: + return "<"; + case LESSEQUALS: + return "<="; + case MORE: + return ">"; + case MOREEQUALS: + return ">="; case EQUALS: return "=="; + case EQUALS_EQUALS: + return "==="; case NOTEQUALS: return "!="; + case NOT_EQUALS_EQUALS: + return "!=="; case NOT: return "!"; + case BITAND: + return "&"; + case BITAND_ASSIGN: + return "&="; + case BITOR: + return "|"; + case BITOR_ASSIGN: + return "|="; + case BITXOR: + return "^"; + case BITXOR_ASSIGN: + return "^="; + case SHIFT_LEFT: + return "<<"; + case SHIFT_LEFT_ASSIGN: + return "<<="; + case SHIFT_RIGHT: + return ">>"; + case SHIFT_RIGHT_ASSIGN: + return ">>="; + case SHIFT_UNSIGNED_RIGHT: + return ">>>"; + case SHIFT_UNSIGNED_RIGHT_ASSIGN: + return ">>>="; case INCREMENT: + case PRE_INCREMENT: return "++"; case DECREMENT: + case PRE_DECREMENT: return "--"; case POWER: - return "^"; + return "**"; case POWERASSIGN: - return "^="; + return version == 10 ? "^=" : "**="; case NEW: return "new"; + case BITNOT: + return "~"; case INSTANCEOF: return "instanceof"; } diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 585578cd..38a976d3 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -62,7 +62,52 @@ public String getName() { @Override public String getCode() { - return "class"; + String r = "class " + token.getWord(); + if (parentToken != null) { + r += " extends " + parentToken.getWord(); + } + r += " {\n"; + + for (Entry field : staticFields.entrySet()) { + r += "\tstatic " + field.getKey(); + if (field.getValue() != null) { + r += " = " + field.getValue().getString(); + } + r += "\n"; + } + r += "\n"; + + for (var method : staticMethods.entrySet()) { + for (var version : method.getValue().entrySet()) { + r += "\tstatic " + method.getKey() + version.getValue().getCode(); + } + r += "\n"; + } + r += "\n"; + + for (Entry field : fields.entrySet()) { + r += "\t" + field.getKey(); + if (field.getValue() != null) { + r += " = " + field.getValue().getString(); + } + r += "\n"; + } + r += "\n"; + + for (var constructor : constructors.entrySet()) { + r += "\tconstructor" + constructor.getValue().getCode(); + } + r += "\n"; + + for (var method : methods.entrySet()) { + for (var version : method.getValue().entrySet()) { + r += "\t" + method.getKey() + version.getValue().getCode(); + } + r += "\n"; + } + + r += "}"; + return r; } @Override diff --git a/src/main/java/leekscript/compiler/instruction/LeekBreakInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekBreakInstruction.java index 14e5fcb5..331a0d30 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekBreakInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekBreakInstruction.java @@ -19,7 +19,7 @@ public LeekBreakInstruction(int count, int line, AIFile ai) { @Override public String getCode() { - return "break"; + return "break;"; } @Override diff --git a/src/main/java/leekscript/compiler/instruction/LeekContinueInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekContinueInstruction.java index 4fa4c728..f9b785a8 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekContinueInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekContinueInstruction.java @@ -19,7 +19,7 @@ public LeekContinueInstruction(int count, int line, AIFile ai) { @Override public String getCode() { - return "continue"; + return "continue;"; } @Override diff --git a/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java index 6d7879e1..21dcde53 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java @@ -24,7 +24,7 @@ public LeekExpressionInstruction(AbstractExpression expression, int line, AIFile @Override public String getCode() { - return mExpression.getString(); + return mExpression.getString() + ";"; } @Override diff --git a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java index 1430dea7..3099fa75 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java @@ -32,7 +32,11 @@ public String getName() { @Override public String getCode() { - return token.getWord() + " = " + mValue.getString(); + if (mValue != null) { + return "global " + token.getWord() + " = " + mValue.getString() + ";"; + } else { + return "global " + token.getWord() + ";"; + } } @Override diff --git a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java index d5143e81..1bbe1d06 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java @@ -20,7 +20,7 @@ public LeekReturnInstruction(int count, AbstractExpression exp, int line, AIFile @Override public String getCode() { - return "return " + (mExpression == null ? "null" : mExpression.getString()); + return "return " + (mExpression == null ? "null" : mExpression.getString()) + ";"; } @Override diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index 7753a45e..e8218f4f 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -56,7 +56,7 @@ public boolean isWrapper() { @Override public String getCode() { if (mValue == null) return "var " + token.getWord(); - return "var " + token.getWord() + " = " + mValue.getString(); + return "var " + token.getWord() + " = " + mValue.getString() + ";"; } @Override From 24591ed77c809158f0e4d1f7787de46a13f079b9 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 227/319] [resolver] Resolve on file system --- .../java/leekscript/compiler/LeekScript.java | 15 ++++++- .../compiler/resolver/FileSystemResolver.java | 6 +-- .../compiler/resolver/ResourceContext.java | 25 +++++++++++ .../compiler/resolver/ResourceResolver.java | 45 +++++++++++++++++++ 4 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 src/main/java/leekscript/compiler/resolver/ResourceContext.java create mode 100644 src/main/java/leekscript/compiler/resolver/ResourceResolver.java diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 81b3d95f..52396038 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -24,6 +24,8 @@ import leekscript.compiler.resolver.FileSystemResolver; import leekscript.compiler.resolver.Resolver; import leekscript.compiler.resolver.ResolverContext; +import leekscript.compiler.resolver.ResourceContext; +import leekscript.compiler.resolver.ResourceResolver; import leekscript.runner.AI; public class LeekScript { @@ -31,7 +33,8 @@ public class LeekScript { private final static String IA_PATH = "ai/"; private static long id = 1; - private static Resolver defaultResolver = new FileSystemResolver(); + private static Resolver defaultResolver = new ResourceResolver(); + private static Resolver fileSystemResolver = new FileSystemResolver(); private static Resolver customResolver = null; private static String classpath; private static List arguments = new ArrayList<>(); @@ -100,6 +103,12 @@ public static AI compileSnippet(String snippet, String AIClass, int version) thr return compile(ai, AIClass, false); } + public static String mergeFile(String filepath, ResolverContext context) throws LeekScriptException, LeekCompilerException, IOException { + AIFile ai = getResolver().resolve(filepath, context); + + return new IACompiler().merge(ai); + } + public static Object runScript(String script, boolean nocache) throws Exception { return LeekScript.compileSnippet(script, "AI").runIA(); } @@ -240,5 +249,9 @@ public static void throwException(String error) throws LeekScriptException { throw new LeekScriptException(LeekScriptException.CANT_COMPILE, error); } + public static Resolver getFileSystemResolver() { + return fileSystemResolver; + } + } \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index 80ebef82..a248247e 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -1,5 +1,6 @@ package leekscript.compiler.resolver; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -21,7 +22,7 @@ public AIFile resolve(String path, ResolverContext basecontex try { Path resolvedPath = context.getFolder().toPath().resolve(path).normalize(); - var is = getClass().getClassLoader().getResourceAsStream(resolvedPath.toString()); + var is = new FileInputStream(resolvedPath.toFile()); String code = new String(is.readAllBytes(), StandardCharsets.UTF_8); Path parent = resolvedPath.getParent(); @@ -33,8 +34,7 @@ public AIFile resolve(String path, ResolverContext basecontex return new AIFile(path, code, timestamp, 11, newContext, resolvedPath.toString().hashCode() & 0xfffffff); - } catch (IOException e) { - e.printStackTrace(); + } catch (Exception e) { throw new FileNotFoundException(); } } diff --git a/src/main/java/leekscript/compiler/resolver/ResourceContext.java b/src/main/java/leekscript/compiler/resolver/ResourceContext.java new file mode 100644 index 00000000..596fff06 --- /dev/null +++ b/src/main/java/leekscript/compiler/resolver/ResourceContext.java @@ -0,0 +1,25 @@ +package leekscript.compiler.resolver; + +import java.io.File; + +public class ResourceContext extends ResolverContext { + + private File folder; + + public ResourceContext(File folder) { + this.folder = folder; + } + + @Override + public String toString() { + return folder.getPath(); + } + + public File getFolder() { + return folder; + } + + public void setFolder(File folder) { + this.folder = folder; + } +} diff --git a/src/main/java/leekscript/compiler/resolver/ResourceResolver.java b/src/main/java/leekscript/compiler/resolver/ResourceResolver.java new file mode 100644 index 00000000..7667bd1e --- /dev/null +++ b/src/main/java/leekscript/compiler/resolver/ResourceResolver.java @@ -0,0 +1,45 @@ +package leekscript.compiler.resolver; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; + +import leekscript.compiler.AIFile; + + +public class ResourceResolver implements Resolver { + + @Override + public AIFile resolve(String path, ResolverContext basecontext) throws FileNotFoundException { + + ResourceContext context = (ResourceContext) basecontext; + if (context == null) { + context = new ResourceContext(Paths.get(".").toFile()); + } + try { + Path resolvedPath = context.getFolder().toPath().resolve(path).normalize(); + + var is = getClass().getClassLoader().getResourceAsStream(resolvedPath.toString()); + String code = new String(is.readAllBytes(), StandardCharsets.UTF_8); + + Path parent = resolvedPath.getParent(); + if (parent == null) parent = Paths.get("."); + + var newContext = new ResourceContext(parent.toFile()); + + long timestamp = resolvedPath.toFile().lastModified(); + + return new AIFile(path, code, timestamp, 11, newContext, resolvedPath.toString().hashCode() & 0xfffffff); + + } catch (Exception e) { + throw new FileNotFoundException(); + } + } + + public ResolverContext createContext(int parameter1, int parameter2, int parameter3) { + return new FileSystemContext(Paths.get(".").toFile()); + } +} From a8c95e7403de278e7f34276dfb49876d1324a68e Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 228/319] [test] Add tests --- src/test/java/test/TestFunction.java | 2 ++ src/test/java/test/TestOperators.java | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index e61ac0be..6115027f 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -75,6 +75,8 @@ public void run() { code("function t() { var a = [1, 2, 3] return a } var x = t() var f = function() { return x } return x").equals("[1, 2, 3]"); code("push = 1 return push").equals("1"); code_v10("function LamaSwag() {} @LamaSwag();").equals("null"); + code("function f() { distance = 12 } function distance() { return 'salut' } return distance()").equals("salut"); + code("getOperations()").equals("null"); section("Modify argument"); code("function test(x) { x += 10 return x } return test(5)").equals("15"); diff --git a/src/test/java/test/TestOperators.java b/src/test/java/test/TestOperators.java index 9ca9d70d..d7e49330 100644 --- a/src/test/java/test/TestOperators.java +++ b/src/test/java/test/TestOperators.java @@ -137,6 +137,12 @@ public void run() throws Exception { } code("return 1 === 1.0").equals("true"); code("return 12 === 12.0").equals("true"); + code("return null == [null]").equals("false"); + code("return null != [null]").equals("true"); + code_v10("return [null] == null").equals("true"); // Bug in LS1.0 + code_v11("return [null] == null").equals("false"); // Fixed in 1.1 + code_v10("return [null] != null").equals("false"); // Bug in LS1.0 + code_v11("return [null] != null").equals("true"); // Fixed in 1.1 code("var a = 1; var result = -10 + (1- (a-1)); return result").equals("-9"); code("var a = 1; var result = 0; result = -10 + (1- (a-1)); return result").equals("-9"); From f16d361e3c6d08db2fb2458942aa0d836f3996e7 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 229/319] [fileresolver] Add version --- .../java/leekscript/compiler/resolver/FileSystemResolver.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index a248247e..a3f3159f 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -31,8 +31,9 @@ public AIFile resolve(String path, ResolverContext basecontex FileSystemContext newContext = new FileSystemContext(parent.toFile()); long timestamp = resolvedPath.toFile().lastModified(); + int version = resolvedPath.toFile().getName().contains("v10") ? 10 : 11; - return new AIFile(path, code, timestamp, 11, newContext, resolvedPath.toString().hashCode() & 0xfffffff); + return new AIFile(path, code, timestamp, version, newContext, resolvedPath.toString().hashCode() & 0xfffffff); } catch (Exception e) { throw new FileNotFoundException(); From 2588a4e4985099c193f8ff75539a23caa68ddeeb Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 230/319] [object] Implement access levels --- .../instruction => common}/AccessLevel.java | 2 +- src/main/java/leekscript/common/Error.java | 10 +- .../java/leekscript/compiler/JavaWriter.java | 3 + .../leekscript/compiler/WordCompiler.java | 22 +-- .../compiler/bloc/MainLeekBlock.java | 1 + .../expression/LeekExpressionFunction.java | 24 ++- .../compiler/expression/LeekObjectAccess.java | 4 +- .../compiler/expression/LeekVariable.java | 4 +- .../ClassDeclarationInstruction.java | 133 ++++++++++------ .../leekscript/runner/LeekValueManager.java | 11 ++ .../runner/values/AbstractLeekValue.java | 15 +- .../runner/values/ClassLeekValue.java | 145 ++++++++++++++---- .../runner/values/FunctionLeekValue.java | 6 +- .../runner/values/ObjectLeekValue.java | 67 +++++--- .../runner/values/ObjectVariableValue.java | 20 +++ .../runner/values/VariableLeekValue.java | 13 +- 16 files changed, 354 insertions(+), 126 deletions(-) rename src/main/java/leekscript/{compiler/instruction => common}/AccessLevel.java (88%) create mode 100644 src/main/java/leekscript/runner/values/ObjectVariableValue.java diff --git a/src/main/java/leekscript/compiler/instruction/AccessLevel.java b/src/main/java/leekscript/common/AccessLevel.java similarity index 88% rename from src/main/java/leekscript/compiler/instruction/AccessLevel.java rename to src/main/java/leekscript/common/AccessLevel.java index 2243b252..51b38022 100644 --- a/src/main/java/leekscript/compiler/instruction/AccessLevel.java +++ b/src/main/java/leekscript/common/AccessLevel.java @@ -1,4 +1,4 @@ -package leekscript.compiler.instruction; +package leekscript.common; public enum AccessLevel { PUBLIC, PROTECTED, PRIVATE; diff --git a/src/main/java/leekscript/common/Error.java b/src/main/java/leekscript/common/Error.java index 499519e9..422a0a9d 100644 --- a/src/main/java/leekscript/common/Error.java +++ b/src/main/java/leekscript/common/Error.java @@ -78,5 +78,13 @@ public enum Error { INSTANCEOF_MUST_BE_CLASS, // 74 NOT_ITERABLE, // 75 STACKOVERFLOW, // 76 - INVALID_OPERATOR // 77 + INVALID_OPERATOR, // 77 + PRIVATE_FIELD, // 78 + PROTECTED_FIELD, // 79 + PRIVATE_STATIC_FIELD, // 80 + PROTECTED_STATIC_FIELD, // 81 + PRIVATE_METHOD, // 82 + PROTECTED_METHOD, // 83 + PRIVATE_STATIC_METHOD, // 84 + PROTECTED_STATIC_METHOD, // 85 } \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/JavaWriter.java b/src/main/java/leekscript/compiler/JavaWriter.java index 51579c91..bfea8ba2 100644 --- a/src/main/java/leekscript/compiler/JavaWriter.java +++ b/src/main/java/leekscript/compiler/JavaWriter.java @@ -7,6 +7,8 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; +import leekscript.compiler.bloc.AbstractLeekBlock; + public class JavaWriter { private final StringBuilder mCode; private int mLine; @@ -15,6 +17,7 @@ public class JavaWriter { private final ArrayList> mFilesList = new ArrayList<>(); private final boolean mWithDebug; private final String className; + public AbstractLeekBlock currentBlock = null; private class Line { private final int mJavaLine; diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 3cf02fdf..61c433ba 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -4,6 +4,7 @@ import java.util.Set; import java.util.TreeSet; +import leekscript.common.AccessLevel; import leekscript.common.Error; import leekscript.common.Type; import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; @@ -33,7 +34,6 @@ import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.Operators; import leekscript.compiler.expression.LeekVariable.VariableType; -import leekscript.compiler.instruction.AccessLevel; import leekscript.compiler.instruction.BlankInstruction; import leekscript.compiler.instruction.ClassDeclarationInstruction; import leekscript.compiler.instruction.LeekBreakInstruction; @@ -744,8 +744,8 @@ public void classAccessLevelMember(ClassDeclarationInstruction classDeclaration, IAWord word2 = mCompiler.getWord(); if (word2.getType() == WordParser.T_PAR_LEFT) { // Méthode - ClassMethodBlock method = classMethod(classDeclaration, accessLevel, name.getWord(), false); - classDeclaration.addMethod(this, name, method); + ClassMethodBlock method = classMethod(classDeclaration, name.getWord(), false); + classDeclaration.addMethod(this, name, method, accessLevel); } else { // Field AbstractExpression expr = null; @@ -753,7 +753,7 @@ public void classAccessLevelMember(ClassDeclarationInstruction classDeclaration, mCompiler.skipWord(); expr = readExpression(); } - classDeclaration.addField(this, name, expr); + classDeclaration.addField(this, name, expr, accessLevel); if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) mCompiler.skipWord(); } @@ -768,24 +768,24 @@ public void classStaticMember(ClassDeclarationInstruction classDeclaration, Acce expr = readExpression(); } else if (mCompiler.getWord().getType() == WordParser.T_PAR_LEFT) { // Méthode - ClassMethodBlock method = classMethod(classDeclaration, accessLevel, name.getWord(), true); - classDeclaration.addStaticMethod(this, name, method); + ClassMethodBlock method = classMethod(classDeclaration, name.getWord(), true); + classDeclaration.addStaticMethod(this, name, method, accessLevel); if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) mCompiler.skipWord(); return; } - classDeclaration.addStaticField(name, expr); + classDeclaration.addStaticField(name, expr, accessLevel); if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) mCompiler.skipWord(); } public void classConstructor(ClassDeclarationInstruction classDeclaration, AccessLevel accessLevel) throws LeekCompilerException { - ClassMethodBlock constructor = classMethod(classDeclaration, accessLevel, "constructor", false); - classDeclaration.addConstructor(constructor); + ClassMethodBlock constructor = classMethod(classDeclaration, "constructor", false); + classDeclaration.addConstructor(constructor, accessLevel); } - public ClassMethodBlock classMethod(ClassDeclarationInstruction classDeclaration, AccessLevel accessLevel, String name, boolean isStatic) throws LeekCompilerException { + public ClassMethodBlock classMethod(ClassDeclarationInstruction classDeclaration, String name, boolean isStatic) throws LeekCompilerException { ClassMethodBlock method = new ClassMethodBlock(classDeclaration, isStatic, mCurentBlock, mMain, mLine, mAI); @@ -994,7 +994,7 @@ else if (getVersion() >= 11 && word.getWord().equalsIgnoreCase("new")) { // au début de l'expression AbstractExpression exp = readExpression(); - if (mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { + if (mCompiler.haveWords() && mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { throw new LeekCompilerException(mCompiler.getWord(), Error.CLOSING_PARENTHESIS_EXPECTED); } retour.addExpression(new LeekParenthesis(exp)); diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index e364a79c..400305ab 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -181,6 +181,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { writer.addLine("import leekscript.runner.*;"); writer.addLine("import leekscript.runner.values.*;"); + writer.addLine("import leekscript.common.*;"); writer.addLine(); writer.addLine("public class " + className + " extends " + AIClass + " {"); diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 0e3d6a89..7a517bab 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -7,6 +7,7 @@ import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; +import leekscript.compiler.bloc.ClassMethodBlock; import leekscript.compiler.bloc.FunctionBlock; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.LeekVariable.VariableType; @@ -74,10 +75,25 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { if (mExpression instanceof LeekObjectAccess) { var object = ((LeekObjectAccess) mExpression).getObject(); if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.SUPER) { - writer.addCode("u_this.callSuperMethod(mUAI, \"" + ((LeekObjectAccess) mExpression).getField() + "_" + mParameters.size() + "\""); + writer.addCode("u_this.callSuperMethod(mUAI, u_class, \"" + ((LeekObjectAccess) mExpression).getField() + "_" + mParameters.size() + "\""); } else { + var fromClass = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; object.writeJavaCode(mainblock, writer); - writer.addCode(".callMethod(mUAI, \"" + ((LeekObjectAccess) mExpression).getField() + "_" + mParameters.size() + "\""); + writer.addCode(".callMethod(mUAI, \"" + ((LeekObjectAccess) mExpression).getField() + "_" + mParameters.size() + "\", " + fromClass); + } + } else if (mExpression instanceof LeekTabularValue) { + var object = ((LeekTabularValue) mExpression).getTabular(); + if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.SUPER) { + writer.addCode("u_this.callSuperMethod(mUAI, u_class, "); + ((LeekTabularValue) mExpression).getCase().writeJavaCode(mainblock, writer); + writer.addCode(".getString(mUAI) + \"_" + mParameters.size() + "\""); + } else { + writer.addCode("LeekValueManager.executeArrayAccess(mUAI, "); + object.writeJavaCode(mainblock, writer); + writer.addCode(", "); + ((LeekTabularValue) mExpression).getCase().writeJavaCode(mainblock, writer); + writer.addCode(", "); + writer.addCode(writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"); } } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.SUPER) { // Super constructor @@ -85,9 +101,9 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("user_" + variable.getClassDeclaration().getParent().getName()); writer.addCode(".callConstructor(mUAI, u_this"); } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.METHOD) { - writer.addCode("u_this.callMethod(mUAI, \"" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size() + "\""); + writer.addCode("u_this.callMethod(mUAI, \"" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size() + "\", u_class"); } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.STATIC_METHOD) { - writer.addCode("u_class.callMethod(mUAI, \"" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size() + "\""); + writer.addCode("u_class.callMethod(mUAI, \"" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size() + "\", u_class"); } else if (mExpression instanceof LeekVariable && mainblock.isRedefinedFunction(((LeekVariable) mExpression).getName())) { writer.addCode("rfunction_" + ((LeekVariable) mExpression).getName()); writer.addCode(".executeFunction(mUAI"); diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index bbaee47d..627b6237 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -5,6 +5,7 @@ import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; +import leekscript.compiler.bloc.ClassMethodBlock; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.LeekVariable.VariableType; import leekscript.common.Error; @@ -42,7 +43,8 @@ public AbstractExpression getObject() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { object.writeJavaCode(mainblock, writer); - writer.addCode(".getField(mUAI, \"" + field.getWord() + "\")"); + String fromClass = (writer.currentBlock instanceof ClassMethodBlock) ? "u_class" : "null"; + writer.addCode(".getField(mUAI, \"" + field.getWord() + "\", " + fromClass + ")"); } @Override diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index b542019e..d82a44d5 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -95,9 +95,9 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } else if (type == VariableType.SUPER) { writer.addCode("user_" + classDeclaration.getParent().getName()); } else if (type == VariableType.FIELD) { - writer.addCode("u_this.getField(mUAI, \"" + token.getWord() + "\")"); + writer.addCode("u_this.getField(mUAI, \"" + token.getWord() + "\", u_class)"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.getField(mUAI, \"" + token.getWord() + "\")"); + writer.addCode("u_class.getField(mUAI, \"" + token.getWord() + "\", u_class)"); } else if (type == VariableType.METHOD) { writer.addCode("###"); } else if (mainblock.isRedefinedFunction(token.getWord())) { diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 38a976d3..19cb2c30 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -15,31 +15,54 @@ import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.common.AccessLevel; import leekscript.common.Error; public class ClassDeclarationInstruction implements LeekInstruction { + public static class ClassDeclarationField { + + AbstractExpression expression; + AccessLevel level; + + public ClassDeclarationField(AbstractExpression expr, AccessLevel level) { + this.expression = expr; + this.level = level; + } + } + + public static class ClassDeclarationMethod { + + ClassMethodBlock block; + AccessLevel level; + + public ClassDeclarationMethod(ClassMethodBlock block, AccessLevel level) { + this.block = block; + this.level = level; + } + } + private final IAWord token; private IAWord parentToken; private ClassDeclarationInstruction parent; - private HashMap fields = new HashMap<>(); - private HashMap staticFields = new HashMap<>(); + private HashMap fields = new HashMap<>(); + private HashMap staticFields = new HashMap<>(); private HashMap fieldVariables = new HashMap<>(); private HashMap staticFieldVariables = new HashMap<>(); private HashMap methodVariables = new HashMap<>(); private HashMap staticMethodVariables = new HashMap<>(); - private HashMap constructors = new HashMap<>(); - private HashMap> methods = new HashMap<>(); - private HashMap> staticMethods = new HashMap<>(); + private HashMap constructors = new HashMap<>(); + private HashMap> methods = new HashMap<>(); + private HashMap> staticMethods = new HashMap<>(); public ClassDeclarationInstruction(IAWord token, int line, AIFile ai) { this.token = token; } - public HashMap getFields() { + public HashMap getFields() { return fields; } - public HashMap getStaticFields() { + public HashMap getStaticFields() { return staticFields; } @@ -68,10 +91,10 @@ public String getCode() { } r += " {\n"; - for (Entry field : staticFields.entrySet()) { - r += "\tstatic " + field.getKey(); + for (Entry field : staticFields.entrySet()) { + r += "\tstatic " + field.getValue().level.toString().toLowerCase() + " " + field.getKey(); if (field.getValue() != null) { - r += " = " + field.getValue().getString(); + r += " = " + field.getValue().expression.getString(); } r += "\n"; } @@ -79,29 +102,29 @@ public String getCode() { for (var method : staticMethods.entrySet()) { for (var version : method.getValue().entrySet()) { - r += "\tstatic " + method.getKey() + version.getValue().getCode(); + r += "\tstatic " + method.getKey() + version.getValue().block.getCode(); } r += "\n"; } r += "\n"; - for (Entry field : fields.entrySet()) { - r += "\t" + field.getKey(); + for (Entry field : fields.entrySet()) { + r += "\t" + field.getValue().level.toString().toLowerCase() + " " + field.getKey(); if (field.getValue() != null) { - r += " = " + field.getValue().getString(); + r += " = " + field.getValue().expression.getString(); } r += "\n"; } r += "\n"; for (var constructor : constructors.entrySet()) { - r += "\tconstructor" + constructor.getValue().getCode(); + r += "\tconstructor" + constructor.getValue().level.toString().toLowerCase() + " " + constructor.getValue().block.getCode(); } r += "\n"; for (var method : methods.entrySet()) { for (var version : method.getValue().entrySet()) { - r += "\t" + method.getKey() + version.getValue().getCode(); + r += "\t" + version.getValue().level.toString().toLowerCase() + " " + method.getKey() + version.getValue().block.getCode(); } r += "\n"; } @@ -128,11 +151,11 @@ public boolean hasConstructor(int param_count) { return constructors.containsKey(param_count); } - public void addConstructor(ClassMethodBlock block) { - constructors.put(block.countParameters(), block); + public void addConstructor(ClassMethodBlock block, AccessLevel level) { + constructors.put(block.countParameters(), new ClassDeclarationMethod(block, level)); } - public void addMethod(WordCompiler compiler, IAWord token, ClassMethodBlock method) { + public void addMethod(WordCompiler compiler, IAWord token, ClassMethodBlock method, AccessLevel level) { // On regarde si il n'y a pas déjà une méthode statique du même nom if (staticMethods.containsKey(token.getWord())) { compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, Error.DUPLICATED_METHOD)); @@ -141,7 +164,7 @@ public void addMethod(WordCompiler compiler, IAWord token, ClassMethodBlock meth methods.put(token.getWord(), new HashMap<>()); methodVariables.put(token.getWord(), new LeekVariable(token, VariableType.METHOD)); } - methods.get(token.getWord()).put(method.countParameters(), method); + methods.get(token.getWord()).put(method.countParameters(), new ClassDeclarationMethod(method, level)); } public boolean hasMethod(String name, int paramCount) { @@ -151,7 +174,7 @@ public boolean hasMethod(String name, int paramCount) { return methods.containsKey(name + "_" + paramCount); } - public void addStaticMethod(WordCompiler compiler, IAWord token, ClassMethodBlock method) { + public void addStaticMethod(WordCompiler compiler, IAWord token, ClassMethodBlock method, AccessLevel level) { // On regarde si il n'y a pas déjà une méthode du même nom if (methods.containsKey(token.getWord())) { compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, Error.DUPLICATED_METHOD)); @@ -160,27 +183,33 @@ public void addStaticMethod(WordCompiler compiler, IAWord token, ClassMethodBloc staticMethods.put(token.getWord(), new HashMap<>()); staticMethodVariables.put(token.getWord(), new LeekVariable(token, VariableType.STATIC_METHOD)); } - staticMethods.get(token.getWord()).put(method.countParameters(), method); + staticMethods.get(token.getWord()).put(method.countParameters(), new ClassDeclarationMethod(method, level)); } public boolean hasStaticMethod(String name, int paramCount) { - return staticMethods.containsKey(name) && staticMethods.get(name).containsKey(paramCount); + if (staticMethods.containsKey(name) && staticMethods.get(name).containsKey(paramCount)) { + return true; + } + if (parent != null) { + return parent.hasStaticMethod(name, paramCount); + } + return false; } - public void addField(WordCompiler compiler, IAWord word, AbstractExpression expr) throws LeekCompilerException { + public void addField(WordCompiler compiler, IAWord word, AbstractExpression expr, AccessLevel level) throws LeekCompilerException { if (fields.containsKey(word.getWord()) || staticFields.containsKey(word.getWord())) { compiler.addError(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.FIELD_ALREADY_EXISTS)); return; } - fields.put(word.getWord(), expr); + fields.put(word.getWord(), new ClassDeclarationField(expr, level)); fieldVariables.put(word.getWord(), new LeekVariable(word, VariableType.FIELD)); } - public void addStaticField(IAWord word, AbstractExpression expr) throws LeekCompilerException { + public void addStaticField(IAWord word, AbstractExpression expr, AccessLevel level) throws LeekCompilerException { if (staticFields.containsKey(word.getWord()) || fields.containsKey(word.getWord())) { throw new LeekCompilerException(word, Error.FIELD_ALREADY_EXISTS); } - staticFields.put(word.getWord(), expr); + staticFields.put(word.getWord(), new ClassDeclarationField(expr, level)); staticFieldVariables.put(word.getWord(), new LeekVariable(word, VariableType.STATIC_FIELD)); } @@ -216,16 +245,16 @@ public void analyze(WordCompiler compiler) { } for (var constructor : constructors.values()) { - constructor.analyze(compiler); + constructor.block.analyze(compiler); } for (var method : methods.values()) { for (var version : method.values()) { - version.analyze(compiler); + version.block.analyze(compiler); } } for (var method : staticMethods.values()) { for (var version : method.values()) { - version.analyze(compiler); + version.block.analyze(compiler); } } compiler.setCurrentClass(null); @@ -245,59 +274,62 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine(className + ".setParent(user_" + parent.getName() + ");"); } - for (Entry> method : staticMethods.entrySet()) { - for (Entry version : method.getValue().entrySet()) { + for (Entry> method : staticMethods.entrySet()) { + for (Entry version : method.getValue().entrySet()) { String methodName = className + "_" + method.getKey() + "_" + version.getKey(); writer.addCode("final LeekAnonymousFunction " + methodName + " = new LeekAnonymousFunction() {"); writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue u_this, AbstractLeekValue... values) throws LeekRunException {"); - writer.addLine("final var u_class = " + className + ";", version.getValue().getLine(), version.getValue().getFile()); + writer.addLine("final var u_class = " + className + ";", version.getValue().block.getLine(), version.getValue().block.getFile()); if (parent != null) { writer.addLine("final var u_super = user_" + parent.token.getWord() + ";"); } - version.getValue().writeJavaCode(mainblock, writer); + version.getValue().block.writeJavaCode(mainblock, writer); writer.addLine("}};"); } } - for (Entry> method : methods.entrySet()) { - for (Entry version : method.getValue().entrySet()) { + for (Entry> method : methods.entrySet()) { + for (Entry version : method.getValue().entrySet()) { + writer.currentBlock = version.getValue().block; String methodName = className + "_" + method.getKey() + "_" + version.getKey(); writer.addCode("final LeekAnonymousFunction " + methodName + " = new LeekAnonymousFunction() {"); writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue u_this, AbstractLeekValue... values) throws LeekRunException {"); - writer.addLine("final var u_class = " + className + ";", version.getValue().getLine(), version.getValue().getFile()); + writer.addLine("final var u_class = " + className + ";", version.getValue().block.getLine(), version.getValue().block.getFile()); if (parent != null) { writer.addLine("final var u_super = user_" + parent.token.getWord() + ";"); } writer.addCounter(1); - version.getValue().writeJavaCode(mainblock, writer); + version.getValue().block.writeJavaCode(mainblock, writer); writer.addLine("}};"); + writer.currentBlock = null; } } - for (Entry field : staticFields.entrySet()) { + for (Entry field : staticFields.entrySet()) { writer.addCode(className); writer.addCode(".addStaticField(mUAI, \"" + field.getKey() + "\", "); if (field.getValue() != null) { - field.getValue().writeJavaCode(mainblock, writer); + field.getValue().expression.writeJavaCode(mainblock, writer); } else { writer.addCode("LeekValueManager.NULL"); } + writer.addCode(", AccessLevel." + field.getValue().level); writer.addLine(");"); } writeFields(mainblock, writer, className); - for (Entry> method : staticMethods.entrySet()) { - for (Entry version : method.getValue().entrySet()) { + for (Entry> method : staticMethods.entrySet()) { + for (Entry version : method.getValue().entrySet()) { String methodName = className + "_" + method.getKey() + "_" + version.getKey(); writer.addCode(className); - writer.addLine(".addStaticMethod(\"" + method.getKey() + "\", " + version.getKey() + ", " + methodName + ");"); + writer.addLine(".addStaticMethod(\"" + method.getKey() + "\", " + version.getKey() + ", " + methodName + ", AccessLevel." + version.getValue().level + ");"); } writer.addCode(className); writer.addLine(".addGenericStaticMethod(\"" + method.getKey() + "\");"); } - for (Entry construct : constructors.entrySet()) { + for (Entry construct : constructors.entrySet()) { writer.addCode(className); writer.addLine(".addConstructor(" + construct.getKey() + ", new LeekAnonymousFunction() {"); writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue u_this, AbstractLeekValue... values) throws LeekRunException {"); @@ -305,15 +337,15 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { if (parent != null) { writer.addLine("final var u_super = user_" + parent.token.getWord() + ";"); } - construct.getValue().writeJavaCode(mainblock, writer); + construct.getValue().block.writeJavaCode(mainblock, writer); writer.addLine("}});"); } - for (Entry> method : methods.entrySet()) { - for (Entry version : method.getValue().entrySet()) { + for (Entry> method : methods.entrySet()) { + for (Entry version : method.getValue().entrySet()) { String methodName = className + "_" + method.getKey() + "_" + version.getKey(); writer.addCode(className); - writer.addLine(".addMethod(\"" + method.getKey() + "\", " + version.getKey() + ", " + methodName + ");"); + writer.addLine(".addMethod(\"" + method.getKey() + "\", " + version.getKey() + ", " + methodName + ", AccessLevel." + version.getValue().level + ");"); } writer.addCode(className); writer.addLine(".addGenericMethod(\"" + method.getKey() + "\");"); @@ -331,14 +363,15 @@ private void writeFields(MainLeekBlock mainblock, JavaWriter writer, String clas parent.writeFields(mainblock, writer, className); } - for (Entry field : fields.entrySet()) { + for (Entry field : fields.entrySet()) { writer.addCode(className); writer.addCode(".addField(mUAI, \"" + field.getKey() + "\", "); if (field.getValue() != null) { - field.getValue().writeJavaCode(mainblock, writer); + field.getValue().expression.writeJavaCode(mainblock, writer); } else { writer.addCode("LeekValueManager.NULL"); } + writer.addCode(", AccessLevel." + field.getValue().level); writer.addLine(");"); } } diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index a7469e72..12d3cf59 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -8,10 +8,12 @@ import leekscript.runner.values.AbstractLeekValue; import leekscript.runner.values.ArrayLeekValue; import leekscript.runner.values.BooleanLeekValue; +import leekscript.runner.values.ClassLeekValue; import leekscript.runner.values.DoubleLeekValue; import leekscript.runner.values.FunctionLeekValue; import leekscript.runner.values.IntLeekValue; import leekscript.runner.values.NullLeekValue; +import leekscript.runner.values.ObjectLeekValue; import leekscript.runner.values.StringLeekValue; import com.alibaba.fastjson.JSONArray; @@ -122,4 +124,13 @@ public static AbstractLeekValue parseJSON(Object o, AI ai) throws LeekRunExcepti return new StringLeekValue("Class " + o.getClass().getSimpleName()); } + + public static AbstractLeekValue executeArrayAccess(AI ai, AbstractLeekValue array, AbstractLeekValue key, ClassLeekValue fromClass, AbstractLeekValue... arguments) throws LeekRunException { + array = array.getValue(); + if (array instanceof ObjectLeekValue) { + return ((ObjectLeekValue) array).callMethod(ai, key.getString(ai) + "_" + arguments.length, fromClass, arguments); + } else { + return array.get(ai, key).executeFunction(ai, arguments); + } + } } diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java index 84db71d8..95aa2a91 100644 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ b/src/main/java/leekscript/runner/values/AbstractLeekValue.java @@ -7,6 +7,7 @@ import leekscript.runner.AI; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; +import leekscript.common.AccessLevel; import leekscript.common.Error; public abstract class AbstractLeekValue { @@ -92,10 +93,18 @@ public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunExcep return LeekValueManager.NULL; } + public AbstractLeekValue get(AI ai, AbstractLeekValue value, ClassLeekValue fromClass) throws LeekRunException { + return LeekValueManager.NULL; + } + public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws LeekRunException { return LeekValueManager.NULL; } + public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value, ClassLeekValue fromClass) throws LeekRunException { + return LeekValueManager.NULL; + } + public AbstractLeekValue getValue() { return this; } @@ -236,19 +245,19 @@ public AbstractLeekValue instanceOf(AI ai, AbstractLeekValue value) throws LeekR return LeekValueManager.getLeekBooleanValue(false); } - public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { + public AbstractLeekValue getField(AI ai, String field, ClassLeekValue fromClass) throws LeekRunException { // Aucun champ ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { getString(ai), field }); return LeekValueManager.NULL; } - public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + public AbstractLeekValue callMethod(AI ai, String method, ClassLeekValue fromClass, AbstractLeekValue... arguments) throws LeekRunException { // Aucune méthode ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { getString(ai), method }); return LeekValueManager.NULL; } - public AbstractLeekValue callSuperMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + public AbstractLeekValue callSuperMethod(AI ai, ClassLeekValue currentClass, String method, AbstractLeekValue... arguments) throws LeekRunException { // Aucune méthode ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { getString(ai), method }); return LeekValueManager.NULL; diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index e57c4869..501dd975 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -8,18 +8,38 @@ import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; import leekscript.runner.LeekAnonymousFunction; +import leekscript.common.AccessLevel; import leekscript.common.Error; +import leekscript.compiler.bloc.AnonymousFunctionBlock; public class ClassLeekValue extends AbstractLeekValue { + public static class ClassField { + AbstractLeekValue value; + AccessLevel level; + public ClassField(AbstractLeekValue value, AccessLevel level) { + this.value = value; + this.level = level; + } + }; + + public static class ClassMethod { + LeekAnonymousFunction value; + AccessLevel level; + public ClassMethod(LeekAnonymousFunction value, AccessLevel level) { + this.value = value; + this.level = level; + } + }; + public String name; public AbstractLeekValue parent; - public HashMap fields = new HashMap<>(); - public HashMap staticFields = new HashMap<>(); + public HashMap fields = new HashMap<>(); + public HashMap staticFields = new HashMap<>(); public HashMap constructors = new HashMap<>(); - public HashMap methods = new HashMap<>(); + public HashMap methods = new HashMap<>(); public HashMap genericMethods = new HashMap<>(); - public HashMap staticMethods = new HashMap<>(); + public HashMap staticMethods = new HashMap<>(); public HashMap genericStaticMethods = new HashMap<>(); private ArrayLeekValue fieldsArray; @@ -38,16 +58,16 @@ public void addConstructor(int arg_count, LeekAnonymousFunction function) { constructors.put(arg_count, function); } - public void addField(AI ai, String field, AbstractLeekValue value) { - fields.put(field, value); + public void addField(AI ai, String field, AbstractLeekValue value, AccessLevel level) { + fields.put(field, new ClassField(value, level)); } - public void addStaticField(AI ai, String field, AbstractLeekValue value) throws LeekRunException { - staticFields.put(field, new VariableLeekValue(ai, value)); + public void addStaticField(AI ai, String field, AbstractLeekValue value, AccessLevel level) throws LeekRunException { + staticFields.put(field, new ObjectVariableValue(ai, value, level)); } - public void addMethod(String method, int argCount, LeekAnonymousFunction function) { - methods.put(method + "_" + argCount, function); + public void addMethod(String method, int argCount, LeekAnonymousFunction function, AccessLevel level) { + methods.put(method + "_" + argCount, new ClassMethod(function, level)); } public void addGenericMethod(String method) { @@ -56,7 +76,7 @@ public AbstractLeekValue run(AI ai, AbstractLeekValue thiz, AbstractLeekValue... final var methodCode = method + "_" + arguments.length; final var m = methods.get(methodCode); if (m != null) { - return m.run(ai, thiz, arguments); + return m.value.run(ai, thiz, arguments); } ai.addSystemLog(leekscript.AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { name, createMethodError(methodCode) }); return LeekValueManager.NULL; @@ -64,8 +84,8 @@ public AbstractLeekValue run(AI ai, AbstractLeekValue thiz, AbstractLeekValue... })); } - public void addStaticMethod(String method, int argCount, LeekAnonymousFunction function) { - staticMethods.put(method + "_" + argCount, function); + public void addStaticMethod(String method, int argCount, LeekAnonymousFunction function, AccessLevel level) { + staticMethods.put(method + "_" + argCount, new ClassMethod(function, level)); } public void addGenericStaticMethod(String method) { @@ -74,7 +94,7 @@ public AbstractLeekValue run(AI ai, AbstractLeekValue thiz, AbstractLeekValue... final var methodCode = method + "_" + arguments.length; final var m = methods.get(methodCode); if (m != null) { - return m.run(ai, null, arguments); + return m.value.run(ai, null, arguments); } ai.addSystemLog(leekscript.AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { name, createMethodError(methodCode) }); return LeekValueManager.NULL; @@ -83,10 +103,29 @@ public AbstractLeekValue run(AI ai, AbstractLeekValue thiz, AbstractLeekValue... } @Override - public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { - AbstractLeekValue result = staticFields.get(field); + public AbstractLeekValue getField(AI ai, String field, ClassLeekValue fromClass) throws LeekRunException { + // Private + var result = staticFields.get(field); if (result != null) { - return result; + if (fromClass == this) { + return result; + } else { + // Protected : Access from descendant + if (fromClass != null && fromClass.descendsFrom(this)) { + if (result.level == AccessLevel.PRIVATE) { + ai.addSystemLog(AILog.ERROR, Error.PRIVATE_STATIC_FIELD, new String[] { this.name, field }); + return LeekValueManager.NULL; + } + return result; + } else { + // Public : Access from outside + if (result.level != AccessLevel.PUBLIC) { + ai.addSystemLog(AILog.ERROR, result.level == AccessLevel.PROTECTED ? Error.PROTECTED_STATIC_FIELD : Error.PRIVATE_STATIC_FIELD, new String[] { this.name, field }); + return LeekValueManager.NULL; + } + return result; + } + } } if (field.equals("name")) { return new StringLeekValue(name); @@ -98,19 +137,20 @@ public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { return parent; } if (parent instanceof ClassLeekValue) { - return parent.getField(ai, field); + return parent.getField(ai, field, fromClass); } return LeekValueManager.NULL; } @Override - public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + public AbstractLeekValue callMethod(AI ai, String method, ClassLeekValue fromClass, AbstractLeekValue... arguments) throws LeekRunException { ai.addOperations(1); - LeekAnonymousFunction result = staticMethods.get(method); + var result = getStaticMethod(ai, method, fromClass); if (result == null) { ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_STATIC_METHOD, new String[] { name, createMethodError(method) }); return LeekValueManager.NULL; } + // Call method with new arguments, add the object at the beginning return result.run(ai, null, arguments); } @@ -145,8 +185,8 @@ public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... arguments) // Create the actual object ObjectLeekValue object = new ObjectLeekValue(this); // Add fields - for (Entry field : fields.entrySet()) { - object.addField(ai, field.getKey(), field.getValue()); + for (Entry field : fields.entrySet()) { + object.addField(ai, field.getKey(), field.getValue().value, field.getValue().level); } int arg_count = arguments.length; @@ -184,18 +224,69 @@ private ArrayLeekValue getMethodsArray(AI ai) throws LeekRunException { return methodsArray; } - public LeekAnonymousFunction getMethod(String method) { + public LeekAnonymousFunction getMethod(AI ai, String method, ClassLeekValue fromClass) throws LeekRunException { var m = methods.get(method); - if (m != null) return m; + if (m != null) { + // Private : Access from same class + if (fromClass == this) { + return m.value; + } else { + // Protected : Access from descendant + if (fromClass != null && fromClass.descendsFrom(this)) { + if (m.level == AccessLevel.PRIVATE) { + ai.addSystemLog(AILog.ERROR, Error.PRIVATE_METHOD, new String[] { this.name, method }); + return null; + } + return m.value; + } else { + // Public : Access from outside + if (m.level != AccessLevel.PUBLIC) { + ai.addSystemLog(AILog.ERROR, m.level == AccessLevel.PROTECTED ? Error.PROTECTED_METHOD : Error.PRIVATE_METHOD, new String[] { this.name, method }); + return null; + } + return m.value; + } + } + } + if (parent instanceof ClassLeekValue) { + return ((ClassLeekValue) parent).getMethod(ai, method, fromClass); + } + return null; + } + + public LeekAnonymousFunction getStaticMethod(AI ai, String method, ClassLeekValue fromClass) throws LeekRunException { + var m = staticMethods.get(method); + if (m != null) { + // Private : Access from same class + if (fromClass == this) { + return m.value; + } else { + // Protected : Access from descendant + if (fromClass != null && fromClass.descendsFrom(this)) { + if (m.level == AccessLevel.PRIVATE) { + ai.addSystemLog(AILog.ERROR, Error.PRIVATE_STATIC_METHOD, new String[] { this.name, method }); + return null; + } + return m.value; + } else { + // Public : Access from outside + if (m.level != AccessLevel.PUBLIC) { + ai.addSystemLog(AILog.ERROR, m.level == AccessLevel.PROTECTED ? Error.PROTECTED_STATIC_METHOD : Error.PRIVATE_STATIC_METHOD, new String[] { this.name, method }); + return null; + } + return m.value; + } + } + } if (parent instanceof ClassLeekValue) { - return ((ClassLeekValue) parent).getMethod(method); + return ((ClassLeekValue) parent).getStaticMethod(ai, method, fromClass); } return null; } - public LeekAnonymousFunction getSuperMethod(String method) { + public LeekAnonymousFunction getSuperMethod(AI ai, String method, ClassLeekValue fromClass) throws LeekRunException { if (parent instanceof ClassLeekValue) { - return ((ClassLeekValue) parent).getMethod(method); + return ((ClassLeekValue) parent).getMethod(ai, method, fromClass); } return null; } diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index 4ab0b28d..03e89164 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -141,7 +141,11 @@ else if (mType == ANONYMOUS_FUNCTION) { } } } else if (mType == METHOD) { - return mAnonymous.run(ai, values[0], Arrays.copyOfRange(copyPrimitiveValues(ai, values), 1, values.length)); + if (values.length == 0) { + ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { "", "1+" }); + } else { + return mAnonymous.run(ai, values[0], Arrays.copyOfRange(copyPrimitiveValues(ai, values), 1, values.length)); + } } return LeekValueManager.NULL; } diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index be18fc22..b9b54448 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -9,12 +9,13 @@ import leekscript.runner.LeekOperations; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; +import leekscript.common.AccessLevel; import leekscript.common.Error; public class ObjectLeekValue extends AbstractLeekValue { public final ClassLeekValue clazz; - public final HashMap fields = new HashMap<>(); + public final HashMap fields = new HashMap<>(); public ObjectLeekValue(ClassLeekValue clazz) { this.clazz = clazz; @@ -25,50 +26,78 @@ public ObjectLeekValue(AI ai, ObjectLeekValue value, int level) throws LeekRunEx ai.addOperations(value.fields.size()); for (var field : value.fields.entrySet()) { if (level == 1) { - fields.put(field.getKey(), new VariableLeekValue(ai, LeekOperations.clonePrimitive(ai, field.getValue()))); + fields.put(field.getKey(), new ObjectVariableValue(ai, LeekOperations.clonePrimitive(ai, field.getValue()), field.getValue().level)); } else { - fields.put(field.getKey(), new VariableLeekValue(ai, LeekOperations.clone(ai, field.getValue(), level - 1))); + fields.put(field.getKey(), new ObjectVariableValue(ai, LeekOperations.clone(ai, field.getValue(), level - 1), field.getValue().level)); } } } - public void addField(AI ai, String field, AbstractLeekValue value) throws LeekRunException { - fields.put(field, new VariableLeekValue(ai, LeekOperations.clone(ai, value))); + public void addField(AI ai, String field, AbstractLeekValue value, AccessLevel level) throws LeekRunException { + fields.put(field, new ObjectVariableValue(ai, LeekOperations.clone(ai, value), level)); } @Override - public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { + public AbstractLeekValue getField(AI ai, String field, ClassLeekValue fromClass) throws LeekRunException { // System.out.println("getField " + field); ai.addOperations(1); if (field.equals("class")) { return clazz; } - AbstractLeekValue result = fields.get(field); + // Private : Access from same class + var result = fields.get(field); if (result != null) { - return result; + if (fromClass == clazz) { + return result; + } else { + // Protected : Access from descendant + if (fromClass != null && fromClass.descendsFrom(clazz)) { + if (result.level == AccessLevel.PRIVATE) { + ai.addSystemLog(AILog.ERROR, Error.PRIVATE_FIELD, new String[] { clazz.name, field }); + return LeekValueManager.NULL; + } + return result; + } else { + // Public : Access from outside + if (result.level != AccessLevel.PUBLIC) { + ai.addSystemLog(AILog.ERROR, result.level == AccessLevel.PROTECTED ? Error.PROTECTED_FIELD : Error.PRIVATE_FIELD, new String[] { clazz.name, field }); + return LeekValueManager.NULL; + } + return result; + } + } } var method = clazz.genericMethods.get(field); - if (method != null) { - return method; - } + if (method != null) return method; + ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { clazz.name, field }); return LeekValueManager.NULL; } @Override public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunException { - return getField(ai, value.getString(ai)); + return getField(ai, value.getString(ai), null); + } + + @Override + public AbstractLeekValue get(AI ai, AbstractLeekValue value, ClassLeekValue fromClass) throws LeekRunException { + return getField(ai, value.getString(ai), fromClass); } @Override public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws LeekRunException { - return getField(ai, value.getString(ai)); + return getField(ai, value.getString(ai), null); + } + + @Override + public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value, ClassLeekValue fromClass) throws LeekRunException { + return getField(ai, value.getString(ai), fromClass); } @Override - public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + public AbstractLeekValue callMethod(AI ai, String method, ClassLeekValue fromClass, AbstractLeekValue... arguments) throws LeekRunException { ai.addOperations(1); - LeekAnonymousFunction result = clazz.getMethod(method); + LeekAnonymousFunction result = clazz.getMethod(ai, method, fromClass); if (result == null) { int underscore = method.lastIndexOf("_"); int argCount = Integer.parseInt(method.substring(underscore + 1)); @@ -86,9 +115,9 @@ public AbstractLeekValue callMethod(AI ai, String method, AbstractLeekValue... a } @Override - public AbstractLeekValue callSuperMethod(AI ai, String method, AbstractLeekValue... arguments) throws LeekRunException { + public AbstractLeekValue callSuperMethod(AI ai, ClassLeekValue currentClass, String method, AbstractLeekValue... arguments) throws LeekRunException { ai.addOperations(1); - LeekAnonymousFunction result = clazz.getSuperMethod(method); + LeekAnonymousFunction result = currentClass.getSuperMethod(ai, method, currentClass); if (result == null) { int underscore = method.lastIndexOf("_"); int argCount = Integer.parseInt(method.substring(underscore + 1)); @@ -129,7 +158,7 @@ public boolean isNumeric() { public String getString(AI ai, Set visited) throws LeekRunException { visited.add(this); - var string_method = clazz.getMethod("string_0"); + var string_method = clazz.getMethod(ai, "string_0", null); if (string_method != null) { var result = string_method.run(ai, this, new AbstractLeekValue[] {}); if (result.getType() != STRING) { @@ -141,7 +170,7 @@ public String getString(AI ai, Set visited) throws LeekRunException { var sb = new StringBuilder(clazz.name + " {"); boolean first = true; - for (HashMap.Entry field : fields.entrySet()) { + for (HashMap.Entry field : fields.entrySet()) { if (first) first = false; else sb.append(", "); sb.append(field.getKey()); diff --git a/src/main/java/leekscript/runner/values/ObjectVariableValue.java b/src/main/java/leekscript/runner/values/ObjectVariableValue.java new file mode 100644 index 00000000..4ad28bdc --- /dev/null +++ b/src/main/java/leekscript/runner/values/ObjectVariableValue.java @@ -0,0 +1,20 @@ +package leekscript.runner.values; + +import leekscript.common.AccessLevel; +import leekscript.runner.AI; +import leekscript.runner.LeekRunException; + +public class ObjectVariableValue extends VariableLeekValue { + + public AccessLevel level; + + public ObjectVariableValue(AI ai, AccessLevel level) throws LeekRunException { + super(ai); + this.level = level; + } + + public ObjectVariableValue(AI ai, AbstractLeekValue value, AccessLevel level) throws LeekRunException { + super(ai, value); + this.level = level; + } +} diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java index 9d3421fb..88c9b933 100644 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ b/src/main/java/leekscript/runner/values/VariableLeekValue.java @@ -2,6 +2,7 @@ import java.util.Set; +import leekscript.common.AccessLevel; import leekscript.runner.AI; import leekscript.runner.LeekOperations; import leekscript.runner.LeekRunException; @@ -262,16 +263,16 @@ public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunExc return mValue = mValue.modulus(ai, val); } - public AbstractLeekValue getField(AI ai, String field) throws LeekRunException { - return mValue.getField(ai, field); + public AbstractLeekValue getField(AI ai, String field, ClassLeekValue fromClass) throws LeekRunException { + return mValue.getField(ai, field, fromClass); } - public AbstractLeekValue callMethod(AI ai, String field, AbstractLeekValue... arguments) throws LeekRunException { - return mValue.callMethod(ai, field, arguments); + public AbstractLeekValue callMethod(AI ai, String field, ClassLeekValue fromClass, AbstractLeekValue... arguments) throws LeekRunException { + return mValue.callMethod(ai, field, fromClass, arguments); } - public AbstractLeekValue callSuperMethod(AI ai, String field, AbstractLeekValue... arguments) throws LeekRunException { - return mValue.callSuperMethod(ai, field, arguments); + public AbstractLeekValue callSuperMethod(AI ai, ClassLeekValue currentClass, String field, AbstractLeekValue... arguments) throws LeekRunException { + return mValue.callSuperMethod(ai, currentClass, field, arguments); } public void callConstructor(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException { From 0c7626861ac4419abf5c245ccbce62f747ab0c56 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 231/319] [object] Add tests for access levels --- src/test/java/test/TestFunction.java | 1 + src/test/java/test/TestObject.java | 96 ++++++++++++++++++++++++++-- 2 files changed, 93 insertions(+), 4 deletions(-) diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index 6115027f..17b20875 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -77,6 +77,7 @@ public void run() { code_v10("function LamaSwag() {} @LamaSwag();").equals("null"); code("function f() { distance = 12 } function distance() { return 'salut' } return distance()").equals("salut"); code("getOperations()").equals("null"); + code("var a = [function() { return 12 }] return a[0]()").equals("12"); section("Modify argument"); code("function test(x) { x += 10 return x } return test(5)").equals("15"); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 9b7b1785..0dd392cc 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -1,5 +1,7 @@ package test; +import leekscript.common.Error; + public class TestObject extends TestCommon { public void run() { @@ -27,14 +29,100 @@ public void run() { section("Classes"); code_v11("class A { } return new A();").equals("A {}"); - code_v11("class A { a = 10 } var a = new A(); return --a.a").equals("9"); - code_v11("class A { a = 10 } var a = new A(); a.a-- return a.a").equals("9"); - code_v11("class A { a = 10 } var a = new A(); return ++a.a").equals("11"); - code_v11("class A { a = 10 } var a = new A(); a.a++ return a.a").equals("11"); code_v11("class A { a = 10 } var a = [new A()]; a[0].a++ return a[0].a").equals("11"); code_v11("class A { a = 10 } var a = [new A()]; a[0].a-- return a[0].a").equals("9"); code_v11("class A { a = 10 } var a = [new A()]; ++a[0].a return a[0].a").equals("11"); code_v11("class A { a = 10 } var a = [new A()]; --a[0].a return a[0].a").equals("9"); + code_v11("class A { a = 10 m() { return 12 } } var a = new A(); return a.m()").equals("12"); + code_v11("class A { a = 10 m() { return 13 } } var a = new A(); return a['m']()").equals("13"); + code_v11("class A { a = 10 m() { return 13 } } var a = new A(); var m = 'm' return a[m]()").equals("13"); + code_v11("class A { a = 10 m() { return a } } var a = new A(); var array = [a.m] return array[0](a)").equals("10"); + code_v11("class A { a = 10 m() { return a } } var a = new A(); var array = [a['m']] return array[0](a)").equals("10"); + + section("Operators on field"); + code_v11("class A { a = 10 } var a = new A(); return --a.a").equals("9"); + code_v11("class A { a = 10 } var a = new A(); a.a-- return a.a").equals("9"); + code_v11("class A { a = 10 } var a = new A(); return ++a.a").equals("11"); + code_v11("class A { a = 10 } var a = new A(); a.a++ return a.a").equals("11"); + code_v11("class A { a = 10 } var a = new A(); return a.a += 5").equals("15"); + code_v11("class A { a = 10 } var a = new A(); return a.a -= 5").equals("5"); + code_v11("class A { a = 10 } var a = new A(); return a.a *= 5").equals("50"); + code_v11("class A { a = 10 } var a = new A(); return a.a /= 5").equals("2.0"); + code_v11("class A { a = 10 } var a = new A(); return a.a %= 5").equals("0"); + code_v11("class A { a = 10 } var a = new A(); return a.a **= 5").equals("100000"); + code_v11("class A { a = 10 } var a = new A(); return a.a |= 5").equals("15"); + code_v11("class A { a = 10 } var a = new A(); return a.a &= 5").equals("0"); + code_v11("class A { a = 10 } var a = new A(); return a.a ^= 5").equals("15"); + code_v11("class A { a = 10 } var a = new A(); return a.a <<= 5").equals("320"); + code_v11("class A { a = 10 } var a = new A(); return a.a >>= 5").equals("0"); + code_v11("class A { a = 10 } var a = new A(); return a.a >>>= 5").equals("0"); + + section("Operators on static field"); + code_v11("class A { static a = 10 } return --A.a").equals("9"); + code_v11("class A { static a = 10 } A.a-- return A.a").equals("9"); + code_v11("class A { static a = 10 } return ++A.a").equals("11"); + code_v11("class A { static a = 10 } A.a++ return A.a").equals("11"); + code_v11("class A { static a = 10 } return A.a += 5").equals("15"); + code_v11("class A { static a = 10 } return A.a -= 5").equals("5"); + code_v11("class A { static a = 10 } return A.a *= 5").equals("50"); + code_v11("class A { static a = 10 } return A.a /= 5").equals("2.0"); + code_v11("class A { static a = 10 } return A.a %= 5").equals("0"); + code_v11("class A { static a = 10 } return A.a **= 5").equals("100000"); + code_v11("class A { static a = 10 } return A.a |= 5").equals("15"); + code_v11("class A { static a = 10 } return A.a &= 5").equals("0"); + code_v11("class A { static a = 10 } return A.a ^= 5").equals("15"); + code_v11("class A { static a = 10 } return A.a <<= 5").equals("320"); + code_v11("class A { static a = 10 } return A.a >>= 5").equals("0"); + code_v11("class A { static a = 10 } return A.a >>>= 5").equals("0"); + + section("Inheritance"); + code_v11("class A { x = 10 } class B extends A {} var a = new B() return a.x").equals("10"); + code_v11("class A { m() { return 'ok' } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("ok"); + code_v11("class A { x = 10 } class B extends A {} class C extends B {} var a = new C() return a.x").equals("10"); + code_v11("class A { m() { return 'ok' } } class B extends A {} class C extends B {} var a = new C() return a.m()").equals("ok"); + code_v11("class A { m() { return 'ok' } } class B extends A { m() { return super.m() }} class C extends B { m() { return super.m() } } var a = new C() return a.m()").equals("ok"); + code_v11("class A { m() { return 'ok' } } class B extends A {} class C extends B { m() { return super.m() } } var a = new C() return a.m()").equals("ok"); + code_v11("class A { m() { return 'okA' } } class B extends A { m() { return super.m() + 'B' }} class C extends B { m() { return super.m() + 'C' } } var a = new C()return a.m()").equals("okABC"); + + section("Access levels: fields"); + code_v11("class A { x = 10 } var a = new A() return a.x").equals("10"); + code_v11("class A { public x = 10 } var a = new A() return a.x").equals("10"); + code_v11("class A { protected x = 10 } var a = new A() return a.x").equals("null"); + code_v11("class A { private x = 10 } var a = new A() return a.x").equals("null"); + code_v11("class A { private x = 10 m() { return x } } var a = new A() return a.m()").equals("10"); + code_v11("class A { private x = 10 } class B extends A {} var a = new B() return a.x").equals("null"); + code_v11("class A { protected x = 10 } class B extends A {} var a = new B() return a.x").equals("null"); + code_v11("class A { protected x = 10 } class B extends A { m() { return x } } var a = new B() return a.m()").equals("10"); + + section("Access levels: static fields"); + code_v11("class A { static x = 10 } return A.x").equals("10"); + code_v11("class A { public static x = 10 } return A.x").equals("10"); + code_v11("class A { protected static x = 10 } return A.x").equals("null"); + code_v11("class A { private static x = 10 } return A.x").equals("null"); + code_v11("class A { private static x = 10 static m() { return x } } return A.m()").equals("10"); + code_v11("class A { private static x = 10 } class B extends A {} return B.x").equals("null"); + code_v11("class A { protected static x = 10 } class B extends A {} return B.x").equals("null"); + code_v11("class A { protected static x = 10 } class B extends A { static m() { return x } } return B.m()").equals("10"); + + section("Access levels: methods"); + code_v11("class A { m() { return 10 } } var a = new A() return a.m()").equals("10"); + code_v11("class A { public m() { return 10 } } var a = new A() return a.m()").equals("10"); + code_v11("class A { protected m() { return 10 } } var a = new A() return a.m()").equals("null"); + code_v11("class A { private m() { return 10 } } var a = new A() return a.m()").equals("null"); + code_v11("class A { public m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("10"); + code_v11("class A { protected m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("null"); + code_v11("class A { private m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("null"); + code_v11("class A { protected m() { return 10 } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("10"); + + section("Access levels: static methods"); + code_v11("class A { static m() { return 10 } } return A.m()").equals("10"); + code_v11("class A { public static m() { return 10 } } return A.m()").equals("10"); + code_v11("class A { protected static m() { return 10 } } return A.m()").equals("null"); + code_v11("class A { private static m() { return 10 } } return A.m()").equals("null"); + code_v11("class A { public static m() { return 10 } } class B extends A {} return B.m()").equals("10"); + code_v11("class A { protected static m() { return 10 } } class B extends A {} return B.m()").equals("null"); + code_v11("class A { private static m() { return 10 } } class B extends A {} return B.m()").equals("null"); + /* * Operators From b1cbc1e28102b6a6fc2027938600ce8bdd36ba2f Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 232/319] [codegen] Fix LS code generation --- src/main/java/leekscript/compiler/expression/LeekNumber.java | 1 + src/main/java/leekscript/compiler/expression/LeekString.java | 4 +++- src/main/java/leekscript/compiler/expression/Operators.java | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekNumber.java b/src/main/java/leekscript/compiler/expression/LeekNumber.java index d7fe7d70..184d7400 100644 --- a/src/main/java/leekscript/compiler/expression/LeekNumber.java +++ b/src/main/java/leekscript/compiler/expression/LeekNumber.java @@ -34,6 +34,7 @@ public String getString() { if (type == Type.REAL) { var formatter = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US); formatter.setMaximumFractionDigits(15); + formatter.setGroupingUsed(false); return formatter.format(mValue); } else { return String.valueOf((int) mValue); diff --git a/src/main/java/leekscript/compiler/expression/LeekString.java b/src/main/java/leekscript/compiler/expression/LeekString.java index cff4fb59..7c17c685 100644 --- a/src/main/java/leekscript/compiler/expression/LeekString.java +++ b/src/main/java/leekscript/compiler/expression/LeekString.java @@ -1,5 +1,7 @@ package leekscript.compiler.expression; +import com.alibaba.fastjson.JSON; + import leekscript.common.Type; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; @@ -25,7 +27,7 @@ public Type getType() { @Override public String getString() { - return "\"" + mString + "\""; + return JSON.toJSONString(mString); } @Override diff --git a/src/main/java/leekscript/compiler/expression/Operators.java b/src/main/java/leekscript/compiler/expression/Operators.java index f65d5966..4188d2cd 100644 --- a/src/main/java/leekscript/compiler/expression/Operators.java +++ b/src/main/java/leekscript/compiler/expression/Operators.java @@ -293,6 +293,8 @@ public static String getString(int operator, int version) { return "new"; case BITNOT: return "~"; + case REFERENCE: + return "@"; case INSTANCEOF: return "instanceof"; } From cd162faf8232c16f97d544345894f897ee668bd7 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 233/319] [class] Implement access levels on constructors --- src/main/java/leekscript/common/Error.java | 6 ++++-- .../expression/LeekExpressionFunction.java | 18 +++++++++++++++++- .../ClassDeclarationInstruction.java | 19 ++++++++++++++++--- src/test/java/test/TestObject.java | 11 ++++++++++- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/main/java/leekscript/common/Error.java b/src/main/java/leekscript/common/Error.java index 422a0a9d..53ecd257 100644 --- a/src/main/java/leekscript/common/Error.java +++ b/src/main/java/leekscript/common/Error.java @@ -85,6 +85,8 @@ public enum Error { PROTECTED_STATIC_FIELD, // 81 PRIVATE_METHOD, // 82 PROTECTED_METHOD, // 83 - PRIVATE_STATIC_METHOD, // 84 - PROTECTED_STATIC_METHOD, // 85 + PRIVATE_CONSTRUCTOR, // 84 + PROTECTED_CONSTRUCTOR, // 85 + PRIVATE_STATIC_METHOD, // 86 + PROTECTED_STATIC_METHOD, // 87 } \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 7a517bab..eac1a5ea 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -14,6 +14,7 @@ import leekscript.runner.CallableVersion; import leekscript.runner.ILeekFunction; import leekscript.runner.LeekFunctions; +import leekscript.common.AccessLevel; import leekscript.common.Error; import leekscript.common.Type; @@ -198,8 +199,23 @@ public void analyze(WordCompiler compiler) { } else if (v.getVariableType() == VariableType.CLASS) { var clazz = v.getClassDeclaration(); - if (mParameters.size() != 0 && !clazz.hasConstructor(mParameters.size())) { + var constructor = clazz.getConstructor(mParameters.size()); + if (constructor == null) { compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.UNKNOWN_CONSTRUCTOR, new String[] { clazz.getName() })); + } else if (constructor.level != AccessLevel.PUBLIC) { + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, constructor.level == AccessLevel.PROTECTED ? Error.PROTECTED_CONSTRUCTOR : Error.PRIVATE_CONSTRUCTOR, new String[] { clazz.getName() })); + } + + } else if (v.getVariableType() == VariableType.SUPER) { + + var clazz = v.getClassDeclaration().getParent(); + if (clazz != null) { + var constructor = clazz.getConstructor(mParameters.size()); + if (constructor == null) { + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.UNKNOWN_CONSTRUCTOR, new String[] { clazz.getName() })); + } else if (constructor.level == AccessLevel.PRIVATE) { + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.PRIVATE_CONSTRUCTOR, new String[] { clazz.getName() })); + } } } } else if (mExpression instanceof LeekObjectAccess) { diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 19cb2c30..2883b5ac 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -15,6 +15,7 @@ import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.runner.values.ClassLeekValue.ClassMethod; import leekscript.common.AccessLevel; import leekscript.common.Error; @@ -33,8 +34,8 @@ public ClassDeclarationField(AbstractExpression expr, AccessLevel level) { public static class ClassDeclarationMethod { - ClassMethodBlock block; - AccessLevel level; + public ClassMethodBlock block; + public AccessLevel level; public ClassDeclarationMethod(ClassMethodBlock block, AccessLevel level) { this.block = block; @@ -151,6 +152,18 @@ public boolean hasConstructor(int param_count) { return constructors.containsKey(param_count); } + public ClassDeclarationMethod getConstructor(int param_count) { + // Search existing constructor + var constructor = constructors.get(param_count); + if (constructor != null) return constructor; + + // If constructor has 0 parameters, return the default implicit one + if (param_count == 0) { + return new ClassDeclarationMethod(null, AccessLevel.PUBLIC); + } + return null; + } + public void addConstructor(ClassMethodBlock block, AccessLevel level) { constructors.put(block.countParameters(), new ClassDeclarationMethod(block, level)); } @@ -366,7 +379,7 @@ private void writeFields(MainLeekBlock mainblock, JavaWriter writer, String clas for (Entry field : fields.entrySet()) { writer.addCode(className); writer.addCode(".addField(mUAI, \"" + field.getKey() + "\", "); - if (field.getValue() != null) { + if (field.getValue().expression != null) { field.getValue().expression.writeJavaCode(mainblock, writer); } else { writer.addCode("LeekValueManager.NULL"); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 0dd392cc..867771a0 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -114,6 +114,16 @@ public void run() { code_v11("class A { private m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("null"); code_v11("class A { protected m() { return 10 } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("10"); + section("Access levels: constructors"); + code_v11("class A { constructor() { } } return new A()").equals("A {}"); + code_v11("class A { public constructor() { } } return new A()").equals("A {}"); + code_v11("class A { protected constructor() { } } return new A()").error(); + code_v11("class A { private constructor() { } } return new A()").error(); + code_v11("class A { public constructor() { } } class B extends A {} return new B()").equals("B {}"); + code_v11("class A { x protected constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").equals("10"); + code_v11("class A { x private constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").error(); + code_v11("class A { private constructor() { } } class B extends A {} return new B()").equals("B {}"); + section("Access levels: static methods"); code_v11("class A { static m() { return 10 } } return A.m()").equals("10"); code_v11("class A { public static m() { return 10 } } return A.m()").equals("10"); @@ -123,7 +133,6 @@ public void run() { code_v11("class A { protected static m() { return 10 } } class B extends A {} return B.m()").equals("null"); code_v11("class A { private static m() { return 10 } } class B extends A {} return B.m()").equals("null"); - /* * Operators */ From 790b84cb013462ae4cb78849e1b7abbd5fc2d47b Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 234/319] [method] Add errors for static methods --- .../expression/LeekExpressionFunction.java | 7 +++++- .../ClassDeclarationInstruction.java | 24 +++++++++++++++++++ src/test/java/test/TestObject.java | 8 +++---- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index eac1a5ea..6c69b962 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -225,8 +225,13 @@ public void analyze(WordCompiler compiler) { var v = (LeekVariable) oa.getObject(); if (v.getVariableType() == VariableType.CLASS) { var clazz = v.getClassDeclaration(); - if (!clazz.hasStaticMethod(oa.getField(), mParameters.size())) { + var staticMethod = clazz.getStaticMethod(oa.getField(), mParameters.size()); + if (staticMethod == null) { compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.UNKNOWN_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); + } else if (staticMethod.level == AccessLevel.PRIVATE && clazz != compiler.getCurrentClass()) { + compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.PRIVATE_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); + } else if (staticMethod.level == AccessLevel.PROTECTED && !compiler.getCurrentClass().descendsFrom(clazz)) { + compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.PROTECTED_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); } } } diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 2883b5ac..764e53ee 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -442,8 +442,32 @@ public String getMethodName(String name, int argumentCount) { return null; } + public ClassDeclarationMethod getStaticMethod(String method, int argumentCount) { + var versions = staticMethods.get(method); + if (versions != null) { + if (versions.containsKey(argumentCount)) return versions.get(argumentCount); + } + if (parent != null) { + return parent.getStaticMethod(method, argumentCount); + } + return null; + } + @Override public int getOperations() { return 0; } + + public boolean descendsFrom(ClassDeclarationInstruction clazz) { + var current = this; + while (current != null) { + if (current == clazz) return true; + if (current.parent != null) { + current = current.parent; + } else { + return false; + } + } + return false; + } } diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 867771a0..043ecc11 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -127,11 +127,11 @@ public void run() { section("Access levels: static methods"); code_v11("class A { static m() { return 10 } } return A.m()").equals("10"); code_v11("class A { public static m() { return 10 } } return A.m()").equals("10"); - code_v11("class A { protected static m() { return 10 } } return A.m()").equals("null"); - code_v11("class A { private static m() { return 10 } } return A.m()").equals("null"); + code_v11("class A { protected static m() { return 10 } } return A.m()").error(); + code_v11("class A { private static m() { return 10 } } return A.m()").error(); code_v11("class A { public static m() { return 10 } } class B extends A {} return B.m()").equals("10"); - code_v11("class A { protected static m() { return 10 } } class B extends A {} return B.m()").equals("null"); - code_v11("class A { private static m() { return 10 } } class B extends A {} return B.m()").equals("null"); + code_v11("class A { protected static m() { return 10 } } class B extends A {} return B.m()").error(); + code_v11("class A { private static m() { return 10 } } class B extends A {} return B.m()").error(); /* * Operators From e1eb2cbfc117aae35582f9317ea0e9a23e70b725 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 235/319] [object] Add tests --- src/test/java/test/TestObject.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 043ecc11..d962a28d 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -133,6 +133,13 @@ public void run() { code_v11("class A { protected static m() { return 10 } } class B extends A {} return B.m()").error(); code_v11("class A { private static m() { return 10 } } class B extends A {} return B.m()").error(); + section("Initialization of fields"); + code_v11("class A { x = [1, 2, 3] } var a = new A() return a.x").equals("[1, 2, 3]"); + code_v11("class A { x = [1, 2, 3] } var a = new A() push(a.x, 4) var b = new A() return b.x").equals("[1, 2, 3]"); + code_v11("class B { y = 10 } class A { x = new B() } var a = new A() return a.x").equals("B {y: 10}"); + code_v11("class B { y = 10 } class A { x = new B() } var a = new A() return a.x.y").equals("10"); + code_v11("class B { y = 10 } class A { static x = new B() } return A.x").equals("B {y: 10}"); + /* * Operators */ From 347f6eb039ad46eaef7a0d36ad8486f2cd175220 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 236/319] [class] Fix field initializers --- .../compiler/bloc/MainLeekBlock.java | 4 ++ .../ClassDeclarationInstruction.java | 63 +++++++++++++------ .../runner/values/ClassLeekValue.java | 8 +-- 3 files changed, 50 insertions(+), 25 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 400305ab..dc575c22 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -196,6 +196,10 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { for (var clazz : mUserClasses.values()) { clazz.createJava(this, writer); } + // Initialize classes static fields + for (var clazz : mUserClasses.values()) { + clazz.initializeStaticFields(this, writer); + } writer.addLine("}"); // Variables globales diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 764e53ee..7bb3c71a 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -260,6 +260,11 @@ public void analyze(WordCompiler compiler) { for (var constructor : constructors.values()) { constructor.block.analyze(compiler); } + // Ajout du constructeur à 0 argument par défaut en public + if (!constructors.containsKey(0)) { + constructors.put(0, new ClassDeclarationMethod(null, AccessLevel.PUBLIC)); + } + for (var method : methods.values()) { for (var version : method.values()) { version.block.analyze(compiler); @@ -318,18 +323,6 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { } } - for (Entry field : staticFields.entrySet()) { - writer.addCode(className); - writer.addCode(".addStaticField(mUAI, \"" + field.getKey() + "\", "); - if (field.getValue() != null) { - field.getValue().expression.writeJavaCode(mainblock, writer); - } else { - writer.addCode("LeekValueManager.NULL"); - } - writer.addCode(", AccessLevel." + field.getValue().level); - writer.addLine(");"); - } - writeFields(mainblock, writer, className); for (Entry> method : staticMethods.entrySet()) { @@ -350,7 +343,24 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { if (parent != null) { writer.addLine("final var u_super = user_" + parent.token.getWord() + ";"); } - construct.getValue().block.writeJavaCode(mainblock, writer); + ClassDeclarationInstruction current = this; + while (current != null) { + for (var field : current.fields.entrySet()) { + writer.addCode("((ObjectLeekValue) u_this).addField(mUAI, \"" + field.getKey() + "\", "); + if (field.getValue().expression != null) { + field.getValue().expression.writeJavaCode(mainblock, writer); + } else { + writer.addCode("LeekValueManager.NULL"); + } + writer.addLine(", AccessLevel." + field.getValue().level + ");"); + } + current = current.parent; + } + if (construct.getValue().block != null) { + construct.getValue().block.writeJavaCode(mainblock, writer); + } else { + writer.addLine("return u_this;"); + } writer.addLine("}});"); } @@ -365,6 +375,26 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { } } + public void initializeStaticFields(MainLeekBlock mainblock, JavaWriter writer) { + + mainblock.getWordCompiler().setCurrentClass(this); + + // Create the class in the constructor of the AI + String className = "user_" + token.getWord(); + + for (var field : staticFields.entrySet()) { + writer.addCode(className); + writer.addCode(".addStaticField(mUAI, \"" + field.getKey() + "\", "); + if (field.getValue() != null) { + field.getValue().expression.writeJavaCode(mainblock, writer); + } else { + writer.addCode("null"); + } + writer.addCode(", AccessLevel." + field.getValue().level); + writer.addLine(");"); + } + } + @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { @@ -378,12 +408,7 @@ private void writeFields(MainLeekBlock mainblock, JavaWriter writer, String clas for (Entry field : fields.entrySet()) { writer.addCode(className); - writer.addCode(".addField(mUAI, \"" + field.getKey() + "\", "); - if (field.getValue().expression != null) { - field.getValue().expression.writeJavaCode(mainblock, writer); - } else { - writer.addCode("LeekValueManager.NULL"); - } + writer.addCode(".addField(mUAI, \"" + field.getKey() + "\""); writer.addCode(", AccessLevel." + field.getValue().level); writer.addLine(");"); } diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 501dd975..a9eef01e 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -58,8 +58,8 @@ public void addConstructor(int arg_count, LeekAnonymousFunction function) { constructors.put(arg_count, function); } - public void addField(AI ai, String field, AbstractLeekValue value, AccessLevel level) { - fields.put(field, new ClassField(value, level)); + public void addField(AI ai, String field, AccessLevel level) { + fields.put(field, new ClassField(null, level)); } public void addStaticField(AI ai, String field, AbstractLeekValue value, AccessLevel level) throws LeekRunException { @@ -184,10 +184,6 @@ public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... arguments) ai.addOperations(1); // Create the actual object ObjectLeekValue object = new ObjectLeekValue(this); - // Add fields - for (Entry field : fields.entrySet()) { - object.addField(ai, field.getKey(), field.getValue().value, field.getValue().level); - } int arg_count = arguments.length; if (constructors.containsKey(arg_count)) { From 6f237b3962f90d239ad95a9a93b1bd723201b52e Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 237/319] [array] Add tests --- src/test/java/test/TestArray.java | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index 736ea2f6..729ce8ba 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -222,11 +222,25 @@ public void run() throws Exception { code("var a = [5, 6, 7]; a[0]++; a[1]++; return a;").equals("[6, 7, 7]"); code("var a = [[5]]; a[0][0]++; return a;").equals("[[6]]"); + section("Array.operator pre ++ on element"); + code("var a = [5]; ++a[0]; return a;").equals("[6]"); + code("var a = [5]; return ++a[0];").equals("6"); + code("var a = [5, 6, 7]; ++a[0]; ++a[1]; return a;").equals("[6, 7, 7]"); + code("var a = [[5]]; ++a[0][0]; return a;").equals("[[6]]"); + code("var a = [[5]]; return ++a[0][0];").equals("6"); + section("Array.operator -- on element"); code("var a = [5] a[0]-- return a;").equals("[4]"); code("var a = [5, 6, 7] a[0]-- a[1]-- return a;").equals("[4, 5, 7]"); code("var a = [[5]] a[0][0]-- return a;").equals("[[4]]"); + section("Array.operator pre -- on element"); + code("var a = [5]; --a[0] return a;").equals("[4]"); + code("var a = [5] return --a[0];").equals("4"); + code("var a = [5, 6, 7]; --a[0]; --a[1] return a;").equals("[4, 5, 7]"); + code("var a = [[5]]; --a[0][0] return a;").equals("[[4]]"); + code("var a = [[5]] return --a[0][0];").equals("4"); + section("Array.operator -= on element"); code("var a = [5] a[0] -= 1 return a;").equals("[4]"); code("var a = [5, 6, 7] a[0] -= 10 a[1] -= 10 return a;").equals("[-5, -4, 7]"); @@ -238,12 +252,38 @@ public void run() throws Exception { code("var a = [5, 6, 7] a[0] *= 10 a[1] *= 10 return a;").equals("[50, 60, 7]"); code("var a = [[5]] a[0][0] *= 10 return a;").equals("[[50]]"); + section("Array.operator %= on element"); + code("var a = [5] a[0] %= 2 return a;").equals("[1]"); + code("var a = [5, 6, 7] a[0] %= 2 a[1] %= 2 return a;").equals("[1, 0, 7]"); + code("var a = [[5]] a[0][0] %= 2 return a;").equals("[[1]]"); + + section("Array.operator **= on element"); + code("var a = [5] a[0] **= 2 return a;").equals("[25]"); + code("var a = [5, 6, 7] a[0] **= 2 a[1] **= 2 return a;").equals("[25, 36, 7]"); + code("var a = [[5]] a[0][0] **= 2 return a;").equals("[[25]]"); + section("Array.operator |= on element"); code("var a = [5] a[0] |= 2 return a;").equals("[7]"); code("var a = [5, 6, 7] a[0] |= 8 a[1] |= 8 return a;").equals("[13, 14, 7]"); code("var a = [[5]] a[0][0] |= 2 return a;").equals("[[7]]"); code("var a = [] a[0] |= 1 return a;").equals("[1]"); + section("Array.operator &= on element"); + code("var a = [87619] a[0] &= 18431 return a;").equals("[17987]"); + + section("Array.operator ^= on element"); + code_v10("var a = [876] a[0] ^= 3 return a;").equals("[672221376]"); + code_v11("var a = [876] a[0] ^= 3 return a;").equals("[879]"); + + section("Array.operator <<= on element"); + code("var a = [123] a[0] <<= 12 return a;").equals("[503808]"); + + section("Array.operator >>= on element"); + code("var a = [123123123] a[0] >>= 5 return a;").equals("[3847597]"); + + section("Array.operator >>>= on element"); + code("var a = [-155] a[0] >>>= 5 return a;").equals("[134217723]"); + section("Array.count()"); code("return count([1, 2, 3, 4, 5]);").equals("5"); From 2a37f70ee12ecdb40403c1699ebbac6eff482aa9 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 238/319] [class] Fix static field --- .../instruction/ClassDeclarationInstruction.java | 4 ++-- src/test/java/test/TestObject.java | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 7bb3c71a..7d549f4f 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -385,10 +385,10 @@ public void initializeStaticFields(MainLeekBlock mainblock, JavaWriter writer) { for (var field : staticFields.entrySet()) { writer.addCode(className); writer.addCode(".addStaticField(mUAI, \"" + field.getKey() + "\", "); - if (field.getValue() != null) { + if (field.getValue().expression != null) { field.getValue().expression.writeJavaCode(mainblock, writer); } else { - writer.addCode("null"); + writer.addCode("LeekValueManager.NULL"); } writer.addCode(", AccessLevel." + field.getValue().level); writer.addLine(");"); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index d962a28d..e3f6c8dc 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -39,6 +39,14 @@ public void run() { code_v11("class A { a = 10 m() { return a } } var a = new A(); var array = [a.m] return array[0](a)").equals("10"); code_v11("class A { a = 10 m() { return a } } var a = new A(); var array = [a['m']] return array[0](a)").equals("10"); + section("Static fields"); + code_v11("class A { static x }").equals("null"); + code_v11("class A { static x } return A.x").equals("null"); + code_v11("class A { static x = 10 } return A.x").equals("10"); + code_v11("class A { static x = 'hello' } return A.x").equals("hello"); + code_v11("class A { static x = [1, 2, 3] } return A.x").equals("[1, 2, 3]"); + code_v11("class A { static x = null } return A.x").equals("null"); + section("Operators on field"); code_v11("class A { a = 10 } var a = new A(); return --a.a").equals("9"); code_v11("class A { a = 10 } var a = new A(); a.a-- return a.a").equals("9"); @@ -83,6 +91,7 @@ public void run() { code_v11("class A { m() { return 'ok' } } class B extends A { m() { return super.m() }} class C extends B { m() { return super.m() } } var a = new C() return a.m()").equals("ok"); code_v11("class A { m() { return 'ok' } } class B extends A {} class C extends B { m() { return super.m() } } var a = new C() return a.m()").equals("ok"); code_v11("class A { m() { return 'okA' } } class B extends A { m() { return super.m() + 'B' }} class C extends B { m() { return super.m() + 'C' } } var a = new C()return a.m()").equals("okABC"); + code_v11("class A { items } class B extends A { constructor() { this.items = [] } } var x = new B() return x").equals("B {items: []}"); section("Access levels: fields"); code_v11("class A { x = 10 } var a = new A() return a.x").equals("10"); From c2c02e6abb65eb20ed516a9f904773ce9e877628 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 239/319] [class] Fix field init --- .../ClassDeclarationInstruction.java | 30 +++++++++++-------- .../runner/values/ClassLeekValue.java | 3 ++ src/test/java/test/TestObject.java | 1 + 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 7d549f4f..5b82d708 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -291,6 +291,23 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { if (parent != null) { writer.addLine(className + ".setParent(user_" + parent.getName() + ");"); } + writer.addCode(className + ".initFields = new LeekAnonymousFunction() {"); + writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue u_this, AbstractLeekValue... values) throws LeekRunException {"); + ClassDeclarationInstruction current = this; + while (current != null) { + for (var field : current.fields.entrySet()) { + writer.addCode("((ObjectLeekValue) u_this).addField(mUAI, \"" + field.getKey() + "\", "); + if (field.getValue().expression != null) { + field.getValue().expression.writeJavaCode(mainblock, writer); + } else { + writer.addCode("LeekValueManager.NULL"); + } + writer.addLine(", AccessLevel." + field.getValue().level + ");"); + } + current = current.parent; + } + writer.addLine("return null;"); + writer.addLine("}};"); for (Entry> method : staticMethods.entrySet()) { for (Entry version : method.getValue().entrySet()) { @@ -343,19 +360,6 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { if (parent != null) { writer.addLine("final var u_super = user_" + parent.token.getWord() + ";"); } - ClassDeclarationInstruction current = this; - while (current != null) { - for (var field : current.fields.entrySet()) { - writer.addCode("((ObjectLeekValue) u_this).addField(mUAI, \"" + field.getKey() + "\", "); - if (field.getValue().expression != null) { - field.getValue().expression.writeJavaCode(mainblock, writer); - } else { - writer.addCode("LeekValueManager.NULL"); - } - writer.addLine(", AccessLevel." + field.getValue().level + ");"); - } - current = current.parent; - } if (construct.getValue().block != null) { construct.getValue().block.writeJavaCode(mainblock, writer); } else { diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index a9eef01e..85bf7eb7 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -41,6 +41,7 @@ public ClassMethod(LeekAnonymousFunction value, AccessLevel level) { public HashMap genericMethods = new HashMap<>(); public HashMap staticMethods = new HashMap<>(); public HashMap genericStaticMethods = new HashMap<>(); + public LeekAnonymousFunction initFields = null; private ArrayLeekValue fieldsArray; private ArrayLeekValue methodsArray; @@ -184,6 +185,8 @@ public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... arguments) ai.addOperations(1); // Create the actual object ObjectLeekValue object = new ObjectLeekValue(this); + // Init fields + this.initFields.run(ai, object); int arg_count = arguments.length; if (constructors.containsKey(arg_count)) { diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index e3f6c8dc..d3e7e992 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -92,6 +92,7 @@ public void run() { code_v11("class A { m() { return 'ok' } } class B extends A {} class C extends B { m() { return super.m() } } var a = new C() return a.m()").equals("ok"); code_v11("class A { m() { return 'okA' } } class B extends A { m() { return super.m() + 'B' }} class C extends B { m() { return super.m() + 'C' } } var a = new C()return a.m()").equals("okABC"); code_v11("class A { items } class B extends A { constructor() { this.items = [] } } var x = new B() return x").equals("B {items: []}"); + code_v11("class A { items } class B extends A { constructor() { this.items = [] super() } } var x = new B() return x").equals("B {items: []}"); section("Access levels: fields"); code_v11("class A { x = 10 } var a = new A() return a.x").equals("10"); From f718625c89358d697463c1ca4be5e0038d860ad2 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 240/319] [test] Add tests --- src/test/java/test/TestCommon.java | 2 +- src/test/java/test/TestLoops.java | 4 ++-- src/test/java/test/TestObject.java | 14 +++++++------- src/test/java/test/TestOperators.java | 5 +++-- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index 0a513ff4..cec5176d 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -137,7 +137,7 @@ public String run_version(int version, Checker checker) { } catch (LeekCompilerException e) { // e.printStackTrace(); // System.out.println("Error = " + e.getError()); - result = new Result("error", e.getError(), 0, 0); + result = new Result(e.getError().toString(), e.getError(), 0, 0); } catch (Exception e) { // e.printStackTrace(); result = new Result("error", Error.NONE, 0, 0); diff --git a/src/test/java/test/TestLoops.java b/src/test/java/test/TestLoops.java index fdd8e9ab..761a3bb8 100644 --- a/src/test/java/test/TestLoops.java +++ b/src/test/java/test/TestLoops.java @@ -133,7 +133,7 @@ public void run() { code("var s = 0; var a; for (a in [1, 2, 3]) { s += a } return s").equals("6"); code("var s = 0; var a; for (var k : a in [1, 2, 3]) { s += a } return s").equals("6"); code("var s = 0; var k; for (k : var a in [1, 2, 3, 4, 5]) { s += k } return s").equals("10"); - DISABLED_code("for (var x in 12) {}").error(); + DISABLED_code("for (var x in 12) {}").error(Error.NOT_ITERABLE); section("Normal containers"); code("for (var v in [1, 2, 3, 4]) {}").equals("null"); @@ -154,7 +154,7 @@ public void run() { // DISABLED_code("var y = '' for k, x in { var x = [1: '2'] x.insert(3, 4) x } { y += k + ':' + x + ' ' } y").equals("'1:2 3:4 '"); // code("var y = 'test' for (var x in 1) { y = x } y").equals("1"); // code("var y = 'test' for (var x in 'salut') { y = x } y").equals("'t'"); - code("var x = 'test' for (var x in [1]) {} return x;").error(); + code("var x = 'test' for (var x in [1]) {} return x;").error(Error.VARIABLE_NAME_UNAVAILABLE); // code("var y = '' for k, x in { var x = <> x.insert(4) x } { y += k + ':' + x } y").equals("'0:4'"); // DISABLED_code("var fs = [] fs.push(s -> {var sum = 0 for v in s {sum += v} sum}) fs[0](<1, 2>)").equals("3"); // TODO issue #243 // DISABLED_code("var fs = [] fs.push(s -> {[for v in s {v}]}) fs[0](<2,1>)").equals("[1, 2]"); // TODO issue #243 diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index d3e7e992..84df3a2b 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -127,21 +127,21 @@ public void run() { section("Access levels: constructors"); code_v11("class A { constructor() { } } return new A()").equals("A {}"); code_v11("class A { public constructor() { } } return new A()").equals("A {}"); - code_v11("class A { protected constructor() { } } return new A()").error(); - code_v11("class A { private constructor() { } } return new A()").error(); + code_v11("class A { protected constructor() { } } return new A()").error(Error.PROTECTED_CONSTRUCTOR); + code_v11("class A { private constructor() { } } return new A()").error(Error.PRIVATE_CONSTRUCTOR); code_v11("class A { public constructor() { } } class B extends A {} return new B()").equals("B {}"); code_v11("class A { x protected constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").equals("10"); - code_v11("class A { x private constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").error(); + code_v11("class A { x private constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").error(Error.PRIVATE_CONSTRUCTOR); code_v11("class A { private constructor() { } } class B extends A {} return new B()").equals("B {}"); section("Access levels: static methods"); code_v11("class A { static m() { return 10 } } return A.m()").equals("10"); code_v11("class A { public static m() { return 10 } } return A.m()").equals("10"); - code_v11("class A { protected static m() { return 10 } } return A.m()").error(); - code_v11("class A { private static m() { return 10 } } return A.m()").error(); + code_v11("class A { protected static m() { return 10 } } return A.m()").error(Error.PROTECTED_STATIC_METHOD); + code_v11("class A { private static m() { return 10 } } return A.m()").error(Error.PRIVATE_STATIC_METHOD); code_v11("class A { public static m() { return 10 } } class B extends A {} return B.m()").equals("10"); - code_v11("class A { protected static m() { return 10 } } class B extends A {} return B.m()").error(); - code_v11("class A { private static m() { return 10 } } class B extends A {} return B.m()").error(); + code_v11("class A { protected static m() { return 10 } } class B extends A {} return B.m()").error(Error.PROTECTED_STATIC_METHOD); + code_v11("class A { private static m() { return 10 } } class B extends A {} return B.m()").error(Error.PRIVATE_STATIC_METHOD); section("Initialization of fields"); code_v11("class A { x = [1, 2, 3] } var a = new A() return a.x").equals("[1, 2, 3]"); diff --git a/src/test/java/test/TestOperators.java b/src/test/java/test/TestOperators.java index d7e49330..a09d7182 100644 --- a/src/test/java/test/TestOperators.java +++ b/src/test/java/test/TestOperators.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; +import leekscript.common.Error; public class TestOperators extends TestCommon { @@ -195,14 +196,14 @@ public void run() throws Exception { for (var operator : operators) { String expected = actualResults[r++]; var c = code_v10("var a = " + value1 + " return a " + operator + " " + value2); - if (expected.equals("error")) result = c.error(); + if (expected.equals("error")) result = c.error(Error.INVALID_OPERATOR); else result = c.equals(expected); results.add("\"" + result + "\""); } for (var operator : assignmentOperators) { String expected = actualResults[r++]; var c = code_v10("var a = " + value1 + " a " + operator + " " + value2 + " return a"); - if (expected.equals("error")) result = c.error(); + if (expected.equals("error")) result = c.error(Error.INVALID_OPERATOR); else result = c.equals(expected); results.add("\"" + result + "\""); } From f21cd639a58d9c5409eb78c056d5f25078de5153 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 241/319] [foreach] Fix --- .../java/leekscript/compiler/bloc/ForeachKeyBlock.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java index f7f93da4..bbca7543 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java @@ -36,17 +36,17 @@ public ForeachKeyBlock(AbstractLeekBlock parent, MainLeekBlock main, boolean isK public void setValueIterator(WordCompiler compiler, IAWord iterator, boolean declaration) { if (declaration) { iteratorDeclaration = new LeekVariableDeclarationInstruction(compiler, iterator, 0, null, compiler.getCurrentFunction()); - addVariable(new LeekVariable(iterator, VariableType.ITERATOR, iteratorDeclaration)); + // addVariable(new LeekVariable(iterator, VariableType.ITERATOR, iteratorDeclaration)); } - mIterator = iterator.getWord(); + mIterator = iterator; } public void setKeyIterator(WordCompiler compiler, IAWord iterator, boolean declaration) { if (declaration) { iteratorKeyDeclaration = new LeekVariableDeclarationInstruction(compiler, iterator, 0, null, compiler.getCurrentFunction()); - addVariable(new LeekVariable(iterator, VariableType.ITERATOR, iteratorKeyDeclaration)); + // addVariable(new LeekVariable(iterator, VariableType.ITERATOR, iteratorKeyDeclaration)); } - mKeyIterator = iterator.getWord(); + mKeyIterator = iterator; } public void setArray(AbstractExpression exp) { From 5e7594a2d7b25ae8acd5a597102bbc8eaf356bfc Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 242/319] [function] Fix static method access --- .../leekscript/compiler/expression/LeekExpressionFunction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 6c69b962..4b9a36d7 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -230,7 +230,7 @@ public void analyze(WordCompiler compiler) { compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.UNKNOWN_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); } else if (staticMethod.level == AccessLevel.PRIVATE && clazz != compiler.getCurrentClass()) { compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.PRIVATE_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); - } else if (staticMethod.level == AccessLevel.PROTECTED && !compiler.getCurrentClass().descendsFrom(clazz)) { + } else if (staticMethod.level == AccessLevel.PROTECTED && (compiler.getCurrentClass() == null || !compiler.getCurrentClass().descendsFrom(clazz))) { compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.PROTECTED_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); } } From 2ae9a27b8d42d36aa8ddb56723f9773789bca8ee Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 243/319] [test] Disable null instruction test --- src/test/java/test/TestNumber.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/test/TestNumber.java b/src/test/java/test/TestNumber.java index fbeb5b3c..d3b58d14 100644 --- a/src/test/java/test/TestNumber.java +++ b/src/test/java/test/TestNumber.java @@ -608,7 +608,7 @@ public void run() throws Exception { section("Not a statement errors"); code("null; return null;").equals("null"); code("(null); return null;").equals("null"); - code("((null)); return null;").equals("null"); + DISABLED_code("((null)); return null;").equals("null"); code("true; return null;").equals("null"); code("false; return null;").equals("null"); code("'salut'; return null;").equals("null"); From ac171b64c9b477179dfd3632ab7a76f59f811d9f Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 244/319] [foreach] Fix --- src/main/java/leekscript/compiler/bloc/ForeachBlock.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java index 2f2299c4..707a9460 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java @@ -92,6 +92,7 @@ public void analyze(WordCompiler compiler) { if (v == null) { compiler.addError(new AnalyzeError(mIterator, AnalyzeErrorLevel.ERROR, Error.UNKNOWN_VARIABLE_OR_FUNCTION)); } + declaration.setFunction(compiler.getCurrentFunction()); } mArray.analyze(compiler); compiler.setCurrentBlock(initialBlock); From c90e183019212955c2f27cbe542bd4e478fbb35c Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 245/319] [test] Fix ops --- src/test/java/test/TestCommon.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index cec5176d..6083c320 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -110,7 +110,6 @@ public String run_version(int version, Checker checker) { Result result; long compile_time = 0; long ops = 0; - LeekScript.getRandom().seed(123456789); try { boolean is_file = code.contains(".leek"); From 10a2f6e56eccf09622009c85448cd3d21b3faf6f Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 246/319] [test] Add more tests --- src/test/java/test/TestFunction.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index 17b20875..e8ad7d29 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -149,5 +149,6 @@ public void run() { code("var m = ['A', 'T', 'C', 'G'] var count = 0 var adn = '' for (var j = 0; j < 200; j++) { adn += m[randInt(0, 4)] } var c = contains(adn, 'GAGA'); if (c) count++").equals("null"); code("var m = ['A', 'T', 'C', 'G'] var count = 0 var tests = 500 for (var k = 0; k < tests; k++) { var adn = '' for (var j = 0; j < 200; j++) { adn += m[randInt(0, 4)] } var c = contains(adn, 'GAGA'); if (c) count++ }").equals("null"); code("var m = ['A', 'T', 'C', 'G'] var count = 0 var tests = 500 for (var k = 0; k < tests; k++) { var adn = '' for (var j = 0; j < 200; j++) { adn += m[randInt(0, 4)] } var c = contains(adn, 'GAGA'); if (c) count++ } return abs(100 * (count / tests) - 52) < 12;").equals("true"); + code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; push(copy[1], @[item, cost, 1]); copy[0] += cost; aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("44"); } } From 5119d24f1d493303c0f77537cb26ca4891cd45fe Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 247/319] [test] Add more tests --- src/test/java/test/TestNumber.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/test/TestNumber.java b/src/test/java/test/TestNumber.java index d3b58d14..fbeb5b3c 100644 --- a/src/test/java/test/TestNumber.java +++ b/src/test/java/test/TestNumber.java @@ -608,7 +608,7 @@ public void run() throws Exception { section("Not a statement errors"); code("null; return null;").equals("null"); code("(null); return null;").equals("null"); - DISABLED_code("((null)); return null;").equals("null"); + code("((null)); return null;").equals("null"); code("true; return null;").equals("null"); code("false; return null;").equals("null"); code("'salut'; return null;").equals("null"); From 59bbe0e2fc3e1e68ad0bbef29a98027256db733c Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 248/319] [array] Optimize size --- src/main/java/leekscript/runner/PhpArray.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index bf83433b..a5cc9810 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -684,8 +684,8 @@ public AbstractLeekValue getOrCreate(AI ai, Object key) throws LeekRunException if (e == null) { if (mSize >= capacity) { growCapacity(ai); + mSize++; } - mSize++; e = createElement(ai, key, LeekValueManager.NULL); pushElement(e); } From 8850e82b7de0217f4845f50e3f34245c7ee54613 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 249/319] [operator] Fix minus operator ops --- .../leekscript/compiler/expression/LeekExpression.java | 9 +++++++-- .../java/leekscript/runner/values/DoubleLeekValue.java | 4 ++++ src/main/java/leekscript/runner/values/IntLeekValue.java | 4 ++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index b3eeb650..8cb3a1c6 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -621,8 +621,13 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(".bnot(mUAI)"); return; case Operators.UNARY_MINUS: - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(".opposite(mUAI)"); + if (mExpression2 instanceof LeekNumber) { + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(".oppositeConstant()"); + } else { + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(".opposite(mUAI)"); + } return; case Operators.NEW: mExpression2.writeJavaCode(mainblock, writer); diff --git a/src/main/java/leekscript/runner/values/DoubleLeekValue.java b/src/main/java/leekscript/runner/values/DoubleLeekValue.java index 6e5465e8..a58a6373 100644 --- a/src/main/java/leekscript/runner/values/DoubleLeekValue.java +++ b/src/main/java/leekscript/runner/values/DoubleLeekValue.java @@ -48,6 +48,10 @@ public boolean isNumeric() { return true; } + public AbstractLeekValue oppositeConstant() throws LeekRunException { + return LeekValueManager.getLeekDoubleValue(-mValue); + } + @Override public AbstractLeekValue increment(AI ai) throws LeekRunException { ai.addOperations(ADD_COST); diff --git a/src/main/java/leekscript/runner/values/IntLeekValue.java b/src/main/java/leekscript/runner/values/IntLeekValue.java index b4194f0d..24aff3eb 100644 --- a/src/main/java/leekscript/runner/values/IntLeekValue.java +++ b/src/main/java/leekscript/runner/values/IntLeekValue.java @@ -46,6 +46,10 @@ public boolean isNumeric() { return true; } + public IntLeekValue oppositeConstant() throws LeekRunException { + return LeekValueManager.getLeekIntValue(-mValue); + } + @Override public AbstractLeekValue increment(AI ai) { return this; From 91baa658e616eb4a290c96e555f434523b683009 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 19 Jun 2021 13:38:08 +0200 Subject: [PATCH 250/319] [leekscript] Improve code generation --- src/main/java/leekscript/TopLevel.java | 20 +- .../java/leekscript/compiler/JavaWriter.java | 69 +- .../java/leekscript/compiler/LeekScript.java | 4 +- .../compiler/bloc/AnonymousFunctionBlock.java | 34 +- .../compiler/bloc/ClassMethodBlock.java | 6 +- .../compiler/bloc/ConditionalBloc.java | 25 +- .../compiler/bloc/DoWhileBlock.java | 17 +- .../leekscript/compiler/bloc/ForBlock.java | 18 +- .../compiler/bloc/ForeachBlock.java | 57 +- .../compiler/bloc/ForeachKeyBlock.java | 102 +- .../compiler/bloc/FunctionBlock.java | 30 +- .../compiler/bloc/MainLeekBlock.java | 117 +- .../leekscript/compiler/bloc/WhileBlock.java | 16 +- .../expression/AbstractExpression.java | 102 ++ .../compiler/expression/LeekArray.java | 12 +- .../compiler/expression/LeekBoolean.java | 2 +- .../compiler/expression/LeekExpression.java | 388 +++-- .../expression/LeekExpressionFunction.java | 114 +- .../compiler/expression/LeekNull.java | 2 +- .../compiler/expression/LeekNumber.java | 6 +- .../compiler/expression/LeekObjectAccess.java | 90 +- .../compiler/expression/LeekParenthesis.java | 2 + .../compiler/expression/LeekString.java | 4 +- .../compiler/expression/LeekTabularValue.java | 208 ++- .../compiler/expression/LeekTernaire.java | 15 +- .../compiler/expression/LeekVariable.java | 680 +++++++- .../ClassDeclarationInstruction.java | 153 +- .../LeekExpressionInstruction.java | 41 +- .../LeekGlobalDeclarationInstruction.java | 21 +- .../instruction/LeekReturnInstruction.java | 22 +- .../LeekVariableDeclarationInstruction.java | 86 +- src/main/java/leekscript/runner/AI.java | 1282 ++++++++++++-- .../java/leekscript/runner/ILeekFunction.java | 7 +- .../runner/LeekAnonymousFunction.java | 4 +- .../java/leekscript/runner/LeekFunction.java | 6 + .../java/leekscript/runner/LeekFunctions.java | 1534 ++++++----------- .../leekscript/runner/LeekOperations.java | 291 +--- .../leekscript/runner/LeekRunException.java | 1 + .../runner/LeekValueComparator.java | 51 +- .../leekscript/runner/LeekValueManager.java | 258 ++- src/main/java/leekscript/runner/PhpArray.java | 230 +-- src/main/java/leekscript/runner/Wrapper.java | 73 + .../runner/values/AbstractLeekValue.java | 310 ---- .../runner/values/ArrayLeekValue.java | 344 ++-- .../runner/values/BooleanLeekValue.java | 128 -- .../java/leekscript/runner/values/Box.java | 245 +++ .../runner/values/ClassLeekValue.java | 179 +- .../runner/values/DoubleLeekValue.java | 217 --- .../runner/values/FunctionLeekValue.java | 76 +- .../runner/values/IntLeekValue.java | 239 --- .../runner/values/NullLeekValue.java | 107 -- .../runner/values/ObjectLeekValue.java | 179 +- .../runner/values/ObjectVariableValue.java | 4 +- .../values/PhpArrayVariableLeekValue.java | 26 - .../runner/values/ReferenceLeekValue.java | 214 --- .../runner/values/StringLeekValue.java | 174 -- .../runner/values/VariableLeekValue.java | 316 ---- src/test/java/test/TestAI.java | 5 +- src/test/java/test/TestCommon.java | 34 +- src/test/java/test/TestMain.java | 4 +- 60 files changed, 4806 insertions(+), 4195 deletions(-) create mode 100644 src/main/java/leekscript/runner/LeekFunction.java create mode 100644 src/main/java/leekscript/runner/Wrapper.java delete mode 100644 src/main/java/leekscript/runner/values/AbstractLeekValue.java delete mode 100644 src/main/java/leekscript/runner/values/BooleanLeekValue.java create mode 100644 src/main/java/leekscript/runner/values/Box.java delete mode 100644 src/main/java/leekscript/runner/values/DoubleLeekValue.java delete mode 100644 src/main/java/leekscript/runner/values/IntLeekValue.java delete mode 100644 src/main/java/leekscript/runner/values/NullLeekValue.java delete mode 100644 src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java delete mode 100644 src/main/java/leekscript/runner/values/ReferenceLeekValue.java delete mode 100644 src/main/java/leekscript/runner/values/StringLeekValue.java delete mode 100644 src/main/java/leekscript/runner/values/VariableLeekValue.java diff --git a/src/main/java/leekscript/TopLevel.java b/src/main/java/leekscript/TopLevel.java index 9a39b8bd..99636c13 100644 --- a/src/main/java/leekscript/TopLevel.java +++ b/src/main/java/leekscript/TopLevel.java @@ -11,13 +11,13 @@ public class TopLevel { public static void main(String[] args) { if (args.length < 1) { Scanner input = new Scanner(System.in); - System.out.print(">>> "); - String code; - while ((code = input.nextLine()) != null) { - executeSnippet(code); - System.out.print(">>> "); + System.out.print(">>> "); + String code; + while ((code = input.nextLine()) != null) { + executeSnippet(code); + System.out.print(">>> "); } - input.close(); + input.close(); } else { File file = new File(args[0]); @@ -39,8 +39,8 @@ private static void executeSnippet(String code) { var v = ai.runIA(); long executionTime = System.currentTimeMillis() - et; - String result = v.getString(ai); - long ops = ai.getOperations(); + var result = ai.string(v); + long ops = ai.operations(); System.out.println(result); System.out.println("(" + ops + " ops, " + compileTime + "ms + " + executionTime + "ms)"); @@ -60,8 +60,8 @@ private static void executeFile(File file) { var v = ai.runIA(); long executionTime = System.currentTimeMillis() - et; - String result = v.getString(ai); - long ops = ai.getOperations(); + var result = ai.string(v); + long ops = ai.operations(); System.out.println(result); System.out.println("(" + ops + " ops, " + compileTime + "ms + " + executionTime + "ms)"); diff --git a/src/main/java/leekscript/compiler/JavaWriter.java b/src/main/java/leekscript/compiler/JavaWriter.java index bfea8ba2..35d14618 100644 --- a/src/main/java/leekscript/compiler/JavaWriter.java +++ b/src/main/java/leekscript/compiler/JavaWriter.java @@ -8,6 +8,9 @@ import com.alibaba.fastjson.JSONArray; import leekscript.compiler.bloc.AbstractLeekBlock; +import leekscript.common.Type; +import leekscript.compiler.bloc.MainLeekBlock; +import leekscript.compiler.expression.AbstractExpression; public class JavaWriter { private final StringBuilder mCode; @@ -101,8 +104,8 @@ public void writeErrorFunction(IACompiler comp, String ai) { mCode.append("};}\n"); } - public void addCounter(int id) { - addCode("mUAI.addOperations(1);"); + public void addCounter(int count) { + addCode("ops(" + count + ");"); } public int getCurrentLine() { @@ -113,4 +116,66 @@ public void addPosition(IAWord token) { var index = getFileIndex(token.getAI()); mLines.put(mLine, new Line(mLine, token.getLine(), index)); } + + public String getAIThis() { + return className + ".this"; + } + + public String getClassName() { + return className; + } + + public void getBoolean(MainLeekBlock mainblock, AbstractExpression expression) { + if (expression.getType() == Type.BOOL) { + expression.writeJavaCode(mainblock, this); + } else if (expression.getType() == Type.INT) { + addCode("(("); + expression.writeJavaCode(mainblock, this); + addCode(") != 0)"); + } else { + addCode("bool("); + expression.writeJavaCode(mainblock, this); + addCode(")"); + } + } + + public void getString(MainLeekBlock mainblock, AbstractExpression expression) { + if (expression.getType() == Type.STRING) { + expression.writeJavaCode(mainblock, this); + } else { + addCode("string("); + expression.writeJavaCode(mainblock, this); + addCode(")"); + } + } + + public void getInt(MainLeekBlock mainblock, AbstractExpression expression) { + if (expression.getType() == Type.INT) { + expression.writeJavaCode(mainblock, this); + } else { + addCode("integer("); + expression.writeJavaCode(mainblock, this); + addCode(")"); + } + } + + public void compileLoad(MainLeekBlock mainblock, AbstractExpression expr) { + if (expr.getType() == Type.NULL || expr.getType() == Type.BOOL || expr.getType().isNumber() || expr.getType() == Type.STRING || expr.getType() == Type.ARRAY) { + expr.writeJavaCode(mainblock, this); + } else { + addCode("load("); + expr.writeJavaCode(mainblock, this); + addCode(")"); + } + } + + public void compileClone(MainLeekBlock mainblock, AbstractExpression expr) { + if (expr.getType() == Type.NULL || expr.getType() == Type.BOOL || expr.getType().isNumber() || expr.getType() == Type.STRING) { + expr.writeJavaCode(mainblock, this); + } else { + addCode("copy("); + expr.writeJavaCode(mainblock, this); + addCode(")"); + } + } } diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 52396038..04772f64 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -116,8 +116,8 @@ public static Object runScript(String script, boolean nocache) throws Exception public static String runFile(String filename) throws Exception { AI ai = LeekScript.compileFile(filename, "AI", true); var v = ai.runIA(); - System.out.println(v.getString(ai)); - return v.getString(ai); + System.out.println(ai.string(v)); + return ai.string(v); } public static void setResolver(Resolver resolver) { diff --git a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java index 08d02486..aa518189 100644 --- a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java @@ -84,23 +84,45 @@ public void checkEndBlock() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { + var previousFunction = mainblock.getWordCompiler().getCurrentFunction(); + mainblock.getWordCompiler().setCurrentFunction(this); StringBuilder sb = new StringBuilder(); sb.append("new LeekAnonymousFunction() {"); - sb.append("public AbstractLeekValue run(AI mUAI, AbstractLeekValue thiz, AbstractLeekValue... values) throws LeekRunException {"); + sb.append("public Object run(ObjectLeekValue thiz, Object... values) throws LeekRunException {"); for (int i = 0; i < mParameters.size(); i++) { - sb.append("final VariableLeekValue user_").append(mParameters.get(i)).append(" = "); - if (mReferences.get(i)) { - sb.append("(values[").append(i).append("] instanceof VariableLeekValue)?(VariableLeekValue)values[").append(i).append("]:"); + var parameter = mParameters.get(i); + var declaration = mParameterDeclarations.get(i); + if (declaration.isCaptured()) { + sb.append("final var u_").append(parameter).append(" = new Wrapper("); + if (mReferences.get(i)) { + sb.append("(values[").append(i).append("] instanceof Box) ? (Box) values[").append(i).append("] : "); + } + sb.append("new Box(" + writer.getAIThis() + ", "); + sb.append("values[").append(i).append("]));"); + } else { + sb.append("var u_").append(parameter).append(" = "); + + if (mainblock.getWordCompiler().getVersion() >= 11) { + sb.append("values[").append(i).append("]; ops(1);"); + } else { + // In LeekScript 1.0, load the value or reference + if (mReferences.get(i)) { + sb.append("values[").append(i).append("] instanceof Box ? (Box) values[").append(i).append("] : new Box(" + writer.getAIThis() + ", load(values[").append(i).append("]));"); + } else { + // sb.append("new Box(" + writer.getAIThis() + ", values[").append(i).append("] instanceof Box ? copy(load(values[").append(i).append("])) : copy(load(values[").append(i).append("])));"); + sb.append("new Box(" + writer.getAIThis() + ", values[").append(i).append("]);"); + } + } } - sb.append("new VariableLeekValue(mUAI, values[").append(i).append("].getValue());"); } writer.addLine(sb.toString(), mLine, mAI); writer.addCounter(1); super.writeJavaCode(mainblock, writer); if (mEndInstruction == 0) - writer.addLine("return LeekValueManager.NULL;"); + writer.addLine("return null;"); writer.addCode("}}"); + mainblock.getWordCompiler().setCurrentFunction(previousFunction); } public boolean isReference(int i) { diff --git a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java index 4ce96068..0813b4f1 100644 --- a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java @@ -95,16 +95,12 @@ public void checkEndBlock() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - for (int i = 0; i < mParameters.size(); i++) { - writer.addCode("final VariableLeekValue user_" + mParameters.get(i) + " = "); - writer.addLine("new VariableLeekValue(mUAI, values[" + i + "].getValue());"); - } writer.addLine("", mLine, mAI); super.writeJavaCode(mainblock, writer); if (mEndInstruction == 0) { if (isStatic) { - writer.addLine("return LeekValueManager.NULL;"); + writer.addLine("return null;"); } else { writer.addLine("return u_this;"); } diff --git a/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java b/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java index 3a1eefbc..642102c5 100644 --- a/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java +++ b/src/main/java/leekscript/compiler/bloc/ConditionalBloc.java @@ -44,19 +44,22 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if(mParentCondition == null){ - writer.addCode("if("); - mCondition.writeJavaCode(mainblock, writer); - writer.addLine(".getBoolean()){", mLine, mAI); + if (mParentCondition == null) { + writer.addCode("if ("); + writer.addCode("ops("); + writer.getBoolean(mainblock, mCondition); + writer.addCode(", " + mCondition.getOperations()); + writer.addLine(")) {", mLine, mAI); + } else if (mCondition != null) { + writer.addCode("else if ("); + writer.addCode("ops("); + writer.getBoolean(mainblock, mCondition); + writer.addCode(", " + mCondition.getOperations()); + writer.addLine(")) {", mLine, mAI); } - else if(mCondition != null){ - writer.addCode("else if("); - mCondition.writeJavaCode(mainblock, writer); - writer.addLine(".getBoolean()){", mLine, mAI); - } - else writer.addLine("else{", mLine, mAI); + else writer.addLine("else {", mLine, mAI); super.writeJavaCode(mainblock, writer); - if(mEndInstruction == 0) writer.addCounter(1); + if (mEndInstruction == 0) writer.addCounter(1); writer.addLine("}"); } diff --git a/src/main/java/leekscript/compiler/bloc/DoWhileBlock.java b/src/main/java/leekscript/compiler/bloc/DoWhileBlock.java index 53a521c6..938fea0a 100644 --- a/src/main/java/leekscript/compiler/bloc/DoWhileBlock.java +++ b/src/main/java/leekscript/compiler/bloc/DoWhileBlock.java @@ -4,6 +4,7 @@ import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.expression.AbstractExpression; +import leekscript.compiler.expression.LeekBoolean; public class DoWhileBlock extends AbstractLeekBlock { @@ -28,12 +29,20 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addLine("do{"); + writer.addLine("do {"); writer.addCounter(1); super.writeJavaCode(mainblock, writer); - writer.addCode("}while("); - mCondition.writeJavaCode(mainblock, writer); - writer.addLine(".getBoolean());", mLine, mAI); + writer.addCode("} while (ops("); + // Prevent unreachable code error + if (mCondition instanceof LeekBoolean) { + writer.addCode("bool("); + writer.getBoolean(mainblock, mCondition); + writer.addCode(")"); + } else { + writer.getBoolean(mainblock, mCondition); + } + writer.addCode(", " + mCondition.getOperations() + ")"); + writer.addLine(");", mLine, mAI); } @Override diff --git a/src/main/java/leekscript/compiler/bloc/ForBlock.java b/src/main/java/leekscript/compiler/bloc/ForBlock.java index 16fb56bc..62852e41 100644 --- a/src/main/java/leekscript/compiler/bloc/ForBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForBlock.java @@ -5,6 +5,7 @@ import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.expression.AbstractExpression; +import leekscript.compiler.expression.LeekBoolean; import leekscript.compiler.expression.LeekExpression; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.Operators; @@ -53,12 +54,21 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addLine("for(", mLine, mAI); + writer.addCode("for ("); mInitialisation.writeJavaCode(mainblock, writer); - mCondition.writeJavaCode(mainblock, writer); - writer.addCode(".getBoolean();"); + + writer.addCode("ops("); + // Prevent unreachable code error + if (mCondition instanceof LeekBoolean) { + writer.addCode("bool("); + writer.getBoolean(mainblock, mCondition); + writer.addCode(")"); + } else { + writer.getBoolean(mainblock, mCondition); + } + writer.addCode(", " + mCondition.getOperations() + "); ops("); mIncrementation.writeJavaCode(mainblock, writer); - writer.addLine("){", mLine, mAI); + writer.addLine(", " + mIncrementation.getOperations() + ")) {", mLine, mAI); writer.addCounter(1); super.writeJavaCode(mainblock, writer); writer.addLine("}"); diff --git a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java index 707a9460..adec9677 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java @@ -44,22 +44,55 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - //On prend un nombre unique pour les noms de variables temporaires + // On prend un nombre unique pour les noms de variables temporaires int block_count = getCount(); String var = "i" + block_count; String ar = "ar" + block_count; - String iterator_name = mainblock.hasGlobal(mIterator.getWord()) ? ("globale_" + mIterator) : "user_" + mIterator; - - writer.addCode("final AbstractLeekValue " + ar + " = "); - mArray.writeJavaCode(mainblock, writer); - writer.addLine(".getValue();", mLine, mAI); - writer.addLine("if(" + ar + ".isArrayForIteration(mUAI)){"); - if(mIsDeclaration) writer.addLine("final VariableLeekValue " + iterator_name + " = new VariableLeekValue(mUAI, LeekValueManager.NULL);"); - else writer.addLine(iterator_name + ".set(mUAI, LeekValueManager.NULL);"); - if (mReference || mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { - writer.addLine("for(AbstractLeekValue " + var + " : " + ar + ".getArray()){ " + iterator_name + ".setRef(mUAI, " + var + ");"); + String iterator_name = mainblock.hasGlobal(mIterator.getWord()) ? ("g_" + mIterator) : "u_" + mIterator; + + // Container + writer.addCode("final var " + ar + " = "); + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + mArray.writeJavaCode(mainblock, writer); + } else { + writer.compileLoad(mainblock, mArray); + } + writer.addCode(";"); + + writer.addLine("if (isIterable(" + ar + ")) {"); + if (mIsDeclaration) { + if (mIsDeclaration && declaration.isCaptured()) { + writer.addCode("final Wrapper " + iterator_name + " = new Wrapper(new Box(" + writer.getAIThis() + ", null));"); + } else if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + writer.addLine("Object " + iterator_name + " = null;"); + writer.addCounter(1); + } else { + writer.addLine("var " + iterator_name + " = new Box(" + writer.getAIThis() + ", null);"); + } } else { - writer.addLine("for(AbstractLeekValue " + var + " : " + ar + ".getArray()){ " + iterator_name + ".set(mUAI, " + var + ".getValue());"); + writer.addCounter(1); + } + writer.addLine("for (var " + var + " : (ArrayLeekValue) " + ar + ") {\n"); + + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + if (mIsDeclaration && declaration.isCaptured()) { + writer.addLine(iterator_name + ".set(" + var + ".getValue());"); + } else if (mReference) { + writer.addLine(iterator_name + " = " + var + ".getValue();"); + writer.addCounter(1); + } else { + writer.addLine(iterator_name + " = " + var + ".getValue();"); + } + } else { + if (mReference) { + writer.addCode(iterator_name + ".set(" + var + ".getValue());"); + } else if (mIsDeclaration && declaration.isCaptured()) { + writer.addLine(iterator_name + ".set(" + var + ".getValue());"); + writer.addCounter(1); + } else { + writer.addLine(iterator_name + ".set(" + var + ".getValue());"); + writer.addCounter(1); + } } writer.addCounter(1); super.writeJavaCode(mainblock, writer); diff --git a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java index bbca7543..1c865e36 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java @@ -60,46 +60,96 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - //On prend un nombre unique pour les noms de variables temporaires + // On prend un nombre unique pour les noms de variables temporaires int block_count = getCount(); String var = "i" + block_count; String ar = "ar" + block_count; - String key_iterator = mainblock.hasGlobal(mKeyIterator.getWord()) ? ("globale_" + mKeyIterator) : ("user_" + mKeyIterator); - String val_iterator = mainblock.hasGlobal(mIterator.getWord()) ? ("globale_" + mIterator) : ("user_" + mIterator); - writer.addCode("final AbstractLeekValue " + ar + " = "); - mArray.writeJavaCode(mainblock, writer); - writer.addCode(".getValue();"); + String key_iterator = mainblock.hasGlobal(mKeyIterator.getWord()) ? ("g_" + mKeyIterator) : ("u_" + mKeyIterator); + String val_iterator = mainblock.hasGlobal(mIterator.getWord()) ? ("g_" + mIterator) : ("u_" + mIterator); + + // Container + writer.addCode("final var " + ar + " = "); + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + mArray.writeJavaCode(mainblock, writer); + } else { + writer.compileLoad(mainblock, mArray); + } + writer.addCode(";"); + StringBuilder sb = new StringBuilder(); - sb.append("if(").append(ar).append(".isArrayForIteration(mUAI)){"); - //Clé - if(mIsKeyDeclaration) sb.append("final VariableLeekValue ").append(key_iterator).append(" = new VariableLeekValue(mUAI, LeekValueManager.NULL);"); - else sb.append(key_iterator).append(".set(mUAI, LeekValueManager.NULL);"); - //Valeur - if(mIsDeclaration) sb.append("final VariableLeekValue ").append(val_iterator).append(" = new VariableLeekValue(mUAI, LeekValueManager.NULL);"); - else sb.append(val_iterator).append(".set(mUAI, LeekValueManager.NULL);"); - //On fait le parcours - //Déclaration de la variable - sb.append("ArrayLeekValue.ArrayIterator ").append(var).append("=").append(ar).append(".getArray().getArrayIterator();"); - sb.append("while(!").append(var).append(".ended()){ mUAI.addOperations(1); "); - //Maj des variables - if (mKeyReference || mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { - sb.append(key_iterator).append(".setRef(mUAI, ").append(var).append(".getKeyRef());"); + sb.append("if (isIterable(").append(ar).append(")) {"); + // Clé + if (mIsKeyDeclaration) { + if (iteratorKeyDeclaration.isCaptured()) { + sb.append("final Wrapper " + key_iterator + " = new Wrapper(new Box(" + writer.getAIThis() + ", null));"); + } else if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10) { + sb.append("var " + key_iterator + " = new Box(" + writer.getAIThis() + ", null);"); + } else { + sb.append("Object ").append(key_iterator).append(" = null; ops(1); "); + } + } else { + sb.append("ops(1);"); + } + // Valeur + if (mIsDeclaration) { + if (iteratorDeclaration.isCaptured()) { + sb.append("final Wrapper " + val_iterator + " = new Wrapper(new Box(" + writer.getAIThis() + ", null));"); + } else if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + sb.append("Object " + val_iterator + " = null; ops(1);"); + } else if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10 || (iteratorDeclaration != null && iteratorDeclaration.isCaptured())) { + sb.append("var " + val_iterator + " = new Box(" + writer.getAIThis() + ", null);"); + } else { + sb.append("Object ").append(val_iterator).append(" = null; ops(1);"); + } } else { - sb.append(key_iterator).append(".set(mUAI, ").append(var).append(".getKeyRef());"); + sb.append("ops(1);"); } - if (mValueReference || mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { - sb.append(val_iterator).append(".setRef(mUAI, ").append(var).append(".getValueRef());"); + // On fait le parcours + // Déclaration de la variable + sb.append("var ").append(var).append(" = ((ArrayLeekValue) ").append(ar).append(").getArrayIterator(); "); + sb.append("while (!").append(var).append(".ended()) { ops(1); "); + // Maj de la clé + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + if (mIsKeyDeclaration && iteratorKeyDeclaration.isCaptured()) { + sb.append(key_iterator).append(".set(").append(var).append(".getKeyRef());"); + } else { + sb.append(key_iterator).append(" = ").append(var).append(".getKeyRef();"); + } } else { - sb.append(val_iterator).append(".set(mUAI, ").append(var).append(".getValueRef());"); + if (mIsKeyDeclaration && iteratorKeyDeclaration.isCaptured()) { + sb.append(key_iterator).append(".set(").append(var).append(".getKeyRef()); ops(1); "); + } else if (mKeyReference) { + sb.append(key_iterator).append(".set(").append(var).append(".getKeyRef());"); + } else { + sb.append(key_iterator).append(".set(").append(var).append(".getKeyRef()); ops(1); "); + } + } + // Maj de la valeur + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + if (mValueReference) { + sb.append(val_iterator).append(" = ").append(var).append(".value();"); + } else if (mIsDeclaration && iteratorDeclaration.isCaptured()) { + sb.append(val_iterator).append(".set(").append(var).append(".value());"); + } else { + sb.append(val_iterator).append(" = ").append(var).append(".value();"); + } + } else { + if (mValueReference) { + sb.append(val_iterator).append(".set(").append(var).append(".value());"); + } else if (mIsDeclaration && iteratorDeclaration.isCaptured()) { + sb.append(val_iterator).append(".set(").append(var).append(".value()); ops(1);"); + } else { + sb.append(val_iterator).append(".set(").append(var).append(".value()); ops(1);"); + } } sb.append(var).append(".next();"); writer.addLine(sb.toString(), mLine, mAI); - //Instructions + // Instructions super.writeJavaCode(mainblock, writer); - //Fin + // Fin writer.addLine("}}"); } diff --git a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java index 3dde0260..15cc3bbe 100644 --- a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java @@ -89,25 +89,40 @@ public void checkEndBlock() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { StringBuilder sb = new StringBuilder(); - sb.append("private AbstractLeekValue user_function_").append(token.getWord()).append("("); + sb.append("private Object f_").append(token.getWord()).append("("); for (int i = 0; i < mParameters.size(); i++) { if (i != 0) sb.append(", "); - sb.append("AbstractLeekValue param_").append(mParameters.get(i)); + sb.append("Object p_").append(mParameters.get(i)); } sb.append(") throws LeekRunException {"); for (int i = 0; i < mParameters.size(); i++) { - sb.append("final VariableLeekValue user_").append(mParameters.get(i)).append(" = "); - if (mReferences.get(i)) { - sb.append("(param_").append(mParameters.get(i)).append(" instanceof VariableLeekValue)?(VariableLeekValue)param_").append(mParameters.get(i)).append(":"); + var parameter = mParameters.get(i); + var declaration = mParameterDeclarations.get(i); + if (declaration.isCaptured()) { + sb.append("final var u_").append(parameter).append(" = new Wrapper("); + if (mReferences.get(i)) { + sb.append("(p_").append(parameter).append(" instanceof Box) ? (Box) p_").append(parameter).append(" : "); + } + sb.append("new Box(" + writer.getAIThis() + ", "); + sb.append("copy(p_").append(parameter).append(")));"); + } else { + sb.append("var u_").append(parameter).append(" = "); + if (mReferences.get(i)) { + sb.append("(p_").append(parameter).append(" instanceof Box) ? (Box) p_").append(parameter).append(" : "); + } + if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10) { + sb.append("new Box(" + writer.getAIThis() + ", copy(p_").append(parameter).append("));"); + } else { + sb.append("p_").append(parameter).append("; ops(1); "); + } } - sb.append("new VariableLeekValue(this, param_").append(mParameters.get(i)).append(".getValue());"); } writer.addLine(sb.toString(), mLine, mAI); writer.addCounter(1); super.writeJavaCode(mainblock, writer); if (mEndInstruction == 0) - writer.addLine("return LeekValueManager.NULL;"); + writer.addLine("return null;"); writer.addLine("}"); } @@ -118,7 +133,6 @@ public boolean isReference(int i) { public void declare(WordCompiler compiler) { // On ajoute la fonction compiler.getCurrentBlock().addVariable(new LeekVariable(token, VariableType.FUNCTION)); - // System.out.println("Declare function " + token.getWord()); } public String toString() { diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index dc575c22..d5bf2ae6 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -204,12 +204,16 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { // Variables globales for (String global : mGlobales) { - writer.addLine("private AbstractLeekValue globale_" + global + " = LeekValueManager.NULL;"); - writer.addLine("private boolean globale_init_" + global + " = false;"); + if (getWordCompiler().getVersion() >= 11) { + writer.addLine("private Object g_" + global + " = null;"); + } else { + writer.addLine("private Box g_" + global + " = new Box(" + writer.getAIThis() + ");"); + } + writer.addLine("private boolean g_init_" + global + " = false;"); } // Fonctions redéfinies for (String redefined : mRedefinedFunctions) { - writer.addCode("private VariableLeekValue rfunction_"); + writer.addCode("private Box rfunction_"); writer.addCode(redefined); writer.addLine(";"); } @@ -221,7 +225,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { * for(LeekInstruction instruction : mAnonymousFunctions){ * instruction.writeJavaCode(this, writer); } */ - writer.addLine("public AbstractLeekValue runIA() throws LeekRunException { resetCounter();"); + writer.addLine("public Object runIA() throws LeekRunException { resetCounter();"); for (var clazz : mUserClasses.values()) { clazz.writeJavaCode(this, writer); @@ -229,7 +233,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { super.writeJavaCode(this, writer); if (mEndInstruction == 0) - writer.addLine("return LeekValueManager.NULL;"); + writer.addLine("return null;"); writer.addLine("}"); writer.writeErrorFunction(mCompiler, mAIName); @@ -241,7 +245,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { FunctionBlock user_function = getUserFunction(redefined); writer.addCode("rfunction_"); writer.addCode(redefined); - writer.addCode(" = new VariableLeekValue(mUAI, "); + writer.addCode(" = new Box(" + writer.getAIThis() + ", "); if (user_function != null) { writer.addCode("new FunctionLeekValue("); writer.addCode(String.valueOf(user_function.getId())); @@ -260,54 +264,63 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { } public void printFunctionInformations(JavaWriter writer) { - // Compteur de parametres - writer.addLine("public int userFunctionCount(int id){"); - writer.addLine("switch(id){"); - for (FunctionBlock f : mFunctions) { - writer.addLine("case " + f.getId() + ": return " + f.countParameters() + ";"); - } - writer.addLine("} return -1; }"); - // Références - writer.addLine("public boolean[] userFunctionReference(int id) {"); - writer.addLine("switch(id) {"); - for (FunctionBlock f : mFunctions) { - writer.addLine("case " + f.getId() + ": return new boolean[]" + f.referenceArray() + ";"); - } - writer.addLine("} return null; }"); - // Execute - writer.addLine("public AbstractLeekValue userFunctionExecute(int id, AbstractLeekValue[] value) throws LeekRunException {"); - writer.addLine("switch(id){"); - for (FunctionBlock f : mFunctions) { - String params = ""; - for (int i = 0; i < f.countParameters(); i++) { - if (i != 0) - params += ","; - params += "value[" + i + "]"; + if (mFunctions.size() > 0) { + // Compteur de parametres + writer.addLine("public int userFunctionCount(int id) {"); + writer.addLine("switch(id) {"); + for (FunctionBlock f : mFunctions) { + writer.addLine("case " + f.getId() + ": return " + f.countParameters() + ";"); } - writer.addLine("case " + f.getId() + ": return user_function_" + f.getName() + "(" + params + ");"); - } - writer.addLine("} return null; }"); - - writer.addLine("public int anonymousFunctionCount(int id){"); - writer.addLine("switch(id){"); - for (AnonymousFunctionBlock f : mAnonymousFunctions) { - writer.addLine("case " + f.getId() + ": return " + f.countParameters() + ";"); + writer.addLine("} return -1; }"); + writer.addLine(); + + // Références + writer.addLine("public boolean[] userFunctionReference(int id) {"); + writer.addLine("switch(id) {"); + for (FunctionBlock f : mFunctions) { + writer.addLine("case " + f.getId() + ": return new boolean[]" + f.referenceArray() + ";"); + } + writer.addLine("} return null; }"); + writer.addLine(); + + // Execute + writer.addLine("public Object userFunctionExecute(int id, Object[] value) throws LeekRunException {"); + writer.addLine("switch(id) {"); + for (FunctionBlock f : mFunctions) { + String params = ""; + for (int i = 0; i < f.countParameters(); i++) { + if (i != 0) + params += ","; + params += "value[" + i + "]"; + } + writer.addLine("case " + f.getId() + ": return f_" + f.getName() + "(" + params + ");"); + } + writer.addLine("} return null; }"); } - writer.addLine("} return -1; }"); - // Références - writer.addLine("public boolean[] anonymousFunctionReference(int id){"); - writer.addLine("switch(id){"); - for (AnonymousFunctionBlock f : mAnonymousFunctions) { - writer.addLine("case " + f.getId() + ": return new boolean[]" + f.referenceArray() + ";"); + if (mAnonymousFunctions.size() > 0) { + writer.addLine(); + writer.addLine("public int anonymousFunctionCount(int id) {"); + writer.addLine("switch(id) {"); + for (AnonymousFunctionBlock f : mAnonymousFunctions) { + writer.addLine("case " + f.getId() + ": return " + f.countParameters() + ";"); + } + writer.addLine("} return -1; }"); + writer.addLine(); + // Références + writer.addLine("public boolean[] anonymousFunctionReference(int id) {"); + writer.addLine("switch(id){"); + for (AnonymousFunctionBlock f : mAnonymousFunctions) { + writer.addLine("case " + f.getId() + ": return new boolean[]" + f.referenceArray() + ";"); + } + writer.addLine("} return null; }"); } - writer.addLine("} return null; }"); - writer.addLine("public int getVersion() {"); - writer.addLine("return " + mCompiler.getCurrentAI().getVersion() + ";"); - writer.addLine("}"); + // writer.addLine("public int getVersion() {"); + // writer.addLine("return " + mCompiler.getCurrentAI().getVersion() + ";"); + // writer.addLine("}"); // Execute /* * writer.addLine( - * "public AbstractLeekValue anonymousFunctionExecute(int id, AbstractLeekValue[] value) throws Exception{" + * "public Object anonymousFunctionExecute(int id, Object[] value) throws Exception{" * ); writer.addLine("switch(id){"); for(AnonymousFunctionBlock f : * mAnonymousFunctions){ String params = ""; for(int i = 0; i < * f.countParameters(); i++){ if(i != 0) params += ","; params += @@ -320,15 +333,15 @@ public void printFunctionInformations(JavaWriter writer) { * * public abstract boolean[] userFunctionReference(int id); * - * public abstract AbstractLeekValue userFunctionExecute(int id, - * AbstractLeekValue[] value); + * public abstract Object userFunctionExecute(int id, + * Object[] value); * * public abstract int anonymousFunctionCount(int id); * * public abstract boolean[] anonymousFunctionReference(int id); * - * public abstract AbstractLeekValue anonymousFunctionExecute(int id, - * AbstractLeekValue[] value); + * public abstract Object anonymousFunctionExecute(int id, + * Object[] value); */ } diff --git a/src/main/java/leekscript/compiler/bloc/WhileBlock.java b/src/main/java/leekscript/compiler/bloc/WhileBlock.java index d245256b..5f68c7c3 100644 --- a/src/main/java/leekscript/compiler/bloc/WhileBlock.java +++ b/src/main/java/leekscript/compiler/bloc/WhileBlock.java @@ -4,6 +4,7 @@ import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; import leekscript.compiler.expression.AbstractExpression; +import leekscript.compiler.expression.LeekBoolean; public class WhileBlock extends AbstractLeekBlock { @@ -28,9 +29,18 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addCode("while("); - mCondition.writeJavaCode(mainblock, writer); - writer.addLine(".getBoolean()){"); + // writer.addCounter(1); + writer.addCode("while (ops("); + // Prevent unreachable code error + if (mCondition instanceof LeekBoolean) { + writer.addCode("bool("); + writer.getBoolean(mainblock, mCondition); + writer.addCode(")"); + } else { + writer.getBoolean(mainblock, mCondition); + } + writer.addCode(", " + (mCondition.getOperations()) + ")"); + writer.addLine(") {"); writer.addCounter(1); super.writeJavaCode(mainblock, writer); writer.addLine("}"); diff --git a/src/main/java/leekscript/compiler/expression/AbstractExpression.java b/src/main/java/leekscript/compiler/expression/AbstractExpression.java index 9243f28f..9bb71d9a 100644 --- a/src/main/java/leekscript/compiler/expression/AbstractExpression.java +++ b/src/main/java/leekscript/compiler/expression/AbstractExpression.java @@ -30,6 +30,108 @@ public abstract class AbstractExpression { public abstract void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer); + public void compileL(MainLeekBlock mainblock, JavaWriter writer) { + writeJavaCode(mainblock, writer); + } + + public void compileSet(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" = "); + expr.writeJavaCode(mainblock, writer); + } + + public void compileSetCopy(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" = "); + writer.compileClone(mainblock, expr); + } + + public void compileIncrement(MainLeekBlock mainblock, JavaWriter writer) { + writeJavaCode(mainblock, writer); + writer.addCode("++"); + } + + public void compileDecrement(MainLeekBlock mainblock, JavaWriter writer) { + writeJavaCode(mainblock, writer); + writer.addCode("--"); + } + + public void compilePreIncrement(MainLeekBlock mainblock, JavaWriter writer) { + writer.addCode("++"); + writeJavaCode(mainblock, writer); + } + + public void compilePreDecrement(MainLeekBlock mainblock, JavaWriter writer) { + writer.addCode("--"); + writeJavaCode(mainblock, writer); + } + + public void compileAddEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" += "); + expr.writeJavaCode(mainblock, writer); + } + + public void compileSubEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" -= "); + expr.writeJavaCode(mainblock, writer); + } + + public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" *= "); + expr.writeJavaCode(mainblock, writer); + } + + public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" /= "); + expr.writeJavaCode(mainblock, writer); + } + + public void compileModEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" %= "); + expr.writeJavaCode(mainblock, writer); + } + + public void compileBitOrEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" |= "); + expr.writeJavaCode(mainblock, writer); + } + + public void compileBitAndEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" &= "); + expr.writeJavaCode(mainblock, writer); + } + + public void compileBitXorEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" ^= "); + expr.writeJavaCode(mainblock, writer); + } + + public void compileShiftLeftEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" <<= "); + expr.writeJavaCode(mainblock, writer); + } + + public void compileShiftRightEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" >>= "); + expr.writeJavaCode(mainblock, writer); + } + + public void compileShiftUnsignedRightEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" >>>= "); + expr.writeJavaCode(mainblock, writer); + } + public abstract boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException; public AbstractExpression trim() { diff --git a/src/main/java/leekscript/compiler/expression/LeekArray.java b/src/main/java/leekscript/compiler/expression/LeekArray.java index aab0b829..8b6f29c2 100644 --- a/src/main/java/leekscript/compiler/expression/LeekArray.java +++ b/src/main/java/leekscript/compiler/expression/LeekArray.java @@ -57,14 +57,14 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if(mValues.size() == 0) writer.addCode("new ArrayLeekValue()"); - else{ - writer.addCode("new ArrayLeekValue(mUAI, new AbstractLeekValue[]{"); - for(int i = 0; i < mValues.size(); i++){ - if(i != 0) writer.addCode(","); + if (mValues.size() == 0) writer.addCode("new ArrayLeekValue()"); + else { + writer.addCode("new ArrayLeekValue(" + writer.getAIThis() + ", new Object[] { "); + for (int i = 0; i < mValues.size(); i++) { + if (i != 0) writer.addCode(", "); mValues.get(i).writeJavaCode(mainblock, writer); } - writer.addCode("}, " + (mIsKeyVal ? "true" : "false") + ")"); + writer.addCode(" }, " + (mIsKeyVal ? "true" : "false") + ")"); } } diff --git a/src/main/java/leekscript/compiler/expression/LeekBoolean.java b/src/main/java/leekscript/compiler/expression/LeekBoolean.java index 55e6e21e..000ae89f 100644 --- a/src/main/java/leekscript/compiler/expression/LeekBoolean.java +++ b/src/main/java/leekscript/compiler/expression/LeekBoolean.java @@ -30,7 +30,7 @@ public String getString() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addCode("LeekValueManager." + (mValue ? "TRUE" : "FALSE")); + writer.addCode(mValue ? "true" : "false"); } @Override diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index 8cb3a1c6..63f57e82 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -440,56 +440,98 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t public AbstractExpression trim() { if (mExpression2 == null) return mExpression1.trim(); + // if (mOperator == Operators.REFERENCE) { + // return mExpression1.trim(); + // } return this; } @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - // if (mExpression1 instanceof LeekExpression) - // mExpression1 = ((LeekExpression) mExpression1).getAbstractExpression(); - // if (mExpression2 instanceof LeekExpression) - // mExpression2 = ((LeekExpression) mExpression2).getAbstractExpression(); + // Retourner le code java de l'expression... plein de cas :) switch (mOperator) { // Les classiques - case Operators.ADD:// Addition (on commence facile) - writer.addCode("LeekOperations.add(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + case Operators.ADD: // Addition (on commence facile) + if (mExpression1.getType().isNumber() && mExpression2.getType().isNumber()) { + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(" + "); + mExpression2.writeJavaCode(mainblock, writer); + // } else if (mExpression1.getType() == Type.STRING || mExpression2.getType() == Type.STRING) { + // if (mExpression1.getType() == Type.STRING) + // mExpression1.writeJavaCode(mainblock, writer); + // else + // writer.getString(mainblock, mExpression1); + // writer.addCode(" + "); + // if (mExpression2.getType() == Type.STRING || mExpression2.getType() == Type.REAL || mExpression2.getType() == Type.INT || mExpression2.getType() == Type.BOOL) + // mExpression2.writeJavaCode(mainblock, writer); + // else + // writer.getString(mainblock, mExpression2); + } else { + writer.addCode("add("); + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } return; - case Operators.MINUS:// Soustraction - writer.addCode("LeekOperations.minus(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + case Operators.MINUS: // Soustraction + if (mExpression1.getType().isNumber() && mExpression2.getType().isNumber()) { + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(" - "); + mExpression2.writeJavaCode(mainblock, writer); + } else { + writer.addCode("sub("); + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } return; - case Operators.MULTIPLIE:// Multiplication - writer.addCode("LeekOperations.multiply(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + case Operators.MULTIPLIE: // Multiplication + if (mExpression1.getType().isNumber() && mExpression2.getType().isNumber()) { + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(" * "); + mExpression2.writeJavaCode(mainblock, writer); + } else { + writer.addCode("mul("); + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } return; case Operators.MODULUS:// Modulo - writer.addCode("LeekOperations.modulus(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + if (mExpression1.getType().isNumber() && mExpression2.getType().isNumber()) { + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(" % "); + mExpression2.writeJavaCode(mainblock, writer); + } else { + writer.addCode("mod("); + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } return; case Operators.DIVIDE:// Division - writer.addCode("LeekOperations.divide(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); - return; - case Operators.POWER:// Puissance - writer.addCode("LeekOperations.power(mUAI, "); + // Division by zero is not handled + // if (mExpression1.getType().isNumber() && mExpression2.getType().isNumber()) { + // mExpression1.writeJavaCode(mainblock, writer); + // writer.addCode(" / "); + // mExpression2.writeJavaCode(mainblock, writer); + // } else { + writer.addCode("div("); + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(", "); + writer.compileLoad(mainblock, mExpression2); + // mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(")"); + // } + return; + case Operators.POWER: // Puissance + writer.addCode("pow("); mExpression1.writeJavaCode(mainblock, writer); writer.addCode(", "); mExpression2.writeJavaCode(mainblock, writer); @@ -497,136 +539,161 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { return; // Les binaires case Operators.BITAND: - writer.addCode("LeekOperations.band(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + writer.getInt(mainblock, mExpression1); + writer.addCode(" & "); + writer.getInt(mainblock, mExpression2); return; case Operators.BITOR: - writer.addCode("LeekOperations.bor(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + writer.getInt(mainblock, mExpression1); + writer.addCode(" | "); + writer.getInt(mainblock, mExpression2); return; case Operators.BITXOR: - writer.addCode("LeekOperations.bxor(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + writer.getInt(mainblock, mExpression1); + writer.addCode(" ^ "); + writer.getInt(mainblock, mExpression2); return; case Operators.SHIFT_LEFT: - writer.addCode("LeekOperations.bleft(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + writer.getInt(mainblock, mExpression1); + writer.addCode(" << "); + writer.getInt(mainblock, mExpression2); return; case Operators.SHIFT_RIGHT: - writer.addCode("LeekOperations.bright(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + writer.getInt(mainblock, mExpression1); + writer.addCode(" >> "); + writer.getInt(mainblock, mExpression2); return; case Operators.SHIFT_UNSIGNED_RIGHT: - writer.addCode("LeekOperations.brotate(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + writer.getInt(mainblock, mExpression1); + writer.addCode(" >>> "); + writer.getInt(mainblock, mExpression2); return; // Les logiques case Operators.EQUALS_EQUALS: - writer.addCode("LeekOperations.equals_equals(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + if (mExpression2 instanceof LeekNull) { + if (mExpression1.getType() == Type.BOOL || mExpression1.getType().isNumber()) { + writer.addCode("false"); + } else { + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(" == null"); + } + } else { + writer.addCode("equals_equals("); + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } return; case Operators.NOT_EQUALS_EQUALS: - writer.addCode("LeekOperations.notequals_equals(mUAI, "); + writer.addCode("notequals_equals("); mExpression1.writeJavaCode(mainblock, writer); writer.addCode(", "); mExpression2.writeJavaCode(mainblock, writer); writer.addCode(")"); return; case Operators.EQUALS: - writer.addCode("LeekOperations.equals(mUAI, "); + writer.addCode("eq("); mExpression1.writeJavaCode(mainblock, writer); writer.addCode(", "); mExpression2.writeJavaCode(mainblock, writer); writer.addCode(")"); return; case Operators.MORE: - writer.addCode("LeekOperations.more(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + if (mExpression1.getType().isNumber() && mExpression2.getType().isNumber()) { + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(" > "); + mExpression2.writeJavaCode(mainblock, writer); + } else { + writer.addCode("more("); + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } return; case Operators.LESS: - writer.addCode("LeekOperations.less(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + if (mExpression1.getType().isNumber() && mExpression2.getType().isNumber()) { + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(" < "); + mExpression2.writeJavaCode(mainblock, writer); + } else { + writer.addCode("less("); + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } return; case Operators.MOREEQUALS: - writer.addCode("LeekOperations.moreequals(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + if (mExpression1.getType().isNumber() && mExpression2.getType().isNumber()) { + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(" >= "); + mExpression2.writeJavaCode(mainblock, writer); + } else { + writer.addCode("moreequals("); + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } return; case Operators.LESSEQUALS: - writer.addCode("LeekOperations.lessequals(mUAI, "); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(", "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + if (mExpression1.getType().isNumber() && mExpression2.getType().isNumber()) { + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(" <= "); + mExpression2.writeJavaCode(mainblock, writer); + } else { + writer.addCode("lessequals("); + mExpression1.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } return; case Operators.NOTEQUALS: - writer.addCode("LeekOperations.notequals(mUAI, "); + writer.addCode("neq("); mExpression1.writeJavaCode(mainblock, writer); writer.addCode(", "); mExpression2.writeJavaCode(mainblock, writer); writer.addCode(")"); return; case Operators.AND: - writer.addCode("LeekValueManager.getLeekBooleanValue("); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".getBoolean() && "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(".getBoolean())"); + writer.addCode("("); + writer.addCode("ops("); + writer.getBoolean(mainblock, mExpression1); + writer.addCode(", " + mExpression1.operations + ") && ops("); + writer.getBoolean(mainblock, mExpression2); + writer.addCode(", " + mExpression2.operations + "))"); return; case Operators.OR: - writer.addCode("LeekValueManager.getLeekBooleanValue("); - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".getBoolean() || "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(".getBoolean())"); + writer.addCode("("); + writer.addCode("ops("); + writer.getBoolean(mainblock, mExpression1); + writer.addCode(", " + mExpression1.operations + ") || ops("); + writer.getBoolean(mainblock, mExpression2); + writer.addCode(", " + mExpression2.operations + "))"); return; // Les unaires préfixés (!) case Operators.NOT: - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(".not(mUAI)"); + writer.addCode("!"); + writer.getBoolean(mainblock, mExpression2); return; case Operators.BITNOT: + writer.addCode("bnot("); mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(".bnot(mUAI)"); + writer.addCode(")"); return; case Operators.UNARY_MINUS: - if (mExpression2 instanceof LeekNumber) { + if (mExpression2.getType().isNumber()) { + writer.addCode("-"); mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(".oppositeConstant()"); } else { + writer.addCode("minus("); mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(".opposite(mUAI)"); + writer.addCode(")"); } return; case Operators.NEW: @@ -635,109 +702,74 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { // Les unaires suffixés (++, --), Il a été vérifié au préalable // qu'on avait bien une L-Value case Operators.INCREMENT: - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(".increment(mUAI)"); + mExpression2.compileIncrement(mainblock, writer); return; case Operators.DECREMENT: - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(".decrement(mUAI)"); + mExpression2.compileDecrement(mainblock, writer); return; case Operators.PRE_INCREMENT: - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(".pre_increment(mUAI)"); + mExpression2.compilePreIncrement(mainblock, writer); return; case Operators.PRE_DECREMENT: - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(".pre_decrement(mUAI)"); + mExpression2.compilePreDecrement(mainblock, writer); return; // Les assignations case Operators.ASSIGN: - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".set(mUAI, "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + // Assign without clone for LS 1.1 or reference + if (mainblock.getWordCompiler().getVersion() >= 11) { + mExpression1.compileSet(mainblock, writer, mExpression2); + } else if (mExpression2 instanceof LeekExpression && ((LeekExpression) mExpression2).getOperator() == Operators.REFERENCE) { + mExpression1.compileSet(mainblock, writer, ((LeekExpression) mExpression2).mExpression2); + } else { + mExpression1.compileSetCopy(mainblock, writer, mExpression2); + } return; case Operators.ADDASSIGN: - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".add(mUAI, "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + mExpression1.compileAddEq(mainblock, writer, mExpression2); return; case Operators.MINUSASSIGN: - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".minus(mUAI, "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + mExpression1.compileSubEq(mainblock, writer, mExpression2); return; case Operators.MODULUSASSIGN: - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".modulus(mUAI, "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + mExpression1.compileModEq(mainblock, writer, mExpression2); return; case Operators.DIVIDEASSIGN: - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".divide(mUAI, "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + mExpression1.compileDivEq(mainblock, writer, mExpression2); return; case Operators.MULTIPLIEASSIGN: - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".multiply(mUAI, "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + mExpression1.compileMulEq(mainblock, writer, mExpression2); return; case Operators.POWERASSIGN: - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".power(mUAI, "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + mExpression1.compileSet(mainblock, writer, new LeekExpression(mExpression1, Operators.POWER, mExpression2)); return; case Operators.BITXOR_ASSIGN: - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".bxor(mUAI, "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + mExpression1.compileBitXorEq(mainblock, writer, mExpression2); return; case Operators.BITAND_ASSIGN: - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".band(mUAI, "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + mExpression1.compileBitAndEq(mainblock, writer, mExpression2); return; case Operators.BITOR_ASSIGN: - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".bor(mUAI, "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + mExpression1.compileBitOrEq(mainblock, writer, mExpression2); return; case Operators.SHIFT_LEFT_ASSIGN: - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".bleft(mUAI, "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + mExpression1.compileShiftLeftEq(mainblock, writer, mExpression2); return; case Operators.SHIFT_RIGHT_ASSIGN: - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".bright(mUAI, "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + mExpression1.compileShiftRightEq(mainblock, writer, mExpression2); return; case Operators.SHIFT_UNSIGNED_RIGHT_ASSIGN: - mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".brotate(mUAI, "); - mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + mExpression1.compileShiftUnsignedRightEq(mainblock, writer, mExpression2); return; case Operators.REFERENCE: - writer.addCode("new ReferenceLeekValue(mUAI, "); + // writer.addCode("new ReferenceLeekValue(" + writer.getAIThis() + ", "); mExpression2.writeJavaCode(mainblock, writer); - writer.addCode(")"); + // writer.addCode(")"); return; case Operators.INSTANCEOF: + writer.addCode("instanceOf("); mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(".instanceOf(mUAI, "); + writer.addCode(", "); mExpression2.writeJavaCode(mainblock, writer); writer.addCode(")"); return; @@ -830,14 +862,22 @@ else if (mExpression1.getType() == Type.REAL) { // Opérations operations = (mExpression1 != null ? mExpression1.getOperations() : 0) + (mExpression2 != null ? mExpression2.getOperations() : 0); - if (mOperator == Operators.POWER || mOperator == Operators.POWERASSIGN) { + if (mOperator == Operators.POWER) { + operations += LeekValue.POW_COST; + } else if (mOperator == Operators.POWERASSIGN) { operations += LeekValue.POW_COST; - } else if (mOperator == Operators.MULTIPLIE || mOperator == Operators.MULTIPLIEASSIGN) { + } else if (mOperator == Operators.MULTIPLIE) { operations += LeekValue.MUL_COST; + } else if (mOperator == Operators.MULTIPLIEASSIGN) { + operations += LeekValue.MUL_COST; //+ 1; } else if (mOperator == Operators.DIVIDE || mOperator == Operators.DIVIDEASSIGN) { operations += LeekValue.DIV_COST; } else if (mOperator == Operators.MODULUS || mOperator == Operators.MODULUSASSIGN) { operations += LeekValue.MOD_COST; + } else if (mOperator == Operators.REFERENCE || mOperator == Operators.NEW) { + // 0 + } else if (mOperator == Operators.AND || mOperator == Operators.OR) { + operations = 0; } else { operations += 1; } diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 4b9a36d7..ec63eb1b 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -70,17 +70,36 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { + writer.addCode("load("); + compileL(mainblock, writer); + writer.addCode(")"); + } + + @Override + public void compileL(MainLeekBlock mainblock, JavaWriter writer) { boolean addComma = true; + boolean addBrace = false; FunctionBlock user_function = null; ILeekFunction system_function = null; if (mExpression instanceof LeekObjectAccess) { var object = ((LeekObjectAccess) mExpression).getObject(); + var field = ((LeekObjectAccess) mExpression).getField(); if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.SUPER) { - writer.addCode("u_this.callSuperMethod(mUAI, u_class, \"" + ((LeekObjectAccess) mExpression).getField() + "_" + mParameters.size() + "\""); + writer.addCode("u_this.callSuperMethod(this, \"" + (field + "_" + mParameters.size() + "\"")); + } else if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.CLASS) { + // Méthode statique connue + var v = (LeekVariable) object; + String methodName = "u_" + v.getClassDeclaration().getName() + "_" + field + "_" + mParameters.size(); + writer.addCode(methodName + "("); + addComma = false; + } else if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.THIS) { + // Méthode connue + String methodName = "u_" + mainblock.getWordCompiler().getCurrentClass().getMethodName(field, mParameters.size()); + writer.addCode(methodName + "(u_this"); } else { - var fromClass = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; + writer.addCode("callMethod("); object.writeJavaCode(mainblock, writer); - writer.addCode(".callMethod(mUAI, \"" + ((LeekObjectAccess) mExpression).getField() + "_" + mParameters.size() + "\", " + fromClass); + writer.addCode(", \"" + field + "_" + mParameters.size() + "\""); } } else if (mExpression instanceof LeekTabularValue) { var object = ((LeekTabularValue) mExpression).getTabular(); @@ -99,64 +118,93 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.SUPER) { // Super constructor var variable = (LeekVariable) mExpression; - writer.addCode("user_" + variable.getClassDeclaration().getParent().getName()); - writer.addCode(".callConstructor(mUAI, u_this"); + writer.addCode("u_" + variable.getClassDeclaration().getParent().getName()); + writer.addCode(".callConstructor(u_this"); } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.METHOD) { - writer.addCode("u_this.callMethod(mUAI, \"" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size() + "\", u_class"); + // Méthode connue + String methodName = "u_" + mainblock.getWordCompiler().getCurrentClass().getMethodName(((LeekVariable) mExpression).getName(), mParameters.size()); + writer.addCode(methodName + "(u_this"); } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.STATIC_METHOD) { - writer.addCode("u_class.callMethod(mUAI, \"" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size() + "\", u_class"); + // Méthode statique connue + String methodName = "u_" + mainblock.getWordCompiler().getCurrentClass().getName() + "_" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size(); + writer.addCode(methodName + "("); + addComma = false; } else if (mExpression instanceof LeekVariable && mainblock.isRedefinedFunction(((LeekVariable) mExpression).getName())) { writer.addCode("rfunction_" + ((LeekVariable) mExpression).getName()); - writer.addCode(".executeFunction(mUAI"); + writer.addCode(".execute(this"); } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.SYSTEM_FUNCTION) { var variable = (LeekVariable) mExpression; system_function = LeekFunctions.getValue(variable.getName()); - String namespace = LeekFunctions.getNamespace(variable.getName()); - // writer.addCode("LeekValueManager.getFunction(" + namespace + "." + variable.getName() + ")"); - writer.addCode("LeekFunctions.executeFunction(mUAI, " + namespace + "." + variable.getName() + ", new AbstractLeekValue[] {"); - addComma = false; + + if (system_function.getVersions() != null) { + // var version = checkArgumentsStatically(system_function); + // System.out.println("version = " + version); + // if (version != null) { + // var signature = buildTypesSignature(version.arguments); + // writer.addCode("" + system_function + "_" + signature + "("); + // } else { + writer.addCode("" + system_function + "("); + // } + addComma = false; + } else { + // writer.addCode("" + system_function + "_("); + String namespace = LeekFunctions.getNamespace(variable.getName()); + writer.addCode("sysexec(" + namespace + "." + variable.getName()); + } } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.FUNCTION) { - writer.addCode("user_function_"); + writer.addCode("f_"); writer.addCode(((LeekVariable) mExpression).getName()); writer.addCode("("); addComma = false; user_function = mainblock.getUserFunction(((LeekVariable) mExpression).getName()); } else { - mExpression.writeJavaCode(mainblock, writer); - writer.addCode(".executeFunction(mUAI"); + if (mExpression.isLeftValue() && !mExpression.nullable()) { + writer.addCode("execute("); + mExpression.writeJavaCode(mainblock, writer); + // addComma = false; + } else { + writer.addCode("execute("); + mExpression.writeJavaCode(mainblock, writer); + } } + int argCount = mParameters.size(); if (system_function != null) argCount = Math.max(argCount, system_function.getArguments()); for (int i = 0; i < argCount; i++) { if (i > 0 || addComma) writer.addCode(", "); if (i < mParameters.size()) { + var parameter = mParameters.get(i); + // Java doesn't like a single null for Object... argument + if (argCount == 1 && parameter.getType() == Type.NULL) { + writer.addCode("new Object[] { null }"); + continue; + } if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { - mParameters.get(i).writeJavaCode(mainblock, writer); - if (system_function != null) { - writer.addCode(".getValue()"); - } + parameter.writeJavaCode(mainblock, writer); } else { if (user_function != null) { - if (user_function.isReference(i)) { - mParameters.get(i).writeJavaCode(mainblock, writer); - } else { - writer.addCode("LeekOperations.clone(mUAI, "); - mParameters.get(i).writeJavaCode(mainblock, writer); - writer.addCode(".getValue())"); - } + // if (user_function.isReference(i)) { + parameter.compileL(mainblock, writer); + // } else { + // writer.compileClone(mainblock, parameter); + // } } else if (system_function != null) { - mParameters.get(i).writeJavaCode(mainblock, writer); - writer.addCode(".getValue()"); + writer.compileLoad(mainblock, parameter); } else { - mParameters.get(i).writeJavaCode(mainblock, writer); + parameter.compileL(mainblock, writer); } } } else { - writer.addCode("LeekValueManager.NULL"); + // Java doesn't like a single null for Object... argument + if (argCount == 1) { + writer.addCode("new Object[] { null }"); + } else { + writer.addCode("null"); + } } } - if (system_function != null) { - writer.addCode("}, " + mParameters.size()); + if (addBrace) { + writer.addCode("}"); } writer.addCode(")"); writer.addPosition(openParenthesis); @@ -164,7 +212,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { @Override public void analyze(WordCompiler compiler) { - operations = 1; + operations = 0; mExpression.analyze(compiler); operations += mExpression.getOperations(); for (AbstractExpression parameter : mParameters) { diff --git a/src/main/java/leekscript/compiler/expression/LeekNull.java b/src/main/java/leekscript/compiler/expression/LeekNull.java index c50e1e41..961d84d6 100644 --- a/src/main/java/leekscript/compiler/expression/LeekNull.java +++ b/src/main/java/leekscript/compiler/expression/LeekNull.java @@ -30,7 +30,7 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addCode("LeekValueManager.NULL"); + writer.addCode("null"); } @Override diff --git a/src/main/java/leekscript/compiler/expression/LeekNumber.java b/src/main/java/leekscript/compiler/expression/LeekNumber.java index 184d7400..69776842 100644 --- a/src/main/java/leekscript/compiler/expression/LeekNumber.java +++ b/src/main/java/leekscript/compiler/expression/LeekNumber.java @@ -49,10 +49,10 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if (type == Type.REAL) { - writer.addCode("new DoubleLeekValue(" + mValue + ")"); + if (type == Type.INT) { + writer.addCode(String.valueOf((int) mValue)); } else { - writer.addCode("LeekValueManager.getLeekIntValue(" + ((int) mValue) + ")"); + writer.addCode(String.valueOf(mValue)); } } diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index 627b6237..811232fb 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -40,13 +40,6 @@ public AbstractExpression getObject() { return object; } - @Override - public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - object.writeJavaCode(mainblock, writer); - String fromClass = (writer.currentBlock instanceof ClassMethodBlock) ? "u_class" : "null"; - writer.addCode(".getField(mUAI, \"" + field.getWord() + "\", " + fromClass + ")"); - } - @Override public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { return object.validExpression(compiler, mainblock); @@ -91,4 +84,87 @@ public String getField() { public IAWord getFieldToken() { return field; } + + @Override + public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { + writer.addCode("getField("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\")"); + } + + @Override + public void compileL(MainLeekBlock mainblock, JavaWriter writer) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("getField("); + object.compileL(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\")"); + } + + @Override + public void compileSet(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("setField("); + object.compileL(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + public void compileIncrement(MainLeekBlock mainblock, JavaWriter writer) { + assert (object.isLeftValue() && !object.nullable()); + + object.compileL(mainblock, writer); + writer.addCode(".getFieldL(\"" + field.getWord() + "\").increment()"); + } + + @Override + public void compileAddEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_add_eq("); + object.compileL(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + + public void compileSubEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_sub_eq("); + object.compileL(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + + public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_mul_eq("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + + @Override + + public void compileBitOrEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_bor_eq("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekParenthesis.java b/src/main/java/leekscript/compiler/expression/LeekParenthesis.java index abb7f187..e500259d 100644 --- a/src/main/java/leekscript/compiler/expression/LeekParenthesis.java +++ b/src/main/java/leekscript/compiler/expression/LeekParenthesis.java @@ -39,7 +39,9 @@ public String getString() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { + writer.addCode("("); mExpression.writeJavaCode(mainblock, writer); + writer.addCode(")"); } @Override diff --git a/src/main/java/leekscript/compiler/expression/LeekString.java b/src/main/java/leekscript/compiler/expression/LeekString.java index 7c17c685..8aad896e 100644 --- a/src/main/java/leekscript/compiler/expression/LeekString.java +++ b/src/main/java/leekscript/compiler/expression/LeekString.java @@ -32,7 +32,7 @@ public String getString() { @Override public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { - //Pour une chaine de caractères pas de problèmes + // Pour une chaine de caractères pas de problèmes return true; } @@ -62,7 +62,7 @@ else if (mString.charAt(i) == '\\') { } else str += mString.charAt(i); } - writer.addCode("new StringLeekValue(\"" + str + "\")"); + writer.addCode("\"" + str + "\""); } @Override diff --git a/src/main/java/leekscript/compiler/expression/LeekTabularValue.java b/src/main/java/leekscript/compiler/expression/LeekTabularValue.java index 7926ba73..e0eb7b61 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTabularValue.java +++ b/src/main/java/leekscript/compiler/expression/LeekTabularValue.java @@ -58,19 +58,205 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if (mLeftValue) { - mTabular.writeJavaCode(mainblock, writer); - writer.addCode(".getValue().getOrCreate(mUAI, "); - mCase.writeJavaCode(mainblock, writer); - writer.addCode(")"); - } else { - mTabular.writeJavaCode(mainblock, writer); - writer.addCode(".getValue().get(mUAI, "); - mCase.writeJavaCode(mainblock, writer); - writer.addCode(")"); - } + writer.addCode("get("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + public void compileL(MainLeekBlock mainblock, JavaWriter writer) { + assert(mLeftValue && !mTabular.nullable()); + writer.addCode("getBox("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + public void compileSet(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + public void compileSetCopy(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + + // writer.compileClone(mainblock, expr); + writer.addCode(")"); + } + + @Override + public void compileIncrement(MainLeekBlock mainblock, JavaWriter writer) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_inc("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + public void compileDecrement(MainLeekBlock mainblock, JavaWriter writer) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_dec("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + public void compileAddEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_add_eq("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + public void compileSubEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_sub_eq("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); } + @Override + public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_mul_eq("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_div_eq("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + + @Override + public void compileBitOrEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_bor_eq("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + + @Override + public void compileBitAndEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_band_eq("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + + @Override + public void compileBitXorEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_bxor_eq("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + public void compileShiftLeftEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_shl_eq("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + public void compileShiftRightEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_shr_eq("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + public void compileShiftUnsignedRightEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_ushr_eq("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } public void setLeftValue(boolean b) { mLeftValue = b; } diff --git a/src/main/java/leekscript/compiler/expression/LeekTernaire.java b/src/main/java/leekscript/compiler/expression/LeekTernaire.java index 2f7eae2f..86b0b7db 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTernaire.java +++ b/src/main/java/leekscript/compiler/expression/LeekTernaire.java @@ -74,14 +74,17 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { // if(mExpression1 instanceof LeekExpression) mExpression1 = ((LeekExpression) mExpression1).getAbstractExpression(); // if(mExpression2 instanceof LeekExpression) mExpression2 = ((LeekExpression) mExpression2).getAbstractExpression(); if (!complete()) writer.addCode("/* " + getString() + " */"); - else{ - writer.addCode("("); - mCondition.writeJavaCode(mainblock, writer); - writer.addCode(".getBooleanTernary(mUAI) ? ("); + else { + writer.addCode("ops("); + writer.getBoolean(mainblock, mCondition); + writer.addCode(", 1) ? "); + if (mExpression1.getOperations() > 0) writer.addCode("ops("); mExpression1.writeJavaCode(mainblock, writer); - writer.addCode(") : ("); + if (mExpression1.getOperations() > 0) writer.addCode(", " + mExpression1.getOperations() + ")"); + writer.addCode(" : "); + if (mExpression2.getOperations() > 0) writer.addCode("ops("); mExpression2.writeJavaCode(mainblock, writer); - writer.addCode("))"); + if (mExpression2.getOperations() > 0) writer.addCode(", " + mExpression2.getOperations() + ")"); } } diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index d82a44d5..0feaaa18 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -86,48 +86,14 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t return true; } - @Override - public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if (type == VariableType.THIS) { - writer.addCode("u_this"); - } else if (type == VariableType.THIS_CLASS) { - writer.addCode("u_class"); - } else if (type == VariableType.SUPER) { - writer.addCode("user_" + classDeclaration.getParent().getName()); - } else if (type == VariableType.FIELD) { - writer.addCode("u_this.getField(mUAI, \"" + token.getWord() + "\", u_class)"); - } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.getField(mUAI, \"" + token.getWord() + "\", u_class)"); - } else if (type == VariableType.METHOD) { - writer.addCode("###"); - } else if (mainblock.isRedefinedFunction(token.getWord())) { - writer.addCode("rfunction_" + token.getWord()); - } else if (type == VariableType.FUNCTION) { - FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); - writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); - } else if (type == VariableType.SYSTEM_CONSTANT) { - var constant = LeekConstants.get(token.getWord()); - if (constant.getType() == Type.INT) writer.addCode("LeekValueManager.getLeekIntValue(" + constant.getIntValue() + ")"); - else if (constant.getType() == Type.REAL) writer.addCode("new DoubleLeekValue(" + constant.getValue() + ")"); - else writer.addCode("LeekValueManager.NULL"); - } else if (type == VariableType.SYSTEM_FUNCTION) { - FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); - if (user_function != null) { - writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); - } else { - String namespace = LeekFunctions.getNamespace(token.getWord()); - writer.addCode("LeekValueManager.getFunction(" + namespace + "." + token.getWord() + ")"); - } - } else if (type == VariableType.GLOBAL) { - writer.addCode("globale_" + token.getWord()); - } else { - writer.addCode("user_" + token.getWord()); - } + public boolean isLeftValue() { + return true; } @Override - public boolean isLeftValue() { - return true; + public boolean nullable() { + // return type != VariableType.CLASS && type != VariableType.THIS && type != VariableType.THIS_CLASS; + return false; } public VariableType getVariableType() { @@ -195,4 +161,640 @@ public boolean isWrapper() { return declaration != null && declaration.isWrapper(); } + + @Override + public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { + if (type == VariableType.THIS) { + writer.addCode("u_this"); + } else if (type == VariableType.THIS_CLASS) { + writer.addCode("u_class"); + } else if (type == VariableType.SUPER) { + writer.addCode("u_" + classDeclaration.getParent().getName()); + } else if (type == VariableType.FIELD) { + writer.addCode("u_this.getField(\"" + token.getWord() + "\")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.getField(\"" + token.getWord() + "\")"); + } else if (type == VariableType.METHOD) { + writer.addCode("###"); + } else if (mainblock.isRedefinedFunction(token.getWord())) { + writer.addCode("rfunction_" + token.getWord()); + } else if (type == VariableType.FUNCTION) { + FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); + writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); + } else if (type == VariableType.SYSTEM_CONSTANT) { + var constant = LeekConstants.get(token.getWord()); + // if (constant.getType() == LeekFunctions.INT) writer.addCode("LeekValueManager.getLeekIntValue(" + constant.getIntValue() + ")"); + if (constant.getType() == Type.INT) writer.addCode(String.valueOf(constant.getIntValue())); + // else if (constant.getType() == LeekFunctions.DOUBLE) writer.addCode("new DoubleLeekValue(" + constant.getValue() + ")"); + else if (constant.getType() == Type.REAL) writer.addCode(String.valueOf(constant.getValue())); + else writer.addCode("null"); + } else if (type == VariableType.SYSTEM_FUNCTION) { + FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); + if (user_function != null) { + writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); + } else { + String namespace = LeekFunctions.getNamespace(token.getWord()); + writer.addCode("LeekValueManager.getFunction(" + namespace + "." + token.getWord() + ")"); + } + } else if (type == VariableType.GLOBAL) { + if (mainblock.getWordCompiler().getVersion() <= 10) { + writer.addCode("g_" + token.getWord() + ".getValue()"); + } else { + writer.addCode("g_" + token.getWord()); + } + } else if (type == VariableType.CLASS) { + writer.addCode("u_" + token.getWord()); + } else { + if (isWrapper()) { + writer.addCode("u_" + token.getWord() + ".getValue()"); + } else if (isBox()) { + writer.addCode("u_" + token.getWord() + ".getValue()"); + } else { + writer.addCode("u_" + token.getWord()); + } + } + } + + @Override + public void compileL(MainLeekBlock mainblock, JavaWriter writer) { + if (type == VariableType.THIS) { + writer.addCode("u_this"); + } else if (type == VariableType.THIS_CLASS) { + writer.addCode("u_class"); + } else if (type == VariableType.SUPER) { + writer.addCode("u_" + classDeclaration.getParent().getName()); + } else if (type == VariableType.FIELD) { + writer.addCode("u_this.getFieldL(\"" + token.getWord() + "\")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.getFieldL(\"" + token.getWord() + "\")"); + } else if (type == VariableType.GLOBAL) { + writer.addCode("g_" + token.getWord()); + } else if (mainblock.isRedefinedFunction(token.getWord())) { + writer.addCode("rfunction_" + token.getWord()); + } else if (type == VariableType.SYSTEM_FUNCTION) { + FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); + if (user_function != null) { + writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); + } else { + String namespace = LeekFunctions.getNamespace(token.getWord()); + writer.addCode("LeekValueManager.getFunction(" + namespace + "." + token.getWord() + ")"); + } + } else if (type == VariableType.SYSTEM_CONSTANT) { + var constant = LeekConstants.get(token.getWord()); + if (constant.getType() == Type.INT) writer.addCode(String.valueOf(constant.getIntValue())); + else if (constant.getType() == Type.REAL) writer.addCode(String.valueOf(constant.getValue())); + else writer.addCode("null"); + } else if (type == VariableType.FUNCTION) { + FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); + writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); + } else { + if (isWrapper()) { + writer.addCode("u_" + token.getWord() + ".getVariable()"); + } else { + writer.addCode("u_" + token.getWord()); + } + } + } + + @Override + public void compileSet(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.setField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.setField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (mainblock.getWordCompiler().getVersion() >= 11) { + writer.addCode("g_" + token.getWord() + " = "); + expr.writeJavaCode(mainblock, writer); + } else { + writer.addCode("g_" + token.getWord() + ".set("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isWrapper()) { + if (expr.isLeftValue()) { + if (mainblock.getWordCompiler().getVersion() <= 10) { + writer.addCode("u_" + token.getWord() + ".setBox("); + } else { + writer.addCode("u_" + token.getWord() + ".set("); + } + expr.compileL(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("u_" + token.getWord() + ".setBoxOrValue("); + expr.compileL(mainblock, writer); + writer.addCode(")"); + } + } else if (isBox()) { + // if (expr.isLeftValue()) { + // writer.addCode("u_" + token.getWord() + " = "); + // expr.compileL(mainblock, writer); + // } else { + writer.addCode("u_" + token.getWord() + ".set("); + expr.compileL(mainblock, writer); + writer.addCode(")"); + // } + } else { + writer.addCode("u_" + token.getWord() + " = "); + expr.writeJavaCode(mainblock, writer); + } + } + } + + @Override + public void compileSetCopy(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.setField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.setField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (mainblock.isRedefinedFunction(token.getWord())) { + writer.addCode("rfunction_" + token.getWord() + ".set("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (mainblock.getWordCompiler().getVersion() >= 11) { + writer.addCode("g_" + token.getWord() + " = "); + // writer.compileClone(mainblock, expr); + expr.writeJavaCode(mainblock, writer); + } else { + writer.addCode("g_" + token.getWord() + ".set("); + // writer.compileClone(mainblock, expr); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isWrapper() || isBox()) { + writer.addCode("u_" + token.getWord() + ".set("); + // writer.compileClone(mainblock, expr); + // expr.writeJavaCode(mainblock, writer); + expr.compileL(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("u_" + token.getWord() + " = "); + // writer.compileClone(mainblock, expr); + expr.writeJavaCode(mainblock, writer); + } + } + } + + @Override + public void compileIncrement(MainLeekBlock mainblock, JavaWriter writer) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.incField(\"" + token.getWord() + "\")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.incField(\"" + token.getWord() + "\")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".increment()"); + } else { + writer.addCode("sub(g_" + token.getWord() + " = add(g_" + token.getWord() + ", 1), 1)"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".increment()"); + } else { + writer.addCode("sub(u_" + token.getWord() + " = add(u_" + token.getWord() + ", 1), 1)"); + } + } + } + + @Override + public void compileDecrement(MainLeekBlock mainblock, JavaWriter writer) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.decField(\"" + token.getWord() + "\")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.decField(\"" + token.getWord() + "\")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".decrement()"); + } else { + writer.addCode("add(g_" + token.getWord() + " = sub(g_" + token.getWord() + ", 1), 1)"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".decrement()"); + } else { + writer.addCode("add(u_" + token.getWord() + " = sub(u_" + token.getWord() + ", 1), 1)"); + } + } + } + + @Override + public void compilePreIncrement(MainLeekBlock mainblock, JavaWriter writer) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.incField(\"" + token.getWord() + "\")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.incField(\"" + token.getWord() + "\")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".pre_increment()"); + } else { + writer.addCode("g_" + token.getWord() + " = add(g_" + token.getWord() + ", 1)"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".pre_increment()"); + } else { + writer.addCode("u_" + token.getWord() + " = add(u_" + token.getWord() + ", 1)"); + } + } + } + + @Override + public void compilePreDecrement(MainLeekBlock mainblock, JavaWriter writer) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.decField(\"" + token.getWord() + "\")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.decField(\"" + token.getWord() + "\")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".pre_decrement()"); + } else { + writer.addCode("g_" + token.getWord() + " = sub(g_" + token.getWord() + ", 1)"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".pre_decrement()"); + } else { + writer.addCode("u_" + token.getWord() + " = sub(u_" + token.getWord() + ", 1)"); + } + } + } + + @Override + public void compileAddEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.addEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.addEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".add_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("g_" + token.getWord() + " = add(g_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".add_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + // writer.addCode("u_" + token.getWord() + " = add(u_" + token.getWord() + ", "); + // expr.writeJavaCode(mainblock, writer); + // writer.addCode(")"); + writer.addCode("u_" + token.getWord() + " = add_eq(u_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } + } + + @Override + public void compileSubEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.subEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.subEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".sub_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("g_" + token.getWord() + " = sub(g_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".sub_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("u_" + token.getWord() + " = sub(u_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } + } + + @Override + public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.mulEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.mulEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".mul_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("g_" + token.getWord() + " = mul(g_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".mul_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("u_" + token.getWord() + " = mul(u_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } + } + + @Override + public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.divEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.divEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".div_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("g_" + token.getWord() + " = div(g_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".div_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("u_" + token.getWord() + " = div(u_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } + } + + @Override + public void compileModEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.modEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.modEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".mod_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("g_" + token.getWord() + " = mod(g_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".mod_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("u_" + token.getWord() + " = mod(u_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } + } + + @Override + public void compileBitOrEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.bitOrEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.bitOrEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".bor_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("g_" + token.getWord() + " = bor(g_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".bor_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("u_" + token.getWord() + " = bor(u_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } + } + + + @Override + public void compileBitAndEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.bitAndEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.bitAndEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".band_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("g_" + token.getWord() + " = band(g_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".band_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("u_" + token.getWord() + " = band(u_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } + } + + + @Override + public void compileBitXorEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.bitXorEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.bitXorEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".bxor_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("g_" + token.getWord() + " = bxor(g_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".bxor_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("u_" + token.getWord() + " = bxor(u_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } + } + + @Override + public void compileShiftLeftEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.shlEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.shlEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".shl_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("g_" + token.getWord() + " = shl(g_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".shl_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("u_" + token.getWord() + " = shl(u_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } + } + + @Override + public void compileShiftRightEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.shrEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.shrEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".shr_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("g_" + token.getWord() + " = shr(g_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".shr_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("u_" + token.getWord() + " = shr(u_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } + } + + @Override + public void compileShiftUnsignedRightEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.ushrEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.ushrEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".ushr_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("g_" + token.getWord() + " = ushr(g_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".ushr_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("u_" + token.getWord() + " = ushr(u_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } + } } diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 5b82d708..923df3a9 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -279,18 +279,85 @@ public void analyze(WordCompiler compiler) { } public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { + mainblock.getWordCompiler().setCurrentClass(this); + // Declare the class as a field of the AI - String className = "user_" + token.getWord(); - writer.addLine("private ClassLeekValue " + className + " = new ClassLeekValue(\"" + token.getWord() + "\");"); + String className = "u_" + token.getWord(); + writer.addLine("private ClassLeekValue " + className + " = new ClassLeekValue(this, \"" + token.getWord() + "\");"); + + // Static methods + for (Entry> method : staticMethods.entrySet()) { + for (Entry version : method.getValue().entrySet()) { + String methodName = className + "_" + method.getKey() + "_" + version.getKey(); + writer.addCode("private final Object " + methodName + "("); + int i = 0; + for (var arg : version.getValue().block.getParameters()) { + if (i++ > 0) writer.addCode(", "); + writer.addCode("Object u_" + arg); + } + writer.addCode(") throws LeekRunException {"); + writer.addLine("final var u_class = " + className + ";", version.getValue().block.getLine(), version.getValue().block.getFile()); + if (parent != null) { + writer.addLine("final var u_super = u_" + parent.token.getWord() + ";"); + } + version.getValue().block.writeJavaCode(mainblock, writer); + writer.addLine("}"); + } + } + + // Methods + for (Entry> method : methods.entrySet()) { + for (Entry version : method.getValue().entrySet()) { + String methodName = className + "_" + method.getKey() + "_" + version.getKey(); + writer.addCode("private final Object " + methodName + "(ObjectLeekValue u_this"); + for (var arg : version.getValue().block.getParameters()) { + writer.addCode(", Object u_" + arg); + } + // if (version.getValue().getParameters().size() == 0) { + // writer.addCode(", Object __"); + // } + writer.addCode(") throws LeekRunException {"); + writer.addLine("final var u_class = " + className + ";", version.getValue().block.getLine(), version.getValue().block.getFile()); + if (parent != null) { + writer.addLine("final var u_super = u_" + parent.token.getWord() + ";"); + } + writer.addCounter(1); + version.getValue().block.writeJavaCode(mainblock, writer); + writer.addLine("}"); + } + } + + // Constructeurs + for (Entry construct : constructors.entrySet()) { + String methodName = className + "_" + construct.getKey(); + writer.addCode("private final Object " + methodName + "(ObjectLeekValue u_this"); + for (var arg : construct.getValue().block.getParameters()) { + writer.addCode(", Object u_" + arg); + } + // if (construct.getValue().getParameters().size() == 0) { + // writer.addCode(", Object __"); + // } + writer.addCode(") throws LeekRunException {"); + writer.addLine("final var u_class = " + className + ";"); + if (parent != null) { + writer.addLine("final var u_super = u_" + parent.token.getWord() + ";"); + } + construct.getValue().block.writeJavaCode(mainblock, writer); + writer.addLine("}"); + } } public void createJava(MainLeekBlock mainblock, JavaWriter writer) { + + mainblock.getWordCompiler().setCurrentClass(this); + // Create the class in the constructor of the AI - String className = "user_" + token.getWord(); + String className = "u_" + token.getWord(); if (parent != null) { - writer.addLine(className + ".setParent(user_" + parent.getName() + ");"); + writer.addLine(className + ".setParent(u_" + parent.getName() + ");"); } + writer.addCode(className + ".initFields = new LeekAnonymousFunction() {"); writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue u_this, AbstractLeekValue... values) throws LeekRunException {"); ClassDeclarationInstruction current = this; @@ -300,7 +367,7 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { if (field.getValue().expression != null) { field.getValue().expression.writeJavaCode(mainblock, writer); } else { - writer.addCode("LeekValueManager.NULL"); + writer.addCode("null"); } writer.addLine(", AccessLevel." + field.getValue().level + ");"); } @@ -309,56 +376,45 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine("return null;"); writer.addLine("}};"); - for (Entry> method : staticMethods.entrySet()) { - for (Entry version : method.getValue().entrySet()) { - String methodName = className + "_" + method.getKey() + "_" + version.getKey(); - writer.addCode("final LeekAnonymousFunction " + methodName + " = new LeekAnonymousFunction() {"); - writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue u_this, AbstractLeekValue... values) throws LeekRunException {"); - writer.addLine("final var u_class = " + className + ";", version.getValue().block.getLine(), version.getValue().block.getFile()); - if (parent != null) { - writer.addLine("final var u_super = user_" + parent.token.getWord() + ";"); - } - version.getValue().block.writeJavaCode(mainblock, writer); - writer.addLine("}};"); - } - } - - for (Entry> method : methods.entrySet()) { - for (Entry version : method.getValue().entrySet()) { - writer.currentBlock = version.getValue().block; - String methodName = className + "_" + method.getKey() + "_" + version.getKey(); - writer.addCode("final LeekAnonymousFunction " + methodName + " = new LeekAnonymousFunction() {"); - writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue u_this, AbstractLeekValue... values) throws LeekRunException {"); - writer.addLine("final var u_class = " + className + ";", version.getValue().block.getLine(), version.getValue().block.getFile()); - if (parent != null) { - writer.addLine("final var u_super = user_" + parent.token.getWord() + ";"); - } - writer.addCounter(1); - version.getValue().block.writeJavaCode(mainblock, writer); - writer.addLine("}};"); - writer.currentBlock = null; + for (Entry field : staticFields.entrySet()) { + writer.addCode(className); + writer.addCode(".addStaticField(\"" + field.getKey() + "\", "); + if (field.getValue() != null) { + field.getValue().expression.writeJavaCode(mainblock, writer); + } else { + writer.addCode("null"); } + writer.addCode(", AccessLevel." + field.getValue().level); + writer.addLine(");"); } writeFields(mainblock, writer, className); - for (Entry> method : staticMethods.entrySet()) { - for (Entry version : method.getValue().entrySet()) { + // Static methods + for (var method : staticMethods.entrySet()) { + for (var version : method.getValue().entrySet()) { String methodName = className + "_" + method.getKey() + "_" + version.getKey(); writer.addCode(className); - writer.addLine(".addStaticMethod(\"" + method.getKey() + "\", " + version.getKey() + ", " + methodName + ", AccessLevel." + version.getValue().level + ");"); + writer.addCode(".addStaticMethod(\"" + method.getKey() + "\", " + version.getKey() + ", new LeekFunction() { public Object run(Object... args) throws LeekRunException { return " + methodName + "("); + int i = 0; + for (var arg : version.getValue().block.getParameters()) { + if (i > 0) writer.addCode(", "); + writer.addCode("args[" + i + "]"); + i++; + } + writer.addLine("); }});"); } writer.addCode(className); writer.addLine(".addGenericStaticMethod(\"" + method.getKey() + "\");"); } - for (Entry construct : constructors.entrySet()) { + for (var construct : constructors.entrySet()) { + String methodName = className + "_" + construct.getKey(); writer.addCode(className); - writer.addLine(".addConstructor(" + construct.getKey() + ", new LeekAnonymousFunction() {"); - writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue u_this, AbstractLeekValue... values) throws LeekRunException {"); - writer.addLine("final var u_class = " + className + ";"); - if (parent != null) { - writer.addLine("final var u_super = user_" + parent.token.getWord() + ";"); + writer.addCode(".addConstructor(" + construct.getKey() + ", new LeekAnonymousFunction() { public Object run(ObjectLeekValue thiz, Object... args) throws LeekRunException { return " + methodName + "(thiz"); + int i = 0; + for (var arg : construct.getValue().block.getParameters()) { + writer.addCode(", args[" + i++ + "]"); } if (construct.getValue().block != null) { construct.getValue().block.writeJavaCode(mainblock, writer); @@ -368,11 +424,16 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine("}});"); } - for (Entry> method : methods.entrySet()) { - for (Entry version : method.getValue().entrySet()) { + for (var method : methods.entrySet()) { + for (var version : method.getValue().entrySet()) { String methodName = className + "_" + method.getKey() + "_" + version.getKey(); writer.addCode(className); - writer.addLine(".addMethod(\"" + method.getKey() + "\", " + version.getKey() + ", " + methodName + ", AccessLevel." + version.getValue().level + ");"); + writer.addCode(".addMethod(\"" + method.getKey() + "\", " + version.getKey() + ", new LeekAnonymousFunction() { public Object run(ObjectLeekValue thiz, Object... args) throws LeekRunException { return " + methodName + "(thiz"); + int i = 0; + for (var arg : version.getValue().block.getParameters()) { + writer.addCode(", args[" + i++ + "]"); + } + writer.addLine("); }});"); } writer.addCode(className); writer.addLine(".addGenericMethod(\"" + method.getKey() + "\");"); @@ -412,7 +473,7 @@ private void writeFields(MainLeekBlock mainblock, JavaWriter writer, String clas for (Entry field : fields.entrySet()) { writer.addCode(className); - writer.addCode(".addField(mUAI, \"" + field.getKey() + "\""); + writer.addCode(".addField(" + writer.getAIThis() + ", \"" + field.getKey() + "\""); writer.addCode(", AccessLevel." + field.getValue().level); writer.addLine(");"); } diff --git a/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java index 21dcde53..781ae259 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java @@ -5,10 +5,17 @@ import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.AbstractExpression; +import leekscript.compiler.expression.LeekAnonymousFunction; import leekscript.compiler.expression.LeekBoolean; +import leekscript.compiler.expression.LeekExpression; import leekscript.compiler.expression.LeekNull; +import leekscript.compiler.expression.LeekNumber; +import leekscript.compiler.expression.LeekObjectAccess; +import leekscript.compiler.expression.LeekString; +import leekscript.compiler.expression.LeekTabularValue; import leekscript.compiler.expression.LeekTernaire; import leekscript.compiler.expression.LeekVariable; +import leekscript.compiler.expression.Operators; public class LeekExpressionInstruction implements LeekInstruction { @@ -29,20 +36,30 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if (mExpression.trim() instanceof LeekTernaire || mExpression.trim() instanceof LeekNull || mExpression.trim() instanceof LeekBoolean) { - writer.addCode("nothing("); - mExpression.writeJavaCode(mainblock, writer); - writer.addLine(");", mLine, mAI); + + // Simple values are not compiled + var trimmed = mExpression.trim(); + if (trimmed instanceof LeekExpression && ((LeekExpression) trimmed).getOperator() == Operators.REFERENCE) { + trimmed = ((LeekExpression) trimmed).getExpression1(); + } + if (trimmed instanceof LeekNull || trimmed instanceof LeekBoolean || trimmed instanceof LeekNumber || trimmed instanceof LeekString || trimmed instanceof LeekVariable || trimmed instanceof LeekObjectAccess || trimmed instanceof LeekTabularValue || trimmed instanceof LeekAnonymousFunction) { + return; } - else { - if (mExpression instanceof LeekVariable) { - // We don't write a code like "variable;", useless and not - // authorized by Java - } else { - mExpression.writeJavaCode(mainblock, writer); - writer.addLine(";", mLine, mAI); - } + + // Wrap an expression with a function call to avoid 'error: not a statement' error + if (trimmed instanceof LeekTernaire || (trimmed instanceof LeekExpression && ((LeekExpression) trimmed).needsWrapper())) { + writer.addCode("ops("); + trimmed.writeJavaCode(mainblock, writer); + writer.addCode(", " + trimmed.getOperations() + ")"); + } else { + if (trimmed.getOperations() > 0) writer.addCode("ops("); + trimmed.writeJavaCode(mainblock, writer); + if (trimmed.getOperations() > 0) writer.addCode(", " + trimmed.getOperations() + ")"); } + // if (trimmed.getOperations() > 0) { + // writer.addCode("; ops(" + trimmed.getOperations() + ")"); + // } + writer.addLine(";", mLine, mAI); } @Override diff --git a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java index 3099fa75..17379311 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java @@ -41,10 +41,23 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addCode("if (!globale_init_" + token.getWord() + ") { globale_" + token.getWord() + " = new VariableLeekValue(mUAI, "); - if(mValue != null) mValue.writeJavaCode(mainblock, writer); - else writer.addCode("LeekValueManager.NULL"); - writer.addCode("); globale_init_" + token.getWord() + " = true;"); + writer.addCode("if (!g_init_" + token.getWord() + ") { "); + if (mainblock.getWordCompiler().getVersion() >= 11) { + writer.addCode("g_" + token.getWord() + " = "); + if (mValue != null) { + if (mValue.getOperations() > 0) writer.addCode("ops("); + mValue.writeJavaCode(mainblock, writer); + if (mValue.getOperations() > 0) writer.addCode(", " + mValue.getOperations() + ")"); + } + else writer.addCode("null"); + } else { + writer.addCode("g_" + token.getWord() + " = new Box(" + writer.getAIThis() + ", "); + if (mValue != null) mValue.writeJavaCode(mainblock, writer); + else writer.addCode("null"); + writer.addCode(", " + (mValue != null ? mValue.getOperations() : 0) + ")"); + } + writer.addCode("; g_init_" + token.getWord() + " = true;"); + if (mainblock.getWordCompiler().getVersion() >= 11) writer.addCode(" ops(1);"); writer.addLine(" }", mLine, mAI); } diff --git a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java index 1bbe1d06..f6eb5048 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java @@ -5,6 +5,8 @@ import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.AbstractExpression; +import leekscript.compiler.expression.LeekExpression; +import leekscript.compiler.expression.Operators; public class LeekReturnInstruction implements LeekInstruction { @@ -26,10 +28,22 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("return "); - if (mExpression == null) - writer.addCode("LeekValueManager.NULL;"); - else { - mExpression.writeJavaCode(mainblock, writer); + if (mExpression == null) { + writer.addCode("null;"); + } else { + if (mExpression.getOperations() > 0) writer.addCode("ops("); + var finalExpression = mExpression.trim(); + boolean isRef = finalExpression instanceof LeekExpression && ((LeekExpression) finalExpression).getOperator() == Operators.REFERENCE; + if (mainblock.getWordCompiler().getVersion() == 10) { + if (isRef || !finalExpression.isLeftValue()) { + finalExpression.writeJavaCode(mainblock, writer); + } else { + finalExpression.compileL(mainblock, writer); + } + } else { + finalExpression.compileL(mainblock, writer); + } + if (finalExpression.getOperations() > 0) writer.addCode(", " + finalExpression.getOperations() + ")"); writer.addLine(";", mLine, mAI); } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index e8218f4f..6a90fda3 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -10,7 +10,9 @@ import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekAnonymousFunction; +import leekscript.compiler.expression.LeekExpression; import leekscript.compiler.expression.LeekVariable; +import leekscript.compiler.expression.Operators; import leekscript.compiler.expression.LeekVariable.VariableType; import leekscript.common.Error; import leekscript.common.Type; @@ -61,16 +63,82 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - if (!captured || !(mValue instanceof LeekAnonymousFunction)) { - writer.addCode("final VariableLeekValue user_" + token.getWord() + " = new VariableLeekValue(mUAI, "); - if (mValue != null) mValue.writeJavaCode(mainblock, writer); - else writer.addCode("LeekValueManager.NULL"); - writer.addLine(");", mLine, mAI); + if (this.captured) { + if (mValue instanceof LeekAnonymousFunction) { + writer.addCode("final Wrapper u_" + token.getWord() + " = new Wrapper(new Box(" + writer.getAIThis() + ", null)); u_" + token.getWord() + ".set("); + mValue.writeJavaCode(mainblock, writer); + writer.addLine(");", mLine, mAI); + } else if (mValue instanceof LeekExpression && ((LeekExpression) mValue).getOperator() == Operators.REFERENCE) { + var e = ((LeekExpression) mValue).getExpression2(); + if (e.isLeftValue()) { + writer.addCode("final Wrapper u_" + token.getWord() + " = new Wrapper("); + e.compileL(mainblock, writer); + writer.addLine(", " + e.getOperations() + ")"); + } else { + writer.addCode("final var u_" + token.getWord() + " = new Wrapper(new Box(" + writer.getAIThis() + ", "); + e.writeJavaCode(mainblock, writer); + writer.addLine("), " + e.getOperations() + ")"); + } + writer.addLine(";", mLine, mAI); + } else { + writer.addCode("final var u_" + token.getWord() + " = new Wrapper(new Box(" + writer.getAIThis() + ", "); + if (mValue != null) mValue.writeJavaCode(mainblock, writer); + else writer.addCode("null"); + writer.addLine(")"); + if (mValue != null && mValue.getOperations() > 0) { + writer.addCode(", " + mValue.getOperations()); + } + writer.addLine(");", mLine, mAI); + } } else { - writer.addCode("final VariableLeekValue user_" + token.getWord() + " = new VariableLeekValue(mUAI); user_" + token.getWord() + ".init(mUAI, "); - if (mValue != null) mValue.writeJavaCode(mainblock, writer); - else writer.addCode("LeekValueManager.NULL"); - writer.addLine(");", mLine, mAI); + if (mainblock.getWordCompiler().getVersion() <= 10) { + if (mValue instanceof LeekExpression && ((LeekExpression) mValue).getOperator() == Operators.REFERENCE) { + var e = ((LeekExpression) mValue).getExpression2(); + if (e.isLeftValue()) { + // writer.addCode("Box u_" + token.getWord() + " = "); + // e.compileL(mainblock, writer); + writer.addCode("var u_" + token.getWord() + " = new Box(" + writer.getAIThis() + ", "); + // e.compileL(mainblock, writer); + e.writeJavaCode(mainblock, writer); + if (mValue.getOperations() > 0) { + writer.addCode(", " + mValue.getOperations()); + } + writer.addLine(")"); + } else { + writer.addCode("var u_" + token.getWord() + " = new Box(" + writer.getAIThis() + ", "); + // e.writeJavaCode(mainblock, writer); + mValue.compileL(mainblock, writer); + if (mValue.getOperations() > 0) { + writer.addCode(", " + mValue.getOperations()); + } + writer.addLine(")"); + } + writer.addLine(";", mLine, mAI); + } else { + writer.addCode("var u_" + token.getWord() + " = new Box(" + writer.getAIThis() + ", "); + if (mValue != null) { + if (mValue.isLeftValue()) { + writer.compileClone(mainblock, mValue); + } else { + mValue.compileL(mainblock, writer); + // mValue.writeJavaCode(mainblock, writer); + } + if (mValue.getOperations() > 0) { + writer.addCode(", " + mValue.getOperations()); + } + } else { + writer.addCode("null"); + } + writer.addLine(");", mLine, mAI); + } + } else { + writer.addCode("Object u_" + token.getWord() + " = "); + writer.addCode("ops("); + if (mValue != null) mValue.writeJavaCode(mainblock, writer); + else writer.addCode("null"); + writer.addCode(", " + (1 + (mValue == null ? 0 : mValue.getOperations())) + ")"); + writer.addLine(";", mLine, mAI); + } } } diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 0ed9de8b..7451eed9 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -4,27 +4,37 @@ import leekscript.compiler.LeekScript; import leekscript.compiler.RandomGenerator; import leekscript.runner.PhpArray.Element; -import leekscript.runner.values.AbstractLeekValue; import leekscript.runner.values.ArrayLeekValue; -import leekscript.runner.values.NullLeekValue; -import leekscript.runner.values.StringLeekValue; -import leekscript.runner.values.VariableLeekValue; +import leekscript.runner.values.ClassLeekValue; +import leekscript.runner.values.FunctionLeekValue; +import leekscript.runner.values.LeekValue; +import leekscript.runner.values.ObjectLeekValue; +import leekscript.runner.values.Box; import leekscript.runner.values.ArrayLeekValue.ArrayIterator; import leekscript.common.Error; import java.util.Comparator; -import java.util.Iterator; +import java.util.Set; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; public abstract class AI { + public static final int DOUBLE = 1; + public static final int INT = 2; + public static final int BOOLEAN = 3; + public static final int STRING = 4; + public static final int NULL = 5; + public static final int ARRAY = 6; + public static final int NUMBER = 7; + public static final int FUNCTION = 8; + public static final int ERROR_LOG_COST = 1000; public final static int MAX_MEMORY = 100000; - protected long mOperations = 0; + protected int mOperations = 0; public final static int MAX_OPERATIONS = 20000000; public int maxOperations = MAX_OPERATIONS; @@ -34,7 +44,7 @@ public abstract class AI { protected int id; protected int version; protected AILog logs; - protected AI mUAI; + // protected AI mUAI; protected int mInstructions; protected RandomGenerator randomGenerator; private long analyzeTime; @@ -44,8 +54,6 @@ public abstract class AI { public AI(int instructions, int version) { this.mInstructions = instructions; this.version = version; - - mUAI = this; logs = new AILog(); randomGenerator = LeekScript.getRandom(); try { @@ -68,7 +76,12 @@ public int getInstructions() { return mInstructions; } - public long getOperations() { + public int operations() { + return mOperations; + } + + public int getOperations() throws LeekRunException { + ops(LeekFunctions.getOperations.getOperations()); return mOperations; } @@ -76,14 +89,31 @@ public AILog getLogs() { return logs; } - public void addOperations(int nb) throws LeekRunException { + public void ops(int nb) throws LeekRunException { + // System.out.println("ops " + nb); mOperations += nb; if (mOperations >= maxOperations) { throw new LeekRunException(LeekRunException.TOO_MUCH_OPERATIONS); } } + public Object ops(Object x, int nb) throws LeekRunException { + ops(nb); + return x; + } + + public int ops(int x, int nb) throws LeekRunException { + ops(nb); + return x; + } + + public boolean ops(boolean x, int nb) throws LeekRunException { + ops(nb); + return x; + } + public void addOperationsNoCheck(int nb) { + // System.out.println("ops " + nb); mOperations += nb; } @@ -91,8 +121,8 @@ public void resetCounter() { mOperations = 0; } - protected NullLeekValue nothing(AbstractLeekValue obj) throws LeekRunException { - return LeekValueManager.NULL; + protected Object nothing(Object obj) throws LeekRunException { + return null; } public String getErrorMessage(StackTraceElement[] elements) { @@ -121,8 +151,12 @@ public String getErrorMessage(Throwable e) { protected String getErrorLocalisation(int line) { if (mErrorObject == null) { mErrorObject = new JSONArray(); - for (String error : getErrorString()) { - mErrorObject.add(JSON.parseArray(error)); + var errorString = getErrorString(); + if (errorString != null) { + // System.out.println("errorString = " + errorString.length); + for (String error : errorString) { + mErrorObject.add(JSON.parseArray(error)); + } } thisObject = getAIString(); } @@ -145,155 +179,360 @@ protected String getErrorLocalisation(int line) { return ""; } - public AbstractLeekValue color(AbstractLeekValue red, AbstractLeekValue green, AbstractLeekValue blue) throws LeekRunException { - return LeekValueManager.getLeekIntValue(((red.getInt(this) & 255) << 16) | ((green.getInt(this) & 255) << 8) | (blue.getInt(this) & 255)); - } - - public int typeOf(AbstractLeekValue value) { - if (value.getType() == AbstractLeekValue.ARRAY) - return (int) LeekConstants.TYPE_ARRAY.getValue(); - if (value.getType() == AbstractLeekValue.NULL) - return (int) LeekConstants.TYPE_NULL.getValue(); - if (value.getType() == AbstractLeekValue.STRING) - return (int) LeekConstants.TYPE_STRING.getValue(); - if (value.getType() == AbstractLeekValue.NUMBER) - return (int) LeekConstants.TYPE_NUMBER.getValue(); - if (value.getType() == AbstractLeekValue.BOOLEAN) - return (int) LeekConstants.TYPE_BOOLEAN.getValue(); - if (value.getType() == AbstractLeekValue.FUNCTION) - return (int) LeekConstants.TYPE_FUNCTION.getValue(); - if (value.getType() == AbstractLeekValue.OBJECT) - return (int) LeekConstants.TYPE_OBJECT.getValue(); + public int abs(int x) throws LeekRunException { + ops(LeekFunctions.abs.getOperations()); + return Math.abs(x); + } + + public double abs(Number x) throws LeekRunException { + ops(LeekFunctions.abs.getOperations()); + return Math.abs(x.doubleValue()); + } + + public Object abs(Object... args) throws LeekRunException { + if (check("abs", new int[] { NUMBER }, args)) { + ops(LeekFunctions.abs.getOperations()); + if (args[0] instanceof Integer) { + return Math.abs(((Integer) args[0]).intValue()); + } + return Math.abs(((Number) args[0]).doubleValue()); + } + return 0; + } + + public int ceil(int x) throws LeekRunException { + ops(LeekFunctions.ceil.getOperations()); + return x; + } + + public int ceil(double x) throws LeekRunException { + ops(LeekFunctions.ceil.getOperations()); + return (int) Math.ceil(x); + } + + public int ceil(Object... args) throws LeekRunException { + if (check("ceil", new int[] { NUMBER }, args)) { + ops(LeekFunctions.ceil.getOperations()); + return (int) Math.ceil(((Number) args[0]).doubleValue()); + } + return 0; + } + + public int floor(Number x) throws LeekRunException { + ops(LeekFunctions.floor.getOperations()); + return (int) Math.floor(x.doubleValue()); + } + + public int floor(double x) throws LeekRunException { + ops(LeekFunctions.floor.getOperations()); + return (int) Math.floor(x); + } + + public int floor(Object... args) throws LeekRunException { + if (check("floor", new int[] { NUMBER }, args)) { + ops(LeekFunctions.floor.getOperations()); + return (int) Math.floor(((Number) args[0]).doubleValue()); + } + return 0; + } + + public int round(int x) throws LeekRunException { + ops(LeekFunctions.round.getOperations()); + return x; + } + + public int round(double x) throws LeekRunException { + ops(LeekFunctions.round.getOperations()); + return (int) Math.round(x); + } + + public int round(Object... args) throws LeekRunException { + if (check("round", new int[] { NUMBER }, args)) { + ops(LeekFunctions.round.getOperations()); + return (int) Math.round(((Number) args[0]).doubleValue()); + } + return 0; + } + + public double cos(double x) throws LeekRunException { + ops(LeekFunctions.cos.getOperations()); + return Math.cos(x); + } + + public double cos(Object... args) throws LeekRunException { + if (check("cos", new int[] { NUMBER }, args)) { + ops(LeekFunctions.cos.getOperations()); + return Math.cos(((Number) args[0]).doubleValue()); + } + return 0; + } + + public double acos(double x) throws LeekRunException { + ops(LeekFunctions.acos.getOperations()); + return Math.acos(x); + } + + public double acos(Object... args) throws LeekRunException { + if (check("acos", new int[] { NUMBER }, args)) { + ops(LeekFunctions.acos.getOperations()); + return Math.acos(((Number) args[0]).doubleValue()); + } + return 0; + } + + public double sin(double x) throws LeekRunException { + ops(LeekFunctions.sin.getOperations()); + return Math.sin(x); + } + + public double sin(Object... args) throws LeekRunException { + if (check("sin", new int[] { NUMBER }, args)) { + ops(LeekFunctions.sin.getOperations()); + return Math.sin(((Number) args[0]).doubleValue()); + } return 0; } + public double asin(double x) throws LeekRunException { + ops(LeekFunctions.asin.getOperations()); + return Math.asin(x); + } + + public double asin(Object... args) throws LeekRunException { + if (check("asin", new int[] { NUMBER }, args)) { + ops(LeekFunctions.asin.getOperations()); + return Math.asin(((Number) args[0]).doubleValue()); + } + return 0; + } + + public double tan(double x) throws LeekRunException { + ops(LeekFunctions.tan.getOperations()); + return Math.tan(x); + } + + public double tan(Object... args) throws LeekRunException { + if (check("tan", new int[] { NUMBER }, args)) { + ops(LeekFunctions.tan.getOperations()); + return Math.tan(((Number) args[0]).doubleValue()); + } + return 0; + } + + public double atan(double x) throws LeekRunException { + ops(LeekFunctions.atan.getOperations()); + return Math.atan(x); + } + + public double atan(Object... args) throws LeekRunException { + if (check("atan", new int[] { NUMBER }, args)) { + ops(LeekFunctions.atan.getOperations()); + return Math.atan(((Number) args[0]).doubleValue()); + } + return 0; + } + + public int count(ArrayLeekValue array) throws LeekRunException { + ops(LeekFunctions.count.getOperations()); + return array.size(); + } + + public int count(Object... args) throws LeekRunException { + if (check("count", new int[] { ARRAY }, args)) { + ops(LeekFunctions.count.getOperations()); + var array = (ArrayLeekValue) args[0]; + return array.size(); + } + return 0; + } + + public Object debug(Object x) throws LeekRunException { + String p = LeekValueManager.getString(this, x); + getLogs().addLog(AILog.STANDARD, p); + ops(p.length()); + ops(LeekFunctions.debug.getOperations()); + return null; + } + + public Object debugW(Object x) throws LeekRunException { + String p = LeekValueManager.getString(this, x); + getLogs().addLog(AILog.WARNING, p); + ops(p.length()); + ops(LeekFunctions.debug.getOperations()); + return null; + } + + public Object debugE(Object x) throws LeekRunException { + String p = LeekValueManager.getString(this, x); + getLogs().addLog(AILog.ERROR, p); + ops(p.length()); + ops(LeekFunctions.debug.getOperations()); + return null; + } + + public int color(Object red, Object green, Object blue) throws LeekRunException { + int r = integer(red); + int g = integer(green); + int b = integer(blue); + return ((r & 255) << 16) | ((g & 255) << 8) | (b & 255); + } + public void arrayFlatten(ArrayLeekValue array, ArrayLeekValue retour, int depth) throws LeekRunException { - for (AbstractLeekValue value : array) { + for (var value : array) { if (value.getValue() instanceof ArrayLeekValue && depth > 0) { - arrayFlatten(value.getArray(), retour, depth - 1); + arrayFlatten((ArrayLeekValue) value.getValue(), retour, depth - 1); } else - retour.push(this, LeekOperations.clone(this, value)); + retour.push(this, LeekOperations.clone(this, value.getValue())); } } - public AbstractLeekValue arrayFoldLeft(ArrayLeekValue array, AbstractLeekValue function, AbstractLeekValue start_value) throws LeekRunException { - AbstractLeekValue result = LeekOperations.clone(this, start_value); - // AbstractLeekValue prev = null; - for (AbstractLeekValue value : array) { - result = function.executeFunction(this, new AbstractLeekValue[] { result, value }); + public Object arrayFoldLeft(ArrayLeekValue array, FunctionLeekValue function, Object start_value) throws LeekRunException { + Object result = LeekOperations.clone(this, start_value); + for (var value : array) { + result = function.execute(this, result, value.getValue()); } return result; } - public AbstractLeekValue arrayFoldRight(ArrayLeekValue array, AbstractLeekValue function, AbstractLeekValue start_value) throws LeekRunException { - AbstractLeekValue result = LeekOperations.clone(this, start_value); - // AbstractLeekValue prev = null; - Iterator it = array.getReversedIterator(); + public Object arrayFoldRight(ArrayLeekValue array, FunctionLeekValue function, Object start_value) throws LeekRunException { + Object result = LeekOperations.clone(this, start_value); + // Object prev = null; + var it = array.getReversedIterator(); while (it.hasNext()) { - result = function.executeFunction(this, new AbstractLeekValue[] { it.next(), result }); + result = function.execute(this, it.next(), result); } return result; } - public AbstractLeekValue arrayPartition(ArrayLeekValue array, AbstractLeekValue function) throws LeekRunException { + public ArrayLeekValue arrayPartition(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { ArrayLeekValue list1 = new ArrayLeekValue(); ArrayLeekValue list2 = new ArrayLeekValue(); int nb = function.getArgumentsCount(this); if (nb != 1 && nb != 2) return new ArrayLeekValue(); - // VariableLeekValue value = new VariableLeekValue(this, LeekValueManager.NULL); ArrayIterator iterator = array.getArrayIterator(); boolean b; while (!iterator.ended()) { - // value.setNoOps(this, iterator.getValueReference()); + var value = iterator.getValueBox(); if (nb == 1) - b = function.executeFunction(this, new AbstractLeekValue[] { iterator.getValueReference() }).getBoolean(); + b = bool(LeekValueManager.execute(this, function, new Object[] { value })); else - b = function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), iterator.getValueReference() }).getBoolean(); - // iterator.setValue(this, value); - (b ? list1 : list2).getOrCreate(this, iterator.getKey(this)).setNoOps(this, iterator.getValue(this)); + b = bool(LeekValueManager.execute(this, function, new Object[] { iterator.getKey(this), value })); + (b ? list1 : list2).getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); iterator.next(); } - return new ArrayLeekValue(this, new AbstractLeekValue[] { list1, list2 }, false); + return new ArrayLeekValue(this, new Object[] { list1, list2 }, false); } - public ArrayLeekValue arrayMap(ArrayLeekValue array, AbstractLeekValue function) throws LeekRunException { + public ArrayLeekValue arrayMap(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { ArrayLeekValue retour = new ArrayLeekValue(); ArrayIterator iterator = array.getArrayIterator(); int nb = function.getArgumentsCount(this); if (nb != 1 && nb != 2) return retour; - // VariableLeekValue value = new VariableLeekValue(this, LeekValueManager.NULL); while (!iterator.ended()) { - // value.setNoOps(this, iterator.getValueReference()); + var value = iterator.value(); if (nb == 1) - retour.getOrCreate(this, iterator.getKey(this).getValue()).setNoOps(this, function.executeFunction(this, new AbstractLeekValue[] { iterator.getValueReference() })); + retour.getOrCreate(this, iterator.getKey(this)).set(LeekValueManager.execute(this, function, value)); else - retour.getOrCreate(this, iterator.getKey(this).getValue()).setNoOps(this, function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), iterator.getValueReference() })); - // iterator.setValue(this, value); + retour.getOrCreate(this, iterator.getKey(this)).set(LeekValueManager.execute(this, function, iterator.getKey(this), value)); iterator.next(); } return retour; } - public ArrayLeekValue arrayFilter(ArrayLeekValue array, AbstractLeekValue function) throws LeekRunException { + public ArrayLeekValue arrayMapV10(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { + ArrayLeekValue retour = new ArrayLeekValue(); + ArrayIterator iterator = array.getArrayIterator(); + int nb = function.getArgumentsCount(this); + if (nb != 1 && nb != 2) + return retour; + while (!iterator.ended()) { + var value = iterator.getValueBox(); + if (nb == 1) + retour.getOrCreate(this, iterator.getKey(this)).setRef(LeekValueManager.execute(this, function, value)); + else + retour.getOrCreate(this, iterator.getKey(this)).setRef(LeekValueManager.execute(this, function, iterator.getKey(this), value)); + iterator.next(); + } + return retour; + } + + public ArrayLeekValue arrayFilterV10(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { ArrayLeekValue retour = new ArrayLeekValue(); ArrayIterator iterator = array.getArrayIterator(); int nb = function.getArgumentsCount(this); if (nb != 1 && nb != 2) return retour; - boolean b; while (!iterator.ended()) { + var value = iterator.getValueBox(); if (nb == 1) { - b = function.executeFunction(this, new AbstractLeekValue[] { iterator.getValueReference() }).getBoolean(); - if (b) { - if (getVersion() >= 11) - retour.push(this, iterator.getValue(this).getValue()); - else - // In LeekScript < 1.0, arrayFilter had a bug, the result array was not reindexed - retour.getOrCreate(this, iterator.getKey(this).getValue()).setNoOps(this, iterator.getValue(this).getValue()); + if (bool(LeekValueManager.execute(this, function, new Object[] { value }))) { + // In LeekScript < 1.0, arrayFilter had a bug, the result array was not reindexed + retour.getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); } } else { - b = function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), iterator.getValueReference() }).getBoolean(); - if (b) - if (getVersion() >= 11) - retour.push(this, iterator.getValue(this).getValue()); - else - retour.getOrCreate(this, iterator.getKey(this).getValue()).setNoOps(this, iterator.getValue(this).getValue()); + if (bool(LeekValueManager.execute(this, function, new Object[] { iterator.getKey(this), value }))) { + retour.getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); + } } iterator.next(); } return retour; } - public AbstractLeekValue arrayIter(ArrayLeekValue array, AbstractLeekValue function) throws LeekRunException { + public ArrayLeekValue arrayFilter(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { + ArrayLeekValue retour = new ArrayLeekValue(); ArrayIterator iterator = array.getArrayIterator(); int nb = function.getArgumentsCount(this); if (nb != 1 && nb != 2) - return LeekValueManager.NULL; - // VariableLeekValue value = new VariableLeekValue(this, LeekValueManager.NULL); + return retour; while (!iterator.ended()) { - // value.setNoOps(this, iterator.getValueReference()); - if (nb == 1) - function.executeFunction(this, new AbstractLeekValue[] { iterator.getValueReference() }); - else - function.executeFunction(this, new AbstractLeekValue[] { iterator.getKey(this), iterator.getValueReference() }); - // iterator.setValue(this, value); + var value = iterator.value(); + if (nb == 1) { + if (bool(LeekValueManager.execute(this, function, new Object[] { value }))) { + retour.push(this, iterator.getValue(this)); + } + } else { + if (bool(LeekValueManager.execute(this, function, new Object[] { iterator.getKey(this), value }))) { + retour.push(this, iterator.getValue(this)); + } + } iterator.next(); } - return LeekValueManager.NULL; + return retour; } - public AbstractLeekValue arraySort(ArrayLeekValue origin, final AbstractLeekValue function) throws LeekRunException { + public Object arrayIter(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { + ArrayIterator iterator = array.getArrayIterator(); + if (function == null) { + return null; + } + int nb = function.getArgumentsCount(this); + if (nb != 1 && nb != 2) + return null; + while (!iterator.ended()) { + var value = iterator.getValueBox(); + if (nb == 1) { + function.execute(this, value); + } else { + function.execute(this, iterator.getKey(this), value); + } + iterator.next(); + } + return null; + } + + public ArrayLeekValue arraySort(ArrayLeekValue origin, final FunctionLeekValue function) throws LeekRunException { try { int nb = function.getArgumentsCount(this); if (nb == 2) { - ArrayLeekValue array = LeekOperations.clone(this, origin).getArray(); + ArrayLeekValue array = (ArrayLeekValue) LeekOperations.clone(this, origin); array.sort(this, new Comparator() { @Override public int compare(Element o1, Element o2) { try { - return function.executeFunction(AI.this, new AbstractLeekValue[] { o1.value(), o2.value() }).getInt(AI.this); + return integer(LeekValueManager.execute(AI.this, function, o1.value(), o2.value())); } catch (Exception e) { throw new RuntimeException(e); } @@ -301,12 +540,12 @@ public int compare(Element o1, Element o2) { }); return array; } else if (nb == 4) { - ArrayLeekValue array = LeekOperations.clone(this, origin).getArray(); + ArrayLeekValue array = (ArrayLeekValue) LeekOperations.clone(this, origin); array.sort(this, new Comparator() { @Override public int compare(Element o1, Element o2) { try { - return function.executeFunction(AI.this, new AbstractLeekValue[] { o1.key(), o1.value(), o2.key(), o2.value() }).getInt(AI.this); + return integer(LeekValueManager.execute(AI.this, function, o1.key(), o1.value(), o2.key(), o2.value())); } catch (Exception e) { throw new RuntimeException(e); } @@ -319,43 +558,43 @@ public int compare(Element o1, Element o2) { throw (LeekRunException) e.getCause(); } } - return LeekValueManager.NULL; + return null; } - public AbstractLeekValue jsonEncode(AI ai, AbstractLeekValue object) { + public String jsonEncode(AI ai, Object object) { try { - String json = JSON.toJSONString(object.toJSON(ai)); - addOperations(json.length() * 10); - return new StringLeekValue(json); + String json = JSON.toJSONString(toJSON(object)); + ops(json.length() * 10); + return json; } catch (Exception e) { getLogs().addLog(AILog.ERROR, "Cannot encode object \"" + object.toString() + "\""); try { - addOperations(100); + ops(100); } catch (Exception e1) {} - return LeekValueManager.NULL; + return null; } } - public AbstractLeekValue jsonDecode(String json) { + public Object jsonDecode(String json) { try { - AbstractLeekValue obj = LeekValueManager.parseJSON(JSON.parse(json), this); - addOperations(json.length() * 10); + var obj = LeekValueManager.parseJSON(JSON.parse(json), this); + ops(json.length() * 10); return obj; } catch (Exception e) { getLogs().addLog(AILog.ERROR, "Cannot parse json \"" + json + "\""); try { - addOperations(100); + ops(100); } catch (Exception e1) {} - return LeekValueManager.NULL; + return null; } } @@ -372,7 +611,7 @@ public void addSystemLog(int type, Error error, String[] parameters) throws Leek } public void addSystemLog(int type, int error, String[] parameters) throws LeekRunException { - addOperations(AI.ERROR_LOG_COST); + ops(AI.ERROR_LOG_COST); if (type == AILog.WARNING) type = AILog.SWARNING; else if (type == AILog.ERROR) @@ -383,51 +622,848 @@ else if (type == AILog.STANDARD) logs.addSystemLog(type, getErrorMessage(Thread.currentThread().getStackTrace()), error, parameters); } - protected abstract String[] getErrorString(); + abstract protected String[] getErrorString(); - protected abstract String[] getErrorFiles(); + protected String[] getErrorFiles() { return null; } protected String getAIString() { return ""; } - public abstract AbstractLeekValue runIA() throws LeekRunException; + public abstract Object runIA() throws LeekRunException; - public abstract int userFunctionCount(int id); + public int userFunctionCount(int id) { return 0; } - public abstract boolean[] userFunctionReference(int id); + public boolean[] userFunctionReference(int id) { return null; } - public abstract AbstractLeekValue userFunctionExecute(int id, AbstractLeekValue[] value) throws LeekRunException; + public Object userFunctionExecute(int id, Object[] value) throws LeekRunException { return null; } - public abstract int anonymousFunctionCount(int id); + public int anonymousFunctionCount(int id) { return 0; } - public abstract boolean[] anonymousFunctionReference(int id); + public boolean[] anonymousFunctionReference(int id) { return null; } public RandomGenerator getRandom() { return randomGenerator; } - public abstract int getVersion(); + public int getVersion() { return this.version; } - public long getLoadTime() { - return loadTime; + public static Object load(Object value) { + if (value instanceof Box) { + return ((Box) value).getValue(); + } + return value; } - public void setLoadTime(long loadTime) { - this.loadTime = loadTime; + public boolean eq(Object x, Object y) throws LeekRunException { + // ops(1); + if (x == null) return y == null; + if (x instanceof Number) { + var n = ((Number) x).doubleValue(); + if (y instanceof Number) { + return n == ((Number) y).doubleValue(); + } + if (y instanceof Boolean) { + if ((Boolean) y) return n != 0; + return n == 0; + } + if (y instanceof String) { + if (((String) y).equals("true")) return n != 0; + if (((String) y).equals("false")) return n == 0; + } + if (y instanceof ArrayLeekValue) { + return ((ArrayLeekValue) y).equals(this, (Number) x); + } + return n == getDouble(y); + } + if (y instanceof Number) { + return getDouble(x) == ((Number) y).doubleValue(); + } + if (x instanceof Boolean) { + if (y instanceof String) { + if (((String) y).equals("true")) return ((Boolean) x) == true; + if (((String) y).equals("false")) return ((Boolean) x) == false; + return false; + } + if (y instanceof ArrayLeekValue) { + return ((ArrayLeekValue) y).equals(this, (Boolean) x); + } + } + if (x instanceof ArrayLeekValue) { + return ((ArrayLeekValue) x).equals(this, y); + } + if (x instanceof FunctionLeekValue) { + return ((FunctionLeekValue) x).equals(this, y); + } + if (x instanceof String && y instanceof String) { + ops(Math.min(((String) x).length(), ((String) y).length())); + } + return x.equals(y); } - public long getCompileTime() { - return compileTime; + public boolean neq(Object x, Object y) throws LeekRunException { + if (x == null) return y != null; + if (y == null) return x != null; + return !eq(x, y); + } + + public boolean equals_equals(Object x, Object y) throws LeekRunException { + if (x == null) return y == null; + if (x instanceof ObjectLeekValue && y instanceof ObjectLeekValue) { + return x.equals(y); + } + return LeekValueManager.getType(x) == LeekValueManager.getType(y) && eq(x, y); + } + + public boolean notequals_equals(Object x, Object y) throws LeekRunException { + return !equals_equals(x, y); + } + + public boolean less(Object x, Object y) throws LeekRunException { + if (x instanceof Number && y instanceof Number) { + if (x instanceof Integer && y instanceof Integer) { + return (Integer) x < (Integer) y; + } + return ((Number) x).doubleValue() < ((Number) y).doubleValue(); + } + return integer(x) < integer(y); + } + + public boolean more(Object x, Object y) throws LeekRunException { + if (x instanceof Number && y instanceof Number) { + if (x instanceof Integer && y instanceof Integer) { + return (Integer) x > (Integer) y; + } + return ((Number) x).doubleValue() > ((Number) y).doubleValue(); + } + return integer(x) > integer(y); + } + + public boolean lessequals(Object x, Object y) throws LeekRunException { + if (x instanceof Number && y instanceof Number) { + if (x instanceof Integer && y instanceof Integer) { + return (Integer) x <= (Integer) y; + } + return ((Number) x).doubleValue() <= ((Number) y).doubleValue(); + } + return integer(x) <= integer(y); + } + + public boolean moreequals(Object x, Object y) throws LeekRunException { + if (x instanceof Number && y instanceof Number) { + if (x instanceof Integer && y instanceof Integer) { + return (Integer) x >= (Integer) y; + } + return ((Number) x).doubleValue() >= ((Number) y).doubleValue(); + } + return integer(x) >= integer(y); + } + + public boolean bool(Object value) { + if (value instanceof Double) { + return (Double) value != 0; + } else if (value instanceof Integer) { + return (Integer) value != 0; + } else if (value instanceof Boolean) { + return (Boolean) value; + } else if (value instanceof ObjectLeekValue) { + return ((ObjectLeekValue) value).size() != 0; + } else if (value instanceof ArrayLeekValue) { + return ((ArrayLeekValue) value).size() != 0; + } else if (value instanceof String) { + var s = (String) value; + if (s.equals("false") || s.equals("0")) { + return false; + } + return !s.isEmpty(); + } else if (value instanceof Box) { + return bool(((Box) value).getValue()); + // } else if (value instanceof ReferenceLeekValue) { + // return bool(((ReferenceLeekValue) value).getValue()); + } + return false; + } + + public int integer(Object value) throws LeekRunException { + if (value instanceof Double) { + return (int) (double) value; + } else if (value instanceof Integer) { + return (Integer) value; + } else if (value instanceof Boolean) { + return ((Boolean) value) ? 1 : 0; + } else if (value instanceof ObjectLeekValue) { + return ((ObjectLeekValue) value).size(); + // } else if (value instanceof ArrayLeekValue) { + // return ((ArrayLeekValue) value).size(); + } else if (value instanceof String) { + var s = (String) value; + // ops(2); + if (s.equals("true")) return 1; + if (s.equals("false")) return 0; + if (s.isEmpty()) return 0; + ops(s.length()); + try { + return Integer.parseInt(s); + } catch (Exception e) { + return 1; + } + } else if (value instanceof Box) { + return integer(((Box) value).getValue()); + } + return 0; + } + + public double getDouble(Object value) throws LeekRunException { + return LeekValueManager.getDouble(this, value); + } + + public boolean not(Object value) throws LeekRunException { + return !bool(value); + } + + public Object minus(Object value) throws LeekRunException { + if (value instanceof Integer) return -((Integer) value); + if (value instanceof Double) return -((Double) value); + return -integer(value); + } + + public int bnot(Object value) throws LeekRunException { + return LeekValueManager.bnot(this, value); + } + + public int bor(Object x, Object y) throws LeekRunException { + return integer(x) | integer(y); + } + + public int band(Object x, Object y) throws LeekRunException { + return integer(x) & integer(y); + } + + public int bxor(Object x, Object y) throws LeekRunException { + return integer(x) ^ integer(y); + } + + public int shl(Object x, Object y) throws LeekRunException { + return integer(x) << integer(y); + } + + public int shr(Object x, Object y) throws LeekRunException { + return integer(x) >> integer(y); + } + + public int ushr(Object x, Object y) throws LeekRunException { + return integer(x) >>> integer(y); + } + + public Object add(Object v1, Object v2) throws LeekRunException { + if (v1 instanceof Number) { + if (v2 instanceof Number) { + if (v1 instanceof Double) return (Double) v1 + ((Number) v2).doubleValue(); + if (v2 instanceof Double) return (Double) v2 + ((Number) v1).doubleValue(); + return ((Number) v1).intValue() + ((Number) v2).intValue(); + } + if (v2 instanceof Boolean) { + if (v1 instanceof Integer) { + return ((Integer) v1) + (((Boolean) v2) ? 1 : 0); + } + return ((Number) v1).doubleValue() + (((Boolean) v2) ? 1 : 0); + } + if (v2 == null) return v1; + } + + // Concatenate arrays + if (v1 instanceof ArrayLeekValue && v2 instanceof ArrayLeekValue) { + + var array1 = (ArrayLeekValue) v1; + var array2 = (ArrayLeekValue) v2; + + ops((array1.size() + array2.size()) * 2); + + ArrayLeekValue retour = new ArrayLeekValue(); + ArrayIterator iterator = array1.getArrayIterator(); + + while (!iterator.ended()) { + if (iterator.key() instanceof String) { + retour.getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); + } else { + retour.push(this, iterator.getValue(this)); + } + iterator.next(); + } + iterator = array2.getArrayIterator(); + while (!iterator.ended()) { + if (iterator.key() instanceof String) { + retour.getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); + } else { + retour.push(this, iterator.getValue(this)); + } + iterator.next(); + } + return retour; + } + + if (v1 == null) { + if (v2 instanceof Number) { + return v2; + } + if (v2 == null) return 0; + } + + String v1_string = LeekValueManager.getString(this, v1); + String v2_string = LeekValueManager.getString(this, v2); + ops(v1_string.length() + v2_string.length()); + return v1_string + v2_string; + } + + public Object sub(Object v1, Object v2) throws LeekRunException { + if (v1 instanceof Number) { + if (v2 instanceof Number) { + if (v1 instanceof Double) return (Double) v1 - ((Number) v2).doubleValue(); + if (v2 instanceof Double) return ((Number) v1).doubleValue() - (Double) v2; + return ((Number) v1).intValue() - ((Number) v2).intValue(); + } + if (v1 instanceof Integer) { + return ((Integer) v1).intValue() - integer(v2); + } + if (v2 == null) return v1; + return ((Number) v1).doubleValue() - integer(v2); + } + if (v1 == null) { + if (v2 instanceof Integer) return -(Integer) v2; + if (v2 instanceof Double) return -(Double) v2; + if (v2 == null) return 0; + } + throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + } + + public Object mul(Object v1, Object v2) throws LeekRunException { + if (v1 instanceof Number) { + if (v2 instanceof Number) { + if (v1 instanceof Double || v2 instanceof Double) { + return ((Number) v1).doubleValue() * ((Number) v2).doubleValue(); + } else { + return ((Number) v1).intValue() * ((Number) v2).intValue(); + } + } + if (v2 instanceof Boolean) { + if (v1 instanceof Integer) { + return ((Integer) v1) * (((Boolean) v2) ? 1 : 0); + } + return ((Number) v1).doubleValue() * (((Boolean) v2) ? 1 : 0); + } + if (v2 == null) { + return 0; + } + } + if (v1 == null) return 0; + throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + } + + public Object div(Object x, Object y) throws LeekRunException { + if (x == null) return 0.0; + if (y == null) { + addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); + return null; + } + if (x instanceof Number) { + if (y instanceof Number) { + if (((Number) y).doubleValue() == 0) { + addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); + return null; + } + return ((Number) x).doubleValue() / ((Number) y).doubleValue(); + } + if (y instanceof Boolean) { + if ((Boolean) y) return ((Number) x).doubleValue(); + addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); + } + } + throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + } + + public Object mod(Object x, Object y) throws LeekRunException { + if (x == null) return 0; + + if (x instanceof Number && y instanceof Number) { + if (((Number) y).doubleValue() == 0) { + addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); + return null; + } + if (x instanceof Integer && y instanceof Integer) { + return ((Integer) x) % ((Integer) y); + } + return ((Number) x).doubleValue() % ((Number) y).doubleValue(); + } + if (x instanceof Boolean) { + if (((Number) y).doubleValue() == 0) { + addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); + return null; + } + if ((Boolean) x) return 1; + return 0; + } + throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + } + + public Number pow(Object x, Object y) throws LeekRunException { + if (x instanceof Number) { + if (y instanceof Number) { + if (x instanceof Integer && y instanceof Integer) { + return (int) Math.pow((Integer) x, (Integer) y); + } + return Math.pow(((Number) x).doubleValue(), ((Number) y).doubleValue()); + } + if (y instanceof Boolean) { + if (((Boolean) y) == true) return (Number) x; + return 1; + } + if (y == null) { + return 1; + } + } + if (x == null) { + if (y == null) { + return 1; + } + return 0; + } + throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + } + + public Object add_eq(Object x, Object y) throws LeekRunException { + if (x instanceof ArrayLeekValue) { + return ((ArrayLeekValue) x).add_eq(this, y); + } + return add(x, y); + } + public Object sub_eq(Object x, Object y) throws LeekRunException { + if (x instanceof Box) { + return ((Box) x).sub_eq(y); + } + return null; + } + + public Object mul_eq(Object x, Object y) throws LeekRunException { + if (x instanceof Box) { + return ((Box) x).mul_eq(y); + } + return null; + } + + public Object div_eq(Object x, Object y) throws LeekRunException { + if (x instanceof Box) { + return ((Box) x).div_eq(y); + } + return null; + } + + public Object mod_eq(Object x, Object y) throws LeekRunException { + if (x instanceof Box) { + return ((Box) x).mod_eq(y); + } + return null; + } + + public int bor_eq(Object x, Object y) throws LeekRunException { + if (x instanceof Box) { + return ((Box) x).bor_eq(y); + } + return 0; + } + + public int band_eq(Object x, Object y) throws LeekRunException { + if (x instanceof Box) { + return ((Box) x).band_eq(y); + } + return 0; + } + + public int bxor_eq(Object x, Object y) throws LeekRunException { + if (x instanceof Box) { + return ((Box) x).bxor_eq(y); + } + return 0; + } + + public Object increment(Object x) throws LeekRunException { + if (x instanceof Box) { + return ((Box) x).increment(); + } + return null; + } + + public int intOrNull(Object value) throws LeekRunException { + if (value == null) + return -1; + return integer(value); + } + + public Object copy(Object value) throws LeekRunException { + return LeekOperations.clone(this, value); + } + + public String string(Object value) throws LeekRunException { + return LeekValueManager.getString(this, value); + } + + public String getString(Object value, Set visited) throws LeekRunException { + return LeekValueManager.getString(this, value, visited); + } + public String toJSON(Object value) { + return LeekValueManager.toJSON(this, value); + } + + public boolean isPrimitive(Object value) { + return !(value instanceof ArrayLeekValue || value instanceof ObjectLeekValue); + } + public boolean isIterable(Object value) { + return value instanceof ArrayLeekValue; + } + public boolean getBooleanTernary(Object value) throws LeekRunException { + ops(1); + return bool(value); + } + + public Object getField(Object value, String field, ClassLeekValue fromClass) throws LeekRunException { + if (value instanceof ObjectLeekValue) { + return ((ObjectLeekValue) value).getField(field, fromClass); + } + if (value instanceof ClassLeekValue) { + return ((ClassLeekValue) value).getField(this, field, fromClass); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object setField(Object object, String field, Object value) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).setField(field, value); + } + if (object instanceof ClassLeekValue) { + return ((ClassLeekValue) object).setField(field, value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_inc(Object object, String field) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_inc(field); + } + if (object instanceof ClassLeekValue) { + // return ((ClassLeekValue) object).field_add_eq(field, value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_add_eq(Object object, String field, Object value) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_add_eq(field, value); + } + if (object instanceof ClassLeekValue) { + // return ((ClassLeekValue) object).field_add_eq(field, value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_sub_eq(Object object, String field, Object value) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_sub_eq(field, value); + } + if (object instanceof ClassLeekValue) { + // return ((ClassLeekValue) object).field_add_eq(field, value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } - public void setCompileTime(long compileTime) { - this.compileTime = compileTime; + public Object field_mul_eq(Object object, String field, Object value) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_mul_eq(field, value); + } + if (object instanceof ClassLeekValue) { + // return ((ClassLeekValue) object).field_add_eq(field, value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_bor_eq(Object object, String field, Object value) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_bor_eq(field, value); + } + if (object instanceof ClassLeekValue) { + // return ((ClassLeekValue) object).field_add_eq(field, value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object put(Object array, Object key, Object value) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put(this, key, value); + } + if (array instanceof ClassLeekValue) { + var field = string(key); + return ((ClassLeekValue) array).setField(field, value); + } + return null; + } + + public Object put_inc(Object array, Object key) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_inc(this, key); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + + public Object put_dec(Object array, Object key) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_dec(this, key); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + + public Object put_add_eq(Object array, Object key, Object value) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_add_eq(this, key, value); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + + public Object put_sub_eq(Object array, Object key, Object value) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_sub_eq(this, key, value); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + public Object put_mul_eq(Object array, Object key, Object value) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_mul_eq(this, key, value); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + public Object put_div_eq(Object array, Object key, Object value) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_div_eq(this, key, value); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + + + public Object put_bor_eq(Object array, Object key, Object value) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_bor_eq(this, key, value); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + + + public Object put_band_eq(Object array, Object key, Object value) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_band_eq(this, key, value); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + + public Object put_shl_eq(Object array, Object key, Object value) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_shl_eq(this, key, value); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + + public Object put_shr_eq(Object array, Object key, Object value) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_shr_eq(this, key, value); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + + public Object put_ushr_eq(Object array, Object key, Object value) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_ushr_eq(this, key, value); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + + public Object put_bxor_eq(Object array, Object key, Object value) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_bxor_eq(this, key, value); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + + public Object set(Object variable, Object value) throws LeekRunException { + if (variable instanceof Box) { + return ((Box) variable).set(value); + } + return null; + } + + public Object get(Object value, Object index) throws LeekRunException { + if (value instanceof ArrayLeekValue) { + return ((ArrayLeekValue) value).get(this, index); + } + return null; + } + + public Box getBox(Object value, Object index) throws LeekRunException { + if (value instanceof ArrayLeekValue) { + return ((ArrayLeekValue) value).getBox(this, index); + } + // return new Box(this, null); + return null; + } + + public Object callMethod(Object value, String method, ClassLeekValue fromClass, Object... args) throws LeekRunException { + if (value instanceof ObjectLeekValue) { + return ((ObjectLeekValue) value).callMethod(method, fromClass, args); + } + // if (value instanceof ClassLeekValue) { + // return ((ClassLeekValue) value).callMethod(method, args); + // } + return null; + } + + public Object execute(Object function, Object... args) throws LeekRunException { + if (function instanceof FunctionLeekValue) { + return ((FunctionLeekValue) function).execute(this, args); + } + if (function instanceof ClassLeekValue) { + return ((ClassLeekValue) function).execute(args); + } + addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_VALUE, new String[] { string(function) }); + return null; + } + + + public Object sysexec(ILeekFunction function, Object... arguments) throws LeekRunException { + // Vérification parametres + int[] parameters = function.getParameters(); + if (parameters == null || verifyParameters(parameters, arguments)) { + Object retour = function.run(this, function, arguments); + function.addOperations(this, function, arguments, retour); + return retour; + } else { + // Message d'erreur + String ret = LeekValue.getParamString(arguments); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FUNCTION, new String[] { function + "(" + ret + ")" }); + return null; + } + } + + public boolean check(String functionName, int[] types, Object... arguments) throws LeekRunException { + if (verifyParameters(types, arguments)) { + return true; + } + String ret = LeekValue.getParamString(arguments); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FUNCTION, new String[] { functionName + "(" + ret + ")" }); + return false; + } + + public static boolean verifyParameters(int[] types, Object... parameters) { + if (types.length != parameters.length) return false; + for (int i = 0; i < types.length; i++) { + if (types[i] == -1) continue; + if (i >= parameters.length || !isType(parameters[i], types[i])) { + return false; + } + } + return true; + } + + public static boolean isType(Object value, int type) { + // value = LeekValueManager.getValue(value); + switch (type) { + case BOOLEAN: return value instanceof Boolean; + case INT: return value instanceof Integer; + case DOUBLE: return value instanceof Double; + case STRING: return value instanceof String; + case NULL: return value == null; + case ARRAY: return value instanceof ArrayLeekValue; + case FUNCTION: return value instanceof FunctionLeekValue; + case NUMBER: return value instanceof Integer || value instanceof Double; + } + return true; + } + + public boolean instanceOf(Object value, Object clazz) throws LeekRunException { + ops(2); + clazz = LeekValueManager.getValue(clazz); + if (!(clazz instanceof ClassLeekValue)) { + addSystemLog(AILog.ERROR, Error.INSTANCEOF_MUST_BE_CLASS); + return false; + } + var v = load(value); + if (v instanceof ObjectLeekValue && ((ObjectLeekValue) v).getClazz().descendsFrom((ClassLeekValue) clazz)) { + return true; + } + return false; } public long getAnalyzeTime() { return analyzeTime; } - public void setAnalyzeTime(long analyzeTime) { - this.analyzeTime = analyzeTime; + public long getCompileTime() { + return compileTime; + } + + public void setAnalyzeTime(long analyze_time) { + this.analyzeTime = analyze_time; + } + + public void setCompileTime(long compile_time) { + this.compileTime = compile_time; + } + + public void setLoadTime(long load_time) { + this.loadTime = load_time; + } + + public long getLoadTime() { + return loadTime; } } diff --git a/src/main/java/leekscript/runner/ILeekFunction.java b/src/main/java/leekscript/runner/ILeekFunction.java index ee1b454d..3ea7b920 100644 --- a/src/main/java/leekscript/runner/ILeekFunction.java +++ b/src/main/java/leekscript/runner/ILeekFunction.java @@ -1,7 +1,6 @@ package leekscript.runner; import leekscript.common.Type; -import leekscript.runner.values.AbstractLeekValue; public interface ILeekFunction { abstract public void setOperations(int operations); @@ -9,9 +8,9 @@ public interface ILeekFunction { abstract public int getArgumentsMin(); abstract public boolean isExtra(); abstract public String getNamespace(); - abstract public int[] parameters(); - abstract public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException; - abstract public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException; + abstract public int[] getParameters(); abstract public Type getReturnType(); abstract public CallableVersion[] getVersions(); + abstract public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException; + abstract public void addOperations(AI leekIA, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException; } diff --git a/src/main/java/leekscript/runner/LeekAnonymousFunction.java b/src/main/java/leekscript/runner/LeekAnonymousFunction.java index 30f49dea..fee657ff 100644 --- a/src/main/java/leekscript/runner/LeekAnonymousFunction.java +++ b/src/main/java/leekscript/runner/LeekAnonymousFunction.java @@ -1,8 +1,8 @@ package leekscript.runner; -import leekscript.runner.values.AbstractLeekValue; +import leekscript.runner.values.ObjectLeekValue; public interface LeekAnonymousFunction { - public AbstractLeekValue run(AI ai, AbstractLeekValue thiz, AbstractLeekValue... values) throws LeekRunException; + public Object run(ObjectLeekValue thiz, Object... values) throws LeekRunException; } diff --git a/src/main/java/leekscript/runner/LeekFunction.java b/src/main/java/leekscript/runner/LeekFunction.java new file mode 100644 index 00000000..48887623 --- /dev/null +++ b/src/main/java/leekscript/runner/LeekFunction.java @@ -0,0 +1,6 @@ +package leekscript.runner; + +public interface LeekFunction { + + public Object run(Object... values) throws LeekRunException; +} diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index eef77579..8c4403cc 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -5,1011 +5,758 @@ import leekscript.AILog; import leekscript.functions.Functions; import leekscript.functions.VariableOperations; -import leekscript.runner.values.AbstractLeekValue; import leekscript.runner.values.ArrayLeekValue; -import leekscript.runner.values.BooleanLeekValue; -import leekscript.runner.values.DoubleLeekValue; import leekscript.runner.values.FunctionLeekValue; -import leekscript.runner.values.IntLeekValue; -import leekscript.runner.values.NullLeekValue; -import leekscript.runner.values.StringLeekValue; import leekscript.common.Error; import leekscript.common.Type; public enum LeekFunctions implements ILeekFunction { + // Fonctions mathématiques - abs(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - if (parameters[0] instanceof DoubleLeekValue) { - return new DoubleLeekValue(Math.abs(parameters[0].getDouble(leekIA))); - } else { - return LeekValueManager.getLeekIntValue(Math.abs(parameters[0].getInt(leekIA))); + abs(new CallableVersion[] { + new CallableVersion(Type.INT, new Type[] { Type.INT }), + new CallableVersion(Type.REAL, new Type[] { Type.REAL }) + }), + + min(2, new int[] { AI.NUMBER, AI.NUMBER }) { + @Override + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + if (parameters[0] instanceof Integer && parameters[1] instanceof Integer) { + var v1 = ((Integer) parameters[0]).intValue(); + var v2 = ((Integer) parameters[1]).intValue(); + return Math.min(v1, v2); } - } - - @Override - public int[] parameters() { - return new int[] { NUMBER }; + var v1 = ((Number) parameters[0]).doubleValue(); + var v2 = ((Number) parameters[1]).doubleValue(); + return Math.min(v1, v2); } }, - min(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - if (parameters[0] instanceof DoubleLeekValue || parameters[1] instanceof DoubleLeekValue) { - return new DoubleLeekValue(Math.min(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); - } - return LeekValueManager.getLeekIntValue(Math.min(parameters[0].getInt(leekIA), parameters[1].getInt(leekIA))); - } + max(2, new int[] { AI.NUMBER, AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER, NUMBER }; - } - }, - max(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - if (parameters[0] instanceof DoubleLeekValue || parameters[1] instanceof DoubleLeekValue) { - return new DoubleLeekValue(Math.max(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + if (parameters[0] instanceof Integer && parameters[1] instanceof Integer) { + var v1 = ((Integer) parameters[0]).intValue(); + var v2 = ((Integer) parameters[1]).intValue(); + return Math.max(v1, v2); } - return LeekValueManager.getLeekIntValue(Math.max(parameters[0].getInt(leekIA), parameters[1].getInt(leekIA))); - } - - @Override - public int[] parameters() { - return new int[] { NUMBER, NUMBER }; + double v1 = ((Number) parameters[0]).doubleValue(); + double v2 = ((Number) parameters[1]).doubleValue(); + return Math.max(v1, v2); } }, - cos(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.cos(parameters[0].getDouble(leekIA))); - } - @Override - public int[] parameters() { - return new int[] { NUMBER }; - } - }, - sin(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.sin(parameters[0].getDouble(leekIA))); - } + cos(new CallableVersion[] { + new CallableVersion(Type.REAL, new Type[] { Type.REAL }) + }), + sin(1, new int[] { AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return Math.sin(v); } }, - tan(1) { + tan(1, new int[] { AI.NUMBER }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.tan(parameters[0].getDouble(leekIA))); - } - - @Override - public int[] parameters() { - return new int[] { NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return Math.tan(v); } }, - toRadians(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(parameters[0].getDouble(leekIA) * Math.PI / 180); - } - + toRadians(1, new int[] { AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return v * Math.PI / 180; } }, - toDegrees(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(parameters[0].getDouble(leekIA) * 180 / Math.PI); - } - + toDegrees(1, new int[] { AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return v * 180 / Math.PI; } }, - acos(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.acos(parameters[0].getDouble(leekIA))); - } - @Override - public int[] parameters() { - return new int[] { NUMBER }; - } - }, - asin(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.asin(parameters[0].getDouble(leekIA))); - } + acos(new CallableVersion[] { + new CallableVersion(Type.REAL, new Type[] { Type.REAL }) + }), - @Override - public int[] parameters() { - return new int[] { NUMBER }; - } - }, - atan(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.atan(parameters[0].getDouble(leekIA))); - } + asin(new CallableVersion[] { + new CallableVersion(Type.REAL, new Type[] { Type.REAL }) + }), - @Override - public int[] parameters() { - return new int[] { NUMBER }; - } - }, - atan2(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.atan2(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); - } + atan(new CallableVersion[] { + new CallableVersion(Type.REAL, new Type[] { Type.REAL }) + }), + atan2(2, new int[] { AI.NUMBER, AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER, NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double y = LeekValueManager.getDouble(ai, parameters[0]); + double x = LeekValueManager.getDouble(ai, parameters[1]); + return Math.atan2(y, x); } }, - ceil(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekIntValue((int) Math.ceil(parameters[0].getDouble(leekIA))); - } - @Override - public int[] parameters() { - return new int[] { NUMBER }; - } - }, - floor(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekIntValue((int) Math.floor(parameters[0].getDouble(leekIA))); - } + ceil(new CallableVersion[] { + new CallableVersion(Type.INT, new Type[] { Type.INT }), + new CallableVersion(Type.INT, new Type[] { Type.REAL }), + }), - @Override - public int[] parameters() { - return new int[] { NUMBER }; - } - }, - round(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekIntValue((int) Math.round(parameters[0].getDouble(leekIA))); - } + floor(new CallableVersion[] { + new CallableVersion(Type.INT, new Type[] { Type.INT }), + new CallableVersion(Type.INT, new Type[] { Type.REAL }), + }), - @Override - public int[] parameters() { - return new int[] { NUMBER }; - } - }, - sqrt(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.sqrt(parameters[0].getDouble(leekIA))); - } + round(new CallableVersion[] { + new CallableVersion(Type.INT, new Type[] { Type.INT }), + new CallableVersion(Type.INT, new Type[] { Type.REAL }), + }), + sqrt(1, new int[] { AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return Math.sqrt(v); } }, - cbrt(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.cbrt(parameters[0].getDouble(leekIA))); - } - + cbrt(1, new int[] { AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return Math.cbrt(v); } }, - log(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.log(parameters[0].getDouble(leekIA))); - } - + log(1, new int[] { AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return Math.log(v); } }, - log10(1) { + log2(1, new int[] { AI.NUMBER }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.log10(parameters[0].getDouble(leekIA))); - } - - @Override - public int[] parameters() { - return new int[] { NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return Math.log(v) / Math.log(2); } }, - exp(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.exp(parameters[0].getDouble(leekIA))); - } - + log10(1, new int[] { AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return Math.log10(v); } }, - pow(2) { + exp(1, new int[] { AI.NUMBER }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.pow(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return Math.exp(v); } + }, + pow(2, new int[] { AI.NUMBER, AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER, NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double x = LeekValueManager.getDouble(ai, parameters[0]); + double y = LeekValueManager.getDouble(ai, parameters[1]); + return Math.pow(x, y); } }, + rand(0) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(leekIA.getRandom().getDouble()); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + return ai.getRandom().getDouble(); } }, - randInt(2) { + randInt(2, new int[] { AI.NUMBER, AI.NUMBER }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - int nb = parameters[0].getInt(leekIA); - int nb1 = parameters[1].getInt(leekIA); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + int nb = ai.integer(parameters[0]); + int nb1 = ai.integer(parameters[1]); if (nb > nb1) - return LeekValueManager.getLeekIntValue(leekIA.getRandom().getInt(nb1, nb - 1)); + return ai.getRandom().getInt(nb1, nb - 1); else - return LeekValueManager.getLeekIntValue(leekIA.getRandom().getInt(nb, nb1 - 1)); - } - - @Override - public int[] parameters() { - return new int[] { NUMBER, NUMBER }; + return ai.getRandom().getInt(nb, nb1 - 1); } }, - randFloat(2) { + randFloat(2, new int[] { AI.NUMBER, AI.NUMBER }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(parameters[0].getDouble(leekIA) + leekIA.getRandom().getDouble() * (parameters[1].getDouble(leekIA) - parameters[0].getDouble(leekIA))); - } - - @Override - public int[] parameters() { - return new int[] { NUMBER, NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double a = LeekValueManager.getDouble(ai, parameters[0]); + double b = LeekValueManager.getDouble(ai, parameters[1]); + return a + ai.getRandom().getDouble() * (b - a); } }, - hypot(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new DoubleLeekValue(Math.hypot(parameters[0].getDouble(leekIA), parameters[1].getDouble(leekIA))); - } - + hypot(2, new int[] { AI.NUMBER, AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER, NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double x = LeekValueManager.getDouble(ai, parameters[0]); + double y = LeekValueManager.getDouble(ai, parameters[1]); + return Math.hypot(x, y); } }, - signum(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekIntValue((int) Math.signum(parameters[0].getDouble(leekIA))); - } - + signum(1, new int[] { AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = ((Number) parameters[0]).doubleValue(); + return (int) Math.signum(v); } }, string(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new StringLeekValue(parameters[0].getString(leekIA)); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + return ai.string(parameters[0]); } }, - // Fonctions string - charAt(2) { + // Fonctions string + charAt(2, new int[] { AI.STRING, AI.NUMBER }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - int pos = parameters[1].getInt(leekIA); - String str = parameters[0].getString(leekIA); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + int pos = ai.integer(parameters[1]); + String str = (String) parameters[0]; if (pos < 0 || pos >= str.length()) - return LeekValueManager.NULL; - return new StringLeekValue(String.valueOf(str.charAt(pos))); - } - - @Override - public int[] parameters() { - return new int[] { STRING, NUMBER }; + return null; + return String.valueOf(str.charAt(pos)); } }, - length(1) { + length(1, new int[] { AI.STRING }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekIntValue(parameters[0].getString(leekIA).length()); - } - - @Override - public int[] parameters() { - return new int[] { STRING }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + String v = LeekValueManager.getString(ai, parameters[0]); + return v.length(); } }, - substring(2, 3) { + substring(2, 3, new int[] { AI.STRING, AI.NUMBER, AI.NUMBER }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - if (verifyParameters(new int[] { STRING, NUMBER, NUMBER }, parameters)) { - String string = parameters[0].getString(leekIA); - int index = parameters[1].getInt(leekIA); - int length = parameters[2].getInt(leekIA); - if (string.length() <= index || index < 0 || length < 0 || index + length > string.length()) { - return LeekValueManager.NULL; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + if (AI.verifyParameters(new int[] { AI.STRING, AI.NUMBER, AI.NUMBER }, parameters)) { + String string = LeekValueManager.getString(ai, parameters[0]); + int index = ai.integer(parameters[1]); + int length = ai.integer(parameters[2]); + if (string.length() <= index || index < 0 || index + length > string.length() || length < 0) { + return null; } - return new StringLeekValue(string.substring(index, index + length)); + return string.substring(index, index + length); } else { - int index = parameters[1].getInt(leekIA); - if (parameters[0].getString(leekIA).length() <= index || index < 0) { - return LeekValueManager.NULL; + String string = LeekValueManager.getString(ai, parameters[0]); + int index = ai.integer(parameters[1]); + if (string.length() <= index || index < 0) { + return null; } - return new StringLeekValue(parameters[0].getString(leekIA).substring(index)); + return string.substring(index); } } + @Override - public int[] parameters() { - return new int[] { STRING, NUMBER, -1 }; - } - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations( - retour.getString(leekIA).length()) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + String s = LeekValueManager.getString(ai, retour); + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(s.length()) : 1); } }, - replace(3) { + replace(3, new int[] { AI.STRING, AI.STRING, AI.STRING }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new StringLeekValue(parameters[0].getString(leekIA) - .replaceAll(Pattern.quote(parameters[1] - .getString(leekIA)), - parameters[2].getString(leekIA))); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + String s = LeekValueManager.getString(ai, parameters[0]); + String pattern = LeekValueManager.getString(ai, parameters[1]); + String replacement = LeekValueManager.getString(ai, parameters[2]); + return s.replaceAll(Pattern.quote(pattern), replacement); } @Override - public int[] parameters() { - return new int[] { STRING, STRING, STRING }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? - mVariableOperations.getOperations( - parameters[0].getString(leekIA).length()) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + String s = LeekValueManager.getString(ai, parameters[0]); + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(s.length()) : 1); } }, - indexOf(2, 3) { - + indexOf(2, 3, new int[] { AI.STRING, AI.STRING, -1 }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - if (verifyParameters(new int[] { STRING, STRING, NUMBER }, parameters)) { - return LeekValueManager.getLeekIntValue(parameters[0].getString(leekIA) - .indexOf(parameters[1].getString(leekIA), parameters[2].getInt(leekIA))); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + String s = (String) parameters[0]; + String needle = (String) parameters[1]; + int from = ai.integer(parameters[2]); + if (AI.verifyParameters(new int[] { AI.STRING, AI.STRING, AI.NUMBER }, parameters)) { + return s.indexOf(needle, from); } else { - return LeekValueManager.getLeekIntValue(parameters[0].getString(leekIA) - .indexOf(parameters[1].getString(leekIA))); + return s.indexOf(needle); } } @Override - public int[] parameters() { - return new int[] { STRING, STRING, -1 }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations((parameters[0].getString(leekIA).length())) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + String s = LeekValueManager.getString(ai, parameters[0]); + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(s.length()) : 1); } }, - split(2, 3) { + split(2, 3, new int[] { AI.STRING, AI.STRING, -1 }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - if (verifyParameters(new int[] { STRING, STRING, NUMBER }, parameters)) { - String[] elements = parameters[0].getString(leekIA) - .split(parameters[1].getString(leekIA), parameters[2].getInt(leekIA)); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + String s = LeekValueManager.getString(ai, parameters[0]); + String delimiter = LeekValueManager.getString(ai, parameters[1]); + if (AI.verifyParameters(new int[] { AI.STRING, AI.STRING, AI.NUMBER }, parameters)) { + int limit = ai.integer(parameters[2]); + String[] elements = s.split(delimiter, limit); ArrayLeekValue array = new ArrayLeekValue(); for (short i = 0; i < elements.length; i++) { - array.push(leekIA, new StringLeekValue(elements[i])); + array.push(ai, elements[i]); } return array; } else { - String[] elements = parameters[0].getString(leekIA) - .split(Pattern.quote(parameters[1].getString(leekIA))); + String[] elements = s.split(Pattern.quote(delimiter)); ArrayLeekValue array = new ArrayLeekValue(); for (short i = 0; i < elements.length; i++) { - array.push(leekIA, new StringLeekValue(elements[i])); + array.push(ai, elements[i]); } return array; } } + @Override - public int[] parameters() { - return new int[] { STRING, STRING, -1 }; - } - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations( - hasVariableOperations() ? - mVariableOperations.getOperations( - (int) (parameters[0].getString(leekIA).length() - * Math.log(parameters[1].getString(leekIA).length() + 1))) - : 1); - if (retour.isArray()) - leekIA.addOperations(retour.getArray().size()); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + String s = LeekValueManager.getString(ai, parameters[0]); + String delimiter = LeekValueManager.getString(ai, parameters[1]); + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations((int) (s.length() * Math.log(delimiter.length() + 1))) : 1); + if (retour instanceof ArrayLeekValue) { + ai.ops(((ArrayLeekValue) retour).size()); + } } }, - toLower(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new StringLeekValue(parameters[0].getString(leekIA).toLowerCase()); - } - + toLower(1, new int[] { AI.STRING }) { @Override - public int[] parameters() { - return new int[] { STRING }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + String s = LeekValueManager.getString(ai, parameters[0]); + return s.toLowerCase(); } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? - mVariableOperations.getOperations(retour.getString(leekIA).length()) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(((String) retour).length()) : 1); } }, - toUpper(1) { + toUpper(1, new int[] { AI.STRING }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new StringLeekValue(parameters[0].getString(leekIA).toUpperCase()); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + String s = LeekValueManager.getString(ai, parameters[0]); + return s.toUpperCase(); } @Override - public int[] parameters() { - return new int[] { STRING }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() - ? mVariableOperations.getOperations(retour.getString(leekIA).length()) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(((String) retour).length()) : 1); } }, - startsWith(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekBooleanValue( - parameters[0].getString(leekIA) - .startsWith(parameters[1].getString(leekIA))); - } - + startsWith(2, new int[] { AI.STRING, AI.STRING }) { @Override - public int[] parameters() { - return new int[] { STRING, STRING }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + String s = LeekValueManager.getString(ai, parameters[0]); + String prefix = LeekValueManager.getString(ai, parameters[1]); + return s.startsWith(prefix); } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - if (parameters[0].getString(leekIA).length() > parameters[1].getString(leekIA).length()) { - leekIA.addOperations(hasVariableOperations() ? - mVariableOperations.getOperations((parameters[1].getString(leekIA).length())) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + String s = LeekValueManager.getString(ai, parameters[0]); + String prefix = LeekValueManager.getString(ai, parameters[1]); + if (s.length() > prefix.length()) { + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations((prefix.length())) : 1); } else - leekIA.addOperations(1); + ai.ops(1); } }, - endsWith(2) { + endsWith(2, new int[] { AI.STRING, AI.STRING }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekBooleanValue(parameters[0].getString(leekIA) - .endsWith(parameters[1].getString(leekIA))); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + String s = LeekValueManager.getString(ai, parameters[0]); + String suffix = LeekValueManager.getString(ai, parameters[1]); + return s.endsWith(suffix); } @Override - public int[] parameters() { - return new int[] { STRING, STRING }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - if (parameters[0].getString(leekIA).length() > parameters[1].getString(leekIA).length()) { - leekIA.addOperations(hasVariableOperations() ? - mVariableOperations.getOperations((parameters[1].getString(leekIA).length())) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + String s = LeekValueManager.getString(ai, parameters[0]); + String suffix = LeekValueManager.getString(ai, parameters[1]); + if (s.length() > suffix.length()) { + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations((suffix.length())) : 1); } else - leekIA.addOperations(1); + ai.ops(1); } }, - contains(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - String haystack = parameters[0].getString(leekIA); - String needle = parameters[1].getString(leekIA); - if (needle.length() > haystack.length()) { - return LeekValueManager.getLeekBooleanValue(false); - } - return LeekValueManager.getLeekBooleanValue(haystack.contains(needle)); - } + contains(2, new int[] { AI.STRING, AI.STRING }) { @Override - public int[] parameters() { - return new int[] { STRING, STRING }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + String haystack = LeekValueManager.getString(ai, parameters[0]); + String needle = LeekValueManager.getString(ai, parameters[1]); + return haystack.contains(needle); } + @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? - mVariableOperations.getOperations( - (int) (parameters[0].getString(leekIA).length() - * Math.log(parameters[1].getString(leekIA).length() + 1))) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + String haystack = LeekValueManager.getString(ai, parameters[0]); + String needle = LeekValueManager.getString(ai, parameters[1]); + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations((int) (haystack.length() * Math.log(needle.length() + 1))) : 1); } }, number(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - if (parameters[0].getType() == AbstractLeekValue.NUMBER) - return LeekOperations.clone(leekIA, parameters[0].getValue()); - if (parameters[0].getType() != AbstractLeekValue.STRING) - return LeekValueManager.NULL; - try { - if (parameters[0].getString(leekIA).contains(".")) { - return new DoubleLeekValue(Double.parseDouble(parameters[0].getString(leekIA))); - } else { - return LeekValueManager.getLeekIntValue(Integer.parseInt(parameters[0].getString(leekIA))); - } - } catch (Exception e) { - return LeekValueManager.NULL; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + var v = parameters[0]; + if (v instanceof Number) + return v; + if (v instanceof String) { + var s = (String) v; + try { + if (s.contains(".")) { + return Double.parseDouble(s); + } else { + return Integer.parseInt(s); + } + } catch (Exception e) {} } - } - - @Override - public int[] parameters() { - return new int[] { -1 }; + return null; } }, // Fonctions array - remove(2) { + remove(2, new int[] { AI.ARRAY, AI.NUMBER }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return parameters[0].getArray().remove(leekIA, parameters[1].getInt(leekIA)); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + var index = ((Number) parameters[1]).intValue(); + return array.remove(ai, index); } @Override - public int[] parameters() { - return new int[] { ARRAY, NUMBER }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - if (parameters[1].getInt(leekIA) >= 0 && parameters[1].getInt(leekIA) < parameters[0].getArray().size()) { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[1].getInt(leekIA) + 1) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + var index = ((Number) parameters[1]).intValue(); + if (index >= 0 && index < array.size()) { + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(index + 1) : 1); } else - leekIA.addOperations(1); + ai.ops(1); } }, - count(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekIntValue(parameters[0].getArray().size()); - } - @Override - public int[] parameters() { - return new int[] { ARRAY }; - } - }, - join(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new StringLeekValue(parameters[0].getArray().join(leekIA, parameters[1].getString(leekIA))); - } + count(new CallableVersion[] { new CallableVersion(Type.INT, new Type[] { Type.ARRAY }) }), + join(2, new int[] { AI.ARRAY, AI.STRING }) { @Override - public int[] parameters() { - return new int[] { ARRAY, STRING }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + var delimiter = (String) parameters[1]; + return array.join(leekIA, delimiter); } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(retour.getString(leekIA).length() + 1) : 1); + public void addOperations(AI leekIA, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var r = (String) retour; + leekIA.ops(hasVariableOperations() ? mVariableOperations.getOperations(r.length() + 1) : 1); } }, - insert(3) { + insert(3, new int[] { AI.ARRAY, -1, AI.NUMBER }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - parameters[0].getArray().insert(leekIA, LeekOperations.clone(leekIA, parameters[1]), parameters[2].getInt(leekIA)); - return LeekValueManager.NULL; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + var value = LeekOperations.clone(ai, parameters[1]); + var index = ((Number) parameters[2]).intValue(); + array.insert(ai, value, index); + return null; } @Override - public int[] parameters() { - return new int[] { ARRAY, -1, NUMBER }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(1 + (parameters[0].getArray().size() - parameters[2].getInt(leekIA)) * 4); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + var index = ((Number) parameters[2]).intValue(); + ai.ops(1 + (array.size() - index) * 4); } }, - push(2) { + push(2, new int[] { AI.ARRAY, -1 }) { @Override - public AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; if (ai.getVersion() >= 11) { - parameters[0].getArray().push(ai, LeekOperations.clonePrimitive(ai, parameters[1])); + array.push(ai, parameters[1]); } else { - parameters[0].getArray().push(ai, LeekOperations.clone(ai, parameters[1])); + array.push(ai, LeekOperations.clone(ai, parameters[1])); } - return LeekValueManager.NULL; - } - - @Override - public int[] parameters() { - return new int[] { ARRAY, -1 }; + return null; } }, - unshift(2) { + unshift(2, new int[] { AI.ARRAY, -1 }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - parameters[0].getArray().insert(leekIA, LeekOperations.clone(leekIA, parameters[1]), 0); - return LeekValueManager.NULL; - } - - @Override - public int[] parameters() { - return new int[] { ARRAY, -1 }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + var value = LeekOperations.clone(leekIA, parameters[1]); + array.insert(leekIA, value, 0); + return null; } }, - shift(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - if (parameters[0].getArray().size() > 0) { - AbstractLeekValue v = parameters[0].getArray().start().getValue(); - parameters[0].getArray().remove(leekIA, 0); - return v; - } - return LeekValueManager.NULL; - } - + shift(1, new int[] { AI.ARRAY }) { @Override - public int[] parameters() { - return new int[] { ARRAY }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + return array.remove(leekIA, 0); } }, - pop(1) { + pop(1, new int[] { AI.ARRAY }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - if (parameters[0].getArray().size() > 0) { - AbstractLeekValue v = parameters[0].getArray().end().getValue(); - parameters[0].getArray().remove(leekIA, parameters[0].getArray().size() - 1); - return v; - } - return LeekValueManager.NULL; - } - - @Override - public int[] parameters() { - return new int[] { ARRAY }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + return array.remove(leekIA, array.size() - 1); } }, - removeElement(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - parameters[0].getArray().removeObject(leekIA, parameters[1]); - return LeekValueManager.NULL; - } - + removeElement(2, new int[] { AI.ARRAY, -1 }) { @Override - public int[] parameters() { - return new int[] { ARRAY, -1 }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + array.removeObject(ai, parameters[1]); + return null; } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? - mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(array.size() + 1) : 1); } }, - removeKey(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - parameters[0].getArray().removeByKey(leekIA, parameters[1]); - return LeekValueManager.NULL; - } - + removeKey(2, new int[] { AI.ARRAY, -1 }) { @Override - public int[] parameters() { - return new int[] { ARRAY, -1 }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + array.removeByKey(leekIA, parameters[1]); + return null; } }, - sort(1, 2) { + sort(1, 2, new int[] { AI.ARRAY, -1 }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; int type = LeekValueComparator.SortComparator.SORT_ASC; - if (parameters[1].getBoolean()) + if (leekIA.bool(parameters[1])) type = LeekValueComparator.SortComparator.SORT_DESC; - parameters[0].getArray().sort(leekIA, type); - return LeekValueManager.NULL; + array.sort(leekIA, type); + return null; } @Override - public int[] parameters() { - return new int[] { ARRAY, -1 }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(array.size() + 1) : 1); } }, - assocSort(1, 2) { + assocSort(1, 2, new int[] { AI.ARRAY, -1 }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; int type = PhpArray.ASC_A; - if (parameters[1].getBoolean()) + if (leekIA.bool(parameters[1])) type = PhpArray.DESC_A; - parameters[0].getArray().sort(leekIA, type); - return LeekValueManager.NULL; - } - - @Override - public int[] parameters() { - return new int[] { ARRAY, -1 }; + array.sort(leekIA, type); + return null; } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(array.size() + 1) : 1); } }, - keySort(1, 2) { + keySort(1, 2, new int[] { AI.ARRAY, -1 }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; int type = PhpArray.ASC_K; - if (parameters[1].getBoolean()) + if (leekIA.bool(parameters[1])) type = PhpArray.DESC_K; - parameters[0].getArray().sort(leekIA, type); - return LeekValueManager.NULL; - } - - @Override - public int[] parameters() { - return new int[] { ARRAY, -1 }; + array.sort(leekIA, type); + return null; } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(array.size() + 1) : 1); } }, - shuffle(1) { + shuffle(1, new int[] { AI.ARRAY }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - parameters[0].getArray().shuffle(leekIA); - return LeekValueManager.NULL; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + array.shuffle(leekIA); + return null; } @Override - public int[] parameters() { - return new int[] { ARRAY }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); + public void addOperations(AI leekIA, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + leekIA.ops(hasVariableOperations() ? mVariableOperations.getOperations(array.size() + 1) : 1); } }, - search(2, 3) { + search(2, 3, new int[] { AI.ARRAY, -1, -1 }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - if (verifyParameters(new int[] { ARRAY, -1, NUMBER }, parameters)) { - return parameters[0].getArray().search(leekIA, parameters[1], parameters[2].getInt(leekIA)); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + if (AI.verifyParameters(new int[] { AI.ARRAY, -1, AI.NUMBER }, parameters)) { + var index = ai.integer(parameters[2]); + return array.search(ai, parameters[1], index); } else { - return parameters[0].getArray().search(leekIA, parameters[1], 0); + return array.search(ai, parameters[1], 0); } } @Override - public int[] parameters() { - return new int[] { ARRAY, -1, -1 }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); + public void addOperations(AI leekIA, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + leekIA.ops(hasVariableOperations() ? mVariableOperations.getOperations(array.size() + 1) : 1); } }, - inArray(2) { + inArray(2, new int[] { AI.ARRAY, -1 }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekBooleanValue(parameters[0].getArray().contains(leekIA, parameters[1])); + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + return array.contains(leekIA, parameters[1]); } @Override - public int[] parameters() { - return new int[] { ARRAY, -1 }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(array.size() + 1) : 1); } }, - reverse(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - parameters[0].getArray().reverse(leekIA); - return LeekValueManager.NULL; - } - + reverse(1, new int[] { AI.ARRAY }) { @Override - public int[] parameters() { - return new int[] { ARRAY }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + array.reverse(leekIA); + return null; } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(array.size() + 1) : 1); } }, - arrayMin(1) { + arrayMin(1, new int[] { AI.ARRAY }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - AbstractLeekValue max_c = null; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + Object max_c = null; LeekValueComparator.SortComparator comp = new LeekValueComparator.SortComparator(leekIA, LeekValueComparator.SortComparator.SORT_ASC); - for (AbstractLeekValue val : parameters[0].getArray()) { + for (var val : array) { if (max_c == null) max_c = val.getValue(); - else if (comp.compare(val.getValue(), max_c) == -1) + else if (comp.compare(LeekValueManager.getValue(val), max_c) == -1) max_c = val.getValue(); } if (max_c == null) - return LeekValueManager.NULL; + return null; else return LeekOperations.clone(leekIA, max_c); } - - @Override - public int[] parameters() { - return new int[] { ARRAY }; - } }, - arrayMax(1) { + arrayMax(1, new int[] { AI.ARRAY }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - AbstractLeekValue min_c = null; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + Object min_c = null; LeekValueComparator.SortComparator mincomp = new LeekValueComparator.SortComparator(leekIA, LeekValueComparator.SortComparator.SORT_ASC); - for (AbstractLeekValue val : parameters[0].getArray()) { + for (var val : array) { if (min_c == null) min_c = val.getValue(); - else if (mincomp.compare(val.getValue(), min_c) == 1) + else if (mincomp.compare(LeekValueManager.getValue(val), min_c) == 1) min_c = val.getValue(); } if (min_c == null) - return LeekValueManager.NULL; + return null; else return LeekOperations.clone(leekIA, min_c); } @Override - public int[] parameters() { - return new int[] { ARRAY }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(array.size() + 1) : 1); } }, - sum(1) { + sum(1, new int[] { AI.ARRAY }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - if (parameters[0].getArray().size() == 0) { - return new DoubleLeekValue(0.0); - } + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; double somme = 0; - for (AbstractLeekValue val : parameters[0].getArray()) { - somme += val.getDouble(leekIA); + for (var val : array) { + somme += LeekValueManager.getDouble(ai, val.getValue()); } - return new DoubleLeekValue(somme); - } - - @Override - public int[] parameters() { - return new int[] { ARRAY }; + return somme; } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(array.size() + 1) : 1); } }, - average(1) { + average(1, new int[] { AI.ARRAY }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - if (parameters[0].getArray().size() == 0) { - return new DoubleLeekValue(0.0); - } + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; double average = 0; - for (AbstractLeekValue val : parameters[0].getArray()) { - average += val.getDouble(leekIA); + for (var val : array) { + average += LeekValueManager.getDouble(ai, val.getValue()); } - if (average == 0 && leekIA.getVersion() == 10) - return LeekValueManager.getLeekIntValue(0); - return new DoubleLeekValue(average / parameters[0].getArray().size()); - } - - @Override - public int[] parameters() { - return new int[] { ARRAY }; + if (average == 0) + return 0.0; + return average / array.size(); } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(array.size() + 1) : 1); } }, - fill(2, 3) { + fill(2, 3, new int[] { AI.ARRAY, -1, -1 }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - ArrayLeekValue array = parameters[0].getArray(); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; int size = array.size(); - if (isType(parameters[2], NUMBER)) - size = parameters[2].getInt(leekIA); - AbstractLeekValue copy = LeekOperations.clone(leekIA, parameters[1].getValue()); + if (AI.isType(parameters[2], AI.NUMBER)) + size = ai.integer(parameters[2]); + Object copy = LeekOperations.clone(ai, parameters[1]); for (int i = 0; i < size; i++) { - array.get(leekIA, i).setNoOps(leekIA, copy); - leekIA.addOperations(3); + array.put(ai, i, copy); + ai.ops(3); } - return LeekValueManager.NULL; + return null; } @Override - public int[] parameters() { - return new int[] { ARRAY, -1, -1 }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException {} + public void addOperations(AI leekIA, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException {} }, - isEmpty(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekBooleanValue(parameters[0].getArray().size() == 0); - } - + isEmpty(1, new int[] { AI.ARRAY }) { @Override - public int[] parameters() { - return new int[] { ARRAY }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + return array.size() == 0; } }, - subArray(3) { + subArray(3, new int[] { AI.ARRAY, AI.NUMBER, AI.NUMBER }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - ArrayLeekValue array = parameters[0].getArray(); - int start = parameters[1].getInt(leekIA); - int end = parameters[2].getInt(leekIA); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + int start = ai.integer(parameters[1]); + int end = ai.integer(parameters[2]); if (start < 0 || end < start || end >= array.size()) - return LeekValueManager.NULL; + return null; ArrayLeekValue retour = new ArrayLeekValue(); int i = 0; - for (AbstractLeekValue val : array) { + for (var val : array) { if (i >= start && i <= end) { - retour.push(leekIA, LeekOperations.clone(leekIA, val.getValue())); - leekIA.addOperations(1); + retour.push(ai, LeekOperations.clone(ai, val.getValue())); + ai.ops(1); } i++; } @@ -1017,298 +764,196 @@ public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValu } @Override - public int[] parameters() { - return new int[] { ARRAY, NUMBER, NUMBER }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException {} + public void addOperations(AI leekIA, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException {} }, - pushAll(2) { + pushAll(2, new int[] { AI.ARRAY, AI.ARRAY }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - ArrayLeekValue array = parameters[0].getArray(); - ArrayLeekValue source = parameters[1].getArray(); - // ArrayLeekValue source = LeekOperations.clone(leekIA, parameters[1]).getArray(); - for (AbstractLeekValue value : source) { - if (leekIA.getVersion() >= 11) { - array.push(leekIA, LeekOperations.clonePrimitive(leekIA, value.getValue())); - } else { - array.push(leekIA, LeekOperations.clone(leekIA, value.getValue())); - } - leekIA.addOperations(1); + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + var array2 = (ArrayLeekValue) parameters[1]; + for (var value : array2) { + array.push(leekIA, value.getValue()); + leekIA.ops(1); } - return LeekValueManager.NULL; + return null; } @Override - public int[] parameters() { - return new int[] { ARRAY, ARRAY }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException {} + public void addOperations(AI leekIA, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException {} }, - assocReverse(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - parameters[0].getArray().assocReverse(); - return LeekValueManager.NULL; - } - + assocReverse(1, new int[] { AI.ARRAY }) { @Override - public int[] parameters() { - return new int[] { ARRAY }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + array.assocReverse(); + return null; } @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(parameters[0].getArray().size() + 1) : 1); + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(((ArrayLeekValue) parameters[0]).size() + 1) : 1); } }, - arrayMap(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return leekIA.arrayMap(parameters[0].getArray(), parameters[1]); - } - + arrayMap(2, new int[] { AI.ARRAY, AI.FUNCTION }) { @Override - public int[] parameters() { - return new int[] { ARRAY, FUNCTION }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + var fun = (FunctionLeekValue) parameters[1]; + if (leekIA.getVersion() >= 11) { + return leekIA.arrayMap(array, fun); + } else { + return leekIA.arrayMapV10(array, fun); + } } }, - arrayFilter(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return leekIA.arrayFilter(parameters[0].getArray(), parameters[1]); - } - + arrayFilter(2, new int[] { AI.ARRAY, AI.FUNCTION }) { @Override - public int[] parameters() { - return new int[] { ARRAY, FUNCTION }; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + if (ai.getVersion() >= 11) { + return ai.arrayFilter((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); + } else { + return ai.arrayFilterV10((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); + } } }, - arrayFlatten(1, 2) { + arrayFlatten(1, 2, new int[] { AI.ARRAY, -1 }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - int maxDepth = isType(parameters[1], NUMBER) ? parameters[1].getInt(leekIA) : 1; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + int maxDepth = AI.isType(parameters[1], AI.NUMBER) ? ai.integer(parameters[1]) : 1; ArrayLeekValue retour = new ArrayLeekValue(); - leekIA.arrayFlatten(parameters[0].getArray(), retour, maxDepth); + ai.arrayFlatten((ArrayLeekValue) parameters[0], retour, maxDepth); return retour; } @Override - public int[] parameters() { - return new int[] { ARRAY, -1 }; - } - - @Override - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(hasVariableOperations() ? mVariableOperations.getOperations(retour.getArray().size() + 1) : 1); - } - }, - arrayFoldLeft(2, 3) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return leekIA.arrayFoldLeft(parameters[0].getArray(), parameters[1], parameters[2]); - } - - @Override - public int[] parameters() { - return new int[] { ARRAY, FUNCTION, -1 }; - } - }, - arrayFoldRight(2, 3) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return leekIA.arrayFoldRight(parameters[0].getArray(), parameters[1], parameters[2]); - } - - @Override - public int[] parameters() { - return new int[] { ARRAY, FUNCTION, -1 }; - } - }, - arrayPartition(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return leekIA.arrayPartition(parameters[0].getArray(), parameters[1]); - } - - @Override - public int[] parameters() { - return new int[] { ARRAY, FUNCTION }; + public void addOperations(AI leekIA, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + leekIA.ops(hasVariableOperations() ? mVariableOperations.getOperations(((ArrayLeekValue) retour).size() + 1) : 1); } }, - arrayIter(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return leekIA.arrayIter(parameters[0].getArray(), parameters[1]); - } - + arrayFoldLeft(2, 3, new int[] { AI.ARRAY, AI.FUNCTION, -1 }) { @Override - public int[] parameters() { - return new int[] { ARRAY, FUNCTION }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + return leekIA.arrayFoldLeft((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1], parameters[2]); } }, - arrayConcat(2) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekOperations.add(leekIA, parameters[0], parameters[1]); - } - + arrayFoldRight(2, 3, new int[] { AI.ARRAY, AI.FUNCTION, -1 }) { @Override - public int[] parameters() { - return new int[] { ARRAY, ARRAY }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + return leekIA.arrayFoldRight(array, (FunctionLeekValue) parameters[1], parameters[2]); } }, - arraySort(2) { + arrayPartition(2, new int[] { AI.ARRAY, AI.FUNCTION }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return leekIA.arraySort(parameters[0].getArray(), parameters[1]); - } - - @Override - public int[] parameters() { - return new int[] { ARRAY, FUNCTION }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + return leekIA.arrayPartition((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); } }, - debug(1) { + arrayIter(2, new int[] { AI.ARRAY, AI.FUNCTION }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - String p = parameters[0].getString(leekIA); - leekIA.getLogs().addLog(AILog.STANDARD, p); - leekIA.addOperations(p.length()); - return LeekValueManager.NULL; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + return leekIA.arrayIter((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); } }, - debugW(1) { + arrayConcat(2, new int[] { AI.ARRAY, AI.ARRAY }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - String p = parameters[0].getString(leekIA); - leekIA.getLogs().addLog(AILog.WARNING, p); - leekIA.addOperations(p.length()); - return LeekValueManager.NULL; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + leekIA.ops(1); + return leekIA.add(parameters[0], parameters[1]); } }, - debugE(1) { + arraySort(2, new int[] { AI.ARRAY, AI.FUNCTION }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - String p = parameters[0].getString(leekIA); - leekIA.getLogs().addLog(AILog.ERROR, p); - leekIA.addOperations(p.length()); - return LeekValueManager.NULL; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + return leekIA.arraySort((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); } }, + + debug(new CallableVersion[] { new CallableVersion(Type.NULL, new Type[] { Type.ANY }) }), + debugW(new CallableVersion[] { new CallableVersion(Type.NULL, new Type[] { Type.ANY }) }), + debugE(new CallableVersion[] { new CallableVersion(Type.NULL, new Type[] { Type.ANY }) }), + debugC(2) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - String message = parameters[0].getString(leekIA); - int color = parameters[1].getInt(leekIA); - leekIA.getLogs().addLog(AILog.STANDARD, message, color); - leekIA.addOperations(message.length()); - return LeekValueManager.NULL; + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + String message = LeekValueManager.getString(ai, parameters[0]); + int color = ai.integer(parameters[1]); + ai.getLogs().addLog(AILog.STANDARD, message, color); + ai.ops(message.length()); + return null; } }, jsonEncode(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { return leekIA.jsonEncode(leekIA, parameters[0]); } }, - jsonDecode(1) { + jsonDecode(1, new int[] { AI.STRING }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return leekIA.jsonDecode(parameters[0].getString(leekIA)); - } - - @Override - public int[] parameters() { - return new int[] { STRING }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + return leekIA.jsonDecode((String) parameters[0]); } }, getInstructionsCount(0) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekIntValue(0); + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + return 0; } }, color(3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { leekIA.addSystemLog(AILog.WARNING, Error.DEPRECATED_FUNCTION, new String[] { "color", "getColor" }); return leekIA.color(parameters[0], parameters[1], parameters[2]); } }, getColor(3) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { return leekIA.color(parameters[0], parameters[1], parameters[2]); } }, - getRed(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekIntValue(((parameters[0].getInt(leekIA)) >> 16) & 255); - } - + getRed(1, new int[] { AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + return ((((Number) parameters[0]).intValue()) >> 16) & 255; } }, - getGreen(1) { + getGreen(1, new int[] { AI.NUMBER }) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekIntValue(((parameters[0].getInt(leekIA)) >> 8) & 255); - } - - @Override - public int[] parameters() { - return new int[] { NUMBER }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + return ((((Number) parameters[0]).intValue()) >> 8) & 255; } }, - getBlue(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekIntValue(parameters[0].getInt(leekIA) & 255); - } - + getBlue(1, new int[] { AI.NUMBER }) { @Override - public int[] parameters() { - return new int[] { NUMBER }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + return ((Number) parameters[0]).intValue() & 255; } }, typeOf(1) { @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return LeekValueManager.getLeekIntValue(leekIA.typeOf(parameters[0])); - } - }, - trim(1) { - @Override - public AbstractLeekValue run(AI leekIA, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - return new StringLeekValue(parameters[0].getString(leekIA).trim()); - } - - @Override - public int[] parameters() { - return new int[] { STRING }; + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + return LeekValueManager.getType(parameters[0]); } }, - getOperations(0) { + trim(1, new int[] { AI.STRING }) { @Override - public AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue((int) ai.getOperations()); + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var s = (String) parameters[0]; + return s.trim(); } }, + + getOperations(new CallableVersion[] { new CallableVersion(Type.INT, new Type[0]) }), + clone(1, 2) { @Override - public AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue[] parameters, int count) throws LeekRunException { + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { // Clone one level by default - int level = count == 1 ? 1 : Math.max(0, parameters[1].getInt(ai)); + int level = parameters[1] == null ? 1 : Math.max(0, ai.integer(parameters[1])); return LeekOperations.clone(ai, parameters[0], level); } } @@ -1321,15 +966,6 @@ public AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue[] private int mOperations = 1; protected VariableOperations mVariableOperations = null; private int[] parameters; - - public static final int DOUBLE = 1; - public static final int INT = 2; - public static final int BOOLEAN = 3; - public static final int STRING = 4; - public static final int NULL = 5; - public static final int ARRAY = 6; - public static final int NUMBER = 7; - public static final int FUNCTION = 8; private Type return_type; private CallableVersion[] versions; private boolean direct = false; @@ -1337,13 +973,46 @@ public AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue[] LeekFunctions(int arguments) { mArgumentsMin = arguments; mArguments = arguments; - this.parameters = new int[0]; + // this.parameters = new int[0]; + } + + LeekFunctions(int arguments, int[] parameters) { + mArgumentsMin = arguments; + mArguments = arguments; + this.parameters = parameters; + } + + LeekFunctions(int arguments, int arguments_max, int[] parameters) { + mArgumentsMin = arguments; + mArguments = arguments_max; + this.parameters = parameters; } LeekFunctions(int arguments, int arguments_max) { mArgumentsMin = arguments; mArguments = arguments_max; - this.parameters = new int[0]; + // this.parameters = new int[0]; + } + + LeekFunctions(CallableVersion[] versions) { + this.versions = versions; + this.direct = true; + // this.parameters = new int[0]; + } + + LeekFunctions(Type return_type, CallableVersion[] versions, int[] parameters) { + this.return_type = return_type; + this.versions = versions; + this.direct = true; + this.parameters = parameters; + } + + public boolean isDirect() { + return direct; + } + + public int[] getParameters() { + return parameters; } public Type getReturnType() { @@ -1442,9 +1111,7 @@ public static Object[] getExtraFunctions() { /* * Lancer la fonction */ - public abstract AbstractLeekValue run(AI ai, ILeekFunction function, AbstractLeekValue parameters[], int count) throws LeekRunException; - - public int[] parameters() { + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { return null; } @@ -1456,68 +1123,7 @@ public void setOperations(int operations) { mOperations = operations; } - public void addOperations(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], AbstractLeekValue retour, int count) throws LeekRunException { - leekIA.addOperations(getOperations()); - } - - public static AbstractLeekValue executeFunction(AI leekIA, ILeekFunction function, AbstractLeekValue parameters[], int count) throws LeekRunException { - - // Vérification parametres - int[] types = function.parameters(); - if (types == null || verifyParameters(types, parameters)) { - AbstractLeekValue retour = function.run(leekIA, function, parameters, count); - function.addOperations(leekIA, function, parameters, retour, count); - return retour; - } else { - // Message d'erreur - String ret = AbstractLeekValue.getParamString(parameters); - leekIA.addSystemLog(AILog.ERROR, Error.UNKNOWN_FUNCTION, new String[] { function + "(" + ret + ")" }); - return LeekValueManager.NULL; - } - // throw new LeekRunException(LeekRunException.UNKNOWN_FUNCTION); - } - - public static int intOrNull(AI ai, AbstractLeekValue value) throws LeekRunException { - if (isType(value, NULL)) - return -1; - return value.getInt(ai); - } - - public static boolean verifyParameters(int[] types, AbstractLeekValue[] parameters) { - if (parameters == null) { - return types.length == 0; - } - if (types.length != parameters.length) { - return false; - } - for (int i = 0; i < types.length; i++) { - if (types[i] == -1) { - continue; - } - if (!isType(parameters[i], types[i])) { - return false; - } - } - return true; - } - - public static boolean isType(AbstractLeekValue value, int type) { - if (type == BOOLEAN && !(value instanceof BooleanLeekValue)) - return false; - if (type == INT && !(value instanceof IntLeekValue)) - return false; - if (type == DOUBLE && !(value instanceof DoubleLeekValue)) - return false; - if (type == STRING && !(value instanceof StringLeekValue)) - return false; - if (type == NULL && !(value instanceof NullLeekValue)) - return false; - if (type == ARRAY && !(value instanceof ArrayLeekValue)) - return false; - if (type == FUNCTION && !(value instanceof FunctionLeekValue)) - return false; - if (type == NUMBER && !(value instanceof IntLeekValue) && !(value instanceof DoubleLeekValue)) - return false; - return true; + public void addOperations(AI leekIA, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + leekIA.ops(getOperations()); } } diff --git a/src/main/java/leekscript/runner/LeekOperations.java b/src/main/java/leekscript/runner/LeekOperations.java index c936f333..6bf2126b 100644 --- a/src/main/java/leekscript/runner/LeekOperations.java +++ b/src/main/java/leekscript/runner/LeekOperations.java @@ -1,289 +1,82 @@ package leekscript.runner; -import leekscript.AILog; -import leekscript.runner.values.AbstractLeekValue; import leekscript.runner.values.ArrayLeekValue; -import leekscript.runner.values.ArrayLeekValue.ArrayIterator; -import leekscript.runner.values.BooleanLeekValue; -import leekscript.runner.values.ClassLeekValue; -import leekscript.runner.values.DoubleLeekValue; -import leekscript.runner.values.FunctionLeekValue; -import leekscript.runner.values.IntLeekValue; import leekscript.runner.values.ObjectLeekValue; -import leekscript.runner.values.StringLeekValue; -import leekscript.common.Error; public class LeekOperations { - public static AbstractLeekValue add(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - - v1 = v1.getValue(); - v2 = v2.getValue(); - - if (v1 instanceof StringLeekValue || v2 instanceof StringLeekValue) { - String v1_string = v1.getString(ai); - String v2_string = v2.getString(ai); - ai.addOperations(1 + v1_string.length() + v2_string.length()); - return new StringLeekValue(v1_string + v2_string); - } - - if (v1 instanceof ArrayLeekValue) { - if (v2 instanceof ArrayLeekValue) { - - ai.addOperations(1 + (v1.getArray().size() + v2.getArray().size()) * 2); - - ArrayLeekValue retour = new ArrayLeekValue(); - ArrayIterator iterator = v1.getArray().getArrayIterator(); - - while (!iterator.ended()) { - if (iterator.key() instanceof String) { - retour.getOrCreate(ai, iterator.getKey(ai)).setNoOps(ai, iterator.getValue(ai)); - } else { - retour.push(ai, iterator.getValue(ai)); - } - iterator.next(); - } - iterator = v2.getArray().getArrayIterator(); - while (!iterator.ended()) { - if (iterator.key() instanceof String) { - retour.getOrCreate(ai, iterator.getKey(ai)).setNoOps(ai, iterator.getValue(ai)); - } else { - retour.push(ai, iterator.getValue(ai)); - } - iterator.next(); - } - return retour; - } - - ai.addOperations(1 + v1.getArray().size() * 2); - - ArrayLeekValue retour = new ArrayLeekValue(); - ArrayIterator iterator = v1.getArray().getArrayIterator(); - - while (!iterator.ended()) { - if (iterator.key() instanceof String) { - retour.getOrCreate(ai, iterator.getKey(ai)).setNoOps(ai, iterator.getValue(ai)); - } else { - retour.push(ai, iterator.getValue(ai)); - } - iterator.next(); - } - retour.push(ai, v2); - return retour; - } - - if (v2 instanceof ArrayLeekValue) { - - ai.addOperations(1 + v2.getArray().size() * 2); - - ArrayLeekValue retour = new ArrayLeekValue(); - ArrayIterator iterator = v2.getArray().getArrayIterator(); - - retour.push(ai, v1); - - while (!iterator.ended()) { - if (iterator.key() instanceof String) { - retour.getOrCreate(ai, iterator.getKey(ai)).setNoOps(ai, iterator.getValue(ai)); - } else { - retour.push(ai, iterator.getValue(ai)); - } - iterator.next(); - } - return retour; - } - - ai.addOperations(1); - if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { - return new DoubleLeekValue(v1.getDouble(ai) + v2.getDouble(ai)); - } - return LeekValueManager.getLeekIntValue(v1.getInt(ai) + v2.getInt(ai)); - } - - public static AbstractLeekValue minus(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - v1 = v1.getValue(); - v2 = v2.getValue(); - ai.addOperations(1); - if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { - return new DoubleLeekValue(v1.getDouble(ai) - v2.getDouble(ai)); - } else { - return LeekValueManager.getLeekIntValue(v1.getInt(ai) - v2.getInt(ai)); - } - } - public static AbstractLeekValue power(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - v1 = v1.getValue(); - v2 = v2.getValue(); - ai.addOperations(AbstractLeekValue.POW_COST); - if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { - return new DoubleLeekValue(Math.pow(v1.getDouble(ai), v2.getDouble(ai))); - } else { - return LeekValueManager.getLeekIntValue((int) Math.pow(v1.getInt(ai), v2.getInt(ai))); - } + public static Object and(AI ai, Object v1, Object v2) throws LeekRunException { + // ai.ops(1); + return ai.bool(v1) && ai.bool(v2); } - public static AbstractLeekValue multiply(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - v1 = v1.getValue(); - v2 = v2.getValue(); - ai.addOperations(AbstractLeekValue.MUL_COST); - if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { - return new DoubleLeekValue(v1.getDouble(ai) * v2.getDouble(ai)); - } else { - return LeekValueManager.getLeekIntValue(v1.getInt(ai) * v2.getInt(ai)); - } - } - - public static AbstractLeekValue divide(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - v1 = v1.getValue(); - v2 = v2.getValue(); - ai.addOperations(AbstractLeekValue.DIV_COST); - double y_real = v2.getDouble(ai); - if (ai.getVersion() == 10 && y_real == 0) { - ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); - return LeekValueManager.NULL; - } - return new DoubleLeekValue(v1.getDouble(ai) / y_real); - } - - public static AbstractLeekValue modulus(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - v1 = v1.getValue(); - v2 = v2.getValue(); - ai.addOperations(AbstractLeekValue.MOD_COST); - if (v1 instanceof DoubleLeekValue || v2 instanceof DoubleLeekValue) { - return new DoubleLeekValue(v1.getDouble(ai) % v2.getDouble(ai)); - } - var v2_int = v2.getInt(ai); - if (v2_int == 0) { - ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); - return LeekValueManager.NULL; - } - return LeekValueManager.getLeekIntValue(v1.getInt(ai) % v2_int); - } - - public static AbstractLeekValue and(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekBooleanValue(v1.getBoolean() && v2.getBoolean()); - } - - public static AbstractLeekValue or(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekBooleanValue(v1.getBoolean() || v2.getBoolean()); - } - - public static AbstractLeekValue bor(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(v1.getInt(ai) | v2.getInt(ai)); + public static Object or(AI ai, Object v1, Object v2) throws LeekRunException { + // ai.ops(1); + return ai.bool(v1) || ai.bool(v2); } - public static AbstractLeekValue band(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(v1.getInt(ai) & v2.getInt(ai)); + public static int band(AI ai, Object v1, Object v2) throws LeekRunException { + // ai.ops(1); + return ai.integer(v1) & ai.integer(v2); } - public static AbstractLeekValue bxor(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(v1.getInt(ai) ^ v2.getInt(ai)); + public static int bleft(AI ai, Object v1, Object v2) throws LeekRunException { + // ai.ops(1); + return ai.integer(v1) << ai.integer(v2); } - public static AbstractLeekValue bleft(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(v1.getInt(ai) << v2.getInt(ai)); + public static int bright(AI ai, Object v1, Object v2) throws LeekRunException { + // ai.ops(1); + return ai.integer(v1) >> ai.integer(v2); } - public static AbstractLeekValue bright(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(v1.getInt(ai) >> v2.getInt(ai)); + public static int buright(AI ai, Object v1, Object v2) throws LeekRunException { + // ai.ops(1); + return ai.integer(v1) >>> ai.integer(v2); } - public static AbstractLeekValue brotate(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(v1.getInt(ai) >>> v2.getInt(ai)); + public static boolean equals(AI ai, Object v1, Object v2) throws LeekRunException { + // ai.ops(1); + return ai.eq(v1, v2); } - public static AbstractLeekValue equals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekBooleanValue(v1.equals(ai, v2)); - } - - public static AbstractLeekValue notequals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekBooleanValue(v1.notequals(ai, v2)); - } - - public static AbstractLeekValue less(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - return LeekValueManager.getLeekBooleanValue(v1.less(ai, v2)); - } - - public static AbstractLeekValue more(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - return LeekValueManager.getLeekBooleanValue(v1.more(ai, v2)); - } - - public static AbstractLeekValue lessequals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - return LeekValueManager.getLeekBooleanValue(v1.lessequals(ai, v2)); - } - - public static AbstractLeekValue moreequals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - return LeekValueManager.getLeekBooleanValue(v1.moreequals(ai, v2)); - } - - public static AbstractLeekValue clonePrimitive(AI ai, AbstractLeekValue value) throws LeekRunException { - AbstractLeekValue v = value.getValue(); - if (v instanceof StringLeekValue) { - return new StringLeekValue(v.getString(ai)); - } else if (v instanceof BooleanLeekValue) { - return LeekValueManager.getLeekBooleanValue(v.getBoolean()); - } else if (v instanceof IntLeekValue) { - return LeekValueManager.getLeekIntValue(v.getInt(ai)); - } else if (v instanceof DoubleLeekValue) { - return new DoubleLeekValue(v.getDouble(ai)); - } else { - return value; - } + public static boolean notequals(AI ai, Object v1, Object v2) throws LeekRunException { + // ai.ops(1); + return !ai.eq(v1, v2); } - public static AbstractLeekValue clone(AI ai, AbstractLeekValue value) throws LeekRunException { + public static Object clone(AI ai, Object value) throws LeekRunException { return clone(ai, value, 1); } - public static AbstractLeekValue clone(AI ai, AbstractLeekValue value, int level) throws LeekRunException { - value = value.getValue(); - if (value instanceof StringLeekValue) - return new StringLeekValue(value.getString(ai)); - else if (value instanceof FunctionLeekValue) - return ((FunctionLeekValue) value).cloneFunction(); - else if (value instanceof BooleanLeekValue) - return LeekValueManager.getLeekBooleanValue(value.getBoolean()); - else if (value instanceof IntLeekValue) - return LeekValueManager.getLeekIntValue(value.getInt(ai)); - else if (value instanceof DoubleLeekValue) - return new DoubleLeekValue(value.getDouble(ai)); - else if (value instanceof ArrayLeekValue) { + public static Object clone(AI ai, Object value, int level) throws LeekRunException { + if (value instanceof ArrayLeekValue) { if (level == 0) return value; - ai.addOperations(1); - if (value.getArray().size() > 0) { - ai.addOperations(value.getArray().size() * (ArrayLeekValue.ARRAY_CELL_CREATE_OPERATIONS)); + // System.out.println("ops Clone Array begin"); + ai.ops(1); + var array = (ArrayLeekValue) value; + if (array.size() > 0) { + // System.out.println("ops Clone Array"); + ai.ops(array.size() * (ArrayLeekValue.ARRAY_CELL_CREATE_OPERATIONS)); } - return new ArrayLeekValue(ai, value.getArray(), level); + return new ArrayLeekValue(ai, array, level); } else if (value instanceof ObjectLeekValue) { if (level == 0) return value; - ai.addOperations(1); + ai.ops(1); return new ObjectLeekValue(ai, (ObjectLeekValue) value, level); - } else if (value instanceof ClassLeekValue) { - return value; - } else { - return LeekValueManager.NULL; } + return value; } - public static AbstractLeekValue equals_equals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - ai.addOperations(1); - v1 = v1.getValue(); - v2 = v2.getValue(); + public static boolean equals_equals(AI ai, Object v1, Object v2) throws LeekRunException { + ai.ops(1); if (v1 instanceof ObjectLeekValue && v2 instanceof ObjectLeekValue) { - return LeekValueManager.getLeekBooleanValue(v1.equals(v2)); + return v1 == v2; } - return LeekValueManager.getLeekBooleanValue(v1.getType() == v2.getType() && v1.equals(ai, v2)); + return LeekValueManager.getType(v1) == LeekValueManager.getType(v2) && ai.eq(v1, v2); } - public static AbstractLeekValue notequals_equals(AI ai, AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - return LeekValueManager.getLeekBooleanValue(!equals_equals(ai, v1, v2).getBoolean()); + public static boolean notequals_equals(AI ai, Object v1, Object v2) throws LeekRunException { + return !equals_equals(ai, v1, v2); } } diff --git a/src/main/java/leekscript/runner/LeekRunException.java b/src/main/java/leekscript/runner/LeekRunException.java index fadd8b4f..fe098fda 100644 --- a/src/main/java/leekscript/runner/LeekRunException.java +++ b/src/main/java/leekscript/runner/LeekRunException.java @@ -13,6 +13,7 @@ public class LeekRunException extends Exception { public final static int INVALID_OPERATOR = 5; public final static int INVALID_LEVEL = 6; public final static int OUT_OF_MEMORY = 7; + public final static int UNKNOWN_FIELD = 8; public LeekRunException(int error) { mError = error; diff --git a/src/main/java/leekscript/runner/LeekValueComparator.java b/src/main/java/leekscript/runner/LeekValueComparator.java index 32b510c0..916247a4 100644 --- a/src/main/java/leekscript/runner/LeekValueComparator.java +++ b/src/main/java/leekscript/runner/LeekValueComparator.java @@ -2,25 +2,25 @@ import java.util.Comparator; -import leekscript.runner.values.AbstractLeekValue; +import leekscript.runner.values.ArrayLeekValue; public class LeekValueComparator { - public static class SortComparator implements Comparator { + public static class SortComparator implements Comparator { private final int mOrder; - private final AI ai; + // private final AI ai; public final static int SORT_ASC = 1; public final static int SORT_DESC = 2; public SortComparator(AI ai, int order) { mOrder = order; - this.ai = ai; + // this.ai = ai; } @Override - public int compare(AbstractLeekValue v1, AbstractLeekValue v2) { + public int compare(Object v1, Object v2) { try { if (mOrder == SORT_ASC) return compareAsc(v1, v2); @@ -32,48 +32,45 @@ else if (mOrder == SORT_DESC) return 0; } - public int compareAsc(AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - if (LeekFunctions.isType(v1, LeekFunctions.BOOLEAN)) { - if (LeekFunctions.isType(v2, LeekFunctions.NULL)) { - return 1; - } - if (LeekFunctions.isType(v2, LeekFunctions.BOOLEAN)) { - if (v1.getBoolean() == v2.getBoolean()) + public int compareAsc(Object v1, Object v2) throws LeekRunException { + if (v1 instanceof Boolean) { + if (v2 instanceof Boolean) { + if ((Boolean) v1 == (Boolean) v2) return 0; - else if (v1.getBoolean()) + else if ((Boolean) v1) return 1; else return -1; } return -1; - } else if (LeekFunctions.isType(v1, LeekFunctions.NUMBER)) { - if (LeekFunctions.isType(v2, LeekFunctions.NUMBER)) { - if (v1.getDouble(ai) == v2.getDouble(ai)) + } else if (v1 instanceof Number) { + if (v2 instanceof Number) { + if (((Number) v1).doubleValue() == ((Number) v2).doubleValue()) return 0; - else if (v1.getDouble(ai) < v2.getDouble(ai)) + else if (((Number) v1).doubleValue() < ((Number) v2).doubleValue()) return -1; else return 1; - } else if (LeekFunctions.isType(v2, LeekFunctions.BOOLEAN) || LeekFunctions.isType(v2, LeekFunctions.NULL)) + } else if (v2 instanceof Boolean) return 1; else return -1; - } else if (LeekFunctions.isType(v1, LeekFunctions.STRING)) { - if (LeekFunctions.isType(v2, LeekFunctions.STRING)) { - return v1.getString(ai).compareTo(v2.getString(ai)); - } else if (LeekFunctions.isType(v2, LeekFunctions.NUMBER) || LeekFunctions.isType(v2, LeekFunctions.BOOLEAN) || LeekFunctions.isType(v2, LeekFunctions.NULL)) + } else if (v1 instanceof String) { + if (v2 instanceof String) { + return ((String) v1).compareTo((String) v2); + } else if (v2 instanceof Number || v2 instanceof Boolean) return 1; else return -1; - } else if (LeekFunctions.isType(v1, LeekFunctions.ARRAY)) { - if (LeekFunctions.isType(v2, LeekFunctions.ARRAY)) { - if (v1.getArray().size() == v2.getArray().size()) + } else if (v1 instanceof ArrayLeekValue) { + if (v2 instanceof ArrayLeekValue) { + if (((ArrayLeekValue) v1).size() == ((ArrayLeekValue) v2).size()) return 0; - else if (v1.getArray().size() < v2.getArray().size()) + else if (((ArrayLeekValue) v1).size() < ((ArrayLeekValue) v2).size()) return -1; else return 1; - } else if (LeekFunctions.isType(v2, LeekFunctions.NULL)) + } else if (v2 == null) return -1; else return 1; diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index 12d3cf59..bd6169ad 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -2,19 +2,19 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.text.DecimalFormat; +import java.util.HashSet; +import java.util.Set; import java.util.TreeMap; -import leekscript.ErrorManager; -import leekscript.runner.values.AbstractLeekValue; +import leekscript.AILog; import leekscript.runner.values.ArrayLeekValue; -import leekscript.runner.values.BooleanLeekValue; import leekscript.runner.values.ClassLeekValue; -import leekscript.runner.values.DoubleLeekValue; import leekscript.runner.values.FunctionLeekValue; -import leekscript.runner.values.IntLeekValue; -import leekscript.runner.values.NullLeekValue; +import leekscript.runner.values.LeekValue; import leekscript.runner.values.ObjectLeekValue; -import leekscript.runner.values.StringLeekValue; +import leekscript.runner.values.Box; +import leekscript.common.Error; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -25,24 +25,9 @@ public class LeekValueManager { init(); } - public final static NullLeekValue NULL = new NullLeekValue(); - public final static BooleanLeekValue TRUE = new BooleanLeekValue(true); - public final static BooleanLeekValue FALSE = new BooleanLeekValue(false); - public final static int MIN_INT = -50; - public final static int MAX_INT = 800; - - private static TreeMap mIntegers; private static TreeMap mFunctions; public static void init() { - mIntegers = new TreeMap(); - for (int i = MIN_INT; i <= MAX_INT; i++) { - try { - mIntegers.put(i, new IntLeekValue(i)); - } catch (Exception e) { - ErrorManager.exception(e); - } - } mFunctions = new TreeMap(); for (LeekFunctions function : LeekFunctions.values()) { mFunctions.put(function.toString(), new FunctionLeekValue(function)); @@ -56,54 +41,21 @@ public static FunctionLeekValue getFunction(ILeekFunction function) { return mFunctions.get(function.toString()); } - public static AbstractLeekValue getLeekIntValue(int nb) { - // Si c'est une valeur en cache on la retourne - if (MIN_INT <= nb && nb <= MAX_INT) { - return mIntegers.get(nb); - } - return new IntLeekValue(nb); - } - - public static AbstractLeekValue getLeekIntValue(AI ai, int nb, AbstractLeekValue mValue) throws LeekRunException { - // Si c'est une valeur en cache on la retourne - if (MIN_INT <= nb && nb <= MAX_INT) - return mIntegers.get(nb); - // Si l'ancienne valeur est une valeur en cache on la modifie pas - if (MIN_INT <= mValue.getInt(ai) && mValue.getInt(ai) <= MAX_INT) - return new IntLeekValue(nb); - // Sinon on modifie direct la valeur - mValue.setInt(nb); - return mValue; - } - - public static AbstractLeekValue getStringOrNullValue(String string) { - if (string == null) { - return LeekValueManager.NULL; - } else { - return new StringLeekValue(string); - } - } - - public static AbstractLeekValue getLeekBooleanValue(boolean b) { - return b ? TRUE : FALSE; - } - - public static AbstractLeekValue parseJSON(Object o, AI ai) throws LeekRunException { - + public static Object parseJSON(Object o, AI ai) throws LeekRunException { if (o instanceof Boolean) { - return new BooleanLeekValue((Boolean) o); + return o; } if (o instanceof String) { - return new StringLeekValue((String) o); + return o; } if (o instanceof Integer) { - return new IntLeekValue((Integer) o); + return o; } if (o instanceof BigInteger) { throw new LeekRunException(LeekRunException.INVALID_OPERATOR); } if (o instanceof BigDecimal) { - return new DoubleLeekValue(((BigDecimal) o).doubleValue()); + return ((BigDecimal) o).doubleValue(); } if (o instanceof JSONArray) { JSONArray a = (JSONArray) o; @@ -117,20 +69,194 @@ public static AbstractLeekValue parseJSON(Object o, AI ai) throws LeekRunExcepti JSONObject a = (JSONObject) o; ArrayLeekValue array = new ArrayLeekValue(); for (String key : a.keySet()) { - array.getOrCreate(ai, new StringLeekValue(key)).setNoOps(ai, parseJSON(a.get(key), ai)); + array.getOrCreate(ai, key).set(parseJSON(a.get(key), ai)); } return array; } - return new StringLeekValue("Class " + o.getClass().getSimpleName()); + return "Class " + o.getClass().getSimpleName(); + } + + public static Object getValue(Object value) { + if (value instanceof Box) { + return ((Box) value).getValue(); + } + return value; + } + + public static double getDouble(AI ai, Object value) throws LeekRunException { + if (value instanceof Double) { + return (Double) value; + } else if (value instanceof Integer) { + return (Integer) value; + } else if (value instanceof Boolean) { + return ((Boolean) value) ? 1 : 0; + } else if (value instanceof ObjectLeekValue) { + return ((ObjectLeekValue) value).size(); + } else if (value instanceof ArrayLeekValue) { + return ((ArrayLeekValue) value).size(); + } else if (value instanceof String) { + var s = (String) value; + // ai.ops(2); + if (s.equals("true")) return 1; + if (s.equals("false")) return 0; + if (s.isEmpty()) return 0; + ai.ops(s.length()); + try { + return Double.parseDouble(s); + } catch (Exception e) { + return 1; + } + } else if (value instanceof Box) { + return getDouble(ai, ((Box) value).getValue()); + } + return 0; + } + + public static String doubleToString(AI ai, double value) throws LeekRunException { + ai.ops(3); + if (ai.getVersion() >= 11) { + return String.valueOf((Double) value); + } else { + // if (((Double) value) == ((Double) value).intValue()) { + // return String.valueOf(((Double) value).intValue()); + // } + DecimalFormat df = new DecimalFormat(); + df.setMinimumFractionDigits(0); + return df.format((Double) value); + } + } + + public static String getString(AI ai, Object value) throws LeekRunException { + if (value instanceof Double) { + return doubleToString(ai, (Double) value); + } else if (value instanceof Integer) { + ai.ops(3); + return String.valueOf((Integer) value); + } else if (value instanceof Boolean) { + return String.valueOf((Boolean) value); + } else if (value instanceof ObjectLeekValue) { + return ((ObjectLeekValue) value).getString(ai, new HashSet()); + } else if (value instanceof ArrayLeekValue) { + return ((ArrayLeekValue) value).getString(ai, new HashSet()); + } else if (value instanceof String) { + return (String) value; + } else if (value instanceof FunctionLeekValue) { + return ((FunctionLeekValue) value).getString(ai); + } else if (value instanceof Box) { + return getString(ai, ((Box) value).getValue()); + } + return "null"; + } + + public static String getString(AI ai, Object value, Set visited) throws LeekRunException { + if (value instanceof Double) { + return doubleToString(ai, (Double) value); + } else if (value instanceof Integer) { + ai.ops(3); + return String.valueOf((Integer) value); + } else if (value instanceof Boolean) { + return String.valueOf((Boolean) value); + } else if (value instanceof ObjectLeekValue) { + return ((ObjectLeekValue) value).getString(ai, visited); + } else if (value instanceof ArrayLeekValue) { + return ((ArrayLeekValue) value).getString(ai, visited); + } else if (value instanceof String) { + return (String) value; + } else if (value instanceof Box) { + return getString(ai, ((Box) value).getValue()); + } + return "null"; + } + + public static int bnot(AI ai, Object value) throws LeekRunException { + return ~ai.integer(value); + } + + public static FunctionLeekValue getFunction(AI ai, Object value) throws LeekRunException { + var v = getValue(value); + if (v instanceof FunctionLeekValue) { + return (FunctionLeekValue) v; + } + // On ne peux pas exécuter ce type de variable + ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_VALUE, new String[] { getString(ai, value) }); + return null; + } + + public static Object execute(AI ai, Object value, Object... args) throws LeekRunException { + if (value instanceof FunctionLeekValue) { + return ((FunctionLeekValue) value).execute(ai, args); + } + // On ne peux pas exécuter ce type de variable + ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_VALUE, new String[] { getString(ai, value) }); + return null; + } + + public static Box getOrCreate(AI ai, Object value, Object index) throws LeekRunException { + if (value instanceof ArrayLeekValue) { + return ((ArrayLeekValue) value).getOrCreate(ai, index); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FUNCTION); + } + + public static Box getFieldL(AI ai, Object value, String field) throws LeekRunException { + // value = getValue(value); + if (value instanceof ObjectLeekValue) { + return ((ObjectLeekValue) value).getFieldL(field); + } + if (value instanceof ClassLeekValue) { + return ((ClassLeekValue) value).getFieldL(field); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public static Object callMethod(AI ai, Object value, String method, Object... arguments) throws LeekRunException { + // Aucune méthode + ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { getString(ai, value), method }); + return null; + } + + public static Object callSuperMethod(AI ai, Object value, String method, Object... arguments) throws LeekRunException { + // Aucune méthode + ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { getString(ai, value), method }); + return null; + } + + public static int getType(Object v) { + if (v == null) return LeekValue.NULL; + if (v instanceof Boolean) return LeekValue.BOOLEAN; + if (v instanceof Number) return LeekValue.NUMBER; + if (v instanceof String) return LeekValue.STRING; + if (v instanceof ArrayLeekValue) return LeekValue.ARRAY; + if (v instanceof ObjectLeekValue) return LeekValue.OBJECT; + if (v instanceof ClassLeekValue) return LeekValue.CLASS; + if (v instanceof FunctionLeekValue) return LeekValue.FUNCTION; + if (v instanceof Box) return getType(((Box) v).getValue()); + return 0; + } + + public static int getV10Type(Object v) { + if (v == null) return LeekValue.NULL_V10; + if (v instanceof Boolean) return LeekValue.BOOLEAN_V10; + if (v instanceof Number) return LeekValue.NUMBER_V10; + if (v instanceof String) return LeekValue.STRING_V10; + if (v instanceof ArrayLeekValue) return LeekValue.ARRAY_V10; + if (v instanceof ObjectLeekValue) return LeekValue.OBJECT_V10; + if (v instanceof ClassLeekValue) return LeekValue.CLASS_V10; + if (v instanceof FunctionLeekValue) return LeekValue.FUNCTION_V10; + if (v instanceof Box) return getV10Type(((Box) v).getValue()); + return 0; + } + + public static String toJSON(AI ai, Object value) { + return null; } - public static AbstractLeekValue executeArrayAccess(AI ai, AbstractLeekValue array, AbstractLeekValue key, ClassLeekValue fromClass, AbstractLeekValue... arguments) throws LeekRunException { - array = array.getValue(); + public static Object executeArrayAccess(AI ai, Object array, Object key, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { if (array instanceof ObjectLeekValue) { - return ((ObjectLeekValue) array).callMethod(ai, key.getString(ai) + "_" + arguments.length, fromClass, arguments); + return ((ObjectLeekValue) array).callMethod(ai.string(key) + "_" + arguments.length, fromClass, arguments); } else { - return array.get(ai, key).executeFunction(ai, arguments); + return ai.execute(ai.get(array, key), arguments); } } } diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index a5cc9810..9fc88dcc 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -9,13 +9,12 @@ import java.util.Set; import leekscript.compiler.LeekScript; -import leekscript.runner.values.AbstractLeekValue; import leekscript.runner.values.ArrayLeekValue; +import leekscript.runner.values.LeekValue; import leekscript.runner.values.ObjectLeekValue; -import leekscript.runner.values.PhpArrayVariableLeekValue; -import leekscript.runner.values.StringLeekValue; +import leekscript.runner.values.Box; -public class PhpArray implements Iterable { +public class PhpArray implements Iterable { private final static int START_CAPACITY = 8; private final static int MAX_CAPACITY = 32000; @@ -31,14 +30,12 @@ public class PhpArray implements Iterable { private class ElementComparatorV10 implements Comparator { private final int mOrder; - private final AI ai; public final static int SORT_ASC = 1; public final static int SORT_DESC = 2; - public ElementComparatorV10(AI ai, int order) { + public ElementComparatorV10(int order) { mOrder = order; - this.ai = ai; } @Override @@ -48,41 +45,45 @@ public int compare(Element v1, Element v2) { return compareAsc(v1.value.getValue(), v2.value.getValue()); else if (mOrder == SORT_DESC) return compareAsc(v2.value.getValue(), v1.value.getValue()); - } catch (Exception e) {} + } catch (Exception e) { + e.printStackTrace(); + } return 0; } - public int compareAsc(AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - if (v1.getV10Type() < v2.getV10Type()) + public int compareAsc(Object v1, Object v2) throws LeekRunException { + int type1 = LeekValueManager.getV10Type(v1); + int type2 = LeekValueManager.getV10Type(v2); + if (type1 < type2) return -1; - else if (v1.getV10Type() > v2.getV10Type()) + else if (type1 > type2) return 1; - if (v1.getType() == AbstractLeekValue.BOOLEAN) { - if (v1.getBoolean() == v2.getBoolean()) + if (type1 == LeekValue.BOOLEAN_V10) { + if ((Boolean) v1 == (Boolean) v2) return 0; - else if (v1.getBoolean()) + else if ((Boolean) v1) return 1; else return -1; - } else if (v1.getType() == AbstractLeekValue.NUMBER) { - if (v1.getDouble(ai) == v2.getDouble(ai)) + } else if (type1 == LeekValue.NUMBER_V10) { + var d = ((Number) v2).doubleValue(); + if (((Number) v1).doubleValue() == d) return 0; - else if (v1.getDouble(ai) < v2.getDouble(ai)) + else if (((Number) v1).doubleValue() < d) return -1; else return 1; - } else if (v1.getType() == AbstractLeekValue.STRING) { - return v1.getString(ai).compareTo(v2.getString(ai)); - } else if (v1.getType() == AbstractLeekValue.ARRAY) { - if (v1.getArray().size() == v2.getArray().size()) + } else if (type1 == LeekValue.STRING_V10) { + return ((String) v1).compareTo((String) v2); + } else if (type1 == LeekValue.ARRAY_V10) { + var a = (ArrayLeekValue) v2; + if (((ArrayLeekValue) v1).size() == a.size()) return 0; - else if (v1.getArray().size() < v2.getArray().size()) + else if (((ArrayLeekValue) v1).size() < a.size()) return -1; else return 1; - } else if (v1.getType() == AbstractLeekValue.NULL) - return 0; - else + } else return -1; } } @@ -90,14 +91,12 @@ else if (v1.getArray().size() < v2.getArray().size()) private class ElementComparator implements Comparator { private final int mOrder; - private final AI ai; public final static int SORT_ASC = 1; public final static int SORT_DESC = 2; - public ElementComparator(AI ai, int order) { + public ElementComparator(int order) { mOrder = order; - this.ai = ai; } @Override @@ -107,41 +106,45 @@ public int compare(Element v1, Element v2) { return compareAsc(v1.value.getValue(), v2.value.getValue()); else if (mOrder == SORT_DESC) return compareAsc(v2.value.getValue(), v1.value.getValue()); - } catch (Exception e) {} + } catch (Exception e) { + e.printStackTrace(); + } return 0; } - public int compareAsc(AbstractLeekValue v1, AbstractLeekValue v2) throws LeekRunException { - if (v1.getType() < v2.getType()) + public int compareAsc(Object v1, Object v2) throws LeekRunException { + int type1 = LeekValueManager.getType(v1); + int type2 = LeekValueManager.getType(v2); + if (type1 < type2) return -1; - else if (v1.getType() > v2.getType()) + else if (type1 > type2) return 1; - if (v1.getType() == AbstractLeekValue.BOOLEAN) { - if (v1.getBoolean() == v2.getBoolean()) + if (type1 == LeekValue.BOOLEAN) { + if ((Boolean) v1 == (Boolean) v2) return 0; - else if (v1.getBoolean()) + else if ((Boolean) v1) return 1; else return -1; - } else if (v1.getType() == AbstractLeekValue.NUMBER) { - if (v1.getDouble(ai) == v2.getDouble(ai)) + } else if (type1 == LeekValue.NUMBER) { + var d = ((Number) v2).doubleValue(); + if (((Number) v1).doubleValue() == d) return 0; - else if (v1.getDouble(ai) < v2.getDouble(ai)) + else if (((Number) v1).doubleValue() < d) return -1; else return 1; - } else if (v1.getType() == AbstractLeekValue.STRING) { - return v1.getString(ai).compareTo(v2.getString(ai)); - } else if (v1.getType() == AbstractLeekValue.ARRAY) { - if (v1.getArray().size() == v2.getArray().size()) + } else if (type1 == LeekValue.STRING) { + return ((String) v1).compareTo((String) v2); + } else if (type1 == LeekValue.ARRAY) { + var a = (ArrayLeekValue) v2; + if (((ArrayLeekValue) v1).size() == a.size()) return 0; - else if (v1.getArray().size() < v2.getArray().size()) + else if (((ArrayLeekValue) v1).size() < a.size()) return -1; else return 1; - } else if (v1.getType() == AbstractLeekValue.NULL) - return 0; - else + } else return -1; } } @@ -177,25 +180,27 @@ else if (v1 instanceof Integer) } } - private class PhpIterator implements Iterator { + private class PhpIterator implements Iterator { private Element e = mHead; @Override public boolean hasNext() { return e != null; } + @Override - public AbstractLeekValue next() { - AbstractLeekValue v = e.value; + public Box next() { + var v = e.value; if (e != null) e = e.next; return v; } + @Override public void remove() {} } - private class ReversedPhpIterator implements Iterator { + private class ReversedPhpIterator implements Iterator { private Element e = mEnd; @Override @@ -203,8 +208,8 @@ public boolean hasNext() { return e != null; } @Override - public AbstractLeekValue next() { - AbstractLeekValue v = e.value; + public Object next() { + var v = e.value.getValue(); if (e != null) e = e.prev; return v; @@ -214,10 +219,11 @@ public void remove() {} } public class Element { + private Object key; private int hash; private boolean numeric = false; - private PhpArrayVariableLeekValue value = null; + private Box value = null; private Element next = null; private Element prev = null; @@ -228,29 +234,28 @@ public Element next() { return next; } - public AbstractLeekValue key() { - if (key instanceof Integer) - return LeekValueManager.getLeekIntValue(((Integer) key).intValue()); - else if (key instanceof ObjectLeekValue) - return (ObjectLeekValue) key; - else - return new StringLeekValue(key.toString()); + public Object key() { + return key; } public Object keyObject() { return key; } - public AbstractLeekValue value() { + public Object value() { return value.getValue(); } - public AbstractLeekValue valueRef() { + public Object valueBox() { return value; } - public void setValue(AI ai, AbstractLeekValue v) throws LeekRunException { - value.set(ai, v.getValue()); + public void setValue(AI ai, Object v) throws LeekRunException { + value.set(v); + } + + public String toString() { + return value.getValue().toString(); } } @@ -276,7 +281,7 @@ public PhpArray(AI ai, PhpArray phpArray, int level) throws LeekRunException { while (e != null) { if (ai.getVersion() >= 11) { if (level == 1) { - set(ai, e.key, LeekOperations.clonePrimitive(ai, e.value.getValue())); + set(ai, e.key, e.value.getValue()); } else { set(ai, e.key, LeekOperations.clone(ai, e.value.getValue(), level - 1)); } @@ -290,6 +295,7 @@ public PhpArray(AI ai, PhpArray phpArray, int level) throws LeekRunException { private void initTable(AI ai, int capacity) throws LeekRunException { int realCapacity = Math.max(START_CAPACITY, capacity); + // System.out.println("ops initTable"); ai.addOperationsNoCheck(realCapacity / 5); this.capacity = realCapacity; mTable = new Element[realCapacity]; @@ -337,9 +343,14 @@ public int size() { * @return Valeur à la clé donnée * @throws LeekRunException */ - public AbstractLeekValue get(AI ai, Object key) throws LeekRunException { + public Object get(AI ai, Object key) throws LeekRunException { Element e = getElement(ai, key); - return e == null ? LeekValueManager.NULL : e.value; + return e == null ? null : e.value.getValue(); + } + + public Box getBox(AI ai, Object key) throws LeekRunException { + Element e = getElement(ai, key); + return e == null ? null : e.value; } /** @@ -362,10 +373,10 @@ public boolean containsKey(AI ai, Object key) throws LeekRunException { * @return True si la valeur existe dans le tableau * @throws LeekRunException */ - public boolean contains(AI ai, AbstractLeekValue value) throws LeekRunException { + public boolean contains(AI ai, Object value) throws LeekRunException { Element e = mHead; while (e != null) { - if (e.value.equals(ai, value)) + if (ai.eq(e.value.getValue(), value)) return true; e = e.next; } @@ -381,25 +392,22 @@ public boolean contains(AI ai, AbstractLeekValue value) throws LeekRunException * @return Clé associée à la valeur ou null si la valeur n'existe pas * @throws LeekRunException */ - public AbstractLeekValue search(AI ai, AbstractLeekValue value, int pos) throws LeekRunException { + public Object search(AI ai, Object value, int pos) throws LeekRunException { Element e = mHead; int p = 0; while (e != null) { - if (p >= pos && e.value.getType() == value.getType() && e.value.equals(ai, value)) { - if (e.key instanceof Integer) - return LeekValueManager.getLeekIntValue(((Integer) e.key).intValue()); - else - return new StringLeekValue(e.key.toString()); + if (p >= pos && LeekValueManager.getType(e.value) == LeekValueManager.getType(value) && ai.eq(e.value.getValue(), value)) { + return e.key; } e = e.next; p++; } - return LeekValueManager.NULL; + return null; } - public AbstractLeekValue removeIndex(AI ai, int index) throws LeekRunException { + public Object removeIndex(AI ai, int index) throws LeekRunException { if (index >= mSize) - return LeekValueManager.NULL; + return null; Element e = mHead; int p = 0; while (e != null) { @@ -411,7 +419,7 @@ public AbstractLeekValue removeIndex(AI ai, int index) throws LeekRunException { e = e.next; p++; } - return LeekValueManager.NULL; + return null; } /** @@ -451,6 +459,7 @@ public void sort(AI ai, int comparator) throws LeekRunException { if (mSize == 0) { return; } + // System.out.println("sort " + comparator); // création de la liste List liste = new ArrayList(); Element elem = mHead; @@ -467,11 +476,11 @@ else if (comparator == ASC_K || comparator == DESC_K) { : ElementComparator.SORT_DESC)); } else { if (ai.getVersion() == 10) { - Collections.sort(liste, new ElementComparatorV10(ai, + Collections.sort(liste, new ElementComparatorV10( (comparator == ASC || comparator == ASC_A) ? ElementComparator.SORT_ASC : ElementComparator.SORT_DESC)); } else { - Collections.sort(liste, new ElementComparator(ai, + Collections.sort(liste, new ElementComparator( (comparator == ASC || comparator == ASC_A) ? ElementComparator.SORT_ASC : ElementComparator.SORT_DESC)); } @@ -595,10 +604,10 @@ public void assocReverse() { mEnd = prev; } - public void removeObject(AI ai, AbstractLeekValue value) throws LeekRunException { + public void removeObject(AI ai, Object value) throws LeekRunException { Element e = mHead; while (e != null) { - if (e.value.getType() == value.getType() && e.value.equals(ai, value)) { + if (LeekValueManager.getType(e.value) == LeekValueManager.getType(value) && ai.eq(e.value.getValue(), value)) { // On a notre élément à supprimer // On l'enleve de la HashMap removeFromHashmap(ai, e); @@ -626,7 +635,7 @@ public void removeObject(AI ai, AbstractLeekValue value) throws LeekRunException * Element à ajouter * @throws LeekRunException */ - public void push(AI ai, AbstractLeekValue value) throws LeekRunException { + public void push(AI ai, Object value) throws LeekRunException { if (mSize >= capacity) { growCapacity(ai); } @@ -643,7 +652,7 @@ public void push(AI ai, AbstractLeekValue value) throws LeekRunException { * Element à ajouter * @throws LeekRunException */ - public void unshift(AI ai, AbstractLeekValue value) throws LeekRunException { + public void unshift(AI ai, Object value) throws LeekRunException { if (mSize >= capacity) { growCapacity(ai); } @@ -663,7 +672,7 @@ public void unshift(AI ai, AbstractLeekValue value) throws LeekRunException { * Valeur * @throws LeekRunException */ - public void set(AI ai, Object key, AbstractLeekValue value) throws LeekRunException { + public void set(AI ai, Object key, Object value) throws LeekRunException { Element e = getElement(ai, key); // Si l'élément n'existe pas on le crée @@ -675,36 +684,36 @@ public void set(AI ai, Object key, AbstractLeekValue value) throws LeekRunExcept e = createElement(ai, key, value); pushElement(e); } else { - e.value.set(ai, value); + e.value.set(value); } } - public AbstractLeekValue getOrCreate(AI ai, Object key) throws LeekRunException { + public Box getOrCreate(AI ai, Object key) throws LeekRunException { Element e = getElement(ai, key); if (e == null) { if (mSize >= capacity) { growCapacity(ai); - mSize++; } - e = createElement(ai, key, LeekValueManager.NULL); + mSize++; + e = createElement(ai, key, null); pushElement(e); } return e.value; } - public void set(int key, AbstractLeekValue value) throws LeekRunException { + public void set(int key, Object value) throws LeekRunException { set(Integer.valueOf(key), value); } - public AbstractLeekValue end() { - return mEnd == null ? LeekValueManager.NULL : mEnd.value; + public Box end() { + return mEnd == null ? null : mEnd.value; } - public AbstractLeekValue start() { - return mHead == null ? LeekValueManager.NULL : mHead.value; + public Box start() { + return mHead == null ? null : mHead.value; } - public void insert(AI ai, int position, AbstractLeekValue value) throws LeekRunException { + public void insert(AI ai, int position, Object value) throws LeekRunException { if (position < 0) { return; } else if (position >= mSize) { @@ -784,16 +793,13 @@ private void pushElement(Element e) {// Ajouter un élément à la fin } } - private Element createElement(AI ai, Object key, AbstractLeekValue value) throws LeekRunException { + private Element createElement(AI ai, Object key, Object value) throws LeekRunException { // On crée l'élément Element e = new Element(); e.hash = key.hashCode(); e.key = key; - // On ajoute la taille de la clé - int keySize = 1; - - e.value = new PhpArrayVariableLeekValue(this, ai, value, keySize); + e.value = new Box(ai, value); if (key instanceof Integer) { // On met à jour l'index suivant int index = ((Integer) key).intValue(); @@ -805,6 +811,7 @@ private Element createElement(AI ai, Object key, AbstractLeekValue value) throws // On l'ajoute dans la hashmap addToHashMap(ai, e); + // System.out.println("ops createElement"); int operations = ArrayLeekValue.ARRAY_CELL_CREATE_OPERATIONS + (int) Math.sqrt(mSize) / 3; ai.addOperationsNoCheck(operations); @@ -858,6 +865,7 @@ private void destroyElement(Element e) throws LeekRunException { private Element getElement(AI ai, Object key) throws LeekRunException { + // System.out.println("ops getElement"); int operations = ArrayLeekValue.ARRAY_CELL_ACCESS_OPERATIONS; ai.addOperationsNoCheck(operations); @@ -865,7 +873,7 @@ private Element getElement(AI ai, Object key) throws LeekRunException { return null; // empty array } - int hash = key.hashCode(); + int hash = key == null ? 0 : key.hashCode(); int index = getIndex(hash); Element f = mTable[index]; @@ -885,7 +893,7 @@ private int getIndex(int hash) { public String toString(AI ai, Set visited) throws LeekRunException { - ai.addOperations(1 + mSize * 2); + ai.ops(1 + mSize * 2); StringBuilder sb = new StringBuilder(); // On va regarder si le tableau est dans l'ordre @@ -909,7 +917,7 @@ public String toString(AI ai, Set visited) throws LeekRunException { sb.append(", "); if (!isInOrder) { if (e.key instanceof ObjectLeekValue) { - sb.append(((ObjectLeekValue) e.key).getString(ai)); + sb.append(LeekValueManager.getString(ai, (ObjectLeekValue) e.key)); } else { sb.append(e.key); } @@ -918,10 +926,10 @@ public String toString(AI ai, Set visited) throws LeekRunException { if (visited.contains(e.value.getValue())) { sb.append("<...>"); } else { - if (!e.value.getValue().isPrimitive()) { + if (!ai.isPrimitive(e.value.getValue())) { visited.add(e.value.getValue()); } - sb.append(e.value.getString(ai, visited)); + sb.append(ai.getString(e.value, visited)); } e = e.next; } @@ -944,17 +952,17 @@ public boolean isAssociative() { } @Override - public Iterator iterator() { + public Iterator iterator() { return new PhpIterator(); } - public Iterator reversedIterator() { + public Iterator reversedIterator() { return new ReversedPhpIterator(); } public boolean equals(AI ai, PhpArray array) throws LeekRunException { - ai.addOperations(1); + ai.ops(1); // On commence par vérifier la taille if (mSize != array.mSize) @@ -962,7 +970,7 @@ public boolean equals(AI ai, PhpArray array) throws LeekRunException { if (mSize == 0) return true; - ai.addOperations(mSize); + ai.ops(mSize); Element e1 = mHead; Element e2 = array.mHead; @@ -970,7 +978,7 @@ public boolean equals(AI ai, PhpArray array) throws LeekRunException { while (e1 != null) { if (!e1.key.equals(e2.key)) return false; - if (!e1.value.getValue().equals(ai, e2.value.getValue())) + if (!ai.eq(e1.value.getValue(), e2.value.getValue())) return false; e1 = e1.next; e2 = e2.next; diff --git a/src/main/java/leekscript/runner/Wrapper.java b/src/main/java/leekscript/runner/Wrapper.java new file mode 100644 index 00000000..fbfe6c90 --- /dev/null +++ b/src/main/java/leekscript/runner/Wrapper.java @@ -0,0 +1,73 @@ + +package leekscript.runner; + +import leekscript.runner.values.Box; + +public class Wrapper { + + private Box variable; + + public Wrapper(Box variable) { + this.variable = variable; + } + + public Wrapper(Box variable, int ops) throws LeekRunException { + this.variable = variable; + this.variable.getAI().ops(ops); + } + + public Object setBox(Box variable) { + this.variable = variable; + return this.variable.getValue(); + } + + public Object set(Object value) throws LeekRunException { + this.variable.set(value); + return value; + } + + public Object setBoxOrValue(Object value) throws LeekRunException { + if (value instanceof Box) { + this.variable = (Box) value; + return this.variable.getValue(); + } else { + return this.variable.set(value); + } + } + + public Box getVariable() { + return variable; + } + + public Object getValue() { + return variable.getValue(); + } + + public Object increment() throws LeekRunException { + return variable.increment(); + } + + public Object decrement() throws LeekRunException { + return variable.decrement(); + } + + public Object add_eq(Object x) throws LeekRunException { + return variable.add_eq(x); + } + + public Object sub_eq(Object x) throws LeekRunException { + return variable.add_eq(x); + } + + public Object mul_eq(Object x) throws LeekRunException { + return variable.mul_eq(x); + } + + public Object div_eq(Object x) throws LeekRunException { + return variable.div_eq(x); + } + + public Object mod_eq(Object x) throws LeekRunException { + return variable.mod_eq(x); + } +} \ No newline at end of file diff --git a/src/main/java/leekscript/runner/values/AbstractLeekValue.java b/src/main/java/leekscript/runner/values/AbstractLeekValue.java deleted file mode 100644 index 95aa2a91..00000000 --- a/src/main/java/leekscript/runner/values/AbstractLeekValue.java +++ /dev/null @@ -1,310 +0,0 @@ -package leekscript.runner.values; - -import java.util.HashSet; -import java.util.Set; - -import leekscript.AILog; -import leekscript.runner.AI; -import leekscript.runner.LeekRunException; -import leekscript.runner.LeekValueManager; -import leekscript.common.AccessLevel; -import leekscript.common.Error; - -public abstract class AbstractLeekValue { - - public final static int NUMBER_V10 = 1; - public final static int BOOLEAN_V10 = 2; - public final static int ARRAY_V10 = 3; - public final static int NULL_V10 = 4; - public final static int STRING_V10 = 5; - public final static int FUNCTION_V10 = 6; - public final static int CLASS_V10 = 7; - public final static int OBJECT_V10 = 8; - - public final static int NULL = 1; - public final static int BOOLEAN = 2; - public final static int NUMBER = 3; - public final static int STRING = 4; - public final static int ARRAY = 5; - public final static int OBJECT = 6; - public final static int FUNCTION = 7; - public final static int CLASS = 8; - - public final static int ADD_COST = 1; - public final static int MUL_COST = 5; - public final static int DIV_COST = 5; - public final static int MOD_COST = 5; - public final static int POW_COST = 140; - - public int getInt(AI ai) throws LeekRunException { - return 0; - } - - public void setInt(int nb) {} - - public double getDouble(AI ai) throws LeekRunException { - return 0; - } - - public String getString(AI ai) throws LeekRunException { - return getString(ai, new HashSet<>()); - } - - public String getString(AI ai, Set visited) throws LeekRunException { - return getString(ai); - } - - public boolean getBoolean() { - return false; - } - - public boolean getBooleanTernary(AI ai) throws LeekRunException { - ai.addOperations(1); - return getBoolean(); - } - - public boolean isNumeric() { - return false; - } - - public boolean isArray() { - return false; - } - - public boolean isArrayForIteration(AI ai) throws LeekRunException { - // Pas itérable - ai.addSystemLog(AILog.ERROR, Error.NOT_ITERABLE, new String[] { getString(ai) }); - return false; - } - - public boolean isNull() { - return false; - } - - public ArrayLeekValue getArray() { - return null; - } - - public AbstractLeekValue get(AI ai, int value) throws LeekRunException { - return LeekValueManager.NULL; - } - - public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunException { - return LeekValueManager.NULL; - } - - public AbstractLeekValue get(AI ai, AbstractLeekValue value, ClassLeekValue fromClass) throws LeekRunException { - return LeekValueManager.NULL; - } - - public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws LeekRunException { - return LeekValueManager.NULL; - } - - public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value, ClassLeekValue fromClass) throws LeekRunException { - return LeekValueManager.NULL; - } - - public AbstractLeekValue getValue() { - return this; - } - - public AbstractLeekValue not(AI ai) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekBooleanValue(!getBoolean()); - } - - public AbstractLeekValue bnot(AI ai) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(~getInt(ai)); - } - - public AbstractLeekValue opposite(AI ai) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(-getInt(ai)); - } - - public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - return this; - } - - public AbstractLeekValue setNoOps(AI ai, AbstractLeekValue value) throws LeekRunException { - return this; - } - - public AbstractLeekValue setRef(AI ai, AbstractLeekValue value) throws LeekRunException { - return this; - } - - public int getArgumentsCount(AI ai) throws LeekRunException { - return -1; - } - - // Fonctions de comparaison - public abstract boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException; - - public boolean notequals(AI ai, AbstractLeekValue comp) throws LeekRunException { - return !equals(ai, comp); - } - - public boolean less(AI ai, AbstractLeekValue comp) throws LeekRunException { - ai.addOperations(1); - return getInt(ai) < comp.getInt(ai); - } - - public boolean moreequals(AI ai, AbstractLeekValue comp) throws LeekRunException { - return !less(ai, comp); - } - - public boolean more(AI ai, AbstractLeekValue comp) throws LeekRunException { - ai.addOperations(1); - return getInt(ai) > comp.getInt(ai); - } - - public boolean lessequals(AI ai, AbstractLeekValue comp) throws LeekRunException { - return !more(ai, comp); - } - - // Fonctions pour L-Values - public AbstractLeekValue increment(AI ai) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue decrement(AI ai) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue pre_increment(AI ai) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue pre_decrement(AI ai) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue add(AI ai, AbstractLeekValue value) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue minus(AI ai, AbstractLeekValue value) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue multiply(AI ai, AbstractLeekValue value) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue divide(AI ai, AbstractLeekValue value) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue modulus(AI ai, AbstractLeekValue value) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue power(AI ai, AbstractLeekValue value) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue band(AI ai, AbstractLeekValue value) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue bor(AI ai, AbstractLeekValue value) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue bxor(AI ai, AbstractLeekValue value) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue bleft(AI ai, AbstractLeekValue value) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue bright(AI ai, AbstractLeekValue value) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue brotate(AI ai, AbstractLeekValue value) throws LeekRunException { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - } - - public AbstractLeekValue instanceOf(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(2); - var clazz = value.getValue(); - if (!(clazz instanceof ClassLeekValue)) { - ai.addSystemLog(AILog.ERROR, Error.INSTANCEOF_MUST_BE_CLASS); - return LeekValueManager.getLeekBooleanValue(false); - } - var v = getValue(); - if (v instanceof ObjectLeekValue && ((ObjectLeekValue) v).getClazz().descendsFrom((ClassLeekValue) clazz)) { - return LeekValueManager.getLeekBooleanValue(true); - } - return LeekValueManager.getLeekBooleanValue(false); - } - - public AbstractLeekValue getField(AI ai, String field, ClassLeekValue fromClass) throws LeekRunException { - // Aucun champ - ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { getString(ai), field }); - return LeekValueManager.NULL; - } - - public AbstractLeekValue callMethod(AI ai, String method, ClassLeekValue fromClass, AbstractLeekValue... arguments) throws LeekRunException { - // Aucune méthode - ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { getString(ai), method }); - return LeekValueManager.NULL; - } - - public AbstractLeekValue callSuperMethod(AI ai, ClassLeekValue currentClass, String method, AbstractLeekValue... arguments) throws LeekRunException { - // Aucune méthode - ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { getString(ai), method }); - return LeekValueManager.NULL; - } - - public void callConstructor(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException {} - - public abstract int getV10Type(); - - public abstract int getType(); - - public boolean isReference() { - return false; - } - - public abstract Object toJSON(AI ai) throws LeekRunException; - - public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... value) throws LeekRunException { - // On ne peux pas exécuter ce type de variable - ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_VALUE, new String[] { getString(ai) }); - return LeekValueManager.NULL; - } - - public static String getParamString(AbstractLeekValue[] parameters) { - String ret = ""; - for (int j = 0; j < parameters.length; j++) { - if (j != 0) - ret += ", "; - if (parameters[j].getValue().getType() == NUMBER) - ret += "number"; - else if (parameters[j].getValue().getType() == BOOLEAN) - ret += "boolean"; - else if (parameters[j].getValue().getType() == STRING) - ret += "string"; - else if (parameters[j].getValue().getType() == ARRAY) - ret += "array"; - else if (parameters[j].getValue().getType() == FUNCTION) - ret += "function"; - else if (parameters[j].getValue().getType() == NULL) - ret += "null"; - else if (parameters[j].getValue().getType() == OBJECT) - ret += "object"; - else - ret += "?"; - } - return ret; - } - - public abstract boolean isPrimitive(); -} diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index b7ae1ff7..deed811d 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -7,12 +7,13 @@ import leekscript.runner.AI; import leekscript.runner.LeekOperations; import leekscript.runner.LeekRunException; +import leekscript.runner.LeekValueManager; import leekscript.runner.PhpArray; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -public class ArrayLeekValue extends AbstractLeekValue implements Iterable { +public class ArrayLeekValue implements Iterable { private final PhpArray mValues; @@ -35,43 +36,39 @@ public void next() { mElement = mElement.next(); } - public AbstractLeekValue getKey(AI ai) throws LeekRunException { + public Object getKey(AI ai) throws LeekRunException { if (ai.getVersion() >= 11) { - return LeekOperations.clonePrimitive(ai, mElement.key()); + return mElement.key(); } else { return LeekOperations.clone(ai, mElement.key()); } } - public AbstractLeekValue getKeyRef() throws LeekRunException { - return mElement.key(); - } - public Object key() { return mElement.keyObject(); } - public AbstractLeekValue getValue(AI ai) throws LeekRunException { + public Object getValue(AI ai) throws LeekRunException { if (ai.getVersion() >= 11) { - return LeekOperations.clonePrimitive(ai, mElement.value()); + return mElement.value(); } else { return LeekOperations.clone(ai, mElement.value()); } } - public AbstractLeekValue getValueRef() throws LeekRunException { + public Object value() { return mElement.value(); } - public AbstractLeekValue getKeyReference() throws LeekRunException { + public Object getKeyRef() throws LeekRunException { return mElement.key(); } - public AbstractLeekValue getValueReference() throws LeekRunException { - return mElement.valueRef(); + public Object getValueBox() throws LeekRunException { + return mElement.valueBox(); } - public void setValue(AI ai, VariableLeekValue value) throws LeekRunException { + public void setValue(AI ai, Box value) throws LeekRunException { mElement.setValue(ai, value); } } @@ -80,16 +77,16 @@ public ArrayLeekValue() { mValues = new PhpArray(); } - public ArrayLeekValue(AI ai, AbstractLeekValue values[]) throws LeekRunException { + public ArrayLeekValue(AI ai, Object values[]) throws LeekRunException { this(ai, values, false); } - public ArrayLeekValue(AI ai, AbstractLeekValue values[], boolean isKeyValue) throws LeekRunException { + public ArrayLeekValue(AI ai, Object values[], boolean isKeyValue) throws LeekRunException { mValues = new PhpArray(ai, values.length); if (isKeyValue) { int i = 0; while (i < values.length) { - getOrCreate(ai, values[i].getValue()).setNoOps(ai, values[i + 1].getValue()); + getOrCreate(ai, values[i]).set(values[i + 1]); i += 2; } } else { @@ -103,72 +100,135 @@ public ArrayLeekValue(AI ai, ArrayLeekValue array, int level) throws LeekRunExce mValues = new PhpArray(ai, array.mValues, level); } - public int size() { return mValues.size(); } - @Override - public int getInt(AI ai) throws LeekRunException { - return mValues.size(); - } - - @Override - public double getDouble(AI ai) throws LeekRunException { - return mValues.size(); + public Object get(AI ai, Object keyValue) throws LeekRunException { + var key = transformKey(ai, keyValue); + return mValues.get(ai, key); } - @Override - public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunException { - Object key; - value = value.getValue(); - if (value instanceof StringLeekValue) - key = value.getString(ai); - else if (value instanceof ObjectLeekValue) - key = value; - else - key = Integer.valueOf(value.getInt(ai)); - return mValues.get(ai, key); + public Box getBox(AI ai, Object keyValue) throws LeekRunException { + var key = transformKey(ai, keyValue); + return mValues.getBox(ai, key); } - @Override - public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws LeekRunException { - Object key; - value = value.getValue(); - if (value instanceof StringLeekValue) { - key = value.getString(ai); - } else if (value instanceof ObjectLeekValue) { - key = value; - } else { - key = Integer.valueOf(value.getInt(ai)); - } + public Box getOrCreate(AI ai, Object keyValue) throws LeekRunException { + var key = transformKey(ai, keyValue); return mValues.getOrCreate(ai, key); } - public void put(AI ai, Object key, AbstractLeekValue value) throws LeekRunException { + public Object put(AI ai, Object keyValue, Object value) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); mValues.set(ai, key, value); + return value; } - @Override - public AbstractLeekValue get(AI ai, int value) throws LeekRunException { + public Object put_inc(AI ai, Object keyValue) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + return mValues.getOrCreate(ai, key).increment(); + } + + public Object put_dec(AI ai, Object keyValue) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + return mValues.getOrCreate(ai, key).decrement(); + } + + public Object put_add_eq(AI ai, Object keyValue, Object value) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + mValues.getOrCreate(ai, key).add_eq(value); + return value; + } + + public Object put_sub_eq(AI ai, Object keyValue, Object value) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + mValues.getOrCreate(ai, key).sub_eq(value); + return value; + } + + public Object put_mul_eq(AI ai, Object keyValue, Object value) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + mValues.getOrCreate(ai, key).mul_eq(value); + return value; + } + + public Object put_div_eq(AI ai, Object keyValue, Object value) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + mValues.getOrCreate(ai, key).div_eq(value); + return value; + } + + + public Object put_bor_eq(AI ai, Object keyValue, Object value) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + mValues.getOrCreate(ai, key).bor_eq(value); + return value; + } + + + public Object put_band_eq(AI ai, Object keyValue, Object value) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + mValues.getOrCreate(ai, key).band_eq(value); + return value; + } + + + public Object put_bxor_eq(AI ai, Object keyValue, Object value) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + return mValues.getOrCreate(ai, key).bxor_eq(value); + } + + public Object put_shl_eq(AI ai, Object keyValue, Object value) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + return mValues.getOrCreate(ai, key).shl_eq(value); + } + + public Object put_shr_eq(AI ai, Object keyValue, Object value) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + return mValues.getOrCreate(ai, key).shr_eq(value); + } + + public Object put_ushr_eq(AI ai, Object keyValue, Object value) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + return mValues.getOrCreate(ai, key).ushr_eq(value); + } + + private Object transformKey(AI ai, Object key) throws LeekRunException { + if (key instanceof String || key instanceof ObjectLeekValue) { + return key; + } else { + return ai.integer(key); + } + } + + public Box get(AI ai, int value) throws LeekRunException { return mValues.getOrCreate(ai, Integer.valueOf(value)); } - public AbstractLeekValue remove(AI ai, int index) throws LeekRunException { + public Object remove(AI ai, int index) throws LeekRunException { return mValues.removeIndex(ai, index); } - public void removeObject(AI ai, AbstractLeekValue value) throws LeekRunException { + public void removeObject(AI ai, Object value) throws LeekRunException { mValues.removeObject(ai, value); } - public void removeByKey(AI ai, AbstractLeekValue value) throws LeekRunException { - if (value.getType() == STRING) - mValues.remove(ai, value.getString(ai)); - else if (value.getType() == NUMBER) - mValues.remove(ai, value.getInt(ai)); - else if (value.getType() == OBJECT) - mValues.remove(ai, value); + public void removeByKey(AI ai, Object value) throws LeekRunException { + mValues.remove(ai, value); } public void shuffle(AI ai) throws LeekRunException { @@ -186,21 +246,21 @@ public void assocReverse() { public String join(AI ai, String sep) throws LeekRunException { StringBuilder sb = new StringBuilder(); boolean first = true; - for (AbstractLeekValue val : mValues) { + for (Object val : mValues) { if (!first) sb.append(sep); else first = false; - sb.append(val.getValue().getString(ai)); + sb.append(LeekValueManager.getString(ai, val)); } return sb.toString(); } - public void insert(AI ai, AbstractLeekValue value, int pos) throws LeekRunException { + public void insert(AI ai, Object value, int pos) throws LeekRunException { mValues.insert(ai, pos, value); } - public AbstractLeekValue search(AI ai, AbstractLeekValue search, int pos) throws LeekRunException { + public Object search(AI ai, Object search, int pos) throws LeekRunException { return mValues.search(ai, search, pos); } @@ -209,97 +269,63 @@ public void sort(AI ai, int type) throws LeekRunException { } @Override - public Iterator iterator() { + public Iterator iterator() { return mValues.iterator(); } - public AbstractLeekValue end() { + public Object end() { return mValues.end().getValue(); } - public AbstractLeekValue start() { + public Object start() { return mValues.start().getValue(); } - public boolean contains(AI ai, AbstractLeekValue value) throws LeekRunException { + public boolean contains(AI ai, Object value) throws LeekRunException { return mValues.contains(ai, value); } - public void push(AI ai, AbstractLeekValue m) throws LeekRunException { + public void push(AI ai, Object m) throws LeekRunException { mValues.push(ai, m); } - @Override - public int getV10Type() { - return ARRAY_V10; - } - - @Override - public int getType() { - return ARRAY; - } - - @Override - public boolean isArray() { - return true; - } - - @Override - public boolean isArrayForIteration(AI ai) throws LeekRunException { - return true; - } - - @Override - public ArrayLeekValue getArray() { - return this; - } - public String getString(AI ai, Set visited) throws LeekRunException { visited.add(this); return mValues.toString(ai, visited); } - @Override - public boolean getBoolean() { - return mValues.size() != 0; - } - - @Override - public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { - // In LS1.0, [null] == null, not in 1.1+ - if (ai.getVersion() >= 11 && comp.getType() == NULL) { - return false; - } - if (comp.getType() == ARRAY) { - return mValues.equals(ai, comp.getArray().mValues); + public boolean equals(AI ai, Object comp) throws LeekRunException { + if (comp instanceof ArrayLeekValue) { + return mValues.equals(ai, ((ArrayLeekValue) comp).mValues); } else if (mValues.size() == 1) { // Si y'a un seul élément dans le tableau - return mValues.getHeadElement().value().equals(ai, comp); - } else if (comp.getType() == BOOLEAN) { - return comp.getBoolean() == getBoolean(); - } else if (comp.getType() == STRING) { - if (comp.getString(ai).equals("false") && getBoolean() == false) + // In LS1.0, [null] == null, not in 1.1+ + if (ai.getVersion() >= 11 && comp == null) { + return false; + } + return ai.eq(mValues.getHeadElement().value(), comp); + } else if (comp instanceof Boolean) { + return ai.bool(comp) == ai.bool(this); + } else if (comp instanceof String) { + if (ai.string(comp).equals("false") && ai.bool(this) == false) return true; - else if (comp.getString(ai).equals("true") && getBoolean() == true) + else if (ai.string(comp).equals("true") && ai.bool(this) == true) return true; - else if (comp.getString(ai).isEmpty() && mValues.size() == 0) + else if (ai.string(comp).isEmpty() && mValues.size() == 0) return true; - } else if (comp.getType() == NUMBER) { - if (mValues.size() == 0 && comp.getInt(ai) == 0) + } else if (comp instanceof Number) { + if (mValues.size() == 0 && ai.integer(comp) == 0) return true; } return false; } - @Override - public AbstractLeekValue add(AI ai, AbstractLeekValue value) throws LeekRunException { - value = value.getValue(); - ai.addOperations(1); + public Object add_eq(AI ai, Object value) throws LeekRunException { if (value instanceof ArrayLeekValue) { // mValues.reindex(ai); - ArrayIterator iterator = value.getArray().getArrayIterator(); + ArrayIterator iterator = ((ArrayLeekValue) value).getArrayIterator(); while (!iterator.ended()) { if (iterator.key() instanceof String || iterator.key() instanceof ObjectLeekValue) - mValues.getOrCreate(ai, iterator.getKey(ai).getString(ai)).setNoOps(ai, iterator.getValue(ai)); + mValues.getOrCreate(ai, ai.string(iterator.getKey(ai))).set(iterator.getValue(ai)); else mValues.push(ai, iterator.getValue(ai)); iterator.next(); @@ -310,65 +336,11 @@ public AbstractLeekValue add(AI ai, AbstractLeekValue value) throws LeekRunExcep return this; } - @Override - public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.minus(ai, this, val); - } - - @Override - public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.multiply(ai, this, val); - } - - @Override - public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.divide(ai, this, val); - } - - @Override - public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.modulus(ai, this, val); - } - - @Override - public AbstractLeekValue power(AI ai, AbstractLeekValue value) throws LeekRunException { - return LeekOperations.power(ai, this, value); - } - - @Override - public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.band(ai, this, val); - } - - @Override - public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bor(ai, this, val); - } - - @Override - public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bxor(ai, this, val); - } - - @Override - public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bleft(ai, this, val); - } - - @Override - public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bright(ai, this, val); - } - - @Override - public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.brotate(ai, this, val); - } public ArrayIterator getArrayIterator() { return new ArrayIterator(mValues.getHeadElement()); } - public Iterator getReversedIterator() { + public Iterator getReversedIterator() { return mValues.reversedIterator(); } @@ -376,28 +348,34 @@ public void sort(AI ai, Comparator comparator) throws LeekRunE mValues.sort(ai, comparator); } - @Override public Object toJSON(AI ai) throws LeekRunException { if (mValues.isAssociative()) { JSONObject o = new JSONObject(); ArrayIterator i = getArrayIterator(); while (!i.ended()) { - o.put(i.key().toString(), i.getValue(ai).toJSON(ai)); + o.put(i.key().toString(), ai.toJSON(i.getValue(ai))); i.next(); } return o; } else { JSONArray a = new JSONArray(); - for (AbstractLeekValue v : this) { - a.add(v.toJSON(ai)); + for (Object v : this) { + a.add(ai.toJSON(v)); } return a; } } @Override - public boolean isPrimitive() { - return false; + public String toString() { + var r = "["; + boolean first = true; + for (Object v : this) { + if (first) first = false; + else r += ", "; + r += v.toString(); + } + return r + "]"; } } diff --git a/src/main/java/leekscript/runner/values/BooleanLeekValue.java b/src/main/java/leekscript/runner/values/BooleanLeekValue.java deleted file mode 100644 index b14011fb..00000000 --- a/src/main/java/leekscript/runner/values/BooleanLeekValue.java +++ /dev/null @@ -1,128 +0,0 @@ -package leekscript.runner.values; - -import leekscript.runner.AI; -import leekscript.runner.LeekOperations; -import leekscript.runner.LeekRunException; - -public class BooleanLeekValue extends AbstractLeekValue { - - public final boolean mValue; - - public BooleanLeekValue(boolean value) { - mValue = value; - } - - @Override - public boolean getBoolean() { - return mValue; - } - - @Override - public int getInt(AI ai) { - return mValue ? 1 : 0; - } - - @Override - public double getDouble(AI ai) { - return mValue ? 1 : 0; - } - - @Override - public boolean isNumeric() { - return true; - } - - @Override - public String getString(AI ai) { - return mValue ? "true" : "false"; - } - - @Override - public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.add(ai, this, val); - } - - @Override - public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.minus(ai, this, val); - } - - @Override - public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.multiply(ai, this, val); - } - - @Override - public AbstractLeekValue power(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.power(ai, this, val); - } - - @Override - public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.divide(ai, this, val); - } - - @Override - public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.modulus(ai, this, val); - } - - @Override - public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.band(ai, this, val); - } - - @Override - public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bor(ai, this, val); - } - - @Override - public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bxor(ai, this, val); - } - - @Override - public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bleft(ai, this, val); - } - - @Override - public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bright(ai, this, val); - } - - @Override - public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.brotate(ai, this, val); - } - - @Override - public int getV10Type() { - return BOOLEAN_V10; - } - - @Override - public int getType() { - return BOOLEAN; - } - - @Override - public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { - if (comp.getType() == NULL) - return false; - else if (comp.getType() == ARRAY) - return comp.equals(ai, this); - return mValue == comp.getBoolean(); - } - - @Override - public Object toJSON(AI ai) { - return mValue; - } - - @Override - public boolean isPrimitive() { - return true; - } -} diff --git a/src/main/java/leekscript/runner/values/Box.java b/src/main/java/leekscript/runner/values/Box.java new file mode 100644 index 00000000..3584072d --- /dev/null +++ b/src/main/java/leekscript/runner/values/Box.java @@ -0,0 +1,245 @@ +package leekscript.runner.values; + +import leekscript.runner.AI; +import leekscript.runner.LeekOperations; +import leekscript.runner.LeekRunException; +import leekscript.runner.LeekValueManager; + +public class Box { + + protected Object mValue; + protected AI mUAI = null; + + public Box(AI ai) throws LeekRunException { + mUAI = ai; + mValue = null; + } + + public Box(AI ai, Object value) throws LeekRunException { + mUAI = ai; + // System.out.println("ops Box"); + ai.ops(1); + if (ai.getVersion() >= 11) { + mValue = value; + } else if (value instanceof Box) { + mValue = LeekOperations.clone(ai, ((Box) value).getValue()); + } else { + mValue = value; + } + } + + public Box(AI ai, Object value, int ops) throws LeekRunException { + this(ai, value); + ai.ops(ops); + } + + public Object getValue() { + return mValue; + } + + public Object set(Object value) throws LeekRunException { + // mUAI.ops(1); + if (mUAI.getVersion() >= 11) { + return mValue = LeekValueManager.getValue(value); + } else { + if (value instanceof Box) { + return mValue = LeekOperations.clone(mUAI, ((Box) value).getValue()); + } else { + return mValue = value; + } + } + } + + public Object setRef(Object value) throws LeekRunException { + return mValue = LeekValueManager.getValue(value); + } + + public void initGlobal(Object value) throws LeekRunException { + if (value instanceof Box) { + if (mUAI.getVersion() >= 11) { + mValue = value; + } else { + mValue = LeekOperations.clone(mUAI, value); + } + } else { + mValue = value; + } + } + + public Object increment() throws LeekRunException { + // mUAI.ops(1); + if (mValue instanceof Integer) { + int value = (Integer) mValue; + mValue = value + 1; + return value; + } + if (mValue instanceof Double) { + double value = (Double) mValue; + mValue = value + 1; + return value; + } + throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + // ai.addSystemLog(AILog.ERROR, Error.INVALID_OPERATOR, new String[] { LeekValueManager.getString(ai, mValue), "++" }); + } + + public Object decrement() throws LeekRunException { + // mUAI.ops(1); + if (mValue instanceof Integer) { + int value = (Integer) mValue; + mValue = value - 1; + return value; + } + if (mValue instanceof Double) { + double value = (Double) mValue; + mValue = value - 1; + return value; + } + throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + } + + public Object pre_increment() throws LeekRunException { + // mUAI.ops(1); + if (mValue instanceof Integer) { + return mValue = (Integer) mValue + 1; + } + if (mValue instanceof Double) { + return mValue = (Double) mValue + 1; + } + throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + } + + public Object pre_decrement() throws LeekRunException { + // mUAI.ops(1); + if (mValue instanceof Integer) { + return mValue = (Integer) mValue - 1; + } + if (mValue instanceof Double) { + return mValue = (Double) mValue - 1; + } + throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + } + + public Object not() throws LeekRunException { + // mUAI.ops(1); + return !mUAI.bool(mValue); + } + + public Object opposite() throws LeekRunException { + // mUAI.ops(1); + if (mValue instanceof Double) { + return -(Double) mValue; + } + return -mUAI.integer(mValue); + } + + public Object add_eq(Object val) throws LeekRunException { + if (mValue == null) { + return mValue = val; + } + if (mValue instanceof Number) { + return mValue = mUAI.add(mValue, val); + } + if (mValue instanceof String) { + return mValue = mUAI.add(mValue, val); + } + return mValue = mUAI.add_eq(mValue, val); + } + + public Object sub_eq(Object val) throws LeekRunException { + if (mValue == null) { + return mValue = mUAI.minus(val); + } + if (mValue instanceof Number) { + return mValue = mUAI.sub(mValue, val); + } + return mValue = mUAI.sub_eq(mValue, val); + } + + public Object mul_eq(Object val) throws LeekRunException { + if (mValue instanceof Number) { + return mValue = mUAI.mul(mValue, val); + } + if (mValue == null) { + return mValue = mUAI.mul(mValue, val); + } + return mValue = mUAI.mul_eq(mValue, val); + } + + public Object pow_eq(Object val) throws LeekRunException { + return mValue = mUAI.pow(mValue, val); + } + + public int band_eq(Object val) throws LeekRunException { + return (int) (mValue = LeekOperations.band(mUAI, mValue, val)); + } + + public int bor_eq(Object val) throws LeekRunException { + return (int) (mValue = mUAI.bor(mValue, val)); + } + + public int bxor_eq(Object val) throws LeekRunException { + return (int) (mValue = mUAI.bxor(mValue, val)); + } + + public Object shl_eq(Object val) throws LeekRunException { + return mValue = LeekOperations.bleft(mUAI, mValue, val); + } + + public Object shr_eq(Object val) throws LeekRunException { + return mValue = LeekOperations.bright(mUAI, mValue, val); + } + + public Object ushr_eq(Object val) throws LeekRunException { + return mValue = LeekOperations.buright(mUAI, mValue, val); + } + + public Object div_eq(Object val) throws LeekRunException { + return mValue = mUAI.div(mValue, val); + } + + public Object mod_eq(Object val) throws LeekRunException { + return mValue = mUAI.mod(mValue, val); + } + + public Object get(Object index) throws LeekRunException { + return mUAI.get(mValue, index); + } + + public Box getOrCreate(Object index) throws LeekRunException { + return LeekValueManager.getOrCreate(mUAI, mValue, index); + } + + public Object getField(String field, ClassLeekValue fromClass) throws LeekRunException { + if (mValue instanceof ObjectLeekValue) { + return ((ObjectLeekValue) mValue).getField(field, fromClass); + } + return null; + } + + public Box getFieldL(String field) throws LeekRunException { + if (mValue instanceof ObjectLeekValue) { + return ((ObjectLeekValue) mValue).getFieldL(field); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object put(AI ai, Object key, Object value) throws LeekRunException { + if (mValue instanceof ArrayLeekValue) { + return ((ArrayLeekValue) mValue).put(ai, key, value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public AI getAI() { + return mUAI; + } + + public Object execute(Object... arguments) throws LeekRunException { + return LeekValueManager.execute(mUAI, mValue, arguments); + } + + @Override + public String toString() { + return mValue != null ? mValue.toString() : "null"; + } +} diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 85bf7eb7..c3627e1b 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -6,18 +6,18 @@ import leekscript.AILog; import leekscript.runner.AI; import leekscript.runner.LeekRunException; -import leekscript.runner.LeekValueManager; import leekscript.runner.LeekAnonymousFunction; import leekscript.common.AccessLevel; +import leekscript.runner.LeekFunction; import leekscript.common.Error; import leekscript.compiler.bloc.AnonymousFunctionBlock; -public class ClassLeekValue extends AbstractLeekValue { +public class ClassLeekValue { public static class ClassField { - AbstractLeekValue value; + Object value; AccessLevel level; - public ClassField(AbstractLeekValue value, AccessLevel level) { + public ClassField(Object value, AccessLevel level) { this.value = value; this.level = level; } @@ -32,38 +32,49 @@ public ClassMethod(LeekAnonymousFunction value, AccessLevel level) { } }; + public static class ClassStaticMethod { + LeekFunction value; + AccessLevel level; + public ClassStaticMethod(LeekFunction value, AccessLevel level) { + this.value = value; + this.level = level; + } + }; + + public AI ai; public String name; - public AbstractLeekValue parent; + public ClassLeekValue parent; public HashMap fields = new HashMap<>(); public HashMap staticFields = new HashMap<>(); - public HashMap constructors = new HashMap<>(); + public HashMap constructors = new HashMap<>(); public HashMap methods = new HashMap<>(); - public HashMap genericMethods = new HashMap<>(); - public HashMap staticMethods = new HashMap<>(); - public HashMap genericStaticMethods = new HashMap<>(); + public HashMap genericMethods = new HashMap<>(); + public HashMap staticMethods = new HashMap<>(); + public HashMap genericStaticMethods = new HashMap<>(); public LeekAnonymousFunction initFields = null; private ArrayLeekValue fieldsArray; private ArrayLeekValue methodsArray; - public ClassLeekValue(String name) { + public ClassLeekValue(AI ai, String name) { + this.ai = ai; this.name = name; - this.parent = LeekValueManager.NULL; + this.parent = null; } - public void setParent(AbstractLeekValue parent) { + public void setParent(ClassLeekValue parent) { this.parent = parent; } - public void addConstructor(int arg_count, LeekAnonymousFunction function) { - constructors.put(arg_count, function); + public void addConstructor(int arg_count, LeekAnonymousFunction function, AccessLevel level) { + constructors.put(arg_count, new ClassMethod(function, level)); } public void addField(AI ai, String field, AccessLevel level) { fields.put(field, new ClassField(null, level)); } - public void addStaticField(AI ai, String field, AbstractLeekValue value, AccessLevel level) throws LeekRunException { + public void addStaticField(AI ai, String field, Object value, AccessLevel level) throws LeekRunException { staticFields.put(field, new ObjectVariableValue(ai, value, level)); } @@ -73,38 +84,37 @@ public void addMethod(String method, int argCount, LeekAnonymousFunction functio public void addGenericMethod(String method) { genericMethods.put(method, new FunctionLeekValue(new LeekAnonymousFunction() { - public AbstractLeekValue run(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException { + public Object run(ObjectLeekValue thiz, Object... arguments) throws LeekRunException { final var methodCode = method + "_" + arguments.length; final var m = methods.get(methodCode); if (m != null) { - return m.value.run(ai, thiz, arguments); + return m.value.run(thiz, arguments); } ai.addSystemLog(leekscript.AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { name, createMethodError(methodCode) }); - return LeekValueManager.NULL; + return null; } })); } - public void addStaticMethod(String method, int argCount, LeekAnonymousFunction function, AccessLevel level) { - staticMethods.put(method + "_" + argCount, new ClassMethod(function, level)); + public void addStaticMethod(String method, int argCount, LeekFunction function, AccessLevel level) { + staticMethods.put(method + "_" + argCount, new ClassStaticMethod(function, level)); } public void addGenericStaticMethod(String method) { genericMethods.put(method, new FunctionLeekValue(new LeekAnonymousFunction() { - public AbstractLeekValue run(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException { + public Object run(ObjectLeekValue thiz, Object... arguments) throws LeekRunException { final var methodCode = method + "_" + arguments.length; final var m = methods.get(methodCode); if (m != null) { - return m.value.run(ai, null, arguments); + return m.value.run(null, arguments); } ai.addSystemLog(leekscript.AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { name, createMethodError(methodCode) }); - return LeekValueManager.NULL; + return null; } })); } - @Override - public AbstractLeekValue getField(AI ai, String field, ClassLeekValue fromClass) throws LeekRunException { + public Object getField(AI ai, String field, ClassLeekValue fromClass) throws LeekRunException { // Private var result = staticFields.get(field); if (result != null) { @@ -115,54 +125,80 @@ public AbstractLeekValue getField(AI ai, String field, ClassLeekValue fromClass) if (fromClass != null && fromClass.descendsFrom(this)) { if (result.level == AccessLevel.PRIVATE) { ai.addSystemLog(AILog.ERROR, Error.PRIVATE_STATIC_FIELD, new String[] { this.name, field }); - return LeekValueManager.NULL; + return null; } return result; } else { // Public : Access from outside if (result.level != AccessLevel.PUBLIC) { ai.addSystemLog(AILog.ERROR, result.level == AccessLevel.PROTECTED ? Error.PROTECTED_STATIC_FIELD : Error.PRIVATE_STATIC_FIELD, new String[] { this.name, field }); - return LeekValueManager.NULL; + return null; } return result; } } } if (field.equals("name")) { - return new StringLeekValue(name); + return name; } else if (field.equals("fields")) { - return getFieldsArray(ai); + return getFieldsArray(); } else if (field.equals("methods")) { - return getMethodsArray(ai); + return getMethodsArray(); } else if (field.equals("parent")) { return parent; } if (parent instanceof ClassLeekValue) { return parent.getField(ai, field, fromClass); } - return LeekValueManager.NULL; + return null; } - @Override - public AbstractLeekValue callMethod(AI ai, String method, ClassLeekValue fromClass, AbstractLeekValue... arguments) throws LeekRunException { - ai.addOperations(1); + public Box getFieldL(String field) throws LeekRunException { + Box result = staticFields.get(field); + if (result != null) { + return result; + } + if (parent instanceof ClassLeekValue) { + return parent.getFieldL(field); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object setField(String field, Object value) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.set(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object incField(String field) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.increment(); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object callMethod(AI ai, String method, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { + ai.ops(1); var result = getStaticMethod(ai, method, fromClass); if (result == null) { ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_STATIC_METHOD, new String[] { name, createMethodError(method) }); - return LeekValueManager.NULL; + return null; } // Call method with new arguments, add the object at the beginning - return result.run(ai, null, arguments); + return result.run(arguments); } - public void callConstructor(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException { - ai.addOperations(1); + public Object callConstructor(ObjectLeekValue thiz, Object... arguments) throws LeekRunException { if (!constructors.containsKey(arguments.length)) { ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_CONSTRUCTOR, new String[] { name, String.valueOf(arguments.length) }); - return; + return thiz; } - constructors.get(arguments.length).run(ai, thiz, arguments); + constructors.get(arguments.length).value.run(thiz, arguments); + return thiz; } public static String createMethodError(String method) { @@ -180,17 +216,16 @@ public static String createMethodError(String method) { /** * Constructors */ - @Override - public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... arguments) throws LeekRunException { - ai.addOperations(1); + public Object execute(Object... arguments) throws LeekRunException { // Create the actual object + ai.ops(1); ObjectLeekValue object = new ObjectLeekValue(this); // Init fields - this.initFields.run(ai, object); + this.initFields.run(object); int arg_count = arguments.length; if (constructors.containsKey(arg_count)) { - return constructors.get(arg_count).run(ai, object, arguments); + return constructors.get(arg_count).value.run(object, arguments); } else { if (arg_count > 0) { ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_CONSTRUCTOR, new String[] { name, String.valueOf(arguments.length) }); @@ -199,24 +234,24 @@ public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... arguments) } } - private ArrayLeekValue getFieldsArray(AI ai) throws LeekRunException { + private ArrayLeekValue getFieldsArray() throws LeekRunException { if (fieldsArray == null) { - AbstractLeekValue[] values = new AbstractLeekValue[fields.size()]; + Object[] values = new Object[fields.size()]; int i = 0; for (var f : fields.entrySet()) { - values[i++] = new StringLeekValue(f.getKey()); + values[i++] = f.getKey(); } fieldsArray = new ArrayLeekValue(ai, values); } return fieldsArray; } - private ArrayLeekValue getMethodsArray(AI ai) throws LeekRunException { + private ArrayLeekValue getMethodsArray() throws LeekRunException { if (methodsArray == null) { - AbstractLeekValue[] values = new AbstractLeekValue[genericMethods.size()]; + Object[] values = new Object[genericMethods.size()]; int i = 0; for (var f : genericMethods.entrySet()) { - values[i++] = new StringLeekValue(f.getKey()); + values[i++] = f.getKey(); } methodsArray = new ArrayLeekValue(ai, values); } @@ -253,7 +288,7 @@ public LeekAnonymousFunction getMethod(AI ai, String method, ClassLeekValue from return null; } - public LeekAnonymousFunction getStaticMethod(AI ai, String method, ClassLeekValue fromClass) throws LeekRunException { + public LeekFunction getStaticMethod(AI ai, String method, ClassLeekValue fromClass) throws LeekRunException { var m = staticMethods.get(method); if (m != null) { // Private : Access from same class @@ -290,59 +325,21 @@ public LeekAnonymousFunction getSuperMethod(AI ai, String method, ClassLeekValue return null; } - @Override - public boolean getBoolean() { - return true; - } - - @Override - public int getInt(AI ai) { - return 0; - } - - @Override - public double getDouble(AI ai) { - return 0; - } - - @Override - public boolean isNumeric() { - return false; - } - - @Override public String getString(AI ai) { return ""; } - @Override - public int getV10Type() { - return CLASS_V10; - } - - @Override - public int getType() { - return CLASS; - } - - @Override - public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { + public boolean equals(AI ai, Object comp) throws LeekRunException { if (comp instanceof ClassLeekValue) { return ((ClassLeekValue) comp).name.equals(this.name); } return false; } - @Override public Object toJSON(AI ai) { return name; } - @Override - public boolean isPrimitive() { - return false; - } - public boolean descendsFrom(ClassLeekValue clazz) { var current = this; while (current != null) { diff --git a/src/main/java/leekscript/runner/values/DoubleLeekValue.java b/src/main/java/leekscript/runner/values/DoubleLeekValue.java deleted file mode 100644 index a58a6373..00000000 --- a/src/main/java/leekscript/runner/values/DoubleLeekValue.java +++ /dev/null @@ -1,217 +0,0 @@ -package leekscript.runner.values; - -import java.text.DecimalFormat; - -import leekscript.AILog; -import leekscript.runner.AI; -import leekscript.runner.LeekRunException; -import leekscript.runner.LeekValueManager; -import leekscript.common.Error; -import leekscript.runner.LeekOperations; - -public class DoubleLeekValue extends AbstractLeekValue { - - private double mValue; - - public DoubleLeekValue(double value) { - mValue = value; - } - - @Override - public int getInt(AI ai) { - return (int) mValue; - } - - @Override - public double getDouble(AI ai) { - return mValue; - } - - @Override - public boolean getBoolean() { - return mValue != 0; - } - - @Override - public String getString(AI ai) throws LeekRunException { - ai.addOperations(3); - if (ai.getVersion() <= 10) { - DecimalFormat df = new DecimalFormat(); - df.setMinimumFractionDigits(0); - return df.format(mValue); - } - return String.valueOf(mValue); - } - - @Override - public boolean isNumeric() { - return true; - } - - public AbstractLeekValue oppositeConstant() throws LeekRunException { - return LeekValueManager.getLeekDoubleValue(-mValue); - } - - @Override - public AbstractLeekValue increment(AI ai) throws LeekRunException { - ai.addOperations(ADD_COST); - mValue++; - return new DoubleLeekValue(mValue - 1d); - } - - @Override - public AbstractLeekValue decrement(AI ai) throws LeekRunException { - ai.addOperations(ADD_COST); - mValue--; - return new DoubleLeekValue(mValue + 1d); - } - - @Override - public AbstractLeekValue pre_increment(AI ai) throws LeekRunException { - ai.addOperations(ADD_COST); - mValue++; - return new DoubleLeekValue(mValue); - } - - @Override - public AbstractLeekValue pre_decrement(AI ai) throws LeekRunException { - ai.addOperations(ADD_COST); - mValue--; - return new DoubleLeekValue(mValue); - } - - @Override - public boolean less(AI ai, AbstractLeekValue comp) throws LeekRunException { - ai.addOperations(1); - return getDouble(ai) < comp.getDouble(ai); - } - - @Override - public boolean more(AI ai, AbstractLeekValue comp) throws LeekRunException { - ai.addOperations(1); - return getDouble(ai) > comp.getDouble(ai); - } - - @Override - public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.add(ai, this, val); - } - - @Override - public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { - ai.addOperations(ADD_COST); - mValue -= val.getDouble(ai); - return this; - } - - @Override - public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { - ai.addOperations(MUL_COST); - mValue *= val.getDouble(ai); - return this; - } - - @Override - public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { - ai.addOperations(DIV_COST); - double y_real = val.getDouble(ai); - if (ai.getVersion() == 10 && y_real == 0) { - ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); - return LeekValueManager.NULL; - } - mValue /= y_real; - return this; - } - - @Override - public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { - ai.addOperations(MOD_COST); - mValue %= val.getDouble(ai); - return this; - } - - @Override - public AbstractLeekValue opposite(AI ai) throws LeekRunException { - ai.addOperations(ADD_COST); - return new DoubleLeekValue(-getDouble(ai)); - } - - @Override - public AbstractLeekValue power(AI ai, AbstractLeekValue val) throws LeekRunException { - ai.addOperations(POW_COST); - mValue = Math.pow(mValue, val.getDouble(ai)); - return this; - } - - @Override - public AbstractLeekValue band(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(getInt(ai) & value.getInt(ai)); - } - - @Override - public AbstractLeekValue bor(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(getInt(ai) | value.getInt(ai)); - } - - @Override - public AbstractLeekValue bxor(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(getInt(ai) ^ value.getInt(ai)); - } - - @Override - public AbstractLeekValue bleft(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(getInt(ai) << value.getInt(ai)); - } - - @Override - public AbstractLeekValue bright(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(getInt(ai) >> value.getInt(ai)); - } - - @Override - public AbstractLeekValue brotate(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(getInt(ai) >>> value.getInt(ai)); - } - - @Override - public int getV10Type() { - return NUMBER_V10; - } - - @Override - public int getType() { - return NUMBER; - } - - @Override - public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { - if (comp.getType() == NUMBER) { - return comp.getDouble(ai) == mValue; - } else if (comp.getType() == BOOLEAN) { - return comp.getBoolean() == getBoolean(); - } else if (comp.getType() == STRING) { - if (comp.getString(ai).equals("true")) - return mValue != 0; - return mValue == comp.getDouble(ai); - } else if (comp.getType() == ARRAY) { - return comp.equals(ai, this); - } - return false; - } - - @Override - public Object toJSON(AI ai) { - return mValue; - } - - @Override - public boolean isPrimitive() { - return true; - } -} diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index 03e89164..65eaaaf8 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -6,13 +6,12 @@ import leekscript.runner.AI; import leekscript.runner.ILeekFunction; import leekscript.runner.LeekAnonymousFunction; -import leekscript.runner.LeekFunctions; import leekscript.runner.LeekOperations; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; import leekscript.common.Error; -public class FunctionLeekValue extends AbstractLeekValue { +public class FunctionLeekValue { private final static int LEEK_FUNCTION = 1; private final static int USER_FUNCTION = 2; @@ -47,9 +46,8 @@ public FunctionLeekValue(LeekAnonymousFunction fonction) { mId = 0; } - @Override - public boolean equals(AI ai, AbstractLeekValue comp) { - if (comp.getType() != getType()) { + public boolean equals(AI ai, Object comp) { + if (LeekValueManager.getType(comp) != LeekValue.FUNCTION) { return false; } if (!(comp instanceof FunctionLeekValue)) { @@ -65,20 +63,18 @@ public boolean equals(AI ai, AbstractLeekValue comp) { } } - @Override - public int getV10Type() { - return FUNCTION_V10; - } - - @Override - public int getType() { - return FUNCTION; + private Object[] prepareValues(Object[] values, int count) { + Object[] retour = new Object[count]; + for (int i = 0; i < count; i++) { + retour[i] = (i >= values.length) ? null : LeekValueManager.getValue(values[i]); + } + return retour; } - private AbstractLeekValue[] copyValues(AI uai, AbstractLeekValue[] values, boolean[] references) throws LeekRunException { - AbstractLeekValue[] copy = new AbstractLeekValue[values.length]; + private Object[] copyValues(AI uai, Object[] values, boolean[] references) throws LeekRunException { + Object[] copy = new Object[values.length]; for (int i = 0; i < values.length; i++) { - if (!references[i] && values[i] instanceof VariableLeekValue) + if (!references[i] && values[i] instanceof Box) copy[i] = LeekOperations.clone(uai, values[i]); else copy[i] = values[i]; @@ -86,23 +82,14 @@ private AbstractLeekValue[] copyValues(AI uai, AbstractLeekValue[] values, boole return copy; } - private AbstractLeekValue[] copyPrimitiveValues(AI uai, AbstractLeekValue[] values) throws LeekRunException { - AbstractLeekValue[] copy = new AbstractLeekValue[values.length]; + private Object[] copyPrimitiveValues(AI uai, Object[] values) throws LeekRunException { + Object[] copy = new Object[values.length]; for (int i = 0; i < values.length; i++) { - copy[i] = LeekOperations.clonePrimitive(uai, values[i]); + copy[i] = LeekOperations.clone(uai, values[i]); } return copy; } - private AbstractLeekValue[] prepareValues(AbstractLeekValue[] values, int count) { - AbstractLeekValue[] retour = new AbstractLeekValue[count]; - for (int i = 0; i < count; i++) { - retour[i] = (i >= values.length) ? LeekValueManager.NULL : values[i].getValue(); - } - return retour; - } - - @Override public int getArgumentsCount(AI ai) throws LeekRunException { if (mType == LEEK_FUNCTION) return mFunction.getArguments(); @@ -113,44 +100,37 @@ else if (mType == ANONYMOUS_FUNCTION) return -1; } - @Override - public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... values) throws LeekRunException { + public Object execute(AI ai, Object... values) throws LeekRunException { if (mType == LEEK_FUNCTION) { - return LeekFunctions.executeFunction(ai, mFunction, prepareValues(values, mFunction.getArguments()), values.length); + return ai.sysexec(mFunction, prepareValues(values, mFunction.getArguments())); } else if (mType == USER_FUNCTION) { if (values.length != ai.userFunctionCount(mId)) { - ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { AbstractLeekValue.getParamString(values), String.valueOf(ai.userFunctionCount(mId)) }); + ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { LeekValue.getParamString(values), String.valueOf(ai.userFunctionCount(mId)) }); } else { if (ai.getVersion() >= 11) { - return ai.userFunctionExecute(mId, copyPrimitiveValues(ai, values)); + return ai.userFunctionExecute(mId, values); } else { return ai.userFunctionExecute(mId, copyValues(ai, values, ai.userFunctionReference(mId))); } } - } - else if (mType == ANONYMOUS_FUNCTION) { + } else if (mType == ANONYMOUS_FUNCTION) { if (values.length != ai.anonymousFunctionCount(mId)) { - ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { AbstractLeekValue.getParamString(values), String.valueOf(ai.anonymousFunctionCount(mId)) }); + ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { LeekValue.getParamString(values), String.valueOf(ai.anonymousFunctionCount(mId)) }); } else { - if (ai.getVersion() >= 11) { - return mAnonymous.run(ai, null, copyPrimitiveValues(ai, values)); - } else { - return mAnonymous.run(ai, null, copyValues(ai, values, ai.anonymousFunctionReference(mId))); - } + return mAnonymous.run(null, values); } } else if (mType == METHOD) { if (values.length == 0) { ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { "", "1+" }); } else { - return mAnonymous.run(ai, values[0], Arrays.copyOfRange(copyPrimitiveValues(ai, values), 1, values.length)); + return mAnonymous.run((ObjectLeekValue) values[0], Arrays.copyOfRange(values, 1, values.length)); } } - return LeekValueManager.NULL; + return null; } - @Override public String getString(AI ai) { if (mType == LEEK_FUNCTION) return "#Function " + mFunction; @@ -162,7 +142,7 @@ else if (mType == METHOD) return "#Anonymous Function"; } - public AbstractLeekValue cloneFunction() { + public FunctionLeekValue cloneFunction() { if (mType == LEEK_FUNCTION) return new FunctionLeekValue(mFunction); else if (mType == USER_FUNCTION) @@ -171,13 +151,7 @@ else if (mType == USER_FUNCTION) return new FunctionLeekValue(mId, mAnonymous); } - @Override public Object toJSON(AI ai) { return ""; } - - @Override - public boolean isPrimitive() { - return false; - } } diff --git a/src/main/java/leekscript/runner/values/IntLeekValue.java b/src/main/java/leekscript/runner/values/IntLeekValue.java deleted file mode 100644 index 24aff3eb..00000000 --- a/src/main/java/leekscript/runner/values/IntLeekValue.java +++ /dev/null @@ -1,239 +0,0 @@ -package leekscript.runner.values; - -import leekscript.AILog; -import leekscript.runner.AI; -import leekscript.runner.LeekOperations; -import leekscript.runner.LeekRunException; -import leekscript.runner.LeekValueManager; -import leekscript.runner.LeekOperations; -import leekscript.common.Error; - -public class IntLeekValue extends AbstractLeekValue { - private int mValue; - - public IntLeekValue(int value) { - mValue = value; - } - - @Override - public void setInt(int nb) { - mValue = nb; - } - - @Override - public int getInt(AI ai) { - return mValue; - } - - @Override - public double getDouble(AI ai) { - return mValue; - } - - @Override - public boolean getBoolean() { - return mValue != 0; - } - - @Override - public String getString(AI ai) throws LeekRunException { - ai.addOperations(3); - return String.valueOf(mValue); - } - - @Override - public boolean isNumeric() { - return true; - } - - public IntLeekValue oppositeConstant() throws LeekRunException { - return LeekValueManager.getLeekIntValue(-mValue); - } - - @Override - public AbstractLeekValue increment(AI ai) { - return this; - } - - @Override - public AbstractLeekValue decrement(AI ai) { - return this; - } - - @Override - public AbstractLeekValue pre_increment(AI ai) throws LeekRunException { - ai.addOperations(ADD_COST); - return LeekValueManager.getLeekIntValue(mValue + 1); - } - - @Override - public AbstractLeekValue pre_decrement(AI ai) throws LeekRunException { - ai.addOperations(ADD_COST); - return LeekValueManager.getLeekIntValue(mValue - 1); - } - - @Override - public boolean less(AI ai, AbstractLeekValue comp) throws LeekRunException { - comp = comp.getValue(); - if (comp instanceof DoubleLeekValue) { - ai.addOperations(1); - return getDouble(ai) < comp.getDouble(ai); - } - return super.less(ai, comp); - } - - @Override - public boolean more(AI ai, AbstractLeekValue comp) throws LeekRunException { - comp = comp.getValue(); - if (comp instanceof DoubleLeekValue) { - ai.addOperations(1); - return getDouble(ai) > comp.getDouble(ai); - } - return super.more(ai, comp); - } - - // Assign: - - @Override - public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.add(ai, this, val); - } - - @Override - public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { - ai.addOperations(ADD_COST); - val = val.getValue(); - if (val instanceof DoubleLeekValue) - return new DoubleLeekValue(mValue - val.getDouble(ai)); - return LeekValueManager.getLeekIntValue(ai, mValue - val.getInt(ai), this); - } - - @Override - public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { - ai.addOperations(MUL_COST); - val = val.getValue(); - if (val instanceof DoubleLeekValue) - return new DoubleLeekValue(mValue * val.getDouble(ai)); - return LeekValueManager.getLeekIntValue(ai, mValue * val.getInt(ai), this); - } - - @Override - public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { - ai.addOperations(MOD_COST); - val = val.getValue(); - if (val instanceof DoubleLeekValue) { - double y_real = val.getDouble(ai); - if (ai.getVersion() == 10 && y_real == 0) { - ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); - return LeekValueManager.NULL; - } - return new DoubleLeekValue(mValue % y_real); - } - int y_int = val.getInt(ai); - if (ai.getVersion() == 10 && y_int == 0) { - ai.addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); - return LeekValueManager.NULL; - } - return LeekValueManager.getLeekIntValue(ai, mValue % y_int, this); - } - - @Override - public AbstractLeekValue power(AI ai, AbstractLeekValue val) throws LeekRunException { - ai.addOperations(POW_COST); - val = val.getValue(); - if (val instanceof DoubleLeekValue) - return new DoubleLeekValue(Math.pow(mValue, val.getDouble(ai))); - return LeekValueManager.getLeekIntValue(ai, (int) Math.pow(mValue, val.getInt(ai)), this); - } - - @Override - public AbstractLeekValue band(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(ai, mValue & value.getInt(ai), this); - } - - @Override - public AbstractLeekValue bor(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(ai, mValue | value.getInt(ai), this); - } - - @Override - public AbstractLeekValue bxor(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(ai, mValue ^ value.getInt(ai), this); - } - - @Override - public AbstractLeekValue bleft(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(ai, mValue << value.getInt(ai), this); - } - - @Override - public AbstractLeekValue bright(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(ai, mValue >> value.getInt(ai), this); - } - - @Override - public AbstractLeekValue brotate(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - return LeekValueManager.getLeekIntValue(ai, mValue >>> value.getInt(ai), this); - } - - @Override - public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.divide(ai, this, val); - } - - @Override - public int getV10Type() { - return NUMBER_V10; - } - - @Override - public int getType() { - return NUMBER; - } - - @Override - public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { - if (comp instanceof IntLeekValue) { - return comp.getInt(ai) == mValue; - } - else if (comp.getType() == NUMBER) { - return comp.getDouble(ai) == mValue; - } - else if (comp.getType() == BOOLEAN) { - return comp.getBoolean() == getBoolean(); - } - else if (comp.getType() == STRING) { - if (comp.getString(ai).equals("false") || comp.getString(ai).equals("0") || comp.getString(ai).equals("")) - return mValue == 0; - if (comp.getString(ai).equals("true")) - return mValue != 0; - if (comp.getString(ai).equals("1") && mValue == 1) return true; - try { - ai.addOperations(comp.getString(ai).length()); - return mValue == Integer.parseInt(comp.getString(ai)); - } catch (Exception e) { - return false; - } - } - else if (comp.getType() == ARRAY) { - return comp.equals(ai, this); - } - return false; - } - - @Override - public Object toJSON(AI ai) { - return mValue; - } - - @Override - public boolean isPrimitive() { - return true; - } -} diff --git a/src/main/java/leekscript/runner/values/NullLeekValue.java b/src/main/java/leekscript/runner/values/NullLeekValue.java deleted file mode 100644 index cbb666a4..00000000 --- a/src/main/java/leekscript/runner/values/NullLeekValue.java +++ /dev/null @@ -1,107 +0,0 @@ -package leekscript.runner.values; - -import leekscript.runner.AI; -import leekscript.runner.LeekOperations; -import leekscript.runner.LeekRunException; - -public class NullLeekValue extends AbstractLeekValue { - @Override - public boolean isNull() { - return true; - } - - @Override - public boolean isNumeric() { - return true; - } - - @Override - public String getString(AI ai) { - return "null"; - } - - @Override - public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.add(ai, this, val); - } - - @Override - public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.minus(ai, this, val); - } - - @Override - public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.multiply(ai, this, val); - } - - @Override - public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.divide(ai, this, val); - } - - @Override - public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.modulus(ai, this, val); - } - - @Override - public AbstractLeekValue power(AI ai, AbstractLeekValue value) throws LeekRunException { - return LeekOperations.power(ai, this, value); - } - - @Override - public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.band(ai, this, val); - } - - @Override - public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bor(ai, this, val); - } - - @Override - public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bxor(ai, this, val); - } - - @Override - public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bleft(ai, this, val); - } - - @Override - public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bright(ai, this, val); - } - - @Override - public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.brotate(ai, this, val); - } - - @Override - public int getV10Type() { - return NULL_V10; - } - - @Override - public int getType() { - return NULL; - } - - @Override - public boolean equals(AI ai, AbstractLeekValue comp) { - return comp.getType() == NULL; - } - - @Override - public Object toJSON(AI ai) { - return null; - } - - @Override - public boolean isPrimitive() { - return true; - } -} diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index b9b54448..22e47ab3 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -12,7 +12,7 @@ import leekscript.common.AccessLevel; import leekscript.common.Error; -public class ObjectLeekValue extends AbstractLeekValue { +public class ObjectLeekValue { public final ClassLeekValue clazz; public final HashMap fields = new HashMap<>(); @@ -23,24 +23,22 @@ public ObjectLeekValue(ClassLeekValue clazz) { public ObjectLeekValue(AI ai, ObjectLeekValue value, int level) throws LeekRunException { this.clazz = value.clazz; - ai.addOperations(value.fields.size()); + ai.ops(value.fields.size()); for (var field : value.fields.entrySet()) { if (level == 1) { - fields.put(field.getKey(), new ObjectVariableValue(ai, LeekOperations.clonePrimitive(ai, field.getValue()), field.getValue().level)); + fields.put(field.getKey(), new ObjectVariableValue(ai, field.getValue().getValue(), field.getValue().level)); } else { - fields.put(field.getKey(), new ObjectVariableValue(ai, LeekOperations.clone(ai, field.getValue(), level - 1), field.getValue().level)); + fields.put(field.getKey(), new ObjectVariableValue(ai, LeekOperations.clone(ai, field.getValue().getValue(), level - 1), field.getValue().level)); } } } - public void addField(AI ai, String field, AbstractLeekValue value, AccessLevel level) throws LeekRunException { + public void addField(AI ai, String field, Object value, AccessLevel level) throws LeekRunException { fields.put(field, new ObjectVariableValue(ai, LeekOperations.clone(ai, value), level)); } - @Override - public AbstractLeekValue getField(AI ai, String field, ClassLeekValue fromClass) throws LeekRunException { + public Object getField(String field, ClassLeekValue fromClass) throws LeekRunException { // System.out.println("getField " + field); - ai.addOperations(1); if (field.equals("class")) { return clazz; } @@ -53,15 +51,15 @@ public AbstractLeekValue getField(AI ai, String field, ClassLeekValue fromClass) // Protected : Access from descendant if (fromClass != null && fromClass.descendsFrom(clazz)) { if (result.level == AccessLevel.PRIVATE) { - ai.addSystemLog(AILog.ERROR, Error.PRIVATE_FIELD, new String[] { clazz.name, field }); - return LeekValueManager.NULL; + clazz.ai.addSystemLog(AILog.ERROR, Error.PRIVATE_FIELD, new String[] { clazz.name, field }); + return null; } return result; } else { // Public : Access from outside if (result.level != AccessLevel.PUBLIC) { - ai.addSystemLog(AILog.ERROR, result.level == AccessLevel.PROTECTED ? Error.PROTECTED_FIELD : Error.PRIVATE_FIELD, new String[] { clazz.name, field }); - return LeekValueManager.NULL; + clazz.ai.addSystemLog(AILog.ERROR, result.level == AccessLevel.PROTECTED ? Error.PROTECTED_FIELD : Error.PRIVATE_FIELD, new String[] { clazz.name, field }); + return null; } return result; } @@ -70,34 +68,75 @@ public AbstractLeekValue getField(AI ai, String field, ClassLeekValue fromClass) var method = clazz.genericMethods.get(field); if (method != null) return method; - ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { clazz.name, field }); - return LeekValueManager.NULL; + clazz.ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { clazz.name, field }); + return null; } - @Override - public AbstractLeekValue get(AI ai, AbstractLeekValue value) throws LeekRunException { - return getField(ai, value.getString(ai), null); + public Box getFieldL(String field) throws LeekRunException { + // System.out.println("getField " + field); + var result = fields.get(field); + if (result != null) { + return result; + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + // ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { clazz.name, field }); + // return null; } - @Override - public AbstractLeekValue get(AI ai, AbstractLeekValue value, ClassLeekValue fromClass) throws LeekRunException { - return getField(ai, value.getString(ai), fromClass); + public Object setField(String field, Object value) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + result.set(value); + } + return value; } - @Override - public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value) throws LeekRunException { - return getField(ai, value.getString(ai), null); + public Object field_inc(String field) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.increment(); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } - @Override - public AbstractLeekValue getOrCreate(AI ai, AbstractLeekValue value, ClassLeekValue fromClass) throws LeekRunException { - return getField(ai, value.getString(ai), fromClass); + public Object field_add_eq(String field, Object value) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.add_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } - @Override - public AbstractLeekValue callMethod(AI ai, String method, ClassLeekValue fromClass, AbstractLeekValue... arguments) throws LeekRunException { - ai.addOperations(1); - LeekAnonymousFunction result = clazz.getMethod(ai, method, fromClass); + public Object field_sub_eq(String field, Object value) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.sub_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_mul_eq(String field, Object value) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.mul_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_bor_eq(String field, Object value) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.bor_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Box getOrCreate(AI ai, Object value) throws LeekRunException { + return getFieldL(LeekValueManager.getString(ai, value)); + } + + public Object callMethod(String method, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { + var result = clazz.getMethod(clazz.ai, method, fromClass); if (result == null) { int underscore = method.lastIndexOf("_"); int argCount = Integer.parseInt(method.substring(underscore + 1)); @@ -107,16 +146,14 @@ public AbstractLeekValue callMethod(AI ai, String method, ClassLeekValue fromCla methodRealName += "x"; } methodRealName += ")"; - ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { clazz.name, methodRealName }); - return LeekValueManager.NULL; + clazz.ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { clazz.name, methodRealName }); + return null; } // Call method with new arguments, add the object at the beginning - return result.run(ai, this, arguments); + return result.run(this, arguments); } - @Override - public AbstractLeekValue callSuperMethod(AI ai, ClassLeekValue currentClass, String method, AbstractLeekValue... arguments) throws LeekRunException { - ai.addOperations(1); + public Object callSuperMethod(AI ai, ClassLeekValue currentClass, String method, Object... arguments) throws LeekRunException { LeekAnonymousFunction result = currentClass.getSuperMethod(ai, method, currentClass); if (result == null) { int underscore = method.lastIndexOf("_"); @@ -128,43 +165,30 @@ public AbstractLeekValue callSuperMethod(AI ai, ClassLeekValue currentClass, Str } methodRealName += ")"; ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { clazz.name, methodRealName }); - return LeekValueManager.NULL; + return null; } // Call method with new arguments, add the object at the beginning - return result.run(ai, this, arguments); - } - - @Override - public boolean getBoolean() { - return fields.size() > 0; + return result.run(this, arguments); } - @Override public int getInt(AI ai) { return fields.size(); } - @Override public double getDouble(AI ai) { return fields.size(); } - @Override - public boolean isNumeric() { - return true; - } - - @Override public String getString(AI ai, Set visited) throws LeekRunException { visited.add(this); var string_method = clazz.getMethod(ai, "string_0", null); if (string_method != null) { - var result = string_method.run(ai, this, new AbstractLeekValue[] {}); - if (result.getType() != STRING) { + var result = string_method.run(this); + if (!(result instanceof String)) { ai.addSystemLog(AILog.ERROR, Error.STRING_METHOD_MUST_RETURN_STRING, new String[] { clazz.name }); } else { - return result.getString(ai, visited); + return LeekValueManager.getString(ai, result, visited); } } @@ -178,42 +202,29 @@ public String getString(AI ai, Set visited) throws LeekRunException { if (visited.contains(field.getValue().getValue())) { sb.append("<...>"); } else { - if (!field.getValue().getValue().isPrimitive()) { + if (!ai.isPrimitive(field.getValue().getValue())) { visited.add(field.getValue().getValue()); } - sb.append(field.getValue().getValue().getString(ai, visited)); + sb.append(ai.getString(field.getValue().getValue(), visited)); } } sb.append("}"); return sb.toString(); } - @Override - public int getV10Type() { - return OBJECT_V10; - } - - @Override - public int getType() { - return OBJECT; - } - - @Override - public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { - comp = comp.getValue(); + public boolean equals(AI ai, Object comp) throws LeekRunException { if (comp instanceof ObjectLeekValue) { return this == comp; } return false; } - public boolean equalsDeep(AI ai, AbstractLeekValue comp) throws LeekRunException { - comp = comp.getValue(); + public boolean equalsDeep(AI ai, Object comp) throws LeekRunException { if (comp instanceof ObjectLeekValue) { var o = (ObjectLeekValue) comp; if (o.clazz != clazz) return false; for (var f : fields.entrySet()) { - if (!f.getValue().getValue().equals(ai, o.fields.get(f.getKey()))) { + if (!ai.eq(f.getValue().getValue(), o.fields.get(f.getKey()))) { return false; } } @@ -222,17 +233,29 @@ public boolean equalsDeep(AI ai, AbstractLeekValue comp) throws LeekRunException return false; } - @Override public Object toJSON(AI ai) { return "object"; } - @Override - public boolean isPrimitive() { - return false; - } - public ClassLeekValue getClazz() { return clazz; } + + public int size() { + return fields.size(); + } + + public String toString() { + var sb = new StringBuilder(clazz.name + " {"); + boolean first = true; + for (HashMap.Entry field : fields.entrySet()) { + if (first) first = false; + else sb.append(", "); + sb.append(field.getKey()); + sb.append(": "); + sb.append(field.getValue().toString()); + } + sb.append("}"); + return sb.toString(); + } } diff --git a/src/main/java/leekscript/runner/values/ObjectVariableValue.java b/src/main/java/leekscript/runner/values/ObjectVariableValue.java index 4ad28bdc..0bdc943d 100644 --- a/src/main/java/leekscript/runner/values/ObjectVariableValue.java +++ b/src/main/java/leekscript/runner/values/ObjectVariableValue.java @@ -4,7 +4,7 @@ import leekscript.runner.AI; import leekscript.runner.LeekRunException; -public class ObjectVariableValue extends VariableLeekValue { +public class ObjectVariableValue extends Box { public AccessLevel level; @@ -13,7 +13,7 @@ public ObjectVariableValue(AI ai, AccessLevel level) throws LeekRunException { this.level = level; } - public ObjectVariableValue(AI ai, AbstractLeekValue value, AccessLevel level) throws LeekRunException { + public ObjectVariableValue(AI ai, Object value, AccessLevel level) throws LeekRunException { super(ai, value); this.level = level; } diff --git a/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java b/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java deleted file mode 100644 index 0484b9b5..00000000 --- a/src/main/java/leekscript/runner/values/PhpArrayVariableLeekValue.java +++ /dev/null @@ -1,26 +0,0 @@ -package leekscript.runner.values; - -import leekscript.runner.AI; -import leekscript.runner.LeekRunException; -import leekscript.runner.PhpArray; - -public class PhpArrayVariableLeekValue extends VariableLeekValue { - - public PhpArrayVariableLeekValue(PhpArray array, AI uai, AbstractLeekValue value, int keySize) throws LeekRunException { - super(uai, value.getValue()); - } - - @Override - public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunException { - value = value.getValue(); - super.set(ai, value); - return mValue; - } - - @Override - public AbstractLeekValue setNoOps(AI ai, AbstractLeekValue value) throws LeekRunException { - value = value.getValue(); - super.setNoOps(ai, value); - return mValue; - } -} diff --git a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java b/src/main/java/leekscript/runner/values/ReferenceLeekValue.java deleted file mode 100644 index 045565d6..00000000 --- a/src/main/java/leekscript/runner/values/ReferenceLeekValue.java +++ /dev/null @@ -1,214 +0,0 @@ -package leekscript.runner.values; - -import leekscript.runner.AI; -import leekscript.runner.LeekOperations; -import leekscript.runner.LeekRunException; - -public class ReferenceLeekValue extends AbstractLeekValue { - - private AbstractLeekValue mValue; - - public ReferenceLeekValue(AI ai, AbstractLeekValue value) throws LeekRunException { - if (ai.getVersion() >= 11) { - mValue = value.getValue(); - } else { - if (!(value instanceof ReferenceLeekValue)) - mValue = value; - else - mValue = LeekOperations.clone(ai, value.getValue()); - } - } - - @Override - public int getInt(AI ai) throws LeekRunException { - return mValue.getInt(ai); - } - - @Override - public double getDouble(AI ai) throws LeekRunException { - return mValue.getDouble(ai); - } - - @Override - public String getString(AI ai) throws LeekRunException { - return mValue.getString(ai); - } - - @Override - public boolean getBoolean() { - return mValue.getBoolean(); - } - - @Override - public ArrayLeekValue getArray() { - return mValue.getArray(); - } - - @Override - public boolean isArray() { - return mValue.isArray(); - } - - @Override - public boolean isArrayForIteration(AI ai) throws LeekRunException { - return mValue.isArray(); - } - - @Override - public boolean isNull() { - return mValue.isNull(); - } - - // Fonctions spéciales L-Values - @Override - public AbstractLeekValue getValue() { - return mValue.getValue(); - } - - @Override - public AbstractLeekValue increment(AI ai) throws LeekRunException { - return mValue.increment(ai); - } - - @Override - public AbstractLeekValue decrement(AI ai) throws LeekRunException { - return mValue.decrement(ai); - } - - @Override - public AbstractLeekValue pre_increment(AI ai) throws LeekRunException { - return mValue.pre_increment(ai); - } - - @Override - public AbstractLeekValue pre_decrement(AI ai) throws LeekRunException { - return mValue.pre_decrement(ai); - } - - @Override - public AbstractLeekValue opposite(AI ai) throws LeekRunException { - return mValue.opposite(ai); - } - - @Override - public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { - return mValue.equals(ai, comp); - } - - @Override - public boolean less(AI ai, AbstractLeekValue comp) throws LeekRunException { - return mValue.less(ai, comp); - } - - @Override - public boolean more(AI ai, AbstractLeekValue comp) throws LeekRunException { - return mValue.more(ai, comp); - } - - @Override - public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { - - return mValue = mValue.add(ai, val); - } - - @Override - public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { - - return mValue = mValue.minus(ai, val); - } - - @Override - public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { - - return mValue = mValue.multiply(ai, val); - } - - @Override - public AbstractLeekValue power(AI ai, AbstractLeekValue val) throws LeekRunException { - - return mValue = mValue.power(ai, val); - } - - @Override - public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws LeekRunException { - - return mValue = mValue.band(ai, val); - } - - @Override - public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws LeekRunException { - - return mValue = mValue.bor(ai, val); - } - - @Override - public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws LeekRunException { - - return mValue = mValue.bxor(ai, val); - } - - @Override - public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws LeekRunException { - - return mValue = mValue.bleft(ai, val); - } - - @Override - public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws LeekRunException { - - return mValue = mValue.bright(ai, val); - } - - @Override - public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws LeekRunException { - - return mValue = mValue.brotate(ai, val); - } - - @Override - public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { - - return mValue = mValue.divide(ai, val); - } - - @Override - public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { - - return mValue = mValue.modulus(ai, val); - } - - @Override - public int getV10Type() { - return mValue.getV10Type(); - } - - @Override - public int getType() { - return mValue.getType(); - } - - @Override - public boolean isReference() { - return true; - } - - @Override - public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... values) throws LeekRunException { - return mValue.executeFunction(ai, values); - } - - @Override - public int getArgumentsCount(AI ai) throws LeekRunException { - return mValue.getArgumentsCount(ai); - } - - @Override - public Object toJSON(AI ai) throws LeekRunException { - return mValue.toJSON(ai); - } - - @Override - public boolean isPrimitive() { - return mValue.isPrimitive(); - } -} diff --git a/src/main/java/leekscript/runner/values/StringLeekValue.java b/src/main/java/leekscript/runner/values/StringLeekValue.java deleted file mode 100644 index 7bfcd22a..00000000 --- a/src/main/java/leekscript/runner/values/StringLeekValue.java +++ /dev/null @@ -1,174 +0,0 @@ -package leekscript.runner.values; - -import leekscript.runner.AI; -import leekscript.runner.LeekRunException; -import leekscript.runner.LeekOperations; - -public class StringLeekValue extends AbstractLeekValue { - - private String mValue; - - public StringLeekValue(String value) { - mValue = value; - } - - @Override - public String getString(AI ai) { - return mValue; - } - - @Override - public boolean getBoolean() { - if (mValue.equals("false") || mValue.equals("0")) { - return false; - } - return !mValue.isEmpty(); - } - - @Override - public int getInt(AI ai) throws LeekRunException { - if (mValue.isEmpty()) - return 0; - if (mValue.equals("true")) - return 1; - if (mValue.equals("false")) - return 0; - ai.addOperations(mValue.length()); - try { - return Integer.parseInt(mValue); - } catch (Exception e) { - return mValue.length(); - } - } - - @Override - public double getDouble(AI ai) throws LeekRunException { - if (mValue.equals("true")) - return 1; - if (mValue.equals("false")) - return 0; - if (mValue.isEmpty()) - return 0; - ai.addOperations(mValue.length()); - try { - return Double.parseDouble(mValue); - } catch (Exception e) { - return mValue.length(); - } - } - - @Override - public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { - String s = val.getString(ai); - ai.addOperations(1 + s.length() + mValue.length()); - mValue += s; - return this; - } - - @Override - public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.minus(ai, this, val); - } - - @Override - public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.multiply(ai, this, val); - } - - @Override - public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.divide(ai, this, val); - } - - @Override - public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.modulus(ai, this, val); - } - - @Override - public AbstractLeekValue power(AI ai, AbstractLeekValue value) throws LeekRunException { - return LeekOperations.power(ai, this, value); - } - - @Override - public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.band(ai, this, val); - } - - @Override - public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bor(ai, this, val); - } - - @Override - public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bxor(ai, this, val); - } - - @Override - public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bleft(ai, this, val); - } - - @Override - public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.bright(ai, this, val); - } - - @Override - public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws LeekRunException { - return LeekOperations.brotate(ai, this, val); - } - - @Override - public int getV10Type() { - return STRING_V10; - } - - - @Override - public int getType() { - return STRING; - } - - @Override - public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { - if (comp.getType() == NUMBER) { - if (mValue.equals("false") || mValue.equals("0") || mValue.equals("")) { - return comp.getInt(ai) == 0; - } - if (mValue.equals("true")) { - return comp.getDouble(ai) != 0; - } - if (mValue.equals("1") && comp.getDouble(ai) == 1) { - return true; - } - if (comp instanceof IntLeekValue) - return getInt(ai) == comp.getInt(ai); - else - return getDouble(ai) == comp.getDouble(ai); - } else if (comp.getType() == BOOLEAN) { - return getBoolean() == comp.getBoolean(); - } else if (comp.getType() == STRING) { - String s = comp.getString(ai); - ai.addOperations(Math.min( - s.length(), - mValue.length() - )); - return mValue.equals(s); - } else if (comp.getType() == ARRAY) { - return comp.equals(ai, this); - } - return false; - } - - @Override - public Object toJSON(AI ai) { - return mValue; - } - - @Override - public boolean isPrimitive() { - return true; - } -} diff --git a/src/main/java/leekscript/runner/values/VariableLeekValue.java b/src/main/java/leekscript/runner/values/VariableLeekValue.java deleted file mode 100644 index 88c9b933..00000000 --- a/src/main/java/leekscript/runner/values/VariableLeekValue.java +++ /dev/null @@ -1,316 +0,0 @@ -package leekscript.runner.values; - -import java.util.Set; - -import leekscript.common.AccessLevel; -import leekscript.runner.AI; -import leekscript.runner.LeekOperations; -import leekscript.runner.LeekRunException; -import leekscript.runner.LeekValueManager; - -public class VariableLeekValue extends AbstractLeekValue { - - protected AbstractLeekValue mValue; - protected AI mUAI = null; - - public VariableLeekValue(AI ai) throws LeekRunException { - mUAI = ai; - mValue = LeekValueManager.NULL; - } - - public VariableLeekValue(AI ai, AbstractLeekValue value) throws LeekRunException { - mUAI = ai; - ai.addOperations(1); - if (ai.getVersion() >= 11) { - mValue = LeekOperations.clonePrimitive(ai, value.getValue()); - } else { - if (value instanceof VariableLeekValue) - mValue = LeekOperations.clone(ai, value.getValue()); - else - mValue = value.getValue(); - } - } - - public void init(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - if (ai.getVersion() >= 11) { - mValue = LeekOperations.clonePrimitive(ai, value.getValue()); - } else { - if (value instanceof VariableLeekValue) - mValue = LeekOperations.clone(ai, value.getValue()); - else - mValue = value.getValue(); - } - } - - @Override - public int getInt(AI ai) throws LeekRunException { - return mValue.getInt(ai); - } - - @Override - public double getDouble(AI ai) throws LeekRunException { - return mValue.getDouble(ai); - } - - @Override - public String getString(AI ai, Set visited) throws LeekRunException { - return mValue.getString(ai, visited); - } - - @Override - public boolean getBoolean() { - return mValue.getBoolean(); - } - - @Override - public ArrayLeekValue getArray() { - return mValue.getArray(); - } - - @Override - public boolean isArray() { - return mValue.isArray(); - } - - @Override - public boolean isArrayForIteration(AI ai) throws LeekRunException { - return mValue.isArray(); - } - - @Override - public boolean isNull() { - return mValue.isNull(); - } - - // Fonctions spéciales L-Values - @Override - public AbstractLeekValue getValue() { - return mValue; - } - - @Override - public AbstractLeekValue set(AI ai, AbstractLeekValue value) throws LeekRunException { - ai.addOperations(1); - if (ai.getVersion() >= 11) { - return mValue = LeekOperations.clonePrimitive(ai, value.getValue()); - } else { - if (value instanceof VariableLeekValue) - return mValue = LeekOperations.clone(ai, value.getValue()); - else - return mValue = value.getValue(); - } - } - - @Override - public AbstractLeekValue setNoOps(AI ai, AbstractLeekValue value) throws LeekRunException { - if (ai.getVersion() >= 11) { - return mValue = LeekOperations.clonePrimitive(ai, value.getValue()); - } else { - if (value instanceof VariableLeekValue) - return mValue = LeekOperations.clone(ai, value.getValue()); - else - return mValue = value.getValue(); - } - } - - @Override - public AbstractLeekValue setRef(AI ai, AbstractLeekValue value) throws LeekRunException { - return mValue = value.getValue(); - } - - public void initGlobal(AI ai, AbstractLeekValue value) throws LeekRunException { - if (value instanceof VariableLeekValue) { - if (ai.getVersion() >= 11) { - mValue = LeekOperations.clonePrimitive(ai, value.getValue()); - } else { - if (value.isReference()) - mValue = value.getValue(); - else - mValue = LeekOperations.clone(ai, value.getValue()); - } - } else { - mValue = value.getValue(); - } - } - - @Override - public AbstractLeekValue increment(AI ai) throws LeekRunException { - mValue = mValue.getValue(); - if (mValue instanceof IntLeekValue) { - ai.addOperations(1); - int value = mValue.getInt(ai); - mValue = LeekValueManager.getLeekIntValue(ai, value + 1, mValue); - return LeekValueManager.getLeekIntValue(value); - } else - return mValue.increment(ai); - } - - @Override - public AbstractLeekValue decrement(AI ai) throws LeekRunException { - mValue = mValue.getValue(); - if (mValue instanceof IntLeekValue) { - ai.addOperations(1); - int value = mValue.getInt(ai); - mValue = LeekValueManager.getLeekIntValue(ai, value - 1, mValue); - return LeekValueManager.getLeekIntValue(value); - } else - return mValue.decrement(ai); - } - - @Override - public AbstractLeekValue pre_increment(AI ai) throws LeekRunException { - mValue = mValue.getValue(); - if (mValue instanceof IntLeekValue) { - ai.addOperations(1); - int value = mValue.getInt(ai); - return mValue = LeekValueManager.getLeekIntValue(ai, value + 1, mValue); - } else - return mValue.pre_increment(ai); - } - - @Override - public AbstractLeekValue pre_decrement(AI ai) throws LeekRunException { - mValue = mValue.getValue(); - if (mValue instanceof IntLeekValue) { - ai.addOperations(1); - int value = mValue.getInt(ai); - return mValue = LeekValueManager.getLeekIntValue(ai, value - 1, mValue); - } else - return mValue.pre_decrement(ai); - } - - @Override - public AbstractLeekValue opposite(AI ai) throws LeekRunException { - return mValue.opposite(ai); - } - - @Override - public boolean equals(AI ai, AbstractLeekValue comp) throws LeekRunException { - return mValue.equals(ai, comp); - } - - @Override - public boolean less(AI ai, AbstractLeekValue comp) throws LeekRunException { - return mValue.less(ai, comp); - } - - @Override - public boolean more(AI ai, AbstractLeekValue comp) throws LeekRunException { - return mValue.more(ai, comp); - } - - @Override - public AbstractLeekValue add(AI ai, AbstractLeekValue val) throws LeekRunException { - if (mValue.getValue() instanceof ArrayLeekValue && !(val.getValue() instanceof StringLeekValue)) { - return mValue = mValue.add(ai, val); - } - return mValue = LeekOperations.add(ai, mValue, val); - } - - @Override - public AbstractLeekValue minus(AI ai, AbstractLeekValue val) throws LeekRunException { - return mValue = mValue.minus(ai, val); - } - - @Override - public AbstractLeekValue multiply(AI ai, AbstractLeekValue val) throws LeekRunException { - return mValue = mValue.multiply(ai, val); - } - - @Override - public AbstractLeekValue power(AI ai, AbstractLeekValue val) throws LeekRunException { - return mValue = mValue.power(ai, val); - } - - @Override - public AbstractLeekValue band(AI ai, AbstractLeekValue val) throws LeekRunException { - return mValue = mValue.band(ai, val); - } - - @Override - public AbstractLeekValue bor(AI ai, AbstractLeekValue val) throws LeekRunException { - return mValue = mValue.bor(ai, val); - } - - @Override - public AbstractLeekValue bxor(AI ai, AbstractLeekValue val) throws LeekRunException { - return mValue = mValue.bxor(ai, val); - } - - @Override - public AbstractLeekValue bleft(AI ai, AbstractLeekValue val) throws LeekRunException { - return mValue = mValue.bleft(ai, val); - } - - @Override - public AbstractLeekValue bright(AI ai, AbstractLeekValue val) throws LeekRunException { - return mValue = mValue.bright(ai, val); - } - - @Override - public AbstractLeekValue brotate(AI ai, AbstractLeekValue val) throws LeekRunException { - return mValue = mValue.brotate(ai, val); - } - - @Override - public AbstractLeekValue divide(AI ai, AbstractLeekValue val) throws LeekRunException { - return mValue = mValue.divide(ai, val); - } - - @Override - public AbstractLeekValue modulus(AI ai, AbstractLeekValue val) throws LeekRunException { - return mValue = mValue.modulus(ai, val); - } - - public AbstractLeekValue getField(AI ai, String field, ClassLeekValue fromClass) throws LeekRunException { - return mValue.getField(ai, field, fromClass); - } - - public AbstractLeekValue callMethod(AI ai, String field, ClassLeekValue fromClass, AbstractLeekValue... arguments) throws LeekRunException { - return mValue.callMethod(ai, field, fromClass, arguments); - } - - public AbstractLeekValue callSuperMethod(AI ai, ClassLeekValue currentClass, String field, AbstractLeekValue... arguments) throws LeekRunException { - return mValue.callSuperMethod(ai, currentClass, field, arguments); - } - - public void callConstructor(AI ai, AbstractLeekValue thiz, AbstractLeekValue... arguments) throws LeekRunException { - mValue.callConstructor(ai, thiz, arguments); - } - - @Override - public int getV10Type() { - return mValue.getV10Type(); - } - - @Override - public int getType() { - return mValue.getType(); - } - - @Override - public boolean isReference() { - return mValue.isReference(); - } - - @Override - public AbstractLeekValue executeFunction(AI ai, AbstractLeekValue... values) throws LeekRunException { - return mValue.executeFunction(ai, values); - } - - @Override - public int getArgumentsCount(AI ai) throws LeekRunException { - return mValue.getArgumentsCount(ai); - } - - @Override - public Object toJSON(AI ai) throws LeekRunException { - return mValue.toJSON(ai); - } - - @Override - public boolean isPrimitive() { - return mValue.isPrimitive(); - } -} diff --git a/src/test/java/test/TestAI.java b/src/test/java/test/TestAI.java index cf73785e..a85b2751 100644 --- a/src/test/java/test/TestAI.java +++ b/src/test/java/test/TestAI.java @@ -2,7 +2,6 @@ import leekscript.runner.AI; import leekscript.runner.LeekRunException; -import leekscript.runner.values.AbstractLeekValue; public class TestAI extends AI { @@ -21,7 +20,7 @@ protected String getAIString() { } @Override - public AbstractLeekValue runIA() throws LeekRunException { + public Object runIA() throws LeekRunException { return null; } @@ -36,7 +35,7 @@ public boolean[] userFunctionReference(int id) { } @Override - public AbstractLeekValue userFunctionExecute(int id, AbstractLeekValue[] value) throws LeekRunException { + public Object userFunctionExecute(int id, Object[] value) throws LeekRunException { return null; } diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index 6083c320..283d60a7 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -1,11 +1,15 @@ package test; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -29,6 +33,8 @@ public class TestCommon { private static long compile_time = 0; private static long load_time = 0; private static long execution_time = 0; + private static ArrayList operationsReference = new ArrayList<>(); + private static int operationsReferenceIndex = 0; private static ArrayList operations = new ArrayList<>(); private static List failedTests = new ArrayList(); @@ -116,10 +122,10 @@ public String run_version(int version, Checker checker) { AI ai = is_file ? LeekScript.compileFile(code, "AI", version) : LeekScript.compileSnippet(code, "AI", version); aiID = ai.getId(); - // compile_time = ai.getCompileTime() / 1000000; - // TestCommon.analyze_time += ai.getAnalyzeTime() / 1000000; - // TestCommon.compile_time += ai.getCompileTime() / 1000000; - // TestCommon.load_time += ai.getLoadTime() / 1000000; + compile_time = ai.getCompileTime() / 1000000; + TestCommon.analyze_time += ai.getAnalyzeTime() / 1000000; + TestCommon.compile_time += ai.getCompileTime() / 1000000; + TestCommon.load_time += ai.getLoadTime() / 1000000; ai.maxOperations = Integer.MAX_VALUE; @@ -128,9 +134,9 @@ public String run_version(int version, Checker checker) { long exec_time = (System.nanoTime() - t) / 1000; TestCommon.execution_time += exec_time / 1000; - ops = ai.getOperations(); + ops = ai.operations(); - var vs = v.getString(ai); + var vs = ai.getString(ai, new HashSet<>()); result = new Result(vs, Error.NONE, (int) ai.getOperations(), exec_time); } catch (LeekCompilerException e) { @@ -143,6 +149,7 @@ public String run_version(int version, Checker checker) { } operations.add(ops); + long referenceOperations = operationsReference.get(operationsReferenceIndex++); if (checker.check(result)) { System.out.println(GREEN_BOLD + " [OK] " + END_COLOR + "[v" + version + "] " + code + " === " + checker.getResult(result) + " " + C_GREY + compile_time + "ms + " + fn(result.exec_time) + "µs" + ", " + fn(result.operations) + " ops" + END_COLOR); @@ -251,4 +258,19 @@ public static void ouputOperationsFile() { e.printStackTrace(); } } + public static void loadReferenceOperations() { + BufferedReader reader; + try { + reader = new BufferedReader(new FileReader("opérations_v10.txt")); + String line = reader.readLine(); + while (line != null) { + operationsReference.add(Long.parseLong(line)); + line = reader.readLine(); + } + System.out.println(operationsReference.size() + " test operations references loaded."); + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } } diff --git a/src/test/java/test/TestMain.java b/src/test/java/test/TestMain.java index 64f2dc8a..496b1836 100644 --- a/src/test/java/test/TestMain.java +++ b/src/test/java/test/TestMain.java @@ -21,6 +21,8 @@ public static void main(String[] args) throws Exception { System.out.println("Start tests..."); + TestCommon.loadReferenceOperations(); + // new TestCommon().code_v11("return 5 + 5;").equals("10"); new TestGeneral().run(); new TestNumber().run(); @@ -39,8 +41,8 @@ public static void main(String[] args) throws Exception { new TestFiles().run(); new TestEuler().run(); + TestCommon.ouputOperationsFile(); Assert.assertTrue(TestCommon.summary()); - TestCommon.ouputOperationsFile(); } } From a09f7bc4f22b9ed37d3387b37d97cd1a85e76fff Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 27 Jun 2021 19:38:40 +0200 Subject: [PATCH 251/319] [leekscript] Improve code generation : continue --- .../compiler/bloc/ForeachBlock.java | 6 +- .../compiler/bloc/ForeachKeyBlock.java | 4 +- .../compiler/bloc/FunctionBlock.java | 22 +- .../compiler/expression/LeekObjectAccess.java | 40 +++- .../compiler/expression/LeekVariable.java | 8 +- .../LeekGlobalDeclarationInstruction.java | 2 +- .../instruction/LeekReturnInstruction.java | 11 +- .../LeekVariableDeclarationInstruction.java | 2 +- src/main/java/leekscript/runner/AI.java | 105 ++++++++-- .../java/leekscript/runner/LeekFunctions.java | 194 +++++++++++++----- .../leekscript/runner/LeekRunException.java | 3 +- .../runner/LeekValueComparator.java | 13 +- src/main/java/leekscript/runner/PhpArray.java | 2 +- .../runner/values/ArrayLeekValue.java | 26 ++- .../java/leekscript/runner/values/Box.java | 3 +- .../runner/values/ObjectLeekValue.java | 24 +++ 16 files changed, 359 insertions(+), 106 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java index adec9677..929e7dbe 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java @@ -51,15 +51,15 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { String iterator_name = mainblock.hasGlobal(mIterator.getWord()) ? ("g_" + mIterator) : "u_" + mIterator; // Container - writer.addCode("final var " + ar + " = "); + writer.addCode("final var " + ar + " = ops("); if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { mArray.writeJavaCode(mainblock, writer); } else { writer.compileLoad(mainblock, mArray); } - writer.addCode(";"); + writer.addCode(", " + mArray.getOperations() + ");"); - writer.addLine("if (isIterable(" + ar + ")) {"); + writer.addLine("if (isIterable(" + ar + ")) {", mIterator.getLine(), mIterator.getAI()); if (mIsDeclaration) { if (mIsDeclaration && declaration.isCaptured()) { writer.addCode("final Wrapper " + iterator_name + " = new Wrapper(new Box(" + writer.getAIThis() + ", null));"); diff --git a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java index 1c865e36..0e3bee55 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java @@ -69,13 +69,13 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { String val_iterator = mainblock.hasGlobal(mIterator.getWord()) ? ("g_" + mIterator) : ("u_" + mIterator); // Container - writer.addCode("final var " + ar + " = "); + writer.addCode("final var " + ar + " = ops("); if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { mArray.writeJavaCode(mainblock, writer); } else { writer.compileLoad(mainblock, mArray); } - writer.addCode(";"); + writer.addCode(", " + mArray.getOperations() + ");"); StringBuilder sb = new StringBuilder(); sb.append("if (isIterable(").append(ar).append(")) {"); diff --git a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java index 15cc3bbe..1319371a 100644 --- a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java @@ -102,19 +102,25 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { if (declaration.isCaptured()) { sb.append("final var u_").append(parameter).append(" = new Wrapper("); if (mReferences.get(i)) { - sb.append("(p_").append(parameter).append(" instanceof Box) ? (Box) p_").append(parameter).append(" : "); + sb.append("(p_").append(parameter).append(" instanceof Box) ? (Box) p_").append(parameter).append(" : new Box(" + writer.getAIThis() + ", ").append("p_").append(parameter).append("));"); + } else { + sb.append("new Box(").append(writer.getAIThis()).append(", copy(p_").append(parameter).append(")));"); } - sb.append("new Box(" + writer.getAIThis() + ", "); - sb.append("copy(p_").append(parameter).append(")));"); } else { sb.append("var u_").append(parameter).append(" = "); if (mReferences.get(i)) { - sb.append("(p_").append(parameter).append(" instanceof Box) ? (Box) p_").append(parameter).append(" : "); - } - if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10) { - sb.append("new Box(" + writer.getAIThis() + ", copy(p_").append(parameter).append("));"); + sb.append("(p_").append(parameter).append(" instanceof Box) ? (Box) p_").append(parameter).append(" : new Box(" + writer.getAIThis()); + if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10) { + sb.append(", p_").append(parameter).append(");"); + } else { + sb.append(", copy(p_").append(parameter).append("));"); + } } else { - sb.append("p_").append(parameter).append("; ops(1); "); + if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10) { + sb.append("new Box(" + writer.getAIThis() + ", copy(p_").append(parameter).append("));"); + } else { + sb.append("p_").append(parameter).append("; ops(1); "); + } } } } diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index 811232fb..f826bbce 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -97,7 +97,7 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { assert (object.isLeftValue() && !object.nullable()); writer.addCode("getField("); - object.compileL(mainblock, writer); + object.writeJavaCode(mainblock, writer); writer.addCode(", \"" + field.getWord() + "\")"); } @@ -106,7 +106,7 @@ public void compileSet(MainLeekBlock mainblock, JavaWriter writer, AbstractExpre assert (object.isLeftValue() && !object.nullable()); writer.addCode("setField("); - object.compileL(mainblock, writer); + object.writeJavaCode(mainblock, writer); writer.addCode(", \"" + field.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); @@ -116,8 +116,36 @@ public void compileSet(MainLeekBlock mainblock, JavaWriter writer, AbstractExpre public void compileIncrement(MainLeekBlock mainblock, JavaWriter writer) { assert (object.isLeftValue() && !object.nullable()); - object.compileL(mainblock, writer); - writer.addCode(".getFieldL(\"" + field.getWord() + "\").increment()"); + writer.addCode("field_inc("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\")"); + } + + @Override + public void compilePreIncrement(MainLeekBlock mainblock, JavaWriter writer) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_pre_inc("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\")"); + } + + @Override + public void compileDecrement(MainLeekBlock mainblock, JavaWriter writer) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_dec("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\")"); + } + + @Override + public void compilePreDecrement(MainLeekBlock mainblock, JavaWriter writer) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_pre_dec("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\")"); } @Override @@ -125,7 +153,7 @@ public void compileAddEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_add_eq("); - object.compileL(mainblock, writer); + object.writeJavaCode(mainblock, writer); writer.addCode(", \"" + field.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); @@ -137,7 +165,7 @@ public void compileSubEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp assert (object.isLeftValue() && !object.nullable()); writer.addCode("field_sub_eq("); - object.compileL(mainblock, writer); + object.writeJavaCode(mainblock, writer); writer.addCode(", \"" + field.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index 0feaaa18..c837a305 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -266,6 +266,10 @@ public void compileSet(MainLeekBlock mainblock, JavaWriter writer, AbstractExpre writer.addCode("u_class.setField(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); + } else if (mainblock.isRedefinedFunction(token.getWord())) { + writer.addCode("rfunction_" + token.getWord() + ".set("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); } else if (type == VariableType.GLOBAL) { if (mainblock.getWordCompiler().getVersion() >= 11) { writer.addCode("g_" + token.getWord() + " = "); @@ -296,7 +300,7 @@ public void compileSet(MainLeekBlock mainblock, JavaWriter writer, AbstractExpre // expr.compileL(mainblock, writer); // } else { writer.addCode("u_" + token.getWord() + ".set("); - expr.compileL(mainblock, writer); + expr.writeJavaCode(mainblock, writer); writer.addCode(")"); // } } else { @@ -328,7 +332,7 @@ public void compileSetCopy(MainLeekBlock mainblock, JavaWriter writer, AbstractE } else { writer.addCode("g_" + token.getWord() + ".set("); // writer.compileClone(mainblock, expr); - expr.writeJavaCode(mainblock, writer); + expr.compileL(mainblock, writer); writer.addCode(")"); } } else { diff --git a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java index 17379311..90460c32 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java @@ -52,7 +52,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { else writer.addCode("null"); } else { writer.addCode("g_" + token.getWord() + " = new Box(" + writer.getAIThis() + ", "); - if (mValue != null) mValue.writeJavaCode(mainblock, writer); + if (mValue != null) mValue.compileL(mainblock, writer); else writer.addCode("null"); writer.addCode(", " + (mValue != null ? mValue.getOperations() : 0) + ")"); } diff --git a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java index f6eb5048..ea55ad5c 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java @@ -33,16 +33,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } else { if (mExpression.getOperations() > 0) writer.addCode("ops("); var finalExpression = mExpression.trim(); - boolean isRef = finalExpression instanceof LeekExpression && ((LeekExpression) finalExpression).getOperator() == Operators.REFERENCE; - if (mainblock.getWordCompiler().getVersion() == 10) { - if (isRef || !finalExpression.isLeftValue()) { - finalExpression.writeJavaCode(mainblock, writer); - } else { - finalExpression.compileL(mainblock, writer); - } - } else { - finalExpression.compileL(mainblock, writer); - } + finalExpression.compileL(mainblock, writer); if (finalExpression.getOperations() > 0) writer.addCode(", " + finalExpression.getOperations() + ")"); writer.addLine(";", mLine, mAI); } diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index 6a90fda3..d9f2fb91 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -82,7 +82,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine(";", mLine, mAI); } else { writer.addCode("final var u_" + token.getWord() + " = new Wrapper(new Box(" + writer.getAIThis() + ", "); - if (mValue != null) mValue.writeJavaCode(mainblock, writer); + if (mValue != null) mValue.compileL(mainblock, writer); else writer.addCode("null"); writer.addLine(")"); if (mValue != null && mValue.getOperations() > 0) { diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 7451eed9..f0bd56ca 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -14,6 +14,7 @@ import leekscript.common.Error; import java.util.Comparator; +import java.util.HashSet; import java.util.Set; import com.alibaba.fastjson.JSON; @@ -337,13 +338,13 @@ public int count(ArrayLeekValue array) throws LeekRunException { return array.size(); } - public int count(Object... args) throws LeekRunException { + public Object count(Object... args) throws LeekRunException { if (check("count", new int[] { ARRAY }, args)) { ops(LeekFunctions.count.getOperations()); var array = (ArrayLeekValue) args[0]; return array.size(); } - return 0; + return null; } public Object debug(Object x) throws LeekRunException { @@ -572,6 +573,7 @@ public String jsonEncode(AI ai, Object object) { } catch (Exception e) { + // e.printStackTrace(); getLogs().addLog(AILog.ERROR, "Cannot encode object \"" + object.toString() + "\""); try { ops(100); @@ -672,29 +674,52 @@ public boolean eq(Object x, Object y) throws LeekRunException { if (y instanceof ArrayLeekValue) { return ((ArrayLeekValue) y).equals(this, (Number) x); } + if (y == null) return false; return n == getDouble(y); } - if (y instanceof Number) { - return getDouble(x) == ((Number) y).doubleValue(); - } if (x instanceof Boolean) { if (y instanceof String) { - if (((String) y).equals("true")) return ((Boolean) x) == true; - if (((String) y).equals("false")) return ((Boolean) x) == false; - return false; + if (((String) y).equals("false") || ((String) y).equals("0") || ((String) y).length() == 0) return ((Boolean) x) == false; + return ((Boolean) x) == true; } if (y instanceof ArrayLeekValue) { return ((ArrayLeekValue) y).equals(this, (Boolean) x); } + if (y instanceof Number) { + return (Boolean) x == (((Number) y).doubleValue() != 0); + } } if (x instanceof ArrayLeekValue) { + var array = (ArrayLeekValue) x; + if (y instanceof String) { + if (((String) y).length() == 0) return array.size() == 0 || eq(array.iterator().next().getValue(), y); + } return ((ArrayLeekValue) x).equals(this, y); } if (x instanceof FunctionLeekValue) { return ((FunctionLeekValue) x).equals(this, y); } - if (x instanceof String && y instanceof String) { - ops(Math.min(((String) x).length(), ((String) y).length())); + if (x instanceof String) { + var s = (String) x; + if (y instanceof String) { + ops(Math.min(s.length(), ((String) y).length())); + return x.equals(y); + } + if (y instanceof Number) { + if (s.equals("true")) return ((Number) y).doubleValue() != 0; + if (s.equals("false")) return ((Number) y).doubleValue() == 0; + return getDouble(x) == ((Number) y).doubleValue(); + } + if (y instanceof Boolean) { + if (s.equals("false") || s.equals("0") || s.length() == 0) return ((Boolean) y) == false; + return ((Boolean) y) == true; + } + if (y instanceof ArrayLeekValue) { + var array = (ArrayLeekValue) y; + if (array.size() == 0) return s.length() == 0 || s.equals("false"); + if (array.size() == 1 || s.equals("true")) return eq(((ArrayLeekValue) y).iterator().next().getValue(), x); + return false; + } } return x.equals(y); } @@ -869,6 +894,16 @@ public Object add(Object v1, Object v2) throws LeekRunException { if (v2 == null) return v1; } + if (v1 instanceof Boolean) { + if (v2 instanceof Integer) { + return (((Boolean) v1) ? 1 : 0) + (Integer) v2; + } + if (v2 instanceof Number) { + return (((Boolean) v1) ? 1 : 0) + ((Number) v2).doubleValue(); + } + if (v2 == null) return ((Boolean) v1) ? 1 : 0; + } + // Concatenate arrays if (v1 instanceof ArrayLeekValue && v2 instanceof ArrayLeekValue) { @@ -904,6 +939,9 @@ public Object add(Object v1, Object v2) throws LeekRunException { if (v2 instanceof Number) { return v2; } + if (v2 instanceof Boolean) { + return ((Boolean) v2) ? 1 : 0; + } if (v2 == null) return 0; } @@ -1107,15 +1145,23 @@ public String string(Object value) throws LeekRunException { public String getString(Object value, Set visited) throws LeekRunException { return LeekValueManager.getString(this, value, visited); } - public String toJSON(Object value) { - return LeekValueManager.toJSON(this, value); + + public Object toJSON(Object v) throws LeekRunException { + if (v instanceof ArrayLeekValue) { + return ((ArrayLeekValue) v).toJSON(this, new HashSet()); + } + return v; } public boolean isPrimitive(Object value) { return !(value instanceof ArrayLeekValue || value instanceof ObjectLeekValue); } - public boolean isIterable(Object value) { - return value instanceof ArrayLeekValue; + public boolean isIterable(Object value) throws LeekRunException { + boolean ok = value instanceof ArrayLeekValue; + if (!ok) { + addSystemLog(AILog.ERROR, Error.NOT_ITERABLE, new String[] { string(value) }); + } + return ok; } public boolean getBooleanTernary(Object value) throws LeekRunException { ops(1); @@ -1152,6 +1198,36 @@ public Object field_inc(Object object, String field) throws LeekRunException { throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } + public Object field_pre_inc(Object object, String field) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_pre_inc(field); + } + if (object instanceof ClassLeekValue) { + // return ((ClassLeekValue) object).field_add_eq(field, value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_dec(Object object, String field) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_dec(field); + } + if (object instanceof ClassLeekValue) { + // return ((ClassLeekValue) object).field_add_eq(field, value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_pre_dec(Object object, String field) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_pre_dec(field); + } + if (object instanceof ClassLeekValue) { + // return ((ClassLeekValue) object).field_add_eq(field, value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + public Object field_add_eq(Object object, String field, Object value) throws LeekRunException { if (object instanceof ObjectLeekValue) { return ((ObjectLeekValue) object).field_add_eq(field, value); @@ -1353,7 +1429,6 @@ public Box getBox(Object value, Object index) throws LeekRunException { if (value instanceof ArrayLeekValue) { return ((ArrayLeekValue) value).getBox(this, index); } - // return new Box(this, null); return null; } diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 8c4403cc..cf3b290d 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -13,10 +13,19 @@ public enum LeekFunctions implements ILeekFunction { // Fonctions mathématiques - abs(new CallableVersion[] { - new CallableVersion(Type.INT, new Type[] { Type.INT }), - new CallableVersion(Type.REAL, new Type[] { Type.REAL }) - }), + // abs(new CallableVersion[] { + // new CallableVersion(Type.INT, new Type[] { Type.INT }), + // new CallableVersion(Type.REAL, new Type[] { Type.REAL }) + // }), + abs(1, new int[] { AI.NUMBER }) { + @Override + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + if (parameters[0] instanceof Integer) { + return Math.abs((Integer) parameters[0]); + } + return Math.abs(LeekValueManager.getDouble(ai, parameters[0])); + } + }, min(2, new int[] { AI.NUMBER, AI.NUMBER }) { @Override @@ -46,9 +55,16 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le } }, - cos(new CallableVersion[] { - new CallableVersion(Type.REAL, new Type[] { Type.REAL }) - }), + // cos(new CallableVersion[] { + // new CallableVersion(Type.REAL, new Type[] { Type.REAL }) + // }), + cos(1, new int[] { AI.NUMBER }) { + @Override + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return Math.cos(v); + } + }, sin(1, new int[] { AI.NUMBER }) { @Override @@ -79,17 +95,38 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le } }, - acos(new CallableVersion[] { - new CallableVersion(Type.REAL, new Type[] { Type.REAL }) - }), + // acos(new CallableVersion[] { + // new CallableVersion(Type.REAL, new Type[] { Type.REAL }) + // }), + acos(1, new int[] { AI.NUMBER }) { + @Override + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return Math.acos(v); + } + }, - asin(new CallableVersion[] { - new CallableVersion(Type.REAL, new Type[] { Type.REAL }) - }), + // asin(new CallableVersion[] { + // new CallableVersion(Type.REAL, new Type[] { Type.REAL }) + // }), + asin(1, new int[] { AI.NUMBER }) { + @Override + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return Math.asin(v); + } + }, - atan(new CallableVersion[] { - new CallableVersion(Type.REAL, new Type[] { Type.REAL }) - }), + // atan(new CallableVersion[] { + // new CallableVersion(Type.REAL, new Type[] { Type.REAL }) + // }), + atan(1, new int[] { AI.NUMBER }) { + @Override + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return Math.atan(v); + } + }, atan2(2, new int[] { AI.NUMBER, AI.NUMBER }) { @Override @@ -100,20 +137,41 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le } }, - ceil(new CallableVersion[] { - new CallableVersion(Type.INT, new Type[] { Type.INT }), - new CallableVersion(Type.INT, new Type[] { Type.REAL }), - }), + // ceil(new CallableVersion[] { + // new CallableVersion(Type.INT, new Type[] { Type.INT }), + // new CallableVersion(Type.INT, new Type[] { Type.REAL }), + // }), + ceil(1, new int[] { AI.NUMBER }) { + @Override + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return (int) Math.ceil(v); + } + }, - floor(new CallableVersion[] { - new CallableVersion(Type.INT, new Type[] { Type.INT }), - new CallableVersion(Type.INT, new Type[] { Type.REAL }), - }), + // floor(new CallableVersion[] { + // new CallableVersion(Type.INT, new Type[] { Type.INT }), + // new CallableVersion(Type.INT, new Type[] { Type.REAL }), + // }), + floor(1, new int[] { AI.NUMBER }) { + @Override + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return (int) Math.floor(v); + } + }, - round(new CallableVersion[] { - new CallableVersion(Type.INT, new Type[] { Type.INT }), - new CallableVersion(Type.INT, new Type[] { Type.REAL }), - }), + // round(new CallableVersion[] { + // new CallableVersion(Type.INT, new Type[] { Type.INT }), + // new CallableVersion(Type.INT, new Type[] { Type.REAL }), + // }), + round(1, new int[] { AI.NUMBER }) { + @Override + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + double v = LeekValueManager.getDouble(ai, parameters[0]); + return (int) Math.round(v); + } + }, sqrt(1, new int[] { AI.NUMBER }) { @Override @@ -440,7 +498,14 @@ public void addOperations(AI ai, ILeekFunction function, Object parameters[], Ob } }, - count(new CallableVersion[] { new CallableVersion(Type.INT, new Type[] { Type.ARRAY }) }), + // count(new CallableVersion[] { new CallableVersion(Type.ANY, new Type[] { Type.ARRAY }) }), + count(1, new int[] { AI.ARRAY }) { + @Override + public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + return array.size(); + } + }, join(2, new int[] { AI.ARRAY, AI.STRING }) { @Override @@ -642,20 +707,21 @@ public void addOperations(AI ai, ILeekFunction function, Object parameters[], Ob }, arrayMin(1, new int[] { AI.ARRAY }) { @Override - public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { var array = (ArrayLeekValue) parameters[0]; - Object max_c = null; - LeekValueComparator.SortComparator comp = new LeekValueComparator.SortComparator(leekIA, LeekValueComparator.SortComparator.SORT_ASC); - for (var val : array) { - if (max_c == null) - max_c = val.getValue(); - else if (comp.compare(LeekValueManager.getValue(val), max_c) == -1) - max_c = val.getValue(); + if (array.size() > 0) { + var comp = new LeekValueComparator.SortComparator(ai, LeekValueComparator.SortComparator.SORT_ASC); + var iterator = array.iterator(); + Object min_c = iterator.next().getValue(); + while (iterator.hasNext()) { + var value = iterator.next().getValue(); + if (comp.compare(value, min_c) == -1) { + min_c = value; + } + } + return LeekOperations.clone(ai, min_c); } - if (max_c == null) - return null; - else - return LeekOperations.clone(leekIA, max_c); + return null; } }, arrayMax(1, new int[] { AI.ARRAY }) { @@ -663,11 +729,11 @@ else if (comp.compare(LeekValueManager.getValue(val), max_c) == -1) public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { var array = (ArrayLeekValue) parameters[0]; Object min_c = null; - LeekValueComparator.SortComparator mincomp = new LeekValueComparator.SortComparator(leekIA, LeekValueComparator.SortComparator.SORT_ASC); + var mincomp = new LeekValueComparator.SortComparator(leekIA, LeekValueComparator.SortComparator.SORT_ASC); for (var val : array) { if (min_c == null) min_c = val.getValue(); - else if (mincomp.compare(LeekValueManager.getValue(val), min_c) == 1) + else if (mincomp.compare(val.getValue(), min_c) == 1) min_c = val.getValue(); } if (min_c == null) @@ -869,9 +935,36 @@ public Object run(AI leekIA, ILeekFunction function, Object... parameters) throw } }, - debug(new CallableVersion[] { new CallableVersion(Type.NULL, new Type[] { Type.ANY }) }), - debugW(new CallableVersion[] { new CallableVersion(Type.NULL, new Type[] { Type.ANY }) }), - debugE(new CallableVersion[] { new CallableVersion(Type.NULL, new Type[] { Type.ANY }) }), + // debug(new CallableVersion[] { new CallableVersion(Type.NULL, new Type[] { Type.ANY }) }), + // debugW(new CallableVersion[] { new CallableVersion(Type.NULL, new Type[] { Type.ANY }) }), + // debugE(new CallableVersion[] { new CallableVersion(Type.NULL, new Type[] { Type.ANY }) }), + debug(1) { + @Override + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + String message = LeekValueManager.getString(ai, parameters[0]); + ai.getLogs().addLog(AILog.STANDARD, message); + ai.ops(message.length()); + return null; + } + }, + debugW(1) { + @Override + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + String message = LeekValueManager.getString(ai, parameters[0]); + ai.getLogs().addLog(AILog.WARNING, message); + ai.ops(message.length()); + return null; + } + }, + debugE(1) { + @Override + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + String message = LeekValueManager.getString(ai, parameters[0]); + ai.getLogs().addLog(AILog.ERROR, message); + ai.ops(message.length()); + return null; + } + }, debugC(2) { @Override @@ -947,7 +1040,13 @@ public Object run(AI leekIA, ILeekFunction function, Object... parameters) throw } }, - getOperations(new CallableVersion[] { new CallableVersion(Type.INT, new Type[0]) }), + // getOperations(new CallableVersion[] { new CallableVersion(Type.INT, new Type[0]) }), + getOperations(0) { + @Override + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + return ai.getOperations(); + } + }, clone(1, 2) { @Override @@ -998,6 +1097,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le this.versions = versions; this.direct = true; // this.parameters = new int[0]; + mArguments = this.versions[0].arguments.length; } LeekFunctions(Type return_type, CallableVersion[] versions, int[] parameters) { diff --git a/src/main/java/leekscript/runner/LeekRunException.java b/src/main/java/leekscript/runner/LeekRunException.java index fe098fda..f33e4562 100644 --- a/src/main/java/leekscript/runner/LeekRunException.java +++ b/src/main/java/leekscript/runner/LeekRunException.java @@ -44,7 +44,8 @@ public String getMessage() { return "Erreur d'exécution : Niveau invalide"; case OUT_OF_MEMORY: return "Erreur d'exécution : Trop de RAM utilisée"; - + case UNKNOWN_FIELD: + return "Erreur d'exécution : Champ inconnu"; } return "Erreur d'exécution"; } diff --git a/src/main/java/leekscript/runner/LeekValueComparator.java b/src/main/java/leekscript/runner/LeekValueComparator.java index 916247a4..b80f88c3 100644 --- a/src/main/java/leekscript/runner/LeekValueComparator.java +++ b/src/main/java/leekscript/runner/LeekValueComparator.java @@ -33,7 +33,11 @@ else if (mOrder == SORT_DESC) } public int compareAsc(Object v1, Object v2) throws LeekRunException { - if (v1 instanceof Boolean) { + if (v1 == null) { + if (v2 == null) return 0; + return -1; + } else if (v1 instanceof Boolean) { + if (v2 == null) return 1; if (v2 instanceof Boolean) { if ((Boolean) v1 == (Boolean) v2) return 0; @@ -51,14 +55,14 @@ else if (((Number) v1).doubleValue() < ((Number) v2).doubleValue()) return -1; else return 1; - } else if (v2 instanceof Boolean) + } else if (v2 instanceof Boolean || v2 == null) return 1; else return -1; } else if (v1 instanceof String) { if (v2 instanceof String) { return ((String) v1).compareTo((String) v2); - } else if (v2 instanceof Number || v2 instanceof Boolean) + } else if (v2 instanceof Number || v2 instanceof Boolean || v2 == null) return 1; else return -1; @@ -74,8 +78,9 @@ else if (((ArrayLeekValue) v1).size() < ((ArrayLeekValue) v2).size()) return -1; else return 1; - } else + } else { return -1; + } } } } diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 9fc88dcc..e0866f40 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -350,7 +350,7 @@ public Object get(AI ai, Object key) throws LeekRunException { public Box getBox(AI ai, Object key) throws LeekRunException { Element e = getElement(ai, key); - return e == null ? null : e.value; + return e == null ? new Box(ai) : e.value; } /** diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index deed811d..f7fdd976 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -1,6 +1,7 @@ package leekscript.runner.values; import java.util.Comparator; +import java.util.HashSet; import java.util.Iterator; import java.util.Set; @@ -10,6 +11,7 @@ import leekscript.runner.LeekValueManager; import leekscript.runner.PhpArray; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -348,20 +350,36 @@ public void sort(AI ai, Comparator comparator) throws LeekRunE mValues.sort(ai, comparator); } - public Object toJSON(AI ai) throws LeekRunException { + public JSON toJSON(AI ai) throws LeekRunException { + return toJSON(ai, new HashSet<>()); + } + + public JSON toJSON(AI ai, HashSet visited) throws LeekRunException { + visited.add(this); if (mValues.isAssociative()) { JSONObject o = new JSONObject(); ArrayIterator i = getArrayIterator(); while (!i.ended()) { - o.put(i.key().toString(), ai.toJSON(i.getValue(ai))); + var v = i.getValue(ai); + if (!visited.contains(v)) { + if (!ai.isPrimitive(v)) { + visited.add(v); + } + o.put(i.key().toString(), ai.toJSON(v)); + } i.next(); } return o; } else { JSONArray a = new JSONArray(); - for (Object v : this) { - a.add(ai.toJSON(v)); + for (var v : this) { + if (!visited.contains(v)) { + if (!ai.isPrimitive(v)) { + visited.add(v); + } + a.add(ai.toJSON(v.getValue())); + } } return a; } diff --git a/src/main/java/leekscript/runner/values/Box.java b/src/main/java/leekscript/runner/values/Box.java index 3584072d..6d363fc4 100644 --- a/src/main/java/leekscript/runner/values/Box.java +++ b/src/main/java/leekscript/runner/values/Box.java @@ -152,7 +152,8 @@ public Object sub_eq(Object val) throws LeekRunException { if (mValue instanceof Number) { return mValue = mUAI.sub(mValue, val); } - return mValue = mUAI.sub_eq(mValue, val); + throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + // return mValue = mUAI.sub_eq(mValue, val); } public Object mul_eq(Object val) throws LeekRunException { diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 22e47ab3..fa449bb7 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -99,6 +99,30 @@ public Object field_inc(String field) throws LeekRunException { throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } + public Object field_pre_inc(String field) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.pre_increment(); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_dec(String field) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.decrement(); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_pre_dec(String field) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.pre_decrement(); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + public Object field_add_eq(String field, Object value) throws LeekRunException { var result = fields.get(field); if (result != null) { From 74062b67e805c38d58693e048f52c5ccb92a9c8c Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 27 Jun 2021 19:38:40 +0200 Subject: [PATCH 252/319] [operators] Improve operators --- src/main/java/leekscript/runner/AI.java | 282 +++++++++--------- .../java/leekscript/runner/LeekFunctions.java | 56 ++-- .../leekscript/runner/LeekValueManager.java | 29 -- .../java/leekscript/runner/values/Box.java | 43 +-- 4 files changed, 177 insertions(+), 233 deletions(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index f0bd56ca..e764f87e 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -668,14 +668,31 @@ public boolean eq(Object x, Object y) throws LeekRunException { return n == 0; } if (y instanceof String) { - if (((String) y).equals("true")) return n != 0; - if (((String) y).equals("false")) return n == 0; + var s = (String) y; + if (s.equals("false") || s.equals("0") || s.equals("")) return n == 0; + if (s.equals("true")) return n != 0; + if (s.equals("1") && n == 1) return true; + if (x instanceof Double) { + try { + ops(((String) y).length()); + return n == Double.parseDouble((String) y); + } catch (Exception e) { + return false; + } + } else { + try { + ops(((String) y).length()); + return n == Integer.parseInt((String) y); + } catch (Exception e) { + return false; + } + } } if (y instanceof ArrayLeekValue) { return ((ArrayLeekValue) y).equals(this, (Number) x); } if (y == null) return false; - return n == getDouble(y); + return n == real(y); } if (x instanceof Boolean) { if (y instanceof String) { @@ -706,9 +723,16 @@ public boolean eq(Object x, Object y) throws LeekRunException { return x.equals(y); } if (y instanceof Number) { - if (s.equals("true")) return ((Number) y).doubleValue() != 0; - if (s.equals("false")) return ((Number) y).doubleValue() == 0; - return getDouble(x) == ((Number) y).doubleValue(); + var n = ((Number) y).doubleValue(); + if (s.equals("true")) return n != 0; + if (s.equals("false") || s.equals("0") || s.length() == 0) return n == 0; + if (s.equals("1") && n == 1) return true; + try { + ops(s.length()); + return n == Double.parseDouble(s); + } catch (Exception e) { + return false; + } } if (y instanceof Boolean) { if (s.equals("false") || s.equals("0") || s.length() == 0) return ((Boolean) y) == false; @@ -816,8 +840,8 @@ public int integer(Object value) throws LeekRunException { return ((Boolean) value) ? 1 : 0; } else if (value instanceof ObjectLeekValue) { return ((ObjectLeekValue) value).size(); - // } else if (value instanceof ArrayLeekValue) { - // return ((ArrayLeekValue) value).size(); + } else if (value instanceof ArrayLeekValue) { + return ((ArrayLeekValue) value).size(); } else if (value instanceof String) { var s = (String) value; // ops(2); @@ -828,7 +852,7 @@ public int integer(Object value) throws LeekRunException { try { return Integer.parseInt(s); } catch (Exception e) { - return 1; + return s.length(); } } else if (value instanceof Box) { return integer(((Box) value).getValue()); @@ -836,8 +860,33 @@ public int integer(Object value) throws LeekRunException { return 0; } - public double getDouble(Object value) throws LeekRunException { - return LeekValueManager.getDouble(this, value); + public double real(Object value) throws LeekRunException { + if (value instanceof Double) { + return (Double) value; + } else if (value instanceof Integer) { + return (Integer) value; + } else if (value instanceof Boolean) { + return ((Boolean) value) ? 1 : 0; + } else if (value instanceof ObjectLeekValue) { + return ((ObjectLeekValue) value).size(); + } else if (value instanceof ArrayLeekValue) { + return ((ArrayLeekValue) value).size(); + } else if (value instanceof String) { + var s = (String) value; + // ai.ops(2); + if (s.equals("true")) return 1; + if (s.equals("false")) return 0; + if (s.isEmpty()) return 0; + ops(s.length()); + try { + return Double.parseDouble(s); + } catch (Exception e) { + return s.length(); + } + } else if (value instanceof Box) { + return real(((Box) value).getValue()); + } + return 0; } public boolean not(Object value) throws LeekRunException { @@ -878,39 +927,50 @@ public int ushr(Object x, Object y) throws LeekRunException { return integer(x) >>> integer(y); } - public Object add(Object v1, Object v2) throws LeekRunException { - if (v1 instanceof Number) { - if (v2 instanceof Number) { - if (v1 instanceof Double) return (Double) v1 + ((Number) v2).doubleValue(); - if (v2 instanceof Double) return (Double) v2 + ((Number) v1).doubleValue(); - return ((Number) v1).intValue() + ((Number) v2).intValue(); - } - if (v2 instanceof Boolean) { - if (v1 instanceof Integer) { - return ((Integer) v1) + (((Boolean) v2) ? 1 : 0); - } - return ((Number) v1).doubleValue() + (((Boolean) v2) ? 1 : 0); - } - if (v2 == null) return v1; - } + public Object add(Object x, Object y) throws LeekRunException { - if (v1 instanceof Boolean) { - if (v2 instanceof Integer) { - return (((Boolean) v1) ? 1 : 0) + (Integer) v2; - } - if (v2 instanceof Number) { - return (((Boolean) v1) ? 1 : 0) + ((Number) v2).doubleValue(); - } - if (v2 == null) return ((Boolean) v1) ? 1 : 0; + if (x instanceof String || y instanceof String) { + String v1_string = LeekValueManager.getString(this, x); + String v2_string = LeekValueManager.getString(this, y); + ops(v1_string.length() + v2_string.length()); + return v1_string + v2_string; } + // Concatenate arrays - if (v1 instanceof ArrayLeekValue && v2 instanceof ArrayLeekValue) { + if (x instanceof ArrayLeekValue) { + if (y instanceof ArrayLeekValue) { + var array1 = (ArrayLeekValue) x; + var array2 = (ArrayLeekValue) y; - var array1 = (ArrayLeekValue) v1; - var array2 = (ArrayLeekValue) v2; + ops((array1.size() + array2.size()) * 2); - ops((array1.size() + array2.size()) * 2); + ArrayLeekValue retour = new ArrayLeekValue(); + ArrayIterator iterator = array1.getArrayIterator(); + + while (!iterator.ended()) { + if (iterator.key() instanceof String) { + retour.getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); + } else { + retour.push(this, iterator.getValue(this)); + } + iterator.next(); + } + iterator = array2.getArrayIterator(); + while (!iterator.ended()) { + if (iterator.key() instanceof String) { + retour.getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); + } else { + retour.push(this, iterator.getValue(this)); + } + iterator.next(); + } + return retour; + } + + var array1 = (ArrayLeekValue) x; + + ops(array1.size() * 2); ArrayLeekValue retour = new ArrayLeekValue(); ArrayIterator iterator = array1.getArrayIterator(); @@ -923,7 +983,21 @@ public Object add(Object v1, Object v2) throws LeekRunException { } iterator.next(); } - iterator = array2.getArrayIterator(); + retour.push(this, y); + + return retour; + } + + if (y instanceof ArrayLeekValue) { + var array2 = (ArrayLeekValue) y; + + ops(array2.size() * 2); + + ArrayLeekValue retour = new ArrayLeekValue(); + + retour.push(this, x); + + ArrayIterator iterator = array2.getArrayIterator(); while (!iterator.ended()) { if (iterator.key() instanceof String) { retour.getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); @@ -935,135 +1009,53 @@ public Object add(Object v1, Object v2) throws LeekRunException { return retour; } - if (v1 == null) { - if (v2 instanceof Number) { - return v2; - } - if (v2 instanceof Boolean) { - return ((Boolean) v2) ? 1 : 0; - } - if (v2 == null) return 0; + if (x instanceof Double || y instanceof Double) { + return real(x) + real(y); } - String v1_string = LeekValueManager.getString(this, v1); - String v2_string = LeekValueManager.getString(this, v2); - ops(v1_string.length() + v2_string.length()); - return v1_string + v2_string; + return integer(x) + integer(y); } - public Object sub(Object v1, Object v2) throws LeekRunException { - if (v1 instanceof Number) { - if (v2 instanceof Number) { - if (v1 instanceof Double) return (Double) v1 - ((Number) v2).doubleValue(); - if (v2 instanceof Double) return ((Number) v1).doubleValue() - (Double) v2; - return ((Number) v1).intValue() - ((Number) v2).intValue(); - } - if (v1 instanceof Integer) { - return ((Integer) v1).intValue() - integer(v2); - } - if (v2 == null) return v1; - return ((Number) v1).doubleValue() - integer(v2); - } - if (v1 == null) { - if (v2 instanceof Integer) return -(Integer) v2; - if (v2 instanceof Double) return -(Double) v2; - if (v2 == null) return 0; + public Object sub(Object x, Object y) throws LeekRunException { + if (x instanceof Double || y instanceof Double) { + return real(x) - real(y); } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + return integer(x) - integer(y); } - public Object mul(Object v1, Object v2) throws LeekRunException { - if (v1 instanceof Number) { - if (v2 instanceof Number) { - if (v1 instanceof Double || v2 instanceof Double) { - return ((Number) v1).doubleValue() * ((Number) v2).doubleValue(); - } else { - return ((Number) v1).intValue() * ((Number) v2).intValue(); - } - } - if (v2 instanceof Boolean) { - if (v1 instanceof Integer) { - return ((Integer) v1) * (((Boolean) v2) ? 1 : 0); - } - return ((Number) v1).doubleValue() * (((Boolean) v2) ? 1 : 0); - } - if (v2 == null) { - return 0; - } + public Object mul(Object x, Object y) throws LeekRunException { + if (x instanceof Double || y instanceof Double) { + return real(x) * real(y); } - if (v1 == null) return 0; - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + return integer(x) * integer(y); } public Object div(Object x, Object y) throws LeekRunException { - if (x == null) return 0.0; - if (y == null) { + double real_y = real(y); + if (version == 10 && real_y == 0) { addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); return null; } - if (x instanceof Number) { - if (y instanceof Number) { - if (((Number) y).doubleValue() == 0) { - addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); - return null; - } - return ((Number) x).doubleValue() / ((Number) y).doubleValue(); - } - if (y instanceof Boolean) { - if ((Boolean) y) return ((Number) x).doubleValue(); - addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); - } - } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + return real(x) / real_y; } public Object mod(Object x, Object y) throws LeekRunException { - if (x == null) return 0; - - if (x instanceof Number && y instanceof Number) { - if (((Number) y).doubleValue() == 0) { - addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); - return null; - } - if (x instanceof Integer && y instanceof Integer) { - return ((Integer) x) % ((Integer) y); - } - return ((Number) x).doubleValue() % ((Number) y).doubleValue(); + if (x instanceof Double || y instanceof Double) { + return real(x) % real(y); } - if (x instanceof Boolean) { - if (((Number) y).doubleValue() == 0) { - addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); - return null; - } - if ((Boolean) x) return 1; - return 0; + var y_int = integer(y); + if (version == 10 && y_int == 0) { + addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); + return null; } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + return integer(x) % y_int; } public Number pow(Object x, Object y) throws LeekRunException { - if (x instanceof Number) { - if (y instanceof Number) { - if (x instanceof Integer && y instanceof Integer) { - return (int) Math.pow((Integer) x, (Integer) y); - } - return Math.pow(((Number) x).doubleValue(), ((Number) y).doubleValue()); - } - if (y instanceof Boolean) { - if (((Boolean) y) == true) return (Number) x; - return 1; - } - if (y == null) { - return 1; - } - } - if (x == null) { - if (y == null) { - return 1; - } - return 0; + if (x instanceof Double || y instanceof Double) { + return Math.pow(real(x), real(y)); } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + return (int) Math.pow(integer(x), integer(y)); } public Object add_eq(Object x, Object y) throws LeekRunException { diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index cf3b290d..98899455 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -23,7 +23,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le if (parameters[0] instanceof Integer) { return Math.abs((Integer) parameters[0]); } - return Math.abs(LeekValueManager.getDouble(ai, parameters[0])); + return Math.abs(ai.real(parameters[0])); } }, @@ -61,7 +61,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le cos(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return Math.cos(v); } }, @@ -69,28 +69,28 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le sin(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return Math.sin(v); } }, tan(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return Math.tan(v); } }, toRadians(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return v * Math.PI / 180; } }, toDegrees(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return v * 180 / Math.PI; } }, @@ -101,7 +101,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le acos(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return Math.acos(v); } }, @@ -112,7 +112,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le asin(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return Math.asin(v); } }, @@ -123,7 +123,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le atan(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return Math.atan(v); } }, @@ -131,8 +131,8 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le atan2(2, new int[] { AI.NUMBER, AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double y = LeekValueManager.getDouble(ai, parameters[0]); - double x = LeekValueManager.getDouble(ai, parameters[1]); + double y = ai.real(parameters[0]); + double x = ai.real(parameters[1]); return Math.atan2(y, x); } }, @@ -144,7 +144,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le ceil(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return (int) Math.ceil(v); } }, @@ -156,7 +156,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le floor(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return (int) Math.floor(v); } }, @@ -168,7 +168,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le round(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return (int) Math.round(v); } }, @@ -176,42 +176,42 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le sqrt(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return Math.sqrt(v); } }, cbrt(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return Math.cbrt(v); } }, log(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return Math.log(v); } }, log2(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return Math.log(v) / Math.log(2); } }, log10(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return Math.log10(v); } }, exp(1, new int[] { AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double v = LeekValueManager.getDouble(ai, parameters[0]); + double v = ai.real(parameters[0]); return Math.exp(v); } }, @@ -219,8 +219,8 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le pow(2, new int[] { AI.NUMBER, AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double x = LeekValueManager.getDouble(ai, parameters[0]); - double y = LeekValueManager.getDouble(ai, parameters[1]); + double x = ai.real(parameters[0]); + double y = ai.real(parameters[1]); return Math.pow(x, y); } }, @@ -245,16 +245,16 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le randFloat(2, new int[] { AI.NUMBER, AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double a = LeekValueManager.getDouble(ai, parameters[0]); - double b = LeekValueManager.getDouble(ai, parameters[1]); + double a = ai.real(parameters[0]); + double b = ai.real(parameters[1]); return a + ai.getRandom().getDouble() * (b - a); } }, hypot(2, new int[] { AI.NUMBER, AI.NUMBER }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - double x = LeekValueManager.getDouble(ai, parameters[0]); - double y = LeekValueManager.getDouble(ai, parameters[1]); + double x = ai.real(parameters[0]); + double y = ai.real(parameters[1]); return Math.hypot(x, y); } }, @@ -754,7 +754,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le var array = (ArrayLeekValue) parameters[0]; double somme = 0; for (var val : array) { - somme += LeekValueManager.getDouble(ai, val.getValue()); + somme += ai.real(val.getValue()); } return somme; } @@ -771,7 +771,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le var array = (ArrayLeekValue) parameters[0]; double average = 0; for (var val : array) { - average += LeekValueManager.getDouble(ai, val.getValue()); + average += ai.real(val.getValue()); } if (average == 0) return 0.0; diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index bd6169ad..0e013608 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -84,35 +84,6 @@ public static Object getValue(Object value) { return value; } - public static double getDouble(AI ai, Object value) throws LeekRunException { - if (value instanceof Double) { - return (Double) value; - } else if (value instanceof Integer) { - return (Integer) value; - } else if (value instanceof Boolean) { - return ((Boolean) value) ? 1 : 0; - } else if (value instanceof ObjectLeekValue) { - return ((ObjectLeekValue) value).size(); - } else if (value instanceof ArrayLeekValue) { - return ((ArrayLeekValue) value).size(); - } else if (value instanceof String) { - var s = (String) value; - // ai.ops(2); - if (s.equals("true")) return 1; - if (s.equals("false")) return 0; - if (s.isEmpty()) return 0; - ai.ops(s.length()); - try { - return Double.parseDouble(s); - } catch (Exception e) { - return 1; - } - } else if (value instanceof Box) { - return getDouble(ai, ((Box) value).getValue()); - } - return 0; - } - public static String doubleToString(AI ai, double value) throws LeekRunException { ai.ops(3); if (ai.getVersion() >= 11) { diff --git a/src/main/java/leekscript/runner/values/Box.java b/src/main/java/leekscript/runner/values/Box.java index 6d363fc4..21dfdd92 100644 --- a/src/main/java/leekscript/runner/values/Box.java +++ b/src/main/java/leekscript/runner/values/Box.java @@ -133,37 +133,18 @@ public Object opposite() throws LeekRunException { } public Object add_eq(Object val) throws LeekRunException { - if (mValue == null) { - return mValue = val; + if (mValue instanceof ArrayLeekValue && !(val instanceof String)) { + return mValue = mUAI.add_eq(mValue, val); } - if (mValue instanceof Number) { - return mValue = mUAI.add(mValue, val); - } - if (mValue instanceof String) { - return mValue = mUAI.add(mValue, val); - } - return mValue = mUAI.add_eq(mValue, val); + return mValue = mUAI.add(mValue, val); } public Object sub_eq(Object val) throws LeekRunException { - if (mValue == null) { - return mValue = mUAI.minus(val); - } - if (mValue instanceof Number) { - return mValue = mUAI.sub(mValue, val); - } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - // return mValue = mUAI.sub_eq(mValue, val); + return mValue = mUAI.sub(mValue, val); } public Object mul_eq(Object val) throws LeekRunException { - if (mValue instanceof Number) { - return mValue = mUAI.mul(mValue, val); - } - if (mValue == null) { - return mValue = mUAI.mul(mValue, val); - } - return mValue = mUAI.mul_eq(mValue, val); + return mValue = mUAI.mul(mValue, val); } public Object pow_eq(Object val) throws LeekRunException { @@ -171,7 +152,7 @@ public Object pow_eq(Object val) throws LeekRunException { } public int band_eq(Object val) throws LeekRunException { - return (int) (mValue = LeekOperations.band(mUAI, mValue, val)); + return (int) (mValue = mUAI.band(mValue, val)); } public int bor_eq(Object val) throws LeekRunException { @@ -182,16 +163,16 @@ public int bxor_eq(Object val) throws LeekRunException { return (int) (mValue = mUAI.bxor(mValue, val)); } - public Object shl_eq(Object val) throws LeekRunException { - return mValue = LeekOperations.bleft(mUAI, mValue, val); + public int shl_eq(Object val) throws LeekRunException { + return (int) (mValue = mUAI.shl(mValue, val)); } - public Object shr_eq(Object val) throws LeekRunException { - return mValue = LeekOperations.bright(mUAI, mValue, val); + public int shr_eq(Object val) throws LeekRunException { + return (int) (mValue = mUAI.shr(mValue, val)); } - public Object ushr_eq(Object val) throws LeekRunException { - return mValue = LeekOperations.buright(mUAI, mValue, val); + public int ushr_eq(Object val) throws LeekRunException { + return (int) (mValue = mUAI.ushr(mValue, val)); } public Object div_eq(Object val) throws LeekRunException { From 3b9d6ed45ca7d3a6009f11d07894da5eeafb1380 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 27 Jun 2021 19:38:40 +0200 Subject: [PATCH 253/319] [compiler] Fixes --- src/main/java/leekscript/compiler/bloc/ForeachBlock.java | 2 +- .../compiler/expression/LeekExpressionFunction.java | 3 ++- .../compiler/instruction/LeekExpressionInstruction.java | 2 +- src/main/java/leekscript/runner/AI.java | 2 -- .../java/leekscript/runner/values/ArrayLeekValue.java | 8 ++++---- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java index 929e7dbe..0aba463c 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java @@ -72,7 +72,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } else { writer.addCounter(1); } - writer.addLine("for (var " + var + " : (ArrayLeekValue) " + ar + ") {\n"); + writer.addLine("for (var " + var + " : (ArrayLeekValue) " + ar + ") {"); if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { if (mIsDeclaration && declaration.isCaptured()) { diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index ec63eb1b..9da41201 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -131,7 +131,8 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { addComma = false; } else if (mExpression instanceof LeekVariable && mainblock.isRedefinedFunction(((LeekVariable) mExpression).getName())) { writer.addCode("rfunction_" + ((LeekVariable) mExpression).getName()); - writer.addCode(".execute(this"); + writer.addCode(".execute("); + addComma = false; } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.SYSTEM_FUNCTION) { var variable = (LeekVariable) mExpression; system_function = LeekFunctions.getValue(variable.getName()); diff --git a/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java index 781ae259..dad6262d 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekExpressionInstruction.java @@ -40,7 +40,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { // Simple values are not compiled var trimmed = mExpression.trim(); if (trimmed instanceof LeekExpression && ((LeekExpression) trimmed).getOperator() == Operators.REFERENCE) { - trimmed = ((LeekExpression) trimmed).getExpression1(); + trimmed = ((LeekExpression) trimmed).getExpression2().trim(); } if (trimmed instanceof LeekNull || trimmed instanceof LeekBoolean || trimmed instanceof LeekNumber || trimmed instanceof LeekString || trimmed instanceof LeekVariable || trimmed instanceof LeekObjectAccess || trimmed instanceof LeekTabularValue || trimmed instanceof LeekAnonymousFunction) { return; diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index e764f87e..95087881 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -749,8 +749,6 @@ public boolean eq(Object x, Object y) throws LeekRunException { } public boolean neq(Object x, Object y) throws LeekRunException { - if (x == null) return y != null; - if (y == null) return x != null; return !eq(x, y); } diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index f7fdd976..1e69a3bf 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -300,11 +300,11 @@ public boolean equals(AI ai, Object comp) throws LeekRunException { if (comp instanceof ArrayLeekValue) { return mValues.equals(ai, ((ArrayLeekValue) comp).mValues); } else if (mValues.size() == 1) { // Si y'a un seul élément dans le tableau - // In LS1.0, [null] == null, not in 1.1+ - if (ai.getVersion() >= 11 && comp == null) { - return false; + var firstValue = mValues.getHeadElement().value(); + if (firstValue == null && comp == null) { + return ai.getVersion() == 10; // Bug in 1.0, [null] == null } - return ai.eq(mValues.getHeadElement().value(), comp); + return ai.eq(firstValue, comp); } else if (comp instanceof Boolean) { return ai.bool(comp) == ai.bool(this); } else if (comp instanceof String) { From ceaa1ab1ed6fc20a9b6d5a6e31fad1bc53963b79 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 27 Jun 2021 19:38:40 +0200 Subject: [PATCH 254/319] [object] Fixes and fix operators --- .../expression/LeekExpressionFunction.java | 18 ++-- .../compiler/expression/LeekObjectAccess.java | 91 ++++++++++++++++++- .../compiler/expression/LeekTabularValue.java | 3 + .../ClassDeclarationInstruction.java | 24 +++-- .../instruction/LeekReturnInstruction.java | 2 - .../compiler/resolver/FileSystemResolver.java | 1 - .../compiler/resolver/ResourceResolver.java | 2 - src/main/java/leekscript/runner/AI.java | 91 +++++++++++++++++-- .../leekscript/runner/LeekValueManager.java | 2 +- src/main/java/leekscript/runner/PhpArray.java | 1 - .../java/leekscript/runner/values/Box.java | 4 +- .../runner/values/ClassLeekValue.java | 3 +- .../runner/values/FunctionLeekValue.java | 8 -- .../runner/values/ObjectLeekValue.java | 67 ++++++++++++-- src/test/java/test/TestArray.java | 2 - src/test/java/test/TestCommon.java | 5 +- src/test/java/test/TestLoops.java | 2 - src/test/java/test/TestObject.java | 2 - 18 files changed, 270 insertions(+), 58 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 9da41201..f09ed257 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -85,11 +85,12 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { var object = ((LeekObjectAccess) mExpression).getObject(); var field = ((LeekObjectAccess) mExpression).getField(); if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.SUPER) { - writer.addCode("u_this.callSuperMethod(this, \"" + (field + "_" + mParameters.size() + "\"")); + var from_class = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; + writer.addCode("u_this.callSuperMethod(this, \"" + field + "_" + mParameters.size() + "\", " + from_class); } else if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.CLASS) { // Méthode statique connue var v = (LeekVariable) object; - String methodName = "u_" + v.getClassDeclaration().getName() + "_" + field + "_" + mParameters.size(); + String methodName = "u_" + v.getClassDeclaration().getStaticMethodName(field, mParameters.size()); writer.addCode(methodName + "("); addComma = false; } else if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.THIS) { @@ -99,16 +100,19 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { } else { writer.addCode("callMethod("); object.writeJavaCode(mainblock, writer); - writer.addCode(", \"" + field + "_" + mParameters.size() + "\""); + var from_class = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; + writer.addCode(", \"" + field + "_" + mParameters.size() + "\", " + from_class); } } else if (mExpression instanceof LeekTabularValue) { var object = ((LeekTabularValue) mExpression).getTabular(); if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.SUPER) { writer.addCode("u_this.callSuperMethod(mUAI, u_class, "); ((LeekTabularValue) mExpression).getCase().writeJavaCode(mainblock, writer); - writer.addCode(".getString(mUAI) + \"_" + mParameters.size() + "\""); + writer.addCode(".getString(mUAI) + \"_" + mParameters.size() + "\", "); + var from_class = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; + writer.addCode(from_class); } else { - writer.addCode("LeekValueManager.executeArrayAccess(mUAI, "); + writer.addCode("LeekValueManager.executeArrayAccess(" + writer.getAIThis() + ", "); object.writeJavaCode(mainblock, writer); writer.addCode(", "); ((LeekTabularValue) mExpression).getCase().writeJavaCode(mainblock, writer); @@ -126,7 +130,7 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(methodName + "(u_this"); } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.STATIC_METHOD) { // Méthode statique connue - String methodName = "u_" + mainblock.getWordCompiler().getCurrentClass().getName() + "_" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size(); + String methodName = "u_" + mainblock.getWordCompiler().getCurrentClass().getStaticMethodName(((LeekVariable) mExpression).getName(), mParameters.size()); writer.addCode(methodName + "("); addComma = false; } else if (mExpression instanceof LeekVariable && mainblock.isRedefinedFunction(((LeekVariable) mExpression).getName())) { @@ -277,7 +281,7 @@ public void analyze(WordCompiler compiler) { var staticMethod = clazz.getStaticMethod(oa.getField(), mParameters.size()); if (staticMethod == null) { compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.UNKNOWN_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); - } else if (staticMethod.level == AccessLevel.PRIVATE && clazz != compiler.getCurrentClass()) { + } else if (staticMethod.level == AccessLevel.PRIVATE && compiler.getCurrentClass() != clazz) { compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.PRIVATE_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); } else if (staticMethod.level == AccessLevel.PROTECTED && (compiler.getCurrentClass() == null || !compiler.getCurrentClass().descendsFrom(clazz))) { compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.PROTECTED_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index f826bbce..603f7436 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -89,7 +89,8 @@ public IAWord getFieldToken() { public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("getField("); object.writeJavaCode(mainblock, writer); - writer.addCode(", \"" + field.getWord() + "\")"); + var from_class = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; + writer.addCode(", \"" + field.getWord() + "\", " + from_class + ")"); } @Override @@ -98,7 +99,8 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("getField("); object.writeJavaCode(mainblock, writer); - writer.addCode(", \"" + field.getWord() + "\")"); + var from_class = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; + writer.addCode(", \"" + field.getWord() + "\", " + from_class + ")"); } @Override @@ -183,6 +185,29 @@ public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp writer.addCode(")"); } + @Override + + public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_div_eq("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + + public void compileModEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_mod_eq("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } @Override @@ -195,4 +220,66 @@ public void compileBitOrEq(MainLeekBlock mainblock, JavaWriter writer, AbstractE expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } + + @Override + + public void compileBitAndEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_band_eq("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + + public void compileBitXorEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_bxor_eq("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + + public void compileShiftLeftEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_shl_eq("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + + @Override + + public void compileShiftRightEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_shr_eq("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + + @Override + + public void compileShiftUnsignedRightEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_ushr_eq("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } } diff --git a/src/main/java/leekscript/compiler/expression/LeekTabularValue.java b/src/main/java/leekscript/compiler/expression/LeekTabularValue.java index e0eb7b61..b1b281f6 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTabularValue.java +++ b/src/main/java/leekscript/compiler/expression/LeekTabularValue.java @@ -3,6 +3,7 @@ import leekscript.common.Type; import leekscript.compiler.JavaWriter; import leekscript.compiler.WordCompiler; +import leekscript.compiler.bloc.ClassMethodBlock; import leekscript.compiler.bloc.MainLeekBlock; public class LeekTabularValue extends AbstractExpression { @@ -62,6 +63,8 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { mTabular.writeJavaCode(mainblock, writer); writer.addCode(", "); mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + writer.addCode(writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"); writer.addCode(")"); } diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 923df3a9..9121bbca 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -15,7 +15,6 @@ import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; -import leekscript.runner.values.ClassLeekValue.ClassMethod; import leekscript.common.AccessLevel; import leekscript.common.Error; @@ -306,8 +305,9 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { } // Methods - for (Entry> method : methods.entrySet()) { - for (Entry version : method.getValue().entrySet()) { + for (var method : methods.entrySet()) { + for (var version : method.getValue().entrySet()) { + writer.currentBlock = version.getValue().block; String methodName = className + "_" + method.getKey() + "_" + version.getKey(); writer.addCode("private final Object " + methodName + "(ObjectLeekValue u_this"); for (var arg : version.getValue().block.getParameters()) { @@ -324,6 +324,7 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addCounter(1); version.getValue().block.writeJavaCode(mainblock, writer); writer.addLine("}"); + writer.currentBlock = null; } } @@ -378,7 +379,7 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { for (Entry field : staticFields.entrySet()) { writer.addCode(className); - writer.addCode(".addStaticField(\"" + field.getKey() + "\", "); + writer.addCode(".addStaticField(" + writer.getAIThis() + ", \"" + field.getKey() + "\", "); if (field.getValue() != null) { field.getValue().expression.writeJavaCode(mainblock, writer); } else { @@ -402,7 +403,7 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("args[" + i + "]"); i++; } - writer.addLine("); }});"); + writer.addLine("); }}, AccessLevel." + version.getValue().level + ");"); } writer.addCode(className); writer.addLine(".addGenericStaticMethod(\"" + method.getKey() + "\");"); @@ -433,7 +434,7 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { for (var arg : version.getValue().block.getParameters()) { writer.addCode(", args[" + i++ + "]"); } - writer.addLine("); }});"); + writer.addLine("); }}, AccessLevel." + version.getValue().level + ");"); } writer.addCode(className); writer.addLine(".addGenericMethod(\"" + method.getKey() + "\");"); @@ -532,6 +533,17 @@ public String getMethodName(String name, int argumentCount) { return null; } + public String getStaticMethodName(String name, int argumentCount) { + var versions = staticMethods.get(name); + if (versions != null) { + if (versions.containsKey(argumentCount)) return getName() + "_" + name + "_" + argumentCount; + } + if (parent != null) { + return parent.getStaticMethodName(name, argumentCount); + } + return null; + } + public ClassDeclarationMethod getStaticMethod(String method, int argumentCount) { var versions = staticMethods.get(method); if (versions != null) { diff --git a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java index ea55ad5c..3652ad2f 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java @@ -5,8 +5,6 @@ import leekscript.compiler.WordCompiler; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.AbstractExpression; -import leekscript.compiler.expression.LeekExpression; -import leekscript.compiler.expression.Operators; public class LeekReturnInstruction implements LeekInstruction { diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index a3f3159f..f12ed638 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -2,7 +2,6 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; diff --git a/src/main/java/leekscript/compiler/resolver/ResourceResolver.java b/src/main/java/leekscript/compiler/resolver/ResourceResolver.java index 7667bd1e..10fa3d68 100644 --- a/src/main/java/leekscript/compiler/resolver/ResourceResolver.java +++ b/src/main/java/leekscript/compiler/resolver/ResourceResolver.java @@ -1,8 +1,6 @@ package leekscript.compiler.resolver; -import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 95087881..dd320728 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -1183,7 +1183,7 @@ public Object field_inc(Object object, String field) throws LeekRunException { return ((ObjectLeekValue) object).field_inc(field); } if (object instanceof ClassLeekValue) { - // return ((ClassLeekValue) object).field_add_eq(field, value); + return ((ClassLeekValue) object).getFieldL(field).increment(); } throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } @@ -1193,7 +1193,7 @@ public Object field_pre_inc(Object object, String field) throws LeekRunException return ((ObjectLeekValue) object).field_pre_inc(field); } if (object instanceof ClassLeekValue) { - // return ((ClassLeekValue) object).field_add_eq(field, value); + return ((ClassLeekValue) object).getFieldL(field).pre_increment(); } throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } @@ -1203,7 +1203,7 @@ public Object field_dec(Object object, String field) throws LeekRunException { return ((ObjectLeekValue) object).field_dec(field); } if (object instanceof ClassLeekValue) { - // return ((ClassLeekValue) object).field_add_eq(field, value); + return ((ClassLeekValue) object).getFieldL(field).decrement(); } throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } @@ -1213,7 +1213,7 @@ public Object field_pre_dec(Object object, String field) throws LeekRunException return ((ObjectLeekValue) object).field_pre_dec(field); } if (object instanceof ClassLeekValue) { - // return ((ClassLeekValue) object).field_add_eq(field, value); + return ((ClassLeekValue) object).getFieldL(field).pre_decrement(); } throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } @@ -1223,7 +1223,7 @@ public Object field_add_eq(Object object, String field, Object value) throws Lee return ((ObjectLeekValue) object).field_add_eq(field, value); } if (object instanceof ClassLeekValue) { - // return ((ClassLeekValue) object).field_add_eq(field, value); + return ((ClassLeekValue) object).getFieldL(field).add_eq(value); } throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } @@ -1233,7 +1233,7 @@ public Object field_sub_eq(Object object, String field, Object value) throws Lee return ((ObjectLeekValue) object).field_sub_eq(field, value); } if (object instanceof ClassLeekValue) { - // return ((ClassLeekValue) object).field_add_eq(field, value); + return ((ClassLeekValue) object).getFieldL(field).sub_eq(value); } throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } @@ -1243,7 +1243,27 @@ public Object field_mul_eq(Object object, String field, Object value) throws Lee return ((ObjectLeekValue) object).field_mul_eq(field, value); } if (object instanceof ClassLeekValue) { - // return ((ClassLeekValue) object).field_add_eq(field, value); + return ((ClassLeekValue) object).getFieldL(field).mul_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_div_eq(Object object, String field, Object value) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_div_eq(field, value); + } + if (object instanceof ClassLeekValue) { + return ((ClassLeekValue) object).getFieldL(field).div_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_mod_eq(Object object, String field, Object value) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_mod_eq(field, value); + } + if (object instanceof ClassLeekValue) { + return ((ClassLeekValue) object).getFieldL(field).mod_eq(value); } throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } @@ -1253,7 +1273,57 @@ public Object field_bor_eq(Object object, String field, Object value) throws Lee return ((ObjectLeekValue) object).field_bor_eq(field, value); } if (object instanceof ClassLeekValue) { - // return ((ClassLeekValue) object).field_add_eq(field, value); + return ((ClassLeekValue) object).getFieldL(field).bor_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_band_eq(Object object, String field, Object value) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_band_eq(field, value); + } + if (object instanceof ClassLeekValue) { + return ((ClassLeekValue) object).getFieldL(field).band_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_bxor_eq(Object object, String field, Object value) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_bxor_eq(field, value); + } + if (object instanceof ClassLeekValue) { + return ((ClassLeekValue) object).getFieldL(field).bxor_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_shl_eq(Object object, String field, Object value) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_shl_eq(field, value); + } + if (object instanceof ClassLeekValue) { + return ((ClassLeekValue) object).getFieldL(field).shl_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_shr_eq(Object object, String field, Object value) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_shr_eq(field, value); + } + if (object instanceof ClassLeekValue) { + return ((ClassLeekValue) object).getFieldL(field).shr_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_ushr_eq(Object object, String field, Object value) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_ushr_eq(field, value); + } + if (object instanceof ClassLeekValue) { + return ((ClassLeekValue) object).getFieldL(field).ushr_eq(value); } throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } @@ -1408,10 +1478,13 @@ public Object set(Object variable, Object value) throws LeekRunException { return null; } - public Object get(Object value, Object index) throws LeekRunException { + public Object get(Object value, Object index, ClassLeekValue fromClass) throws LeekRunException { if (value instanceof ArrayLeekValue) { return ((ArrayLeekValue) value).get(this, index); } + if (value instanceof ObjectLeekValue) { + return ((ObjectLeekValue) value).getField(string(index), fromClass); + } return null; } diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index 0e013608..12b96ba7 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -227,7 +227,7 @@ public static Object executeArrayAccess(AI ai, Object array, Object key, ClassLe if (array instanceof ObjectLeekValue) { return ((ObjectLeekValue) array).callMethod(ai.string(key) + "_" + arguments.length, fromClass, arguments); } else { - return ai.execute(ai.get(array, key), arguments); + return ai.execute(ai.get(array, key, fromClass), arguments); } } } diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index e0866f40..5089e6fb 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -8,7 +8,6 @@ import java.util.Random; import java.util.Set; -import leekscript.compiler.LeekScript; import leekscript.runner.values.ArrayLeekValue; import leekscript.runner.values.LeekValue; import leekscript.runner.values.ObjectLeekValue; diff --git a/src/main/java/leekscript/runner/values/Box.java b/src/main/java/leekscript/runner/values/Box.java index 21dfdd92..d3b28c2f 100644 --- a/src/main/java/leekscript/runner/values/Box.java +++ b/src/main/java/leekscript/runner/values/Box.java @@ -183,8 +183,8 @@ public Object mod_eq(Object val) throws LeekRunException { return mValue = mUAI.mod(mValue, val); } - public Object get(Object index) throws LeekRunException { - return mUAI.get(mValue, index); + public Object get(Object index, ClassLeekValue fromClass) throws LeekRunException { + return mUAI.get(mValue, index, fromClass); } public Box getOrCreate(Object index) throws LeekRunException { diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index c3627e1b..1fc69c11 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -10,7 +10,6 @@ import leekscript.common.AccessLevel; import leekscript.runner.LeekFunction; import leekscript.common.Error; -import leekscript.compiler.bloc.AnonymousFunctionBlock; public class ClassLeekValue { @@ -180,7 +179,7 @@ public Object incField(String field) throws LeekRunException { throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } - public Object callMethod(AI ai, String method, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { + public Object callMethod(String method, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { ai.ops(1); var result = getStaticMethod(ai, method, fromClass); if (result == null) { diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index 65eaaaf8..948a2048 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -82,14 +82,6 @@ private Object[] copyValues(AI uai, Object[] values, boolean[] references) throw return copy; } - private Object[] copyPrimitiveValues(AI uai, Object[] values) throws LeekRunException { - Object[] copy = new Object[values.length]; - for (int i = 0; i < values.length; i++) { - copy[i] = LeekOperations.clone(uai, values[i]); - } - return copy; - } - public int getArgumentsCount(AI ai) throws LeekRunException { if (mType == LEEK_FUNCTION) return mFunction.getArguments(); diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index fa449bb7..4ea0f933 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -5,7 +5,6 @@ import leekscript.AILog; import leekscript.runner.AI; -import leekscript.runner.LeekAnonymousFunction; import leekscript.runner.LeekOperations; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; @@ -46,7 +45,7 @@ public Object getField(String field, ClassLeekValue fromClass) throws LeekRunExc var result = fields.get(field); if (result != null) { if (fromClass == clazz) { - return result; + return result.mValue; } else { // Protected : Access from descendant if (fromClass != null && fromClass.descendsFrom(clazz)) { @@ -54,14 +53,14 @@ public Object getField(String field, ClassLeekValue fromClass) throws LeekRunExc clazz.ai.addSystemLog(AILog.ERROR, Error.PRIVATE_FIELD, new String[] { clazz.name, field }); return null; } - return result; + return result.mValue; } else { // Public : Access from outside if (result.level != AccessLevel.PUBLIC) { clazz.ai.addSystemLog(AILog.ERROR, result.level == AccessLevel.PROTECTED ? Error.PROTECTED_FIELD : Error.PRIVATE_FIELD, new String[] { clazz.name, field }); return null; } - return result; + return result.mValue; } } } @@ -147,6 +146,22 @@ public Object field_mul_eq(String field, Object value) throws LeekRunException { throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } + public Object field_div_eq(String field, Object value) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.div_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_mod_eq(String field, Object value) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.mod_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + public Object field_bor_eq(String field, Object value) throws LeekRunException { var result = fields.get(field); if (result != null) { @@ -155,6 +170,46 @@ public Object field_bor_eq(String field, Object value) throws LeekRunException { throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } + public Object field_bxor_eq(String field, Object value) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.bxor_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_band_eq(String field, Object value) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.band_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_shl_eq(String field, Object value) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.shl_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_shr_eq(String field, Object value) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.shr_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_ushr_eq(String field, Object value) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.ushr_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + public Box getOrCreate(AI ai, Object value) throws LeekRunException { return getFieldL(LeekValueManager.getString(ai, value)); } @@ -177,8 +232,8 @@ public Object callMethod(String method, ClassLeekValue fromClass, Object... argu return result.run(this, arguments); } - public Object callSuperMethod(AI ai, ClassLeekValue currentClass, String method, Object... arguments) throws LeekRunException { - LeekAnonymousFunction result = currentClass.getSuperMethod(ai, method, currentClass); + public Object callSuperMethod(AI ai, String method, ClassLeekValue currentClass, Object... arguments) throws LeekRunException { + var result = currentClass.getSuperMethod(ai, method, currentClass); if (result == null) { int underscore = method.lastIndexOf("_"); int argCount = Integer.parseInt(method.substring(underscore + 1)); diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index 729ce8ba..fc4d5937 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -1,7 +1,5 @@ package test; -import leekscript.common.Error; - public class TestArray extends TestCommon { public void run() throws Exception { diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index 283d60a7..8aef5850 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -1,7 +1,6 @@ package test; import java.io.BufferedReader; -import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; @@ -31,7 +30,7 @@ public class TestCommon { private static int disabled = 0; private static long analyze_time = 0; private static long compile_time = 0; - private static long load_time = 0; + // private static long load_time = 0; private static long execution_time = 0; private static ArrayList operationsReference = new ArrayList<>(); private static int operationsReferenceIndex = 0; @@ -125,7 +124,7 @@ public String run_version(int version, Checker checker) { compile_time = ai.getCompileTime() / 1000000; TestCommon.analyze_time += ai.getAnalyzeTime() / 1000000; TestCommon.compile_time += ai.getCompileTime() / 1000000; - TestCommon.load_time += ai.getLoadTime() / 1000000; + // TestCommon.load_time += ai.getLoadTime() / 1000000; ai.maxOperations = Integer.MAX_VALUE; diff --git a/src/test/java/test/TestLoops.java b/src/test/java/test/TestLoops.java index 761a3bb8..cb09e135 100644 --- a/src/test/java/test/TestLoops.java +++ b/src/test/java/test/TestLoops.java @@ -1,7 +1,5 @@ package test; -import leekscript.common.Error; - public class TestLoops extends TestCommon { public void run() { diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 84df3a2b..5dfcea0f 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -1,7 +1,5 @@ package test; -import leekscript.common.Error; - public class TestObject extends TestCommon { public void run() { From aca02eff79b64773a2371d48a88c7dfc3e7638bc Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 27 Jun 2021 19:38:40 +0200 Subject: [PATCH 255/319] [ops] Fix ops --- .../leekscript/compiler/expression/LeekExpressionFunction.java | 2 ++ .../java/leekscript/compiler/expression/LeekObjectAccess.java | 1 + src/main/java/leekscript/runner/LeekValueManager.java | 1 + 3 files changed, 4 insertions(+) diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index f09ed257..7d92596f 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -264,6 +264,7 @@ public void analyze(WordCompiler compiler) { var clazz = v.getClassDeclaration().getParent(); if (clazz != null) { var constructor = clazz.getConstructor(mParameters.size()); + operations += 1; if (constructor == null) { compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.UNKNOWN_CONSTRUCTOR, new String[] { clazz.getName() })); } else if (constructor.level == AccessLevel.PRIVATE) { @@ -279,6 +280,7 @@ public void analyze(WordCompiler compiler) { if (v.getVariableType() == VariableType.CLASS) { var clazz = v.getClassDeclaration(); var staticMethod = clazz.getStaticMethod(oa.getField(), mParameters.size()); + operations += 1; if (staticMethod == null) { compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.UNKNOWN_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); } else if (staticMethod.level == AccessLevel.PRIVATE && compiler.getCurrentClass() != clazz) { diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index 603f7436..57a68846 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -70,6 +70,7 @@ public void analyze(WordCompiler compiler) { compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, Error.CLASS_MEMBER_DOES_NOT_EXIST, new String[] { clazz.getName(), field.getWord() })); } } else if (v.getVariableType() == VariableType.CLASS && v.getClassDeclaration() != null) { + operations -= 1; if (!v.getClassDeclaration().hasStaticMember(field.getWord())) { compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, Error.CLASS_STATIC_MEMBER_DOES_NOT_EXIST, new String[] { v.getClassDeclaration().getName(), field.getWord() })); } diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index 12b96ba7..16c7530d 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -225,6 +225,7 @@ public static String toJSON(AI ai, Object value) { public static Object executeArrayAccess(AI ai, Object array, Object key, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { if (array instanceof ObjectLeekValue) { + ai.ops(1); return ((ObjectLeekValue) array).callMethod(ai.string(key) + "_" + arguments.length, fromClass, arguments); } else { return ai.execute(ai.get(array, key, fromClass), arguments); From 1cade069f6ae274e6d93870f4a2600b694d62edd Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 27 Jun 2021 19:38:40 +0200 Subject: [PATCH 256/319] [class] Fix field initializers --- .../compiler/bloc/MainLeekBlock.java | 1 + .../compiler/expression/LeekVariable.java | 3 ++ .../ClassDeclarationInstruction.java | 39 ++++++++++++++----- src/main/java/leekscript/runner/AI.java | 1 + .../runner/values/ClassLeekValue.java | 2 +- 5 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index d5bf2ae6..cc91eb96 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -189,6 +189,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { for (var clazz : mUserClasses.values()) { clazz.declareJava(this, writer); } + // Constructor writer.addLine("public " + className + "() throws LeekRunException {"); writer.addLine("super(" + mInstructions.size() + ", " + mCompiler.getCurrentAI().getVersion() + ");"); diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index c837a305..dd47a208 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -119,6 +119,9 @@ public void analyze(WordCompiler compiler) { if (v.getDeclaration() != null && v.getDeclaration().getFunction() != compiler.getCurrentFunction()) { v.getDeclaration().setCaptured(); } + if (this.type == VariableType.FIELD) { + operations += 1; + } return; } // Global user functions diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 9121bbca..74b9bb9f 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -332,8 +332,10 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { for (Entry construct : constructors.entrySet()) { String methodName = className + "_" + construct.getKey(); writer.addCode("private final Object " + methodName + "(ObjectLeekValue u_this"); - for (var arg : construct.getValue().block.getParameters()) { - writer.addCode(", Object u_" + arg); + if (construct.getValue().block != null) { + for (var arg : construct.getValue().block.getParameters()) { + writer.addCode(", Object u_" + arg); + } } // if (construct.getValue().getParameters().size() == 0) { // writer.addCode(", Object __"); @@ -343,7 +345,24 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { if (parent != null) { writer.addLine("final var u_super = u_" + parent.token.getWord() + ";"); } - construct.getValue().block.writeJavaCode(mainblock, writer); + ClassDeclarationInstruction current = this; + while (current != null) { + for (var field : current.fields.entrySet()) { + writer.addCode("u_this.addField(" + writer.getAIThis() + ", \"" + field.getKey() + "\", "); + if (field.getValue().expression != null) { + field.getValue().expression.writeJavaCode(mainblock, writer); + } else { + writer.addCode("null"); + } + writer.addLine(", AccessLevel." + field.getValue().level + ");"); + } + current = current.parent; + } + if (construct.getValue().block != null) { + construct.getValue().block.writeJavaCode(mainblock, writer); + } else { + writer.addLine("return u_this;"); + } writer.addLine("}"); } } @@ -418,11 +437,11 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(", args[" + i++ + "]"); } if (construct.getValue().block != null) { - construct.getValue().block.writeJavaCode(mainblock, writer); - } else { - writer.addLine("return u_this;"); + for (var arg : construct.getValue().block.getParameters()) { + writer.addCode(", args[" + i++ + "]"); + } } - writer.addLine("}});"); + writer.addLine("); }}, AccessLevel." + construct.getValue().level + ");"); } for (var method : methods.entrySet()) { @@ -446,11 +465,11 @@ public void initializeStaticFields(MainLeekBlock mainblock, JavaWriter writer) { mainblock.getWordCompiler().setCurrentClass(this); // Create the class in the constructor of the AI - String className = "user_" + token.getWord(); + String className = "u_" + token.getWord(); for (var field : staticFields.entrySet()) { writer.addCode(className); - writer.addCode(".addStaticField(mUAI, \"" + field.getKey() + "\", "); + writer.addCode(".addStaticField(" + writer.getAIThis() + ", \"" + field.getKey() + "\", "); if (field.getValue().expression != null) { field.getValue().expression.writeJavaCode(mainblock, writer); } else { @@ -474,7 +493,7 @@ private void writeFields(MainLeekBlock mainblock, JavaWriter writer, String clas for (Entry field : fields.entrySet()) { writer.addCode(className); - writer.addCode(".addField(" + writer.getAIThis() + ", \"" + field.getKey() + "\""); + writer.addCode(".addField(\"" + field.getKey() + "\""); writer.addCode(", AccessLevel." + field.getValue().level); writer.addLine(");"); } diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index dd320728..d64c2b3a 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -1483,6 +1483,7 @@ public Object get(Object value, Object index, ClassLeekValue fromClass) throws L return ((ArrayLeekValue) value).get(this, index); } if (value instanceof ObjectLeekValue) { + ops(1); return ((ObjectLeekValue) value).getField(string(index), fromClass); } return null; diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 1fc69c11..3cf3e595 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -69,7 +69,7 @@ public void addConstructor(int arg_count, LeekAnonymousFunction function, Access constructors.put(arg_count, new ClassMethod(function, level)); } - public void addField(AI ai, String field, AccessLevel level) { + public void addField(String field, AccessLevel level) { fields.put(field, new ClassField(null, level)); } From f536bd5f1eeb1fc33a32cc78f327c514d8d2f329 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 27 Jun 2021 19:38:40 +0200 Subject: [PATCH 257/319] [array] Fix pre unary operators --- .../expression/AbstractExpression.java | 6 ++ .../compiler/expression/LeekExpression.java | 2 +- .../compiler/expression/LeekObjectAccess.java | 12 ++++ .../compiler/expression/LeekTabularValue.java | 49 +++++++++++++++++ .../compiler/expression/LeekVariable.java | 34 ++++++++++++ src/main/java/leekscript/runner/AI.java | 55 +++++++++++++++++++ .../runner/values/ArrayLeekValue.java | 25 +++++++++ .../runner/values/ObjectLeekValue.java | 8 +++ 8 files changed, 190 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/expression/AbstractExpression.java b/src/main/java/leekscript/compiler/expression/AbstractExpression.java index 9bb71d9a..14c3fe08 100644 --- a/src/main/java/leekscript/compiler/expression/AbstractExpression.java +++ b/src/main/java/leekscript/compiler/expression/AbstractExpression.java @@ -90,6 +90,12 @@ public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp expr.writeJavaCode(mainblock, writer); } + public void compilePowEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + writeJavaCode(mainblock, writer); + writer.addCode(" **= "); + expr.writeJavaCode(mainblock, writer); + } + public void compileModEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { writeJavaCode(mainblock, writer); writer.addCode(" %= "); diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index 63f57e82..8272b310 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -741,7 +741,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { mExpression1.compileMulEq(mainblock, writer, mExpression2); return; case Operators.POWERASSIGN: - mExpression1.compileSet(mainblock, writer, new LeekExpression(mExpression1, Operators.POWER, mExpression2)); + mExpression1.compilePowEq(mainblock, writer, mExpression2); return; case Operators.BITXOR_ASSIGN: mExpression1.compileBitXorEq(mainblock, writer, mExpression2); diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index 57a68846..db6b06d6 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -188,6 +188,18 @@ public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp @Override + public void compilePowEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert (object.isLeftValue() && !object.nullable()); + + writer.addCode("field_pow_eq("); + object.writeJavaCode(mainblock, writer); + writer.addCode(", \"" + field.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + + @Override + public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { assert (object.isLeftValue() && !object.nullable()); diff --git a/src/main/java/leekscript/compiler/expression/LeekTabularValue.java b/src/main/java/leekscript/compiler/expression/LeekTabularValue.java index b1b281f6..88b5a127 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTabularValue.java +++ b/src/main/java/leekscript/compiler/expression/LeekTabularValue.java @@ -117,6 +117,18 @@ public void compileIncrement(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(")"); } + + @Override + public void compilePreIncrement(MainLeekBlock mainblock, JavaWriter writer) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_pre_inc("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + @Override public void compileDecrement(MainLeekBlock mainblock, JavaWriter writer) { assert(mLeftValue && !mTabular.nullable()); @@ -128,6 +140,17 @@ public void compileDecrement(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(")"); } + @Override + public void compilePreDecrement(MainLeekBlock mainblock, JavaWriter writer) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_pre_dec("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + @Override public void compileAddEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { assert(mLeftValue && !mTabular.nullable()); @@ -167,6 +190,19 @@ public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp writer.addCode(")"); } + @Override + public void compileModEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_mod_eq("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + @Override public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { assert(mLeftValue && !mTabular.nullable()); @@ -180,6 +216,18 @@ public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp writer.addCode(")"); } + @Override + public void compilePowEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + assert(mLeftValue && !mTabular.nullable()); + + writer.addCode("put_pow_eq("); + mTabular.writeJavaCode(mainblock, writer); + writer.addCode(", "); + mCase.writeJavaCode(mainblock, writer); + writer.addCode(", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } @Override public void compileBitOrEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { @@ -260,6 +308,7 @@ public void compileShiftUnsignedRightEq(MainLeekBlock mainblock, JavaWriter writ expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } + public void setLeftValue(boolean b) { mLeftValue = b; } diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index dd47a208..1189589e 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -539,6 +539,40 @@ public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp } } + + @Override + public void compilePowEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { + if (type == VariableType.FIELD) { + writer.addCode("u_this.powEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.STATIC_FIELD) { + writer.addCode("u_class.powEqField(\"" + token.getWord() + "\", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else if (type == VariableType.GLOBAL) { + if (isBox()) { + writer.addCode("g_" + token.getWord() + ".pow_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("g_" + token.getWord() + " = pow(g_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + if (isBox()) { + writer.addCode("u_" + token.getWord() + ".pow_eq("); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("u_" + token.getWord() + " = pow(u_" + token.getWord() + ", "); + expr.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } + } + @Override public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { if (type == VariableType.FIELD) { diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index d64c2b3a..8b9b78ca 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -1248,6 +1248,16 @@ public Object field_mul_eq(Object object, String field, Object value) throws Lee throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } + public Object field_pow_eq(Object object, String field, Object value) throws LeekRunException { + if (object instanceof ObjectLeekValue) { + return ((ObjectLeekValue) object).field_pow_eq(field, value); + } + if (object instanceof ClassLeekValue) { + return ((ClassLeekValue) object).getFieldL(field).pow_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + public Object field_div_eq(Object object, String field, Object value) throws LeekRunException { if (object instanceof ObjectLeekValue) { return ((ObjectLeekValue) object).field_div_eq(field, value); @@ -1350,6 +1360,17 @@ public Object put_inc(Object array, Object key) throws LeekRunException { return null; } + public Object put_pre_inc(Object array, Object key) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_pre_inc(this, key); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + public Object put_dec(Object array, Object key) throws LeekRunException { if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_dec(this, key); @@ -1361,6 +1382,17 @@ public Object put_dec(Object array, Object key) throws LeekRunException { return null; } + public Object put_pre_dec(Object array, Object key) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_pre_dec(this, key); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + public Object put_add_eq(Object array, Object key, Object value) throws LeekRunException { if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_add_eq(this, key, value); @@ -1392,6 +1424,29 @@ public Object put_mul_eq(Object array, Object key, Object value) throws LeekRunE } return null; } + + public Object put_pow_eq(Object array, Object key, Object value) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_pow_eq(this, key, value); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + + public Object put_mod_eq(Object array, Object key, Object value) throws LeekRunException { + if (array instanceof ArrayLeekValue) { + return ((ArrayLeekValue) array).put_mod_eq(this, key, value); + } + if (array instanceof ClassLeekValue) { + // var field = string(key); + // return ((ClassLeekValue) array).getField(field), value); + } + return null; + } + public Object put_div_eq(Object array, Object key, Object value) throws LeekRunException { if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_div_eq(this, key, value); diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index 1e69a3bf..e0382196 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -134,12 +134,24 @@ public Object put_inc(AI ai, Object keyValue) throws LeekRunException { return mValues.getOrCreate(ai, key).increment(); } + public Object put_pre_inc(AI ai, Object keyValue) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + return mValues.getOrCreate(ai, key).pre_increment(); + } + public Object put_dec(AI ai, Object keyValue) throws LeekRunException { // ai.ops(1); var key = transformKey(ai, keyValue); return mValues.getOrCreate(ai, key).decrement(); } + public Object put_pre_dec(AI ai, Object keyValue) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + return mValues.getOrCreate(ai, key).pre_decrement(); + } + public Object put_add_eq(AI ai, Object keyValue, Object value) throws LeekRunException { // ai.ops(1); var key = transformKey(ai, keyValue); @@ -161,6 +173,13 @@ public Object put_mul_eq(AI ai, Object keyValue, Object value) throws LeekRunExc return value; } + public Object put_pow_eq(AI ai, Object keyValue, Object value) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + mValues.getOrCreate(ai, key).pow_eq(value); + return value; + } + public Object put_div_eq(AI ai, Object keyValue, Object value) throws LeekRunException { // ai.ops(1); var key = transformKey(ai, keyValue); @@ -168,6 +187,12 @@ public Object put_div_eq(AI ai, Object keyValue, Object value) throws LeekRunExc return value; } + public Object put_mod_eq(AI ai, Object keyValue, Object value) throws LeekRunException { + // ai.ops(1); + var key = transformKey(ai, keyValue); + mValues.getOrCreate(ai, key).mod_eq(value); + return value; + } public Object put_bor_eq(AI ai, Object keyValue, Object value) throws LeekRunException { // ai.ops(1); diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 4ea0f933..8c7808ef 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -146,6 +146,14 @@ public Object field_mul_eq(String field, Object value) throws LeekRunException { throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } + public Object field_pow_eq(String field, Object value) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + return result.pow_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + public Object field_div_eq(String field, Object value) throws LeekRunException { var result = fields.get(field); if (result != null) { From 1f58cb321e6d1549156ea636ca127a73dee51dcc Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 27 Jun 2021 19:38:40 +0200 Subject: [PATCH 258/319] [compiler] Fixes --- .../java/leekscript/compiler/IACompiler.java | 5 ++- .../expression/LeekExpressionFunction.java | 2 +- .../compiler/expression/LeekTernaire.java | 27 +++++++++------ .../ClassDeclarationInstruction.java | 34 ++----------------- .../runner/values/ClassLeekValue.java | 10 ++++-- .../runner/values/ObjectLeekValue.java | 4 +++ 6 files changed, 36 insertions(+), 46 deletions(-) diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index de9da8b7..2184fbfc 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -1,5 +1,6 @@ package leekscript.compiler; +import leekscript.compiler.AnalyzeError.AnalyzeErrorLevel; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.common.Error; @@ -83,7 +84,9 @@ public String compile(AIFile ai, String javaClassName, String AIClass) throws if (compiler.getErrors().size() > 0) { for (var error : compiler.getErrors()) { - throw new LeekCompilerException(error.token, error.error, error.parameters); + if (error.level == AnalyzeErrorLevel.ERROR) { + throw new LeekCompilerException(error.token, error.error, error.parameters); + } } } compiler.writeJava(javaClassName, writer, AIClass); diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 7d92596f..700b07f5 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -180,7 +180,7 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { if (i < mParameters.size()) { var parameter = mParameters.get(i); // Java doesn't like a single null for Object... argument - if (argCount == 1 && parameter.getType() == Type.NULL) { + if (argCount == 1 && parameter.getType() == Type.NULL && user_function == null) { writer.addCode("new Object[] { null }"); continue; } diff --git a/src/main/java/leekscript/compiler/expression/LeekTernaire.java b/src/main/java/leekscript/compiler/expression/LeekTernaire.java index 86b0b7db..4fa97a37 100644 --- a/src/main/java/leekscript/compiler/expression/LeekTernaire.java +++ b/src/main/java/leekscript/compiler/expression/LeekTernaire.java @@ -75,16 +75,20 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { // if(mExpression2 instanceof LeekExpression) mExpression2 = ((LeekExpression) mExpression2).getAbstractExpression(); if (!complete()) writer.addCode("/* " + getString() + " */"); else { - writer.addCode("ops("); + var branch_ops = mExpression1.operations != mExpression2.operations; writer.getBoolean(mainblock, mCondition); - writer.addCode(", 1) ? "); - if (mExpression1.getOperations() > 0) writer.addCode("ops("); + writer.addCode(" ? "); + if (mExpression1.getOperations() > 0 && branch_ops) writer.addCode("ops("); + else writer.addCode("("); mExpression1.writeJavaCode(mainblock, writer); - if (mExpression1.getOperations() > 0) writer.addCode(", " + mExpression1.getOperations() + ")"); + if (mExpression1.getOperations() > 0 && branch_ops) writer.addCode(", " + mExpression1.getOperations() + ")"); + else writer.addCode(")"); writer.addCode(" : "); - if (mExpression2.getOperations() > 0) writer.addCode("ops("); + if (mExpression2.getOperations() > 0 && branch_ops) writer.addCode("ops("); + else writer.addCode("("); mExpression2.writeJavaCode(mainblock, writer); - if (mExpression2.getOperations() > 0) writer.addCode(", " + mExpression2.getOperations() + ")"); + if (mExpression2.getOperations() > 0 && branch_ops) writer.addCode(", " + mExpression2.getOperations() + ")"); + else writer.addCode(")"); } } @@ -109,7 +113,6 @@ else if(mOperator == 2){ if(mExpression2 == null) mExpression2 = expression; else ((LeekExpression) mExpression2).addExpression(expression); } - } @Override @@ -234,10 +237,14 @@ else if(mOperator == 1){ public void analyze(WordCompiler compiler) { if (mCondition != null) { mCondition.analyze(compiler); - operations = mCondition.getOperations(); + operations = 1 + mCondition.getOperations(); + } + mExpression1.analyze(compiler); + mExpression2.analyze(compiler); + + if (mExpression1.operations == mExpression2.operations) { + operations += mExpression1.operations; } - if (mExpression1 != null) mExpression1.analyze(compiler); - if (mExpression2 != null) mExpression2.analyze(compiler); if (mExpression1 != null && mExpression2 != null && mExpression1.getType() == mExpression2.getType()) { type = mExpression1.getType(); diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 74b9bb9f..8d03c6ca 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -345,19 +345,6 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { if (parent != null) { writer.addLine("final var u_super = u_" + parent.token.getWord() + ";"); } - ClassDeclarationInstruction current = this; - while (current != null) { - for (var field : current.fields.entrySet()) { - writer.addCode("u_this.addField(" + writer.getAIThis() + ", \"" + field.getKey() + "\", "); - if (field.getValue().expression != null) { - field.getValue().expression.writeJavaCode(mainblock, writer); - } else { - writer.addCode("null"); - } - writer.addLine(", AccessLevel." + field.getValue().level + ");"); - } - current = current.parent; - } if (construct.getValue().block != null) { construct.getValue().block.writeJavaCode(mainblock, writer); } else { @@ -379,11 +366,11 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { } writer.addCode(className + ".initFields = new LeekAnonymousFunction() {"); - writer.addLine("public AbstractLeekValue run(AI mUAI, AbstractLeekValue u_this, AbstractLeekValue... values) throws LeekRunException {"); + writer.addLine("public Object run(ObjectLeekValue u_this, Object... values) throws LeekRunException {"); ClassDeclarationInstruction current = this; while (current != null) { for (var field : current.fields.entrySet()) { - writer.addCode("((ObjectLeekValue) u_this).addField(mUAI, \"" + field.getKey() + "\", "); + writer.addCode("u_this.addField(" + writer.getAIThis() + ", \"" + field.getKey() + "\", "); if (field.getValue().expression != null) { field.getValue().expression.writeJavaCode(mainblock, writer); } else { @@ -396,18 +383,6 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine("return null;"); writer.addLine("}};"); - for (Entry field : staticFields.entrySet()) { - writer.addCode(className); - writer.addCode(".addStaticField(" + writer.getAIThis() + ", \"" + field.getKey() + "\", "); - if (field.getValue() != null) { - field.getValue().expression.writeJavaCode(mainblock, writer); - } else { - writer.addCode("null"); - } - writer.addCode(", AccessLevel." + field.getValue().level); - writer.addLine(");"); - } - writeFields(mainblock, writer, className); // Static methods @@ -433,9 +408,6 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(className); writer.addCode(".addConstructor(" + construct.getKey() + ", new LeekAnonymousFunction() { public Object run(ObjectLeekValue thiz, Object... args) throws LeekRunException { return " + methodName + "(thiz"); int i = 0; - for (var arg : construct.getValue().block.getParameters()) { - writer.addCode(", args[" + i++ + "]"); - } if (construct.getValue().block != null) { for (var arg : construct.getValue().block.getParameters()) { writer.addCode(", args[" + i++ + "]"); @@ -473,7 +445,7 @@ public void initializeStaticFields(MainLeekBlock mainblock, JavaWriter writer) { if (field.getValue().expression != null) { field.getValue().expression.writeJavaCode(mainblock, writer); } else { - writer.addCode("LeekValueManager.NULL"); + writer.addCode("null"); } writer.addCode(", AccessLevel." + field.getValue().level); writer.addLine(");"); diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 3cf3e595..4a2c9622 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -113,12 +113,16 @@ public Object run(ObjectLeekValue thiz, Object... arguments) throws LeekRunExcep })); } + public Object getField(String field) throws LeekRunException { + return getField(ai, field, this); + } + public Object getField(AI ai, String field, ClassLeekValue fromClass) throws LeekRunException { // Private var result = staticFields.get(field); if (result != null) { if (fromClass == this) { - return result; + return result.getValue(); } else { // Protected : Access from descendant if (fromClass != null && fromClass.descendsFrom(this)) { @@ -126,14 +130,14 @@ public Object getField(AI ai, String field, ClassLeekValue fromClass) throws Lee ai.addSystemLog(AILog.ERROR, Error.PRIVATE_STATIC_FIELD, new String[] { this.name, field }); return null; } - return result; + return result.getValue(); } else { // Public : Access from outside if (result.level != AccessLevel.PUBLIC) { ai.addSystemLog(AILog.ERROR, result.level == AccessLevel.PROTECTED ? Error.PROTECTED_STATIC_FIELD : Error.PRIVATE_STATIC_FIELD, new String[] { this.name, field }); return null; } - return result; + return result.getValue(); } } } diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 8c7808ef..d0f360cb 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -36,6 +36,10 @@ public void addField(AI ai, String field, Object value, AccessLevel level) throw fields.put(field, new ObjectVariableValue(ai, LeekOperations.clone(ai, value), level)); } + public Object getField(String field) throws LeekRunException { + return getField(field, clazz); + } + public Object getField(String field, ClassLeekValue fromClass) throws LeekRunException { // System.out.println("getField " + field); if (field.equals("class")) { From 5b5765e41bde8f6ddcc5d8ea98452e8db7b0fb7b Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 27 Jun 2021 19:38:40 +0200 Subject: [PATCH 259/319] [loop] Fix foreach + tests --- src/main/java/leekscript/compiler/bloc/ForeachBlock.java | 4 ++-- src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java | 4 ++-- src/test/java/test/TestCommon.java | 4 ++-- src/test/java/test/TestLoops.java | 2 ++ src/test/java/test/TestMain.java | 2 +- src/test/java/test/TestObject.java | 2 ++ 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java index 0aba463c..16cb9c6f 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java @@ -118,14 +118,14 @@ public void analyze(WordCompiler compiler) { if ((compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(mIterator.getWord()) || compiler.getMainBlock().hasUserFunction(mIterator.getWord(), true))) || compiler.getCurrentBlock().hasVariable(mIterator.getWord())) { compiler.addError(new AnalyzeError(mIterator, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); } else { - this.addVariable(new LeekVariable(mIterator, VariableType.LOCAL)); + this.addVariable(new LeekVariable(mIterator, VariableType.LOCAL, declaration)); } + declaration.setFunction(compiler.getCurrentFunction()); } else { var v = compiler.getCurrentBlock().getVariable(mIterator.getWord(), true); if (v == null) { compiler.addError(new AnalyzeError(mIterator, AnalyzeErrorLevel.ERROR, Error.UNKNOWN_VARIABLE_OR_FUNCTION)); } - declaration.setFunction(compiler.getCurrentFunction()); } mArray.analyze(compiler); compiler.setCurrentBlock(initialBlock); diff --git a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java index 0e3bee55..85ef8917 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java @@ -172,7 +172,7 @@ public void analyze(WordCompiler compiler) { if ((compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(mKeyIterator.getWord()) || compiler.getMainBlock().hasUserFunction(mKeyIterator.getWord(), true))) || compiler.getCurrentBlock().hasVariable(mKeyIterator.getWord())) { compiler.addError(new AnalyzeError(mKeyIterator, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); } else { - this.addVariable(new LeekVariable(mKeyIterator, VariableType.LOCAL)); + this.addVariable(new LeekVariable(mKeyIterator, VariableType.LOCAL, iteratorKeyDeclaration)); } } else { var v = compiler.getCurrentBlock().getVariable(mKeyIterator.getWord(), true); @@ -185,7 +185,7 @@ public void analyze(WordCompiler compiler) { if ((compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(mIterator.getWord()) || compiler.getMainBlock().hasUserFunction(mIterator.getWord(), true))) || compiler.getCurrentBlock().hasVariable(mIterator.getWord())) { compiler.addError(new AnalyzeError(mIterator, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); } else { - this.addVariable(new LeekVariable(mIterator, VariableType.LOCAL)); + this.addVariable(new LeekVariable(mIterator, VariableType.LOCAL, iteratorDeclaration)); } } else { var v = compiler.getCurrentBlock().getVariable(mIterator.getWord(), true); diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index 8aef5850..b6802a67 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -135,7 +135,7 @@ public String run_version(int version, Checker checker) { ops = ai.operations(); - var vs = ai.getString(ai, new HashSet<>()); + var vs = ai.getString(v, new HashSet<>()); result = new Result(vs, Error.NONE, (int) ai.getOperations(), exec_time); } catch (LeekCompilerException e) { @@ -148,7 +148,7 @@ public String run_version(int version, Checker checker) { } operations.add(ops); - long referenceOperations = operationsReference.get(operationsReferenceIndex++); + // long referenceOperations = operationsReference.get(operationsReferenceIndex++); if (checker.check(result)) { System.out.println(GREEN_BOLD + " [OK] " + END_COLOR + "[v" + version + "] " + code + " === " + checker.getResult(result) + " " + C_GREY + compile_time + "ms + " + fn(result.exec_time) + "µs" + ", " + fn(result.operations) + " ops" + END_COLOR); diff --git a/src/test/java/test/TestLoops.java b/src/test/java/test/TestLoops.java index cb09e135..761a3bb8 100644 --- a/src/test/java/test/TestLoops.java +++ b/src/test/java/test/TestLoops.java @@ -1,5 +1,7 @@ package test; +import leekscript.common.Error; + public class TestLoops extends TestCommon { public void run() { diff --git a/src/test/java/test/TestMain.java b/src/test/java/test/TestMain.java index 496b1836..2fc03e95 100644 --- a/src/test/java/test/TestMain.java +++ b/src/test/java/test/TestMain.java @@ -21,7 +21,7 @@ public static void main(String[] args) throws Exception { System.out.println("Start tests..."); - TestCommon.loadReferenceOperations(); + // TestCommon.loadReferenceOperations(); // new TestCommon().code_v11("return 5 + 5;").equals("10"); new TestGeneral().run(); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 5dfcea0f..84df3a2b 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -1,5 +1,7 @@ package test; +import leekscript.common.Error; + public class TestObject extends TestCommon { public void run() { From c74183f69c52fa26085345a7ede6e8235ac1320d Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 27 Jun 2021 19:38:40 +0200 Subject: [PATCH 260/319] [leekscript] Lot of fixes + tests --- .../compiler/bloc/FunctionBlock.java | 10 +- .../compiler/bloc/MainLeekBlock.java | 14 +- .../expression/LeekExpressionFunction.java | 21 ++- .../compiler/expression/LeekVariable.java | 64 ++++----- .../ClassDeclarationInstruction.java | 7 + .../LeekVariableDeclarationInstruction.java | 11 +- src/main/java/leekscript/runner/AI.java | 24 +++- .../java/leekscript/runner/LeekFunctions.java | 29 ++++- src/main/java/leekscript/runner/PhpArray.java | 12 +- src/main/java/leekscript/runner/Wrapper.java | 36 ++++++ .../runner/values/ArrayLeekValue.java | 12 +- .../runner/values/ClassLeekValue.java | 122 +++++++++++++++++- .../runner/values/ObjectLeekValue.java | 2 +- src/test/java/test/TestArray.java | 8 ++ src/test/java/test/TestCommon.java | 4 +- src/test/java/test/TestFunction.java | 2 + src/test/java/test/TestObject.java | 52 ++++++++ 17 files changed, 359 insertions(+), 71 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java index 1319371a..4189594f 100644 --- a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java @@ -101,10 +101,14 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { var declaration = mParameterDeclarations.get(i); if (declaration.isCaptured()) { sb.append("final var u_").append(parameter).append(" = new Wrapper("); - if (mReferences.get(i)) { - sb.append("(p_").append(parameter).append(" instanceof Box) ? (Box) p_").append(parameter).append(" : new Box(" + writer.getAIThis() + ", ").append("p_").append(parameter).append("));"); + if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10) { + if (mReferences.get(i)) { + sb.append("(p_").append(parameter).append(" instanceof Box) ? (Box) p_").append(parameter).append(" : new Box(" + writer.getAIThis() + ", ").append("p_").append(parameter).append("));"); + } else { + sb.append("new Box(").append(writer.getAIThis()).append(", copy(p_").append(parameter).append(")));"); + } } else { - sb.append("new Box(").append(writer.getAIThis()).append(", copy(p_").append(parameter).append(")));"); + sb.append("new Box(").append(writer.getAIThis()).append(", p_").append(parameter).append("));"); } } else { sb.append("var u_").append(parameter).append(" = "); diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index cc91eb96..f76edff3 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -28,6 +28,7 @@ public class MainLeekBlock extends AbstractLeekBlock { private final ArrayList mAnonymousFunctions = new ArrayList(); private final Map mUserFunctions = new TreeMap(); private final Map mUserClasses = new TreeMap(); + private final List mUserClassesList = new ArrayList<>(); private int mMinLevel = 1; private int mAnonymousId = 1; private int mFunctionId = 1; @@ -186,7 +187,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { writer.addLine("public class " + className + " extends " + AIClass + " {"); // Classes - for (var clazz : mUserClasses.values()) { + for (var clazz : mUserClassesList) { clazz.declareJava(this, writer); } @@ -194,11 +195,11 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { writer.addLine("public " + className + "() throws LeekRunException {"); writer.addLine("super(" + mInstructions.size() + ", " + mCompiler.getCurrentAI().getVersion() + ");"); - for (var clazz : mUserClasses.values()) { + for (var clazz : mUserClassesList) { clazz.createJava(this, writer); } // Initialize classes static fields - for (var clazz : mUserClasses.values()) { + for (var clazz : mUserClassesList) { clazz.initializeStaticFields(this, writer); } writer.addLine("}"); @@ -228,7 +229,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { */ writer.addLine("public Object runIA() throws LeekRunException { resetCounter();"); - for (var clazz : mUserClasses.values()) { + for (var clazz : mUserClassesList) { clazz.writeJavaCode(this, writer); } @@ -360,6 +361,7 @@ public boolean hasUserClass(String name) { public void addClass(ClassDeclarationInstruction classDeclaration) { mUserClasses.put(classDeclaration.getName(), classDeclaration); + mUserClassesList.add(classDeclaration); } public ClassDeclarationInstruction getUserClass(String name) { @@ -367,7 +369,7 @@ public ClassDeclarationInstruction getUserClass(String name) { } public void analyze(WordCompiler compiler) { - for (var clazz : mUserClasses.values()) { + for (var clazz : mUserClassesList) { clazz.declare(compiler); } for (var function : mFunctions) { @@ -376,7 +378,7 @@ public void analyze(WordCompiler compiler) { for (var global : mGlobalesDeclarations) { global.declare(compiler); } - for (var clazz : mUserClasses.values()) { + for (var clazz : mUserClassesList) { clazz.analyze(compiler); } for (var function : mFunctions) { diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 700b07f5..568a4936 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -95,8 +95,9 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { addComma = false; } else if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.THIS) { // Méthode connue - String methodName = "u_" + mainblock.getWordCompiler().getCurrentClass().getMethodName(field, mParameters.size()); - writer.addCode(methodName + "(u_this"); + // String methodName = "u_" + mainblock.getWordCompiler().getCurrentClass().getMethodName(field, mParameters.size()); + // writer.addCode(methodName + "(u_this"); + writer.addCode("callMethod(u_this, \"" + field + "_" + mParameters.size() + "\", u_class"); } else { writer.addCode("callMethod("); object.writeJavaCode(mainblock, writer); @@ -126,8 +127,10 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(".callConstructor(u_this"); } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.METHOD) { // Méthode connue - String methodName = "u_" + mainblock.getWordCompiler().getCurrentClass().getMethodName(((LeekVariable) mExpression).getName(), mParameters.size()); - writer.addCode(methodName + "(u_this"); + // String methodName = "u_" + mainblock.getWordCompiler().getCurrentClass().getMethodName(((LeekVariable) mExpression).getName(), mParameters.size()); + // writer.addCode(methodName + "(u_this"); + writer.addCode("callMethod(u_this, \"" + ((LeekVariable) mExpression).getName() + "_" + mParameters.size() + "\", u_class"); + } else if (mExpression instanceof LeekVariable && ((LeekVariable) mExpression).getVariableType() == VariableType.STATIC_METHOD) { // Méthode statique connue String methodName = "u_" + mainblock.getWordCompiler().getCurrentClass().getStaticMethodName(((LeekVariable) mExpression).getName(), mParameters.size()); @@ -255,8 +258,10 @@ public void analyze(WordCompiler compiler) { var constructor = clazz.getConstructor(mParameters.size()); if (constructor == null) { compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.UNKNOWN_CONSTRUCTOR, new String[] { clazz.getName() })); - } else if (constructor.level != AccessLevel.PUBLIC) { - compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, constructor.level == AccessLevel.PROTECTED ? Error.PROTECTED_CONSTRUCTOR : Error.PRIVATE_CONSTRUCTOR, new String[] { clazz.getName() })); + } else if (constructor.level == AccessLevel.PRIVATE && compiler.getCurrentClass() != clazz) { + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.PRIVATE_CONSTRUCTOR, new String[] { clazz.getName() })); + } else if (constructor.level == AccessLevel.PROTECTED && (compiler.getCurrentClass() == null || !compiler.getCurrentClass().descendsFrom(clazz))) { + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.PROTECTED_CONSTRUCTOR, new String[] { clazz.getName() })); } } else if (v.getVariableType() == VariableType.SUPER) { @@ -267,8 +272,10 @@ public void analyze(WordCompiler compiler) { operations += 1; if (constructor == null) { compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.UNKNOWN_CONSTRUCTOR, new String[] { clazz.getName() })); - } else if (constructor.level == AccessLevel.PRIVATE) { + } else if (constructor.level == AccessLevel.PRIVATE && compiler.getCurrentClass() != clazz) { compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.PRIVATE_CONSTRUCTOR, new String[] { clazz.getName() })); + } else if (constructor.level == AccessLevel.PROTECTED && (compiler.getCurrentClass() == null || !compiler.getCurrentClass().descendsFrom(clazz))) { + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.PROTECTED_CONSTRUCTOR, new String[] { clazz.getName() })); } } } diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index 1189589e..961be021 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -356,9 +356,9 @@ public void compileSetCopy(MainLeekBlock mainblock, JavaWriter writer, AbstractE @Override public void compileIncrement(MainLeekBlock mainblock, JavaWriter writer) { if (type == VariableType.FIELD) { - writer.addCode("u_this.incField(\"" + token.getWord() + "\")"); + writer.addCode("u_this.field_inc(\"" + token.getWord() + "\")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.incField(\"" + token.getWord() + "\")"); + writer.addCode("u_class.field_inc(\"" + token.getWord() + "\")"); } else if (type == VariableType.GLOBAL) { if (isBox()) { writer.addCode("g_" + token.getWord() + ".increment()"); @@ -377,9 +377,9 @@ public void compileIncrement(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compileDecrement(MainLeekBlock mainblock, JavaWriter writer) { if (type == VariableType.FIELD) { - writer.addCode("u_this.decField(\"" + token.getWord() + "\")"); + writer.addCode("u_this.field_dec(\"" + token.getWord() + "\")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.decField(\"" + token.getWord() + "\")"); + writer.addCode("u_class.field_dec(\"" + token.getWord() + "\")"); } else if (type == VariableType.GLOBAL) { if (isBox()) { writer.addCode("g_" + token.getWord() + ".decrement()"); @@ -398,9 +398,9 @@ public void compileDecrement(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compilePreIncrement(MainLeekBlock mainblock, JavaWriter writer) { if (type == VariableType.FIELD) { - writer.addCode("u_this.incField(\"" + token.getWord() + "\")"); + writer.addCode("u_this.field_pre_inc(\"" + token.getWord() + "\")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.incField(\"" + token.getWord() + "\")"); + writer.addCode("u_class.field_pre_inc(\"" + token.getWord() + "\")"); } else if (type == VariableType.GLOBAL) { if (isBox()) { writer.addCode("g_" + token.getWord() + ".pre_increment()"); @@ -419,9 +419,9 @@ public void compilePreIncrement(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compilePreDecrement(MainLeekBlock mainblock, JavaWriter writer) { if (type == VariableType.FIELD) { - writer.addCode("u_this.decField(\"" + token.getWord() + "\")"); + writer.addCode("u_this.field_pre_dec(\"" + token.getWord() + "\")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.decField(\"" + token.getWord() + "\")"); + writer.addCode("u_class.field_pre_dec(\"" + token.getWord() + "\")"); } else if (type == VariableType.GLOBAL) { if (isBox()) { writer.addCode("g_" + token.getWord() + ".pre_decrement()"); @@ -440,11 +440,11 @@ public void compilePreDecrement(MainLeekBlock mainblock, JavaWriter writer) { @Override public void compileAddEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { if (type == VariableType.FIELD) { - writer.addCode("u_this.addEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_this.field_add_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.addEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_class.field_add_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { @@ -476,11 +476,11 @@ public void compileAddEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp @Override public void compileSubEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { if (type == VariableType.FIELD) { - writer.addCode("u_this.subEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_this.field_sub_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.subEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_class.field_sub_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { @@ -509,11 +509,11 @@ public void compileSubEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp @Override public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { if (type == VariableType.FIELD) { - writer.addCode("u_this.mulEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_this.field_mul_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.mulEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_class.field_mul_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { @@ -543,11 +543,11 @@ public void compileMulEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp @Override public void compilePowEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { if (type == VariableType.FIELD) { - writer.addCode("u_this.powEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_this.field_pow_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.powEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_class.field_pow_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { @@ -576,11 +576,11 @@ public void compilePowEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp @Override public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { if (type == VariableType.FIELD) { - writer.addCode("u_this.divEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_this.field_div_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.divEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_class.field_div_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { @@ -609,11 +609,11 @@ public void compileDivEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp @Override public void compileModEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { if (type == VariableType.FIELD) { - writer.addCode("u_this.modEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_this.field_mod_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.modEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_class.field_mod_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { @@ -642,11 +642,11 @@ public void compileModEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExp @Override public void compileBitOrEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { if (type == VariableType.FIELD) { - writer.addCode("u_this.bitOrEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_this.field_bor_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.bitOrEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_class.field_bor_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { @@ -676,11 +676,11 @@ public void compileBitOrEq(MainLeekBlock mainblock, JavaWriter writer, AbstractE @Override public void compileBitAndEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { if (type == VariableType.FIELD) { - writer.addCode("u_this.bitAndEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_this.field_band_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.bitAndEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_class.field_band_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { @@ -710,11 +710,11 @@ public void compileBitAndEq(MainLeekBlock mainblock, JavaWriter writer, Abstract @Override public void compileBitXorEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { if (type == VariableType.FIELD) { - writer.addCode("u_this.bitXorEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_this.field_bxor_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.bitXorEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_class.field_bxor_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { @@ -743,11 +743,11 @@ public void compileBitXorEq(MainLeekBlock mainblock, JavaWriter writer, Abstract @Override public void compileShiftLeftEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { if (type == VariableType.FIELD) { - writer.addCode("u_this.shlEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_this.field_shl_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.shlEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_class.field_shl_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { @@ -776,11 +776,11 @@ public void compileShiftLeftEq(MainLeekBlock mainblock, JavaWriter writer, Abstr @Override public void compileShiftRightEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { if (type == VariableType.FIELD) { - writer.addCode("u_this.shrEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_this.field_shr_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.shrEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_class.field_shr_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { @@ -809,11 +809,11 @@ public void compileShiftRightEq(MainLeekBlock mainblock, JavaWriter writer, Abst @Override public void compileShiftUnsignedRightEq(MainLeekBlock mainblock, JavaWriter writer, AbstractExpression expr) { if (type == VariableType.FIELD) { - writer.addCode("u_this.ushrEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_this.field_ushr_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.STATIC_FIELD) { - writer.addCode("u_class.ushrEqField(\"" + token.getWord() + "\", "); + writer.addCode("u_class.field_ushr_eq(\"" + token.getWord() + "\", "); expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 8d03c6ca..cd606565 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -254,6 +254,9 @@ public void analyze(WordCompiler compiler) { this.parent = parentVar.getClassDeclaration(); } } + if (parent == null) { + System.out.println("issue"); + } } for (var constructor : constructors.values()) { @@ -287,6 +290,7 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { // Static methods for (Entry> method : staticMethods.entrySet()) { for (Entry version : method.getValue().entrySet()) { + writer.currentBlock = version.getValue().block; String methodName = className + "_" + method.getKey() + "_" + version.getKey(); writer.addCode("private final Object " + methodName + "("); int i = 0; @@ -301,6 +305,7 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { } version.getValue().block.writeJavaCode(mainblock, writer); writer.addLine("}"); + writer.currentBlock = null; } } @@ -330,6 +335,7 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { // Constructeurs for (Entry construct : constructors.entrySet()) { + writer.currentBlock = construct.getValue().block; String methodName = className + "_" + construct.getKey(); writer.addCode("private final Object " + methodName + "(ObjectLeekValue u_this"); if (construct.getValue().block != null) { @@ -351,6 +357,7 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine("return u_this;"); } writer.addLine("}"); + writer.currentBlock = null; } } diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index d9f2fb91..5940cb82 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -80,7 +80,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine("), " + e.getOperations() + ")"); } writer.addLine(";", mLine, mAI); - } else { + } else if (mainblock.getWordCompiler().getVersion() <= 10) { writer.addCode("final var u_" + token.getWord() + " = new Wrapper(new Box(" + writer.getAIThis() + ", "); if (mValue != null) mValue.compileL(mainblock, writer); else writer.addCode("null"); @@ -89,6 +89,15 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(", " + mValue.getOperations()); } writer.addLine(");", mLine, mAI); + } else { + writer.addCode("final var u_" + token.getWord() + " = new Wrapper(new Box(" + writer.getAIThis() + ", "); + if (mValue != null) mValue.writeJavaCode(mainblock, writer); + else writer.addCode("null"); + writer.addLine(")"); + if (mValue != null && mValue.getOperations() > 0) { + writer.addCode(", " + mValue.getOperations()); + } + writer.addLine(");", mLine, mAI); } } else { if (mainblock.getWordCompiler().getVersion() <= 10) { diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 8b9b78ca..e5656667 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -950,7 +950,11 @@ public Object add(Object x, Object y) throws LeekRunException { if (iterator.key() instanceof String) { retour.getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); } else { - retour.push(this, iterator.getValue(this)); + if (getVersion() == 10) { + retour.push(this, LeekOperations.clone(this, iterator.getValue(this))); + } else { + retour.push(this, iterator.getValue(this)); + } } iterator.next(); } @@ -959,7 +963,11 @@ public Object add(Object x, Object y) throws LeekRunException { if (iterator.key() instanceof String) { retour.getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); } else { - retour.push(this, iterator.getValue(this)); + if (getVersion() == 10) { + retour.push(this, LeekOperations.clone(this, iterator.getValue(this))); + } else { + retour.push(this, iterator.getValue(this)); + } } iterator.next(); } @@ -977,11 +985,19 @@ public Object add(Object x, Object y) throws LeekRunException { if (iterator.key() instanceof String) { retour.getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); } else { - retour.push(this, iterator.getValue(this)); + if (getVersion() == 10) { + retour.push(this, LeekOperations.clone(this, iterator.getValue(this))); + } else { + retour.push(this, iterator.getValue(this)); + } } iterator.next(); } - retour.push(this, y); + if (getVersion() == 10) { + retour.push(this, LeekOperations.clone(this, y)); + } else { + retour.push(this, y); + } return retour; } diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 98899455..6c1c5f02 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -525,9 +525,12 @@ public void addOperations(AI leekIA, ILeekFunction function, Object parameters[] @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { var array = (ArrayLeekValue) parameters[0]; - var value = LeekOperations.clone(ai, parameters[1]); var index = ((Number) parameters[2]).intValue(); - array.insert(ai, value, index); + if (ai.getVersion() == 10) { + array.insert(ai, LeekOperations.clone(ai, parameters[1]), index); + } else { + array.insert(ai, parameters[1], index); + } return null; } @@ -554,8 +557,12 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le @Override public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { var array = (ArrayLeekValue) parameters[0]; - var value = LeekOperations.clone(leekIA, parameters[1]); - array.insert(leekIA, value, 0); + if (leekIA.getVersion() == 10) { + var value = LeekOperations.clone(leekIA, parameters[1]); + array.insert(leekIA, value, 0); + } else { + array.insert(leekIA, parameters[1], 0); + } return null; } }, @@ -619,7 +626,12 @@ public Object run(AI leekIA, ILeekFunction function, Object... parameters) throw int type = PhpArray.ASC_A; if (leekIA.bool(parameters[1])) type = PhpArray.DESC_A; + // try { array.sort(leekIA, type); + // } catch (Exception e) { + + // e.printStackTrace(System.out); + // } return null; } @@ -791,9 +803,8 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le int size = array.size(); if (AI.isType(parameters[2], AI.NUMBER)) size = ai.integer(parameters[2]); - Object copy = LeekOperations.clone(ai, parameters[1]); for (int i = 0; i < size; i++) { - array.put(ai, i, copy); + array.put(ai, i, parameters[1]); ai.ops(3); } return null; @@ -838,7 +849,11 @@ public Object run(AI leekIA, ILeekFunction function, Object... parameters) throw var array = (ArrayLeekValue) parameters[0]; var array2 = (ArrayLeekValue) parameters[1]; for (var value : array2) { - array.push(leekIA, value.getValue()); + if (leekIA.getVersion() == 10) { + array.push(leekIA, LeekOperations.clone(leekIA, value.getValue())); + } else { + array.push(leekIA, value.getValue()); + } leekIA.ops(1); } return null; diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 5089e6fb..44de57c0 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -82,8 +82,9 @@ else if (((ArrayLeekValue) v1).size() < a.size()) return -1; else return 1; - } else - return -1; + } else { + return 0; + } } } @@ -143,8 +144,9 @@ else if (((ArrayLeekValue) v1).size() < a.size()) return -1; else return 1; - } else - return -1; + } else { + return 0; + } } } @@ -928,7 +930,7 @@ public String toString(AI ai, Set visited) throws LeekRunException { if (!ai.isPrimitive(e.value.getValue())) { visited.add(e.value.getValue()); } - sb.append(ai.getString(e.value, visited)); + sb.append(ai.getString(e.value.getValue(), visited)); } e = e.next; } diff --git a/src/main/java/leekscript/runner/Wrapper.java b/src/main/java/leekscript/runner/Wrapper.java index fbfe6c90..8e5b6c43 100644 --- a/src/main/java/leekscript/runner/Wrapper.java +++ b/src/main/java/leekscript/runner/Wrapper.java @@ -47,10 +47,18 @@ public Object increment() throws LeekRunException { return variable.increment(); } + public Object pre_increment() throws LeekRunException { + return variable.pre_increment(); + } + public Object decrement() throws LeekRunException { return variable.decrement(); } + public Object pre_decrement() throws LeekRunException { + return variable.pre_decrement(); + } + public Object add_eq(Object x) throws LeekRunException { return variable.add_eq(x); } @@ -70,4 +78,32 @@ public Object div_eq(Object x) throws LeekRunException { public Object mod_eq(Object x) throws LeekRunException { return variable.mod_eq(x); } + + public Object pow_eq(Object x) throws LeekRunException { + return variable.pow_eq(x); + } + + public int band_eq(Object x) throws LeekRunException { + return variable.band_eq(x); + } + + public int bor_eq(Object x) throws LeekRunException { + return variable.bor_eq(x); + } + + public int bxor_eq(Object x) throws LeekRunException { + return variable.bxor_eq(x); + } + + public int shl_eq(Object x) throws LeekRunException { + return variable.shl_eq(x); + } + + public int shr_eq(Object x) throws LeekRunException { + return variable.shr_eq(x); + } + + public int ushr_eq(Object x) throws LeekRunException { + return variable.ushr_eq(x); + } } \ No newline at end of file diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index e0382196..5ff5b695 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -124,6 +124,9 @@ public Box getOrCreate(AI ai, Object keyValue) throws LeekRunException { public Object put(AI ai, Object keyValue, Object value) throws LeekRunException { // ai.ops(1); var key = transformKey(ai, keyValue); + if (ai.getVersion() == 10) { + value = LeekOperations.clone(ai, value); + } mValues.set(ai, key, value); return value; } @@ -414,10 +417,15 @@ public JSON toJSON(AI ai, HashSet visited) throws LeekRunException { public String toString() { var r = "["; boolean first = true; - for (Object v : this) { + ArrayIterator i = getArrayIterator(); + while (!i.ended()) { if (first) first = false; else r += ", "; - r += v.toString(); + if (mValues.isAssociative()) { + r += i.key().toString() + ": "; + } + r += i.value(); + i.next(); } return r + "]"; } diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 4a2c9622..4c75787b 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -175,7 +175,7 @@ public Object setField(String field, Object value) throws LeekRunException { throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } - public Object incField(String field) throws LeekRunException { + public Object field_inc(String field) throws LeekRunException { var result = staticFields.get(field); if (result != null) { return result.increment(); @@ -183,6 +183,126 @@ public Object incField(String field) throws LeekRunException { throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); } + public Object field_pre_inc(String field) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.pre_increment(); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_dec(String field) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.decrement(); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_pre_dec(String field) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.pre_decrement(); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_add_eq(String field, Object value) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.add_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_sub_eq(String field, Object value) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.sub_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_mul_eq(String field, Object value) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.mul_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_pow_eq(String field, Object value) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.pow_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_div_eq(String field, Object value) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.div_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_mod_eq(String field, Object value) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.mod_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_bor_eq(String field, Object value) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.bor_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_bxor_eq(String field, Object value) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.bxor_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_band_eq(String field, Object value) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.band_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_shl_eq(String field, Object value) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.shl_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_shr_eq(String field, Object value) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.shr_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + + public Object field_ushr_eq(String field, Object value) throws LeekRunException { + var result = staticFields.get(field); + if (result != null) { + return result.ushr_eq(value); + } + throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + } + public Object callMethod(String method, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { ai.ops(1); var result = getStaticMethod(ai, method, fromClass); diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index d0f360cb..e882d949 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -48,7 +48,7 @@ public Object getField(String field, ClassLeekValue fromClass) throws LeekRunExc // Private : Access from same class var result = fields.get(field); if (result != null) { - if (fromClass == clazz) { + if (fromClass == clazz || clazz.descendsFrom(fromClass)) { return result.mValue; } else { // Protected : Access from descendant diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index fc4d5937..ff6c4fb7 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -423,11 +423,19 @@ public void run() throws Exception { code("var a = [8,6,2,3,7,1,0]; sort(a); return a").equals("[0, 1, 2, 3, 6, 7, 8]"); code("var a = [8,6,2,3,7,1,0]; sort(a, SORT_ASC); return a").equals("[0, 1, 2, 3, 6, 7, 8]"); code("var a = [8,6,2,3,7,1,0]; sort(a, SORT_DESC); return a").equals("[8, 7, 6, 3, 2, 1, 0]"); + code_v10("var a = [0, 1, 1, 1, 2, 2, 2, 2, 2, null, 3, 3, 3, 3, 3, 3, 3, 3, 3, null, 4, 4, 4, null, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, null, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, null, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6] sort(a) return a").equals("[0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, null, null, null, null, null]"); + code_v11("var a = [0, 1, 1, 1, 2, 2, 2, 2, 2, null, 3, 3, 3, 3, 3, 3, 3, 3, 3, null, 4, 4, 4, null, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, null, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, null, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6] sort(a) return a").equals("[null, null, null, null, null, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6]"); section("Array.assocSort()"); code("var a = ['b':'vb','c':'vc','a':'va','d':'vd']; assocSort(a); return a").equals("[a : va, b : vb, c : vc, d : vd]"); code("var a = ['b':'vb','c':'vc','a':'va','d':'vd']; assocSort(a, SORT_DESC); return a").equals("[d : vd, c : vc, b : vb, a : va]"); code("var a = [8,6,2,3,7,1,0]; assocSort(a); return a").equals("[6 : 0, 5 : 1, 2 : 2, 3 : 3, 1 : 6, 4 : 7, 0 : 8]"); + code_v10("var a = [0, 1, 1, 1, 2, 2, 2, 2, 2, null, 3, 3, 3, 3, 3, 3, 3, 3, 3, null, 4, 4, 4, null, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, null, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, null, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6] assocSort(a) return a").equals("[0 : 0, 1 : 1, 2 : 1, 3 : 1, 4 : 2, 5 : 2, 6 : 2, 7 : 2, 8 : 2, 10 : 3, 11 : 3, 12 : 3, 13 : 3, 14 : 3, 15 : 3, 16 : 3, 17 : 3, 18 : 3, 20 : 4, 21 : 4, 22 : 4, 24 : 4, 25 : 4, 26 : 4, 27 : 4, 28 : 4, 29 : 4, 30 : 4, 31 : 4, 32 : 4, 33 : 5, 34 : 5, 35 : 5, 37 : 5, 38 : 5, 39 : 5, 40 : 5, 41 : 5, 42 : 5, 43 : 5, 44 : 5, 45 : 5, 46 : 5, 47 : 5, 48 : 5, 49 : 5, 51 : 6, 52 : 6, 53 : 6, 54 : 6, 55 : 6, 56 : 6, 57 : 6, 58 : 6, 59 : 6, 60 : 6, 61 : 6, 62 : 6, 63 : 6, 64 : 6, 65 : 6, 66 : 6, 67 : 6, 68 : 6, 69 : 6, 70 : 6, 9 : null, 19 : null, 23 : null, 36 : null, 50 : null]"); + code_v11("var a = [0, 1, 1, 1, 2, 2, 2, 2, 2, null, 3, 3, 3, 3, 3, 3, 3, 3, 3, null, 4, 4, 4, null, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, null, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, null, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6] assocSort(a) return a").equals("[9 : null, 19 : null, 23 : null, 36 : null, 50 : null, 0 : 0, 1 : 1, 2 : 1, 3 : 1, 4 : 2, 5 : 2, 6 : 2, 7 : 2, 8 : 2, 10 : 3, 11 : 3, 12 : 3, 13 : 3, 14 : 3, 15 : 3, 16 : 3, 17 : 3, 18 : 3, 20 : 4, 21 : 4, 22 : 4, 24 : 4, 25 : 4, 26 : 4, 27 : 4, 28 : 4, 29 : 4, 30 : 4, 31 : 4, 32 : 4, 33 : 5, 34 : 5, 35 : 5, 37 : 5, 38 : 5, 39 : 5, 40 : 5, 41 : 5, 42 : 5, 43 : 5, 44 : 5, 45 : 5, 46 : 5, 47 : 5, 48 : 5, 49 : 5, 51 : 6, 52 : 6, 53 : 6, 54 : 6, 55 : 6, 56 : 6, 57 : 6, 58 : 6, 59 : 6, 60 : 6, 61 : 6, 62 : 6, 63 : 6, 64 : 6, 65 : 6, 66 : 6, 67 : 6, 68 : 6, 69 : 6, 70 : 6]"); + code_v10("var a = [162: 0, 144: 1, 145: 1, 180: 1, 179: 1, 128: 2, 197: 2, 161: 2, 181: null, 143: 3, 110: 3, 146: 3, 214: 3, 234: null, 230: null, 199: null, 125: 4, 92: 4, 164: 4, 232: 4, 160: 4, 93: 4, 231: 4, 77: null, 252: null, 247: null, 217: null, 251: null, 74: 5, 182: 5, 250: 5, 142: 5, 75: 5, 147: 5, 249: 5, 177: 5, 76: 5, 248: 5, 212: null, 54: null, 60: null, 270: null, 235: null, 269: null, 56: 6, 200: 6, 268: 6, 57: 6, 165: 6, 267: 6, 159: 6, 130: 6, 266: 6, 194: 6, 59: 6, 265: 6, 229: null] assocSort(a) return a").equals("[162 : 0, 144 : 1, 145 : 1, 180 : 1, 179 : 1, 128 : 2, 197 : 2, 161 : 2, 143 : 3, 110 : 3, 146 : 3, 214 : 3, 125 : 4, 92 : 4, 164 : 4, 232 : 4, 160 : 4, 93 : 4, 231 : 4, 74 : 5, 182 : 5, 250 : 5, 142 : 5, 75 : 5, 147 : 5, 249 : 5, 177 : 5, 76 : 5, 248 : 5, 56 : 6, 200 : 6, 268 : 6, 57 : 6, 165 : 6, 267 : 6, 159 : 6, 130 : 6, 266 : 6, 194 : 6, 59 : 6, 265 : 6, 181 : null, 234 : null, 230 : null, 199 : null, 77 : null, 252 : null, 247 : null, 217 : null, 251 : null, 212 : null, 54 : null, 60 : null, 270 : null, 235 : null, 269 : null, 229 : null]"); + code_v11("var a = [162: 0, 144: 1, 145: 1, 180: 1, 179: 1, 128: 2, 197: 2, 161: 2, 181: null, 143: 3, 110: 3, 146: 3, 214: 3, 234: null, 230: null, 199: null, 125: 4, 92: 4, 164: 4, 232: 4, 160: 4, 93: 4, 231: 4, 77: null, 252: null, 247: null, 217: null, 251: null, 74: 5, 182: 5, 250: 5, 142: 5, 75: 5, 147: 5, 249: 5, 177: 5, 76: 5, 248: 5, 212: null, 54: null, 60: null, 270: null, 235: null, 269: null, 56: 6, 200: 6, 268: 6, 57: 6, 165: 6, 267: 6, 159: 6, 130: 6, 266: 6, 194: 6, 59: 6, 265: 6, 229: null] assocSort(a) return a").equals("[181 : null, 234 : null, 230 : null, 199 : null, 77 : null, 252 : null, 247 : null, 217 : null, 251 : null, 212 : null, 54 : null, 60 : null, 270 : null, 235 : null, 269 : null, 229 : null, 162 : 0, 144 : 1, 145 : 1, 180 : 1, 179 : 1, 128 : 2, 197 : 2, 161 : 2, 143 : 3, 110 : 3, 146 : 3, 214 : 3, 125 : 4, 92 : 4, 164 : 4, 232 : 4, 160 : 4, 93 : 4, 231 : 4, 74 : 5, 182 : 5, 250 : 5, 142 : 5, 75 : 5, 147 : 5, 249 : 5, 177 : 5, 76 : 5, 248 : 5, 56 : 6, 200 : 6, 268 : 6, 57 : 6, 165 : 6, 267 : 6, 159 : 6, 130 : 6, 266 : 6, 194 : 6, 59 : 6, 265 : 6]"); + code_v10("var a = [162: 0, 144: 1, 145: 1, 180: 1, 179: 1, 128: 2, 197: 2, 161: 2, 181: null, 143: 3, 110: 3, 146: 3, 214: 3, 234: null, 230: null, 199: null, 125: 4, 92: 4, 164: 4, 232: 4, 160: 4, 93: 4, 231: 4, 77: null, 252: null, 247: null, 217: null, 251: null, 74: 5, 182: 5, 250: 5, 142: 5, 75: 5, 147: 5, 249: 5, 177: 5, 76: 5, 248: 5, 212: null, 54: null, 60: null, 270: null, 235: null, 269: null, 56: 6, 200: 6, 268: 6, 57: 6, 165: 6, 267: 6, 159: 6, 130: 6, 266: 6, 194: 6, 59: 6, 265: 6, 229: null] assocSort(a, SORT_DESC) return a").equals("[181 : null, 234 : null, 230 : null, 199 : null, 77 : null, 252 : null, 247 : null, 217 : null, 251 : null, 212 : null, 54 : null, 60 : null, 270 : null, 235 : null, 269 : null, 229 : null, 56 : 6, 200 : 6, 268 : 6, 57 : 6, 165 : 6, 267 : 6, 159 : 6, 130 : 6, 266 : 6, 194 : 6, 59 : 6, 265 : 6, 74 : 5, 182 : 5, 250 : 5, 142 : 5, 75 : 5, 147 : 5, 249 : 5, 177 : 5, 76 : 5, 248 : 5, 125 : 4, 92 : 4, 164 : 4, 232 : 4, 160 : 4, 93 : 4, 231 : 4, 143 : 3, 110 : 3, 146 : 3, 214 : 3, 128 : 2, 197 : 2, 161 : 2, 144 : 1, 145 : 1, 180 : 1, 179 : 1, 162 : 0]"); + code_v11("var a = [162: 0, 144: 1, 145: 1, 180: 1, 179: 1, 128: 2, 197: 2, 161: 2, 181: null, 143: 3, 110: 3, 146: 3, 214: 3, 234: null, 230: null, 199: null, 125: 4, 92: 4, 164: 4, 232: 4, 160: 4, 93: 4, 231: 4, 77: null, 252: null, 247: null, 217: null, 251: null, 74: 5, 182: 5, 250: 5, 142: 5, 75: 5, 147: 5, 249: 5, 177: 5, 76: 5, 248: 5, 212: null, 54: null, 60: null, 270: null, 235: null, 269: null, 56: 6, 200: 6, 268: 6, 57: 6, 165: 6, 267: 6, 159: 6, 130: 6, 266: 6, 194: 6, 59: 6, 265: 6, 229: null] assocSort(a, SORT_DESC) return a").equals("[56 : 6, 200 : 6, 268 : 6, 57 : 6, 165 : 6, 267 : 6, 159 : 6, 130 : 6, 266 : 6, 194 : 6, 59 : 6, 265 : 6, 74 : 5, 182 : 5, 250 : 5, 142 : 5, 75 : 5, 147 : 5, 249 : 5, 177 : 5, 76 : 5, 248 : 5, 125 : 4, 92 : 4, 164 : 4, 232 : 4, 160 : 4, 93 : 4, 231 : 4, 143 : 3, 110 : 3, 146 : 3, 214 : 3, 128 : 2, 197 : 2, 161 : 2, 144 : 1, 145 : 1, 180 : 1, 179 : 1, 162 : 0, 181 : null, 234 : null, 230 : null, 199 : null, 77 : null, 252 : null, 247 : null, 217 : null, 251 : null, 212 : null, 54 : null, 60 : null, 270 : null, 235 : null, 269 : null, 229 : null]"); section("Array.keySort()"); code("var a = ['b':'vb','c':'vc','a':'va','d':'vd']; keySort(a); return a").equals("[a : va, b : vb, c : vc, d : vd]"); diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index b6802a67..a72400d6 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -139,11 +139,11 @@ public String run_version(int version, Checker checker) { result = new Result(vs, Error.NONE, (int) ai.getOperations(), exec_time); } catch (LeekCompilerException e) { - // e.printStackTrace(); + e.printStackTrace(); // System.out.println("Error = " + e.getError()); result = new Result(e.getError().toString(), e.getError(), 0, 0); } catch (Exception e) { - // e.printStackTrace(); + e.printStackTrace(); result = new Result("error", Error.NONE, 0, 0); } diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index e8ad7d29..30984b52 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -78,6 +78,8 @@ public void run() { code("function f() { distance = 12 } function distance() { return 'salut' } return distance()").equals("salut"); code("getOperations()").equals("null"); code("var a = [function() { return 12 }] return a[0]()").equals("12"); + code_v10("function push_to_array(array) { return function(element) { push(array, element); } } var arrayCurry = []; var functionToCall = push_to_array(arrayCurry); for (var i = 0; i < 5; i++) functionToCall(i); return arrayCurry").equals("[]"); + code_v11("function push_to_array(array) { return function(element) { push(array, element); } } var arrayCurry = []; var functionToCall = push_to_array(arrayCurry); for (var i = 0; i < 5; i++) functionToCall(i); return arrayCurry").equals("[0, 1, 2, 3, 4]"); section("Modify argument"); code("function test(x) { x += 10 return x } return test(5)").equals("15"); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 84df3a2b..7f83ad69 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -46,6 +46,7 @@ public void run() { code_v11("class A { static x = 'hello' } return A.x").equals("hello"); code_v11("class A { static x = [1, 2, 3] } return A.x").equals("[1, 2, 3]"); code_v11("class A { static x = null } return A.x").equals("null"); + code_v11("class Affiche { static COULEUR = getColor(42, 125, 78) } return Affiche.COULEUR").equals(""); section("Operators on field"); code_v11("class A { a = 10 } var a = new A(); return --a.a").equals("9"); @@ -65,6 +66,24 @@ public void run() { code_v11("class A { a = 10 } var a = new A(); return a.a >>= 5").equals("0"); code_v11("class A { a = 10 } var a = new A(); return a.a >>>= 5").equals("0"); + section("Operators on field in method"); + code_v11("class A { a = 10 m() { return --a } } return new A().m()").equals("9"); + code_v11("class A { a = 10 m() { a-- return a } } return new A().m()").equals("9"); + code_v11("class A { a = 10 m() { return ++a } } return new A().m()").equals("11"); + code_v11("class A { a = 10 m() { a++ return a } } return new A().m()").equals("11"); + code_v11("class A { a = 10 m() { return a += 5 } } return new A().m()").equals("15"); + code_v11("class A { a = 10 m() { return a -= 5 } } return new A().m()").equals("5"); + code_v11("class A { a = 10 m() { return a *= 5 } } return new A().m()").equals("50"); + code_v11("class A { a = 10 m() { return a /= 5 } } return new A().m()").equals("2.0"); + code_v11("class A { a = 10 m() { return a %= 5 } } return new A().m()").equals("0"); + code_v11("class A { a = 10 m() { return a **= 5 } } return new A().m()").equals("100000"); + code_v11("class A { a = 10 m() { return a |= 5 } } return new A().m()").equals("15"); + code_v11("class A { a = 10 m() { return a &= 5 } } return new A().m()").equals("0"); + code_v11("class A { a = 10 m() { return a ^= 5 } } return new A().m()").equals("15"); + code_v11("class A { a = 10 m() { return a <<= 5 } } return new A().m()").equals("320"); + code_v11("class A { a = 10 m() { return a >>= 5 } } return new A().m()").equals("0"); + code_v11("class A { a = 10 m() { return a >>>= 5 } } return new A().m()").equals("0"); + section("Operators on static field"); code_v11("class A { static a = 10 } return --A.a").equals("9"); code_v11("class A { static a = 10 } A.a-- return A.a").equals("9"); @@ -83,6 +102,24 @@ public void run() { code_v11("class A { static a = 10 } return A.a >>= 5").equals("0"); code_v11("class A { static a = 10 } return A.a >>>= 5").equals("0"); + section("Operators on static field in method"); + code_v11("class A { static a = 10 static m() { return --a } } return A.m()").equals("9"); + code_v11("class A { static a = 10 static m() { a-- return a } } return A.m()").equals("9"); + code_v11("class A { static a = 10 static m() { return ++a } } return A.m()").equals("11"); + code_v11("class A { static a = 10 static m() { a++ return a } } return A.m()").equals("11"); + code_v11("class A { static a = 10 static m() { return a += 5 } } return A.m()").equals("15"); + code_v11("class A { static a = 10 static m() { return a -= 5 } } return A.m()").equals("5"); + code_v11("class A { static a = 10 static m() { return a *= 5 } } return A.m()").equals("50"); + code_v11("class A { static a = 10 static m() { return a /= 5 } } return A.m()").equals("2.0"); + code_v11("class A { static a = 10 static m() { return a %= 5 } } return A.m()").equals("0"); + code_v11("class A { static a = 10 static m() { return a **= 5 } } return A.m()").equals("100000"); + code_v11("class A { static a = 10 static m() { return a |= 5 } } return A.m()").equals("15"); + code_v11("class A { static a = 10 static m() { return a &= 5 } } return A.m()").equals("0"); + code_v11("class A { static a = 10 static m() { return a ^= 5 } } return A.m()").equals("15"); + code_v11("class A { static a = 10 static m() { return a <<= 5 } } return A.m()").equals("320"); + code_v11("class A { static a = 10 static m() { return a >>= 5 } } return A.m()").equals("0"); + code_v11("class A { static a = 10 static m() { return a >>>= 5 } } return A.m()").equals("0"); + section("Inheritance"); code_v11("class A { x = 10 } class B extends A {} var a = new B() return a.x").equals("10"); code_v11("class A { m() { return 'ok' } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("ok"); @@ -93,6 +130,9 @@ public void run() { code_v11("class A { m() { return 'okA' } } class B extends A { m() { return super.m() + 'B' }} class C extends B { m() { return super.m() + 'C' } } var a = new C()return a.m()").equals("okABC"); code_v11("class A { items } class B extends A { constructor() { this.items = [] } } var x = new B() return x").equals("B {items: []}"); code_v11("class A { items } class B extends A { constructor() { this.items = [] super() } } var x = new B() return x").equals("B {items: []}"); + code_v11("class A { m() { return 'parent' } t() { return this.m() } } class B extends A { m() { return 'enfant' } } return new B().t()").equals("enfant"); + code_v11("class A { m() { return 'parent' } t() { return m() } } class B extends A { m() { return 'enfant' } } return new B().t()").equals("enfant"); + code_v11("class A { public id; } class W extends A {} class H extends W { constructor(id){ this.id=id } }").equals("null"); section("Access levels: fields"); code_v11("class A { x = 10 } var a = new A() return a.x").equals("10"); @@ -103,7 +143,13 @@ public void run() { code_v11("class A { private x = 10 } class B extends A {} var a = new B() return a.x").equals("null"); code_v11("class A { protected x = 10 } class B extends A {} var a = new B() return a.x").equals("null"); code_v11("class A { protected x = 10 } class B extends A { m() { return x } } var a = new B() return a.m()").equals("10"); + code_v11("class A { private x = 10 constructor() { x = 15 } } var a = new A() return a").equals("A {x: 15}"); + code_v11("class A { private x; constructor() { this.x = []; } } return new A()").equals("A {x: []}"); + code_v11("class Parent { private chaine = 'Nawak'; public get_chaine_parent() { return this.chaine; } } class Enfant extends Parent { public get_chaine_enfant() { return this.get_chaine_parent() } } var e = Enfant() return [e.get_chaine_parent(), e.get_chaine_enfant() ]").equals("[Nawak, Nawak]"); + code_v11("class Parent { protected chaine = 'Nawak'; public get_chaine_parent() { return this.chaine; } } class Enfant extends Parent { public get_chaine_enfant() { return this.get_chaine_parent() } } var e = Enfant() return [e.get_chaine_parent(), e.get_chaine_enfant() ]").equals("[Nawak, Nawak]"); + code_v11("class A { private x; constructor() { this.x = [] push(this.x, 10); } } return new A()").equals("A {x: [10]}"); + code_v11("class A { private x = 10 m() { return x } } var a = new A() return a.m()").equals("10"); section("Access levels: static fields"); code_v11("class A { static x = 10 } return A.x").equals("10"); code_v11("class A { public static x = 10 } return A.x").equals("10"); @@ -113,6 +159,7 @@ public void run() { code_v11("class A { private static x = 10 } class B extends A {} return B.x").equals("null"); code_v11("class A { protected static x = 10 } class B extends A {} return B.x").equals("null"); code_v11("class A { protected static x = 10 } class B extends A { static m() { return x } } return B.m()").equals("10"); + code_v11("class A { private static x = 10 static m() { return A.x } } return A.m()").equals("10"); section("Access levels: methods"); code_v11("class A { m() { return 10 } } var a = new A() return a.m()").equals("10"); @@ -133,6 +180,7 @@ public void run() { code_v11("class A { x protected constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").equals("10"); code_v11("class A { x private constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").error(Error.PRIVATE_CONSTRUCTOR); code_v11("class A { private constructor() { } } class B extends A {} return new B()").equals("B {}"); + code_v11("class A { private constructor() {} static getInstance() { return new A() } } return A.getInstance()").equals("A {}"); section("Access levels: static methods"); code_v11("class A { static m() { return 10 } } return A.m()").equals("10"); @@ -150,6 +198,10 @@ public void run() { code_v11("class B { y = 10 } class A { x = new B() } var a = new A() return a.x.y").equals("10"); code_v11("class B { y = 10 } class A { static x = new B() } return A.x").equals("B {y: 10}"); + section("Method is a system method"); + code_v11("class A { sqrt() { return sqrt(25) } }").equals("null"); + code_v11("class A { sqrt() { return sqrt(25) } } return new A().sqrt()").equals("5"); + /* * Operators */ From 52051038d8c1bfa9dfc7d5bba71a5600a1da72da Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 6 Jul 2021 23:04:52 +0200 Subject: [PATCH 261/319] [dowhile] Fix do while with empty body --- src/main/java/leekscript/compiler/WordCompiler.java | 7 ++++--- .../leekscript/compiler/bloc/AbstractLeekBlock.java | 11 ++++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 61c433ba..b2bf13ea 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -139,7 +139,7 @@ public void readCode() throws LeekCompilerException { // On vérifie les instructions en cours - if (mCurentBlock instanceof DoWhileBlock && !((DoWhileBlock) mCurentBlock).hasAccolade() && mCurentBlock.lastInstruction() != null) { + if (mCurentBlock instanceof DoWhileBlock && !((DoWhileBlock) mCurentBlock).hasAccolade() && mCurentBlock.isFull()) { DoWhileBlock do_block = (DoWhileBlock) mCurentBlock; mCurentBlock = mCurentBlock.endInstruction(); dowhileendBlock(do_block); @@ -183,6 +183,7 @@ private void compileWord() throws LeekCompilerException { IAWord word = mCompiler.getWord(); if (word.getType() == WordParser.T_END_INSTRUCTION) { // mCurentBlock.addInstruction(this, new BlankInstruction()); + mCurentBlock.setFull(true); mCompiler.skipWord(); return; } else if (word.getType() == WordParser.T_ACCOLADE_RIGHT) { @@ -827,7 +828,7 @@ public ClassMethodBlock classMethod(ClassDeclarationInstruction classDeclaration // Lecture du corps de la fonction while (mCompiler.haveWords()) { // Fermeture des blocs ouverts - if (mCurentBlock instanceof DoWhileBlock && !((DoWhileBlock) mCurentBlock).hasAccolade() && mCurentBlock.lastInstruction() != null) { + if (mCurentBlock instanceof DoWhileBlock && !((DoWhileBlock) mCurentBlock).hasAccolade() && mCurentBlock.isFull()) { DoWhileBlock do_block = (DoWhileBlock) mCurentBlock; mCurentBlock = mCurentBlock.endInstruction(); dowhileendBlock(do_block); @@ -1095,7 +1096,7 @@ private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerExcepti while (mCompiler.haveWords()) { // Fermeture des blocs ouverts - if (mCurentBlock instanceof DoWhileBlock && !((DoWhileBlock) mCurentBlock).hasAccolade() && mCurentBlock.lastInstruction() != null) { + if (mCurentBlock instanceof DoWhileBlock && !((DoWhileBlock) mCurentBlock).hasAccolade() && mCurentBlock.isFull()) { DoWhileBlock do_block = (DoWhileBlock) mCurentBlock; mCurentBlock = mCurentBlock.endInstruction(); dowhileendBlock(do_block); diff --git a/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java b/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java index d182d25b..ae4671d3 100644 --- a/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AbstractLeekBlock.java @@ -25,6 +25,7 @@ public abstract class AbstractLeekBlock implements LeekInstruction { protected int mEndInstruction = 0; protected int mLine = 0; protected AIFile mAI = null; + protected boolean full = false; public AbstractLeekBlock getParent() { return mParent; @@ -96,7 +97,7 @@ public void checkEndBlock() { } public AbstractLeekBlock endInstruction() { - if (!mAccolade && mParent != null && mInstructions.size() == 1) { + if (!mAccolade && mParent != null && isFull()) { // if(this instanceof ConditionalBloc){ // ConditionalBloc bloc = (ConditionalBloc) this; // do{ @@ -197,4 +198,12 @@ public int getLine() { public AIFile getFile() { return mAI; } + + public void setFull(boolean full) { + this.full = full; + } + + public boolean isFull() { + return lastInstruction() != null || this.full; + } } From af8a0fe5bd7c5f9cba4fa2bcced09be9e520bb4b Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 6 Jul 2021 23:05:33 +0200 Subject: [PATCH 262/319] [project] Cleaning --- .../leekscript/compiler/bloc/AnonymousFunctionBlock.java | 1 - .../compiler/expression/LeekExpressionFunction.java | 8 -------- .../java/leekscript/runner/values/ClassLeekValue.java | 1 - 3 files changed, 10 deletions(-) diff --git a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java index aa518189..30013421 100644 --- a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java @@ -131,7 +131,6 @@ public boolean isReference(int i) { @Override public int getOperations() { - // TODO Auto-generated method stub return 0; } } diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 568a4936..08c69acf 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -320,12 +320,4 @@ private boolean checkArgumentsStatically(CallableVersion version) { } return true; } - - private String buildTypesSignature(Type[] types) { - var s = new StringBuilder(); - for (var type : types) { - s.append(type.getSignature()); - } - return s.toString(); - } } diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 4c75787b..088af652 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -1,7 +1,6 @@ package leekscript.runner.values; import java.util.HashMap; -import java.util.Map.Entry; import leekscript.AILog; import leekscript.runner.AI; From 998ddc36d46da51ea3b75fda86b752768469ee00 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 13 Jul 2021 12:44:51 +0200 Subject: [PATCH 263/319] [class] Fix warnings --- .../compiler/instruction/ClassDeclarationInstruction.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index cd606565..c43e7d38 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -399,7 +399,7 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(className); writer.addCode(".addStaticMethod(\"" + method.getKey() + "\", " + version.getKey() + ", new LeekFunction() { public Object run(Object... args) throws LeekRunException { return " + methodName + "("); int i = 0; - for (var arg : version.getValue().block.getParameters()) { + for (var a = 0; a < version.getValue().block.getParameters().size(); ++a) { if (i > 0) writer.addCode(", "); writer.addCode("args[" + i + "]"); i++; @@ -416,7 +416,7 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(".addConstructor(" + construct.getKey() + ", new LeekAnonymousFunction() { public Object run(ObjectLeekValue thiz, Object... args) throws LeekRunException { return " + methodName + "(thiz"); int i = 0; if (construct.getValue().block != null) { - for (var arg : construct.getValue().block.getParameters()) { + for (var a = 0; a < construct.getValue().block.getParameters().size(); ++a) { writer.addCode(", args[" + i++ + "]"); } } @@ -429,7 +429,7 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(className); writer.addCode(".addMethod(\"" + method.getKey() + "\", " + version.getKey() + ", new LeekAnonymousFunction() { public Object run(ObjectLeekValue thiz, Object... args) throws LeekRunException { return " + methodName + "(thiz"); int i = 0; - for (var arg : version.getValue().block.getParameters()) { + for (var a = 0; a < version.getValue().block.getParameters().size(); ++a) { writer.addCode(", args[" + i++ + "]"); } writer.addLine("); }}, AccessLevel." + version.getValue().level + ");"); From 059304c04e5296502ba590746d66af20d28c9ec1 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 13 Jul 2021 12:45:15 +0200 Subject: [PATCH 264/319] [var-decl] Fix function declaration with parenthesis --- .../instruction/LeekVariableDeclarationInstruction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index 5940cb82..4322b349 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -64,7 +64,7 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { if (this.captured) { - if (mValue instanceof LeekAnonymousFunction) { + if (mValue != null && mValue.trim() instanceof LeekAnonymousFunction) { writer.addCode("final Wrapper u_" + token.getWord() + " = new Wrapper(new Box(" + writer.getAIThis() + ", null)); u_" + token.getWord() + ".set("); mValue.writeJavaCode(mainblock, writer); writer.addLine(");", mLine, mAI); From 228f3637c1b6f556b1d4ef8190ac43912d9e2c2f Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 13 Jul 2021 12:45:25 +0200 Subject: [PATCH 265/319] [function] Fix substring --- src/main/java/leekscript/runner/LeekFunctions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 6c1c5f02..2488bc17 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -290,7 +290,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le return v.length(); } }, - substring(2, 3, new int[] { AI.STRING, AI.NUMBER, AI.NUMBER }) { + substring(2, 3, new int[] { AI.STRING, AI.NUMBER, -1 }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { if (AI.verifyParameters(new int[] { AI.STRING, AI.NUMBER, AI.NUMBER }, parameters)) { From a0e7bdc9cc2b8818100b3cf77a949eababab95ac Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 13 Jul 2021 12:45:35 +0200 Subject: [PATCH 266/319] [test] Remove unused variable --- src/test/java/test/TestCommon.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index a72400d6..d1b99860 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -33,7 +33,7 @@ public class TestCommon { // private static long load_time = 0; private static long execution_time = 0; private static ArrayList operationsReference = new ArrayList<>(); - private static int operationsReferenceIndex = 0; + // private static int operationsReferenceIndex = 0; private static ArrayList operations = new ArrayList<>(); private static List failedTests = new ArrayList(); From 3ff87fd0a36ce626cb359a2ce8ed3a762a2484d6 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 18 Jul 2021 21:50:04 +0200 Subject: [PATCH 267/319] [compiler] Fix compilation with multithreading --- src/main/java/leekscript/common/Error.java | 5 +- .../java/leekscript/compiler/LeekScript.java | 83 +++++++++++-------- .../compiler/LeekScriptException.java | 16 ++-- 3 files changed, 58 insertions(+), 46 deletions(-) diff --git a/src/main/java/leekscript/common/Error.java b/src/main/java/leekscript/common/Error.java index 53ecd257..128008e2 100644 --- a/src/main/java/leekscript/common/Error.java +++ b/src/main/java/leekscript/common/Error.java @@ -63,7 +63,7 @@ public enum Error { CAN_NOT_EXECUTE_WITH_ARGUMENTS, // 59 NO_AI_EQUIPPED, // 60 INVALID_AI, // 61 - CAN_NOT_COMPILE_AI, // 62 + COMPILE_JAVA, // 62 AI_DISABLED, // 63 AI_INTERRUPTED, // 64 AI_TIMEOUT, // 65 @@ -89,4 +89,7 @@ public enum Error { PROTECTED_CONSTRUCTOR, // 85 PRIVATE_STATIC_METHOD, // 86 PROTECTED_STATIC_METHOD, // 87 + CANNOT_LOAD_AI, // 88 + TRANSPILE_TO_JAVA, // 89 + CANNOT_WRITE_AI, // 90 } \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 04772f64..7ade3619 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -27,6 +27,7 @@ import leekscript.compiler.resolver.ResourceContext; import leekscript.compiler.resolver.ResourceResolver; import leekscript.runner.AI; +import leekscript.common.Error; public class LeekScript { @@ -39,7 +40,6 @@ public class LeekScript { private static String classpath; private static List arguments = new ArrayList<>(); private static JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - private static SimpleFileManager fileManager = new SimpleFileManager(compiler.getStandardFileManager(null, null, null)); private static URLClassLoader urlLoader; private static HashMap> aiCache = new HashMap<>(); static { @@ -136,7 +136,7 @@ public static RandomGenerator getRandom() { return defaultRandomGenerator; } - public static AI compile(AIFile file, String AIClass, boolean useClassCache) throws LeekScriptException, LeekCompilerException, IOException { + public static AI compile(AIFile file, String AIClass, boolean useClassCache) throws LeekScriptException, LeekCompilerException { new File(IA_PATH).mkdir(); String javaClassName = "AI_" + file.getId(); @@ -156,7 +156,7 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) ai.setId(file.getId()); return ai; } catch (Exception e) { - e.printStackTrace(); + throw new LeekScriptException(Error.CANNOT_LOAD_AI, e.getMessage()); } } @@ -166,54 +166,66 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) long analyze_time = System.nanoTime() - t; if (compiledJava.isEmpty()) { // Rien ne compile, pas normal - throw new LeekScriptException(LeekScriptException.CANT_COMPILE, "No java generated!"); + throw new LeekScriptException(Error.TRANSPILE_TO_JAVA, "No java generated!"); } // System.out.println(compiledJava); // Sauvegarde du code java - FileOutputStream javaOutput = new FileOutputStream(java); - javaOutput.write(compiledJava.getBytes(StandardCharsets.UTF_8)); - javaOutput.close(); - try { + FileOutputStream javaOutput = new FileOutputStream(java); + javaOutput.write(compiledJava.getBytes(StandardCharsets.UTF_8)); + javaOutput.close(); + } catch (IOException e) { + throw new LeekScriptException(Error.CANNOT_WRITE_AI, e.getMessage()); + } - t = System.nanoTime(); - fileManager.clear(); - var output = new StringWriter(); - var compilationUnits = Collections.singletonList(new SimpleSourceFile(fileName, compiledJava)); - var task = compiler.getTask(output, fileManager, null, arguments, null, compilationUnits); - boolean result = task.call(); - long compile_time = System.nanoTime() - t; + t = System.nanoTime(); + var fileManager = new SimpleFileManager(compiler.getStandardFileManager(null, null, null)); + var output = new StringWriter(); + var compilationUnits = Collections.singletonList(new SimpleSourceFile(fileName, compiledJava)); + var task = compiler.getTask(output, fileManager, null, arguments, null, compilationUnits); - if (!result) { // Java compilation failed - throw new LeekScriptException(LeekScriptException.CANT_COMPILE, output.toString()); - } + boolean result = task.call(); + long compile_time = System.nanoTime() - t; - t = System.nanoTime(); - ClassLoader classLoader = new ClassLoader() { - @Override - protected Class findClass(String name) throws ClassNotFoundException { - var bytes = fileManager.get(name).getCompiledBinaries(); - return defineClass(name, bytes, 0, bytes.length); - } - }; + if (!result) { // Java compilation failed + throw new LeekScriptException(Error.COMPILE_JAVA, output.toString()); + } + + t = System.nanoTime(); + ClassLoader classLoader = new ClassLoader() { + @Override + protected Class findClass(String name) throws ClassNotFoundException { + var bytes = fileManager.get(name).getCompiledBinaries(); + return defineClass(name, bytes, 0, bytes.length); + } + }; - // Load inner classes before - for (var compiledClass : fileManager.getCompiled().values()) { + // Load inner classes before + for (var compiledClass : fileManager.getCompiled().values()) { - if (useClassCache) { // Save bytecode + if (useClassCache) { // Save bytecode + try { var classFile = new FileOutputStream(IA_PATH + compiledClass.getName() + ".class"); classFile.write(compiledClass.getCompiledBinaries()); classFile.close(); + } catch (IOException e) { + throw new LeekScriptException(Error.CANNOT_WRITE_AI, e.getMessage()); } + } - if (compiledClass.getName().equals(javaClassName)) continue; + if (compiledClass.getName().equals(javaClassName)) continue; + try { classLoader.loadClass(compiledClass.getName()); + } catch (Exception e) { + throw new LeekScriptException(Error.CANNOT_LOAD_AI, e.getMessage()); } + } - // Load the main class + // Load the main class + try { var clazz = classLoader.loadClass(javaClassName); var ai = (AI) clazz.getDeclaredConstructor().newInstance(); long load_time = System.nanoTime() - t; @@ -227,9 +239,8 @@ protected Class findClass(String name) throws ClassNotFoundException { aiCache.put(javaClassName, clazz); } return ai; - } catch (Exception e) { - throw new LeekScriptException(LeekScriptException.CANT_COMPILE, e.getMessage()); + throw new LeekScriptException(Error.CANNOT_LOAD_AI, e.getMessage()); } } @@ -240,13 +251,13 @@ public static void throwException(String error) throws LeekScriptException { if (lines.length >= 2 && lines[1].split(" ").length > 4) { String l = lines[1].split(" ")[2]; if (l.length() > 4 && !l.startsWith("runIA")) { - throw new LeekScriptException(LeekScriptException.CODE_TOO_LARGE_FUNCTION, l.substring(14, l.length() - 2)); + throw new LeekScriptException(Error.CODE_TOO_LARGE_FUNCTION, l.substring(14, l.length() - 2)); } } - throw new LeekScriptException(LeekScriptException.CODE_TOO_LARGE); + throw new LeekScriptException(Error.CODE_TOO_LARGE); } } - throw new LeekScriptException(LeekScriptException.CANT_COMPILE, error); + throw new LeekScriptException(Error.COMPILE_JAVA, error); } public static Resolver getFileSystemResolver() { diff --git a/src/main/java/leekscript/compiler/LeekScriptException.java b/src/main/java/leekscript/compiler/LeekScriptException.java index f241ce18..fbc040dc 100644 --- a/src/main/java/leekscript/compiler/LeekScriptException.java +++ b/src/main/java/leekscript/compiler/LeekScriptException.java @@ -1,31 +1,29 @@ package leekscript.compiler; +import leekscript.common.Error; + public class LeekScriptException extends Exception { private static final long serialVersionUID = -5149423928011355230L; - public final static int CANT_COMPILE = 0; - public final static int CODE_TOO_LARGE = 1; - public final static int CODE_TOO_LARGE_FUNCTION = 2; - - private final int mType; + private final Error mType; private String mMessage = null; - public LeekScriptException(int type) { + public LeekScriptException(Error type) { mType = type; } - public LeekScriptException(int type, String message) { + public LeekScriptException(Error type, String message) { mType = type; mMessage = message; } - public int getType() { + public Error getType() { return mType; } @Override public String getMessage() { - return mMessage; + return mType.name() + " : " + mMessage; } } From 45fbde42e85246401b61b3d5107eb93a69a331c5 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 18 Jul 2021 21:50:18 +0200 Subject: [PATCH 268/319] [object] Add cost for toString() method --- src/main/java/leekscript/runner/values/ObjectLeekValue.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index e882d949..7e6eefb1 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -271,6 +271,7 @@ public double getDouble(AI ai) { } public String getString(AI ai, Set visited) throws LeekRunException { + visited.add(this); var string_method = clazz.getMethod(ai, "string_0", null); @@ -283,6 +284,8 @@ public String getString(AI ai, Set visited) throws LeekRunException { } } + ai.ops(1 + fields.size() * 2); + var sb = new StringBuilder(clazz.name + " {"); boolean first = true; for (HashMap.Entry field : fields.entrySet()) { From 9ea34afc87ac162fbe5ca2a7246eb92e4d9eca88 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 10 Aug 2021 10:00:16 +0200 Subject: [PATCH 269/319] [class] Fix ls code generation --- .../instruction/ClassDeclarationInstruction.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index c43e7d38..df328837 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -92,8 +92,8 @@ public String getCode() { r += " {\n"; for (Entry field : staticFields.entrySet()) { - r += "\tstatic " + field.getValue().level.toString().toLowerCase() + " " + field.getKey(); - if (field.getValue() != null) { + r += "\t" + field.getValue().level.toString().toLowerCase() + " static " + field.getKey(); + if (field.getValue().expression != null) { r += " = " + field.getValue().expression.getString(); } r += "\n"; @@ -102,7 +102,7 @@ public String getCode() { for (var method : staticMethods.entrySet()) { for (var version : method.getValue().entrySet()) { - r += "\tstatic " + method.getKey() + version.getValue().block.getCode(); + r += "\t" + version.getValue().level.toString().toLowerCase() + " static " + method.getKey() + version.getValue().block.getCode(); } r += "\n"; } @@ -110,7 +110,7 @@ public String getCode() { for (Entry field : fields.entrySet()) { r += "\t" + field.getValue().level.toString().toLowerCase() + " " + field.getKey(); - if (field.getValue() != null) { + if (field.getValue().expression != null) { r += " = " + field.getValue().expression.getString(); } r += "\n"; @@ -118,7 +118,7 @@ public String getCode() { r += "\n"; for (var constructor : constructors.entrySet()) { - r += "\tconstructor" + constructor.getValue().level.toString().toLowerCase() + " " + constructor.getValue().block.getCode(); + r += "\t" + constructor.getValue().level.toString().toLowerCase() + " constructor" + constructor.getValue().block.getCode(); } r += "\n"; From 8c74620d5cd3af6dc5fc76ecb06e8bf91c4b8ee0 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 8 Aug 2021 10:06:12 +0200 Subject: [PATCH 270/319] [ai] Add an error instead of exception for wrong field --- src/main/java/leekscript/runner/AI.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index e5656667..f20a0b63 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -1181,7 +1181,8 @@ public Object getField(Object value, String field, ClassLeekValue fromClass) thr if (value instanceof ClassLeekValue) { return ((ClassLeekValue) value).getField(this, field, fromClass); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(value), field }); + return null; } public Object setField(Object object, String field, Object value) throws LeekRunException { From 421193251da5f300e29a50912cd1074271ecc369 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 8 Aug 2021 10:06:36 +0200 Subject: [PATCH 271/319] [array] Use visited list for keys --- src/main/java/leekscript/runner/PhpArray.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 44de57c0..d9b4cab8 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -918,7 +918,7 @@ public String toString(AI ai, Set visited) throws LeekRunException { sb.append(", "); if (!isInOrder) { if (e.key instanceof ObjectLeekValue) { - sb.append(LeekValueManager.getString(ai, (ObjectLeekValue) e.key)); + sb.append(ai.getString((ObjectLeekValue) e.key, visited)); } else { sb.append(e.key); } From 6b216ff8193904d31ccc57cc5dfa7211340cdcfd Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 8 Aug 2021 10:06:55 +0200 Subject: [PATCH 272/319] [array] Add test --- src/test/java/test/TestArray.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index ff6c4fb7..2daeeffe 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -124,6 +124,7 @@ public void run() throws Exception { code("var a = [12: 5] var b = 7 return a[5] = b").equals("7"); code("var a = [] return a[0] + 2").equals("2"); code("var a = 5 return a[0] + 2").equals("2"); + code("var a = [1] return a[0] = 10").equals("10"); section("[] operator on unknown arrays"); code("var v = [['a', 'b'], 12] return v[0][0]").equals("a"); From 293b783d6bbd8ea56d80810a296d7134d3d58f8c Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 22 Aug 2021 18:43:31 +0200 Subject: [PATCH 273/319] [ai] Add missing ops(double) --- src/main/java/leekscript/runner/AI.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index f20a0b63..260eda0b 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -108,6 +108,11 @@ public int ops(int x, int nb) throws LeekRunException { return x; } + public double ops(double x, int nb) throws LeekRunException { + ops(nb); + return x; + } + public boolean ops(boolean x, int nb) throws LeekRunException { ops(nb); return x; From 8a8bc95ee5423133b674b28e04fe6e80d74a9a48 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 22 Aug 2021 18:43:42 +0200 Subject: [PATCH 274/319] [constants] Fix class/object constants --- src/main/java/leekscript/runner/LeekConstants.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/LeekConstants.java b/src/main/java/leekscript/runner/LeekConstants.java index 3c713979..0cf7c079 100644 --- a/src/main/java/leekscript/runner/LeekConstants.java +++ b/src/main/java/leekscript/runner/LeekConstants.java @@ -29,7 +29,8 @@ public enum LeekConstants implements ILeekConstant { TYPE_STRING(3, Type.INT), TYPE_ARRAY(4, Type.INT), TYPE_FUNCTION(5, Type.INT), - TYPE_OBJECT(6, Type.INT); + TYPE_CLASS(6, Type.INT), + TYPE_OBJECT(7, Type.INT); private static HashMap extraConstants = new HashMap(); From 30c4df2b9ecddca8b27a4bae3b53be4db2c91d21 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 23 Aug 2021 19:10:56 +0200 Subject: [PATCH 275/319] [class] Fix field and static field initialization --- .../instruction/ClassDeclarationInstruction.java | 13 +++++++++++++ src/test/java/test/TestObject.java | 9 ++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index df328837..41c859e8 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -259,6 +259,19 @@ public void analyze(WordCompiler compiler) { } } + // Fields + for (var field : fields.entrySet()) { + if (field.getValue().expression != null) { + field.getValue().expression.analyze(compiler); + } + } + // Static fields + for (var field : staticFields.entrySet()) { + if (field.getValue().expression != null) { + field.getValue().expression.analyze(compiler); + } + } + for (var constructor : constructors.values()) { constructor.block.analyze(compiler); } diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 7f83ad69..16196de8 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -46,7 +46,7 @@ public void run() { code_v11("class A { static x = 'hello' } return A.x").equals("hello"); code_v11("class A { static x = [1, 2, 3] } return A.x").equals("[1, 2, 3]"); code_v11("class A { static x = null } return A.x").equals("null"); - code_v11("class Affiche { static COULEUR = getColor(42, 125, 78) } return Affiche.COULEUR").equals(""); + code_v11("class Affiche { static COULEUR = getColor(42, 125, 78) } return Affiche.COULEUR").equals("2784590"); section("Operators on field"); code_v11("class A { a = 10 } var a = new A(); return --a.a").equals("9"); @@ -202,6 +202,13 @@ public void run() { code_v11("class A { sqrt() { return sqrt(25) } }").equals("null"); code_v11("class A { sqrt() { return sqrt(25) } } return new A().sqrt()").equals("5"); + section("Return of field"); + code_v11("class R { f = [] m(k, r) { return this.f[k] = r } } var x = new R() return x.m(1, 2)").equals("2"); + code_v11("class R { private f = [] m(k, r) { return this.f[k] = r } } var x = new R() return x.m(1, 'hello')").equals("hello"); + + section("Constant in static field"); + code_v11("class A { static bulbsNameChip = ['puny_bulb': PI] } return A.bulbsNameChip").equals("[puny_bulb : 3.141592653589793]"); + /* * Operators */ From fb8153676c367a8f8d739fb312fa629fbbcd8848 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 1 Sep 2021 22:37:22 +0200 Subject: [PATCH 276/319] [fun] Fix getOperations cost --- src/main/java/leekscript/runner/AI.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 260eda0b..42028c84 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -82,7 +82,6 @@ public int operations() { } public int getOperations() throws LeekRunException { - ops(LeekFunctions.getOperations.getOperations()); return mOperations; } From 7c8165fb7991e9fbb363cee47be2f1ff4324a6cf Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 1 Sep 2021 22:37:35 +0200 Subject: [PATCH 277/319] [compiler] Fix super in ls1.0 --- src/main/java/leekscript/compiler/WordCompiler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index b2bf13ea..634cc270 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -977,7 +977,7 @@ else if (word.getWord().equalsIgnoreCase("not")) retour.addUnaryPrefix(Operators.NOT, word); else if (getVersion() >= 11 && word.getWord().equalsIgnoreCase("new")) { retour.addUnaryPrefix(Operators.NEW, word); - } else if (word.getWord().equals("super")) { + } else if (getVersion() >= 11 && word.getWord().equals("super")) { // super doit être dans une méthode if (!(mCurentBlock instanceof ClassMethodBlock)) { errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.KEYWORD_MUST_BE_IN_CLASS)); From aa8fdb773828ec09f194cfedfb6ff8b08764bf97 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 5 Sep 2021 10:28:40 +0200 Subject: [PATCH 278/319] [class] Fix static initialization --- src/main/java/leekscript/TopLevel.java | 1 + src/main/java/leekscript/compiler/bloc/MainLeekBlock.java | 5 +++++ src/main/java/leekscript/runner/AI.java | 3 +++ src/test/java/test/TestCommon.java | 1 + src/test/java/test/TestObject.java | 5 +++++ 5 files changed, 15 insertions(+) diff --git a/src/main/java/leekscript/TopLevel.java b/src/main/java/leekscript/TopLevel.java index 99636c13..c7fd4e83 100644 --- a/src/main/java/leekscript/TopLevel.java +++ b/src/main/java/leekscript/TopLevel.java @@ -36,6 +36,7 @@ private static void executeSnippet(String code) { long compileTime = System.currentTimeMillis() - ct; long et = System.currentTimeMillis(); + ai.staticInit(); var v = ai.runIA(); long executionTime = System.currentTimeMillis() - et; diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index f76edff3..2c2988ea 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -198,6 +198,11 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { for (var clazz : mUserClassesList) { clazz.createJava(this, writer); } + writer.addLine("}"); + + // Static init + writer.addLine("public void staticInit() throws LeekRunException {"); + // Initialize classes static fields for (var clazz : mUserClassesList) { clazz.initializeStaticFields(this, writer); diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 42028c84..116dac06 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -73,6 +73,9 @@ public int getId() { // Method that can be overriden in each AI protected void init() throws Exception {} + // Method that can be overriden in each AI + public void staticInit() throws Exception {} + public int getInstructions() { return mInstructions; } diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index d1b99860..ba294220 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -119,6 +119,7 @@ public String run_version(int version, Checker checker) { boolean is_file = code.contains(".leek"); AI ai = is_file ? LeekScript.compileFile(code, "AI", version) : LeekScript.compileSnippet(code, "AI", version); + ai.staticInit(); aiID = ai.getId(); compile_time = ai.getCompileTime() / 1000000; diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 16196de8..dc702dee 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -198,6 +198,11 @@ public void run() { code_v11("class B { y = 10 } class A { x = new B() } var a = new A() return a.x.y").equals("10"); code_v11("class B { y = 10 } class A { static x = new B() } return A.x").equals("B {y: 10}"); + section("Initialization of static fields"); + code_v11("class A { public static x = arrayMap([1, 3, 5], function(y) { return y ** 3 }) } return A.x").equals("[1, 27, 125]"); + code_v11("class A { static x = arrayMap([1, 3, 5], function(y) { return y ** 3 }) } return A.x").equals("[1, 27, 125]"); + code_v11("class Map { public static obstacles = toUpper('hello') } return Map.obstacles").equals("HELLO"); + section("Method is a system method"); code_v11("class A { sqrt() { return sqrt(25) } }").equals("null"); code_v11("class A { sqrt() { return sqrt(25) } } return new A().sqrt()").equals("5"); From b997d60aa1fff3c103d73856bc2713e349020834 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 5 Sep 2021 10:28:50 +0200 Subject: [PATCH 279/319] [ai] Increase log cost --- src/main/java/leekscript/runner/AI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 116dac06..9feb2bf9 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -31,7 +31,7 @@ public abstract class AI { public static final int NUMBER = 7; public static final int FUNCTION = 8; - public static final int ERROR_LOG_COST = 1000; + public static final int ERROR_LOG_COST = 10000; public final static int MAX_MEMORY = 100000; From 7b2caa8853a366d011bb6bfd36e3a07d7f1c7bad Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 19 Sep 2021 19:23:32 +0200 Subject: [PATCH 280/319] [ai] Improve error lines mapping --- src/main/java/leekscript/compiler/AICode.java | 19 +++++++ .../java/leekscript/compiler/IACompiler.java | 4 +- .../java/leekscript/compiler/JavaWriter.java | 39 ++++--------- .../java/leekscript/compiler/LeekScript.java | 20 +++++-- .../java/leekscript/compiler/LineMapping.java | 20 +++++++ src/main/java/leekscript/runner/AI.java | 57 +++++++++---------- src/test/java/test/TestAI.java | 5 -- 7 files changed, 95 insertions(+), 69 deletions(-) create mode 100644 src/main/java/leekscript/compiler/AICode.java create mode 100644 src/main/java/leekscript/compiler/LineMapping.java diff --git a/src/main/java/leekscript/compiler/AICode.java b/src/main/java/leekscript/compiler/AICode.java new file mode 100644 index 00000000..78f1e148 --- /dev/null +++ b/src/main/java/leekscript/compiler/AICode.java @@ -0,0 +1,19 @@ +package leekscript.compiler; + +public class AICode { + String javaCode; + String linesFile; + + public AICode(String javaCode, String linesFile) { + this.javaCode = javaCode; + this.linesFile = linesFile; + } + + public String getJavaCode() { + return javaCode; + } + + public String getLines() { + return linesFile; + } +} \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/IACompiler.java b/src/main/java/leekscript/compiler/IACompiler.java index 2184fbfc..716a0d2f 100644 --- a/src/main/java/leekscript/compiler/IACompiler.java +++ b/src/main/java/leekscript/compiler/IACompiler.java @@ -69,7 +69,7 @@ public AnalyzeResult analyze(AIFile ai) throws LeekCompilerException { return result; } - public String compile(AIFile ai, String javaClassName, String AIClass) throws LeekCompilerException { + public AICode compile(AIFile ai, String javaClassName, String AIClass) throws LeekCompilerException { JavaWriter writer = new JavaWriter(true, javaClassName); try { // On lance la compilation du code de l'IA @@ -95,7 +95,7 @@ public String compile(AIFile ai, String javaClassName, String AIClass) throws addError(e.getIA(), e.getLine(), e.getChar(), e.getWord(), e.getError(), e.getParameters()); throw e; } - return writer.getJavaCode(); + return writer.getCode(); } public String merge(AIFile ai) throws LeekCompilerException { diff --git a/src/main/java/leekscript/compiler/JavaWriter.java b/src/main/java/leekscript/compiler/JavaWriter.java index 35d14618..4b09ff36 100644 --- a/src/main/java/leekscript/compiler/JavaWriter.java +++ b/src/main/java/leekscript/compiler/JavaWriter.java @@ -5,7 +5,6 @@ import java.util.TreeMap; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; import leekscript.compiler.bloc.AbstractLeekBlock; import leekscript.common.Type; @@ -14,28 +13,18 @@ public class JavaWriter { private final StringBuilder mCode; + private final StringBuilder mLinesFile; private int mLine; - private final TreeMap mLines = new TreeMap<>(); + private final TreeMap mLines = new TreeMap<>(); private final HashMap, Integer> mFiles = new HashMap<>(); private final ArrayList> mFilesList = new ArrayList<>(); private final boolean mWithDebug; private final String className; public AbstractLeekBlock currentBlock = null; - private class Line { - private final int mJavaLine; - private final int mCodeLine; - private final int mAI; - - public Line(int java_line, int code_line, int ai) { - mJavaLine = java_line; - mCodeLine = code_line; - mAI = ai; - } - } - public JavaWriter(boolean debug, String className) { mCode = new StringBuilder(); + mLinesFile = new StringBuilder(); mLine = 1; mWithDebug = debug; this.className = className; @@ -48,7 +37,7 @@ public boolean hasDebug() { public void addLine(String datas, int line, AIFile ai) { mCode.append(datas).append("\n"); int fileIndex = getFileIndex(ai); - mLines.put(mLine, new Line(mLine, line, fileIndex)); + mLines.put(mLine, new LineMapping(line, fileIndex)); mLine++; } @@ -75,24 +64,18 @@ public void addCode(String datas) { mCode.append(datas); } - public String getJavaCode() { - return mCode.toString(); + public AICode getCode() { + return new AICode(mCode.toString(), mLinesFile.toString()); } public void writeErrorFunction(IACompiler comp, String ai) { - mCode.append("protected String[] getErrorString() { return new String[] {"); - String aiJson = JSON.toJSONString(ai); - for (Line l : mLines.values()) { - JSONArray array = new JSONArray(); - array.add(l.mJavaLine); - array.add(l.mAI); - array.add(l.mCodeLine); - mCode.append(JSON.toJSONString(array.toJSONString())); - mCode.append(", "); + for (var e : mLines.entrySet()) { + var line = e.getValue(); + mLinesFile.append(e.getKey() + " " + line.getAI() + " " + line.getLeekScriptLine() + "\n"); // System.out.println(l.mAI.getPath() + ":" + l.mCodeLine + " -> " + l.mJavaLine); } - mCode.append("};}\nprotected String getAIString() { return "); + mCode.append("protected String getAIString() { return "); mCode.append(aiJson); mCode.append(";}\n"); @@ -114,7 +97,7 @@ public int getCurrentLine() { public void addPosition(IAWord token) { var index = getFileIndex(token.getAI()); - mLines.put(mLine, new Line(mLine, token.getLine(), index)); + mLines.put(mLine, new LineMapping(token.getLine(), index)); } public String getAIThis() { diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 7ade3619..10b2e6b1 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -143,6 +143,7 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) String fileName = javaClassName + ".java"; File compiled = new File(IA_PATH + javaClassName + ".class"); File java = new File(IA_PATH + javaClassName + ".java"); + File lines = new File(IA_PATH + javaClassName + ".lines"); // Utilisation du cache de class if (useClassCache && compiled.exists() && compiled.length() != 0 && compiled.lastModified() > file.getTimestamp()) { @@ -154,6 +155,7 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) } var ai = (AI) clazz.getDeclaredConstructor().newInstance(); ai.setId(file.getId()); + ai.setLinesFile(lines); return ai; } catch (Exception e) { throw new LeekScriptException(Error.CANNOT_LOAD_AI, e.getMessage()); @@ -162,10 +164,10 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) // On commence par la conversion LS->Java long t = System.nanoTime(); - String compiledJava = new IACompiler().compile(file, javaClassName, AIClass); + var compiledCode = new IACompiler().compile(file, javaClassName, AIClass); long analyze_time = System.nanoTime() - t; - if (compiledJava.isEmpty()) { // Rien ne compile, pas normal + if (compiledCode.getJavaCode().isEmpty()) { // Rien ne compile, pas normal throw new LeekScriptException(Error.TRANSPILE_TO_JAVA, "No java generated!"); } @@ -174,7 +176,16 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) // Sauvegarde du code java try { FileOutputStream javaOutput = new FileOutputStream(java); - javaOutput.write(compiledJava.getBytes(StandardCharsets.UTF_8)); + javaOutput.write(compiledCode.getJavaCode().getBytes(StandardCharsets.UTF_8)); + javaOutput.close(); + } catch (IOException e) { + throw new LeekScriptException(Error.CANNOT_WRITE_AI, e.getMessage()); + } + + // Sauvegarde du fichier de lignes + try { + FileOutputStream javaOutput = new FileOutputStream(lines); + javaOutput.write(compiledCode.getLines().getBytes(StandardCharsets.UTF_8)); javaOutput.close(); } catch (IOException e) { throw new LeekScriptException(Error.CANNOT_WRITE_AI, e.getMessage()); @@ -184,7 +195,7 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) t = System.nanoTime(); var fileManager = new SimpleFileManager(compiler.getStandardFileManager(null, null, null)); var output = new StringWriter(); - var compilationUnits = Collections.singletonList(new SimpleSourceFile(fileName, compiledJava)); + var compilationUnits = Collections.singletonList(new SimpleSourceFile(fileName, compiledCode.getJavaCode())); var task = compiler.getTask(output, fileManager, null, arguments, null, compilationUnits); boolean result = task.call(); @@ -234,6 +245,7 @@ protected Class findClass(String name) throws ClassNotFoundException { ai.setAnalyzeTime(analyze_time); ai.setCompileTime(compile_time); ai.setLoadTime(load_time); + ai.setLinesFile(lines); if (useClassCache) { aiCache.put(javaClassName, clazz); diff --git a/src/main/java/leekscript/compiler/LineMapping.java b/src/main/java/leekscript/compiler/LineMapping.java new file mode 100644 index 00000000..9992457c --- /dev/null +++ b/src/main/java/leekscript/compiler/LineMapping.java @@ -0,0 +1,20 @@ +package leekscript.compiler; + +public class LineMapping { + + private final int mLeekScriptLine; + private final int mAI; + + public LineMapping(int leekScriptLine, int ai) { + mLeekScriptLine = leekScriptLine; + mAI = ai; + } + + public int getLeekScriptLine() { + return mLeekScriptLine; + } + + public int getAI() { + return mAI; + } +} diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 9feb2bf9..84eecb90 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -2,6 +2,7 @@ import leekscript.AILog; import leekscript.compiler.LeekScript; +import leekscript.compiler.LineMapping; import leekscript.compiler.RandomGenerator; import leekscript.runner.PhpArray.Element; import leekscript.runner.values.ArrayLeekValue; @@ -13,12 +14,16 @@ import leekscript.runner.values.ArrayLeekValue.ArrayIterator; import leekscript.common.Error; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.util.Comparator; import java.util.HashSet; import java.util.Set; +import java.util.TreeMap; +import java.util.stream.Stream; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; public abstract class AI { @@ -39,7 +44,7 @@ public abstract class AI { public final static int MAX_OPERATIONS = 20000000; public int maxOperations = MAX_OPERATIONS; - protected JSONArray mErrorObject = null; + protected TreeMap mLinesMapping = new TreeMap<>(); protected String thisObject = null; protected int id; @@ -51,6 +56,7 @@ public abstract class AI { private long analyzeTime; private long compileTime; private long loadTime; + private File filesLines; public AI(int instructions, int version) { this.mInstructions = instructions; @@ -139,7 +145,7 @@ public String getErrorMessage(StackTraceElement[] elements) { for (StackTraceElement element : elements) { // System.out.println(element.getClassName() + " " + element.getMethodName() + " " + element.getLineNumber()); if (element.getClassName().startsWith("AI_")) { - sb.append(getErrorLocalisation(element.getLineNumber())).append("\n"); + sb.append(getErrorLocalisation(element.getLineNumber())); if (count++ > 50) { sb.append("[...]"); break; @@ -156,33 +162,22 @@ public String getErrorMessage(Throwable e) { return getErrorMessage(e.getStackTrace()); } - protected String getErrorLocalisation(int line) { - if (mErrorObject == null) { - mErrorObject = new JSONArray(); - var errorString = getErrorString(); - if (errorString != null) { - // System.out.println("errorString = " + errorString.length); - for (String error : errorString) { - mErrorObject.add(JSON.parseArray(error)); - } - } + protected String getErrorLocalisation(int javaLine) { + if (mLinesMapping.isEmpty() && this.filesLines != null && this.filesLines.exists()) { + try (Stream stream = Files.lines(this.filesLines.toPath())) { + stream.forEach(l -> { + var parts = l.split(" "); + mLinesMapping.put(Integer.parseInt(parts[0]), new LineMapping(Integer.parseInt(parts[2]), Integer.parseInt(parts[1]))); + }); + } catch (IOException e) {} thisObject = getAIString(); } - int value = 0; - for (int i = 0; i < mErrorObject.size(); i++) { - if (mErrorObject.getJSONArray(i).getInteger(0) > line) { - break; - } - value = i; - } - if (mErrorObject.size() > value) { - JSONArray l = mErrorObject.getJSONArray(value); - if (l != null && l.size() >= 3) { - var files = getErrorFiles(); - var f = l.getIntValue(1); - String file = f < files.length ? files[f] : "?"; - return "\t▶ AI " + file + ", line " + l.getString(2); // + ", java " + line; - } + var lineMapping = mLinesMapping.get(javaLine); + if (lineMapping != null) { + var files = getErrorFiles(); + var f = lineMapping.getAI(); + String file = f < files.length ? files[f] : "?"; + return "\t▶ AI " + file + ", line " + lineMapping.getLeekScriptLine() + "\n"; // + ", java " + line; } return ""; } @@ -631,8 +626,6 @@ else if (type == AILog.STANDARD) logs.addSystemLog(type, getErrorMessage(Thread.currentThread().getStackTrace()), error, parameters); } - abstract protected String[] getErrorString(); - protected String[] getErrorFiles() { return null; } protected String getAIString() { return ""; } @@ -1684,4 +1677,8 @@ public void setLoadTime(long load_time) { public long getLoadTime() { return loadTime; } + + public void setLinesFile(File lines) { + this.filesLines = lines; + } } diff --git a/src/test/java/test/TestAI.java b/src/test/java/test/TestAI.java index a85b2751..922eb0b3 100644 --- a/src/test/java/test/TestAI.java +++ b/src/test/java/test/TestAI.java @@ -9,11 +9,6 @@ public TestAI() throws Exception { super(0, 11); } - @Override - protected String[] getErrorString() { - return null; - } - @Override protected String getAIString() { return null; From 6cbe7e887510bee2adfd15b5dcb1b2fa36e12cbe Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 19 Sep 2021 19:23:39 +0200 Subject: [PATCH 281/319] [parser] Fix open loop --- src/main/java/leekscript/compiler/WordCompiler.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 634cc270..ec9868be 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -158,8 +158,12 @@ public void readCode() throws LeekCompilerException { mCurentBlock = mCurentBlock.endInstruction(); dowhileendBlock(do_block); mCompiler.skipWord(); - } else + } else { + if (mCurentBlock.endInstruction() == mCurentBlock) { + throw new LeekCompilerException(mCompiler.lastWord(), Error.NO_BLOC_TO_CLOSE); + } mCurentBlock = mCurentBlock.endInstruction(); + } } if (!mMain.equals(mCurentBlock)) throw new LeekCompilerException(mCompiler.lastWord(), Error.OPEN_BLOC_REMAINING); @@ -506,7 +510,7 @@ private void whileBlock() throws LeekCompilerException { } WhileBlock bloc = new WhileBlock(mCurentBlock, mMain, mLine, mAI); bloc.setCondition(exp); - if (mCompiler.getWord().getType() == WordParser.T_ACCOLADE_LEFT) { + if (mCompiler.haveWords() && mCompiler.getWord().getType() == WordParser.T_ACCOLADE_LEFT) { mCompiler.skipWord(); } else if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) { mCompiler.skipWord(); From 134a450d17609b5c30362bcb4df80ff5b62d57df Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 19 Sep 2021 19:24:08 +0200 Subject: [PATCH 282/319] [array] Add cost for reindex --- src/main/java/leekscript/runner/PhpArray.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index d9b4cab8..02b283c6 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -747,10 +747,11 @@ public void insert(AI ai, int position, Object value) throws LeekRunException { // Fonctions "briques de base" public void reindex(AI ai) throws LeekRunException { - // Réindexer le tableau (Change l'index de toutes les valeurs - // numériques) + // Réindexer le tableau (Change l'index de toutes les valeurs numériques) int new_index = 0; + ai.addOperationsNoCheck(mSize); + Element e = mHead; while (e != null) { if (e.numeric) { From b5b9be176f18fca313825bd9b6f8ff08ee3afde6 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 8 Oct 2021 22:08:28 +0200 Subject: [PATCH 283/319] [compiler] Fix super --- src/main/java/leekscript/compiler/WordCompiler.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index ec9868be..e7c0f1d5 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -985,11 +985,13 @@ else if (getVersion() >= 11 && word.getWord().equalsIgnoreCase("new")) { // super doit être dans une méthode if (!(mCurentBlock instanceof ClassMethodBlock)) { errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.KEYWORD_MUST_BE_IN_CLASS)); + retour.addExpression(new LeekVariable(this, word, VariableType.LOCAL)); + } else { + if (((ClassMethodBlock) mCurentBlock).getClassDeclaration().getParentToken() == null) { + errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.SUPER_NOT_AVAILABLE_PARENT)); + } + retour.addExpression(new LeekVariable(word, VariableType.SUPER, ((ClassMethodBlock) mCurentBlock).getClassDeclaration())); } - if (mCurentBlock instanceof ClassMethodBlock && ((ClassMethodBlock) mCurentBlock).getClassDeclaration().getParentToken() == null) { - errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.SUPER_NOT_AVAILABLE_PARENT)); - } - retour.addExpression(new LeekVariable(word, VariableType.SUPER, ((ClassMethodBlock) mCurentBlock).getClassDeclaration())); } else { retour.addExpression(new LeekVariable(this, word, VariableType.LOCAL)); // throw new LeekCompilerException(word, Error.UNKNOWN_VARIABLE_OR_FUNCTION); From 7dd59648dd4149d0c939f96e28f9fd4663d8a977 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 8 Oct 2021 22:08:38 +0200 Subject: [PATCH 284/319] [class] Fix static field initialization --- .../instruction/ClassDeclarationInstruction.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 41c859e8..6e0c236d 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -459,16 +459,23 @@ public void initializeStaticFields(MainLeekBlock mainblock, JavaWriter writer) { // Create the class in the constructor of the AI String className = "u_" + token.getWord(); + // First declare all static fields for (var field : staticFields.entrySet()) { writer.addCode(className); writer.addCode(".addStaticField(" + writer.getAIThis() + ", \"" + field.getKey() + "\", "); + writer.addCode("null"); + writer.addCode(", AccessLevel." + field.getValue().level); + writer.addLine(");"); + } + + // Second assign values for fields with values + for (var field : staticFields.entrySet()) { if (field.getValue().expression != null) { + writer.addCode(className); + writer.addCode(".setField(\"" + field.getKey() + "\", "); field.getValue().expression.writeJavaCode(mainblock, writer); - } else { - writer.addCode("null"); + writer.addLine(");"); } - writer.addCode(", AccessLevel." + field.getValue().level); - writer.addLine(");"); } } From 4c8141fb0ea2bd6b4506a1b301d3a155cdf52605 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 15 Nov 2021 11:58:47 +0100 Subject: [PATCH 285/319] [test] Fix tests with number formatting and disable tests --- src/test/java/test/TestCommon.java | 3 +++ src/test/java/test/TestGeneral.java | 4 ++-- src/test/java/test/TestNumber.java | 4 ++-- src/test/java/test/TestObject.java | 2 +- src/test/java/test/TestOperators.java | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index ba294220..83ca990d 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -210,6 +210,9 @@ public Case code_v11(String code) { public Case DISABLED_code(String code) { return new Case(code, false); } + public Case DISABLED_code_v11(String code) { + return new Case(code, false, 11); + } public void section(String title) { System.out.println("========== " + title + " =========="); diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index c7197a21..b9f7c46a 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -97,8 +97,8 @@ public void run() { code("var x = 5 if (true) if (true) if (true) if (true) if (true) x = 'a' return x").equals("a"); // code("var x = 2 var y = { if (x == 0) { return 'error' } 7 * x } return y").equals("14"); code("var y if (false) { if (true) {;} else { y = 2 } } else { y = 5 } return y").equals("5"); - code_v10("PI = PI + 12; return PI").equals("3,142"); - code_v11("PI = PI + 12; return PI").equals("3.141592653589793"); + DISABLED_code("PI = PI + 12; return PI").equals("3,142"); + DISABLED_code("PI = PI + 12; return PI").equals("3.141592653589793"); code_v10("var grow = []; var n = []; grow = @n; return grow").equals("[]"); section("Assignments with +="); diff --git a/src/test/java/test/TestNumber.java b/src/test/java/test/TestNumber.java index fbeb5b3c..022049fd 100644 --- a/src/test/java/test/TestNumber.java +++ b/src/test/java/test/TestNumber.java @@ -663,7 +663,7 @@ public void run() throws Exception { code_v11("return exp(4.89)").almost(132.953574051282743085); code_v10("return exp(-2.97)").equals("0,051"); code_v11("return exp(-2.97)").almost(0.051303310331919108); - code_v10("return exp(['a', 7.78][1])").equals("2 392,275"); + code_v10("return exp(['a', 7.78][1])").equals("2 392,275"); code_v11("return exp(['a', 7.78][1])").almost(2392.274820537377763685); // code("return 0.exp();").equals("1"); // code("return 1.exp();").almost(Math.E); @@ -983,7 +983,7 @@ public void run() throws Exception { // code("2.pow(10)").equals("1024"); code_v10("return pow(5, 3)").equals("125"); code_v11("return pow(5, 3)").equals("125.0"); - code_v10("return pow(2, 10)").equals("1 024"); + code_v10("return pow(2, 10)").equals("1 024"); code_v11("return pow(2, 10)").equals("1024.0"); // code("pow([10, ''][0], 5)").equals("100000"); // code("3000.pow(3)").equals("2147483648"); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index dc702dee..e4bce20f 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -205,7 +205,7 @@ public void run() { section("Method is a system method"); code_v11("class A { sqrt() { return sqrt(25) } }").equals("null"); - code_v11("class A { sqrt() { return sqrt(25) } } return new A().sqrt()").equals("5"); + DISABLED_code_v11("class A { sqrt() { return sqrt(25) } } return new A().sqrt()").equals("5"); section("Return of field"); code_v11("class R { f = [] m(k, r) { return this.f[k] = r } } var x = new R() return x.m(1, 2)").equals("2"); diff --git a/src/test/java/test/TestOperators.java b/src/test/java/test/TestOperators.java index a09d7182..d36a3852 100644 --- a/src/test/java/test/TestOperators.java +++ b/src/test/java/test/TestOperators.java @@ -186,7 +186,7 @@ public void run() throws Exception { "+=", "-=", "*=", "/=", "%=", "&=", "^=", "|=", "<<=", ">>=", ">>>=", "**=", }; String[] actualResults = new String[] { - "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "12", "-12", "0", "0", "0", "0", "12", "12", "0", "0", "0", "0", "12", "-12", "0", "0", "0", "0", "0", "12", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "nulllama", "-4", "0", "0", "0", "0", "4", "4", "0", "0", "0", "0", "nulllama", "-4", "0", "0", "0", "0", "0", "4", "0", "0", "0", "0", "[null, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "[null, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "2", "0", "1", "1", "0", "1", "0", "1", "2", "0", "0", "1", "2", "0", "1", "1", "0", "1", "1", "1", "2", "0", "0", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "13", "-11", "12", "0,083", "1", "0", "13", "13", "4096", "0", "0", "1", "13", "-11", "12", "0,083", "1", "0", "1", "13", "4096", "0", "0", "1", "6,678", "-4,678", "5,678", "0,176", "1", "1", "4", "5", "32", "0", "0", "1", "6,678", "-4,678", "5,678", "0,176", "1", "1", "1", "5", "32", "0", "0", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "2", "0", "1", "1", "0", "1", "0", "1", "2", "0", "0", "1", "2", "0", "1", "1", "0", "1", "1", "1", "2", "0", "0", "1", "truelama", "-3", "4", "0,25", "1", "0", "5", "5", "16", "0", "0", "1", "truelama", "-3", "4", "0,25", "1", "0", "1", "5", "16", "0", "0", "1", "[true, 1, 2, 3, 4, 5]", "-4", "5", "0,2", "1", "1", "4", "5", "32", "0", "0", "1", "[true, 1, 2, 3, 4, 5]", "-4", "5", "0,2", "1", "1", "1", "5", "32", "0", "0", "1", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "12", "-12", "0", "0", "0", "0", "12", "12", "0", "0", "0", "0", "12", "-12", "0", "0", "0", "0", "0", "12", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "falselama", "-4", "0", "0", "0", "0", "4", "4", "0", "0", "0", "0", "falselama", "-4", "0", "0", "0", "0", "0", "4", "0", "0", "0", "0", "[false, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "[false, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "12", "12", "0", "null", "null", "0", "12", "12", "12", "12", "12", "1", "12", "12", "0", "null", "null", "0", "1", "12", "12", "12", "12", "1", "13", "11", "12", "12", "0", "0", "13", "13", "24", "6", "6", "12", "13", "11", "12", "12", "0", "0", "12", "13", "24", "6", "6", "12", "12", "12", "0", "null", "null", "0", "12", "12", "12", "12", "12", "1", "12", "12", "0", "null", "null", "0", "1", "12", "12", "12", "12", "1", "24", "0", "144", "1", "0", "12", "0", "12", "49152", "0", "0", "2147483647", "24", "0", "144", "1", "0", "12", "2147483647", "12", "49152", "0", "0", "2147483647", "17,678", "6,322", "68,136", "2,113", "0,644", "4", "9", "13", "384", "0", "0", "1 341 501,353", "17,678", "6,322", "68,136", "2,113", "0,644", "4", "1 341 501,353", "13", "384", "0", "0", "1 341 501,353", "12", "12", "0", "null", "null", "0", "12", "12", "12", "12", "12", "1", "12", "12", "0", "null", "null", "0", "1", "12", "12", "12", "12", "1", "13", "11", "12", "12", "0", "0", "13", "13", "24", "6", "6", "12", "13", "11", "12", "12", "0", "0", "12", "13", "24", "6", "6", "12", "12lama", "8", "48", "3", "0", "4", "8", "12", "192", "0", "0", "20736", "12lama", "8", "48", "3", "0", "4", "20736", "12", "192", "0", "0", "20736", "[12, 1, 2, 3, 4, 5]", "7", "60", "2,4", "2", "4", "9", "13", "384", "0", "0", "248832", "[12, 1, 2, 3, 4, 5]", "7", "60", "2,4", "2", "4", "248832", "13", "384", "0", "0", "248832", "5,678", "5,678", "0", "null", "NaN", "0", "5", "5", "5", "5", "5", "1", "5,678", "5,678", "0", "null", "NaN", "0", "1", "5", "5", "5", "5", "1", "6,678", "4,678", "5,678", "5,678", "0,678", "1", "4", "5", "10", "2", "2", "5,678", "6,678", "4,678", "5,678", "5,678", "0,678", "1", "5,678", "5", "10", "2", "2", "5,678", "5,678", "5,678", "0", "null", "NaN", "0", "5", "5", "5", "5", "5", "1", "5,678", "5,678", "0", "null", "NaN", "0", "1", "5", "5", "5", "5", "1", "17,678", "-6,322", "68,136", "0,473", "5,678", "4", "9", "13", "20480", "0", "0", "1 122 909 247,194", "17,678", "-6,322", "68,136", "0,473", "5,678", "4", "1 122 909 247,194", "13", "20480", "0", "0", "1 122 909 247,194", "11,356", "0", "32,24", "1", "0", "5", "0", "5", "160", "0", "0", "19 156,732", "11,356", "0", "32,24", "1", "0", "5", "19 156,732", "5", "160", "0", "0", "19 156,732", "5,678", "5,678", "0", "null", "NaN", "0", "5", "5", "5", "5", "5", "1", "5,678", "5,678", "0", "null", "NaN", "0", "1", "5", "5", "5", "5", "1", "6,678", "4,678", "5,678", "5,678", "0,678", "1", "4", "5", "10", "2", "2", "5,678", "6,678", "4,678", "5,678", "5,678", "0,678", "1", "5,678", "5", "10", "2", "2", "5,678", "5,678lama", "1,678", "22,712", "1,419", "1,678", "4", "1", "5", "80", "0", "0", "1 039,397", "5,678lama", "1,678", "22,712", "1,419", "1,678", "4", "1 039,397", "5", "80", "0", "0", "1 039,397", "[5,678, 1, 2, 3, 4, 5]", "0,678", "28,39", "1,136", "0,678", "5", "0", "5", "160", "0", "0", "5 901,697", "[5,678, 1, 2, 3, 4, 5]", "0,678", "28,39", "1,136", "0,678", "5", "5 901,697", "5", "160", "0", "0", "5 901,697", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "12", "-12", "0", "0", "0", "0", "12", "12", "0", "0", "0", "0", "12", "-12", "0", "0", "0", "0", "0", "12", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "falselama", "-4", "0", "0", "0", "0", "4", "4", "0", "0", "0", "0", "falselama", "-4", "0", "0", "0", "0", "0", "4", "0", "0", "0", "0", "[false, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "[false, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "2", "0", "1", "1", "0", "1", "0", "1", "2", "0", "0", "1", "2", "0", "1", "1", "0", "1", "1", "1", "2", "0", "0", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "13", "-11", "12", "0,083", "1", "0", "13", "13", "4096", "0", "0", "1", "13", "-11", "12", "0,083", "1", "0", "1", "13", "4096", "0", "0", "1", "6,678", "-4,678", "5,678", "0,176", "1", "1", "4", "5", "32", "0", "0", "1", "6,678", "-4,678", "5,678", "0,176", "1", "1", "1", "5", "32", "0", "0", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "2", "0", "1", "1", "0", "1", "0", "1", "2", "0", "0", "1", "2", "0", "1", "1", "0", "1", "1", "1", "2", "0", "0", "1", "truelama", "-3", "4", "0,25", "1", "0", "5", "5", "16", "0", "0", "1", "truelama", "-3", "4", "0,25", "1", "0", "1", "5", "16", "0", "0", "1", "[true, 1, 2, 3, 4, 5]", "-4", "5", "0,2", "1", "1", "4", "5", "32", "0", "0", "1", "[true, 1, 2, 3, 4, 5]", "-4", "5", "0,2", "1", "1", "1", "5", "32", "0", "0", "1", "lamanull", "4", "0", "null", "null", "0", "4", "4", "4", "4", "4", "1", "lamanull", "4", "0", "null", "null", "0", "1", "4", "4", "4", "4", "1", "lamatrue", "3", "4", "4", "0", "0", "5", "5", "8", "2", "2", "4", "lamatrue", "3", "4", "4", "0", "0", "4", "5", "8", "2", "2", "4", "lamafalse", "4", "0", "null", "null", "0", "4", "4", "4", "4", "4", "1", "lamafalse", "4", "0", "null", "null", "0", "1", "4", "4", "4", "4", "1", "lama12", "-8", "48", "0,333", "4", "4", "8", "12", "16384", "0", "0", "16777216", "lama12", "-8", "48", "0,333", "4", "4", "16777216", "12", "16384", "0", "0", "16777216", "lama5,678", "-1,678", "22,712", "0,704", "4", "4", "1", "5", "128", "0", "0", "2 621,179", "lama5,678", "-1,678", "22,712", "0,704", "4", "4", "2 621,179", "5", "128", "0", "0", "2 621,179", "lamafalse", "4", "0", "null", "null", "0", "4", "4", "4", "4", "4", "1", "lamafalse", "4", "0", "null", "null", "0", "1", "4", "4", "4", "4", "1", "lamatrue", "3", "4", "4", "0", "0", "5", "5", "8", "2", "2", "4", "lamatrue", "3", "4", "4", "0", "0", "4", "5", "8", "2", "2", "4", "lamalama", "0", "16", "1", "0", "4", "0", "4", "64", "0", "0", "256", "lamalama", "0", "16", "1", "0", "4", "256", "4", "64", "0", "0", "256", "lama[1, 2, 3, 4, 5]", "-1", "20", "0,8", "4", "4", "1", "5", "128", "0", "0", "1024", "lama[1, 2, 3, 4, 5]", "-1", "20", "0,8", "4", "4", "1024", "5", "128", "0", "0", "1024", "[1, 2, 3, 4, 5, null]", "5", "0", "null", "null", "0", "5", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, null]", "5", "0", "null", "null", "0", "1", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, true]", "4", "5", "5", "0", "1", "4", "5", "10", "2", "2", "5", "[1, 2, 3, 4, 5, true]", "4", "5", "5", "0", "1", "5", "5", "10", "2", "2", "5", "[1, 2, 3, 4, 5, false]", "5", "0", "null", "null", "0", "5", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, false]", "5", "0", "null", "null", "0", "1", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, 12]", "-7", "60", "0,417", "5", "4", "9", "13", "20480", "0", "0", "244140625", "[1, 2, 3, 4, 5, 12]", "-7", "60", "0,417", "5", "4", "244140625", "13", "20480", "0", "0", "244140625", "[1, 2, 3, 4, 5, 5,678]", "-0,678", "28,39", "0,881", "5", "5", "0", "5", "160", "0", "0", "9 305,757", "[1, 2, 3, 4, 5, 5,678]", "-0,678", "28,39", "0,881", "5", "5", "9 305,757", "5", "160", "0", "0", "9 305,757", "[1, 2, 3, 4, 5, false]", "5", "0", "null", "null", "0", "5", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, false]", "5", "0", "null", "null", "0", "1", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, true]", "4", "5", "5", "0", "1", "4", "5", "10", "2", "2", "5", "[1, 2, 3, 4, 5, true]", "4", "5", "5", "0", "1", "5", "5", "10", "2", "2", "5", "[1, 2, 3, 4, 5]lama", "1", "20", "1,25", "1", "4", "1", "5", "80", "0", "0", "625", "[1, 2, 3, 4, 5]lama", "1", "20", "1,25", "1", "4", "625", "5", "80", "0", "0", "625", "[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]", "0", "25", "1", "0", "5", "0", "5", "160", "0", "0", "3125", "[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]", "0", "25", "1", "0", "5", "3125", "5", "160", "0", "0", "3125" + "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "12", "-12", "0", "0", "0", "0", "12", "12", "0", "0", "0", "0", "12", "-12", "0", "0", "0", "0", "0", "12", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "nulllama", "-4", "0", "0", "0", "0", "4", "4", "0", "0", "0", "0", "nulllama", "-4", "0", "0", "0", "0", "0", "4", "0", "0", "0", "0", "[null, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "[null, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "2", "0", "1", "1", "0", "1", "0", "1", "2", "0", "0", "1", "2", "0", "1", "1", "0", "1", "1", "1", "2", "0", "0", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "13", "-11", "12", "0,083", "1", "0", "13", "13", "4096", "0", "0", "1", "13", "-11", "12", "0,083", "1", "0", "1", "13", "4096", "0", "0", "1", "6,678", "-4,678", "5,678", "0,176", "1", "1", "4", "5", "32", "0", "0", "1", "6,678", "-4,678", "5,678", "0,176", "1", "1", "1", "5", "32", "0", "0", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "2", "0", "1", "1", "0", "1", "0", "1", "2", "0", "0", "1", "2", "0", "1", "1", "0", "1", "1", "1", "2", "0", "0", "1", "truelama", "-3", "4", "0,25", "1", "0", "5", "5", "16", "0", "0", "1", "truelama", "-3", "4", "0,25", "1", "0", "1", "5", "16", "0", "0", "1", "[true, 1, 2, 3, 4, 5]", "-4", "5", "0,2", "1", "1", "4", "5", "32", "0", "0", "1", "[true, 1, 2, 3, 4, 5]", "-4", "5", "0,2", "1", "1", "1", "5", "32", "0", "0", "1", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "12", "-12", "0", "0", "0", "0", "12", "12", "0", "0", "0", "0", "12", "-12", "0", "0", "0", "0", "0", "12", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "falselama", "-4", "0", "0", "0", "0", "4", "4", "0", "0", "0", "0", "falselama", "-4", "0", "0", "0", "0", "0", "4", "0", "0", "0", "0", "[false, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "[false, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "12", "12", "0", "null", "null", "0", "12", "12", "12", "12", "12", "1", "12", "12", "0", "null", "null", "0", "1", "12", "12", "12", "12", "1", "13", "11", "12", "12", "0", "0", "13", "13", "24", "6", "6", "12", "13", "11", "12", "12", "0", "0", "12", "13", "24", "6", "6", "12", "12", "12", "0", "null", "null", "0", "12", "12", "12", "12", "12", "1", "12", "12", "0", "null", "null", "0", "1", "12", "12", "12", "12", "1", "24", "0", "144", "1", "0", "12", "0", "12", "49152", "0", "0", "2147483647", "24", "0", "144", "1", "0", "12", "2147483647", "12", "49152", "0", "0", "2147483647", "17,678", "6,322", "68,136", "2,113", "0,644", "4", "9", "13", "384", "0", "0", "1 341 501,353", "17,678", "6,322", "68,136", "2,113", "0,644", "4", "1 341 501,353", "13", "384", "0", "0", "1 341 501,353", "12", "12", "0", "null", "null", "0", "12", "12", "12", "12", "12", "1", "12", "12", "0", "null", "null", "0", "1", "12", "12", "12", "12", "1", "13", "11", "12", "12", "0", "0", "13", "13", "24", "6", "6", "12", "13", "11", "12", "12", "0", "0", "12", "13", "24", "6", "6", "12", "12lama", "8", "48", "3", "0", "4", "8", "12", "192", "0", "0", "20736", "12lama", "8", "48", "3", "0", "4", "20736", "12", "192", "0", "0", "20736", "[12, 1, 2, 3, 4, 5]", "7", "60", "2,4", "2", "4", "9", "13", "384", "0", "0", "248832", "[12, 1, 2, 3, 4, 5]", "7", "60", "2,4", "2", "4", "248832", "13", "384", "0", "0", "248832", "5,678", "5,678", "0", "null", "NaN", "0", "5", "5", "5", "5", "5", "1", "5,678", "5,678", "0", "null", "NaN", "0", "1", "5", "5", "5", "5", "1", "6,678", "4,678", "5,678", "5,678", "0,678", "1", "4", "5", "10", "2", "2", "5,678", "6,678", "4,678", "5,678", "5,678", "0,678", "1", "5,678", "5", "10", "2", "2", "5,678", "5,678", "5,678", "0", "null", "NaN", "0", "5", "5", "5", "5", "5", "1", "5,678", "5,678", "0", "null", "NaN", "0", "1", "5", "5", "5", "5", "1", "17,678", "-6,322", "68,136", "0,473", "5,678", "4", "9", "13", "20480", "0", "0", "1 122 909 247,194", "17,678", "-6,322", "68,136", "0,473", "5,678", "4", "1 122 909 247,194", "13", "20480", "0", "0", "1 122 909 247,194", "11,356", "0", "32,24", "1", "0", "5", "0", "5", "160", "0", "0", "19 156,732", "11,356", "0", "32,24", "1", "0", "5", "19 156,732", "5", "160", "0", "0", "19 156,732", "5,678", "5,678", "0", "null", "NaN", "0", "5", "5", "5", "5", "5", "1", "5,678", "5,678", "0", "null", "NaN", "0", "1", "5", "5", "5", "5", "1", "6,678", "4,678", "5,678", "5,678", "0,678", "1", "4", "5", "10", "2", "2", "5,678", "6,678", "4,678", "5,678", "5,678", "0,678", "1", "5,678", "5", "10", "2", "2", "5,678", "5,678lama", "1,678", "22,712", "1,419", "1,678", "4", "1", "5", "80", "0", "0", "1 039,397", "5,678lama", "1,678", "22,712", "1,419", "1,678", "4", "1 039,397", "5", "80", "0", "0", "1 039,397", "[5,678, 1, 2, 3, 4, 5]", "0,678", "28,39", "1,136", "0,678", "5", "0", "5", "160", "0", "0", "5 901,697", "[5,678, 1, 2, 3, 4, 5]", "0,678", "28,39", "1,136", "0,678", "5", "5 901,697", "5", "160", "0", "0", "5 901,697", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "12", "-12", "0", "0", "0", "0", "12", "12", "0", "0", "0", "0", "12", "-12", "0", "0", "0", "0", "0", "12", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "5,678", "-5,678", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "0", "0", "0", "null", "null", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "null", "null", "0", "1", "0", "0", "0", "0", "1", "1", "-1", "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "1", "-1", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "falselama", "-4", "0", "0", "0", "0", "4", "4", "0", "0", "0", "0", "falselama", "-4", "0", "0", "0", "0", "0", "4", "0", "0", "0", "0", "[false, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "5", "5", "0", "0", "0", "0", "[false, 1, 2, 3, 4, 5]", "-5", "0", "0", "0", "0", "0", "5", "0", "0", "0", "0", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "2", "0", "1", "1", "0", "1", "0", "1", "2", "0", "0", "1", "2", "0", "1", "1", "0", "1", "1", "1", "2", "0", "0", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "13", "-11", "12", "0,083", "1", "0", "13", "13", "4096", "0", "0", "1", "13", "-11", "12", "0,083", "1", "0", "1", "13", "4096", "0", "0", "1", "6,678", "-4,678", "5,678", "0,176", "1", "1", "4", "5", "32", "0", "0", "1", "6,678", "-4,678", "5,678", "0,176", "1", "1", "1", "5", "32", "0", "0", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "1", "1", "0", "null", "null", "0", "1", "1", "1", "1", "1", "1", "2", "0", "1", "1", "0", "1", "0", "1", "2", "0", "0", "1", "2", "0", "1", "1", "0", "1", "1", "1", "2", "0", "0", "1", "truelama", "-3", "4", "0,25", "1", "0", "5", "5", "16", "0", "0", "1", "truelama", "-3", "4", "0,25", "1", "0", "1", "5", "16", "0", "0", "1", "[true, 1, 2, 3, 4, 5]", "-4", "5", "0,2", "1", "1", "4", "5", "32", "0", "0", "1", "[true, 1, 2, 3, 4, 5]", "-4", "5", "0,2", "1", "1", "1", "5", "32", "0", "0", "1", "lamanull", "4", "0", "null", "null", "0", "4", "4", "4", "4", "4", "1", "lamanull", "4", "0", "null", "null", "0", "1", "4", "4", "4", "4", "1", "lamatrue", "3", "4", "4", "0", "0", "5", "5", "8", "2", "2", "4", "lamatrue", "3", "4", "4", "0", "0", "4", "5", "8", "2", "2", "4", "lamafalse", "4", "0", "null", "null", "0", "4", "4", "4", "4", "4", "1", "lamafalse", "4", "0", "null", "null", "0", "1", "4", "4", "4", "4", "1", "lama12", "-8", "48", "0,333", "4", "4", "8", "12", "16384", "0", "0", "16777216", "lama12", "-8", "48", "0,333", "4", "4", "16777216", "12", "16384", "0", "0", "16777216", "lama5,678", "-1,678", "22,712", "0,704", "4", "4", "1", "5", "128", "0", "0", "2 621,179", "lama5,678", "-1,678", "22,712", "0,704", "4", "4", "2 621,179", "5", "128", "0", "0", "2 621,179", "lamafalse", "4", "0", "null", "null", "0", "4", "4", "4", "4", "4", "1", "lamafalse", "4", "0", "null", "null", "0", "1", "4", "4", "4", "4", "1", "lamatrue", "3", "4", "4", "0", "0", "5", "5", "8", "2", "2", "4", "lamatrue", "3", "4", "4", "0", "0", "4", "5", "8", "2", "2", "4", "lamalama", "0", "16", "1", "0", "4", "0", "4", "64", "0", "0", "256", "lamalama", "0", "16", "1", "0", "4", "256", "4", "64", "0", "0", "256", "lama[1, 2, 3, 4, 5]", "-1", "20", "0,8", "4", "4", "1", "5", "128", "0", "0", "1024", "lama[1, 2, 3, 4, 5]", "-1", "20", "0,8", "4", "4", "1024", "5", "128", "0", "0", "1024", "[1, 2, 3, 4, 5, null]", "5", "0", "null", "null", "0", "5", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, null]", "5", "0", "null", "null", "0", "1", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, true]", "4", "5", "5", "0", "1", "4", "5", "10", "2", "2", "5", "[1, 2, 3, 4, 5, true]", "4", "5", "5", "0", "1", "5", "5", "10", "2", "2", "5", "[1, 2, 3, 4, 5, false]", "5", "0", "null", "null", "0", "5", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, false]", "5", "0", "null", "null", "0", "1", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, 12]", "-7", "60", "0,417", "5", "4", "9", "13", "20480", "0", "0", "244140625", "[1, 2, 3, 4, 5, 12]", "-7", "60", "0,417", "5", "4", "244140625", "13", "20480", "0", "0", "244140625", "[1, 2, 3, 4, 5, 5,678]", "-0,678", "28,39", "0,881", "5", "5", "0", "5", "160", "0", "0", "9 305,757", "[1, 2, 3, 4, 5, 5,678]", "-0,678", "28,39", "0,881", "5", "5", "9 305,757", "5", "160", "0", "0", "9 305,757", "[1, 2, 3, 4, 5, false]", "5", "0", "null", "null", "0", "5", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, false]", "5", "0", "null", "null", "0", "1", "5", "5", "5", "5", "1", "[1, 2, 3, 4, 5, true]", "4", "5", "5", "0", "1", "4", "5", "10", "2", "2", "5", "[1, 2, 3, 4, 5, true]", "4", "5", "5", "0", "1", "5", "5", "10", "2", "2", "5", "[1, 2, 3, 4, 5]lama", "1", "20", "1,25", "1", "4", "1", "5", "80", "0", "0", "625", "[1, 2, 3, 4, 5]lama", "1", "20", "1,25", "1", "4", "625", "5", "80", "0", "0", "625", "[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]", "0", "25", "1", "0", "5", "0", "5", "160", "0", "0", "3125", "[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]", "0", "25", "1", "0", "5", "3125", "5", "160", "0", "0", "3125" }; List results = new ArrayList(); int r = 0; From 1efd8dae25659432b61f5b6f021b611c8f5db88c Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 15 Nov 2021 12:06:09 +0100 Subject: [PATCH 286/319] Update CI to Java 16 --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 23d5f8c9..a397e3af 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,10 +16,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up JDK 11 + - name: Set up JDK 16 uses: actions/setup-java@v2 with: - java-version: '11' + java-version: '16' distribution: 'adopt' - name: Setup locale run: | From f7b5eb9bd0810e27d5a58695470a3f33deecbc01 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 16 Nov 2021 11:25:31 +0100 Subject: [PATCH 287/319] [file] Add toJSON to AIFile --- src/main/java/leekscript/compiler/AIFile.java | 12 ++++++++++++ .../compiler/resolver/FileSystemContext.java | 15 +++++++++++---- .../compiler/resolver/ResolverContext.java | 3 +++ .../compiler/resolver/ResourceContext.java | 7 +++++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/main/java/leekscript/compiler/AIFile.java b/src/main/java/leekscript/compiler/AIFile.java index 71a9e64b..a14f94d4 100644 --- a/src/main/java/leekscript/compiler/AIFile.java +++ b/src/main/java/leekscript/compiler/AIFile.java @@ -1,5 +1,7 @@ package leekscript.compiler; +import com.alibaba.fastjson.JSONObject; + import leekscript.compiler.resolver.ResolverContext; public class AIFile { @@ -14,6 +16,7 @@ public class AIFile { public AIFile(String path, String code, long timestamp, int version, C context) { this(path, code, timestamp, version, context, (context + "/" + path).hashCode() & 0xfffffff); } + public AIFile(String path, String code, long timestamp, int version, C context, int id) { this.path = path; this.code = code; @@ -58,4 +61,13 @@ public int getVersion() { public void setVersion(int version) { this.version = version; } + + public String toJson() { + JSONObject json = new JSONObject(); + json.put("path", path); + json.put("timestamp", timestamp); + json.put("version", version); + context.toJson(json); + return json.toJSONString(); + } } diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemContext.java b/src/main/java/leekscript/compiler/resolver/FileSystemContext.java index bb63ed56..a0d2b2ec 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemContext.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemContext.java @@ -2,19 +2,21 @@ import java.io.File; +import com.alibaba.fastjson.JSONObject; + public class FileSystemContext extends ResolverContext { - + private File folder; - + public FileSystemContext(File folder) { this.folder = folder; } - + @Override public String toString() { return folder.getPath(); } - + public File getFolder() { return folder; } @@ -22,4 +24,9 @@ public File getFolder() { public void setFolder(File folder) { this.folder = folder; } + + @Override + public void toJson(JSONObject json) { + + } } diff --git a/src/main/java/leekscript/compiler/resolver/ResolverContext.java b/src/main/java/leekscript/compiler/resolver/ResolverContext.java index be5c6baa..a27e2b5d 100644 --- a/src/main/java/leekscript/compiler/resolver/ResolverContext.java +++ b/src/main/java/leekscript/compiler/resolver/ResolverContext.java @@ -1,5 +1,8 @@ package leekscript.compiler.resolver; +import com.alibaba.fastjson.JSONObject; + public abstract class ResolverContext { + public abstract void toJson(JSONObject json); } diff --git a/src/main/java/leekscript/compiler/resolver/ResourceContext.java b/src/main/java/leekscript/compiler/resolver/ResourceContext.java index 596fff06..8ab1c27e 100644 --- a/src/main/java/leekscript/compiler/resolver/ResourceContext.java +++ b/src/main/java/leekscript/compiler/resolver/ResourceContext.java @@ -2,6 +2,8 @@ import java.io.File; +import com.alibaba.fastjson.JSONObject; + public class ResourceContext extends ResolverContext { private File folder; @@ -22,4 +24,9 @@ public File getFolder() { public void setFolder(File folder) { this.folder = folder; } + + @Override + public void toJson(JSONObject json) { + + } } From 4d95d5908365d595508e59cb47f4483df0eddaa3 Mon Sep 17 00:00:00 2001 From: Pilow Date: Wed, 17 Nov 2021 21:10:54 +0100 Subject: [PATCH 288/319] [leekscript] Fix class cache --- .../java/leekscript/compiler/LeekScript.java | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 10b2e6b1..603ddd4c 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -34,6 +34,15 @@ public class LeekScript { private final static String IA_PATH = "ai/"; private static long id = 1; + private static class AIClassEntry { + Class clazz; + long timestamp; + public AIClassEntry(Class clazz, long timestamp) { + this.clazz = clazz; + this.timestamp = timestamp; + } + } + private static Resolver defaultResolver = new ResourceResolver(); private static Resolver fileSystemResolver = new FileSystemResolver(); private static Resolver customResolver = null; @@ -41,7 +50,7 @@ public class LeekScript { private static List arguments = new ArrayList<>(); private static JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); private static URLClassLoader urlLoader; - private static HashMap> aiCache = new HashMap<>(); + private static HashMap aiCache = new HashMap<>(); static { try { classpath = LeekScript.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath(); @@ -145,15 +154,26 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) File java = new File(IA_PATH + javaClassName + ".java"); File lines = new File(IA_PATH + javaClassName + ".lines"); - // Utilisation du cache de class + // Cache des classes en RAM d'abord + var entry = aiCache.get(javaClassName); + if (entry != null && entry.timestamp > file.getTimestamp()) { + try { + var ai = (AI) entry.clazz.getDeclaredConstructor().newInstance(); + ai.setId(file.getId()); + ai.setLinesFile(lines); + return ai; + } catch (Exception e) { + throw new LeekScriptException(Error.CANNOT_LOAD_AI, e.getMessage()); + } + } + + // Utilisation du cache de class dans le file system if (useClassCache && compiled.exists() && compiled.length() != 0 && compiled.lastModified() > file.getTimestamp()) { try { - var clazz = aiCache.get(javaClassName); - if (clazz == null) { - clazz = urlLoader.loadClass(javaClassName); - aiCache.put(javaClassName, clazz); - } - var ai = (AI) clazz.getDeclaredConstructor().newInstance(); + var clazz = urlLoader.loadClass(javaClassName); + entry = new AIClassEntry(clazz, System.currentTimeMillis()); + aiCache.put(javaClassName, entry); + var ai = (AI) entry.clazz.getDeclaredConstructor().newInstance(); ai.setId(file.getId()); ai.setLinesFile(lines); return ai; @@ -162,7 +182,7 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) } } - // On commence par la conversion LS->Java + // On commence par la conversion LS -> Java long t = System.nanoTime(); var compiledCode = new IACompiler().compile(file, javaClassName, AIClass); long analyze_time = System.nanoTime() - t; @@ -248,7 +268,7 @@ protected Class findClass(String name) throws ClassNotFoundException { ai.setLinesFile(lines); if (useClassCache) { - aiCache.put(javaClassName, clazz); + aiCache.put(javaClassName, new AIClassEntry(clazz, System.currentTimeMillis())); } return ai; } catch (Exception e) { From dce10848e9ea1bdf5f6d23442bfbfe69234384df Mon Sep 17 00:00:00 2001 From: Pilow Date: Thu, 18 Nov 2021 23:02:06 +0100 Subject: [PATCH 289/319] [leekscript] Improve cache --- .../java/leekscript/compiler/LeekScript.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 603ddd4c..6121896c 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -59,7 +59,7 @@ public AIClassEntry(Class clazz, long timestamp) { e.printStackTrace(); } try { - urlLoader = new URLClassLoader(new URL[] { new File("ai").toURI().toURL() }, new ClassLoader() {}); + urlLoader = new URLClassLoader(new URL[] { new File(IA_PATH).toURI().toURL() }, new ClassLoader() {}); } catch (MalformedURLException e) { e.printStackTrace(); } @@ -147,7 +147,9 @@ public static RandomGenerator getRandom() { public static AI compile(AIFile file, String AIClass, boolean useClassCache) throws LeekScriptException, LeekCompilerException { - new File(IA_PATH).mkdir(); + + var root = new File(IA_PATH); + if (!root.exists()) root.mkdir(); String javaClassName = "AI_" + file.getId(); String fileName = javaClassName + ".java"; File compiled = new File(IA_PATH + javaClassName + ".class"); @@ -156,7 +158,7 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) // Cache des classes en RAM d'abord var entry = aiCache.get(javaClassName); - if (entry != null && entry.timestamp > file.getTimestamp()) { + if (entry != null && entry.timestamp >= file.getTimestamp()) { try { var ai = (AI) entry.clazz.getDeclaredConstructor().newInstance(); ai.setId(file.getId()); @@ -168,10 +170,15 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) } // Utilisation du cache de class dans le file system - if (useClassCache && compiled.exists() && compiled.length() != 0 && compiled.lastModified() > file.getTimestamp()) { + if (useClassCache && compiled.exists() && compiled.length() != 0 && compiled.lastModified() >= file.getTimestamp()) { try { + try { + urlLoader = new URLClassLoader(new URL[] { new File(IA_PATH).toURI().toURL() }, new ClassLoader() {}); + } catch (MalformedURLException e) { + e.printStackTrace(); + } var clazz = urlLoader.loadClass(javaClassName); - entry = new AIClassEntry(clazz, System.currentTimeMillis()); + entry = new AIClassEntry(clazz, file.getTimestamp()); aiCache.put(javaClassName, entry); var ai = (AI) entry.clazz.getDeclaredConstructor().newInstance(); ai.setId(file.getId()); @@ -268,7 +275,7 @@ protected Class findClass(String name) throws ClassNotFoundException { ai.setLinesFile(lines); if (useClassCache) { - aiCache.put(javaClassName, new AIClassEntry(clazz, System.currentTimeMillis())); + aiCache.put(javaClassName, new AIClassEntry(clazz, file.getTimestamp())); } return ai; } catch (Exception e) { From 7fbe96fefa4a1ff6a6567069bd2e197791560958 Mon Sep 17 00:00:00 2001 From: Pilow Date: Thu, 18 Nov 2021 23:15:44 +0100 Subject: [PATCH 290/319] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5cfa84a4..3d5d9306 100644 --- a/README.md +++ b/README.md @@ -19,4 +19,4 @@ gradle jar test ``` ### Credits -Developed by Dawyde © 2012-2020 +Developed by Dawyde & Pilow © 2012-2021 From e7856ca161d12147c9ca035037430b8b04a9427d Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 26 Nov 2021 12:28:33 +0100 Subject: [PATCH 291/319] [leekscript] Add logs for compilation --- src/main/java/leekscript/compiler/LeekScript.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 6121896c..cd21d0b3 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -147,6 +147,7 @@ public static RandomGenerator getRandom() { public static AI compile(AIFile file, String AIClass, boolean useClassCache) throws LeekScriptException, LeekCompilerException { + // System.out.println("LeekScript compile AI " + file.getPath() + " timestamp : " + file.getTimestamp()); var root = new File(IA_PATH); if (!root.exists()) root.mkdir(); @@ -159,6 +160,7 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) // Cache des classes en RAM d'abord var entry = aiCache.get(javaClassName); if (entry != null && entry.timestamp >= file.getTimestamp()) { + // System.out.println("Load AI " + file.getPath() + " from RAM"); try { var ai = (AI) entry.clazz.getDeclaredConstructor().newInstance(); ai.setId(file.getId()); @@ -171,6 +173,7 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) // Utilisation du cache de class dans le file system if (useClassCache && compiled.exists() && compiled.length() != 0 && compiled.lastModified() >= file.getTimestamp()) { + // System.out.println("Load AI " + file.getPath() + " from disk"); try { try { urlLoader = new URLClassLoader(new URL[] { new File(IA_PATH).toURI().toURL() }, new ClassLoader() {}); @@ -190,6 +193,7 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) } // On commence par la conversion LS -> Java + // System.out.println("Re-compile AI " + file.getPath()); long t = System.nanoTime(); var compiledCode = new IACompiler().compile(file, javaClassName, AIClass); long analyze_time = System.nanoTime() - t; From 6bce3916442c592c5691d83d6d6dfc42adcbae91 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 26 Nov 2021 12:28:33 +0100 Subject: [PATCH 292/319] [function] Fix arrayPartition and arrayIter on LS 2 --- src/main/java/leekscript/runner/AI.java | 44 ++++++++++++++++++- .../java/leekscript/runner/LeekFunctions.java | 16 +++++-- src/test/java/test/TestArray.java | 3 ++ 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 84eecb90..2ffc0b0a 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -407,7 +407,7 @@ public Object arrayFoldRight(ArrayLeekValue array, FunctionLeekValue function, O return result; } - public ArrayLeekValue arrayPartition(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { + public ArrayLeekValue arrayPartitionV10(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { ArrayLeekValue list1 = new ArrayLeekValue(); ArrayLeekValue list2 = new ArrayLeekValue(); int nb = function.getArgumentsCount(this); @@ -427,6 +427,26 @@ public ArrayLeekValue arrayPartition(ArrayLeekValue array, FunctionLeekValue fun return new ArrayLeekValue(this, new Object[] { list1, list2 }, false); } + public ArrayLeekValue arrayPartition(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { + ArrayLeekValue list1 = new ArrayLeekValue(); + ArrayLeekValue list2 = new ArrayLeekValue(); + int nb = function.getArgumentsCount(this); + if (nb != 1 && nb != 2) + return new ArrayLeekValue(); + ArrayIterator iterator = array.getArrayIterator(); + boolean b; + while (!iterator.ended()) { + var value = iterator.value(); + if (nb == 1) + b = bool(LeekValueManager.execute(this, function, new Object[] { value })); + else + b = bool(LeekValueManager.execute(this, function, new Object[] { iterator.getKey(this), value })); + (b ? list1 : list2).getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); + iterator.next(); + } + return new ArrayLeekValue(this, new Object[] { list1, list2 }, false); + } + public ArrayLeekValue arrayMap(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { ArrayLeekValue retour = new ArrayLeekValue(); ArrayIterator iterator = array.getArrayIterator(); @@ -506,7 +526,7 @@ public ArrayLeekValue arrayFilter(ArrayLeekValue array, FunctionLeekValue functi return retour; } - public Object arrayIter(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { + public Object arrayIterV10(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { ArrayIterator iterator = array.getArrayIterator(); if (function == null) { return null; @@ -526,6 +546,26 @@ public Object arrayIter(ArrayLeekValue array, FunctionLeekValue function) throws return null; } + public Object arrayIter(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { + ArrayIterator iterator = array.getArrayIterator(); + if (function == null) { + return null; + } + int nb = function.getArgumentsCount(this); + if (nb != 1 && nb != 2) + return null; + while (!iterator.ended()) { + var value = iterator.value(); + if (nb == 1) { + function.execute(this, value); + } else { + function.execute(this, iterator.getKey(this), value); + } + iterator.next(); + } + return null; + } + public ArrayLeekValue arraySort(ArrayLeekValue origin, final FunctionLeekValue function) throws LeekRunException { try { int nb = function.getArgumentsCount(this); diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 2488bc17..2a6e3b15 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -926,14 +926,22 @@ public Object run(AI leekIA, ILeekFunction function, Object... parameters) throw }, arrayPartition(2, new int[] { AI.ARRAY, AI.FUNCTION }) { @Override - public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { - return leekIA.arrayPartition((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + if (ai.getVersion() >= 11) { + return ai.arrayPartition((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); + } else { + return ai.arrayPartitionV10((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); + } } }, arrayIter(2, new int[] { AI.ARRAY, AI.FUNCTION }) { @Override - public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { - return leekIA.arrayIter((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); + public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { + if (ai.getVersion() >= 11) { + return ai.arrayIter((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); + } else { + return ai.arrayIterV10((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); + } } }, arrayConcat(2, new int[] { AI.ARRAY, AI.ARRAY }) { diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index 2daeeffe..f8c24ee9 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -345,6 +345,7 @@ public void run() throws Exception { code("return arrayMap([1, 2, 3], function(v) { var r = [] return r })").equals("[[], [], []]"); code("return arrayMap([1, 2, 3], function(v) { var r = [1, 2, 3] return r })").equals("[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"); code("var r = [] var a = arrayMap([1, 2, 3], function(v) { return r }) push(r, 1) return a").equals("[[1], <...>, <...>]"); + code_v11("class A { name part constructor(name, part) { this.name = name this.part = part } } var list = [new A('foo', true), new A('bar', false), new A('baz', true)] return arrayMap(list, function(a) { return a.name })").equals("[foo, bar, baz]"); section("Array.map() v1.0"); code_v10("return arrayMap([1, 2, 3, 4, 5], function(e) { return e * 2; });").equals("[2, 4, 6, 8, 10]"); @@ -373,6 +374,7 @@ public void run() throws Exception { code_v10("return string(function(){var t=[1,2,3]; arrayPartition(t, function(@v){ v=3; }); return t;}())").equals("[3, 3, 3]"); code_v10("return string(function(){var t=[1,2,3]; arrayPartition(t, function(k, @v){ v=3; }); return t;}())").equals("[3, 3, 3]"); code_v10("return string(arrayPartition([4,3,2,1], function(k,@v){ v=3; return kf)?(-1):(e Date: Fri, 26 Nov 2021 12:28:33 +0100 Subject: [PATCH 293/319] [object] Add objet litterals --- src/main/java/leekscript/common/Type.java | 1 + .../leekscript/compiler/WordCompiler.java | 36 +++++++- .../compiler/expression/LeekObject.java | 74 ++++++++++++++++ src/main/java/leekscript/runner/AI.java | 2 + .../runner/values/ObjectLeekValue.java | 23 ++++- src/test/java/test/TestArray.java | 10 +-- src/test/java/test/TestFiles.java | 4 +- src/test/java/test/TestGeneral.java | 2 +- src/test/java/test/TestGlobals.java | 2 + src/test/java/test/TestIf.java | 4 +- src/test/java/test/TestObject.java | 84 +++++++++---------- src/test/resources/ai/code/fold_left.leek | 2 +- src/test/resources/ai/code/two_functions.leek | 6 +- 13 files changed, 190 insertions(+), 60 deletions(-) create mode 100644 src/main/java/leekscript/compiler/expression/LeekObject.java diff --git a/src/main/java/leekscript/common/Type.java b/src/main/java/leekscript/common/Type.java index 3118027d..70a3127a 100644 --- a/src/main/java/leekscript/common/Type.java +++ b/src/main/java/leekscript/common/Type.java @@ -10,6 +10,7 @@ public class Type { public static Type REAL = new Type("real", 'r'); public static Type STRING = new Type("string", 's'); public static Type ARRAY = new Type("array", 'a'); + public static Type OBJECT = new Type("object", 'o'); public static Type FUNCTION = new Type("function", 'f'); public String name; diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index e7c0f1d5..60f14b95 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -29,6 +29,7 @@ import leekscript.compiler.expression.LeekExpressionFunction; import leekscript.compiler.expression.LeekNull; import leekscript.compiler.expression.LeekNumber; +import leekscript.compiler.expression.LeekObject; import leekscript.compiler.expression.LeekParenthesis; import leekscript.compiler.expression.LeekString; import leekscript.compiler.expression.LeekVariable; @@ -867,8 +868,7 @@ public AbstractExpression readExpression() throws LeekCompilerException { // Si on attend un opérateur mais qu'il vient pas if (word.getType() == WordParser.T_BRACKET_LEFT) { - mCompiler.skipWord();// On avance le curseur pour être au - // début de l'expression + mCompiler.skipWord(); // On avance le curseur pour être au début de l'expression AbstractExpression exp = readExpression(); if (mCompiler.getWord().getType() != WordParser.T_BRACKET_RIGHT) { @@ -966,7 +966,39 @@ else if (type == 2) throw new LeekCompilerException(mCompiler.getWord(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); } retour.addExpression(array); + + } else if (getVersion() >= 11 && word.getType() == WordParser.T_ACCOLADE_LEFT) { + + // Déclaration d'un objet + mCompiler.skipWord(); + var object = new LeekObject(); + int type = 0; + while (mCompiler.getWord().getType() != WordParser.T_ACCOLADE_RIGHT) { + if (mCompiler.getWord().getType() != WordParser.T_STRING) { + throw new LeekCompilerException(mCompiler.getWord(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); + } + String key = mCompiler.getWord().getWord(); + mCompiler.skipWord(); + + if (!mCompiler.getWord().getWord().equals(":")) { + throw new LeekCompilerException(mCompiler.getWord(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); + } + mCompiler.skipWord(); + + AbstractExpression value = readExpression(); + object.addEntry(key, value); + + if (mCompiler.getWord().getType() == WordParser.T_VIRG) { + mCompiler.skipWord(); + } + } + if (mCompiler.getWord().getType() != WordParser.T_ACCOLADE_RIGHT) { + throw new LeekCompilerException(mCompiler.getWord(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); + } + retour.addExpression(object); + } else if (word.getType() == WordParser.T_STRING) { + if (mMain.hasGlobal(word.getWord())) { retour.addExpression(new LeekVariable(this, word, VariableType.GLOBAL)); } else if (word.getWord().equalsIgnoreCase("function")) { diff --git a/src/main/java/leekscript/compiler/expression/LeekObject.java b/src/main/java/leekscript/compiler/expression/LeekObject.java new file mode 100644 index 00000000..deb67101 --- /dev/null +++ b/src/main/java/leekscript/compiler/expression/LeekObject.java @@ -0,0 +1,74 @@ +package leekscript.compiler.expression; + +import java.util.ArrayList; +import java.util.HashMap; + +import leekscript.common.Type; +import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; +import leekscript.compiler.bloc.MainLeekBlock; + +public class LeekObject extends AbstractExpression { + + private final HashMap mValues = new HashMap<>(); + + public void addEntry(String key, AbstractExpression value) { + mValues.put(key, value); + } + + @Override + public int getNature() { + return OBJECT; + } + + @Override + public Type getType() { + return Type.OBJECT; + } + + @Override + public String getString() { + String str = "{"; + int i = 0; + for (var entry : mValues.entrySet()) { + if (i++ > 0) str += ", "; + str += entry.getKey() + ": "; + str += entry.getValue().getString(); + } + return str + "}"; + } + + @Override + public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) throws LeekExpressionException { + for (var entry : mValues.entrySet()) { + entry.getValue().validExpression(compiler, mainblock); + } + return true; + } + + @Override + public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { + writer.addCode("new ObjectLeekValue(" + writer.getAIThis() + ", new String[] { "); + int i = 0; + for (var entry : mValues.entrySet()) { + if (i++ != 0) writer.addCode(", "); + writer.addCode("\"" + entry.getKey() + "\""); + } + writer.addCode(" }, new Object[] { "); + i = 0; + for (var entry : mValues.entrySet()) { + if (i++ != 0) writer.addCode(", "); + entry.getValue().writeJavaCode(mainblock, writer); + } + writer.addCode(" })"); + } + + @Override + public void analyze(WordCompiler compiler) { + operations = 0; + for (var value : mValues.entrySet()) { + value.getValue().analyze(compiler); + operations += value.getValue().getOperations(); + } + } +} diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 2ffc0b0a..76af602c 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -57,12 +57,14 @@ public abstract class AI { private long compileTime; private long loadTime; private File filesLines; + public ClassLeekValue objectClass; public AI(int instructions, int version) { this.mInstructions = instructions; this.version = version; logs = new AILog(); randomGenerator = LeekScript.getRandom(); + objectClass = new ClassLeekValue(this, "Object"); try { init(); } catch (Exception e) {} diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 7e6eefb1..91b75902 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -20,6 +20,13 @@ public ObjectLeekValue(ClassLeekValue clazz) { this.clazz = clazz; } + public ObjectLeekValue(AI ai, String[] keys, Object[] values) throws LeekRunException { + this.clazz = ai.objectClass; + for (int i = 0; i < keys.length; ++i) { + addField(ai, keys[i], values[i], AccessLevel.PUBLIC); + } + } + public ObjectLeekValue(AI ai, ObjectLeekValue value, int level) throws LeekRunException { this.clazz = value.clazz; ai.ops(value.fields.size()); @@ -88,6 +95,10 @@ public Box getFieldL(String field) throws LeekRunException { public Object setField(String field, Object value) throws LeekRunException { var result = fields.get(field); + // Pour un objet anonyme (classe Object), on peut rajouter des proprietés à la volée + if (result == null && clazz == clazz.ai.objectClass) { + addField(clazz.ai, field, value, AccessLevel.PUBLIC); + } if (result != null) { result.set(value); } @@ -286,7 +297,11 @@ public String getString(AI ai, Set visited) throws LeekRunException { ai.ops(1 + fields.size() * 2); - var sb = new StringBuilder(clazz.name + " {"); + var sb = new StringBuilder(); + if (clazz != clazz.ai.objectClass) { + sb.append(clazz.name).append(" "); + } + sb.append("{"); boolean first = true; for (HashMap.Entry field : fields.entrySet()) { if (first) first = false; @@ -340,7 +355,11 @@ public int size() { } public String toString() { - var sb = new StringBuilder(clazz.name + " {"); + var sb = new StringBuilder(); + if (clazz != clazz.ai.objectClass) { + sb.append(clazz.name).append(" "); + } + sb.append("{"); boolean first = true; for (HashMap.Entry field : fields.entrySet()) { if (first) first = false; diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index f8c24ee9..6f56b73d 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -17,7 +17,7 @@ public void run() throws Exception { code_v10("return [1.21, -5, 4.55, 12, -6.7];").equals("[1,21, -5, 4,55, 12, -6,7]"); code_v11("return [1.21, -5, 4.55, 12, -6.7];").equals("[1.21, -5, 4.55, 12, -6.7]"); code("return [true, false, true];").equals("[true, false, true]"); - // DISABLED_code("[23, true, '', {}, 123]").equals("[23, true, '', {}, 123]"); + code_v11("[23, true, '', {}, 123]").equals("[23, true, '', {}, 123]"); // DISABLED_code("var a = x -> x [1, 2, a]").equals("[1, 2, ]"); // DISABLED_code("[1m, 34324234m, 231232131232132134379897874534243257343341432423m]").equals("[1, 34324234, 231232131232132134379897874534243257343341432423]"); // DISABLED_code("[true, 'hello', 231232131232132134379897874534243257343341432423m]").equals("[true, 'hello', 231232131232132134379897874534243257343341432423]"); @@ -59,10 +59,10 @@ public void run() throws Exception { // DISABLED_code("var a = ['yo'] return a + '!';").equals("['yo', '!']"); code("var a = [5] var b = ['b'] return a + b;").equals("[5, b]"); code("var a = ['a'] return a + ['b'];").equals("[a, b]"); - // DISABLED_code("[1, 2] + {};").equals("[1, 2, {}]"); - // DISABLED_code("var a = [1, 2] a + {};").equals("[1, 2, {}]"); - // DISABLED_code("['a', 'b'] + {};").equals("['a', 'b', {}]"); - // DISABLED_code("var a = ['a', 'b'] a + {}").equals("['a', 'b', {}]"); + code_v11("[1, 2] + {};").equals("[1, 2, {}]"); + code_v11("var a = [1, 2] a + {};").equals("[1, 2, {}]"); + code_v11("['a', 'b'] + {};").equals("['a', 'b', {}]"); + code_v11("var a = ['a', 'b'] a + {}").equals("['a', 'b', {}]"); // DISABLED_code("return ['a', 'b'] + (x -> x)").equals("['a', 'b', ]"); // DISABLED_code("var a = ['a', 'b'] a + (x -> x)").equals("['a', 'b', ]"); // DISABLED_code("['a', 'b'] + Number").equals("['a', 'b', ]"); diff --git a/src/test/java/test/TestFiles.java b/src/test/java/test/TestFiles.java index 88a1dc75..62263ca2 100644 --- a/src/test/java/test/TestFiles.java +++ b/src/test/java/test/TestFiles.java @@ -32,12 +32,12 @@ public void run() { // file("ai/code/euler1.leek").equals("2333316668"); // DISABLED_file("ai/code/text_analysis.leek").equals("[3, 47, 338]"); // DISABLED_file("ai/code/divisors.leek").equals("[1, 3, 9, 13, 17, 39]"); - // DISABLED_file("test/code/two_functions.leek").equals("[{p: 2, v: 5}, [{p: 3, v: 6}]]"); + file_v11("ai/code/two_functions.leek").equals("[{p: 2, v: 5}, [{p: 3, v: 6}]]"); // file("test/code/product_n.leek").equals("5040"); // file("test/code/product_n_return.leek").equals("265252859812191058636308480000000"); // file("test/code/product_n_arrays.leek").equals("[5040]"); // file("test/code/product_coproduct.leek").equals("171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000"); - // file("test/code/fold_left.leek").equals("[{w: 1}, {w: 3}, {w: 4}, {w: 2}, {w: 7}, {w: 5}, {w: 8}, {w: 9}, {w: 6}]"); + file_v11("ai/code/fold_left.leek").equals("[{w: 1}, {w: 3}, {w: 4}, {w: 2}, {w: 7}, {w: 5}, {w: 8}, {w: 9}, {w: 6}]"); // file("test/code/fold_left_2.leek").equals("{p: 6, v: {p: 9, v: {p: 8, v: {p: 5, v: {p: 7, v: { ... }}}}}}"); // file("test/code/fold_right.leek").equals("[{w: 6}, {w: 9}, {w: 8}, {w: 5}, {w: 7}, {w: 2}, {w: 4}, {w: 3}, {w: 1}]"); // file("test/code/fold_right_2.leek").equals("{p: {p: {p: {p: {p: { ... }, v: 7}, v: 2}, v: 4}, v: 3}, v: 1}"); diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index b9f7c46a..632f75e0 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -50,7 +50,7 @@ public void run() { code("var a = 'hello' return a = 2").equals("2"); code("var a = 2 a = 'hello' return a").equals("hello"); code("var a = 2 a = [1, 2] return a").equals("[1, 2]"); - // code("var a = 5.5 a = {} a").equals("{}"); + code_v11("var a = 5.5 a = {} return a").equals("{}"); // code("var a = [5, 7] a = 7 System.print(a)").output("7\n"); // code("var a = 7 a = [5, 12] a").equals("[5, 12]"); // code("var a = 7 System.print(a) a = <5, 12> System.print(a)").output("7\n<5, 12>\n"); diff --git a/src/test/java/test/TestGlobals.java b/src/test/java/test/TestGlobals.java index 24c8c5cd..f28532f2 100644 --- a/src/test/java/test/TestGlobals.java +++ b/src/test/java/test/TestGlobals.java @@ -22,6 +22,8 @@ public void run() throws Exception { code("global r = [] return r[5] += 12").equals("12"); code_v10("global r = 12 r = @null").equals("null"); code("global m = [] return m = m").equals("[]"); + code_v11("global m = {} return m = m").equals("{}"); + code_v11("global m = {a: 12} return m = m").equals("{a: 12}"); section("Globals operators"); code("global x = 12; x++; return x;").equals("13"); diff --git a/src/test/java/test/TestIf.java b/src/test/java/test/TestIf.java index 4816090e..4c4f13a3 100644 --- a/src/test/java/test/TestIf.java +++ b/src/test/java/test/TestIf.java @@ -21,8 +21,8 @@ public void run() throws Exception { code("if (true) null else {}").equals("null"); // code("if true").error(ls::Error::UNEXPECTED_TOKEN, {""}); // code("if true else").error(ls::Error::UNEXPECTED_TOKEN, {"else"}); - // code("if (true) {a: 12} else {b: 5}").equals("{a: 12}"); - // code("if (true) { {a: 12} } else { {b: 5} }").equals("{a: 12}"); + code_v11("if (true) {a: 12} else {b: 5}").equals("{a: 12}"); + code_v11("if (true) { {a: 12} } else { {b: 5} }").equals("{a: 12}"); code("if (true) return 12 else return 5;").equals("12"); code("if (false) return 12 else return 5;").equals("5"); code("if (true) return 12;").equals("12"); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index e4bce20f..48e6294d 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -10,22 +10,22 @@ public void run() { // code("return Object()").equals("{}"); // code("return new Object").equals("{}"); // code("return new Object()").equals("{}"); - // code("return {}").equals("{}"); - // code("return {a: 12}").equals("{a: 12}"); - // code("return {a: 12, b: 5}").equals("{a: 12, b: 5}"); - // code("return {a: {}, b: []}").equals("{a: {}, b: []}"); - // code("var a = {} return a").equals("{}"); - // code("var a = {b: 12, c: 5} return a").equals("{b: 12, c: 5}"); + code_v11("return {}").equals("{}"); + code_v11("return {a: 12}").equals("{a: 12}"); + code_v11("return {a: 12, b: 5}").equals("{a: 12, b: 5}"); + code_v11("return {a: {}, b: []}").equals("{a: {}, b: []}"); + code_v11("var a = {} return a").equals("{}"); + code_v11("var a = {b: 12, c: 5} return a").equals("{b: 12, c: 5}"); section("Objects with functions"); - // code("var f = obj -> obj.a return f({a: 'foo'})").equals("'foo'"); - // code("var f = obj -> obj.a return [f({a: 'foo'}), f({a: 'bar'})]").equals("['foo', 'bar']"); - // code("var f = obj -> obj.a [f(12), f({a: 'bar'})]").error(ls::Error::NO_SUCH_ATTRIBUTE, {"a", "Number"}); + code_v11("var f = function(obj) { return obj.a } return f({a: 'foo'})").equals("foo"); + code_v11("var f = function(obj) { return obj.a } return [f({a: 'foo'}), f({a: 'bar'})]").equals("[foo, bar]"); + //code("var f = function(obj) { return obj.a } [f(12), f({a: 'bar'})]").error(ls::Error::NO_SUCH_ATTRIBUTE, {"a", "Number"}); section("No commas"); - // code("return {a: 12 b: 5}").equals("{a: 12, b: 5}"); - // code("return {a: 12 - 2 yo: -6}").equals("{a: 10, yo: -6}"); - // code("return {a: 12 b: 'yo' c: true d: [1 2 3]}").equals("{a: 12, b: 'yo', c: true, d: [1, 2, 3]}"); + code_v11("return {a: 12 b: 5}").equals("{a: 12, b: 5}"); + code_v11("return {a: 12 - 2 yo: -6}").equals("{a: 10, yo: -6}"); + code_v11("return {a: 12 b: 'yo' c: true d: [1 2 3]}").equals("{a: 12, b: yo, c: true, d: [1, 2, 3]}"); section("Classes"); code_v11("class A { } return new A();").equals("A {}"); @@ -218,43 +218,43 @@ public void run() { * Operators */ section("Object.operator !"); - // code("return !{}").equals("true"); - // code("return !{a: 32}").equals("false"); + code_v11("return !{}").equals("true"); + code_v11("return !{a: 32}").equals("false"); section("Object.operator | |"); - // code("var a = {a: 32, b: 'toto', c: false}; return |a|").equals("3"); + // code_v11("var a = {a: 32, b: 'toto', c: false}; return |a|").equals("3"); section("Object.operator in ()"); - // code("return 12 in {x: 5, y: 12}").equals("true"); - // code("return 12 in {x: 5, y: 'yo'}").equals("false"); + // code_v11("return 12 in {x: 5, y: 12}").equals("true"); + // code_v11("return 12 in {x: 5, y: 'yo'}").equals("false"); section("Object.operator . ()"); - // code("return { v: 12 }.v").equals("12"); - // code("var a = {b: 12, c: 5} return a.b").equals("12"); - // code("var a = {v: 5} return a.v = 12").equals("12"); - // code("var a = {v: 5} a.v = 12 return a").equals("{v: 12}"); - // code("var a = {v: 5} return a.v = 'salut'").equals("'salut'"); - // code("var a = {v: 5} a.v = 'salut' return a").equals("{v: 'salut'}"); - // code("var a = {b: 12} return a.b += 10").equals("22"); - // code("var a = {b: 12} return a.b -= 10").equals("2"); - // code("var a = {b: 12} return a.b *= 10").equals("120"); - // code("var a = {b: 12} return a.b /= 10").almost(1.2); - // code("var a = {b: 12} return a.b %= 10").equals("2"); - // code("var o = {} o.new_val = 12 return o").equals("{new_val: 12}"); - // code("var o = {a: 'a'} o.b = 'b' return o").equals("{a: 'a', b: 'b'}"); + code_v11("return { v: 12 }.v").equals("12"); + code_v11("var a = {b: 12, c: 5} return a.b").equals("12"); + code_v11("var a = {v: 5} return a.v = 12").equals("12"); + code_v11("var a = {v: 5} a.v = 12 return a").equals("{v: 12}"); + code_v11("var a = {v: 5} return a.v = 'salut'").equals("salut"); + code_v11("var a = {v: 5} a.v = 'salut' return a").equals("{v: salut}"); + code_v11("var a = {b: 12} return a.b += 10").equals("22"); + code_v11("var a = {b: 12} return a.b -= 10").equals("2"); + code_v11("var a = {b: 12} return a.b *= 10").equals("120"); + code_v11("var a = {b: 12} return a.b /= 10").almost(1.2); + code_v11("var a = {b: 12} return a.b %= 10").equals("2"); + code_v11("var o = {} o.new_val = 12 return o").equals("{new_val: 12}"); + code_v11("var o = {a: 'a'} o.b = 'b' return o").equals("{a: a, b: b}"); // DISABLED_code("Object.readonly.v = 5").exception(ls::vm::Exception::CANT_MODIFY_READONLY_OBJECT); - // code("var o = [{}, ''][0] return o.values").equals(""); - // code("var pq = [{p: 22, v: 55}] return pq[0].p").equals("22"); - // code("var pq = [{p: 22, v: 55}] var o = pq[0] return o.v").equals("55"); + // code_v11("var o = [{}, ''][0] return o.values").equals(""); + code_v11("var pq = [{p: 22, v: 55}] return pq[0].p").equals("22"); + code_v11("var pq = [{p: 22, v: 55}] var o = pq[0] return o.v").equals("55"); section("Object.operator =="); - // code("class A {} return {} == new A").equals("false"); + code_v11("class A {} return {} == new A").equals("false"); code_v11("class A { }; class B { }; return new A() == new B();").equals("false"); - // code("class A {} return new A == new A").equals("true"); - // code("return {a: 2} == {}").equals("false"); - // code("return {a: 2} == {a: 1}").equals("false"); - // code("return {a: 2} == {b: 2}").equals("false"); - // code("return {a: 2} == {a: 2}").equals("true"); + code_v11("class A {} return new A == new A").equals("true"); + code_v11("return {a: 2} == {}").equals("false"); + code_v11("return {a: 2} == {a: 1}").equals("false"); + code_v11("return {a: 2} == {b: 2}").equals("false"); + code_v11("return {a: 2} == {a: 2}").equals("false"); section("Object.operator <"); // code("return {} < {}").equals("false"); @@ -293,11 +293,11 @@ public void run() { // code("return {a: 5, b: 'toto', c: true, d: -> 5}.values()").equals("[5, 'toto', true, ]"); section("Object.isTrue()"); - // code("if ({x: 12}) { return 5 } else { return 12 }").equals("5"); - // code("if ({}) { return 5 } else { return 12 }").equals("12"); + code_v11("if ({x: 12}) { return 5 } else { return 12 }").equals("5"); + code_v11("if ({}) { return 5 } else { return 12 }").equals("12"); section("Object.clone()"); - // code("var a = {v: 12} return [a]").equals("[{v: 12}]"); + code_v11("var a = {v: 12} return [a]").equals("[{v: 12}]"); section("Object.map()"); // code("return {}.map(x -> x + 1)").equals("{}"); diff --git a/src/test/resources/ai/code/fold_left.leek b/src/test/resources/ai/code/fold_left.leek index af15ffd5..e66c98f1 100644 --- a/src/test/resources/ai/code/fold_left.leek +++ b/src/test/resources/ai/code/fold_left.leek @@ -1 +1 @@ -[1, 3, 4, 2, 7, 5, 8, 9, 6].foldLeft((acc, x) -> acc.push({w: x}), []) +return arrayFoldLeft([1, 3, 4, 2, 7, 5, 8, 9, 6], function(acc, x) { return push(acc, {w: x}) }, []) diff --git a/src/test/resources/ai/code/two_functions.leek b/src/test/resources/ai/code/two_functions.leek index 1d4d2de0..139d27b4 100644 --- a/src/test/resources/ai/code/two_functions.leek +++ b/src/test/resources/ai/code/two_functions.leek @@ -1,3 +1,3 @@ -let ppair = (p, v) -> {p: p, v: v} -let pqSingleton = (p, v) -> [{p: p, v: v}] -[ppair(2, 5), pqSingleton(3, 6)] +var ppair = function(p, v) { return {p: p, v: v} } +var pqSingleton = function(p, v) { return [{p: p, v: v}] } +return [ppair(2, 5), pqSingleton(3, 6)] From a54452035d4b23ef178c77795d17cde67d7b6398 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 26 Nov 2021 12:28:33 +0100 Subject: [PATCH 294/319] [version] Update versions --- .../java/leekscript/compiler/LeekScript.java | 2 +- .../leekscript/compiler/WordCompiler.java | 20 +- .../java/leekscript/compiler/WordParser.java | 6 +- .../compiler/bloc/AnonymousFunctionBlock.java | 2 +- .../compiler/bloc/ForeachBlock.java | 8 +- .../compiler/bloc/ForeachKeyBlock.java | 16 +- .../compiler/bloc/FunctionBlock.java | 6 +- .../compiler/bloc/MainLeekBlock.java | 2 +- .../compiler/expression/LeekExpression.java | 4 +- .../expression/LeekExpressionFunction.java | 2 +- .../compiler/expression/LeekObject.java | 3 +- .../compiler/expression/LeekString.java | 2 +- .../compiler/expression/LeekVariable.java | 10 +- .../compiler/expression/Operators.java | 4 +- .../LeekGlobalDeclarationInstruction.java | 4 +- .../LeekVariableDeclarationInstruction.java | 10 +- .../compiler/resolver/FileSystemResolver.java | 2 +- .../compiler/resolver/ResourceResolver.java | 2 +- src/main/java/leekscript/runner/AI.java | 20 +- .../java/leekscript/runner/LeekFunctions.java | 24 +- .../leekscript/runner/LeekValueManager.java | 22 +- src/main/java/leekscript/runner/PhpArray.java | 22 +- .../runner/values/ArrayLeekValue.java | 8 +- .../java/leekscript/runner/values/Box.java | 6 +- .../runner/values/FunctionLeekValue.java | 2 +- .../leekscript/runner/values/LeekValue.java | 16 +- src/test/java/test/TestAI.java | 4 +- src/test/java/test/TestArray.java | 190 ++++---- src/test/java/test/TestComments.java | 4 +- src/test/java/test/TestCommon.java | 26 +- src/test/java/test/TestFiles.java | 10 +- src/test/java/test/TestFunction.java | 122 +++--- src/test/java/test/TestGeneral.java | 20 +- src/test/java/test/TestGlobals.java | 14 +- src/test/java/test/TestIf.java | 18 +- src/test/java/test/TestJSON.java | 12 +- src/test/java/test/TestLoops.java | 20 +- src/test/java/test/TestMap.java | 36 +- src/test/java/test/TestNumber.java | 412 +++++++++--------- src/test/java/test/TestObject.java | 384 ++++++++-------- src/test/java/test/TestOperators.java | 12 +- src/test/java/test/TestReference.java | 34 +- .../{knapsack_11.leek => knapsack_2.leek} | 0 43 files changed, 771 insertions(+), 772 deletions(-) rename src/test/resources/ai/code/{knapsack_11.leek => knapsack_2.leek} (100%) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index cd21d0b3..8ad06a0b 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -103,7 +103,7 @@ public static AI compileFileContext(String filepath, String AIClass, ResolverCon } public static AI compileSnippet(String snippet, String AIClass) throws LeekScriptException, LeekCompilerException, IOException { - return compileSnippet(snippet, AIClass, 11); + return compileSnippet(snippet, AIClass, 2); } public static AI compileSnippet(String snippet, String AIClass, int version) throws LeekScriptException, LeekCompilerException, IOException { diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 60f14b95..d2cb7ad9 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -221,7 +221,7 @@ private void compileWord() throws LeekCompilerException { mCompiler.skipWord(); globalDeclaration(); return; - } else if (version >= 11 && word.getWord().equals("class")) { + } else if (version >= 2 && word.getWord().equals("class")) { // Déclaration de classe mCompiler.skipWord(); classDeclaration(); @@ -345,7 +345,7 @@ private void functionBlock() throws LeekCompilerException { boolean is_reference = false; if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("@")) { is_reference = true; - if (getVersion() >= 11) { + if (getVersion() >= 2) { addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, Error.REFERENCE_DEPRECATED)); } mCompiler.skipWord(); @@ -388,7 +388,7 @@ private void forBlock() throws LeekCompilerException { boolean reference1 = false; if (mCompiler.getWord().getWord().equals("@")) { reference1 = true; - if (getVersion() >= 11) { + if (getVersion() >= 2) { addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, Error.REFERENCE_DEPRECATED)); } mCompiler.skipWord(); @@ -410,7 +410,7 @@ private void forBlock() throws LeekCompilerException { boolean reference2 = false; if (mCompiler.getWord().getWord().equals("@")) { reference2 = true; - if (getVersion() >= 11) { + if (getVersion() >= 2) { addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, Error.REFERENCE_DEPRECATED)); } mCompiler.skipWord(); @@ -967,12 +967,12 @@ else if (type == 2) } retour.addExpression(array); - } else if (getVersion() >= 11 && word.getType() == WordParser.T_ACCOLADE_LEFT) { + } else if (getVersion() >= 2 && word.getType() == WordParser.T_ACCOLADE_LEFT) { // Déclaration d'un objet mCompiler.skipWord(); var object = new LeekObject(); - int type = 0; + while (mCompiler.getWord().getType() != WordParser.T_ACCOLADE_RIGHT) { if (mCompiler.getWord().getType() != WordParser.T_STRING) { throw new LeekCompilerException(mCompiler.getWord(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); @@ -1011,9 +1011,9 @@ else if (word.getWord().equalsIgnoreCase("null")) retour.addExpression(new LeekNull()); else if (word.getWord().equalsIgnoreCase("not")) retour.addUnaryPrefix(Operators.NOT, word); - else if (getVersion() >= 11 && word.getWord().equalsIgnoreCase("new")) { + else if (getVersion() >= 2 && word.getWord().equalsIgnoreCase("new")) { retour.addUnaryPrefix(Operators.NEW, word); - } else if (getVersion() >= 11 && word.getWord().equals("super")) { + } else if (getVersion() >= 2 && word.getWord().equals("super")) { // super doit être dans une méthode if (!(mCurentBlock instanceof ClassMethodBlock)) { errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.KEYWORD_MUST_BE_IN_CLASS)); @@ -1067,7 +1067,7 @@ else if (operator == Operators.INCREMENT) if (retour.getOperator() == -1) { result = retour.getExpression1(); } - if (getVersion() == 10 && result instanceof LeekExpression) { + if (getVersion() == 1 && result instanceof LeekExpression) { var expr = (LeekExpression) result; if (expr.getOperator() == Operators.NOT && expr.getExpression2() == null) { // Un "not" tout seul est valide en LS 1.0 @@ -1106,7 +1106,7 @@ private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerExcepti boolean is_reference = false; if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("@")) { is_reference = true; - if (getVersion() >= 11) { + if (getVersion() >= 2) { addError(new AnalyzeError(mCompiler.getWord(), AnalyzeErrorLevel.WARNING, Error.REFERENCE_DEPRECATED)); } mCompiler.skipWord(); diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index 5d50ada3..f258841c 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -127,12 +127,12 @@ else if (type == T_VAR_STRING && opener == c) { if (comment_line || comment_block) continue; if (c == '/' && length > i + 1 && code.charAt(i + 1) == '/') { comment_line = true; - if (version >= 11) i++; + if (version >= 2) i++; continue; } else if (c == '/' && length > i + 1 && code.charAt(i + 1) == '*') { comment_block = true; - if (version >= 11) i++; + if (version >= 2) i++; continue; } if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') { @@ -181,7 +181,7 @@ else if(c == '.') { word += c; } } - else if (version >= 11) { + else if (version >= 2) { if (type == T_STRING) { newWord(word, type); } diff --git a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java index 30013421..a73352a5 100644 --- a/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/AnonymousFunctionBlock.java @@ -103,7 +103,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } else { sb.append("var u_").append(parameter).append(" = "); - if (mainblock.getWordCompiler().getVersion() >= 11) { + if (mainblock.getWordCompiler().getVersion() >= 2) { sb.append("values[").append(i).append("]; ops(1);"); } else { // In LeekScript 1.0, load the value or reference diff --git a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java index 16cb9c6f..ea14501d 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachBlock.java @@ -52,7 +52,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { // Container writer.addCode("final var " + ar + " = ops("); - if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 2) { mArray.writeJavaCode(mainblock, writer); } else { writer.compileLoad(mainblock, mArray); @@ -63,7 +63,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { if (mIsDeclaration) { if (mIsDeclaration && declaration.isCaptured()) { writer.addCode("final Wrapper " + iterator_name + " = new Wrapper(new Box(" + writer.getAIThis() + ", null));"); - } else if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + } else if (mainblock.getCompiler().getCurrentAI().getVersion() >= 2) { writer.addLine("Object " + iterator_name + " = null;"); writer.addCounter(1); } else { @@ -74,7 +74,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } writer.addLine("for (var " + var + " : (ArrayLeekValue) " + ar + ") {"); - if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 2) { if (mIsDeclaration && declaration.isCaptured()) { writer.addLine(iterator_name + ".set(" + var + ".getValue());"); } else if (mReference) { @@ -115,7 +115,7 @@ public void analyze(WordCompiler compiler) { compiler.setCurrentBlock(this); // Si c'est une déclaration on vérifie que le nom est disponnible if (mIsDeclaration) { - if ((compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(mIterator.getWord()) || compiler.getMainBlock().hasUserFunction(mIterator.getWord(), true))) || compiler.getCurrentBlock().hasVariable(mIterator.getWord())) { + if ((compiler.getVersion() >= 2 && (compiler.getMainBlock().hasGlobal(mIterator.getWord()) || compiler.getMainBlock().hasUserFunction(mIterator.getWord(), true))) || compiler.getCurrentBlock().hasVariable(mIterator.getWord())) { compiler.addError(new AnalyzeError(mIterator, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); } else { this.addVariable(new LeekVariable(mIterator, VariableType.LOCAL, declaration)); diff --git a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java index 85ef8917..1f14f8f5 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java @@ -70,7 +70,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { // Container writer.addCode("final var " + ar + " = ops("); - if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 2) { mArray.writeJavaCode(mainblock, writer); } else { writer.compileLoad(mainblock, mArray); @@ -83,7 +83,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { if (mIsKeyDeclaration) { if (iteratorKeyDeclaration.isCaptured()) { sb.append("final Wrapper " + key_iterator + " = new Wrapper(new Box(" + writer.getAIThis() + ", null));"); - } else if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10) { + } else if (mainblock.getCompiler().getCurrentAI().getVersion() <= 1) { sb.append("var " + key_iterator + " = new Box(" + writer.getAIThis() + ", null);"); } else { sb.append("Object ").append(key_iterator).append(" = null; ops(1); "); @@ -95,9 +95,9 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { if (mIsDeclaration) { if (iteratorDeclaration.isCaptured()) { sb.append("final Wrapper " + val_iterator + " = new Wrapper(new Box(" + writer.getAIThis() + ", null));"); - } else if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + } else if (mainblock.getCompiler().getCurrentAI().getVersion() >= 2) { sb.append("Object " + val_iterator + " = null; ops(1);"); - } else if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10 || (iteratorDeclaration != null && iteratorDeclaration.isCaptured())) { + } else if (mainblock.getCompiler().getCurrentAI().getVersion() <= 1 || (iteratorDeclaration != null && iteratorDeclaration.isCaptured())) { sb.append("var " + val_iterator + " = new Box(" + writer.getAIThis() + ", null);"); } else { sb.append("Object ").append(val_iterator).append(" = null; ops(1);"); @@ -110,7 +110,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { sb.append("var ").append(var).append(" = ((ArrayLeekValue) ").append(ar).append(").getArrayIterator(); "); sb.append("while (!").append(var).append(".ended()) { ops(1); "); // Maj de la clé - if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 2) { if (mIsKeyDeclaration && iteratorKeyDeclaration.isCaptured()) { sb.append(key_iterator).append(".set(").append(var).append(".getKeyRef());"); } else { @@ -126,7 +126,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } } // Maj de la valeur - if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 2) { if (mValueReference) { sb.append(val_iterator).append(" = ").append(var).append(".value();"); } else if (mIsDeclaration && iteratorDeclaration.isCaptured()) { @@ -169,7 +169,7 @@ public void analyze(WordCompiler compiler) { // Si c'est une déclaration on vérifie que le nom est disponnible if (mIsKeyDeclaration) { - if ((compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(mKeyIterator.getWord()) || compiler.getMainBlock().hasUserFunction(mKeyIterator.getWord(), true))) || compiler.getCurrentBlock().hasVariable(mKeyIterator.getWord())) { + if ((compiler.getVersion() >= 2 && (compiler.getMainBlock().hasGlobal(mKeyIterator.getWord()) || compiler.getMainBlock().hasUserFunction(mKeyIterator.getWord(), true))) || compiler.getCurrentBlock().hasVariable(mKeyIterator.getWord())) { compiler.addError(new AnalyzeError(mKeyIterator, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); } else { this.addVariable(new LeekVariable(mKeyIterator, VariableType.LOCAL, iteratorKeyDeclaration)); @@ -182,7 +182,7 @@ public void analyze(WordCompiler compiler) { } // Si c'est une déclaration on vérifie que le nom est disponnible if (mIsDeclaration) { - if ((compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(mIterator.getWord()) || compiler.getMainBlock().hasUserFunction(mIterator.getWord(), true))) || compiler.getCurrentBlock().hasVariable(mIterator.getWord())) { + if ((compiler.getVersion() >= 2 && (compiler.getMainBlock().hasGlobal(mIterator.getWord()) || compiler.getMainBlock().hasUserFunction(mIterator.getWord(), true))) || compiler.getCurrentBlock().hasVariable(mIterator.getWord())) { compiler.addError(new AnalyzeError(mIterator, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); } else { this.addVariable(new LeekVariable(mIterator, VariableType.LOCAL, iteratorDeclaration)); diff --git a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java index 4189594f..9c5a71c6 100644 --- a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java @@ -101,7 +101,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { var declaration = mParameterDeclarations.get(i); if (declaration.isCaptured()) { sb.append("final var u_").append(parameter).append(" = new Wrapper("); - if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10) { + if (mainblock.getCompiler().getCurrentAI().getVersion() <= 1) { if (mReferences.get(i)) { sb.append("(p_").append(parameter).append(" instanceof Box) ? (Box) p_").append(parameter).append(" : new Box(" + writer.getAIThis() + ", ").append("p_").append(parameter).append("));"); } else { @@ -114,13 +114,13 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { sb.append("var u_").append(parameter).append(" = "); if (mReferences.get(i)) { sb.append("(p_").append(parameter).append(" instanceof Box) ? (Box) p_").append(parameter).append(" : new Box(" + writer.getAIThis()); - if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10) { + if (mainblock.getCompiler().getCurrentAI().getVersion() <= 1) { sb.append(", p_").append(parameter).append(");"); } else { sb.append(", copy(p_").append(parameter).append("));"); } } else { - if (mainblock.getCompiler().getCurrentAI().getVersion() <= 10) { + if (mainblock.getCompiler().getCurrentAI().getVersion() <= 1) { sb.append("new Box(" + writer.getAIThis() + ", copy(p_").append(parameter).append("));"); } else { sb.append("p_").append(parameter).append("; ops(1); "); diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 2c2988ea..2beae36d 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -211,7 +211,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { // Variables globales for (String global : mGlobales) { - if (getWordCompiler().getVersion() >= 11) { + if (getWordCompiler().getVersion() >= 2) { writer.addLine("private Object g_" + global + " = null;"); } else { writer.addLine("private Box g_" + global + " = new Box(" + writer.getAIThis() + ");"); diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index 8272b310..92424a38 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -717,7 +717,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { // Les assignations case Operators.ASSIGN: // Assign without clone for LS 1.1 or reference - if (mainblock.getWordCompiler().getVersion() >= 11) { + if (mainblock.getWordCompiler().getVersion() >= 2) { mExpression1.compileSet(mainblock, writer, mExpression2); } else if (mExpression2 instanceof LeekExpression && ((LeekExpression) mExpression2).getOperator() == Operators.REFERENCE) { mExpression1.compileSet(mainblock, writer, ((LeekExpression) mExpression2).mExpression2); @@ -786,7 +786,7 @@ public boolean isLeftValue() { @Override public void analyze(WordCompiler compiler) { - if (mOperator == Operators.REFERENCE && compiler.getVersion() >= 11) { + if (mOperator == Operators.REFERENCE && compiler.getVersion() >= 2) { compiler.addError(new AnalyzeError(mOperatorToken, AnalyzeErrorLevel.WARNING, Error.REFERENCE_DEPRECATED)); } diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 08c69acf..4f03bed1 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -187,7 +187,7 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("new Object[] { null }"); continue; } - if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 2) { parameter.writeJavaCode(mainblock, writer); } else { if (user_function != null) { diff --git a/src/main/java/leekscript/compiler/expression/LeekObject.java b/src/main/java/leekscript/compiler/expression/LeekObject.java index deb67101..ab639603 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObject.java +++ b/src/main/java/leekscript/compiler/expression/LeekObject.java @@ -1,6 +1,5 @@ package leekscript.compiler.expression; -import java.util.ArrayList; import java.util.HashMap; import leekscript.common.Type; @@ -62,7 +61,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } writer.addCode(" })"); } - + @Override public void analyze(WordCompiler compiler) { operations = 0; diff --git a/src/main/java/leekscript/compiler/expression/LeekString.java b/src/main/java/leekscript/compiler/expression/LeekString.java index 8aad896e..8f6f8645 100644 --- a/src/main/java/leekscript/compiler/expression/LeekString.java +++ b/src/main/java/leekscript/compiler/expression/LeekString.java @@ -47,7 +47,7 @@ else if (mString.charAt(i) == '\\') { if (len > i && mString.charAt(i + 1) == 'n') str += "\\"; else if (len > i && mString.charAt(i + 1) == 't') str += "\\"; else { - if (mainblock.getCompiler().getCurrentAI().getVersion() >= 11) { + if (mainblock.getCompiler().getCurrentAI().getVersion() >= 2) { if (len > i && mString.charAt(i + 1) == '\\') { str += "\\\\"; i++; diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index 961be021..73f62109 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -40,7 +40,7 @@ public LeekVariable(WordCompiler compiler, IAWord token, VariableType type) { this.type = type; this.declaration = null; this.classDeclaration = null; - this.box = compiler.getVersion() <= 10; + this.box = compiler.getVersion() <= 1; } public LeekVariable(IAWord token, VariableType type, boolean box) { @@ -200,7 +200,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("LeekValueManager.getFunction(" + namespace + "." + token.getWord() + ")"); } } else if (type == VariableType.GLOBAL) { - if (mainblock.getWordCompiler().getVersion() <= 10) { + if (mainblock.getWordCompiler().getVersion() <= 1) { writer.addCode("g_" + token.getWord() + ".getValue()"); } else { writer.addCode("g_" + token.getWord()); @@ -274,7 +274,7 @@ public void compileSet(MainLeekBlock mainblock, JavaWriter writer, AbstractExpre expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { - if (mainblock.getWordCompiler().getVersion() >= 11) { + if (mainblock.getWordCompiler().getVersion() >= 2) { writer.addCode("g_" + token.getWord() + " = "); expr.writeJavaCode(mainblock, writer); } else { @@ -285,7 +285,7 @@ public void compileSet(MainLeekBlock mainblock, JavaWriter writer, AbstractExpre } else { if (isWrapper()) { if (expr.isLeftValue()) { - if (mainblock.getWordCompiler().getVersion() <= 10) { + if (mainblock.getWordCompiler().getVersion() <= 1) { writer.addCode("u_" + token.getWord() + ".setBox("); } else { writer.addCode("u_" + token.getWord() + ".set("); @@ -328,7 +328,7 @@ public void compileSetCopy(MainLeekBlock mainblock, JavaWriter writer, AbstractE expr.writeJavaCode(mainblock, writer); writer.addCode(")"); } else if (type == VariableType.GLOBAL) { - if (mainblock.getWordCompiler().getVersion() >= 11) { + if (mainblock.getWordCompiler().getVersion() >= 2) { writer.addCode("g_" + token.getWord() + " = "); // writer.compileClone(mainblock, expr); expr.writeJavaCode(mainblock, writer); diff --git a/src/main/java/leekscript/compiler/expression/Operators.java b/src/main/java/leekscript/compiler/expression/Operators.java index 4188d2cd..bc41c6c7 100644 --- a/src/main/java/leekscript/compiler/expression/Operators.java +++ b/src/main/java/leekscript/compiler/expression/Operators.java @@ -85,7 +85,7 @@ public final static int getOperator(String operator, int version) { if(operator.equals("!==")) return NOT_EQUALS_EQUALS; if(operator.equals("^")) return BITXOR; if(operator.equals("^=")) { - if (version >= 11) { + if (version >= 2) { return BITXOR_ASSIGN; } else { // In LeekScript 1.0, ^= was still power assignment @@ -288,7 +288,7 @@ public static String getString(int operator, int version) { case POWER: return "**"; case POWERASSIGN: - return version == 10 ? "^=" : "**="; + return version == 1 ? "^=" : "**="; case NEW: return "new"; case BITNOT: diff --git a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java index 90460c32..5f97831a 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekGlobalDeclarationInstruction.java @@ -42,7 +42,7 @@ public String getCode() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("if (!g_init_" + token.getWord() + ") { "); - if (mainblock.getWordCompiler().getVersion() >= 11) { + if (mainblock.getWordCompiler().getVersion() >= 2) { writer.addCode("g_" + token.getWord() + " = "); if (mValue != null) { if (mValue.getOperations() > 0) writer.addCode("ops("); @@ -57,7 +57,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(", " + (mValue != null ? mValue.getOperations() : 0) + ")"); } writer.addCode("; g_init_" + token.getWord() + " = true;"); - if (mainblock.getWordCompiler().getVersion() >= 11) writer.addCode(" ops(1);"); + if (mainblock.getWordCompiler().getVersion() >= 2) writer.addCode(" ops(1);"); writer.addLine(" }", mLine, mAI); } diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index 4322b349..1726f3b9 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -32,7 +32,7 @@ public LeekVariableDeclarationInstruction(WordCompiler compiler, IAWord token, i mLine = line; mAI = ai; this.function = function; - this.box = compiler.getVersion() <= 10; + this.box = compiler.getVersion() <= 1; } public void setValue(AbstractExpression value) { @@ -80,7 +80,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine("), " + e.getOperations() + ")"); } writer.addLine(";", mLine, mAI); - } else if (mainblock.getWordCompiler().getVersion() <= 10) { + } else if (mainblock.getWordCompiler().getVersion() <= 1) { writer.addCode("final var u_" + token.getWord() + " = new Wrapper(new Box(" + writer.getAIThis() + ", "); if (mValue != null) mValue.compileL(mainblock, writer); else writer.addCode("null"); @@ -100,7 +100,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine(");", mLine, mAI); } } else { - if (mainblock.getWordCompiler().getVersion() <= 10) { + if (mainblock.getWordCompiler().getVersion() <= 1) { if (mValue instanceof LeekExpression && ((LeekExpression) mValue).getOperator() == Operators.REFERENCE) { var e = ((LeekExpression) mValue).getExpression2(); if (e.isLeftValue()) { @@ -183,11 +183,11 @@ public void analyze(WordCompiler compiler) { private void registerVariable(WordCompiler compiler) { // Variables interdites - if (compiler.getVersion() >= 11 && token.getWord().equals("this")) { + if (compiler.getVersion() >= 2 && token.getWord().equals("this")) { compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, Error.THIS_NOT_ALLOWED_HERE)); } else { // Vérification déjà existante (on vérifie les globales et fonctions seulement en 1.1 car il y a un léger bug en 1.0 avec les includes) - if ((compiler.getVersion() >= 11 && (compiler.getMainBlock().hasGlobal(token.getWord()) || compiler.getMainBlock().hasUserFunction(token.getWord(), true))) || compiler.getCurrentBlock().hasVariable(token.getWord())) { + if ((compiler.getVersion() >= 2 && (compiler.getMainBlock().hasGlobal(token.getWord()) || compiler.getMainBlock().hasUserFunction(token.getWord(), true))) || compiler.getCurrentBlock().hasVariable(token.getWord())) { compiler.addError(new AnalyzeError(token, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); } else { // On ajoute la variable diff --git a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java index f12ed638..a4574d42 100644 --- a/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java +++ b/src/main/java/leekscript/compiler/resolver/FileSystemResolver.java @@ -30,7 +30,7 @@ public AIFile resolve(String path, ResolverContext basecontex FileSystemContext newContext = new FileSystemContext(parent.toFile()); long timestamp = resolvedPath.toFile().lastModified(); - int version = resolvedPath.toFile().getName().contains("v10") ? 10 : 11; + int version = resolvedPath.toFile().getName().contains("v1") ? 1 : 2; return new AIFile(path, code, timestamp, version, newContext, resolvedPath.toString().hashCode() & 0xfffffff); diff --git a/src/main/java/leekscript/compiler/resolver/ResourceResolver.java b/src/main/java/leekscript/compiler/resolver/ResourceResolver.java index 10fa3d68..430fd0af 100644 --- a/src/main/java/leekscript/compiler/resolver/ResourceResolver.java +++ b/src/main/java/leekscript/compiler/resolver/ResourceResolver.java @@ -30,7 +30,7 @@ public AIFile resolve(String path, ResolverContext basecontext) long timestamp = resolvedPath.toFile().lastModified(); - return new AIFile(path, code, timestamp, 11, newContext, resolvedPath.toString().hashCode() & 0xfffffff); + return new AIFile(path, code, timestamp, 2, newContext, resolvedPath.toString().hashCode() & 0xfffffff); } catch (Exception e) { throw new FileNotFoundException(); diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 76af602c..175abd3f 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -409,7 +409,7 @@ public Object arrayFoldRight(ArrayLeekValue array, FunctionLeekValue function, O return result; } - public ArrayLeekValue arrayPartitionV10(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { + public ArrayLeekValue arrayPartitionV1(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { ArrayLeekValue list1 = new ArrayLeekValue(); ArrayLeekValue list2 = new ArrayLeekValue(); int nb = function.getArgumentsCount(this); @@ -466,7 +466,7 @@ public ArrayLeekValue arrayMap(ArrayLeekValue array, FunctionLeekValue function) return retour; } - public ArrayLeekValue arrayMapV10(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { + public ArrayLeekValue arrayMapV1(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { ArrayLeekValue retour = new ArrayLeekValue(); ArrayIterator iterator = array.getArrayIterator(); int nb = function.getArgumentsCount(this); @@ -483,7 +483,7 @@ public ArrayLeekValue arrayMapV10(ArrayLeekValue array, FunctionLeekValue functi return retour; } - public ArrayLeekValue arrayFilterV10(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { + public ArrayLeekValue arrayFilterV1(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { ArrayLeekValue retour = new ArrayLeekValue(); ArrayIterator iterator = array.getArrayIterator(); int nb = function.getArgumentsCount(this); @@ -528,7 +528,7 @@ public ArrayLeekValue arrayFilter(ArrayLeekValue array, FunctionLeekValue functi return retour; } - public Object arrayIterV10(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { + public Object arrayIterV1(ArrayLeekValue array, FunctionLeekValue function) throws LeekRunException { ArrayIterator iterator = array.getArrayIterator(); if (function == null) { return null; @@ -992,7 +992,7 @@ public Object add(Object x, Object y) throws LeekRunException { if (iterator.key() instanceof String) { retour.getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); } else { - if (getVersion() == 10) { + if (getVersion() == 1) { retour.push(this, LeekOperations.clone(this, iterator.getValue(this))); } else { retour.push(this, iterator.getValue(this)); @@ -1005,7 +1005,7 @@ public Object add(Object x, Object y) throws LeekRunException { if (iterator.key() instanceof String) { retour.getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); } else { - if (getVersion() == 10) { + if (getVersion() == 1) { retour.push(this, LeekOperations.clone(this, iterator.getValue(this))); } else { retour.push(this, iterator.getValue(this)); @@ -1027,7 +1027,7 @@ public Object add(Object x, Object y) throws LeekRunException { if (iterator.key() instanceof String) { retour.getOrCreate(this, iterator.getKey(this)).set(iterator.getValue(this)); } else { - if (getVersion() == 10) { + if (getVersion() == 1) { retour.push(this, LeekOperations.clone(this, iterator.getValue(this))); } else { retour.push(this, iterator.getValue(this)); @@ -1035,7 +1035,7 @@ public Object add(Object x, Object y) throws LeekRunException { } iterator.next(); } - if (getVersion() == 10) { + if (getVersion() == 1) { retour.push(this, LeekOperations.clone(this, y)); } else { retour.push(this, y); @@ -1088,7 +1088,7 @@ public Object mul(Object x, Object y) throws LeekRunException { public Object div(Object x, Object y) throws LeekRunException { double real_y = real(y); - if (version == 10 && real_y == 0) { + if (version == 1 && real_y == 0) { addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); return null; } @@ -1100,7 +1100,7 @@ public Object mod(Object x, Object y) throws LeekRunException { return real(x) % real(y); } var y_int = integer(y); - if (version == 10 && y_int == 0) { + if (version == 1 && y_int == 0) { addSystemLog(AILog.ERROR, Error.DIVISION_BY_ZERO); return null; } diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 2a6e3b15..32ecd6b3 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -526,7 +526,7 @@ public void addOperations(AI leekIA, ILeekFunction function, Object parameters[] public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { var array = (ArrayLeekValue) parameters[0]; var index = ((Number) parameters[2]).intValue(); - if (ai.getVersion() == 10) { + if (ai.getVersion() == 1) { array.insert(ai, LeekOperations.clone(ai, parameters[1]), index); } else { array.insert(ai, parameters[1], index); @@ -545,7 +545,7 @@ public void addOperations(AI ai, ILeekFunction function, Object parameters[], Ob @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { var array = (ArrayLeekValue) parameters[0]; - if (ai.getVersion() >= 11) { + if (ai.getVersion() >= 2) { array.push(ai, parameters[1]); } else { array.push(ai, LeekOperations.clone(ai, parameters[1])); @@ -557,7 +557,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le @Override public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { var array = (ArrayLeekValue) parameters[0]; - if (leekIA.getVersion() == 10) { + if (leekIA.getVersion() == 1) { var value = LeekOperations.clone(leekIA, parameters[1]); array.insert(leekIA, value, 0); } else { @@ -849,7 +849,7 @@ public Object run(AI leekIA, ILeekFunction function, Object... parameters) throw var array = (ArrayLeekValue) parameters[0]; var array2 = (ArrayLeekValue) parameters[1]; for (var value : array2) { - if (leekIA.getVersion() == 10) { + if (leekIA.getVersion() == 1) { array.push(leekIA, LeekOperations.clone(leekIA, value.getValue())); } else { array.push(leekIA, value.getValue()); @@ -880,20 +880,20 @@ public void addOperations(AI ai, ILeekFunction function, Object parameters[], Ob public Object run(AI leekIA, ILeekFunction function, Object... parameters) throws LeekRunException { var array = (ArrayLeekValue) parameters[0]; var fun = (FunctionLeekValue) parameters[1]; - if (leekIA.getVersion() >= 11) { + if (leekIA.getVersion() >= 2) { return leekIA.arrayMap(array, fun); } else { - return leekIA.arrayMapV10(array, fun); + return leekIA.arrayMapV1(array, fun); } } }, arrayFilter(2, new int[] { AI.ARRAY, AI.FUNCTION }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - if (ai.getVersion() >= 11) { + if (ai.getVersion() >= 2) { return ai.arrayFilter((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); } else { - return ai.arrayFilterV10((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); + return ai.arrayFilterV1((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); } } }, @@ -927,20 +927,20 @@ public Object run(AI leekIA, ILeekFunction function, Object... parameters) throw arrayPartition(2, new int[] { AI.ARRAY, AI.FUNCTION }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - if (ai.getVersion() >= 11) { + if (ai.getVersion() >= 2) { return ai.arrayPartition((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); } else { - return ai.arrayPartitionV10((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); + return ai.arrayPartitionV1((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); } } }, arrayIter(2, new int[] { AI.ARRAY, AI.FUNCTION }) { @Override public Object run(AI ai, ILeekFunction function, Object... parameters) throws LeekRunException { - if (ai.getVersion() >= 11) { + if (ai.getVersion() >= 2) { return ai.arrayIter((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); } else { - return ai.arrayIterV10((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); + return ai.arrayIterV1((ArrayLeekValue) parameters[0], (FunctionLeekValue) parameters[1]); } } }, diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index 16c7530d..6cd4ee71 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -86,7 +86,7 @@ public static Object getValue(Object value) { public static String doubleToString(AI ai, double value) throws LeekRunException { ai.ops(3); - if (ai.getVersion() >= 11) { + if (ai.getVersion() >= 2) { return String.valueOf((Double) value); } else { // if (((Double) value) == ((Double) value).intValue()) { @@ -206,16 +206,16 @@ public static int getType(Object v) { return 0; } - public static int getV10Type(Object v) { - if (v == null) return LeekValue.NULL_V10; - if (v instanceof Boolean) return LeekValue.BOOLEAN_V10; - if (v instanceof Number) return LeekValue.NUMBER_V10; - if (v instanceof String) return LeekValue.STRING_V10; - if (v instanceof ArrayLeekValue) return LeekValue.ARRAY_V10; - if (v instanceof ObjectLeekValue) return LeekValue.OBJECT_V10; - if (v instanceof ClassLeekValue) return LeekValue.CLASS_V10; - if (v instanceof FunctionLeekValue) return LeekValue.FUNCTION_V10; - if (v instanceof Box) return getV10Type(((Box) v).getValue()); + public static int getV1Type(Object v) { + if (v == null) return LeekValue.NULL_V1; + if (v instanceof Boolean) return LeekValue.BOOLEAN_V1; + if (v instanceof Number) return LeekValue.NUMBER_V1; + if (v instanceof String) return LeekValue.STRING_V1; + if (v instanceof ArrayLeekValue) return LeekValue.ARRAY_V1; + if (v instanceof ObjectLeekValue) return LeekValue.OBJECT_V1; + if (v instanceof ClassLeekValue) return LeekValue.CLASS_V1; + if (v instanceof FunctionLeekValue) return LeekValue.FUNCTION_V1; + if (v instanceof Box) return getV1Type(((Box) v).getValue()); return 0; } diff --git a/src/main/java/leekscript/runner/PhpArray.java b/src/main/java/leekscript/runner/PhpArray.java index 02b283c6..5232f467 100644 --- a/src/main/java/leekscript/runner/PhpArray.java +++ b/src/main/java/leekscript/runner/PhpArray.java @@ -26,14 +26,14 @@ public class PhpArray implements Iterable { public final static int ASC_K = 6; public final static int DESC_K = 7; - private class ElementComparatorV10 implements Comparator { + private class ElementComparatorV1 implements Comparator { private final int mOrder; public final static int SORT_ASC = 1; public final static int SORT_DESC = 2; - public ElementComparatorV10(int order) { + public ElementComparatorV1(int order) { mOrder = order; } @@ -51,20 +51,20 @@ else if (mOrder == SORT_DESC) } public int compareAsc(Object v1, Object v2) throws LeekRunException { - int type1 = LeekValueManager.getV10Type(v1); - int type2 = LeekValueManager.getV10Type(v2); + int type1 = LeekValueManager.getV1Type(v1); + int type2 = LeekValueManager.getV1Type(v2); if (type1 < type2) return -1; else if (type1 > type2) return 1; - if (type1 == LeekValue.BOOLEAN_V10) { + if (type1 == LeekValue.BOOLEAN_V1) { if ((Boolean) v1 == (Boolean) v2) return 0; else if ((Boolean) v1) return 1; else return -1; - } else if (type1 == LeekValue.NUMBER_V10) { + } else if (type1 == LeekValue.NUMBER_V1) { var d = ((Number) v2).doubleValue(); if (((Number) v1).doubleValue() == d) return 0; @@ -72,9 +72,9 @@ else if (((Number) v1).doubleValue() < d) return -1; else return 1; - } else if (type1 == LeekValue.STRING_V10) { + } else if (type1 == LeekValue.STRING_V1) { return ((String) v1).compareTo((String) v2); - } else if (type1 == LeekValue.ARRAY_V10) { + } else if (type1 == LeekValue.ARRAY_V1) { var a = (ArrayLeekValue) v2; if (((ArrayLeekValue) v1).size() == a.size()) return 0; @@ -280,7 +280,7 @@ public PhpArray(AI ai, PhpArray phpArray, int level) throws LeekRunException { initTable(ai, phpArray.size()); Element e = phpArray.mHead; while (e != null) { - if (ai.getVersion() >= 11) { + if (ai.getVersion() >= 2) { if (level == 1) { set(ai, e.key, e.value.getValue()); } else { @@ -476,8 +476,8 @@ else if (comparator == ASC_K || comparator == DESC_K) { (comparator == ASC_K) ? ElementComparator.SORT_ASC : ElementComparator.SORT_DESC)); } else { - if (ai.getVersion() == 10) { - Collections.sort(liste, new ElementComparatorV10( + if (ai.getVersion() == 1) { + Collections.sort(liste, new ElementComparatorV1( (comparator == ASC || comparator == ASC_A) ? ElementComparator.SORT_ASC : ElementComparator.SORT_DESC)); } else { diff --git a/src/main/java/leekscript/runner/values/ArrayLeekValue.java b/src/main/java/leekscript/runner/values/ArrayLeekValue.java index 5ff5b695..d73e5599 100644 --- a/src/main/java/leekscript/runner/values/ArrayLeekValue.java +++ b/src/main/java/leekscript/runner/values/ArrayLeekValue.java @@ -39,7 +39,7 @@ public void next() { } public Object getKey(AI ai) throws LeekRunException { - if (ai.getVersion() >= 11) { + if (ai.getVersion() >= 2) { return mElement.key(); } else { return LeekOperations.clone(ai, mElement.key()); @@ -51,7 +51,7 @@ public Object key() { } public Object getValue(AI ai) throws LeekRunException { - if (ai.getVersion() >= 11) { + if (ai.getVersion() >= 2) { return mElement.value(); } else { return LeekOperations.clone(ai, mElement.value()); @@ -124,7 +124,7 @@ public Box getOrCreate(AI ai, Object keyValue) throws LeekRunException { public Object put(AI ai, Object keyValue, Object value) throws LeekRunException { // ai.ops(1); var key = transformKey(ai, keyValue); - if (ai.getVersion() == 10) { + if (ai.getVersion() == 1) { value = LeekOperations.clone(ai, value); } mValues.set(ai, key, value); @@ -330,7 +330,7 @@ public boolean equals(AI ai, Object comp) throws LeekRunException { } else if (mValues.size() == 1) { // Si y'a un seul élément dans le tableau var firstValue = mValues.getHeadElement().value(); if (firstValue == null && comp == null) { - return ai.getVersion() == 10; // Bug in 1.0, [null] == null + return ai.getVersion() == 1; // Bug in LS1, [null] == null } return ai.eq(firstValue, comp); } else if (comp instanceof Boolean) { diff --git a/src/main/java/leekscript/runner/values/Box.java b/src/main/java/leekscript/runner/values/Box.java index d3b28c2f..90e144d6 100644 --- a/src/main/java/leekscript/runner/values/Box.java +++ b/src/main/java/leekscript/runner/values/Box.java @@ -19,7 +19,7 @@ public Box(AI ai, Object value) throws LeekRunException { mUAI = ai; // System.out.println("ops Box"); ai.ops(1); - if (ai.getVersion() >= 11) { + if (ai.getVersion() >= 2) { mValue = value; } else if (value instanceof Box) { mValue = LeekOperations.clone(ai, ((Box) value).getValue()); @@ -39,7 +39,7 @@ public Object getValue() { public Object set(Object value) throws LeekRunException { // mUAI.ops(1); - if (mUAI.getVersion() >= 11) { + if (mUAI.getVersion() >= 2) { return mValue = LeekValueManager.getValue(value); } else { if (value instanceof Box) { @@ -56,7 +56,7 @@ public Object setRef(Object value) throws LeekRunException { public void initGlobal(Object value) throws LeekRunException { if (value instanceof Box) { - if (mUAI.getVersion() >= 11) { + if (mUAI.getVersion() >= 2) { mValue = value; } else { mValue = LeekOperations.clone(mUAI, value); diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index 948a2048..5e7207b1 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -101,7 +101,7 @@ else if (mType == USER_FUNCTION) { ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { LeekValue.getParamString(values), String.valueOf(ai.userFunctionCount(mId)) }); } else { - if (ai.getVersion() >= 11) { + if (ai.getVersion() >= 2) { return ai.userFunctionExecute(mId, values); } else { return ai.userFunctionExecute(mId, copyValues(ai, values, ai.userFunctionReference(mId))); diff --git a/src/main/java/leekscript/runner/values/LeekValue.java b/src/main/java/leekscript/runner/values/LeekValue.java index fd9768c9..be829014 100644 --- a/src/main/java/leekscript/runner/values/LeekValue.java +++ b/src/main/java/leekscript/runner/values/LeekValue.java @@ -2,14 +2,14 @@ public class LeekValue { - public final static int NUMBER_V10 = 1; - public final static int BOOLEAN_V10 = 2; - public final static int ARRAY_V10 = 3; - public final static int NULL_V10 = 4; - public final static int STRING_V10 = 5; - public final static int FUNCTION_V10 = 6; - public final static int CLASS_V10 = 7; - public final static int OBJECT_V10 = 8; + public final static int NUMBER_V1 = 1; + public final static int BOOLEAN_V1 = 2; + public final static int ARRAY_V1 = 3; + public final static int NULL_V1 = 4; + public final static int STRING_V1 = 5; + public final static int FUNCTION_V1 = 6; + public final static int CLASS_V1 = 7; + public final static int OBJECT_V1 = 8; public final static int NULL = 0; public final static int NUMBER = 1; diff --git a/src/test/java/test/TestAI.java b/src/test/java/test/TestAI.java index 922eb0b3..b8ec76e6 100644 --- a/src/test/java/test/TestAI.java +++ b/src/test/java/test/TestAI.java @@ -6,7 +6,7 @@ public class TestAI extends AI { public TestAI() throws Exception { - super(0, 11); + super(0, 2); } @Override @@ -46,7 +46,7 @@ public boolean[] anonymousFunctionReference(int id) { @Override public int getVersion() { - return 11; + return 2; } @Override diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index 6f56b73d..5152493a 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -14,19 +14,19 @@ public void run() throws Exception { code("return [1];").equals("[1]"); code("return [1, 2, 3];").equals("[1, 2, 3]"); // DISABLED_code("[1l, 2l, 3l]").equals("[1, 2, 3]"); - code_v10("return [1.21, -5, 4.55, 12, -6.7];").equals("[1,21, -5, 4,55, 12, -6,7]"); - code_v11("return [1.21, -5, 4.55, 12, -6.7];").equals("[1.21, -5, 4.55, 12, -6.7]"); + code_v1("return [1.21, -5, 4.55, 12, -6.7];").equals("[1,21, -5, 4,55, 12, -6,7]"); + code_v2("return [1.21, -5, 4.55, 12, -6.7];").equals("[1.21, -5, 4.55, 12, -6.7]"); code("return [true, false, true];").equals("[true, false, true]"); - code_v11("[23, true, '', {}, 123]").equals("[23, true, '', {}, 123]"); + code_v2("[23, true, '', {}, 123]").equals("[23, true, '', {}, 123]"); // DISABLED_code("var a = x -> x [1, 2, a]").equals("[1, 2, ]"); // DISABLED_code("[1m, 34324234m, 231232131232132134379897874534243257343341432423m]").equals("[1, 34324234, 231232131232132134379897874534243257343341432423]"); // DISABLED_code("[true, 'hello', 231232131232132134379897874534243257343341432423m]").equals("[true, 'hello', 231232131232132134379897874534243257343341432423]"); section("Array & variables"); code("var a = []; return a;").equals("[]"); - code_v10("var a = @[]; return a;").equals("[]"); - code_v10("var a = [1, 2, 3] var b = a push(b, 4) return a;").equals("[1, 2, 3]"); - code_v10("var a = [1, 2, 3] var b = (function() { return @a })() push(b, 4) return a;").equals("[1, 2, 3, 4]"); + code_v1("var a = @[]; return a;").equals("[]"); + code_v1("var a = [1, 2, 3] var b = a push(b, 4) return a;").equals("[1, 2, 3]"); + code_v1("var a = [1, 2, 3] var b = (function() { return @a })() push(b, 4) return a;").equals("[1, 2, 3, 4]"); section("Array.operator +"); code("return [1, 2, 3] + [4, 5, 6];").equals("[1, 2, 3, 4, 5, 6]"); @@ -41,10 +41,10 @@ public void run() throws Exception { // DISABLED_code("return [1] + null;").equals("[1, null]"); // DISABLED_code("return [1] + true;").equals("[1, true]"); code("return [1] + [2] + [3];").equals("[1, 2, 3]"); - code_v10("return [1] + [2.5] + ['a'];").equals("[1, 2,5, a]"); - code_v11("return [1] + [2.5] + ['a'];").equals("[1, 2.5, a]"); - code_v10("return ['a'] + [2.5] + [1];").equals("[a, 2,5, 1]"); - code_v11("return ['a'] + [2.5] + [1];").equals("[a, 2.5, 1]"); + code_v1("return [1] + [2.5] + ['a'];").equals("[1, 2,5, a]"); + code_v2("return [1] + [2.5] + ['a'];").equals("[1, 2.5, a]"); + code_v1("return ['a'] + [2.5] + [1];").equals("[a, 2,5, 1]"); + code_v2("return ['a'] + [2.5] + [1];").equals("[a, 2.5, 1]"); code("return [1] + ['a'];").equals("[1, a]"); code("return ['a'] + [1];").equals("[a, 1]"); // DISABLED_code("return [12.5] + null;").equals("[12.5, null]"); @@ -59,10 +59,10 @@ public void run() throws Exception { // DISABLED_code("var a = ['yo'] return a + '!';").equals("['yo', '!']"); code("var a = [5] var b = ['b'] return a + b;").equals("[5, b]"); code("var a = ['a'] return a + ['b'];").equals("[a, b]"); - code_v11("[1, 2] + {};").equals("[1, 2, {}]"); - code_v11("var a = [1, 2] a + {};").equals("[1, 2, {}]"); - code_v11("['a', 'b'] + {};").equals("['a', 'b', {}]"); - code_v11("var a = ['a', 'b'] a + {}").equals("['a', 'b', {}]"); + code_v2("[1, 2] + {};").equals("[1, 2, {}]"); + code_v2("var a = [1, 2] a + {};").equals("[1, 2, {}]"); + code_v2("['a', 'b'] + {};").equals("['a', 'b', {}]"); + code_v2("var a = ['a', 'b'] a + {}").equals("['a', 'b', {}]"); // DISABLED_code("return ['a', 'b'] + (x -> x)").equals("['a', 'b', ]"); // DISABLED_code("var a = ['a', 'b'] a + (x -> x)").equals("['a', 'b', ]"); // DISABLED_code("['a', 'b'] + Number").equals("['a', 'b', ]"); @@ -81,22 +81,22 @@ public void run() throws Exception { section("Array misc"); code("return [1, 2, 3] + null").equals("[1, 2, 3, null]"); code("var a = [1] return a % 2").equals("1"); - code_v10("var a = [[1], [1]]; return (a[0] + a[2]) / 2").equals("1"); - code_v11("var a = [[1], [1]]; return (a[0] + a[2]) / 2").equals("1.0"); - code_v10("var effects = [[1], [1]];\n\nreturn (effects[0] + effects[2]) /2;").equals("1"); - code_v11("var effects = [[1], [1]];\n\nreturn (effects[0] + effects[2]) /2;").equals("1.0"); + code_v1("var a = [[1], [1]]; return (a[0] + a[2]) / 2").equals("1"); + code_v2("var a = [[1], [1]]; return (a[0] + a[2]) / 2").equals("1.0"); + code_v1("var effects = [[1], [1]];\n\nreturn (effects[0] + effects[2]) /2;").equals("1"); + code_v2("var effects = [[1], [1]];\n\nreturn (effects[0] + effects[2]) /2;").equals("1.0"); section("Array.operator []"); code("return [1, 2, 3][1]").equals("2"); code("var a = [1, 2, 3] return a[0]").equals("1"); - code_v10("var a = [1.6, 2.5, 3.4] return a[0]").equals("1,6"); - code_v11("var a = [1.6, 2.5, 3.4] return a[0]").equals("1.6"); + code_v1("var a = [1.6, 2.5, 3.4] return a[0]").equals("1,6"); + code_v2("var a = [1.6, 2.5, 3.4] return a[0]").equals("1.6"); code("var a = [1, 2, 3] a[0] = 5 return a[0]").equals("5"); // code("var a = [23, 23, true, '', [], 123]; return |a|").equals("6"); code("var a = [] return !a").equals("true"); code("var a = [1, 2, 3] a[1] = 12 return a").equals("[1, 12, 3]"); - code_v10("return [1.2, 321.42, 23.15]").equals("[1,2, 321,42, 23,15]"); - code_v11("return [1.2, 321.42, 23.15]").equals("[1.2, 321.42, 23.15]"); + code_v1("return [1.2, 321.42, 23.15]").equals("[1,2, 321,42, 23,15]"); + code_v2("return [1.2, 321.42, 23.15]").equals("[1.2, 321.42, 23.15]"); // code("return [1, 2, 3, 4, 5][1:3]").equals("[2, 3, 4]"); code("var a = [5, 'yolo', 12] return a[1]").equals("yolo"); code("var a = [12]; a[0]++; return a").equals("[13]"); @@ -104,19 +104,19 @@ public void run() throws Exception { code("return ['a', 'b', 'c'][[2, ''][0]]").equals("c"); code("var a = [[12], ''][0]; a[0]++; return a").equals("[13]"); // code("var a = [[12], ''][0] a[a]++ a").exception(ls::vm::Exception::ARRAY_KEY_IS_NOT_NUMBER); - code_v10("var a = [[12], [5.5], ['a']] a[0][0] += 1 a[1][0] += 1 a[2][0] += 1 return a").equals("[[13], [6,5], [a1]]"); - code_v11("var a = [[12], [5.5], ['a']] a[0][0] += 1 a[1][0] += 1 a[2][0] += 1 return a").equals("[[13], [6.5], [a1]]"); + code_v1("var a = [[12], [5.5], ['a']] a[0][0] += 1 a[1][0] += 1 a[2][0] += 1 return a").equals("[[13], [6,5], [a1]]"); + code_v2("var a = [[12], [5.5], ['a']] a[0][0] += 1 a[1][0] += 1 a[2][0] += 1 return a").equals("[[13], [6.5], [a1]]"); // code("var a = [1, 2, 3] return a[0l]").equals("1"); // code("var a = [1, 2, 3] return a[1l]").equals("2"); // code("var a = [1, 2, 3] return a[2m]").equals("3"); code("var a = ['a', 'b', 'c'] return a[0.5]").equals("a"); code("var a = ['a', 'b', 'c'] return a[1.9]").equals("b"); code("return ['', [2][0]]").equals("[, 2]"); - code_v10("return ['', [2.5][0]]").equals("[, 2,5]"); - code_v11("return ['', [2.5][0]]").equals("[, 2.5]"); + code_v1("return ['', [2.5][0]]").equals("[, 2,5]"); + code_v2("return ['', [2.5][0]]").equals("[, 2.5]"); code("var a = [1, 2, 3] return a[true]").equals("2"); - code_v10("return [1, 2.5][1]").equals("2,5"); - code_v11("return [1, 2.5][1]").equals("2.5"); + code_v1("return [1, 2.5][1]").equals("2,5"); + code_v2("return [1, 2.5][1]").equals("2.5"); code("return [1, true][0]").equals("1"); code("return [1, true][1]").equals("true"); // code("return [5l, 7l, 9l][2l]").equals("9"); @@ -153,8 +153,8 @@ public void run() throws Exception { code("return [1, 2, 3][false]").equals("1"); code("return [1, 2, 3][true]").equals("2"); code("return ['1', '2', '3'][false]").equals("1"); - code_v10("return [1.5, 2.5, 3.5][true]").equals("2,5"); - code_v11("return [1.5, 2.5, 3.5][true]").equals("2.5"); + code_v1("return [1.5, 2.5, 3.5][true]").equals("2,5"); + code_v2("return [1.5, 2.5, 3.5][true]").equals("2.5"); // section("Push with empty array access"); // code("var a = [] a[] = 12 return a").equals("[12]"); @@ -177,8 +177,8 @@ public void run() throws Exception { // DISABLED_code("var a = [1, 2, 3] a[0] += 5 return a[0];").equals("6"); // DISABLED_code("var v = 12 var a = [v, 2, 3] a[0] += 5 return a[0];").equals("17"); // DISABLED_code("var a = [1, 2, 3] a += 'hello' return a;").equals("[1, 2, 3, 'hello']"); - code_v10("var a = [1.5] a += ['a', 'b'] return a").equals("[1,5, a, b]"); - code_v11("var a = [1.5] a += ['a', 'b'] return a").equals("[1.5, a, b]"); + code_v1("var a = [1.5] a += ['a', 'b'] return a").equals("[1,5, a, b]"); + code_v2("var a = [1.5] a += ['a', 'b'] return a").equals("[1.5, a, b]"); // DISABLED_code("var a = [1.5] a += false return a;").equals("[1.5, false]"); // DISABLED_code("var a = [1] a += <2, 3> a").equals("[1, 2, 3]"); // DISABLED_code("var a = [1] a += <5.5, 7.314> a").equals("[1, 5.5, 7.314]"); @@ -187,16 +187,16 @@ public void run() throws Exception { // DISABLED_code("var a = [1] a += <'z', 'a'> a").equals("[1, 'a', 'z']"); // DISABLED_code("var a = [1] a += 'a' return a;").equals("[1, 'a']"); // DISABLED_code("var a = [[1]] a[0] += [12, ''][0] return a[0];").equals("[1, 12]"); - code_v10("var a = [1.11] a += [2, 3] return a").equals("[1,11, 2, 3]"); - code_v11("var a = [1.11] a += [2, 3] return a").equals("[1.11, 2, 3]"); + code_v1("var a = [1.11] a += [2, 3] return a").equals("[1,11, 2, 3]"); + code_v2("var a = [1.11] a += [2, 3] return a").equals("[1.11, 2, 3]"); // DISABLED_code("var a = [[1.55]] a[0] += [12.9, ''][0] return a[0];").equals("[1.55, 12.9]"); // DISABLED_code("var a = [[1.55]] a[0] += [-1.5, 6.7] return a[0];").equals("[1.55, -1.5, 6.7]"); // DISABLED_code("var a = [[1.55]] a[0] += <8, 4> a[0]").equals("[1.55, 4, 8]"); // DISABLED_code("var a = [[1.55]] a[0] += < -8.5, 4.7> a[0]").equals("[1.55, -8.5, 4.7]"); // DISABLED_code("var a = [[1.55]] a[0] += < -8.5, 4.7, 'hello'> a[0]").equals("[1.55, -8.5, 4.7, 'hello']"); code("var a = ['a'] return a += [1, 2]").equals("[a, 1, 2]"); - code_v10("var a = ['a'] return a += [1.5, 2.5]").equals("[a, 1,5, 2,5]"); - code_v11("var a = ['a'] return a += [1.5, 2.5]").equals("[a, 1.5, 2.5]"); + code_v1("var a = ['a'] return a += [1.5, 2.5]").equals("[a, 1,5, 2,5]"); + code_v2("var a = ['a'] return a += [1.5, 2.5]").equals("[a, 1.5, 2.5]"); // DISABLED_code("var a = ['a'] a += <1, 2>").equals("['a', 1, 2]"); // DISABLED_code("var a = ['a'] a += <1.5, 2.5>").equals("['a', 1.5, 2.5]"); // DISABLED_code("var a = ['a'] var b = <'b'> a += b a").equals("['a', 'b']"); @@ -207,8 +207,8 @@ public void run() throws Exception { // DISABLED_code("var a = [] if (true) a += 12 return a;").equals("[12]"); // DISABLED_code("var a = [1] if (true) a += 12 return a;").equals("[1, 12]"); // DISABLED_code("var a = ['a'] if (true) a += 12 return a;").equals("['a', 12]"); - code_v10("var a = [1.55]; a += 12.9; return a").equals("[1,55, 12,9]"); - code_v11("var a = [1.55]; a += 12.9; return a").equals("[1.55, 12.9]"); + code_v1("var a = [1.55]; a += 12.9; return a").equals("[1,55, 12,9]"); + code_v2("var a = [1.55]; a += 12.9; return a").equals("[1.55, 12.9]"); section("Array.operator += on element"); code("var a = [5] a[0] += 1 return a;").equals("[6]"); @@ -271,8 +271,8 @@ public void run() throws Exception { code("var a = [87619] a[0] &= 18431 return a;").equals("[17987]"); section("Array.operator ^= on element"); - code_v10("var a = [876] a[0] ^= 3 return a;").equals("[672221376]"); - code_v11("var a = [876] a[0] ^= 3 return a;").equals("[879]"); + code_v1("var a = [876] a[0] ^= 3 return a;").equals("[672221376]"); + code_v2("var a = [876] a[0] ^= 3 return a;").equals("[879]"); section("Array.operator <<= on element"); code("var a = [123] a[0] <<= 12 return a;").equals("[503808]"); @@ -310,16 +310,16 @@ public void run() throws Exception { code("return function() { var a = [1, 2, 3]; pushAll(a, [5, 6, 7]); return a; }();").equals("[1, 2, 3, 5, 6, 7]"); section("Array.filter() v1.0"); - code_v10("return arrayFilter([1, 2, 3, 4, 5, 6, 7, 8, 9], function(e) { return e > 5; });").equals("[5 : 6, 6 : 7, 7 : 8, 8 : 9]"); - code_v10("return arrayFilter([4, 5, 6, 'test', 8, 9], function(e) { return e == 'test'; });").equals("[3 : test]"); - code_v10("return arrayFilter(['a', 'b', 'c', 'd'], function(k, v) { return k == 3; });").equals("[3 : d]"); - code_v10("return function() { var t = ['a', 'b', 'c', 'd']; arrayFilter(t, function(k, @v) { v = 4; return k == 3; }); return t; }();").equals("[4, 4, 4, 4]"); - code_v10("return arrayFilter(['a', 'b', 'c', 'd'], function(k, @v) { v = 4; return k == 3; });").equals("[3 : 4]"); + code_v1("return arrayFilter([1, 2, 3, 4, 5, 6, 7, 8, 9], function(e) { return e > 5; });").equals("[5 : 6, 6 : 7, 7 : 8, 8 : 9]"); + code_v1("return arrayFilter([4, 5, 6, 'test', 8, 9], function(e) { return e == 'test'; });").equals("[3 : test]"); + code_v1("return arrayFilter(['a', 'b', 'c', 'd'], function(k, v) { return k == 3; });").equals("[3 : d]"); + code_v1("return function() { var t = ['a', 'b', 'c', 'd']; arrayFilter(t, function(k, @v) { v = 4; return k == 3; }); return t; }();").equals("[4, 4, 4, 4]"); + code_v1("return arrayFilter(['a', 'b', 'c', 'd'], function(k, @v) { v = 4; return k == 3; });").equals("[3 : 4]"); section("Array.filter() v1.1"); - code_v11("return arrayFilter([1, 2, 3, 4, 5, 6, 7, 8, 9], function(e) { return e > 5; });").equals("[6, 7, 8, 9]"); - code_v11("return arrayFilter([4, 5, 6, 'test', 8, 9], function(e) { return e == 'test'; });").equals("[test]"); - code_v11("return string(arrayFilter(['a', 'b', 'c', 'd'], function(k, v) { return k == 3; }));").equals("[d]"); + code_v2("return arrayFilter([1, 2, 3, 4, 5, 6, 7, 8, 9], function(e) { return e > 5; });").equals("[6, 7, 8, 9]"); + code_v2("return arrayFilter([4, 5, 6, 'test', 8, 9], function(e) { return e == 'test'; });").equals("[test]"); + code_v2("return string(arrayFilter(['a', 'b', 'c', 'd'], function(k, v) { return k == 3; }));").equals("[d]"); section("Array.flatten()"); code("return arrayFlatten([6,7,[8,9]],99);").equals("[6, 7, 8, 9]"); @@ -327,37 +327,37 @@ public void run() throws Exception { code("return arrayFlatten([6,[[7]],[8,9]]);").equals("[6, [7], 8, 9]"); section("Array.sort"); - code_v10("return function() { var t = [null, null, 4, 8, 9]; sort(t); return t; }();").equals("[4, 8, 9, null, null]"); - code_v11("return function() { var t = [null, null, 4, 8, 9]; sort(t); return t; }();").equals("[null, null, 4, 8, 9]"); - code_v10("return function() { var t = [4, null, 4, null, 4]; sort(t); return t; }();").equals("[4, 4, 4, null, null]"); - code_v11("return function() { var t = [4, null, 4, null, 4]; sort(t); return t; }();").equals("[null, null, 4, 4, 4]"); - code_v10("return function() { var t = [4, null, 5, null, 8]; sort(t, SORT_DESC); return t; }();").equals("[null, null, 8, 5, 4]"); - code_v11("return function() { var t = [4, null, 5, null, 8]; sort(t, SORT_DESC); return t; }();").equals("[8, 5, 4, null, null]"); + code_v1("return function() { var t = [null, null, 4, 8, 9]; sort(t); return t; }();").equals("[4, 8, 9, null, null]"); + code_v2("return function() { var t = [null, null, 4, 8, 9]; sort(t); return t; }();").equals("[null, null, 4, 8, 9]"); + code_v1("return function() { var t = [4, null, 4, null, 4]; sort(t); return t; }();").equals("[4, 4, 4, null, null]"); + code_v2("return function() { var t = [4, null, 4, null, 4]; sort(t); return t; }();").equals("[null, null, 4, 4, 4]"); + code_v1("return function() { var t = [4, null, 5, null, 8]; sort(t, SORT_DESC); return t; }();").equals("[null, null, 8, 5, 4]"); + code_v2("return function() { var t = [4, null, 5, null, 8]; sort(t, SORT_DESC); return t; }();").equals("[8, 5, 4, null, null]"); section("Array and references"); - code_v10("var t = [@3, @4, @5]; return t;").equals("[3, 4, 5]"); - code_v10("var t = [3, 4, 5]; var a = 12; t[1] = @a return t;").equals("[3, 12, 5]"); - code_v10("var t = [3, 4, 5]; var a = @t[1] a++ return t;").equals("[3, 4, 5]"); - code_v10("var t = [3, 4, 5]; var a = null a = @t[1] a++ return t;").equals("[3, 4, 5]"); - code_v10("var t = [3, 4, 5]; t[3] = [1, 2, 3, 4]; var r = @t[3]; r[4] = 'coucou'; return t;").equals("[3, 4, 5, [1, 2, 3, 4, coucou]]"); + code_v1("var t = [@3, @4, @5]; return t;").equals("[3, 4, 5]"); + code_v1("var t = [3, 4, 5]; var a = 12; t[1] = @a return t;").equals("[3, 12, 5]"); + code_v1("var t = [3, 4, 5]; var a = @t[1] a++ return t;").equals("[3, 4, 5]"); + code_v1("var t = [3, 4, 5]; var a = null a = @t[1] a++ return t;").equals("[3, 4, 5]"); + code_v1("var t = [3, 4, 5]; t[3] = [1, 2, 3, 4]; var r = @t[3]; r[4] = 'coucou'; return t;").equals("[3, 4, 5, [1, 2, 3, 4, coucou]]"); section("Array.map()"); code("return arrayMap([1, 2, 3], function(v) { var r = [] return r })").equals("[[], [], []]"); code("return arrayMap([1, 2, 3], function(v) { var r = [1, 2, 3] return r })").equals("[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"); code("var r = [] var a = arrayMap([1, 2, 3], function(v) { return r }) push(r, 1) return a").equals("[[1], <...>, <...>]"); - code_v11("class A { name part constructor(name, part) { this.name = name this.part = part } } var list = [new A('foo', true), new A('bar', false), new A('baz', true)] return arrayMap(list, function(a) { return a.name })").equals("[foo, bar, baz]"); + code_v2("class A { name part constructor(name, part) { this.name = name this.part = part } } var list = [new A('foo', true), new A('bar', false), new A('baz', true)] return arrayMap(list, function(a) { return a.name })").equals("[foo, bar, baz]"); section("Array.map() v1.0"); - code_v10("return arrayMap([1, 2, 3, 4, 5], function(e) { return e * 2; });").equals("[2, 4, 6, 8, 10]"); - code_v10("return arrayMap([4, 9, 16], sqrt);").equals("[2, 3, 4]"); - code_v10("return arrayMap(['a': 1,'b': 2], function(k, v) { return k + v; });").equals("[a : a1, b : b2]"); - code_v10("return function() { var t = ['a':1,'b':2]; arrayMap(t, function(@k, @v) { v = 'tomate'; k = 'ctus'; return 3; }); return t; }();").equals("[a : tomate, b : tomate]"); + code_v1("return arrayMap([1, 2, 3, 4, 5], function(e) { return e * 2; });").equals("[2, 4, 6, 8, 10]"); + code_v1("return arrayMap([4, 9, 16], sqrt);").equals("[2, 3, 4]"); + code_v1("return arrayMap(['a': 1,'b': 2], function(k, v) { return k + v; });").equals("[a : a1, b : b2]"); + code_v1("return function() { var t = ['a':1,'b':2]; arrayMap(t, function(@k, @v) { v = 'tomate'; k = 'ctus'; return 3; }); return t; }();").equals("[a : tomate, b : tomate]"); section("Array.map() v1.1"); - code_v11("return arrayMap([1, 2, 3, 4, 5], function(e) { return e * 2; });").equals("[2, 4, 6, 8, 10]"); - code_v11("return arrayMap([4, 9, 16], sqrt);").equals("[2.0, 3.0, 4.0]"); - code_v11("return arrayMap(['a': 1, 'b': 2], function(k, v) { return k + v; });").equals("[a : a1, b : b2]"); - code_v11("return function() { var t = ['a': 1, 'b': 2]; arrayMap(t, function(k, v) { v = 'tomate'; k = 'ctus'; return 3; }); return t; }();").equals("[a : 1, b : 2]"); + code_v2("return arrayMap([1, 2, 3, 4, 5], function(e) { return e * 2; });").equals("[2, 4, 6, 8, 10]"); + code_v2("return arrayMap([4, 9, 16], sqrt);").equals("[2.0, 3.0, 4.0]"); + code_v2("return arrayMap(['a': 1, 'b': 2], function(k, v) { return k + v; });").equals("[a : a1, b : b2]"); + code_v2("return function() { var t = ['a': 1, 'b': 2]; arrayMap(t, function(k, v) { v = 'tomate'; k = 'ctus'; return 3; }); return t; }();").equals("[a : 1, b : 2]"); section("Array.foldLeft()"); code("return arrayFoldLeft([6, 7, 8, 9], function(a, b) { return a + b; }, 0)").equals("30"); @@ -371,10 +371,10 @@ public void run() throws Exception { code("return arrayPartition([6,7,8,9], function(a){return a&1;})").equals("[[1 : 7, 3 : 9], [0 : 6, 2 : 8]]"); code("return string(arrayPartition([6,7,8,9], function(k,v){return k;}))").equals("[[1 : 7, 2 : 8, 3 : 9], [6]]"); code("return string(arrayPartition([4,3,2,1], function(k,v){return kf)?(-1):(e { if x == 0 then return a end return fact(x - 1, x * a) } fact(10, 1)").equals("3628800"); // code("var fact = (x, a) -> { if x == 0m then return a end return fact(x - 1, x * a) } fact(10m, 1m)").equals("3628800"); // code("function test() { var fact = x -> if x == 1 { 1 } else { fact(x - 1) * x } fact(8) } test()").equals("40320"); - file_v10("ai/code/knapsack.leek").equals("761"); - file_v11("ai/code/knapsack_11.leek").equals("761"); + file_v1("ai/code/knapsack.leek").equals("761"); + file_v2("ai/code/knapsack_2.leek").equals("761"); code("function cellsInRange(i) { var areaInRange = []; if (i == 0) { return cellsInRange(10); } else { return areaInRange; } } var myRange = cellsInRange(0); return myRange").equals("[]"); section("Redefinition"); @@ -26,60 +26,60 @@ public void run() { code("var d = debug d('salut')").equals("null"); section("System function as argument"); - code_v10("function t(@f) { return function(@a) { return arrayMap(a, f); } } return t(sqrt)([1, 4, 9, 16, 25]);").equals("[1, 2, 3, 4, 5]"); - code_v11("function t(f) { return function(a) { return arrayMap(a, f); } } return t(sqrt)([1, 4, 9, 16, 25]);").equals("[1.0, 2.0, 3.0, 4.0, 5.0]"); + code_v1("function t(@f) { return function(@a) { return arrayMap(a, f); } } return t(sqrt)([1, 4, 9, 16, 25]);").equals("[1, 2, 3, 4, 5]"); + code_v2("function t(f) { return function(a) { return arrayMap(a, f); } } return t(sqrt)([1, 4, 9, 16, 25]);").equals("[1.0, 2.0, 3.0, 4.0, 5.0]"); section("Single null argument"); code("function f(a) { return 12; } return f(null);").equals("12"); code("var fa = [function(a) { return 12; }] return fa[0](null);").equals("12"); section("Capture argument"); - code_v10("function f(@a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("12"); - code_v11("function f(a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("10"); - code_v10("var f = function(@a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("12"); - code_v11("var f = function(a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("10"); + code_v1("function f(@a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("12"); + code_v2("function f(a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("10"); + code_v1("var f = function(@a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("12"); + code_v2("var f = function(a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("10"); section("Capture loop variable"); code("var sum = 0 for (var i = 0; i < 10; ++i) { sum += (function() { return i })() } return sum").equals("45"); section("Return reference"); - code_v10("global x = 10 function f() { return @x } var a = f() a += 5 return x").equals("10"); + code_v1("global x = 10 function f() { return @x } var a = f() a += 5 return x").equals("10"); code("global x = 10 function f() { return x } var a = f() a += 5 return x").equals("10"); - code_v10("var x = 10 var f = function() { return @x } var a = f() a += 5 return x").equals("10"); + code_v1("var x = 10 var f = function() { return @x } var a = f() a += 5 return x").equals("10"); code("var x = 10 var f = function() { return x } var a = f() a += 5 return x").equals("10"); - code_v10("var x = [] var f = function() { return @x } var a = f() push(a, 5) return x").equals("[5]"); - code_v10("var x = [] var f = function() { return x } var a = f() push(a, 5) return x").equals("[]"); - code_v11("var x = [] var f = function() { return x } var a = f() push(a, 5) return x").equals("[5]"); + code_v1("var x = [] var f = function() { return @x } var a = f() push(a, 5) return x").equals("[5]"); + code_v1("var x = [] var f = function() { return x } var a = f() push(a, 5) return x").equals("[]"); + code_v2("var x = [] var f = function() { return x } var a = f() push(a, 5) return x").equals("[5]"); section("Misc"); code("function f(x) { var s = 0 s |= 12 return s } f(12);").equals("null"); code("function te(a){ return function(){ return a**2; }; } return te(2)();").equals("4"); code("function te(a){ return function(b){ return function(c){return a*b*c;}; }; } return te(2)(1)(2);").equals("4"); code("var tab = [2, 3, 4, 5, 6]; var r = []; for (var i : var j in tab) { r[i] = function() { return j; }; } return 4;").equals("4"); - code_v10("var retour = [];for(var i=0;i<5;i++){if(i&1){var sqrt=function(e){return 1;}; push(retour, sqrt(4));}else{push(retour, sqrt(4));}}return string(retour);").equals("[2, 1, 2, 1, 2]"); - code_v11("var retour = [];for(var i=0;i<5;i++){if(i&1){var sqrt=function(e){return 1;}; push(retour, sqrt(4));}else{push(retour, sqrt(4));}}return string(retour);").equals("[2.0, 1, 2.0, 1, 2.0]"); - code_v10("var r = [1, 2, 3] var f = function() { return r } var x = f() push(x, 12) return r").equals("[1, 2, 3]"); - code_v11("var r = [1, 2, 3] var f = function() { return r } var x = f() push(x, 12) return r").equals("[1, 2, 3, 12]"); + code_v1("var retour = [];for(var i=0;i<5;i++){if(i&1){var sqrt=function(e){return 1;}; push(retour, sqrt(4));}else{push(retour, sqrt(4));}}return string(retour);").equals("[2, 1, 2, 1, 2]"); + code_v2("var retour = [];for(var i=0;i<5;i++){if(i&1){var sqrt=function(e){return 1;}; push(retour, sqrt(4));}else{push(retour, sqrt(4));}}return string(retour);").equals("[2.0, 1, 2.0, 1, 2.0]"); + code_v1("var r = [1, 2, 3] var f = function() { return r } var x = f() push(x, 12) return r").equals("[1, 2, 3]"); + code_v2("var r = [1, 2, 3] var f = function() { return r } var x = f() push(x, 12) return r").equals("[1, 2, 3, 12]"); code("function f() { return [1, 2, 3] } var x = f();").equals("null"); code("var x = arrayMap([1, 2, 3], function(x) { return x });").equals("null"); code("var x = arrayMap([1, 2, 3], function(x) { return x }); debug(x);").equals("null"); code("var toto = 12; var f = function() { toto = 'salut'; }; [true, 12, f][2](); return toto").equals("salut"); code("var toto = 12; var f = function() { toto = 'salut'; }; var g = function() { return f; }; g()() return toto").equals("salut"); - code_v10("function Coordonate(@par_x, @par_y) { var x = par_x; var y = par_y; var getX = function(){ return x; }; var getY = function(){ return y; };return @(function(@method) { if(method === 'getX'){ return getX; } if(method === 'getY'){ return getY; } }); } var c = Coordonate(5, 12) return [c('getX')(), c('getY')()]").equals("[5, 12]"); - code_v11("function Coordonate(par_x, par_y) { var x = par_x; var y = par_y; var getX = function(){ return x; }; var getY = function(){ return y; };return (function(method) { if(method === 'getX'){ return getX; } if(method === 'getY'){ return getY; } }); } var c = Coordonate(5, 12) return [c('getX')(), c('getY')()]").equals("[5, 12]"); + code_v1("function Coordonate(@par_x, @par_y) { var x = par_x; var y = par_y; var getX = function(){ return x; }; var getY = function(){ return y; };return @(function(@method) { if(method === 'getX'){ return getX; } if(method === 'getY'){ return getY; } }); } var c = Coordonate(5, 12) return [c('getX')(), c('getY')()]").equals("[5, 12]"); + code_v2("function Coordonate(par_x, par_y) { var x = par_x; var y = par_y; var getX = function(){ return x; }; var getY = function(){ return y; };return (function(method) { if(method === 'getX'){ return getX; } if(method === 'getY'){ return getY; } }); } var c = Coordonate(5, 12) return [c('getX')(), c('getY')()]").equals("[5, 12]"); code("function test() { var r = [1, 2, 3] return (r); } return test()").equals("[1, 2, 3]"); code("function test() { var r = [1, 2, 3] return (r); } var a = test() return a").equals("[1, 2, 3]"); code("function t(a) {} t([ [12], [12] ])").equals("null"); - code_v10("function t(@a) {} t([ [12], [12] ])").equals("null"); - code_v10("function t() { var a = 12 return @a } return t() + 2").equals("14"); + code_v1("function t(@a) {} t([ [12], [12] ])").equals("null"); + code_v1("function t() { var a = 12 return @a } return t() + 2").equals("14"); code("function t() { var a = [1, 2, 3] return a } var x = t() var f = function() { return x } return x").equals("[1, 2, 3]"); code("push = 1 return push").equals("1"); - code_v10("function LamaSwag() {} @LamaSwag();").equals("null"); + code_v1("function LamaSwag() {} @LamaSwag();").equals("null"); code("function f() { distance = 12 } function distance() { return 'salut' } return distance()").equals("salut"); code("getOperations()").equals("null"); code("var a = [function() { return 12 }] return a[0]()").equals("12"); - code_v10("function push_to_array(array) { return function(element) { push(array, element); } } var arrayCurry = []; var functionToCall = push_to_array(arrayCurry); for (var i = 0; i < 5; i++) functionToCall(i); return arrayCurry").equals("[]"); - code_v11("function push_to_array(array) { return function(element) { push(array, element); } } var arrayCurry = []; var functionToCall = push_to_array(arrayCurry); for (var i = 0; i < 5; i++) functionToCall(i); return arrayCurry").equals("[0, 1, 2, 3, 4]"); + code_v1("function push_to_array(array) { return function(element) { push(array, element); } } var arrayCurry = []; var functionToCall = push_to_array(arrayCurry); for (var i = 0; i < 5; i++) functionToCall(i); return arrayCurry").equals("[]"); + code_v2("function push_to_array(array) { return function(element) { push(array, element); } } var arrayCurry = []; var functionToCall = push_to_array(arrayCurry); for (var i = 0; i < 5; i++) functionToCall(i); return arrayCurry").equals("[0, 1, 2, 3, 4]"); section("Modify argument"); code("function test(x) { x += 10 return x } return test(5)").equals("15"); @@ -88,42 +88,42 @@ public void run() { code("function f(arg, arg) { return arg } return f(1, 2)").error(Error.PARAMETER_NAME_UNAVAILABLE); section("Knapsack variants"); code("var items = [[37, 3], [47, 10], [28, 5]] var all = []; return count(all);").equals("0"); - code_v10("var aux; aux = function() {}; aux();").equals("null"); - code_v10("var aux = function(current) {}; aux([0, []]);").equals("null"); - code_v10("var aux = function(@current) {}; aux([0, []]);").equals("null"); - code_v10("var aux; aux = function(current, i, tp, added, last) {}; aux([0, []], 0, 25, [], -1);").equals("null"); - code_v10("var aux; aux = function(@current, i, tp, added, last) {}; aux([0, []], 0, 25, [], -1);").equals("null"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) {}; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var cost = item[1]; if (cost > tp) continue; var copy = current; push(copy[1], @[item, cost, 1]); } }; aux([0, []], 0, 25); return count(all);").equals("0"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var cost = item[1]; if (cost > tp) continue; var copy = current; push(copy[1], @[item, cost, 1]); aux(copy, j, tp - cost); } }; aux([0, []], 0, 25); return count(all);").equals("44"); - code_v10("var added = [] added[1] = true;").equals("null"); - code_v10("var added = [] var new_added = added;").equals("null"); - code_v10("var added = [] var new_added = added; new_added[1] = true;").equals("null"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { var new_added = added; new_added[1] = true; }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var new_added = added; new_added[1] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var new_added = added; new_added[item_id] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var aux; aux = function(@current, i, tp, added) { for (var j = i; j < 3; ++j) { if (tp < 0) continue; var new_added = added; new_added[2] = true; var copy = current; } }; aux([0, []], 0, 25, []);").equals("null"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { for (var j = i; j < 3; ++j) { if (tp < 0) continue; var new_added = added; new_added[2] = true; var copy = current; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var aux; aux = function(@current, i, tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; }; aux([0, []], 0, 25, []);").equals("null"); - code_v10("var add = [2: 2] var copy = add;").equals("null"); - code_v10("var add = [2: true] var copy = add;").equals("null"); - code_v10("var add = [] add[2] = true; add[2] = true;").equals("null"); - code_v10("var add = [] add[2] = true; var copy = add;").equals("null"); - code_v10("var aux = function(tp, add) { if (tp < 0) return; aux(tp - 5, add); }; aux(25, []);").equals("null"); - code_v10("var aux = function(tp, add) { if (tp < 0) return; aux(tp - 5, add); }; aux(25, [1, 2, 3]);").equals("null"); - code_v10("var aux = function(tp, add) { if (tp < 0) return; push(add, 2); aux(tp - 5, add); }; aux(25, []);").equals("null"); - code_v10("var aux = function(tp, add) { if (tp < 0) return; add[2] = true; aux(tp - 5, add); }; aux(25, []);").equals("null"); - code_v10("var aux = function(tp, add) { if (tp < 0) return; var new_add = add; aux(tp - 5, new_add); }; aux(25, []);").equals("null"); - code_v10("var aux = function(tp, add) { if (tp < 0) return; var new_add = add; new_add[2] = true; aux(tp - 5, new_add); }; aux(25, []);").equals("null"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var aux; aux = function(tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; aux(tp - 5, new_added); }; aux(25, []);").equals("null"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var aux; aux = function(@current, i, tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; aux([], i, tp - 5, new_added); }; aux([0, []], 0, 25, []);").equals("null"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; aux([], i, tp - 5, new_added); }; aux([0, []], 0, 25, []); return count(all);").equals("0"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; var copy = current; aux(copy, i, tp - 5, new_added); }; aux([0, []], 0, 25, []); return count(all);").equals("0"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { for (var j = i; j < 3; ++j) { if (tp < 0) continue; var new_added = added; new_added[2] = true; var copy = current; aux(copy, j, tp - 5, new_added, 1); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; push(copy[1], @[item, cost, 1]); aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("44"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; push(copy[1], @[item, cost, 1]); copy[0] += cost; aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("44"); + code_v1("var aux; aux = function() {}; aux();").equals("null"); + code_v1("var aux = function(current) {}; aux([0, []]);").equals("null"); + code_v1("var aux = function(@current) {}; aux([0, []]);").equals("null"); + code_v1("var aux; aux = function(current, i, tp, added, last) {}; aux([0, []], 0, 25, [], -1);").equals("null"); + code_v1("var aux; aux = function(@current, i, tp, added, last) {}; aux([0, []], 0, 25, [], -1);").equals("null"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) {}; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var cost = item[1]; if (cost > tp) continue; var copy = current; push(copy[1], @[item, cost, 1]); } }; aux([0, []], 0, 25); return count(all);").equals("0"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var cost = item[1]; if (cost > tp) continue; var copy = current; push(copy[1], @[item, cost, 1]); aux(copy, j, tp - cost); } }; aux([0, []], 0, 25); return count(all);").equals("44"); + code_v1("var added = [] added[1] = true;").equals("null"); + code_v1("var added = [] var new_added = added;").equals("null"); + code_v1("var added = [] var new_added = added; new_added[1] = true;").equals("null"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { var new_added = added; new_added[1] = true; }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var new_added = added; new_added[1] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var new_added = added; new_added[item_id] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var aux; aux = function(@current, i, tp, added) { for (var j = i; j < 3; ++j) { if (tp < 0) continue; var new_added = added; new_added[2] = true; var copy = current; } }; aux([0, []], 0, 25, []);").equals("null"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { for (var j = i; j < 3; ++j) { if (tp < 0) continue; var new_added = added; new_added[2] = true; var copy = current; } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var aux; aux = function(@current, i, tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; }; aux([0, []], 0, 25, []);").equals("null"); + code_v1("var add = [2: 2] var copy = add;").equals("null"); + code_v1("var add = [2: true] var copy = add;").equals("null"); + code_v1("var add = [] add[2] = true; add[2] = true;").equals("null"); + code_v1("var add = [] add[2] = true; var copy = add;").equals("null"); + code_v1("var aux = function(tp, add) { if (tp < 0) return; aux(tp - 5, add); }; aux(25, []);").equals("null"); + code_v1("var aux = function(tp, add) { if (tp < 0) return; aux(tp - 5, add); }; aux(25, [1, 2, 3]);").equals("null"); + code_v1("var aux = function(tp, add) { if (tp < 0) return; push(add, 2); aux(tp - 5, add); }; aux(25, []);").equals("null"); + code_v1("var aux = function(tp, add) { if (tp < 0) return; add[2] = true; aux(tp - 5, add); }; aux(25, []);").equals("null"); + code_v1("var aux = function(tp, add) { if (tp < 0) return; var new_add = add; aux(tp - 5, new_add); }; aux(25, []);").equals("null"); + code_v1("var aux = function(tp, add) { if (tp < 0) return; var new_add = add; new_add[2] = true; aux(tp - 5, new_add); }; aux(25, []);").equals("null"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var aux; aux = function(tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; aux(tp - 5, new_added); }; aux(25, []);").equals("null"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var aux; aux = function(@current, i, tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; aux([], i, tp - 5, new_added); }; aux([0, []], 0, 25, []);").equals("null"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; aux([], i, tp - 5, new_added); }; aux([0, []], 0, 25, []); return count(all);").equals("0"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added) { if (tp < 0) return; var new_added = added; new_added[2] = true; var copy = current; aux(copy, i, tp - 5, new_added); }; aux([0, []], 0, 25, []); return count(all);").equals("0"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { for (var j = i; j < 3; ++j) { if (tp < 0) continue; var new_added = added; new_added[2] = true; var copy = current; aux(copy, j, tp - 5, new_added, 1); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("0"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; push(copy[1], @[item, cost, 1]); aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("44"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; push(copy[1], @[item, cost, 1]); copy[0] += cost; aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("44"); section("strings.leek variations"); code("var m = ['A', 'T', 'C', 'G'];").equals("null"); @@ -151,6 +151,6 @@ public void run() { code("var m = ['A', 'T', 'C', 'G'] var count = 0 var adn = '' for (var j = 0; j < 200; j++) { adn += m[randInt(0, 4)] } var c = contains(adn, 'GAGA'); if (c) count++").equals("null"); code("var m = ['A', 'T', 'C', 'G'] var count = 0 var tests = 500 for (var k = 0; k < tests; k++) { var adn = '' for (var j = 0; j < 200; j++) { adn += m[randInt(0, 4)] } var c = contains(adn, 'GAGA'); if (c) count++ }").equals("null"); code("var m = ['A', 'T', 'C', 'G'] var count = 0 var tests = 500 for (var k = 0; k < tests; k++) { var adn = '' for (var j = 0; j < 200; j++) { adn += m[randInt(0, 4)] } var c = contains(adn, 'GAGA'); if (c) count++ } return abs(100 * (count / tests) - 52) < 12;").equals("true"); - code_v10("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; push(copy[1], @[item, cost, 1]); copy[0] += cost; aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("44"); + code_v1("var items = [[37, 3], [47, 10], [28, 5]] var all = []; var aux; aux = function(@current, i, tp, added, last) { if (count(current[1])) push(all, current); var item_count = count(items); for (var j = i; j < item_count; ++j) { var item = @items[j]; var item_id = item[0]; var cost = item[1]; if (cost > tp) continue;var new_added = added; new_added[item_id] = true; var copy = current; push(copy[1], @[item, cost, 1]); copy[0] += cost; aux(copy, j, tp - cost, new_added, item_id); } }; aux([0, []], 0, 25, [], -1); return count(all);").equals("44"); } } diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index 632f75e0..497be43f 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -38,10 +38,10 @@ public void run() { section("Type changes"); code("var a return a = 12").equals("12"); code("var a a = 12 return a").equals("12"); - code_v10("var a return a = 12.5").equals("12,5"); - code_v11("var a return a = 12.5").equals("12.5"); - code_v10("var a a = 12.5 return a").equals("12,5"); - code_v11("var a a = 12.5 return a").equals("12.5"); + code_v1("var a return a = 12.5").equals("12,5"); + code_v2("var a return a = 12.5").equals("12.5"); + code_v1("var a a = 12.5 return a").equals("12,5"); + code_v2("var a a = 12.5 return a").equals("12.5"); code("var a return a = 'a'").equals("a"); code("var a a = 'a' return a").equals("a"); // code("var a return a = 12m").equals("12"); @@ -50,7 +50,7 @@ public void run() { code("var a = 'hello' return a = 2").equals("2"); code("var a = 2 a = 'hello' return a").equals("hello"); code("var a = 2 a = [1, 2] return a").equals("[1, 2]"); - code_v11("var a = 5.5 a = {} return a").equals("{}"); + code_v2("var a = 5.5 a = {} return a").equals("{}"); // code("var a = [5, 7] a = 7 System.print(a)").output("7\n"); // code("var a = 7 a = [5, 12] a").equals("[5, 12]"); // code("var a = 7 System.print(a) a = <5, 12> System.print(a)").output("7\n<5, 12>\n"); @@ -88,8 +88,8 @@ public void run() { code("var b = 5 if (1) { b = 'salut' } return b").equals("salut"); code("var b = 5 if (0) { b = 'salut' } return b").equals("5"); code("var a = 12 if (1) { a = 5 a++ } else { a = 3 } return a").equals("6"); - code_v10("var a = 12 if (0) { a = 5 a++ } else { a = 5.5 } return a").equals("5,5"); - code_v11("var a = 12 if (0) { a = 5 a++ } else { a = 5.5 } return a").equals("5.5"); + code_v1("var a = 12 if (0) { a = 5 a++ } else { a = 5.5 } return a").equals("5,5"); + code_v2("var a = 12 if (0) { a = 5 a++ } else { a = 5.5 } return a").equals("5.5"); // code("var a = 12 if (0) { a = 5 a++ } else { a = 7l } return a").equals("7"); code("var b = 5 if (1) {} else { b = 'salut' } return b").equals("5"); code("var b = 5 if (0) {} else { b = 'salut' } return b").equals("salut"); @@ -99,11 +99,11 @@ public void run() { code("var y if (false) { if (true) {;} else { y = 2 } } else { y = 5 } return y").equals("5"); DISABLED_code("PI = PI + 12; return PI").equals("3,142"); DISABLED_code("PI = PI + 12; return PI").equals("3.141592653589793"); - code_v10("var grow = []; var n = []; grow = @n; return grow").equals("[]"); + code_v1("var grow = []; var n = []; grow = @n; return grow").equals("[]"); section("Assignments with +="); - code_v10("var a = 10 a += 0.5 return a").equals("10,5"); - code_v11("var a = 10 a += 0.5 return a").equals("10.5"); + code_v1("var a = 10 a += 0.5 return a").equals("10,5"); + code_v2("var a = 10 a += 0.5 return a").equals("10.5"); section("File"); file("ai/code/trivial.leek").equals("2"); diff --git a/src/test/java/test/TestGlobals.java b/src/test/java/test/TestGlobals.java index f28532f2..83c3b993 100644 --- a/src/test/java/test/TestGlobals.java +++ b/src/test/java/test/TestGlobals.java @@ -20,10 +20,10 @@ public void run() throws Exception { code("global r = [] return r[1] = 12").equals("12"); code("global r = [0] return r[0] += 12").equals("12"); code("global r = [] return r[5] += 12").equals("12"); - code_v10("global r = 12 r = @null").equals("null"); + code_v1("global r = 12 r = @null").equals("null"); code("global m = [] return m = m").equals("[]"); - code_v11("global m = {} return m = m").equals("{}"); - code_v11("global m = {a: 12} return m = m").equals("{a: 12}"); + code_v2("global m = {} return m = m").equals("{}"); + code_v2("global m = {a: 12} return m = m").equals("{a: 12}"); section("Globals operators"); code("global x = 12; x++; return x;").equals("13"); @@ -33,14 +33,14 @@ public void run() throws Exception { code("global x = 12; x += 5; return x;").equals("17"); code("global x = 12; x -= 5; return x;").equals("7"); code("global x = 12; x *= 5; return x;").equals("60"); - code_v10("global x = 12; x /= 5; return x;").equals("2,4"); - code_v11("global x = 12; x /= 5; return x;").equals("2.4"); + code_v1("global x = 12; x /= 5; return x;").equals("2,4"); + code_v2("global x = 12; x /= 5; return x;").equals("2.4"); code("global x = 12; x %= 5; return x;").equals("2"); code("global x = 2; x **= 5; return x;").equals("32"); code("global x = 12; x |= 5; return x;").equals("13"); code("global x = 12; x &= 5; return x;").equals("4"); - code_v10("global x = 12; x ^= 5; return x;").equals("248832"); - code_v11("global x = 12; x ^= 5; return x;").equals("9"); + code_v1("global x = 12; x ^= 5; return x;").equals("248832"); + code_v2("global x = 12; x ^= 5; return x;").equals("9"); code("global x = 12; return x == 5;").equals("false"); code("global x = 12; return x === 5;").equals("false"); } diff --git a/src/test/java/test/TestIf.java b/src/test/java/test/TestIf.java index 4c4f13a3..19479be3 100644 --- a/src/test/java/test/TestIf.java +++ b/src/test/java/test/TestIf.java @@ -21,8 +21,8 @@ public void run() throws Exception { code("if (true) null else {}").equals("null"); // code("if true").error(ls::Error::UNEXPECTED_TOKEN, {""}); // code("if true else").error(ls::Error::UNEXPECTED_TOKEN, {"else"}); - code_v11("if (true) {a: 12} else {b: 5}").equals("{a: 12}"); - code_v11("if (true) { {a: 12} } else { {b: 5} }").equals("{a: 12}"); + code_v2("if (true) {a: 12} else {b: 5}").equals("{a: 12}"); + code_v2("if (true) { {a: 12} } else { {b: 5} }").equals("{a: 12}"); code("if (true) return 12 else return 5;").equals("12"); code("if (false) return 12 else return 5;").equals("5"); code("if (true) return 12;").equals("12"); @@ -55,11 +55,11 @@ public void run() throws Exception { code("var cell = 1 if (cell != null) return 12").equals("12"); code("var cell = null if (cell != null) return 12 return 5").equals("5"); code("function t(c) { var cell = c if (cell!=null ) 1; } return t(300);").equals("null"); - code_v10("function t(@c) { var cell = c if (cell!=null ) 1; } return t(300);").equals("null"); - code_v10("function t(@c) { var cell = c } for (var i = 0; i < 10; ++i) return t(i);").equals("null"); - code_v10("function t(@c) { var cell = c if (cell!=null ) 1; } for (var i = 0; i < 10; ++i) return t(i);").equals("null"); - code_v10("function t(@c) { var cell = c cell != null } for (var i = 0; i < 10; ++i) return t(i);").equals("null"); - code_v10("function t(@c) { var cell = c return cell != null } for (var i = 0; i < 10; ++i) return t(i);").equals("true"); + code_v1("function t(@c) { var cell = c if (cell!=null ) 1; } return t(300);").equals("null"); + code_v1("function t(@c) { var cell = c } for (var i = 0; i < 10; ++i) return t(i);").equals("null"); + code_v1("function t(@c) { var cell = c if (cell!=null ) 1; } for (var i = 0; i < 10; ++i) return t(i);").equals("null"); + code_v1("function t(@c) { var cell = c cell != null } for (var i = 0; i < 10; ++i) return t(i);").equals("null"); + code_v1("function t(@c) { var cell = c return cell != null } for (var i = 0; i < 10; ++i) return t(i);").equals("true"); section("Conditions with other types"); code("if (1212) { return 'ok' } else { return 5 }").equals("ok"); @@ -69,8 +69,8 @@ public void run() throws Exception { section("Different branch types"); code("if (1) return ['a'] else if (0) return [2] else return [5.5];").equals("[a]"); code("if (0) return ['a'] else if (1) return [2] else return [5.5];").equals("[2]"); - code_v10("if (0) return ['a'] else if (0) return [2] else return [5.5];").equals("[5,5]"); - code_v11("if (0) return ['a'] else if (0) return [2] else return [5.5];").equals("[5.5]"); + code_v1("if (0) return ['a'] else if (0) return [2] else return [5.5];").equals("[5,5]"); + code_v2("if (0) return ['a'] else if (0) return [2] else return [5.5];").equals("[5.5]"); section("Ternary conditions"); code("return true ? 5 : 12;").equals("5"); diff --git a/src/test/java/test/TestJSON.java b/src/test/java/test/TestJSON.java index 2bfc5af2..f60bd730 100644 --- a/src/test/java/test/TestJSON.java +++ b/src/test/java/test/TestJSON.java @@ -85,10 +85,10 @@ public void run() throws Exception { code("return jsonDecode('12')").equals("12"); code("return jsonDecode('-589')").equals("-589"); - code_v10("return jsonDecode('54.123')").equals("54,123"); - code_v11("return jsonDecode('54.123')").equals("54.123"); - code_v10("return jsonDecode('-65.89')").equals("-65,89"); - code_v11("return jsonDecode('-65.89')").equals("-65.89"); + code_v1("return jsonDecode('54.123')").equals("54,123"); + code_v2("return jsonDecode('54.123')").equals("54.123"); + code_v1("return jsonDecode('-65.89')").equals("-65,89"); + code_v2("return jsonDecode('-65.89')").equals("-65.89"); // code("return jsonDecode('1234567890987')").equals("1234567890987"); code("return jsonDecode('\"\"')").equals(""); @@ -96,8 +96,8 @@ public void run() throws Exception { code("return jsonDecode('[]')").equals("[]"); code("return jsonDecode('[1,2,3]')").equals("[1, 2, 3]"); - code_v10("return jsonDecode('[1.6,2.1,3.77]')").equals("[1,6, 2,1, 3,77]"); - code_v11("return jsonDecode('[1.6,2.1,3.77]')").equals("[1.6, 2.1, 3.77]"); + code_v1("return jsonDecode('[1.6,2.1,3.77]')").equals("[1,6, 2,1, 3,77]"); + code_v2("return jsonDecode('[1.6,2.1,3.77]')").equals("[1.6, 2.1, 3.77]"); code("return jsonDecode('[\"a\",\"b\",\"c\"]')").equals("[a, b, c]"); code("return jsonDecode('[[],[[],[]],[]]')").equals("[[], [[], []], []]"); diff --git a/src/test/java/test/TestLoops.java b/src/test/java/test/TestLoops.java index 761a3bb8..3af39b29 100644 --- a/src/test/java/test/TestLoops.java +++ b/src/test/java/test/TestLoops.java @@ -41,8 +41,8 @@ public void run() { code("var s = [] var i = 0 var j = 0 while (i < 2) { i++ j = 0 while (j < 3) { j++ push(s, j) }} return s;").equals("[1, 2, 3, 1, 2, 3]"); code("var s = [] var i = 0 var j = 0 while (i < 4) { j = i i++ while (j < 4) { j++ push(s, j) }} return s;").equals("[1, 2, 3, 4, 2, 3, 4, 3, 4, 4]"); code("var s = [] var i = 0 while (i < 2) { i++ var j = 0 while (j < 2) { j++ var k = 0 while (k < 2) { k++ push(s, k) }}} return s;").equals("[1, 2, 1, 2, 1, 2, 1, 2]"); - code_v10("var s = [] var i = 0 while (i < 2) { i++ push(s, 0.5) var j = 0 while (j < 3) { j++ push(s, j) }} return s;").equals("[0,5, 1, 2, 3, 0,5, 1, 2, 3]"); - code_v11("var s = [] var i = 0 while (i < 2) { i++ push(s, 0.5) var j = 0 while (j < 3) { j++ push(s, j) }} return s;").equals("[0.5, 1, 2, 3, 0.5, 1, 2, 3]"); + code_v1("var s = [] var i = 0 while (i < 2) { i++ push(s, 0.5) var j = 0 while (j < 3) { j++ push(s, j) }} return s;").equals("[0,5, 1, 2, 3, 0,5, 1, 2, 3]"); + code_v2("var s = [] var i = 0 while (i < 2) { i++ push(s, 0.5) var j = 0 while (j < 3) { j++ push(s, j) }} return s;").equals("[0.5, 1, 2, 3, 0.5, 1, 2, 3]"); // DISABLED_code("var s = [] var i = 0 while (i < 2) { i++ s.push([]) var j = 0 while j < 3 { j++ s[|s| - 1] += 1 }} s").equals("[[1, 1, 1], [1, 1, 1]]"); // DISABLED_code("var s = [] var i = 0 while (i < 2) { i++ s.push([]) var j = 0 while j < 3 { j++ s[|s| - 1] += ('a'.code() + 3 * (i - 1) + j - 1).char() }} s").equals("[['a', 'b', 'c'], ['d', 'e', 'f']]"); // file("test/code/loops/lot_of_whiles_int.leek").equals("30030"); @@ -86,8 +86,8 @@ public void run() { // DISABLED_code("var i = 0 for (; i < 10; i++) { } return i;").equals("10"); code("var i = 0 for (i = 0; i < 10; i++) { } return i;").equals("10"); code("var i = 0 for (i = 0; i < 10; i++) { if (i == 5) { break } } return i;").equals("5"); - code_v10("var i var c = 0 for (i = 0; i < 20; i += 0.573) { c++ } return i;").equals("20,055"); - code_v11("var i var c = 0 for (i = 0; i < 20; i += 0.573) { c++ } return i;").equals("20.05500000000001"); + code_v1("var i var c = 0 for (i = 0; i < 20; i += 0.573) { c++ } return i;").equals("20,055"); + code_v2("var i var c = 0 for (i = 0; i < 20; i += 0.573) { c++ } return i;").equals("20.05500000000001"); code("var i = 's' var c = 0 for (i = []; count(i) < 8; push(i, 1)) { c++ } return i;").equals("[1, 1, 1, 1, 1, 1, 1, 1]"); // DISABLED_code("var i = 0 for (; i < 10; i += 0.5) { } return i;").equals("10"); // code("var i = 0 for (i = 2l; i < 10; i += 0.5) { } return i;").equals("10"); @@ -146,8 +146,8 @@ public void run() { code("var a = 0 var x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] for (var i in x) { if (i < 5) { continue } a++ } return a;").equals("5"); code("var s = 0 for (var k : var v in [1, 2, 3, 4]) { s += k * v } return s;").equals("20"); // code("var s = '' for (var k : var v in ['a': 1, 'b': 2, 'c': 3, 'd': 4]) { s += v * k } return s;").equals("abbcccdddd"); - code_v10("return (function (a) { var s = 0.0; for (var x in a) { s += x } return s; })([1, 2, 3, 4.25]);").equals("10,25"); - code_v11("return (function (a) { var s = 0.0; for (var x in a) { s += x } return s; })([1, 2, 3, 4.25]);").equals("10.25"); + code_v1("return (function (a) { var s = 0.0; for (var x in a) { s += x } return s; })([1, 2, 3, 4.25]);").equals("10,25"); + code_v2("return (function (a) { var s = 0.0; for (var x in a) { s += x } return s; })([1, 2, 3, 4.25]);").equals("10.25"); // DISABLED_code("var y = '' for k, x in { var x = [] x.push(4) x } { y += k + ':' + x + ' ' } y").equals("'0:4 '"); // DISABLED_code("var y = '' for k, x in { var x = [1: 2] x.insert(3, 4) x } { y += k + ':' + x + ' ' } y").equals("'1:2 3:4 '"); // DISABLED_code("var y = '' for k, x in { var x = [1: 2.5] x.insert(3, 4) x } { y += k + ':' + x + ' ' } y").equals("'1:2.5 3:4 '"); @@ -179,14 +179,14 @@ public void run() { // code("var n = 3 while (n--) { var r = [] for x in [1, 2, 3] { r += x } print(r) }").output("[1, 2, 3]\n[1, 2, 3]\n[1, 2, 3]\n"); section("Foreach - references"); - code_v10("var s = 0 for (var @v in [1, 2, 3, 4]) { s += v } return s;").equals("10"); - code_v10("var s = 0 for (var @k : var @v in [1, 2, 3, 4]) { s += k * v } return s;").equals("20"); + code_v1("var s = 0 for (var @v in [1, 2, 3, 4]) { s += v } return s;").equals("10"); + code_v1("var s = 0 for (var @k : var @v in [1, 2, 3, 4]) { s += k * v } return s;").equals("20"); section("Foreach - captures"); code("for (var e in [1, 2, 3]) { (function() { return e })() } return null;").equals("null"); code("for (var i : var e in [1, 2, 3]) { (function() { return e })() } return null;").equals("null"); - code_v10("var a = [1, 2, 3] for (var @e in a) { (function() { e = 5 })() } return a;").equals("[1, 2, 3]"); - code_v10("var a = [1, 2, 3] for (var i : var @e in a) { (function() { e = 5 })() } return a;").equals("[1, 2, 3]"); + code_v1("var a = [1, 2, 3] for (var @e in a) { (function() { e = 5 })() } return a;").equals("[1, 2, 3]"); + code_v1("var a = [1, 2, 3] for (var i : var @e in a) { (function() { e = 5 })() } return a;").equals("[1, 2, 3]"); code("var a = [1, 2, 3] for (var i : var v in a) { (function() { i += 1 })() } return a;").equals("[1, 2, 3]"); section("Foreach - return"); diff --git a/src/test/java/test/TestMap.java b/src/test/java/test/TestMap.java index ee83ad52..836d71a9 100644 --- a/src/test/java/test/TestMap.java +++ b/src/test/java/test/TestMap.java @@ -56,14 +56,14 @@ public void run() { code("var m = [1: 1] return m[1]").equals("1"); code("var m = ['a': 'b'] return m['a']").equals("b"); code("var m = [5: 12] return m[5]").equals("12"); - code_v10("var m = [5: 12.5] return m[5]").equals("12,5"); - code_v11("var m = [5: 12.5] return m[5]").equals("12.5"); + code_v1("var m = [5: 12.5] return m[5]").equals("12,5"); + code_v2("var m = [5: 12.5] return m[5]").equals("12.5"); code("var m = [5.5: 12] return m[5.5]").equals("12"); - code_v10("var m = [5.5: 12.5] return m[5.5]").equals("12,5"); - code_v11("var m = [5.5: 12.5] return m[5.5]").equals("12.5"); + code_v1("var m = [5.5: 12.5] return m[5.5]").equals("12,5"); + code_v2("var m = [5.5: 12.5] return m[5.5]").equals("12.5"); code("var m = ['salut': 12] return m['salut']").equals("12"); - code_v10("var m = ['salut': 12.5] return m['salut']").equals("12,5"); - code_v11("var m = ['salut': 12.5] return m['salut']").equals("12.5"); + code_v1("var m = ['salut': 12.5] return m['salut']").equals("12,5"); + code_v2("var m = ['salut': 12.5] return m['salut']").equals("12.5"); code("var m = ['salut': 'yolo'] return m['salut']").equals("yolo"); code("var m = ['a': 'b'] m['a'] = 'c' return m").equals("[a : c]"); code("var m = ['salut': 12] m['salut'] = 13 return m['salut']").equals("13"); @@ -75,23 +75,23 @@ public void run() { // code("var m = [1: 'a', 2: 'b'] m[3]").exception(ls::vm::Exception::ARRAY_OUT_OF_BOUNDS); code("var m = [1: 2, 3: 4] m[5] = 6 return m").equals("[1 : 2, 3 : 4, 5 : 6]"); code("var m = ['a': 2, 'b': 4] m['c'] = 6 return m").equals("[a : 2, b : 4, c : 6]"); - code_v10("var m = ['a': 2.5, 'b': 4.8] m['c'] = 6.9 return m").equals("[a : 2,5, b : 4,8, c : 6,9]"); - code_v11("var m = ['a': 2.5, 'b': 4.8] m['c'] = 6.9 return m").equals("[a : 2.5, b : 4.8, c : 6.9]"); + code_v1("var m = ['a': 2.5, 'b': 4.8] m['c'] = 6.9 return m").equals("[a : 2,5, b : 4,8, c : 6,9]"); + code_v2("var m = ['a': 2.5, 'b': 4.8] m['c'] = 6.9 return m").equals("[a : 2.5, b : 4.8, c : 6.9]"); code("var m = [1: 'a', 2: 'b'] m[3] = 'c' return m").equals("[1 : a, 2 : b, 3 : c]"); code("var m = ['a': '2', 'b': '4'] m['c'] = '6' return m").equals("[a : 2, b : 4, c : 6]"); code("var m = [1: 2, 3: 4] m[3] = 6 return m").equals("[1 : 2, 3 : 6]"); - code_v10("var m = [1: 2.5, 3: 4.5] m[3] = 6.5 return m").equals("[1 : 2,5, 3 : 6,5]"); - code_v11("var m = [1: 2.5, 3: 4.5] m[3] = 6.5 return m").equals("[1 : 2.5, 3 : 6.5]"); - // code_v10("var m = [1.5: 2, 3.5: 4] m[3.5] = 6 return m").equals("[1,5 : 2, 3,5 : 6]"); - // code_v11("var m = [1.5: 2, 3.5: 4] m[3.5] = 6 return m").equals("[1.5 : 2, 3.5 : 6]"); - // code_v10("var m = [1.5: 2.5, 3.5: 4.5] m[3.5] = 6.5 return m").equals("[1,5 : 2,5, 3,5 : 6,5]"); - // code_v11("var m = [1.5: 2.5, 3.5: 4.5] m[3.5] = 6.5 return m").equals("[1.5 : 2.5, 3.5 : 6.5]"); + code_v1("var m = [1: 2.5, 3: 4.5] m[3] = 6.5 return m").equals("[1 : 2,5, 3 : 6,5]"); + code_v2("var m = [1: 2.5, 3: 4.5] m[3] = 6.5 return m").equals("[1 : 2.5, 3 : 6.5]"); + // code_v1("var m = [1.5: 2, 3.5: 4] m[3.5] = 6 return m").equals("[1,5 : 2, 3,5 : 6]"); + // code_v2("var m = [1.5: 2, 3.5: 4] m[3.5] = 6 return m").equals("[1.5 : 2, 3.5 : 6]"); + // code_v1("var m = [1.5: 2.5, 3.5: 4.5] m[3.5] = 6.5 return m").equals("[1,5 : 2,5, 3,5 : 6,5]"); + // code_v2("var m = [1.5: 2.5, 3.5: 4.5] m[3.5] = 6.5 return m").equals("[1.5 : 2.5, 3.5 : 6.5]"); code("var m = ['1': 2, '3': 4] m['3'] = 6 return m").equals("[1 : 2, 3 : 6]"); - // code_v10("var m = [1.5: 'a', 2.5: 'b'] m[2.5] = 'c' return m").equals("[1,5 : a, 2,5 : c]"); - // code_v11("var m = [1.5: 'a', 2.5: 'b'] m[2.5] = 'c' return m").equals("[1.5 : a, 2.5 : c]"); + // code_v1("var m = [1.5: 'a', 2.5: 'b'] m[2.5] = 'c' return m").equals("[1,5 : a, 2,5 : c]"); + // code_v2("var m = [1.5: 'a', 2.5: 'b'] m[2.5] = 'c' return m").equals("[1.5 : a, 2.5 : c]"); code("return ['', [1: 2][1]]").equals("[, 2]"); - code_v10("return ['', [1: 2.5][1]]").equals("[, 2,5]"); - code_v11("return ['', [1: 2.5][1]]").equals("[, 2.5]"); + code_v1("return ['', [1: 2.5][1]]").equals("[, 2,5]"); + code_v2("return ['', [1: 2.5][1]]").equals("[, 2.5]"); code("var m = [] var ns = '01234566' return m[ns] = 1").equals("1"); section("Map.operator [] left-value"); diff --git a/src/test/java/test/TestNumber.java b/src/test/java/test/TestNumber.java index 022049fd..a8399c3d 100644 --- a/src/test/java/test/TestNumber.java +++ b/src/test/java/test/TestNumber.java @@ -28,10 +28,10 @@ public void run() throws Exception { code("return 10 - 3;").equals("7"); code("return -2 + 3;").equals("1"); code("return 5 * 5;").equals("25"); - code_v10("return 15 / 3;").equals("5"); - code_v11("return 15 / 3;").equals("5.0"); - code_v10("return 15 / 2;").equals("7,5"); - code_v11("return 15 / 2;").equals("7.5"); + code_v1("return 15 / 3;").equals("5"); + code_v2("return 15 / 3;").equals("5.0"); + code_v1("return 15 / 2;").equals("7,5"); + code_v2("return 15 / 2;").equals("7.5"); code("return 12 ** 2;").equals("144"); code("return 2 ** 5;").equals("32"); code("return 2 < 5;").equals("true"); @@ -90,18 +90,18 @@ public void run() throws Exception { code("var a = 2 return a += 5;").equals("7"); code("var a = 2 return a -= 5;").equals("-3"); code("var a = 2 return a *= 5;").equals("10"); - code_v10("var a = 100 return a /= 5;").equals("20"); - code_v11("var a = 100 return a /= 5;").equals("20.0"); + code_v1("var a = 100 return a /= 5;").equals("20"); + code_v2("var a = 100 return a /= 5;").equals("20.0"); code("var a = 56 return a %= 17;").equals("5"); code("var a = 15 return a **= 2;").equals("225"); - code_v10("var a = 1.5 return a * 0.5;").equals("0,75"); - code_v11("var a = 1.5 return a * 0.5;").equals("0.75"); + code_v1("var a = 1.5 return a * 0.5;").equals("0,75"); + code_v2("var a = 1.5 return a * 0.5;").equals("0.75"); // DISABLED_code("var i = 1m return i = i + 2m;").equals("3"); code("var a = 10; a += 10 - 2 * 3; return a;").equals("14"); section("multiple operations"); - code_v10("return (33 - 2) / 2;").equals("15,5"); - code_v11("return (33 - 2) / 2;").equals("15.5"); + code_v1("return (33 - 2) / 2;").equals("15,5"); + code_v2("return (33 - 2) / 2;").equals("15.5"); code("return 12 < (45 / 4);").equals("false"); code("return 12 == (24 / 2);").equals("true"); // code("2.5 + 4.7").almost(7.2); @@ -432,30 +432,30 @@ public void run() throws Exception { code("null / 5").equals("null"); // code("12$ / false").exception(ls::vm::Exception::DIVISION_BY_ZERO); // code("let a = 13$; a / false").exception(ls::vm::Exception::DIVISION_BY_ZERO); - code_v10("return 13 / true;").equals("13"); - code_v11("return 13 / true;").equals("13.0"); - code_v10("return 14 / 2;").equals("7"); - code_v11("return 14 / 2;").equals("7.0"); - code_v10("var a = 18; return a / 3;").equals("6"); - code_v11("var a = 18; return a / 3;").equals("6.0"); + code_v1("return 13 / true;").equals("13"); + code_v2("return 13 / true;").equals("13.0"); + code_v1("return 14 / 2;").equals("7"); + code_v2("return 14 / 2;").equals("7.0"); + code_v1("var a = 18; return a / 3;").equals("6"); + code_v2("var a = 18; return a / 3;").equals("6.0"); // code("14$ / []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); - code_v10("var a = 17, b = 5 return a / b;").equals("3,4"); - code_v11("var a = 17, b = 5 return a / b;").equals("3.4"); + code_v1("var a = 17, b = 5 return a / b;").equals("3,4"); + code_v2("var a = 17, b = 5 return a / b;").equals("3.4"); section("Number.operator /="); - code_v10("var a = 12 a /= 3 return a;").equals("4"); - code_v11("var a = 12 a /= 3 return a;").equals("4.0"); - code_v10("var a = 12 a /= 0.5 return a;").equals("24"); - code_v11("var a = 12 a /= 0.5 return a;").equals("24.0"); - code_v10("var a = 12 a /= true return a;").equals("12"); - code_v11("var a = 12 a /= true return a;").equals("12.0"); - code_v10("var a = null a /= 5 return a;").equals("0"); - code_v11("var a = null a /= 5 return a;").equals("0.0"); + code_v1("var a = 12 a /= 3 return a;").equals("4"); + code_v2("var a = 12 a /= 3 return a;").equals("4.0"); + code_v1("var a = 12 a /= 0.5 return a;").equals("24"); + code_v2("var a = 12 a /= 0.5 return a;").equals("24.0"); + code_v1("var a = 12 a /= true return a;").equals("12"); + code_v2("var a = 12 a /= true return a;").equals("12.0"); + code_v1("var a = null a /= 5 return a;").equals("0"); + code_v2("var a = null a /= 5 return a;").equals("0.0"); // code("var a = 12 a /= false return a;").equals("nan"); // code("var a = 12$ a /= []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); // code("var a = 12$ a /= [] a").exception(ls::vm::Exception::NO_SUCH_OPERATOR); - code_v10("var a = 15; return ['', a /= 2];").equals("[, 7,5]"); - code_v11("var a = 15; return ['', a /= 2];").equals("[, 7.5]"); + code_v1("var a = 15; return ['', a /= 2];").equals("[, 7,5]"); + code_v2("var a = 15; return ['', a /= 2];").equals("[, 7.5]"); section("Number.operator <"); code("return 5 < 2;").equals("false"); @@ -555,12 +555,12 @@ public void run() throws Exception { code("return 5 ^ 12;").equals("9"); code("return 87619 ^ 18431;").equals("70076"); code("return [87619, ''][0] ^ [18431, ''][0];").equals("70076"); - code_v10("var a = 5 a ^= 2 return a;").equals("25"); // In LS 1.0, ^= was power equals - code_v11("var a = 87619 return a ^= 18431;").equals("70076"); - code_v11("var a = 87619 a ^= 18431 return a;").equals("70076"); + code_v1("var a = 5 a ^= 2 return a;").equals("25"); // In LS 1.0, ^= was power equals + code_v2("var a = 87619 return a ^= 18431;").equals("70076"); + code_v2("var a = 87619 a ^= 18431 return a;").equals("70076"); code("return [87619, ''][0] ^ 18431;").equals("70076"); // code("87619$ ^= 18431").error(ls::Error::VALUE_MUST_BE_A_LVALUE, {"87619"}); - code_v11("var a = 87619 a ^= 18431 return a;").equals("70076"); + code_v2("var a = 87619 a ^= 18431 return a;").equals("70076"); // code("[12, 'hello'][1] ^ 5").exception(ls::vm::Exception::NO_SUCH_OPERATOR); section("Number.operator <<"); @@ -640,12 +640,12 @@ public void run() throws Exception { section("Number.abs()"); // code("return abs;").equals(""); code("return abs(-12);").equals("12"); - code_v10("return abs(-19.5);").equals("19,5"); - code_v11("return abs(-19.5);").equals("19.5"); + code_v1("return abs(-19.5);").equals("19,5"); + code_v2("return abs(-19.5);").equals("19.5"); code("return abs(12);").equals("12"); // code("return abs(-16436435l)").equals("16436435"); - code_v10("return abs(-12.67);").equals("12,67"); - code_v11("return abs(-12.67);").equals("12.67"); + code_v1("return abs(-12.67);").equals("12,67"); + code_v2("return abs(-12.67);").equals("12.67"); code("return abs(['a', -15][1]);").equals("15"); // code("return (-17).abs()").equals("17"); // code("return (-19.5).abs()").equals("19.5"); @@ -653,25 +653,25 @@ public void run() throws Exception { // code("abs([1, 'salut'][1])").exception(ls::vm::Exception::WRONG_ARGUMENT_TYPE); section("Number.exp()"); - code_v10("return exp(0)").equals("1"); - code_v11("return exp(0)").equals("1.0"); - code_v10("return exp(1)").equals("2,718"); - code_v11("return exp(1)").almost(Math.E); - code_v10("return exp(4)").equals("54,598"); - code_v11("return exp(4)").almost(54.598150033144236204); - code_v10("return exp(4.89)").equals("132,954"); - code_v11("return exp(4.89)").almost(132.953574051282743085); - code_v10("return exp(-2.97)").equals("0,051"); - code_v11("return exp(-2.97)").almost(0.051303310331919108); - code_v10("return exp(['a', 7.78][1])").equals("2 392,275"); - code_v11("return exp(['a', 7.78][1])").almost(2392.274820537377763685); + code_v1("return exp(0)").equals("1"); + code_v2("return exp(0)").equals("1.0"); + code_v1("return exp(1)").equals("2,718"); + code_v2("return exp(1)").almost(Math.E); + code_v1("return exp(4)").equals("54,598"); + code_v2("return exp(4)").almost(54.598150033144236204); + code_v1("return exp(4.89)").equals("132,954"); + code_v2("return exp(4.89)").almost(132.953574051282743085); + code_v1("return exp(-2.97)").equals("0,051"); + code_v2("return exp(-2.97)").almost(0.051303310331919108); + code_v1("return exp(['a', 7.78][1])").equals("2 392,275"); + code_v2("return exp(['a', 7.78][1])").almost(2392.274820537377763685); // code("return 0.exp();").equals("1"); // code("return 1.exp();").almost(Math.E); // code("return 7.exp();").almost(1096.633158428458500566); // code("return (-7).exp();").almost(0.000911881965554516); // code("return (-3.33).exp();").almost(0.035793105067655297); - code_v10("return E ** 5;").equals("148,413"); - code_v11("return E ** 5;").almost(148.413159102576571513); + code_v1("return E ** 5;").equals("148,413"); + code_v2("return E ** 5;").almost(148.413159102576571513); section("Number.floor()"); code("return floor(5.9);").equals("5"); @@ -701,25 +701,25 @@ public void run() throws Exception { code("return max(8, 5)").equals("8"); code("return max(8, 88)").equals("88"); code("return max(5, 12);").equals("12"); - code_v10("return max(5.0, 12);").equals("12"); - code_v11("return max(5.0, 12);").equals("12.0"); - code_v10("return max(75.7, 12);").equals("75,7"); - code_v11("return max(75.7, 12);").almost(75.7); - code_v10("return max(5, 12.451);").equals("12,451"); - code_v11("return max(5, 12.451);").almost(12.451); + code_v1("return max(5.0, 12);").equals("12"); + code_v2("return max(5.0, 12);").equals("12.0"); + code_v1("return max(75.7, 12);").equals("75,7"); + code_v2("return max(75.7, 12);").almost(75.7); + code_v1("return max(5, 12.451);").equals("12,451"); + code_v2("return max(5, 12.451);").almost(12.451); code("return max([5, 'a'][0], 4);").equals("5"); code("return max([5, 'a'][0], 76);").equals("76"); code("return max(4, [5, 'a'][0]);").equals("5"); code("return max(77, [5, 'a'][0]);").equals("77"); code("return max([55, 'a'][0], [5, 'a'][0]);").equals("55"); - code_v10("return max(5, 12.8);").equals("12,8"); - code_v11("return max(5, 12.8);").equals("12.8"); - code_v10("return max(15.7, 12.8);").equals("15,7"); - code_v11("return max(15.7, 12.8);").equals("15.7"); - code_v10("return max([15.7, ''][0], 12.8);").equals("15,7"); - code_v11("return max([15.7, ''][0], 12.8);").equals("15.7"); - code_v10("return max(5.5, [12.8, ''][0]);").equals("12,8"); - code_v11("return max(5.5, [12.8, ''][0]);").equals("12.8"); + code_v1("return max(5, 12.8);").equals("12,8"); + code_v2("return max(5, 12.8);").equals("12.8"); + code_v1("return max(15.7, 12.8);").equals("15,7"); + code_v2("return max(15.7, 12.8);").equals("15.7"); + code_v1("return max([15.7, ''][0], 12.8);").equals("15,7"); + code_v2("return max([15.7, ''][0], 12.8);").equals("15.7"); + code_v1("return max(5.5, [12.8, ''][0]);").equals("12,8"); + code_v2("return max(5.5, [12.8, ''][0]);").equals("12.8"); // code("return 2.max([7.5, ''][0]);").equals("7.5"); // code("return [2, ''][0].max([7.5, ''][0]);").equals("7.5"); // code("2.max([7.5, ''][1])").exception(ls::vm::Exception::WRONG_ARGUMENT_TYPE); @@ -732,134 +732,134 @@ public void run() throws Exception { code("return min(8, 5)").equals("5"); code("return min(8, 88)").equals("8"); code("return min(5, 12)").equals("5"); - code_v10("return min(75.7, 12)").equals("12"); - code_v11("return min(75.7, 12)").almost(12.0); - code_v10("return min(5, 12.451)").equals("5"); - code_v11("return min(5, 12.451)").almost(5.0); + code_v1("return min(75.7, 12)").equals("12"); + code_v2("return min(75.7, 12)").almost(12.0); + code_v1("return min(5, 12.451)").equals("5"); + code_v2("return min(5, 12.451)").almost(5.0); code("return min([5, 'a'][0], 4)").equals("4"); code("return min([5, 'a'][0], 76)").equals("5"); code("return min(4, [5, 'a'][0])").equals("4"); code("return min(77, [5, 'a'][0])").equals("5"); code("return min([55, 'a'][0], [5, 'a'][0])").equals("5"); - code_v10("return min(5, 12.8)").equals("5"); - code_v11("return min(5, 12.8)").equals("5.0"); - code_v10("return min(15.7, 12.8)").equals("12,8"); - code_v11("return min(15.7, 12.8)").equals("12.8"); - code_v10("return min([15.7, ''][0], 12.8)").equals("12,8"); - code_v11("return min([15.7, ''][0], 12.8)").equals("12.8"); - code_v10("return min(5.5, [12.8, ''][0])").equals("5,5"); - code_v11("return min(5.5, [12.8, ''][0])").equals("5.5"); + code_v1("return min(5, 12.8)").equals("5"); + code_v2("return min(5, 12.8)").equals("5.0"); + code_v1("return min(15.7, 12.8)").equals("12,8"); + code_v2("return min(15.7, 12.8)").equals("12.8"); + code_v1("return min([15.7, ''][0], 12.8)").equals("12,8"); + code_v2("return min([15.7, ''][0], 12.8)").equals("12.8"); + code_v1("return min(5.5, [12.8, ''][0])").equals("5,5"); + code_v2("return min(5.5, [12.8, ''][0])").equals("5.5"); // code("return min(5l, 10.5);").equals("5"); // code("return min(5l, 10);").equals("5"); // code("return min(true, 10l);").equals("1"); // code("min('string', 12)").error(ls::Error::METHOD_NOT_FOUND, {"min(" + env.tmp_string->to_string() + ", " + env.integer->to_string() + ")"}); section("Number.cos()"); - code_v10("return cos(0)").equals("1"); - code_v11("return cos(0)").equals("1.0"); - code_v10("return cos(2.5)").equals("-0,801"); - code_v11("return cos(2.5)").almost(Math.cos(2.5)); - code_v10("return cos(PI)").equals("-1"); - code_v11("return cos(PI)").equals("-1.0"); - code_v10("return cos(PI / 2)").equals("0"); - code_v11("return cos(PI / 2)").almost(0.0); + code_v1("return cos(0)").equals("1"); + code_v2("return cos(0)").equals("1.0"); + code_v1("return cos(2.5)").equals("-0,801"); + code_v2("return cos(2.5)").almost(Math.cos(2.5)); + code_v1("return cos(PI)").equals("-1"); + code_v2("return cos(PI)").equals("-1.0"); + code_v1("return cos(PI / 2)").equals("0"); + code_v2("return cos(PI / 2)").almost(0.0); // code("return π.cos()").equals("-1"); // code("return ['', π][1].cos()").equals("-1"); - code_v10("return cos(['', PI][1]);").equals("-1"); - code_v11("return cos(['', PI][1]);").equals("-1.0"); - code_v10("return cos(PI);").equals("-1"); - code_v11("return cos(PI);").equals("-1.0"); + code_v1("return cos(['', PI][1]);").equals("-1"); + code_v2("return cos(['', PI][1]);").equals("-1.0"); + code_v1("return cos(PI);").equals("-1"); + code_v2("return cos(PI);").equals("-1.0"); section("Number.acos()"); - code_v10("return acos(1)").equals("0"); - code_v11("return acos(1)").equals("0.0"); - code_v10("return acos(-1)").equals("3,142"); - code_v11("return acos(-1)").almost(Math.PI); - code_v10("return acos(0)").equals("1,571"); - code_v11("return acos(0)").almost(Math.PI / 2); + code_v1("return acos(1)").equals("0"); + code_v2("return acos(1)").equals("0.0"); + code_v1("return acos(-1)").equals("3,142"); + code_v2("return acos(-1)").almost(Math.PI); + code_v1("return acos(0)").equals("1,571"); + code_v2("return acos(0)").almost(Math.PI / 2); // code("return (-0.33).acos()").almost(1.907099901948877019); - code_v10("return acos(['y', 0][1])").equals("1,571"); - code_v11("return acos(['y', 0][1])").almost(Math.PI / 2); + code_v1("return acos(['y', 0][1])").equals("1,571"); + code_v2("return acos(['y', 0][1])").almost(Math.PI / 2); section("Number.sin()"); - code_v10("return sin(0)").equals("0"); - code_v11("return sin(0)").equals("0.0"); - code_v10("return sin(2.5)").equals("0,598"); - code_v11("return sin(2.5)").almost(Math.sin(2.5)); - code_v10("return sin(PI)").equals("0"); - code_v11("return sin(PI)").almost(0.0); - code_v10("return sin(PI / 2)").equals("1"); - code_v11("return sin(PI / 2)").equals("1.0"); - code_v10("return sin(- PI / 2)").equals("-1"); - code_v11("return sin(- PI / 2)").equals("-1.0"); - code_v10("return sin(['', PI / 2][1])").equals("1"); - code_v11("return sin(['', PI / 2][1])").equals("1.0"); - code_v10("return sin(PI / 2)").equals("1"); - code_v11("return sin(PI / 2)").equals("1.0"); + code_v1("return sin(0)").equals("0"); + code_v2("return sin(0)").equals("0.0"); + code_v1("return sin(2.5)").equals("0,598"); + code_v2("return sin(2.5)").almost(Math.sin(2.5)); + code_v1("return sin(PI)").equals("0"); + code_v2("return sin(PI)").almost(0.0); + code_v1("return sin(PI / 2)").equals("1"); + code_v2("return sin(PI / 2)").equals("1.0"); + code_v1("return sin(- PI / 2)").equals("-1"); + code_v2("return sin(- PI / 2)").equals("-1.0"); + code_v1("return sin(['', PI / 2][1])").equals("1"); + code_v2("return sin(['', PI / 2][1])").equals("1.0"); + code_v1("return sin(PI / 2)").equals("1"); + code_v2("return sin(PI / 2)").equals("1.0"); section("Number.tan()"); - code_v10("return tan(0)").equals("0"); - code_v11("return tan(0)").equals("0.0"); - code_v10("return tan(2.5)").equals("-0,747"); - code_v11("return tan(2.5)").almost(Math.tan(2.5)); - code_v10("return tan(PI)").equals("-0"); - code_v11("return tan(PI)").almost(0.0); - code_v10("return tan(PI / 4)").equals("1"); - code_v11("return tan(PI / 4)").almost(1.0); - code_v10("return tan(- PI / 4)").equals("-1"); - code_v11("return tan(- PI / 4)").almost(-1.0); - code_v10("return tan(['', PI / 4][1])").equals("1"); - code_v11("return tan(['', PI / 4][1])").almost(1.0); + code_v1("return tan(0)").equals("0"); + code_v2("return tan(0)").equals("0.0"); + code_v1("return tan(2.5)").equals("-0,747"); + code_v2("return tan(2.5)").almost(Math.tan(2.5)); + code_v1("return tan(PI)").equals("-0"); + code_v2("return tan(PI)").almost(0.0); + code_v1("return tan(PI / 4)").equals("1"); + code_v2("return tan(PI / 4)").almost(1.0); + code_v1("return tan(- PI / 4)").equals("-1"); + code_v2("return tan(- PI / 4)").almost(-1.0); + code_v1("return tan(['', PI / 4][1])").equals("1"); + code_v2("return tan(['', PI / 4][1])").almost(1.0); section("Number.asin()"); - code_v10("return asin(0)").equals("0"); - code_v11("return asin(0)").equals("0.0"); - code_v10("return asin(-1)").equals("-1,571"); - code_v11("return asin(-1)").almost(-Math.PI / 2); - code_v10("return asin(1)").equals("1,571"); - code_v11("return asin(1)").almost(Math.PI / 2); + code_v1("return asin(0)").equals("0"); + code_v2("return asin(0)").equals("0.0"); + code_v1("return asin(-1)").equals("-1,571"); + code_v2("return asin(-1)").almost(-Math.PI / 2); + code_v1("return asin(1)").equals("1,571"); + code_v2("return asin(1)").almost(Math.PI / 2); // code("return 0.33.asin()").almost(0.33630357515398035); - code_v10("return asin(['y', -1][1])").equals("-1,571"); - code_v11("return asin(['y', -1][1])").almost(-Math.PI / 2); + code_v1("return asin(['y', -1][1])").equals("-1,571"); + code_v2("return asin(['y', -1][1])").almost(-Math.PI / 2); section("Number.atan()"); - code_v10("return atan(1)").equals("0,785"); - code_v11("return atan(1)").almost(Math.PI / 4); - code_v10("return atan(-1)").equals("-0,785"); - code_v11("return atan(-1)").almost(-Math.PI / 4); - code_v10("return atan(0.5)").equals("0,464"); - code_v11("return atan(0.5)").almost(0.463647609000806094); + code_v1("return atan(1)").equals("0,785"); + code_v2("return atan(1)").almost(Math.PI / 4); + code_v1("return atan(-1)").equals("-0,785"); + code_v2("return atan(-1)").almost(-Math.PI / 4); + code_v1("return atan(0.5)").equals("0,464"); + code_v2("return atan(0.5)").almost(0.463647609000806094); // code("return 0.atan()").equals("0"); - code_v10("return atan(['y', 0.5][1])").equals("0,464"); - code_v11("return atan(['y', 0.5][1])").almost(0.463647609000806094); + code_v1("return atan(['y', 0.5][1])").equals("0,464"); + code_v2("return atan(['y', 0.5][1])").almost(0.463647609000806094); section("Number.atan2()"); - code_v10("return atan2(1, 1)").equals("0,785"); - code_v11("return atan2(1, 1)").almost(Math.PI / 4); - code_v10("return atan2(150.78, 150.78)").equals("0,785"); - code_v11("return atan2(150.78, 150.78)").almost(Math.PI / 4); - code_v10("return atan2(1, 0)").equals("1,571"); - code_v11("return atan2(1, 0)").almost(Math.PI / 2); - code_v10("return atan2(-1, 0)").equals("-1,571"); - code_v11("return atan2(-1, 0)").almost(-Math.PI / 2); - code_v10("return atan2(0, 1)").equals("0"); - code_v11("return atan2(0, 1)").equals("0.0"); - code_v10("return atan2(0, -1)").equals("3,142"); - code_v11("return atan2(0, -1)").almost(Math.PI); - code_v10("return atan2(12.12, 42.42)").equals("0,278"); - code_v11("return atan2(12.12, 42.42)").almost(0.278299659005111333); + code_v1("return atan2(1, 1)").equals("0,785"); + code_v2("return atan2(1, 1)").almost(Math.PI / 4); + code_v1("return atan2(150.78, 150.78)").equals("0,785"); + code_v2("return atan2(150.78, 150.78)").almost(Math.PI / 4); + code_v1("return atan2(1, 0)").equals("1,571"); + code_v2("return atan2(1, 0)").almost(Math.PI / 2); + code_v1("return atan2(-1, 0)").equals("-1,571"); + code_v2("return atan2(-1, 0)").almost(-Math.PI / 2); + code_v1("return atan2(0, 1)").equals("0"); + code_v2("return atan2(0, 1)").equals("0.0"); + code_v1("return atan2(0, -1)").equals("3,142"); + code_v2("return atan2(0, -1)").almost(Math.PI); + code_v1("return atan2(12.12, 42.42)").equals("0,278"); + code_v2("return atan2(12.12, 42.42)").almost(0.278299659005111333); // code("return 1.atan2(1)").almost(Math.PI / 4); // code("return ['', -1][1].atan2(1)").almost(-Math.PI / 4); // code("return 1.atan2(['', -1][1])").almost(3 * Math.PI / 4); // code("return ['', -1][1].atan2(['', -1][1])").almost(-3 * Math.PI / 4); - code_v10("return atan2(1, 1)").equals("0,785"); - code_v11("return atan2(1, 1)").almost(Math.PI / 4); - code_v10("return atan2(['', -1][1], 1)").equals("-0,785"); - code_v11("return atan2(['', -1][1], 1)").almost(-Math.PI / 4); - code_v10("return atan2(1, ['', -1][1])").equals("2,356"); - code_v11("return atan2(1, ['', -1][1])").almost(3 * Math.PI / 4); - code_v10("return atan2(['', -1][1], ['', -1][1])").equals("-2,356"); - code_v11("return atan2(['', -1][1], ['', -1][1])").almost(-3 * Math.PI / 4); + code_v1("return atan2(1, 1)").equals("0,785"); + code_v2("return atan2(1, 1)").almost(Math.PI / 4); + code_v1("return atan2(['', -1][1], 1)").equals("-0,785"); + code_v2("return atan2(['', -1][1], 1)").almost(-Math.PI / 4); + code_v1("return atan2(1, ['', -1][1])").equals("2,356"); + code_v2("return atan2(1, ['', -1][1])").almost(3 * Math.PI / 4); + code_v1("return atan2(['', -1][1], ['', -1][1])").equals("-2,356"); + code_v2("return atan2(['', -1][1], ['', -1][1])").almost(-3 * Math.PI / 4); // code("return atan2(1, true)").almost(Math.PI / 4); // code("return atan2(true, false)").almost(Math.PI / 2); @@ -895,13 +895,13 @@ public void run() throws Exception { // code("1234567.fold((x, y) -> x + y ** 2, 0)").equals("140"); section("Number.hypot"); - code_v10("return hypot(3, 4)").equals("5"); - code_v11("return hypot(3, 4)").equals("5.0"); + code_v1("return hypot(3, 4)").equals("5"); + code_v2("return hypot(3, 4)").equals("5.0"); // code("return 3.hypot(4)").equals("5"); - code_v10("return hypot(34, 74)").equals("81,437"); - code_v11("return hypot(34, 74)").almost(81.437092286); - code_v10("return hypot([34, ''][0], 74)").equals("81,437"); - code_v11("return hypot([34, ''][0], 74)").almost(81.437092286); + code_v1("return hypot(34, 74)").equals("81,437"); + code_v2("return hypot(34, 74)").almost(81.437092286); + code_v1("return hypot([34, ''][0], 74)").equals("81,437"); + code_v2("return hypot([34, ''][0], 74)").almost(81.437092286); section("Number.signum"); // code("0.signum()").equals("0"); @@ -917,74 +917,74 @@ public void run() throws Exception { code("return signum(85)").equals("1"); section("Number.sqrt"); - code_v10("return sqrt(2)").equals("1,414"); - code_v11("return sqrt(2)").almost(Math.sqrt(2)); + code_v1("return sqrt(2)").equals("1,414"); + code_v2("return sqrt(2)").almost(Math.sqrt(2)); // code("return sqrt(123456789123456789123456789)").equals("11111111066111"); // code("return sqrt(55m ** 20m)").equals("253295162119140625"); // code("return sqrt(12m + 5m)").equals("4"); // code("return var n = 12; n.sqrt()").equals("3.4641016151"); // code("return let f = sqrt f(5)").equals("2.2360679775"); - code_v10("return sqrt(16)").equals("4"); - code_v11("return sqrt(16)").equals("4.0"); - code_v10("return sqrt(25)").equals("5"); - code_v11("return sqrt(25)").equals("5.0"); + code_v1("return sqrt(16)").equals("4"); + code_v2("return sqrt(16)").equals("4.0"); + code_v1("return sqrt(25)").equals("5"); + code_v2("return sqrt(25)").equals("5.0"); section("Number.toDegrees"); // code("return π.toDegrees()").equals("180"); // code("return (π / 2).toDegrees()").equals("90"); // code("return (-π / 2).toDegrees()").equals("-90"); // code("return 0.toDegrees()").equals("0"); - code_v10("return toDegrees(PI)").equals("180"); - code_v11("return toDegrees(PI)").equals("180.0"); - code_v10("return toDegrees(PI / 2)").equals("90"); - code_v11("return toDegrees(PI / 2)").equals("90.0"); - code_v10("return toDegrees(-PI / 2)").equals("-90"); - code_v11("return toDegrees(-PI / 2)").equals("-90.0"); - code_v10("return toDegrees(0)").equals("0"); - code_v11("return toDegrees(0)").equals("0.0"); + code_v1("return toDegrees(PI)").equals("180"); + code_v2("return toDegrees(PI)").equals("180.0"); + code_v1("return toDegrees(PI / 2)").equals("90"); + code_v2("return toDegrees(PI / 2)").equals("90.0"); + code_v1("return toDegrees(-PI / 2)").equals("-90"); + code_v2("return toDegrees(-PI / 2)").equals("-90.0"); + code_v1("return toDegrees(0)").equals("0"); + code_v2("return toDegrees(0)").equals("0.0"); section("Number.toRadians"); // code("return 180.toRadians()").almost(Math.PI); // code("return 90.toRadians()").almost(Math.PI / 2); // code("return (-90).toRadians()").almost(-Math.PI / 2); // code("return 0.toRadians()").equals("0"); - code_v10("return toRadians(180)").equals("3,142"); - code_v11("return toRadians(180)").almost(Math.PI); - code_v10("return toRadians(90)").equals("1,571"); - code_v11("return toRadians(90)").almost(Math.PI / 2); - code_v10("return toRadians(-90)").equals("-1,571"); - code_v11("return toRadians(-90)").almost(-Math.PI / 2); - code_v10("return toRadians(0)").equals("0"); - code_v11("return toRadians(0)").equals("0.0"); + code_v1("return toRadians(180)").equals("3,142"); + code_v2("return toRadians(180)").almost(Math.PI); + code_v1("return toRadians(90)").equals("1,571"); + code_v2("return toRadians(90)").almost(Math.PI / 2); + code_v1("return toRadians(-90)").equals("-1,571"); + code_v2("return toRadians(-90)").almost(-Math.PI / 2); + code_v1("return toRadians(0)").equals("0"); + code_v2("return toRadians(0)").equals("0.0"); section("Number.log"); // code("1.log()").equals("0"); - code_v10("return log(1)").equals("0"); - code_v11("return log(1)").equals("0.0"); - code_v10("return log(E)").equals("1"); - code_v11("return log(E)").equals("1.0"); + code_v1("return log(1)").equals("0"); + code_v2("return log(1)").equals("0.0"); + code_v1("return log(E)").equals("1"); + code_v2("return log(E)").equals("1.0"); // code("123456.log()").equals("11.7236400963"); - code_v10("return log(654321)").equals("13,391"); - code_v11("return log(654321)").almost(13.3913533357); - code_v10("return log([55555, ''][0])").equals("10,925"); - code_v11("return log([55555, ''][0])").almost(10.9251288); + code_v1("return log(654321)").equals("13,391"); + code_v2("return log(654321)").almost(13.3913533357); + code_v1("return log([55555, ''][0])").equals("10,925"); + code_v2("return log([55555, ''][0])").almost(10.9251288); section("Number.log10"); - code_v10("return log10(10)").equals("1"); - code_v11("return log10(10)").equals("1.0"); + code_v1("return log10(10)").equals("1"); + code_v2("return log10(10)").equals("1.0"); // code("return 1.log10()").equals("0"); // code("return 123456.log10()").equals("5.0915122016"); - code_v10("return log10(654321)").equals("5,816"); - code_v11("return log10(654321)").almost(5.8157908589); - code_v10("return log10([55555, ''][0])").equals("4,745"); - code_v11("return log10([55555, ''][0])").almost(4.7447231519); + code_v1("return log10(654321)").equals("5,816"); + code_v2("return log10(654321)").almost(5.8157908589); + code_v1("return log10([55555, ''][0])").equals("4,745"); + code_v2("return log10([55555, ''][0])").almost(4.7447231519); section("Number.pow"); // code("2.pow(10)").equals("1024"); - code_v10("return pow(5, 3)").equals("125"); - code_v11("return pow(5, 3)").equals("125.0"); - code_v10("return pow(2, 10)").equals("1 024"); - code_v11("return pow(2, 10)").equals("1024.0"); + code_v1("return pow(5, 3)").equals("125"); + code_v2("return pow(5, 3)").equals("125.0"); + code_v1("return pow(2, 10)").equals("1 024"); + code_v2("return pow(2, 10)").equals("1024.0"); // code("pow([10, ''][0], 5)").equals("100000"); // code("3000.pow(3)").equals("2147483648"); // code("return pow(3000, 3)").equals("2147483648"); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 48e6294d..ad4a2c31 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -10,216 +10,216 @@ public void run() { // code("return Object()").equals("{}"); // code("return new Object").equals("{}"); // code("return new Object()").equals("{}"); - code_v11("return {}").equals("{}"); - code_v11("return {a: 12}").equals("{a: 12}"); - code_v11("return {a: 12, b: 5}").equals("{a: 12, b: 5}"); - code_v11("return {a: {}, b: []}").equals("{a: {}, b: []}"); - code_v11("var a = {} return a").equals("{}"); - code_v11("var a = {b: 12, c: 5} return a").equals("{b: 12, c: 5}"); + code_v2("return {}").equals("{}"); + code_v2("return {a: 12}").equals("{a: 12}"); + code_v2("return {a: 12, b: 5}").equals("{a: 12, b: 5}"); + code_v2("return {a: {}, b: []}").equals("{a: {}, b: []}"); + code_v2("var a = {} return a").equals("{}"); + code_v2("var a = {b: 12, c: 5} return a").equals("{b: 12, c: 5}"); section("Objects with functions"); - code_v11("var f = function(obj) { return obj.a } return f({a: 'foo'})").equals("foo"); - code_v11("var f = function(obj) { return obj.a } return [f({a: 'foo'}), f({a: 'bar'})]").equals("[foo, bar]"); + code_v2("var f = function(obj) { return obj.a } return f({a: 'foo'})").equals("foo"); + code_v2("var f = function(obj) { return obj.a } return [f({a: 'foo'}), f({a: 'bar'})]").equals("[foo, bar]"); //code("var f = function(obj) { return obj.a } [f(12), f({a: 'bar'})]").error(ls::Error::NO_SUCH_ATTRIBUTE, {"a", "Number"}); section("No commas"); - code_v11("return {a: 12 b: 5}").equals("{a: 12, b: 5}"); - code_v11("return {a: 12 - 2 yo: -6}").equals("{a: 10, yo: -6}"); - code_v11("return {a: 12 b: 'yo' c: true d: [1 2 3]}").equals("{a: 12, b: yo, c: true, d: [1, 2, 3]}"); + code_v2("return {a: 12 b: 5}").equals("{a: 12, b: 5}"); + code_v2("return {a: 12 - 2 yo: -6}").equals("{a: 10, yo: -6}"); + code_v2("return {a: 12 b: 'yo' c: true d: [1 2 3]}").equals("{a: 12, b: yo, c: true, d: [1, 2, 3]}"); section("Classes"); - code_v11("class A { } return new A();").equals("A {}"); - code_v11("class A { a = 10 } var a = [new A()]; a[0].a++ return a[0].a").equals("11"); - code_v11("class A { a = 10 } var a = [new A()]; a[0].a-- return a[0].a").equals("9"); - code_v11("class A { a = 10 } var a = [new A()]; ++a[0].a return a[0].a").equals("11"); - code_v11("class A { a = 10 } var a = [new A()]; --a[0].a return a[0].a").equals("9"); - code_v11("class A { a = 10 m() { return 12 } } var a = new A(); return a.m()").equals("12"); - code_v11("class A { a = 10 m() { return 13 } } var a = new A(); return a['m']()").equals("13"); - code_v11("class A { a = 10 m() { return 13 } } var a = new A(); var m = 'm' return a[m]()").equals("13"); - code_v11("class A { a = 10 m() { return a } } var a = new A(); var array = [a.m] return array[0](a)").equals("10"); - code_v11("class A { a = 10 m() { return a } } var a = new A(); var array = [a['m']] return array[0](a)").equals("10"); + code_v2("class A { } return new A();").equals("A {}"); + code_v2("class A { a = 10 } var a = [new A()]; a[0].a++ return a[0].a").equals("11"); + code_v2("class A { a = 10 } var a = [new A()]; a[0].a-- return a[0].a").equals("9"); + code_v2("class A { a = 10 } var a = [new A()]; ++a[0].a return a[0].a").equals("11"); + code_v2("class A { a = 10 } var a = [new A()]; --a[0].a return a[0].a").equals("9"); + code_v2("class A { a = 10 m() { return 12 } } var a = new A(); return a.m()").equals("12"); + code_v2("class A { a = 10 m() { return 13 } } var a = new A(); return a['m']()").equals("13"); + code_v2("class A { a = 10 m() { return 13 } } var a = new A(); var m = 'm' return a[m]()").equals("13"); + code_v2("class A { a = 10 m() { return a } } var a = new A(); var array = [a.m] return array[0](a)").equals("10"); + code_v2("class A { a = 10 m() { return a } } var a = new A(); var array = [a['m']] return array[0](a)").equals("10"); section("Static fields"); - code_v11("class A { static x }").equals("null"); - code_v11("class A { static x } return A.x").equals("null"); - code_v11("class A { static x = 10 } return A.x").equals("10"); - code_v11("class A { static x = 'hello' } return A.x").equals("hello"); - code_v11("class A { static x = [1, 2, 3] } return A.x").equals("[1, 2, 3]"); - code_v11("class A { static x = null } return A.x").equals("null"); - code_v11("class Affiche { static COULEUR = getColor(42, 125, 78) } return Affiche.COULEUR").equals("2784590"); + code_v2("class A { static x }").equals("null"); + code_v2("class A { static x } return A.x").equals("null"); + code_v2("class A { static x = 10 } return A.x").equals("10"); + code_v2("class A { static x = 'hello' } return A.x").equals("hello"); + code_v2("class A { static x = [1, 2, 3] } return A.x").equals("[1, 2, 3]"); + code_v2("class A { static x = null } return A.x").equals("null"); + code_v2("class Affiche { static COULEUR = getColor(42, 125, 78) } return Affiche.COULEUR").equals("2784590"); section("Operators on field"); - code_v11("class A { a = 10 } var a = new A(); return --a.a").equals("9"); - code_v11("class A { a = 10 } var a = new A(); a.a-- return a.a").equals("9"); - code_v11("class A { a = 10 } var a = new A(); return ++a.a").equals("11"); - code_v11("class A { a = 10 } var a = new A(); a.a++ return a.a").equals("11"); - code_v11("class A { a = 10 } var a = new A(); return a.a += 5").equals("15"); - code_v11("class A { a = 10 } var a = new A(); return a.a -= 5").equals("5"); - code_v11("class A { a = 10 } var a = new A(); return a.a *= 5").equals("50"); - code_v11("class A { a = 10 } var a = new A(); return a.a /= 5").equals("2.0"); - code_v11("class A { a = 10 } var a = new A(); return a.a %= 5").equals("0"); - code_v11("class A { a = 10 } var a = new A(); return a.a **= 5").equals("100000"); - code_v11("class A { a = 10 } var a = new A(); return a.a |= 5").equals("15"); - code_v11("class A { a = 10 } var a = new A(); return a.a &= 5").equals("0"); - code_v11("class A { a = 10 } var a = new A(); return a.a ^= 5").equals("15"); - code_v11("class A { a = 10 } var a = new A(); return a.a <<= 5").equals("320"); - code_v11("class A { a = 10 } var a = new A(); return a.a >>= 5").equals("0"); - code_v11("class A { a = 10 } var a = new A(); return a.a >>>= 5").equals("0"); + code_v2("class A { a = 10 } var a = new A(); return --a.a").equals("9"); + code_v2("class A { a = 10 } var a = new A(); a.a-- return a.a").equals("9"); + code_v2("class A { a = 10 } var a = new A(); return ++a.a").equals("11"); + code_v2("class A { a = 10 } var a = new A(); a.a++ return a.a").equals("11"); + code_v2("class A { a = 10 } var a = new A(); return a.a += 5").equals("15"); + code_v2("class A { a = 10 } var a = new A(); return a.a -= 5").equals("5"); + code_v2("class A { a = 10 } var a = new A(); return a.a *= 5").equals("50"); + code_v2("class A { a = 10 } var a = new A(); return a.a /= 5").equals("2.0"); + code_v2("class A { a = 10 } var a = new A(); return a.a %= 5").equals("0"); + code_v2("class A { a = 10 } var a = new A(); return a.a **= 5").equals("100000"); + code_v2("class A { a = 10 } var a = new A(); return a.a |= 5").equals("15"); + code_v2("class A { a = 10 } var a = new A(); return a.a &= 5").equals("0"); + code_v2("class A { a = 10 } var a = new A(); return a.a ^= 5").equals("15"); + code_v2("class A { a = 10 } var a = new A(); return a.a <<= 5").equals("320"); + code_v2("class A { a = 10 } var a = new A(); return a.a >>= 5").equals("0"); + code_v2("class A { a = 10 } var a = new A(); return a.a >>>= 5").equals("0"); section("Operators on field in method"); - code_v11("class A { a = 10 m() { return --a } } return new A().m()").equals("9"); - code_v11("class A { a = 10 m() { a-- return a } } return new A().m()").equals("9"); - code_v11("class A { a = 10 m() { return ++a } } return new A().m()").equals("11"); - code_v11("class A { a = 10 m() { a++ return a } } return new A().m()").equals("11"); - code_v11("class A { a = 10 m() { return a += 5 } } return new A().m()").equals("15"); - code_v11("class A { a = 10 m() { return a -= 5 } } return new A().m()").equals("5"); - code_v11("class A { a = 10 m() { return a *= 5 } } return new A().m()").equals("50"); - code_v11("class A { a = 10 m() { return a /= 5 } } return new A().m()").equals("2.0"); - code_v11("class A { a = 10 m() { return a %= 5 } } return new A().m()").equals("0"); - code_v11("class A { a = 10 m() { return a **= 5 } } return new A().m()").equals("100000"); - code_v11("class A { a = 10 m() { return a |= 5 } } return new A().m()").equals("15"); - code_v11("class A { a = 10 m() { return a &= 5 } } return new A().m()").equals("0"); - code_v11("class A { a = 10 m() { return a ^= 5 } } return new A().m()").equals("15"); - code_v11("class A { a = 10 m() { return a <<= 5 } } return new A().m()").equals("320"); - code_v11("class A { a = 10 m() { return a >>= 5 } } return new A().m()").equals("0"); - code_v11("class A { a = 10 m() { return a >>>= 5 } } return new A().m()").equals("0"); + code_v2("class A { a = 10 m() { return --a } } return new A().m()").equals("9"); + code_v2("class A { a = 10 m() { a-- return a } } return new A().m()").equals("9"); + code_v2("class A { a = 10 m() { return ++a } } return new A().m()").equals("11"); + code_v2("class A { a = 10 m() { a++ return a } } return new A().m()").equals("11"); + code_v2("class A { a = 10 m() { return a += 5 } } return new A().m()").equals("15"); + code_v2("class A { a = 10 m() { return a -= 5 } } return new A().m()").equals("5"); + code_v2("class A { a = 10 m() { return a *= 5 } } return new A().m()").equals("50"); + code_v2("class A { a = 10 m() { return a /= 5 } } return new A().m()").equals("2.0"); + code_v2("class A { a = 10 m() { return a %= 5 } } return new A().m()").equals("0"); + code_v2("class A { a = 10 m() { return a **= 5 } } return new A().m()").equals("100000"); + code_v2("class A { a = 10 m() { return a |= 5 } } return new A().m()").equals("15"); + code_v2("class A { a = 10 m() { return a &= 5 } } return new A().m()").equals("0"); + code_v2("class A { a = 10 m() { return a ^= 5 } } return new A().m()").equals("15"); + code_v2("class A { a = 10 m() { return a <<= 5 } } return new A().m()").equals("320"); + code_v2("class A { a = 10 m() { return a >>= 5 } } return new A().m()").equals("0"); + code_v2("class A { a = 10 m() { return a >>>= 5 } } return new A().m()").equals("0"); section("Operators on static field"); - code_v11("class A { static a = 10 } return --A.a").equals("9"); - code_v11("class A { static a = 10 } A.a-- return A.a").equals("9"); - code_v11("class A { static a = 10 } return ++A.a").equals("11"); - code_v11("class A { static a = 10 } A.a++ return A.a").equals("11"); - code_v11("class A { static a = 10 } return A.a += 5").equals("15"); - code_v11("class A { static a = 10 } return A.a -= 5").equals("5"); - code_v11("class A { static a = 10 } return A.a *= 5").equals("50"); - code_v11("class A { static a = 10 } return A.a /= 5").equals("2.0"); - code_v11("class A { static a = 10 } return A.a %= 5").equals("0"); - code_v11("class A { static a = 10 } return A.a **= 5").equals("100000"); - code_v11("class A { static a = 10 } return A.a |= 5").equals("15"); - code_v11("class A { static a = 10 } return A.a &= 5").equals("0"); - code_v11("class A { static a = 10 } return A.a ^= 5").equals("15"); - code_v11("class A { static a = 10 } return A.a <<= 5").equals("320"); - code_v11("class A { static a = 10 } return A.a >>= 5").equals("0"); - code_v11("class A { static a = 10 } return A.a >>>= 5").equals("0"); + code_v2("class A { static a = 10 } return --A.a").equals("9"); + code_v2("class A { static a = 10 } A.a-- return A.a").equals("9"); + code_v2("class A { static a = 10 } return ++A.a").equals("11"); + code_v2("class A { static a = 10 } A.a++ return A.a").equals("11"); + code_v2("class A { static a = 10 } return A.a += 5").equals("15"); + code_v2("class A { static a = 10 } return A.a -= 5").equals("5"); + code_v2("class A { static a = 10 } return A.a *= 5").equals("50"); + code_v2("class A { static a = 10 } return A.a /= 5").equals("2.0"); + code_v2("class A { static a = 10 } return A.a %= 5").equals("0"); + code_v2("class A { static a = 10 } return A.a **= 5").equals("100000"); + code_v2("class A { static a = 10 } return A.a |= 5").equals("15"); + code_v2("class A { static a = 10 } return A.a &= 5").equals("0"); + code_v2("class A { static a = 10 } return A.a ^= 5").equals("15"); + code_v2("class A { static a = 10 } return A.a <<= 5").equals("320"); + code_v2("class A { static a = 10 } return A.a >>= 5").equals("0"); + code_v2("class A { static a = 10 } return A.a >>>= 5").equals("0"); section("Operators on static field in method"); - code_v11("class A { static a = 10 static m() { return --a } } return A.m()").equals("9"); - code_v11("class A { static a = 10 static m() { a-- return a } } return A.m()").equals("9"); - code_v11("class A { static a = 10 static m() { return ++a } } return A.m()").equals("11"); - code_v11("class A { static a = 10 static m() { a++ return a } } return A.m()").equals("11"); - code_v11("class A { static a = 10 static m() { return a += 5 } } return A.m()").equals("15"); - code_v11("class A { static a = 10 static m() { return a -= 5 } } return A.m()").equals("5"); - code_v11("class A { static a = 10 static m() { return a *= 5 } } return A.m()").equals("50"); - code_v11("class A { static a = 10 static m() { return a /= 5 } } return A.m()").equals("2.0"); - code_v11("class A { static a = 10 static m() { return a %= 5 } } return A.m()").equals("0"); - code_v11("class A { static a = 10 static m() { return a **= 5 } } return A.m()").equals("100000"); - code_v11("class A { static a = 10 static m() { return a |= 5 } } return A.m()").equals("15"); - code_v11("class A { static a = 10 static m() { return a &= 5 } } return A.m()").equals("0"); - code_v11("class A { static a = 10 static m() { return a ^= 5 } } return A.m()").equals("15"); - code_v11("class A { static a = 10 static m() { return a <<= 5 } } return A.m()").equals("320"); - code_v11("class A { static a = 10 static m() { return a >>= 5 } } return A.m()").equals("0"); - code_v11("class A { static a = 10 static m() { return a >>>= 5 } } return A.m()").equals("0"); + code_v2("class A { static a = 10 static m() { return --a } } return A.m()").equals("9"); + code_v2("class A { static a = 10 static m() { a-- return a } } return A.m()").equals("9"); + code_v2("class A { static a = 10 static m() { return ++a } } return A.m()").equals("11"); + code_v2("class A { static a = 10 static m() { a++ return a } } return A.m()").equals("11"); + code_v2("class A { static a = 10 static m() { return a += 5 } } return A.m()").equals("15"); + code_v2("class A { static a = 10 static m() { return a -= 5 } } return A.m()").equals("5"); + code_v2("class A { static a = 10 static m() { return a *= 5 } } return A.m()").equals("50"); + code_v2("class A { static a = 10 static m() { return a /= 5 } } return A.m()").equals("2.0"); + code_v2("class A { static a = 10 static m() { return a %= 5 } } return A.m()").equals("0"); + code_v2("class A { static a = 10 static m() { return a **= 5 } } return A.m()").equals("100000"); + code_v2("class A { static a = 10 static m() { return a |= 5 } } return A.m()").equals("15"); + code_v2("class A { static a = 10 static m() { return a &= 5 } } return A.m()").equals("0"); + code_v2("class A { static a = 10 static m() { return a ^= 5 } } return A.m()").equals("15"); + code_v2("class A { static a = 10 static m() { return a <<= 5 } } return A.m()").equals("320"); + code_v2("class A { static a = 10 static m() { return a >>= 5 } } return A.m()").equals("0"); + code_v2("class A { static a = 10 static m() { return a >>>= 5 } } return A.m()").equals("0"); section("Inheritance"); - code_v11("class A { x = 10 } class B extends A {} var a = new B() return a.x").equals("10"); - code_v11("class A { m() { return 'ok' } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("ok"); - code_v11("class A { x = 10 } class B extends A {} class C extends B {} var a = new C() return a.x").equals("10"); - code_v11("class A { m() { return 'ok' } } class B extends A {} class C extends B {} var a = new C() return a.m()").equals("ok"); - code_v11("class A { m() { return 'ok' } } class B extends A { m() { return super.m() }} class C extends B { m() { return super.m() } } var a = new C() return a.m()").equals("ok"); - code_v11("class A { m() { return 'ok' } } class B extends A {} class C extends B { m() { return super.m() } } var a = new C() return a.m()").equals("ok"); - code_v11("class A { m() { return 'okA' } } class B extends A { m() { return super.m() + 'B' }} class C extends B { m() { return super.m() + 'C' } } var a = new C()return a.m()").equals("okABC"); - code_v11("class A { items } class B extends A { constructor() { this.items = [] } } var x = new B() return x").equals("B {items: []}"); - code_v11("class A { items } class B extends A { constructor() { this.items = [] super() } } var x = new B() return x").equals("B {items: []}"); - code_v11("class A { m() { return 'parent' } t() { return this.m() } } class B extends A { m() { return 'enfant' } } return new B().t()").equals("enfant"); - code_v11("class A { m() { return 'parent' } t() { return m() } } class B extends A { m() { return 'enfant' } } return new B().t()").equals("enfant"); - code_v11("class A { public id; } class W extends A {} class H extends W { constructor(id){ this.id=id } }").equals("null"); + code_v2("class A { x = 10 } class B extends A {} var a = new B() return a.x").equals("10"); + code_v2("class A { m() { return 'ok' } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("ok"); + code_v2("class A { x = 10 } class B extends A {} class C extends B {} var a = new C() return a.x").equals("10"); + code_v2("class A { m() { return 'ok' } } class B extends A {} class C extends B {} var a = new C() return a.m()").equals("ok"); + code_v2("class A { m() { return 'ok' } } class B extends A { m() { return super.m() }} class C extends B { m() { return super.m() } } var a = new C() return a.m()").equals("ok"); + code_v2("class A { m() { return 'ok' } } class B extends A {} class C extends B { m() { return super.m() } } var a = new C() return a.m()").equals("ok"); + code_v2("class A { m() { return 'okA' } } class B extends A { m() { return super.m() + 'B' }} class C extends B { m() { return super.m() + 'C' } } var a = new C()return a.m()").equals("okABC"); + code_v2("class A { items } class B extends A { constructor() { this.items = [] } } var x = new B() return x").equals("B {items: []}"); + code_v2("class A { items } class B extends A { constructor() { this.items = [] super() } } var x = new B() return x").equals("B {items: []}"); + code_v2("class A { m() { return 'parent' } t() { return this.m() } } class B extends A { m() { return 'enfant' } } return new B().t()").equals("enfant"); + code_v2("class A { m() { return 'parent' } t() { return m() } } class B extends A { m() { return 'enfant' } } return new B().t()").equals("enfant"); + code_v2("class A { public id; } class W extends A {} class H extends W { constructor(id){ this.id=id } }").equals("null"); section("Access levels: fields"); - code_v11("class A { x = 10 } var a = new A() return a.x").equals("10"); - code_v11("class A { public x = 10 } var a = new A() return a.x").equals("10"); - code_v11("class A { protected x = 10 } var a = new A() return a.x").equals("null"); - code_v11("class A { private x = 10 } var a = new A() return a.x").equals("null"); - code_v11("class A { private x = 10 m() { return x } } var a = new A() return a.m()").equals("10"); - code_v11("class A { private x = 10 } class B extends A {} var a = new B() return a.x").equals("null"); - code_v11("class A { protected x = 10 } class B extends A {} var a = new B() return a.x").equals("null"); - code_v11("class A { protected x = 10 } class B extends A { m() { return x } } var a = new B() return a.m()").equals("10"); - code_v11("class A { private x = 10 constructor() { x = 15 } } var a = new A() return a").equals("A {x: 15}"); - code_v11("class A { private x; constructor() { this.x = []; } } return new A()").equals("A {x: []}"); - code_v11("class Parent { private chaine = 'Nawak'; public get_chaine_parent() { return this.chaine; } } class Enfant extends Parent { public get_chaine_enfant() { return this.get_chaine_parent() } } var e = Enfant() return [e.get_chaine_parent(), e.get_chaine_enfant() ]").equals("[Nawak, Nawak]"); - code_v11("class Parent { protected chaine = 'Nawak'; public get_chaine_parent() { return this.chaine; } } class Enfant extends Parent { public get_chaine_enfant() { return this.get_chaine_parent() } } var e = Enfant() return [e.get_chaine_parent(), e.get_chaine_enfant() ]").equals("[Nawak, Nawak]"); - code_v11("class A { private x; constructor() { this.x = [] push(this.x, 10); } } return new A()").equals("A {x: [10]}"); - - code_v11("class A { private x = 10 m() { return x } } var a = new A() return a.m()").equals("10"); + code_v2("class A { x = 10 } var a = new A() return a.x").equals("10"); + code_v2("class A { public x = 10 } var a = new A() return a.x").equals("10"); + code_v2("class A { protected x = 10 } var a = new A() return a.x").equals("null"); + code_v2("class A { private x = 10 } var a = new A() return a.x").equals("null"); + code_v2("class A { private x = 10 m() { return x } } var a = new A() return a.m()").equals("10"); + code_v2("class A { private x = 10 } class B extends A {} var a = new B() return a.x").equals("null"); + code_v2("class A { protected x = 10 } class B extends A {} var a = new B() return a.x").equals("null"); + code_v2("class A { protected x = 10 } class B extends A { m() { return x } } var a = new B() return a.m()").equals("10"); + code_v2("class A { private x = 10 constructor() { x = 15 } } var a = new A() return a").equals("A {x: 15}"); + code_v2("class A { private x; constructor() { this.x = []; } } return new A()").equals("A {x: []}"); + code_v2("class Parent { private chaine = 'Nawak'; public get_chaine_parent() { return this.chaine; } } class Enfant extends Parent { public get_chaine_enfant() { return this.get_chaine_parent() } } var e = Enfant() return [e.get_chaine_parent(), e.get_chaine_enfant() ]").equals("[Nawak, Nawak]"); + code_v2("class Parent { protected chaine = 'Nawak'; public get_chaine_parent() { return this.chaine; } } class Enfant extends Parent { public get_chaine_enfant() { return this.get_chaine_parent() } } var e = Enfant() return [e.get_chaine_parent(), e.get_chaine_enfant() ]").equals("[Nawak, Nawak]"); + code_v2("class A { private x; constructor() { this.x = [] push(this.x, 10); } } return new A()").equals("A {x: [10]}"); + + code_v2("class A { private x = 10 m() { return x } } var a = new A() return a.m()").equals("10"); section("Access levels: static fields"); - code_v11("class A { static x = 10 } return A.x").equals("10"); - code_v11("class A { public static x = 10 } return A.x").equals("10"); - code_v11("class A { protected static x = 10 } return A.x").equals("null"); - code_v11("class A { private static x = 10 } return A.x").equals("null"); - code_v11("class A { private static x = 10 static m() { return x } } return A.m()").equals("10"); - code_v11("class A { private static x = 10 } class B extends A {} return B.x").equals("null"); - code_v11("class A { protected static x = 10 } class B extends A {} return B.x").equals("null"); - code_v11("class A { protected static x = 10 } class B extends A { static m() { return x } } return B.m()").equals("10"); - code_v11("class A { private static x = 10 static m() { return A.x } } return A.m()").equals("10"); + code_v2("class A { static x = 10 } return A.x").equals("10"); + code_v2("class A { public static x = 10 } return A.x").equals("10"); + code_v2("class A { protected static x = 10 } return A.x").equals("null"); + code_v2("class A { private static x = 10 } return A.x").equals("null"); + code_v2("class A { private static x = 10 static m() { return x } } return A.m()").equals("10"); + code_v2("class A { private static x = 10 } class B extends A {} return B.x").equals("null"); + code_v2("class A { protected static x = 10 } class B extends A {} return B.x").equals("null"); + code_v2("class A { protected static x = 10 } class B extends A { static m() { return x } } return B.m()").equals("10"); + code_v2("class A { private static x = 10 static m() { return A.x } } return A.m()").equals("10"); section("Access levels: methods"); - code_v11("class A { m() { return 10 } } var a = new A() return a.m()").equals("10"); - code_v11("class A { public m() { return 10 } } var a = new A() return a.m()").equals("10"); - code_v11("class A { protected m() { return 10 } } var a = new A() return a.m()").equals("null"); - code_v11("class A { private m() { return 10 } } var a = new A() return a.m()").equals("null"); - code_v11("class A { public m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("10"); - code_v11("class A { protected m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("null"); - code_v11("class A { private m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("null"); - code_v11("class A { protected m() { return 10 } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("10"); + code_v2("class A { m() { return 10 } } var a = new A() return a.m()").equals("10"); + code_v2("class A { public m() { return 10 } } var a = new A() return a.m()").equals("10"); + code_v2("class A { protected m() { return 10 } } var a = new A() return a.m()").equals("null"); + code_v2("class A { private m() { return 10 } } var a = new A() return a.m()").equals("null"); + code_v2("class A { public m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("10"); + code_v2("class A { protected m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("null"); + code_v2("class A { private m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("null"); + code_v2("class A { protected m() { return 10 } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("10"); section("Access levels: constructors"); - code_v11("class A { constructor() { } } return new A()").equals("A {}"); - code_v11("class A { public constructor() { } } return new A()").equals("A {}"); - code_v11("class A { protected constructor() { } } return new A()").error(Error.PROTECTED_CONSTRUCTOR); - code_v11("class A { private constructor() { } } return new A()").error(Error.PRIVATE_CONSTRUCTOR); - code_v11("class A { public constructor() { } } class B extends A {} return new B()").equals("B {}"); - code_v11("class A { x protected constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").equals("10"); - code_v11("class A { x private constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").error(Error.PRIVATE_CONSTRUCTOR); - code_v11("class A { private constructor() { } } class B extends A {} return new B()").equals("B {}"); - code_v11("class A { private constructor() {} static getInstance() { return new A() } } return A.getInstance()").equals("A {}"); + code_v2("class A { constructor() { } } return new A()").equals("A {}"); + code_v2("class A { public constructor() { } } return new A()").equals("A {}"); + code_v2("class A { protected constructor() { } } return new A()").error(Error.PROTECTED_CONSTRUCTOR); + code_v2("class A { private constructor() { } } return new A()").error(Error.PRIVATE_CONSTRUCTOR); + code_v2("class A { public constructor() { } } class B extends A {} return new B()").equals("B {}"); + code_v2("class A { x protected constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").equals("10"); + code_v2("class A { x private constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").error(Error.PRIVATE_CONSTRUCTOR); + code_v2("class A { private constructor() { } } class B extends A {} return new B()").equals("B {}"); + code_v2("class A { private constructor() {} static getInstance() { return new A() } } return A.getInstance()").equals("A {}"); section("Access levels: static methods"); - code_v11("class A { static m() { return 10 } } return A.m()").equals("10"); - code_v11("class A { public static m() { return 10 } } return A.m()").equals("10"); - code_v11("class A { protected static m() { return 10 } } return A.m()").error(Error.PROTECTED_STATIC_METHOD); - code_v11("class A { private static m() { return 10 } } return A.m()").error(Error.PRIVATE_STATIC_METHOD); - code_v11("class A { public static m() { return 10 } } class B extends A {} return B.m()").equals("10"); - code_v11("class A { protected static m() { return 10 } } class B extends A {} return B.m()").error(Error.PROTECTED_STATIC_METHOD); - code_v11("class A { private static m() { return 10 } } class B extends A {} return B.m()").error(Error.PRIVATE_STATIC_METHOD); + code_v2("class A { static m() { return 10 } } return A.m()").equals("10"); + code_v2("class A { public static m() { return 10 } } return A.m()").equals("10"); + code_v2("class A { protected static m() { return 10 } } return A.m()").error(Error.PROTECTED_STATIC_METHOD); + code_v2("class A { private static m() { return 10 } } return A.m()").error(Error.PRIVATE_STATIC_METHOD); + code_v2("class A { public static m() { return 10 } } class B extends A {} return B.m()").equals("10"); + code_v2("class A { protected static m() { return 10 } } class B extends A {} return B.m()").error(Error.PROTECTED_STATIC_METHOD); + code_v2("class A { private static m() { return 10 } } class B extends A {} return B.m()").error(Error.PRIVATE_STATIC_METHOD); section("Initialization of fields"); - code_v11("class A { x = [1, 2, 3] } var a = new A() return a.x").equals("[1, 2, 3]"); - code_v11("class A { x = [1, 2, 3] } var a = new A() push(a.x, 4) var b = new A() return b.x").equals("[1, 2, 3]"); - code_v11("class B { y = 10 } class A { x = new B() } var a = new A() return a.x").equals("B {y: 10}"); - code_v11("class B { y = 10 } class A { x = new B() } var a = new A() return a.x.y").equals("10"); - code_v11("class B { y = 10 } class A { static x = new B() } return A.x").equals("B {y: 10}"); + code_v2("class A { x = [1, 2, 3] } var a = new A() return a.x").equals("[1, 2, 3]"); + code_v2("class A { x = [1, 2, 3] } var a = new A() push(a.x, 4) var b = new A() return b.x").equals("[1, 2, 3]"); + code_v2("class B { y = 10 } class A { x = new B() } var a = new A() return a.x").equals("B {y: 10}"); + code_v2("class B { y = 10 } class A { x = new B() } var a = new A() return a.x.y").equals("10"); + code_v2("class B { y = 10 } class A { static x = new B() } return A.x").equals("B {y: 10}"); section("Initialization of static fields"); - code_v11("class A { public static x = arrayMap([1, 3, 5], function(y) { return y ** 3 }) } return A.x").equals("[1, 27, 125]"); - code_v11("class A { static x = arrayMap([1, 3, 5], function(y) { return y ** 3 }) } return A.x").equals("[1, 27, 125]"); - code_v11("class Map { public static obstacles = toUpper('hello') } return Map.obstacles").equals("HELLO"); + code_v2("class A { public static x = arrayMap([1, 3, 5], function(y) { return y ** 3 }) } return A.x").equals("[1, 27, 125]"); + code_v2("class A { static x = arrayMap([1, 3, 5], function(y) { return y ** 3 }) } return A.x").equals("[1, 27, 125]"); + code_v2("class Map { public static obstacles = toUpper('hello') } return Map.obstacles").equals("HELLO"); section("Method is a system method"); - code_v11("class A { sqrt() { return sqrt(25) } }").equals("null"); - DISABLED_code_v11("class A { sqrt() { return sqrt(25) } } return new A().sqrt()").equals("5"); + code_v2("class A { sqrt() { return sqrt(25) } }").equals("null"); + DISABLED_code_v2("class A { sqrt() { return sqrt(25) } } return new A().sqrt()").equals("5"); section("Return of field"); - code_v11("class R { f = [] m(k, r) { return this.f[k] = r } } var x = new R() return x.m(1, 2)").equals("2"); - code_v11("class R { private f = [] m(k, r) { return this.f[k] = r } } var x = new R() return x.m(1, 'hello')").equals("hello"); + code_v2("class R { f = [] m(k, r) { return this.f[k] = r } } var x = new R() return x.m(1, 2)").equals("2"); + code_v2("class R { private f = [] m(k, r) { return this.f[k] = r } } var x = new R() return x.m(1, 'hello')").equals("hello"); section("Constant in static field"); - code_v11("class A { static bulbsNameChip = ['puny_bulb': PI] } return A.bulbsNameChip").equals("[puny_bulb : 3.141592653589793]"); + code_v2("class A { static bulbsNameChip = ['puny_bulb': PI] } return A.bulbsNameChip").equals("[puny_bulb : 3.141592653589793]"); /* * Operators */ section("Object.operator !"); - code_v11("return !{}").equals("true"); - code_v11("return !{a: 32}").equals("false"); + code_v2("return !{}").equals("true"); + code_v2("return !{a: 32}").equals("false"); section("Object.operator | |"); // code_v11("var a = {a: 32, b: 'toto', c: false}; return |a|").equals("3"); @@ -229,32 +229,32 @@ public void run() { // code_v11("return 12 in {x: 5, y: 'yo'}").equals("false"); section("Object.operator . ()"); - code_v11("return { v: 12 }.v").equals("12"); - code_v11("var a = {b: 12, c: 5} return a.b").equals("12"); - code_v11("var a = {v: 5} return a.v = 12").equals("12"); - code_v11("var a = {v: 5} a.v = 12 return a").equals("{v: 12}"); - code_v11("var a = {v: 5} return a.v = 'salut'").equals("salut"); - code_v11("var a = {v: 5} a.v = 'salut' return a").equals("{v: salut}"); - code_v11("var a = {b: 12} return a.b += 10").equals("22"); - code_v11("var a = {b: 12} return a.b -= 10").equals("2"); - code_v11("var a = {b: 12} return a.b *= 10").equals("120"); - code_v11("var a = {b: 12} return a.b /= 10").almost(1.2); - code_v11("var a = {b: 12} return a.b %= 10").equals("2"); - code_v11("var o = {} o.new_val = 12 return o").equals("{new_val: 12}"); - code_v11("var o = {a: 'a'} o.b = 'b' return o").equals("{a: a, b: b}"); + code_v2("return { v: 12 }.v").equals("12"); + code_v2("var a = {b: 12, c: 5} return a.b").equals("12"); + code_v2("var a = {v: 5} return a.v = 12").equals("12"); + code_v2("var a = {v: 5} a.v = 12 return a").equals("{v: 12}"); + code_v2("var a = {v: 5} return a.v = 'salut'").equals("salut"); + code_v2("var a = {v: 5} a.v = 'salut' return a").equals("{v: salut}"); + code_v2("var a = {b: 12} return a.b += 10").equals("22"); + code_v2("var a = {b: 12} return a.b -= 10").equals("2"); + code_v2("var a = {b: 12} return a.b *= 10").equals("120"); + code_v2("var a = {b: 12} return a.b /= 10").almost(1.2); + code_v2("var a = {b: 12} return a.b %= 10").equals("2"); + code_v2("var o = {} o.new_val = 12 return o").equals("{new_val: 12}"); + code_v2("var o = {a: 'a'} o.b = 'b' return o").equals("{a: a, b: b}"); // DISABLED_code("Object.readonly.v = 5").exception(ls::vm::Exception::CANT_MODIFY_READONLY_OBJECT); // code_v11("var o = [{}, ''][0] return o.values").equals(""); - code_v11("var pq = [{p: 22, v: 55}] return pq[0].p").equals("22"); - code_v11("var pq = [{p: 22, v: 55}] var o = pq[0] return o.v").equals("55"); + code_v2("var pq = [{p: 22, v: 55}] return pq[0].p").equals("22"); + code_v2("var pq = [{p: 22, v: 55}] var o = pq[0] return o.v").equals("55"); section("Object.operator =="); - code_v11("class A {} return {} == new A").equals("false"); - code_v11("class A { }; class B { }; return new A() == new B();").equals("false"); - code_v11("class A {} return new A == new A").equals("true"); - code_v11("return {a: 2} == {}").equals("false"); - code_v11("return {a: 2} == {a: 1}").equals("false"); - code_v11("return {a: 2} == {b: 2}").equals("false"); - code_v11("return {a: 2} == {a: 2}").equals("false"); + code_v2("class A {} return {} == new A").equals("false"); + code_v2("class A { }; class B { }; return new A() == new B();").equals("false"); + code_v2("class A {} return new A == new A").equals("true"); + code_v2("return {a: 2} == {}").equals("false"); + code_v2("return {a: 2} == {a: 1}").equals("false"); + code_v2("return {a: 2} == {b: 2}").equals("false"); + code_v2("return {a: 2} == {a: 2}").equals("false"); section("Object.operator <"); // code("return {} < {}").equals("false"); @@ -293,11 +293,11 @@ public void run() { // code("return {a: 5, b: 'toto', c: true, d: -> 5}.values()").equals("[5, 'toto', true, ]"); section("Object.isTrue()"); - code_v11("if ({x: 12}) { return 5 } else { return 12 }").equals("5"); - code_v11("if ({}) { return 5 } else { return 12 }").equals("12"); + code_v2("if ({x: 12}) { return 5 } else { return 12 }").equals("5"); + code_v2("if ({}) { return 5 } else { return 12 }").equals("12"); section("Object.clone()"); - code_v11("var a = {v: 12} return [a]").equals("[{v: 12}]"); + code_v2("var a = {v: 12} return [a]").equals("[{v: 12}]"); section("Object.map()"); // code("return {}.map(x -> x + 1)").equals("{}"); diff --git a/src/test/java/test/TestOperators.java b/src/test/java/test/TestOperators.java index d36a3852..f98852ae 100644 --- a/src/test/java/test/TestOperators.java +++ b/src/test/java/test/TestOperators.java @@ -140,10 +140,10 @@ public void run() throws Exception { code("return 12 === 12.0").equals("true"); code("return null == [null]").equals("false"); code("return null != [null]").equals("true"); - code_v10("return [null] == null").equals("true"); // Bug in LS1.0 - code_v11("return [null] == null").equals("false"); // Fixed in 1.1 - code_v10("return [null] != null").equals("false"); // Bug in LS1.0 - code_v11("return [null] != null").equals("true"); // Fixed in 1.1 + code_v1("return [null] == null").equals("true"); // Bug in LS1.0 + code_v2("return [null] == null").equals("false"); // Fixed in 1.1 + code_v1("return [null] != null").equals("false"); // Bug in LS1.0 + code_v2("return [null] != null").equals("true"); // Fixed in 1.1 code("var a = 1; var result = -10 + (1- (a-1)); return result").equals("-9"); code("var a = 1; var result = 0; result = -10 + (1- (a-1)); return result").equals("-9"); @@ -195,14 +195,14 @@ public void run() throws Exception { for (var value2 : values2) { for (var operator : operators) { String expected = actualResults[r++]; - var c = code_v10("var a = " + value1 + " return a " + operator + " " + value2); + var c = code_v1("var a = " + value1 + " return a " + operator + " " + value2); if (expected.equals("error")) result = c.error(Error.INVALID_OPERATOR); else result = c.equals(expected); results.add("\"" + result + "\""); } for (var operator : assignmentOperators) { String expected = actualResults[r++]; - var c = code_v10("var a = " + value1 + " a " + operator + " " + value2 + " return a"); + var c = code_v1("var a = " + value1 + " a " + operator + " " + value2 + " return a"); if (expected.equals("error")) result = c.error(Error.INVALID_OPERATOR); else result = c.equals(expected); results.add("\"" + result + "\""); diff --git a/src/test/java/test/TestReference.java b/src/test/java/test/TestReference.java index 104e5315..d9970de6 100644 --- a/src/test/java/test/TestReference.java +++ b/src/test/java/test/TestReference.java @@ -7,22 +7,22 @@ public class TestReference extends TestCommon { public void run() throws Exception { section("Références"); - code_v10("var t = [3, 4, 5]; var a = @t[1] a++ return t;").equals("[3, 4, 5]"); - code_v10("var t = [3, 4, 5]; var a = null a = @t[1] a++ return t;").equals("[3, 4, 5]"); - code_v10("var t = 0; var f = function(a) { t = a }; f([]);").equals("null"); - code_v10("var t = 0; var f = function(a) { t = a }; var b = []; f(b);").equals("null"); - code_v10("var t = 0; var f = function(a) { t = a }; var b = []; f(b); push(t, 5);").equals("null"); - code_v10("var t = 0; var f = function(a) { t = a }; var b = []; f(b); push(t, 5); return [t, b];").equals("[[5], []]"); - code_v10("var t = 0; var f = function(a) { t = @a }; var b = []; f(b); push(t, 5); return b;").equals("[]"); - code_v10("var t = 0; var f = function(@a) { t = @a }; var b = []; f(b); push(t, 5); return b;").equals("[5]"); - code_v10("var t = 0; var f = function(a) { t; }; f(t); return 'ok';").equals("ok"); - code_v10("function ref() { var a = 2; return @a; } return 1 / ref();").equals("0,5"); - code_v10("var a = @[1, 2, 3]; var b = @a; return (@(b));").equals("[1, 2, 3]"); - code_v10("var count = count([1, 2, 3]) return count").equals("3"); - code_v10("var a = 12; var b = @a; a++; return [a, b]").equals("[13, 12]"); - code_v10("var a = 12; var b = @a; var c = @b; a++; return [a, b, c]").equals("[13, 12, 12]"); - code_v10("var a = [12]; var b = @a[0]; a[0]++; return [a, b]").equals("[[13], 12]"); - code_v10("var a = @[1, 2, 3]; var b = @a; (@(b));").equals("null"); - code_v10("var a = @[1, 2, 3]; var b = @a; return (@(b));").equals("[1, 2, 3]"); + code_v1("var t = [3, 4, 5]; var a = @t[1] a++ return t;").equals("[3, 4, 5]"); + code_v1("var t = [3, 4, 5]; var a = null a = @t[1] a++ return t;").equals("[3, 4, 5]"); + code_v1("var t = 0; var f = function(a) { t = a }; f([]);").equals("null"); + code_v1("var t = 0; var f = function(a) { t = a }; var b = []; f(b);").equals("null"); + code_v1("var t = 0; var f = function(a) { t = a }; var b = []; f(b); push(t, 5);").equals("null"); + code_v1("var t = 0; var f = function(a) { t = a }; var b = []; f(b); push(t, 5); return [t, b];").equals("[[5], []]"); + code_v1("var t = 0; var f = function(a) { t = @a }; var b = []; f(b); push(t, 5); return b;").equals("[]"); + code_v1("var t = 0; var f = function(@a) { t = @a }; var b = []; f(b); push(t, 5); return b;").equals("[5]"); + code_v1("var t = 0; var f = function(a) { t; }; f(t); return 'ok';").equals("ok"); + code_v1("function ref() { var a = 2; return @a; } return 1 / ref();").equals("0,5"); + code_v1("var a = @[1, 2, 3]; var b = @a; return (@(b));").equals("[1, 2, 3]"); + code_v1("var count = count([1, 2, 3]) return count").equals("3"); + code_v1("var a = 12; var b = @a; a++; return [a, b]").equals("[13, 12]"); + code_v1("var a = 12; var b = @a; var c = @b; a++; return [a, b, c]").equals("[13, 12, 12]"); + code_v1("var a = [12]; var b = @a[0]; a[0]++; return [a, b]").equals("[[13], 12]"); + code_v1("var a = @[1, 2, 3]; var b = @a; (@(b));").equals("null"); + code_v1("var a = @[1, 2, 3]; var b = @a; return (@(b));").equals("[1, 2, 3]"); } } diff --git a/src/test/resources/ai/code/knapsack_11.leek b/src/test/resources/ai/code/knapsack_2.leek similarity index 100% rename from src/test/resources/ai/code/knapsack_11.leek rename to src/test/resources/ai/code/knapsack_2.leek From 98c7394e14540e0b50fdb394853d887b248805de Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 26 Nov 2021 12:28:33 +0100 Subject: [PATCH 295/319] [test] Fix tests --- src/test/java/test/TestArray.java | 10 +++++----- src/test/java/test/TestFiles.java | 2 +- src/test/java/test/TestIf.java | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index 5152493a..888502dd 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -17,7 +17,7 @@ public void run() throws Exception { code_v1("return [1.21, -5, 4.55, 12, -6.7];").equals("[1,21, -5, 4,55, 12, -6,7]"); code_v2("return [1.21, -5, 4.55, 12, -6.7];").equals("[1.21, -5, 4.55, 12, -6.7]"); code("return [true, false, true];").equals("[true, false, true]"); - code_v2("[23, true, '', {}, 123]").equals("[23, true, '', {}, 123]"); + code_v2("return [23, true, 'salut', {}, 123]").equals("[23, true, salut, {}, 123]"); // DISABLED_code("var a = x -> x [1, 2, a]").equals("[1, 2, ]"); // DISABLED_code("[1m, 34324234m, 231232131232132134379897874534243257343341432423m]").equals("[1, 34324234, 231232131232132134379897874534243257343341432423]"); // DISABLED_code("[true, 'hello', 231232131232132134379897874534243257343341432423m]").equals("[true, 'hello', 231232131232132134379897874534243257343341432423]"); @@ -59,10 +59,10 @@ public void run() throws Exception { // DISABLED_code("var a = ['yo'] return a + '!';").equals("['yo', '!']"); code("var a = [5] var b = ['b'] return a + b;").equals("[5, b]"); code("var a = ['a'] return a + ['b'];").equals("[a, b]"); - code_v2("[1, 2] + {};").equals("[1, 2, {}]"); - code_v2("var a = [1, 2] a + {};").equals("[1, 2, {}]"); - code_v2("['a', 'b'] + {};").equals("['a', 'b', {}]"); - code_v2("var a = ['a', 'b'] a + {}").equals("['a', 'b', {}]"); + code_v2("return [1, 2] + {}").equals("[1, 2, {}]"); + code_v2("var a = [1, 2] return a + {};").equals("[1, 2, {}]"); + code_v2("return ['a', 'b'] + {}").equals("[a, b, {}]"); + code_v2("var a = ['a', 'b'] return a + {}").equals("[a, b, {}]"); // DISABLED_code("return ['a', 'b'] + (x -> x)").equals("['a', 'b', ]"); // DISABLED_code("var a = ['a', 'b'] a + (x -> x)").equals("['a', 'b', ]"); // DISABLED_code("['a', 'b'] + Number").equals("['a', 'b', ]"); diff --git a/src/test/java/test/TestFiles.java b/src/test/java/test/TestFiles.java index bfe3a1b8..01ffc787 100644 --- a/src/test/java/test/TestFiles.java +++ b/src/test/java/test/TestFiles.java @@ -37,7 +37,7 @@ public void run() { // file("test/code/product_n_return.leek").equals("265252859812191058636308480000000"); // file("test/code/product_n_arrays.leek").equals("[5040]"); // file("test/code/product_coproduct.leek").equals("171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000"); - file_v2("ai/code/fold_left.leek").equals("[{w: 1}, {w: 3}, {w: 4}, {w: 2}, {w: 7}, {w: 5}, {w: 8}, {w: 9}, {w: 6}]"); + DISABLED_file_v2("ai/code/fold_left.leek").equals("[{w: 1}, {w: 3}, {w: 4}, {w: 2}, {w: 7}, {w: 5}, {w: 8}, {w: 9}, {w: 6}]"); // file("test/code/fold_left_2.leek").equals("{p: 6, v: {p: 9, v: {p: 8, v: {p: 5, v: {p: 7, v: { ... }}}}}}"); // file("test/code/fold_right.leek").equals("[{w: 6}, {w: 9}, {w: 8}, {w: 5}, {w: 7}, {w: 2}, {w: 4}, {w: 3}, {w: 1}]"); // file("test/code/fold_right_2.leek").equals("{p: {p: {p: {p: {p: { ... }, v: 7}, v: 2}, v: 4}, v: 3}, v: 1}"); diff --git a/src/test/java/test/TestIf.java b/src/test/java/test/TestIf.java index 19479be3..f0ff37d4 100644 --- a/src/test/java/test/TestIf.java +++ b/src/test/java/test/TestIf.java @@ -21,8 +21,8 @@ public void run() throws Exception { code("if (true) null else {}").equals("null"); // code("if true").error(ls::Error::UNEXPECTED_TOKEN, {""}); // code("if true else").error(ls::Error::UNEXPECTED_TOKEN, {"else"}); - code_v2("if (true) {a: 12} else {b: 5}").equals("{a: 12}"); - code_v2("if (true) { {a: 12} } else { {b: 5} }").equals("{a: 12}"); + DISABLED_code_v2("if (true) {a: 12} else {b: 5}").equals("{a: 12}"); + code_v2("if (true) { return {a: 12} } else { return {b: 5} }").equals("{a: 12}"); code("if (true) return 12 else return 5;").equals("12"); code("if (false) return 12 else return 5;").equals("5"); code("if (true) return 12;").equals("12"); From 66186de6ce6a130891dde777dc9659fa11f702c3 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 26 Nov 2021 12:31:34 +0100 Subject: [PATCH 296/319] [compiler] Fix paths on Windows --- .../java/leekscript/compiler/LeekScript.java | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/main/java/leekscript/compiler/LeekScript.java b/src/main/java/leekscript/compiler/LeekScript.java index 8ad06a0b..ec63ef24 100644 --- a/src/main/java/leekscript/compiler/LeekScript.java +++ b/src/main/java/leekscript/compiler/LeekScript.java @@ -4,8 +4,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.StringWriter; +import java.nio.file.Paths; import java.net.MalformedURLException; -import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.nio.charset.StandardCharsets; @@ -31,7 +31,7 @@ public class LeekScript { - private final static String IA_PATH = "ai/"; + private final static String IA_PATH = "ai"; private static long id = 1; private static class AIClassEntry { @@ -52,12 +52,8 @@ public AIClassEntry(Class clazz, long timestamp) { private static URLClassLoader urlLoader; private static HashMap aiCache = new HashMap<>(); static { - try { - classpath = LeekScript.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath(); - arguments.addAll(Arrays.asList("-classpath", classpath, "-nowarn")); - } catch (URISyntaxException e) { - e.printStackTrace(); - } + classpath = new File(LeekScript.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getPath(); + arguments.addAll(Arrays.asList("-classpath", classpath, "-nowarn")); try { urlLoader = new URLClassLoader(new URL[] { new File(IA_PATH).toURI().toURL() }, new ClassLoader() {}); } catch (MalformedURLException e) { @@ -153,9 +149,9 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) if (!root.exists()) root.mkdir(); String javaClassName = "AI_" + file.getId(); String fileName = javaClassName + ".java"; - File compiled = new File(IA_PATH + javaClassName + ".class"); - File java = new File(IA_PATH + javaClassName + ".java"); - File lines = new File(IA_PATH + javaClassName + ".lines"); + File compiled = Paths.get(IA_PATH, javaClassName + ".class").toFile(); + File java = Paths.get(IA_PATH, javaClassName + ".java").toFile(); + File lines = Paths.get(IA_PATH, javaClassName + ".lines").toFile(); // Cache des classes en RAM d'abord var entry = aiCache.get(javaClassName); @@ -222,7 +218,6 @@ public static AI compile(AIFile file, String AIClass, boolean useClassCache) throw new LeekScriptException(Error.CANNOT_WRITE_AI, e.getMessage()); } - t = System.nanoTime(); var fileManager = new SimpleFileManager(compiler.getStandardFileManager(null, null, null)); var output = new StringWriter(); @@ -250,7 +245,7 @@ protected Class findClass(String name) throws ClassNotFoundException { if (useClassCache) { // Save bytecode try { - var classFile = new FileOutputStream(IA_PATH + compiledClass.getName() + ".class"); + var classFile = new FileOutputStream(Paths.get(IA_PATH, compiledClass.getName() + ".class").toFile()); classFile.write(compiledClass.getCompiledBinaries()); classFile.close(); } catch (IOException e) { From 6f6fb2405a7ad0f67af02b6dd8497f0ae38d4bea Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 26 Nov 2021 12:35:38 +0100 Subject: [PATCH 297/319] [test] Fix test --- src/test/java/test/TestCommon.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index 2c7c280c..9f4e3159 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -201,6 +201,9 @@ public Case file_v2(String code) { public Case DISABLED_file(String code) { return new Case(code, false); } + public Case DISABLED_file_v2(String code) { + return new Case(code, false, 2); + } public Case code_v1(String code) { return new Case(code, true, 1); } From 7ed9089d38fd49333d7ba8c263f9ba068376fe4a Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 26 Nov 2021 18:26:04 +0100 Subject: [PATCH 298/319] [test] Fix test --- src/test/java/test/TestFiles.java | 2 +- src/test/resources/ai/code/fold_left.leek | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/test/TestFiles.java b/src/test/java/test/TestFiles.java index 01ffc787..bfe3a1b8 100644 --- a/src/test/java/test/TestFiles.java +++ b/src/test/java/test/TestFiles.java @@ -37,7 +37,7 @@ public void run() { // file("test/code/product_n_return.leek").equals("265252859812191058636308480000000"); // file("test/code/product_n_arrays.leek").equals("[5040]"); // file("test/code/product_coproduct.leek").equals("171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000"); - DISABLED_file_v2("ai/code/fold_left.leek").equals("[{w: 1}, {w: 3}, {w: 4}, {w: 2}, {w: 7}, {w: 5}, {w: 8}, {w: 9}, {w: 6}]"); + file_v2("ai/code/fold_left.leek").equals("[{w: 1}, {w: 3}, {w: 4}, {w: 2}, {w: 7}, {w: 5}, {w: 8}, {w: 9}, {w: 6}]"); // file("test/code/fold_left_2.leek").equals("{p: 6, v: {p: 9, v: {p: 8, v: {p: 5, v: {p: 7, v: { ... }}}}}}"); // file("test/code/fold_right.leek").equals("[{w: 6}, {w: 9}, {w: 8}, {w: 5}, {w: 7}, {w: 2}, {w: 4}, {w: 3}, {w: 1}]"); // file("test/code/fold_right_2.leek").equals("{p: {p: {p: {p: {p: { ... }, v: 7}, v: 2}, v: 4}, v: 3}, v: 1}"); diff --git a/src/test/resources/ai/code/fold_left.leek b/src/test/resources/ai/code/fold_left.leek index e66c98f1..60c5416b 100644 --- a/src/test/resources/ai/code/fold_left.leek +++ b/src/test/resources/ai/code/fold_left.leek @@ -1 +1 @@ -return arrayFoldLeft([1, 3, 4, 2, 7, 5, 8, 9, 6], function(acc, x) { return push(acc, {w: x}) }, []) +return arrayFoldLeft([1, 3, 4, 2, 7, 5, 8, 9, 6], function(acc, x) { push(acc, {w: x}) return acc }, []) From b0bc4738c2a2aea66005c855c2edc5e939149cb8 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 29 Nov 2021 21:01:15 +0100 Subject: [PATCH 299/319] [object] Keep natural order --- .../java/leekscript/compiler/expression/LeekObject.java | 4 ++-- .../compiler/instruction/ClassDeclarationInstruction.java | 3 ++- src/main/java/leekscript/runner/values/ClassLeekValue.java | 3 ++- src/main/java/leekscript/runner/values/ObjectLeekValue.java | 3 ++- src/test/java/test/TestObject.java | 6 ++++++ 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekObject.java b/src/main/java/leekscript/compiler/expression/LeekObject.java index ab639603..fe9ecb14 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObject.java +++ b/src/main/java/leekscript/compiler/expression/LeekObject.java @@ -1,6 +1,6 @@ package leekscript.compiler.expression; -import java.util.HashMap; +import java.util.LinkedHashMap; import leekscript.common.Type; import leekscript.compiler.JavaWriter; @@ -9,7 +9,7 @@ public class LeekObject extends AbstractExpression { - private final HashMap mValues = new HashMap<>(); + private final LinkedHashMap mValues = new LinkedHashMap<>(); public void addEntry(String key, AbstractExpression value) { mValues.put(key, value); diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 6e0c236d..70ac1788 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -1,6 +1,7 @@ package leekscript.compiler.instruction; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map.Entry; import leekscript.compiler.AIFile; @@ -45,7 +46,7 @@ public ClassDeclarationMethod(ClassMethodBlock block, AccessLevel level) { private final IAWord token; private IAWord parentToken; private ClassDeclarationInstruction parent; - private HashMap fields = new HashMap<>(); + private LinkedHashMap fields = new LinkedHashMap<>(); private HashMap staticFields = new HashMap<>(); private HashMap fieldVariables = new HashMap<>(); private HashMap staticFieldVariables = new HashMap<>(); diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 088af652..e0616921 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -1,6 +1,7 @@ package leekscript.runner.values; import java.util.HashMap; +import java.util.LinkedHashMap; import leekscript.AILog; import leekscript.runner.AI; @@ -42,7 +43,7 @@ public ClassStaticMethod(LeekFunction value, AccessLevel level) { public AI ai; public String name; public ClassLeekValue parent; - public HashMap fields = new HashMap<>(); + public LinkedHashMap fields = new LinkedHashMap<>(); public HashMap staticFields = new HashMap<>(); public HashMap constructors = new HashMap<>(); public HashMap methods = new HashMap<>(); diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 91b75902..ef59c3e2 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -1,6 +1,7 @@ package leekscript.runner.values; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Set; import leekscript.AILog; @@ -14,7 +15,7 @@ public class ObjectLeekValue { public final ClassLeekValue clazz; - public final HashMap fields = new HashMap<>(); + public final LinkedHashMap fields = new LinkedHashMap<>(); public ObjectLeekValue(ClassLeekValue clazz) { this.clazz = clazz; diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index ad4a2c31..35a861cc 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -214,6 +214,12 @@ public void run() { section("Constant in static field"); code_v2("class A { static bulbsNameChip = ['puny_bulb': PI] } return A.bulbsNameChip").equals("[puny_bulb : 3.141592653589793]"); + section("Object.string()"); + code_v2("return string({x: 1, y: 2, z: 3})").equals("{x: 1, y: 2, z: 3}"); + code_v2("return string({z: 1, y: 2, x: 3})").equals("{z: 1, y: 2, x: 3}"); + code_v2("class A { z = 1 y = 2 x = 3 } return string(new A())").equals("A {z: 1, y: 2, x: 3}"); + code_v2("class A { x = 1 y = 2 z = 3 } return string(new A())").equals("A {x: 1, y: 2, z: 3}"); + /* * Operators */ From 8b810370fd87a57ce3d4c60954521e03870ff817 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 29 Nov 2021 21:01:15 +0100 Subject: [PATCH 300/319] [test] Add min and max version --- src/test/java/test/TestArray.java | 88 +++--- src/test/java/test/TestComments.java | 2 +- src/test/java/test/TestCommon.java | 51 ++-- src/test/java/test/TestFiles.java | 10 +- src/test/java/test/TestFunction.java | 18 +- src/test/java/test/TestGeneral.java | 10 +- src/test/java/test/TestGlobals.java | 8 +- src/test/java/test/TestIf.java | 6 +- src/test/java/test/TestJSON.java | 6 +- src/test/java/test/TestLoops.java | 6 +- src/test/java/test/TestMap.java | 18 +- src/test/java/test/TestNumber.java | 208 +++++++------- src/test/java/test/TestObject.java | 392 +++++++++++++------------- src/test/java/test/TestOperators.java | 4 +- 14 files changed, 416 insertions(+), 411 deletions(-) diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index 888502dd..de5ca1f7 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -15,9 +15,9 @@ public void run() throws Exception { code("return [1, 2, 3];").equals("[1, 2, 3]"); // DISABLED_code("[1l, 2l, 3l]").equals("[1, 2, 3]"); code_v1("return [1.21, -5, 4.55, 12, -6.7];").equals("[1,21, -5, 4,55, 12, -6,7]"); - code_v2("return [1.21, -5, 4.55, 12, -6.7];").equals("[1.21, -5, 4.55, 12, -6.7]"); + code_v2_("return [1.21, -5, 4.55, 12, -6.7];").equals("[1.21, -5, 4.55, 12, -6.7]"); code("return [true, false, true];").equals("[true, false, true]"); - code_v2("return [23, true, 'salut', {}, 123]").equals("[23, true, salut, {}, 123]"); + code_v2_("return [23, true, 'salut', {}, 123]").equals("[23, true, salut, {}, 123]"); // DISABLED_code("var a = x -> x [1, 2, a]").equals("[1, 2, ]"); // DISABLED_code("[1m, 34324234m, 231232131232132134379897874534243257343341432423m]").equals("[1, 34324234, 231232131232132134379897874534243257343341432423]"); // DISABLED_code("[true, 'hello', 231232131232132134379897874534243257343341432423m]").equals("[true, 'hello', 231232131232132134379897874534243257343341432423]"); @@ -42,9 +42,9 @@ public void run() throws Exception { // DISABLED_code("return [1] + true;").equals("[1, true]"); code("return [1] + [2] + [3];").equals("[1, 2, 3]"); code_v1("return [1] + [2.5] + ['a'];").equals("[1, 2,5, a]"); - code_v2("return [1] + [2.5] + ['a'];").equals("[1, 2.5, a]"); + code_v2_("return [1] + [2.5] + ['a'];").equals("[1, 2.5, a]"); code_v1("return ['a'] + [2.5] + [1];").equals("[a, 2,5, 1]"); - code_v2("return ['a'] + [2.5] + [1];").equals("[a, 2.5, 1]"); + code_v2_("return ['a'] + [2.5] + [1];").equals("[a, 2.5, 1]"); code("return [1] + ['a'];").equals("[1, a]"); code("return ['a'] + [1];").equals("[a, 1]"); // DISABLED_code("return [12.5] + null;").equals("[12.5, null]"); @@ -59,10 +59,10 @@ public void run() throws Exception { // DISABLED_code("var a = ['yo'] return a + '!';").equals("['yo', '!']"); code("var a = [5] var b = ['b'] return a + b;").equals("[5, b]"); code("var a = ['a'] return a + ['b'];").equals("[a, b]"); - code_v2("return [1, 2] + {}").equals("[1, 2, {}]"); - code_v2("var a = [1, 2] return a + {};").equals("[1, 2, {}]"); - code_v2("return ['a', 'b'] + {}").equals("[a, b, {}]"); - code_v2("var a = ['a', 'b'] return a + {}").equals("[a, b, {}]"); + code_v2_("return [1, 2] + {}").equals("[1, 2, {}]"); + code_v2_("var a = [1, 2] return a + {};").equals("[1, 2, {}]"); + code_v2_("return ['a', 'b'] + {}").equals("[a, b, {}]"); + code_v2_("var a = ['a', 'b'] return a + {}").equals("[a, b, {}]"); // DISABLED_code("return ['a', 'b'] + (x -> x)").equals("['a', 'b', ]"); // DISABLED_code("var a = ['a', 'b'] a + (x -> x)").equals("['a', 'b', ]"); // DISABLED_code("['a', 'b'] + Number").equals("['a', 'b', ]"); @@ -82,21 +82,21 @@ public void run() throws Exception { code("return [1, 2, 3] + null").equals("[1, 2, 3, null]"); code("var a = [1] return a % 2").equals("1"); code_v1("var a = [[1], [1]]; return (a[0] + a[2]) / 2").equals("1"); - code_v2("var a = [[1], [1]]; return (a[0] + a[2]) / 2").equals("1.0"); + code_v2_("var a = [[1], [1]]; return (a[0] + a[2]) / 2").equals("1.0"); code_v1("var effects = [[1], [1]];\n\nreturn (effects[0] + effects[2]) /2;").equals("1"); - code_v2("var effects = [[1], [1]];\n\nreturn (effects[0] + effects[2]) /2;").equals("1.0"); + code_v2_("var effects = [[1], [1]];\n\nreturn (effects[0] + effects[2]) /2;").equals("1.0"); section("Array.operator []"); code("return [1, 2, 3][1]").equals("2"); code("var a = [1, 2, 3] return a[0]").equals("1"); code_v1("var a = [1.6, 2.5, 3.4] return a[0]").equals("1,6"); - code_v2("var a = [1.6, 2.5, 3.4] return a[0]").equals("1.6"); + code_v2_("var a = [1.6, 2.5, 3.4] return a[0]").equals("1.6"); code("var a = [1, 2, 3] a[0] = 5 return a[0]").equals("5"); // code("var a = [23, 23, true, '', [], 123]; return |a|").equals("6"); code("var a = [] return !a").equals("true"); code("var a = [1, 2, 3] a[1] = 12 return a").equals("[1, 12, 3]"); code_v1("return [1.2, 321.42, 23.15]").equals("[1,2, 321,42, 23,15]"); - code_v2("return [1.2, 321.42, 23.15]").equals("[1.2, 321.42, 23.15]"); + code_v2_("return [1.2, 321.42, 23.15]").equals("[1.2, 321.42, 23.15]"); // code("return [1, 2, 3, 4, 5][1:3]").equals("[2, 3, 4]"); code("var a = [5, 'yolo', 12] return a[1]").equals("yolo"); code("var a = [12]; a[0]++; return a").equals("[13]"); @@ -105,7 +105,7 @@ public void run() throws Exception { code("var a = [[12], ''][0]; a[0]++; return a").equals("[13]"); // code("var a = [[12], ''][0] a[a]++ a").exception(ls::vm::Exception::ARRAY_KEY_IS_NOT_NUMBER); code_v1("var a = [[12], [5.5], ['a']] a[0][0] += 1 a[1][0] += 1 a[2][0] += 1 return a").equals("[[13], [6,5], [a1]]"); - code_v2("var a = [[12], [5.5], ['a']] a[0][0] += 1 a[1][0] += 1 a[2][0] += 1 return a").equals("[[13], [6.5], [a1]]"); + code_v2_("var a = [[12], [5.5], ['a']] a[0][0] += 1 a[1][0] += 1 a[2][0] += 1 return a").equals("[[13], [6.5], [a1]]"); // code("var a = [1, 2, 3] return a[0l]").equals("1"); // code("var a = [1, 2, 3] return a[1l]").equals("2"); // code("var a = [1, 2, 3] return a[2m]").equals("3"); @@ -113,10 +113,10 @@ public void run() throws Exception { code("var a = ['a', 'b', 'c'] return a[1.9]").equals("b"); code("return ['', [2][0]]").equals("[, 2]"); code_v1("return ['', [2.5][0]]").equals("[, 2,5]"); - code_v2("return ['', [2.5][0]]").equals("[, 2.5]"); + code_v2_("return ['', [2.5][0]]").equals("[, 2.5]"); code("var a = [1, 2, 3] return a[true]").equals("2"); code_v1("return [1, 2.5][1]").equals("2,5"); - code_v2("return [1, 2.5][1]").equals("2.5"); + code_v2_("return [1, 2.5][1]").equals("2.5"); code("return [1, true][0]").equals("1"); code("return [1, true][1]").equals("true"); // code("return [5l, 7l, 9l][2l]").equals("9"); @@ -154,7 +154,7 @@ public void run() throws Exception { code("return [1, 2, 3][true]").equals("2"); code("return ['1', '2', '3'][false]").equals("1"); code_v1("return [1.5, 2.5, 3.5][true]").equals("2,5"); - code_v2("return [1.5, 2.5, 3.5][true]").equals("2.5"); + code_v2_("return [1.5, 2.5, 3.5][true]").equals("2.5"); // section("Push with empty array access"); // code("var a = [] a[] = 12 return a").equals("[12]"); @@ -178,7 +178,7 @@ public void run() throws Exception { // DISABLED_code("var v = 12 var a = [v, 2, 3] a[0] += 5 return a[0];").equals("17"); // DISABLED_code("var a = [1, 2, 3] a += 'hello' return a;").equals("[1, 2, 3, 'hello']"); code_v1("var a = [1.5] a += ['a', 'b'] return a").equals("[1,5, a, b]"); - code_v2("var a = [1.5] a += ['a', 'b'] return a").equals("[1.5, a, b]"); + code_v2_("var a = [1.5] a += ['a', 'b'] return a").equals("[1.5, a, b]"); // DISABLED_code("var a = [1.5] a += false return a;").equals("[1.5, false]"); // DISABLED_code("var a = [1] a += <2, 3> a").equals("[1, 2, 3]"); // DISABLED_code("var a = [1] a += <5.5, 7.314> a").equals("[1, 5.5, 7.314]"); @@ -188,7 +188,7 @@ public void run() throws Exception { // DISABLED_code("var a = [1] a += 'a' return a;").equals("[1, 'a']"); // DISABLED_code("var a = [[1]] a[0] += [12, ''][0] return a[0];").equals("[1, 12]"); code_v1("var a = [1.11] a += [2, 3] return a").equals("[1,11, 2, 3]"); - code_v2("var a = [1.11] a += [2, 3] return a").equals("[1.11, 2, 3]"); + code_v2_("var a = [1.11] a += [2, 3] return a").equals("[1.11, 2, 3]"); // DISABLED_code("var a = [[1.55]] a[0] += [12.9, ''][0] return a[0];").equals("[1.55, 12.9]"); // DISABLED_code("var a = [[1.55]] a[0] += [-1.5, 6.7] return a[0];").equals("[1.55, -1.5, 6.7]"); // DISABLED_code("var a = [[1.55]] a[0] += <8, 4> a[0]").equals("[1.55, 4, 8]"); @@ -196,7 +196,7 @@ public void run() throws Exception { // DISABLED_code("var a = [[1.55]] a[0] += < -8.5, 4.7, 'hello'> a[0]").equals("[1.55, -8.5, 4.7, 'hello']"); code("var a = ['a'] return a += [1, 2]").equals("[a, 1, 2]"); code_v1("var a = ['a'] return a += [1.5, 2.5]").equals("[a, 1,5, 2,5]"); - code_v2("var a = ['a'] return a += [1.5, 2.5]").equals("[a, 1.5, 2.5]"); + code_v2_("var a = ['a'] return a += [1.5, 2.5]").equals("[a, 1.5, 2.5]"); // DISABLED_code("var a = ['a'] a += <1, 2>").equals("['a', 1, 2]"); // DISABLED_code("var a = ['a'] a += <1.5, 2.5>").equals("['a', 1.5, 2.5]"); // DISABLED_code("var a = ['a'] var b = <'b'> a += b a").equals("['a', 'b']"); @@ -208,7 +208,7 @@ public void run() throws Exception { // DISABLED_code("var a = [1] if (true) a += 12 return a;").equals("[1, 12]"); // DISABLED_code("var a = ['a'] if (true) a += 12 return a;").equals("['a', 12]"); code_v1("var a = [1.55]; a += 12.9; return a").equals("[1,55, 12,9]"); - code_v2("var a = [1.55]; a += 12.9; return a").equals("[1.55, 12.9]"); + code_v2_("var a = [1.55]; a += 12.9; return a").equals("[1.55, 12.9]"); section("Array.operator += on element"); code("var a = [5] a[0] += 1 return a;").equals("[6]"); @@ -272,7 +272,7 @@ public void run() throws Exception { section("Array.operator ^= on element"); code_v1("var a = [876] a[0] ^= 3 return a;").equals("[672221376]"); - code_v2("var a = [876] a[0] ^= 3 return a;").equals("[879]"); + code_v2_("var a = [876] a[0] ^= 3 return a;").equals("[879]"); section("Array.operator <<= on element"); code("var a = [123] a[0] <<= 12 return a;").equals("[503808]"); @@ -317,9 +317,9 @@ public void run() throws Exception { code_v1("return arrayFilter(['a', 'b', 'c', 'd'], function(k, @v) { v = 4; return k == 3; });").equals("[3 : 4]"); section("Array.filter() v1.1"); - code_v2("return arrayFilter([1, 2, 3, 4, 5, 6, 7, 8, 9], function(e) { return e > 5; });").equals("[6, 7, 8, 9]"); - code_v2("return arrayFilter([4, 5, 6, 'test', 8, 9], function(e) { return e == 'test'; });").equals("[test]"); - code_v2("return string(arrayFilter(['a', 'b', 'c', 'd'], function(k, v) { return k == 3; }));").equals("[d]"); + code_v2_("return arrayFilter([1, 2, 3, 4, 5, 6, 7, 8, 9], function(e) { return e > 5; });").equals("[6, 7, 8, 9]"); + code_v2_("return arrayFilter([4, 5, 6, 'test', 8, 9], function(e) { return e == 'test'; });").equals("[test]"); + code_v2_("return string(arrayFilter(['a', 'b', 'c', 'd'], function(k, v) { return k == 3; }));").equals("[d]"); section("Array.flatten()"); code("return arrayFlatten([6,7,[8,9]],99);").equals("[6, 7, 8, 9]"); @@ -328,11 +328,11 @@ public void run() throws Exception { section("Array.sort"); code_v1("return function() { var t = [null, null, 4, 8, 9]; sort(t); return t; }();").equals("[4, 8, 9, null, null]"); - code_v2("return function() { var t = [null, null, 4, 8, 9]; sort(t); return t; }();").equals("[null, null, 4, 8, 9]"); + code_v2_("return function() { var t = [null, null, 4, 8, 9]; sort(t); return t; }();").equals("[null, null, 4, 8, 9]"); code_v1("return function() { var t = [4, null, 4, null, 4]; sort(t); return t; }();").equals("[4, 4, 4, null, null]"); - code_v2("return function() { var t = [4, null, 4, null, 4]; sort(t); return t; }();").equals("[null, null, 4, 4, 4]"); + code_v2_("return function() { var t = [4, null, 4, null, 4]; sort(t); return t; }();").equals("[null, null, 4, 4, 4]"); code_v1("return function() { var t = [4, null, 5, null, 8]; sort(t, SORT_DESC); return t; }();").equals("[null, null, 8, 5, 4]"); - code_v2("return function() { var t = [4, null, 5, null, 8]; sort(t, SORT_DESC); return t; }();").equals("[8, 5, 4, null, null]"); + code_v2_("return function() { var t = [4, null, 5, null, 8]; sort(t, SORT_DESC); return t; }();").equals("[8, 5, 4, null, null]"); section("Array and references"); code_v1("var t = [@3, @4, @5]; return t;").equals("[3, 4, 5]"); @@ -345,7 +345,7 @@ public void run() throws Exception { code("return arrayMap([1, 2, 3], function(v) { var r = [] return r })").equals("[[], [], []]"); code("return arrayMap([1, 2, 3], function(v) { var r = [1, 2, 3] return r })").equals("[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"); code("var r = [] var a = arrayMap([1, 2, 3], function(v) { return r }) push(r, 1) return a").equals("[[1], <...>, <...>]"); - code_v2("class A { name part constructor(name, part) { this.name = name this.part = part } } var list = [new A('foo', true), new A('bar', false), new A('baz', true)] return arrayMap(list, function(a) { return a.name })").equals("[foo, bar, baz]"); + code_v2_("class A { name part constructor(name, part) { this.name = name this.part = part } } var list = [new A('foo', true), new A('bar', false), new A('baz', true)] return arrayMap(list, function(a) { return a.name })").equals("[foo, bar, baz]"); section("Array.map() v1.0"); code_v1("return arrayMap([1, 2, 3, 4, 5], function(e) { return e * 2; });").equals("[2, 4, 6, 8, 10]"); @@ -354,10 +354,10 @@ public void run() throws Exception { code_v1("return function() { var t = ['a':1,'b':2]; arrayMap(t, function(@k, @v) { v = 'tomate'; k = 'ctus'; return 3; }); return t; }();").equals("[a : tomate, b : tomate]"); section("Array.map() v1.1"); - code_v2("return arrayMap([1, 2, 3, 4, 5], function(e) { return e * 2; });").equals("[2, 4, 6, 8, 10]"); - code_v2("return arrayMap([4, 9, 16], sqrt);").equals("[2.0, 3.0, 4.0]"); - code_v2("return arrayMap(['a': 1, 'b': 2], function(k, v) { return k + v; });").equals("[a : a1, b : b2]"); - code_v2("return function() { var t = ['a': 1, 'b': 2]; arrayMap(t, function(k, v) { v = 'tomate'; k = 'ctus'; return 3; }); return t; }();").equals("[a : 1, b : 2]"); + code_v2_("return arrayMap([1, 2, 3, 4, 5], function(e) { return e * 2; });").equals("[2, 4, 6, 8, 10]"); + code_v2_("return arrayMap([4, 9, 16], sqrt);").equals("[2.0, 3.0, 4.0]"); + code_v2_("return arrayMap(['a': 1, 'b': 2], function(k, v) { return k + v; });").equals("[a : a1, b : b2]"); + code_v2_("return function() { var t = ['a': 1, 'b': 2]; arrayMap(t, function(k, v) { v = 'tomate'; k = 'ctus'; return 3; }); return t; }();").equals("[a : 1, b : 2]"); section("Array.foldLeft()"); code("return arrayFoldLeft([6, 7, 8, 9], function(a, b) { return a + b; }, 0)").equals("30"); @@ -374,7 +374,7 @@ public void run() throws Exception { code_v1("return string(function(){var t=[1,2,3]; arrayPartition(t, function(@v){ v=3; }); return t;}())").equals("[3, 3, 3]"); code_v1("return string(function(){var t=[1,2,3]; arrayPartition(t, function(k, @v){ v=3; }); return t;}())").equals("[3, 3, 3]"); code_v1("return string(arrayPartition([4,3,2,1], function(k,@v){ v=3; return kf)?(-1):(e { if x == 0m then return a end return fact(x - 1, x * a) } fact(10m, 1m)").equals("3628800"); // code("function test() { var fact = x -> if x == 1 { 1 } else { fact(x - 1) * x } fact(8) } test()").equals("40320"); file_v1("ai/code/knapsack.leek").equals("761"); - file_v2("ai/code/knapsack_2.leek").equals("761"); + file_v2_("ai/code/knapsack_2.leek").equals("761"); code("function cellsInRange(i) { var areaInRange = []; if (i == 0) { return cellsInRange(10); } else { return areaInRange; } } var myRange = cellsInRange(0); return myRange").equals("[]"); section("Redefinition"); @@ -27,7 +27,7 @@ public void run() { section("System function as argument"); code_v1("function t(@f) { return function(@a) { return arrayMap(a, f); } } return t(sqrt)([1, 4, 9, 16, 25]);").equals("[1, 2, 3, 4, 5]"); - code_v2("function t(f) { return function(a) { return arrayMap(a, f); } } return t(sqrt)([1, 4, 9, 16, 25]);").equals("[1.0, 2.0, 3.0, 4.0, 5.0]"); + code_v2_("function t(f) { return function(a) { return arrayMap(a, f); } } return t(sqrt)([1, 4, 9, 16, 25]);").equals("[1.0, 2.0, 3.0, 4.0, 5.0]"); section("Single null argument"); code("function f(a) { return 12; } return f(null);").equals("12"); @@ -35,9 +35,9 @@ public void run() { section("Capture argument"); code_v1("function f(@a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("12"); - code_v2("function f(a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("10"); + code_v2_("function f(a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("10"); code_v1("var f = function(@a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("12"); - code_v2("var f = function(a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("10"); + code_v2_("var f = function(a) { return function() { a += 2 } }; var x = 10 f(x)() return x;").equals("10"); section("Capture loop variable"); code("var sum = 0 for (var i = 0; i < 10; ++i) { sum += (function() { return i })() } return sum").equals("45"); @@ -49,7 +49,7 @@ public void run() { code("var x = 10 var f = function() { return x } var a = f() a += 5 return x").equals("10"); code_v1("var x = [] var f = function() { return @x } var a = f() push(a, 5) return x").equals("[5]"); code_v1("var x = [] var f = function() { return x } var a = f() push(a, 5) return x").equals("[]"); - code_v2("var x = [] var f = function() { return x } var a = f() push(a, 5) return x").equals("[5]"); + code_v2_("var x = [] var f = function() { return x } var a = f() push(a, 5) return x").equals("[5]"); section("Misc"); code("function f(x) { var s = 0 s |= 12 return s } f(12);").equals("null"); @@ -57,16 +57,16 @@ public void run() { code("function te(a){ return function(b){ return function(c){return a*b*c;}; }; } return te(2)(1)(2);").equals("4"); code("var tab = [2, 3, 4, 5, 6]; var r = []; for (var i : var j in tab) { r[i] = function() { return j; }; } return 4;").equals("4"); code_v1("var retour = [];for(var i=0;i<5;i++){if(i&1){var sqrt=function(e){return 1;}; push(retour, sqrt(4));}else{push(retour, sqrt(4));}}return string(retour);").equals("[2, 1, 2, 1, 2]"); - code_v2("var retour = [];for(var i=0;i<5;i++){if(i&1){var sqrt=function(e){return 1;}; push(retour, sqrt(4));}else{push(retour, sqrt(4));}}return string(retour);").equals("[2.0, 1, 2.0, 1, 2.0]"); + code_v2_("var retour = [];for(var i=0;i<5;i++){if(i&1){var sqrt=function(e){return 1;}; push(retour, sqrt(4));}else{push(retour, sqrt(4));}}return string(retour);").equals("[2.0, 1, 2.0, 1, 2.0]"); code_v1("var r = [1, 2, 3] var f = function() { return r } var x = f() push(x, 12) return r").equals("[1, 2, 3]"); - code_v2("var r = [1, 2, 3] var f = function() { return r } var x = f() push(x, 12) return r").equals("[1, 2, 3, 12]"); + code_v2_("var r = [1, 2, 3] var f = function() { return r } var x = f() push(x, 12) return r").equals("[1, 2, 3, 12]"); code("function f() { return [1, 2, 3] } var x = f();").equals("null"); code("var x = arrayMap([1, 2, 3], function(x) { return x });").equals("null"); code("var x = arrayMap([1, 2, 3], function(x) { return x }); debug(x);").equals("null"); code("var toto = 12; var f = function() { toto = 'salut'; }; [true, 12, f][2](); return toto").equals("salut"); code("var toto = 12; var f = function() { toto = 'salut'; }; var g = function() { return f; }; g()() return toto").equals("salut"); code_v1("function Coordonate(@par_x, @par_y) { var x = par_x; var y = par_y; var getX = function(){ return x; }; var getY = function(){ return y; };return @(function(@method) { if(method === 'getX'){ return getX; } if(method === 'getY'){ return getY; } }); } var c = Coordonate(5, 12) return [c('getX')(), c('getY')()]").equals("[5, 12]"); - code_v2("function Coordonate(par_x, par_y) { var x = par_x; var y = par_y; var getX = function(){ return x; }; var getY = function(){ return y; };return (function(method) { if(method === 'getX'){ return getX; } if(method === 'getY'){ return getY; } }); } var c = Coordonate(5, 12) return [c('getX')(), c('getY')()]").equals("[5, 12]"); + code_v2_("function Coordonate(par_x, par_y) { var x = par_x; var y = par_y; var getX = function(){ return x; }; var getY = function(){ return y; };return (function(method) { if(method === 'getX'){ return getX; } if(method === 'getY'){ return getY; } }); } var c = Coordonate(5, 12) return [c('getX')(), c('getY')()]").equals("[5, 12]"); code("function test() { var r = [1, 2, 3] return (r); } return test()").equals("[1, 2, 3]"); code("function test() { var r = [1, 2, 3] return (r); } var a = test() return a").equals("[1, 2, 3]"); code("function t(a) {} t([ [12], [12] ])").equals("null"); @@ -79,7 +79,7 @@ public void run() { code("getOperations()").equals("null"); code("var a = [function() { return 12 }] return a[0]()").equals("12"); code_v1("function push_to_array(array) { return function(element) { push(array, element); } } var arrayCurry = []; var functionToCall = push_to_array(arrayCurry); for (var i = 0; i < 5; i++) functionToCall(i); return arrayCurry").equals("[]"); - code_v2("function push_to_array(array) { return function(element) { push(array, element); } } var arrayCurry = []; var functionToCall = push_to_array(arrayCurry); for (var i = 0; i < 5; i++) functionToCall(i); return arrayCurry").equals("[0, 1, 2, 3, 4]"); + code_v2_("function push_to_array(array) { return function(element) { push(array, element); } } var arrayCurry = []; var functionToCall = push_to_array(arrayCurry); for (var i = 0; i < 5; i++) functionToCall(i); return arrayCurry").equals("[0, 1, 2, 3, 4]"); section("Modify argument"); code("function test(x) { x += 10 return x } return test(5)").equals("15"); diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index 497be43f..0d72fe5c 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -39,9 +39,9 @@ public void run() { code("var a return a = 12").equals("12"); code("var a a = 12 return a").equals("12"); code_v1("var a return a = 12.5").equals("12,5"); - code_v2("var a return a = 12.5").equals("12.5"); + code_v2_("var a return a = 12.5").equals("12.5"); code_v1("var a a = 12.5 return a").equals("12,5"); - code_v2("var a a = 12.5 return a").equals("12.5"); + code_v2_("var a a = 12.5 return a").equals("12.5"); code("var a return a = 'a'").equals("a"); code("var a a = 'a' return a").equals("a"); // code("var a return a = 12m").equals("12"); @@ -50,7 +50,7 @@ public void run() { code("var a = 'hello' return a = 2").equals("2"); code("var a = 2 a = 'hello' return a").equals("hello"); code("var a = 2 a = [1, 2] return a").equals("[1, 2]"); - code_v2("var a = 5.5 a = {} return a").equals("{}"); + code_v2_("var a = 5.5 a = {} return a").equals("{}"); // code("var a = [5, 7] a = 7 System.print(a)").output("7\n"); // code("var a = 7 a = [5, 12] a").equals("[5, 12]"); // code("var a = 7 System.print(a) a = <5, 12> System.print(a)").output("7\n<5, 12>\n"); @@ -89,7 +89,7 @@ public void run() { code("var b = 5 if (0) { b = 'salut' } return b").equals("5"); code("var a = 12 if (1) { a = 5 a++ } else { a = 3 } return a").equals("6"); code_v1("var a = 12 if (0) { a = 5 a++ } else { a = 5.5 } return a").equals("5,5"); - code_v2("var a = 12 if (0) { a = 5 a++ } else { a = 5.5 } return a").equals("5.5"); + code_v2_("var a = 12 if (0) { a = 5 a++ } else { a = 5.5 } return a").equals("5.5"); // code("var a = 12 if (0) { a = 5 a++ } else { a = 7l } return a").equals("7"); code("var b = 5 if (1) {} else { b = 'salut' } return b").equals("5"); code("var b = 5 if (0) {} else { b = 'salut' } return b").equals("salut"); @@ -103,7 +103,7 @@ public void run() { section("Assignments with +="); code_v1("var a = 10 a += 0.5 return a").equals("10,5"); - code_v2("var a = 10 a += 0.5 return a").equals("10.5"); + code_v2_("var a = 10 a += 0.5 return a").equals("10.5"); section("File"); file("ai/code/trivial.leek").equals("2"); diff --git a/src/test/java/test/TestGlobals.java b/src/test/java/test/TestGlobals.java index 83c3b993..66b89feb 100644 --- a/src/test/java/test/TestGlobals.java +++ b/src/test/java/test/TestGlobals.java @@ -22,8 +22,8 @@ public void run() throws Exception { code("global r = [] return r[5] += 12").equals("12"); code_v1("global r = 12 r = @null").equals("null"); code("global m = [] return m = m").equals("[]"); - code_v2("global m = {} return m = m").equals("{}"); - code_v2("global m = {a: 12} return m = m").equals("{a: 12}"); + code_v2_("global m = {} return m = m").equals("{}"); + code_v2_("global m = {a: 12} return m = m").equals("{a: 12}"); section("Globals operators"); code("global x = 12; x++; return x;").equals("13"); @@ -34,13 +34,13 @@ public void run() throws Exception { code("global x = 12; x -= 5; return x;").equals("7"); code("global x = 12; x *= 5; return x;").equals("60"); code_v1("global x = 12; x /= 5; return x;").equals("2,4"); - code_v2("global x = 12; x /= 5; return x;").equals("2.4"); + code_v2_("global x = 12; x /= 5; return x;").equals("2.4"); code("global x = 12; x %= 5; return x;").equals("2"); code("global x = 2; x **= 5; return x;").equals("32"); code("global x = 12; x |= 5; return x;").equals("13"); code("global x = 12; x &= 5; return x;").equals("4"); code_v1("global x = 12; x ^= 5; return x;").equals("248832"); - code_v2("global x = 12; x ^= 5; return x;").equals("9"); + code_v2_("global x = 12; x ^= 5; return x;").equals("9"); code("global x = 12; return x == 5;").equals("false"); code("global x = 12; return x === 5;").equals("false"); } diff --git a/src/test/java/test/TestIf.java b/src/test/java/test/TestIf.java index f0ff37d4..2849dec6 100644 --- a/src/test/java/test/TestIf.java +++ b/src/test/java/test/TestIf.java @@ -21,8 +21,8 @@ public void run() throws Exception { code("if (true) null else {}").equals("null"); // code("if true").error(ls::Error::UNEXPECTED_TOKEN, {""}); // code("if true else").error(ls::Error::UNEXPECTED_TOKEN, {"else"}); - DISABLED_code_v2("if (true) {a: 12} else {b: 5}").equals("{a: 12}"); - code_v2("if (true) { return {a: 12} } else { return {b: 5} }").equals("{a: 12}"); + DISABLED_code_v2_("if (true) {a: 12} else {b: 5}").equals("{a: 12}"); + code_v2_("if (true) { return {a: 12} } else { return {b: 5} }").equals("{a: 12}"); code("if (true) return 12 else return 5;").equals("12"); code("if (false) return 12 else return 5;").equals("5"); code("if (true) return 12;").equals("12"); @@ -70,7 +70,7 @@ public void run() throws Exception { code("if (1) return ['a'] else if (0) return [2] else return [5.5];").equals("[a]"); code("if (0) return ['a'] else if (1) return [2] else return [5.5];").equals("[2]"); code_v1("if (0) return ['a'] else if (0) return [2] else return [5.5];").equals("[5,5]"); - code_v2("if (0) return ['a'] else if (0) return [2] else return [5.5];").equals("[5.5]"); + code_v2_("if (0) return ['a'] else if (0) return [2] else return [5.5];").equals("[5.5]"); section("Ternary conditions"); code("return true ? 5 : 12;").equals("5"); diff --git a/src/test/java/test/TestJSON.java b/src/test/java/test/TestJSON.java index f60bd730..d165be15 100644 --- a/src/test/java/test/TestJSON.java +++ b/src/test/java/test/TestJSON.java @@ -86,9 +86,9 @@ public void run() throws Exception { code("return jsonDecode('12')").equals("12"); code("return jsonDecode('-589')").equals("-589"); code_v1("return jsonDecode('54.123')").equals("54,123"); - code_v2("return jsonDecode('54.123')").equals("54.123"); + code_v2_("return jsonDecode('54.123')").equals("54.123"); code_v1("return jsonDecode('-65.89')").equals("-65,89"); - code_v2("return jsonDecode('-65.89')").equals("-65.89"); + code_v2_("return jsonDecode('-65.89')").equals("-65.89"); // code("return jsonDecode('1234567890987')").equals("1234567890987"); code("return jsonDecode('\"\"')").equals(""); @@ -97,7 +97,7 @@ public void run() throws Exception { code("return jsonDecode('[]')").equals("[]"); code("return jsonDecode('[1,2,3]')").equals("[1, 2, 3]"); code_v1("return jsonDecode('[1.6,2.1,3.77]')").equals("[1,6, 2,1, 3,77]"); - code_v2("return jsonDecode('[1.6,2.1,3.77]')").equals("[1.6, 2.1, 3.77]"); + code_v2_("return jsonDecode('[1.6,2.1,3.77]')").equals("[1.6, 2.1, 3.77]"); code("return jsonDecode('[\"a\",\"b\",\"c\"]')").equals("[a, b, c]"); code("return jsonDecode('[[],[[],[]],[]]')").equals("[[], [[], []], []]"); diff --git a/src/test/java/test/TestLoops.java b/src/test/java/test/TestLoops.java index 3af39b29..17fbc8a8 100644 --- a/src/test/java/test/TestLoops.java +++ b/src/test/java/test/TestLoops.java @@ -42,7 +42,7 @@ public void run() { code("var s = [] var i = 0 var j = 0 while (i < 4) { j = i i++ while (j < 4) { j++ push(s, j) }} return s;").equals("[1, 2, 3, 4, 2, 3, 4, 3, 4, 4]"); code("var s = [] var i = 0 while (i < 2) { i++ var j = 0 while (j < 2) { j++ var k = 0 while (k < 2) { k++ push(s, k) }}} return s;").equals("[1, 2, 1, 2, 1, 2, 1, 2]"); code_v1("var s = [] var i = 0 while (i < 2) { i++ push(s, 0.5) var j = 0 while (j < 3) { j++ push(s, j) }} return s;").equals("[0,5, 1, 2, 3, 0,5, 1, 2, 3]"); - code_v2("var s = [] var i = 0 while (i < 2) { i++ push(s, 0.5) var j = 0 while (j < 3) { j++ push(s, j) }} return s;").equals("[0.5, 1, 2, 3, 0.5, 1, 2, 3]"); + code_v2_("var s = [] var i = 0 while (i < 2) { i++ push(s, 0.5) var j = 0 while (j < 3) { j++ push(s, j) }} return s;").equals("[0.5, 1, 2, 3, 0.5, 1, 2, 3]"); // DISABLED_code("var s = [] var i = 0 while (i < 2) { i++ s.push([]) var j = 0 while j < 3 { j++ s[|s| - 1] += 1 }} s").equals("[[1, 1, 1], [1, 1, 1]]"); // DISABLED_code("var s = [] var i = 0 while (i < 2) { i++ s.push([]) var j = 0 while j < 3 { j++ s[|s| - 1] += ('a'.code() + 3 * (i - 1) + j - 1).char() }} s").equals("[['a', 'b', 'c'], ['d', 'e', 'f']]"); // file("test/code/loops/lot_of_whiles_int.leek").equals("30030"); @@ -87,7 +87,7 @@ public void run() { code("var i = 0 for (i = 0; i < 10; i++) { } return i;").equals("10"); code("var i = 0 for (i = 0; i < 10; i++) { if (i == 5) { break } } return i;").equals("5"); code_v1("var i var c = 0 for (i = 0; i < 20; i += 0.573) { c++ } return i;").equals("20,055"); - code_v2("var i var c = 0 for (i = 0; i < 20; i += 0.573) { c++ } return i;").equals("20.05500000000001"); + code_v2_("var i var c = 0 for (i = 0; i < 20; i += 0.573) { c++ } return i;").equals("20.05500000000001"); code("var i = 's' var c = 0 for (i = []; count(i) < 8; push(i, 1)) { c++ } return i;").equals("[1, 1, 1, 1, 1, 1, 1, 1]"); // DISABLED_code("var i = 0 for (; i < 10; i += 0.5) { } return i;").equals("10"); // code("var i = 0 for (i = 2l; i < 10; i += 0.5) { } return i;").equals("10"); @@ -147,7 +147,7 @@ public void run() { code("var s = 0 for (var k : var v in [1, 2, 3, 4]) { s += k * v } return s;").equals("20"); // code("var s = '' for (var k : var v in ['a': 1, 'b': 2, 'c': 3, 'd': 4]) { s += v * k } return s;").equals("abbcccdddd"); code_v1("return (function (a) { var s = 0.0; for (var x in a) { s += x } return s; })([1, 2, 3, 4.25]);").equals("10,25"); - code_v2("return (function (a) { var s = 0.0; for (var x in a) { s += x } return s; })([1, 2, 3, 4.25]);").equals("10.25"); + code_v2_("return (function (a) { var s = 0.0; for (var x in a) { s += x } return s; })([1, 2, 3, 4.25]);").equals("10.25"); // DISABLED_code("var y = '' for k, x in { var x = [] x.push(4) x } { y += k + ':' + x + ' ' } y").equals("'0:4 '"); // DISABLED_code("var y = '' for k, x in { var x = [1: 2] x.insert(3, 4) x } { y += k + ':' + x + ' ' } y").equals("'1:2 3:4 '"); // DISABLED_code("var y = '' for k, x in { var x = [1: 2.5] x.insert(3, 4) x } { y += k + ':' + x + ' ' } y").equals("'1:2.5 3:4 '"); diff --git a/src/test/java/test/TestMap.java b/src/test/java/test/TestMap.java index 836d71a9..18eeed1b 100644 --- a/src/test/java/test/TestMap.java +++ b/src/test/java/test/TestMap.java @@ -57,13 +57,13 @@ public void run() { code("var m = ['a': 'b'] return m['a']").equals("b"); code("var m = [5: 12] return m[5]").equals("12"); code_v1("var m = [5: 12.5] return m[5]").equals("12,5"); - code_v2("var m = [5: 12.5] return m[5]").equals("12.5"); + code_v2_("var m = [5: 12.5] return m[5]").equals("12.5"); code("var m = [5.5: 12] return m[5.5]").equals("12"); code_v1("var m = [5.5: 12.5] return m[5.5]").equals("12,5"); - code_v2("var m = [5.5: 12.5] return m[5.5]").equals("12.5"); + code_v2_("var m = [5.5: 12.5] return m[5.5]").equals("12.5"); code("var m = ['salut': 12] return m['salut']").equals("12"); code_v1("var m = ['salut': 12.5] return m['salut']").equals("12,5"); - code_v2("var m = ['salut': 12.5] return m['salut']").equals("12.5"); + code_v2_("var m = ['salut': 12.5] return m['salut']").equals("12.5"); code("var m = ['salut': 'yolo'] return m['salut']").equals("yolo"); code("var m = ['a': 'b'] m['a'] = 'c' return m").equals("[a : c]"); code("var m = ['salut': 12] m['salut'] = 13 return m['salut']").equals("13"); @@ -76,22 +76,22 @@ public void run() { code("var m = [1: 2, 3: 4] m[5] = 6 return m").equals("[1 : 2, 3 : 4, 5 : 6]"); code("var m = ['a': 2, 'b': 4] m['c'] = 6 return m").equals("[a : 2, b : 4, c : 6]"); code_v1("var m = ['a': 2.5, 'b': 4.8] m['c'] = 6.9 return m").equals("[a : 2,5, b : 4,8, c : 6,9]"); - code_v2("var m = ['a': 2.5, 'b': 4.8] m['c'] = 6.9 return m").equals("[a : 2.5, b : 4.8, c : 6.9]"); + code_v2_("var m = ['a': 2.5, 'b': 4.8] m['c'] = 6.9 return m").equals("[a : 2.5, b : 4.8, c : 6.9]"); code("var m = [1: 'a', 2: 'b'] m[3] = 'c' return m").equals("[1 : a, 2 : b, 3 : c]"); code("var m = ['a': '2', 'b': '4'] m['c'] = '6' return m").equals("[a : 2, b : 4, c : 6]"); code("var m = [1: 2, 3: 4] m[3] = 6 return m").equals("[1 : 2, 3 : 6]"); code_v1("var m = [1: 2.5, 3: 4.5] m[3] = 6.5 return m").equals("[1 : 2,5, 3 : 6,5]"); - code_v2("var m = [1: 2.5, 3: 4.5] m[3] = 6.5 return m").equals("[1 : 2.5, 3 : 6.5]"); + code_v2_("var m = [1: 2.5, 3: 4.5] m[3] = 6.5 return m").equals("[1 : 2.5, 3 : 6.5]"); // code_v1("var m = [1.5: 2, 3.5: 4] m[3.5] = 6 return m").equals("[1,5 : 2, 3,5 : 6]"); - // code_v2("var m = [1.5: 2, 3.5: 4] m[3.5] = 6 return m").equals("[1.5 : 2, 3.5 : 6]"); + // code_v2_("var m = [1.5: 2, 3.5: 4] m[3.5] = 6 return m").equals("[1.5 : 2, 3.5 : 6]"); // code_v1("var m = [1.5: 2.5, 3.5: 4.5] m[3.5] = 6.5 return m").equals("[1,5 : 2,5, 3,5 : 6,5]"); - // code_v2("var m = [1.5: 2.5, 3.5: 4.5] m[3.5] = 6.5 return m").equals("[1.5 : 2.5, 3.5 : 6.5]"); + // code_v2_("var m = [1.5: 2.5, 3.5: 4.5] m[3.5] = 6.5 return m").equals("[1.5 : 2.5, 3.5 : 6.5]"); code("var m = ['1': 2, '3': 4] m['3'] = 6 return m").equals("[1 : 2, 3 : 6]"); // code_v1("var m = [1.5: 'a', 2.5: 'b'] m[2.5] = 'c' return m").equals("[1,5 : a, 2,5 : c]"); - // code_v2("var m = [1.5: 'a', 2.5: 'b'] m[2.5] = 'c' return m").equals("[1.5 : a, 2.5 : c]"); + // code_v2_("var m = [1.5: 'a', 2.5: 'b'] m[2.5] = 'c' return m").equals("[1.5 : a, 2.5 : c]"); code("return ['', [1: 2][1]]").equals("[, 2]"); code_v1("return ['', [1: 2.5][1]]").equals("[, 2,5]"); - code_v2("return ['', [1: 2.5][1]]").equals("[, 2.5]"); + code_v2_("return ['', [1: 2.5][1]]").equals("[, 2.5]"); code("var m = [] var ns = '01234566' return m[ns] = 1").equals("1"); section("Map.operator [] left-value"); diff --git a/src/test/java/test/TestNumber.java b/src/test/java/test/TestNumber.java index a8399c3d..563dc6cd 100644 --- a/src/test/java/test/TestNumber.java +++ b/src/test/java/test/TestNumber.java @@ -29,9 +29,9 @@ public void run() throws Exception { code("return -2 + 3;").equals("1"); code("return 5 * 5;").equals("25"); code_v1("return 15 / 3;").equals("5"); - code_v2("return 15 / 3;").equals("5.0"); + code_v2_("return 15 / 3;").equals("5.0"); code_v1("return 15 / 2;").equals("7,5"); - code_v2("return 15 / 2;").equals("7.5"); + code_v2_("return 15 / 2;").equals("7.5"); code("return 12 ** 2;").equals("144"); code("return 2 ** 5;").equals("32"); code("return 2 < 5;").equals("true"); @@ -91,17 +91,17 @@ public void run() throws Exception { code("var a = 2 return a -= 5;").equals("-3"); code("var a = 2 return a *= 5;").equals("10"); code_v1("var a = 100 return a /= 5;").equals("20"); - code_v2("var a = 100 return a /= 5;").equals("20.0"); + code_v2_("var a = 100 return a /= 5;").equals("20.0"); code("var a = 56 return a %= 17;").equals("5"); code("var a = 15 return a **= 2;").equals("225"); code_v1("var a = 1.5 return a * 0.5;").equals("0,75"); - code_v2("var a = 1.5 return a * 0.5;").equals("0.75"); + code_v2_("var a = 1.5 return a * 0.5;").equals("0.75"); // DISABLED_code("var i = 1m return i = i + 2m;").equals("3"); code("var a = 10; a += 10 - 2 * 3; return a;").equals("14"); section("multiple operations"); code_v1("return (33 - 2) / 2;").equals("15,5"); - code_v2("return (33 - 2) / 2;").equals("15.5"); + code_v2_("return (33 - 2) / 2;").equals("15.5"); code("return 12 < (45 / 4);").equals("false"); code("return 12 == (24 / 2);").equals("true"); // code("2.5 + 4.7").almost(7.2); @@ -433,29 +433,29 @@ public void run() throws Exception { // code("12$ / false").exception(ls::vm::Exception::DIVISION_BY_ZERO); // code("let a = 13$; a / false").exception(ls::vm::Exception::DIVISION_BY_ZERO); code_v1("return 13 / true;").equals("13"); - code_v2("return 13 / true;").equals("13.0"); + code_v2_("return 13 / true;").equals("13.0"); code_v1("return 14 / 2;").equals("7"); - code_v2("return 14 / 2;").equals("7.0"); + code_v2_("return 14 / 2;").equals("7.0"); code_v1("var a = 18; return a / 3;").equals("6"); - code_v2("var a = 18; return a / 3;").equals("6.0"); + code_v2_("var a = 18; return a / 3;").equals("6.0"); // code("14$ / []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); code_v1("var a = 17, b = 5 return a / b;").equals("3,4"); - code_v2("var a = 17, b = 5 return a / b;").equals("3.4"); + code_v2_("var a = 17, b = 5 return a / b;").equals("3.4"); section("Number.operator /="); code_v1("var a = 12 a /= 3 return a;").equals("4"); - code_v2("var a = 12 a /= 3 return a;").equals("4.0"); + code_v2_("var a = 12 a /= 3 return a;").equals("4.0"); code_v1("var a = 12 a /= 0.5 return a;").equals("24"); - code_v2("var a = 12 a /= 0.5 return a;").equals("24.0"); + code_v2_("var a = 12 a /= 0.5 return a;").equals("24.0"); code_v1("var a = 12 a /= true return a;").equals("12"); - code_v2("var a = 12 a /= true return a;").equals("12.0"); + code_v2_("var a = 12 a /= true return a;").equals("12.0"); code_v1("var a = null a /= 5 return a;").equals("0"); - code_v2("var a = null a /= 5 return a;").equals("0.0"); + code_v2_("var a = null a /= 5 return a;").equals("0.0"); // code("var a = 12 a /= false return a;").equals("nan"); // code("var a = 12$ a /= []").exception(ls::vm::Exception::NO_SUCH_OPERATOR); // code("var a = 12$ a /= [] a").exception(ls::vm::Exception::NO_SUCH_OPERATOR); code_v1("var a = 15; return ['', a /= 2];").equals("[, 7,5]"); - code_v2("var a = 15; return ['', a /= 2];").equals("[, 7.5]"); + code_v2_("var a = 15; return ['', a /= 2];").equals("[, 7.5]"); section("Number.operator <"); code("return 5 < 2;").equals("false"); @@ -556,11 +556,11 @@ public void run() throws Exception { code("return 87619 ^ 18431;").equals("70076"); code("return [87619, ''][0] ^ [18431, ''][0];").equals("70076"); code_v1("var a = 5 a ^= 2 return a;").equals("25"); // In LS 1.0, ^= was power equals - code_v2("var a = 87619 return a ^= 18431;").equals("70076"); - code_v2("var a = 87619 a ^= 18431 return a;").equals("70076"); + code_v2_("var a = 87619 return a ^= 18431;").equals("70076"); + code_v2_("var a = 87619 a ^= 18431 return a;").equals("70076"); code("return [87619, ''][0] ^ 18431;").equals("70076"); // code("87619$ ^= 18431").error(ls::Error::VALUE_MUST_BE_A_LVALUE, {"87619"}); - code_v2("var a = 87619 a ^= 18431 return a;").equals("70076"); + code_v2_("var a = 87619 a ^= 18431 return a;").equals("70076"); // code("[12, 'hello'][1] ^ 5").exception(ls::vm::Exception::NO_SUCH_OPERATOR); section("Number.operator <<"); @@ -641,11 +641,11 @@ public void run() throws Exception { // code("return abs;").equals(""); code("return abs(-12);").equals("12"); code_v1("return abs(-19.5);").equals("19,5"); - code_v2("return abs(-19.5);").equals("19.5"); + code_v2_("return abs(-19.5);").equals("19.5"); code("return abs(12);").equals("12"); // code("return abs(-16436435l)").equals("16436435"); code_v1("return abs(-12.67);").equals("12,67"); - code_v2("return abs(-12.67);").equals("12.67"); + code_v2_("return abs(-12.67);").equals("12.67"); code("return abs(['a', -15][1]);").equals("15"); // code("return (-17).abs()").equals("17"); // code("return (-19.5).abs()").equals("19.5"); @@ -654,24 +654,24 @@ public void run() throws Exception { section("Number.exp()"); code_v1("return exp(0)").equals("1"); - code_v2("return exp(0)").equals("1.0"); + code_v2_("return exp(0)").equals("1.0"); code_v1("return exp(1)").equals("2,718"); - code_v2("return exp(1)").almost(Math.E); + code_v2_("return exp(1)").almost(Math.E); code_v1("return exp(4)").equals("54,598"); - code_v2("return exp(4)").almost(54.598150033144236204); + code_v2_("return exp(4)").almost(54.598150033144236204); code_v1("return exp(4.89)").equals("132,954"); - code_v2("return exp(4.89)").almost(132.953574051282743085); + code_v2_("return exp(4.89)").almost(132.953574051282743085); code_v1("return exp(-2.97)").equals("0,051"); - code_v2("return exp(-2.97)").almost(0.051303310331919108); + code_v2_("return exp(-2.97)").almost(0.051303310331919108); code_v1("return exp(['a', 7.78][1])").equals("2 392,275"); - code_v2("return exp(['a', 7.78][1])").almost(2392.274820537377763685); + code_v2_("return exp(['a', 7.78][1])").almost(2392.274820537377763685); // code("return 0.exp();").equals("1"); // code("return 1.exp();").almost(Math.E); // code("return 7.exp();").almost(1096.633158428458500566); // code("return (-7).exp();").almost(0.000911881965554516); // code("return (-3.33).exp();").almost(0.035793105067655297); code_v1("return E ** 5;").equals("148,413"); - code_v2("return E ** 5;").almost(148.413159102576571513); + code_v2_("return E ** 5;").almost(148.413159102576571513); section("Number.floor()"); code("return floor(5.9);").equals("5"); @@ -702,24 +702,24 @@ public void run() throws Exception { code("return max(8, 88)").equals("88"); code("return max(5, 12);").equals("12"); code_v1("return max(5.0, 12);").equals("12"); - code_v2("return max(5.0, 12);").equals("12.0"); + code_v2_("return max(5.0, 12);").equals("12.0"); code_v1("return max(75.7, 12);").equals("75,7"); - code_v2("return max(75.7, 12);").almost(75.7); + code_v2_("return max(75.7, 12);").almost(75.7); code_v1("return max(5, 12.451);").equals("12,451"); - code_v2("return max(5, 12.451);").almost(12.451); + code_v2_("return max(5, 12.451);").almost(12.451); code("return max([5, 'a'][0], 4);").equals("5"); code("return max([5, 'a'][0], 76);").equals("76"); code("return max(4, [5, 'a'][0]);").equals("5"); code("return max(77, [5, 'a'][0]);").equals("77"); code("return max([55, 'a'][0], [5, 'a'][0]);").equals("55"); code_v1("return max(5, 12.8);").equals("12,8"); - code_v2("return max(5, 12.8);").equals("12.8"); + code_v2_("return max(5, 12.8);").equals("12.8"); code_v1("return max(15.7, 12.8);").equals("15,7"); - code_v2("return max(15.7, 12.8);").equals("15.7"); + code_v2_("return max(15.7, 12.8);").equals("15.7"); code_v1("return max([15.7, ''][0], 12.8);").equals("15,7"); - code_v2("return max([15.7, ''][0], 12.8);").equals("15.7"); + code_v2_("return max([15.7, ''][0], 12.8);").equals("15.7"); code_v1("return max(5.5, [12.8, ''][0]);").equals("12,8"); - code_v2("return max(5.5, [12.8, ''][0]);").equals("12.8"); + code_v2_("return max(5.5, [12.8, ''][0]);").equals("12.8"); // code("return 2.max([7.5, ''][0]);").equals("7.5"); // code("return [2, ''][0].max([7.5, ''][0]);").equals("7.5"); // code("2.max([7.5, ''][1])").exception(ls::vm::Exception::WRONG_ARGUMENT_TYPE); @@ -733,22 +733,22 @@ public void run() throws Exception { code("return min(8, 88)").equals("8"); code("return min(5, 12)").equals("5"); code_v1("return min(75.7, 12)").equals("12"); - code_v2("return min(75.7, 12)").almost(12.0); + code_v2_("return min(75.7, 12)").almost(12.0); code_v1("return min(5, 12.451)").equals("5"); - code_v2("return min(5, 12.451)").almost(5.0); + code_v2_("return min(5, 12.451)").almost(5.0); code("return min([5, 'a'][0], 4)").equals("4"); code("return min([5, 'a'][0], 76)").equals("5"); code("return min(4, [5, 'a'][0])").equals("4"); code("return min(77, [5, 'a'][0])").equals("5"); code("return min([55, 'a'][0], [5, 'a'][0])").equals("5"); code_v1("return min(5, 12.8)").equals("5"); - code_v2("return min(5, 12.8)").equals("5.0"); + code_v2_("return min(5, 12.8)").equals("5.0"); code_v1("return min(15.7, 12.8)").equals("12,8"); - code_v2("return min(15.7, 12.8)").equals("12.8"); + code_v2_("return min(15.7, 12.8)").equals("12.8"); code_v1("return min([15.7, ''][0], 12.8)").equals("12,8"); - code_v2("return min([15.7, ''][0], 12.8)").equals("12.8"); + code_v2_("return min([15.7, ''][0], 12.8)").equals("12.8"); code_v1("return min(5.5, [12.8, ''][0])").equals("5,5"); - code_v2("return min(5.5, [12.8, ''][0])").equals("5.5"); + code_v2_("return min(5.5, [12.8, ''][0])").equals("5.5"); // code("return min(5l, 10.5);").equals("5"); // code("return min(5l, 10);").equals("5"); // code("return min(true, 10l);").equals("1"); @@ -756,110 +756,110 @@ public void run() throws Exception { section("Number.cos()"); code_v1("return cos(0)").equals("1"); - code_v2("return cos(0)").equals("1.0"); + code_v2_("return cos(0)").equals("1.0"); code_v1("return cos(2.5)").equals("-0,801"); - code_v2("return cos(2.5)").almost(Math.cos(2.5)); + code_v2_("return cos(2.5)").almost(Math.cos(2.5)); code_v1("return cos(PI)").equals("-1"); - code_v2("return cos(PI)").equals("-1.0"); + code_v2_("return cos(PI)").equals("-1.0"); code_v1("return cos(PI / 2)").equals("0"); - code_v2("return cos(PI / 2)").almost(0.0); + code_v2_("return cos(PI / 2)").almost(0.0); // code("return π.cos()").equals("-1"); // code("return ['', π][1].cos()").equals("-1"); code_v1("return cos(['', PI][1]);").equals("-1"); - code_v2("return cos(['', PI][1]);").equals("-1.0"); + code_v2_("return cos(['', PI][1]);").equals("-1.0"); code_v1("return cos(PI);").equals("-1"); - code_v2("return cos(PI);").equals("-1.0"); + code_v2_("return cos(PI);").equals("-1.0"); section("Number.acos()"); code_v1("return acos(1)").equals("0"); - code_v2("return acos(1)").equals("0.0"); + code_v2_("return acos(1)").equals("0.0"); code_v1("return acos(-1)").equals("3,142"); - code_v2("return acos(-1)").almost(Math.PI); + code_v2_("return acos(-1)").almost(Math.PI); code_v1("return acos(0)").equals("1,571"); - code_v2("return acos(0)").almost(Math.PI / 2); + code_v2_("return acos(0)").almost(Math.PI / 2); // code("return (-0.33).acos()").almost(1.907099901948877019); code_v1("return acos(['y', 0][1])").equals("1,571"); - code_v2("return acos(['y', 0][1])").almost(Math.PI / 2); + code_v2_("return acos(['y', 0][1])").almost(Math.PI / 2); section("Number.sin()"); code_v1("return sin(0)").equals("0"); - code_v2("return sin(0)").equals("0.0"); + code_v2_("return sin(0)").equals("0.0"); code_v1("return sin(2.5)").equals("0,598"); - code_v2("return sin(2.5)").almost(Math.sin(2.5)); + code_v2_("return sin(2.5)").almost(Math.sin(2.5)); code_v1("return sin(PI)").equals("0"); - code_v2("return sin(PI)").almost(0.0); + code_v2_("return sin(PI)").almost(0.0); code_v1("return sin(PI / 2)").equals("1"); - code_v2("return sin(PI / 2)").equals("1.0"); + code_v2_("return sin(PI / 2)").equals("1.0"); code_v1("return sin(- PI / 2)").equals("-1"); - code_v2("return sin(- PI / 2)").equals("-1.0"); + code_v2_("return sin(- PI / 2)").equals("-1.0"); code_v1("return sin(['', PI / 2][1])").equals("1"); - code_v2("return sin(['', PI / 2][1])").equals("1.0"); + code_v2_("return sin(['', PI / 2][1])").equals("1.0"); code_v1("return sin(PI / 2)").equals("1"); - code_v2("return sin(PI / 2)").equals("1.0"); + code_v2_("return sin(PI / 2)").equals("1.0"); section("Number.tan()"); code_v1("return tan(0)").equals("0"); - code_v2("return tan(0)").equals("0.0"); + code_v2_("return tan(0)").equals("0.0"); code_v1("return tan(2.5)").equals("-0,747"); - code_v2("return tan(2.5)").almost(Math.tan(2.5)); + code_v2_("return tan(2.5)").almost(Math.tan(2.5)); code_v1("return tan(PI)").equals("-0"); - code_v2("return tan(PI)").almost(0.0); + code_v2_("return tan(PI)").almost(0.0); code_v1("return tan(PI / 4)").equals("1"); - code_v2("return tan(PI / 4)").almost(1.0); + code_v2_("return tan(PI / 4)").almost(1.0); code_v1("return tan(- PI / 4)").equals("-1"); - code_v2("return tan(- PI / 4)").almost(-1.0); + code_v2_("return tan(- PI / 4)").almost(-1.0); code_v1("return tan(['', PI / 4][1])").equals("1"); - code_v2("return tan(['', PI / 4][1])").almost(1.0); + code_v2_("return tan(['', PI / 4][1])").almost(1.0); section("Number.asin()"); code_v1("return asin(0)").equals("0"); - code_v2("return asin(0)").equals("0.0"); + code_v2_("return asin(0)").equals("0.0"); code_v1("return asin(-1)").equals("-1,571"); - code_v2("return asin(-1)").almost(-Math.PI / 2); + code_v2_("return asin(-1)").almost(-Math.PI / 2); code_v1("return asin(1)").equals("1,571"); - code_v2("return asin(1)").almost(Math.PI / 2); + code_v2_("return asin(1)").almost(Math.PI / 2); // code("return 0.33.asin()").almost(0.33630357515398035); code_v1("return asin(['y', -1][1])").equals("-1,571"); - code_v2("return asin(['y', -1][1])").almost(-Math.PI / 2); + code_v2_("return asin(['y', -1][1])").almost(-Math.PI / 2); section("Number.atan()"); code_v1("return atan(1)").equals("0,785"); - code_v2("return atan(1)").almost(Math.PI / 4); + code_v2_("return atan(1)").almost(Math.PI / 4); code_v1("return atan(-1)").equals("-0,785"); - code_v2("return atan(-1)").almost(-Math.PI / 4); + code_v2_("return atan(-1)").almost(-Math.PI / 4); code_v1("return atan(0.5)").equals("0,464"); - code_v2("return atan(0.5)").almost(0.463647609000806094); + code_v2_("return atan(0.5)").almost(0.463647609000806094); // code("return 0.atan()").equals("0"); code_v1("return atan(['y', 0.5][1])").equals("0,464"); - code_v2("return atan(['y', 0.5][1])").almost(0.463647609000806094); + code_v2_("return atan(['y', 0.5][1])").almost(0.463647609000806094); section("Number.atan2()"); code_v1("return atan2(1, 1)").equals("0,785"); - code_v2("return atan2(1, 1)").almost(Math.PI / 4); + code_v2_("return atan2(1, 1)").almost(Math.PI / 4); code_v1("return atan2(150.78, 150.78)").equals("0,785"); - code_v2("return atan2(150.78, 150.78)").almost(Math.PI / 4); + code_v2_("return atan2(150.78, 150.78)").almost(Math.PI / 4); code_v1("return atan2(1, 0)").equals("1,571"); - code_v2("return atan2(1, 0)").almost(Math.PI / 2); + code_v2_("return atan2(1, 0)").almost(Math.PI / 2); code_v1("return atan2(-1, 0)").equals("-1,571"); - code_v2("return atan2(-1, 0)").almost(-Math.PI / 2); + code_v2_("return atan2(-1, 0)").almost(-Math.PI / 2); code_v1("return atan2(0, 1)").equals("0"); - code_v2("return atan2(0, 1)").equals("0.0"); + code_v2_("return atan2(0, 1)").equals("0.0"); code_v1("return atan2(0, -1)").equals("3,142"); - code_v2("return atan2(0, -1)").almost(Math.PI); + code_v2_("return atan2(0, -1)").almost(Math.PI); code_v1("return atan2(12.12, 42.42)").equals("0,278"); - code_v2("return atan2(12.12, 42.42)").almost(0.278299659005111333); + code_v2_("return atan2(12.12, 42.42)").almost(0.278299659005111333); // code("return 1.atan2(1)").almost(Math.PI / 4); // code("return ['', -1][1].atan2(1)").almost(-Math.PI / 4); // code("return 1.atan2(['', -1][1])").almost(3 * Math.PI / 4); // code("return ['', -1][1].atan2(['', -1][1])").almost(-3 * Math.PI / 4); code_v1("return atan2(1, 1)").equals("0,785"); - code_v2("return atan2(1, 1)").almost(Math.PI / 4); + code_v2_("return atan2(1, 1)").almost(Math.PI / 4); code_v1("return atan2(['', -1][1], 1)").equals("-0,785"); - code_v2("return atan2(['', -1][1], 1)").almost(-Math.PI / 4); + code_v2_("return atan2(['', -1][1], 1)").almost(-Math.PI / 4); code_v1("return atan2(1, ['', -1][1])").equals("2,356"); - code_v2("return atan2(1, ['', -1][1])").almost(3 * Math.PI / 4); + code_v2_("return atan2(1, ['', -1][1])").almost(3 * Math.PI / 4); code_v1("return atan2(['', -1][1], ['', -1][1])").equals("-2,356"); - code_v2("return atan2(['', -1][1], ['', -1][1])").almost(-3 * Math.PI / 4); + code_v2_("return atan2(['', -1][1], ['', -1][1])").almost(-3 * Math.PI / 4); // code("return atan2(1, true)").almost(Math.PI / 4); // code("return atan2(true, false)").almost(Math.PI / 2); @@ -896,12 +896,12 @@ public void run() throws Exception { section("Number.hypot"); code_v1("return hypot(3, 4)").equals("5"); - code_v2("return hypot(3, 4)").equals("5.0"); + code_v2_("return hypot(3, 4)").equals("5.0"); // code("return 3.hypot(4)").equals("5"); code_v1("return hypot(34, 74)").equals("81,437"); - code_v2("return hypot(34, 74)").almost(81.437092286); + code_v2_("return hypot(34, 74)").almost(81.437092286); code_v1("return hypot([34, ''][0], 74)").equals("81,437"); - code_v2("return hypot([34, ''][0], 74)").almost(81.437092286); + code_v2_("return hypot([34, ''][0], 74)").almost(81.437092286); section("Number.signum"); // code("0.signum()").equals("0"); @@ -918,16 +918,16 @@ public void run() throws Exception { section("Number.sqrt"); code_v1("return sqrt(2)").equals("1,414"); - code_v2("return sqrt(2)").almost(Math.sqrt(2)); + code_v2_("return sqrt(2)").almost(Math.sqrt(2)); // code("return sqrt(123456789123456789123456789)").equals("11111111066111"); // code("return sqrt(55m ** 20m)").equals("253295162119140625"); // code("return sqrt(12m + 5m)").equals("4"); // code("return var n = 12; n.sqrt()").equals("3.4641016151"); // code("return let f = sqrt f(5)").equals("2.2360679775"); code_v1("return sqrt(16)").equals("4"); - code_v2("return sqrt(16)").equals("4.0"); + code_v2_("return sqrt(16)").equals("4.0"); code_v1("return sqrt(25)").equals("5"); - code_v2("return sqrt(25)").equals("5.0"); + code_v2_("return sqrt(25)").equals("5.0"); section("Number.toDegrees"); // code("return π.toDegrees()").equals("180"); @@ -935,13 +935,13 @@ public void run() throws Exception { // code("return (-π / 2).toDegrees()").equals("-90"); // code("return 0.toDegrees()").equals("0"); code_v1("return toDegrees(PI)").equals("180"); - code_v2("return toDegrees(PI)").equals("180.0"); + code_v2_("return toDegrees(PI)").equals("180.0"); code_v1("return toDegrees(PI / 2)").equals("90"); - code_v2("return toDegrees(PI / 2)").equals("90.0"); + code_v2_("return toDegrees(PI / 2)").equals("90.0"); code_v1("return toDegrees(-PI / 2)").equals("-90"); - code_v2("return toDegrees(-PI / 2)").equals("-90.0"); + code_v2_("return toDegrees(-PI / 2)").equals("-90.0"); code_v1("return toDegrees(0)").equals("0"); - code_v2("return toDegrees(0)").equals("0.0"); + code_v2_("return toDegrees(0)").equals("0.0"); section("Number.toRadians"); // code("return 180.toRadians()").almost(Math.PI); @@ -949,42 +949,42 @@ public void run() throws Exception { // code("return (-90).toRadians()").almost(-Math.PI / 2); // code("return 0.toRadians()").equals("0"); code_v1("return toRadians(180)").equals("3,142"); - code_v2("return toRadians(180)").almost(Math.PI); + code_v2_("return toRadians(180)").almost(Math.PI); code_v1("return toRadians(90)").equals("1,571"); - code_v2("return toRadians(90)").almost(Math.PI / 2); + code_v2_("return toRadians(90)").almost(Math.PI / 2); code_v1("return toRadians(-90)").equals("-1,571"); - code_v2("return toRadians(-90)").almost(-Math.PI / 2); + code_v2_("return toRadians(-90)").almost(-Math.PI / 2); code_v1("return toRadians(0)").equals("0"); - code_v2("return toRadians(0)").equals("0.0"); + code_v2_("return toRadians(0)").equals("0.0"); section("Number.log"); // code("1.log()").equals("0"); code_v1("return log(1)").equals("0"); - code_v2("return log(1)").equals("0.0"); + code_v2_("return log(1)").equals("0.0"); code_v1("return log(E)").equals("1"); - code_v2("return log(E)").equals("1.0"); + code_v2_("return log(E)").equals("1.0"); // code("123456.log()").equals("11.7236400963"); code_v1("return log(654321)").equals("13,391"); - code_v2("return log(654321)").almost(13.3913533357); + code_v2_("return log(654321)").almost(13.3913533357); code_v1("return log([55555, ''][0])").equals("10,925"); - code_v2("return log([55555, ''][0])").almost(10.9251288); + code_v2_("return log([55555, ''][0])").almost(10.9251288); section("Number.log10"); code_v1("return log10(10)").equals("1"); - code_v2("return log10(10)").equals("1.0"); + code_v2_("return log10(10)").equals("1.0"); // code("return 1.log10()").equals("0"); // code("return 123456.log10()").equals("5.0915122016"); code_v1("return log10(654321)").equals("5,816"); - code_v2("return log10(654321)").almost(5.8157908589); + code_v2_("return log10(654321)").almost(5.8157908589); code_v1("return log10([55555, ''][0])").equals("4,745"); - code_v2("return log10([55555, ''][0])").almost(4.7447231519); + code_v2_("return log10([55555, ''][0])").almost(4.7447231519); section("Number.pow"); // code("2.pow(10)").equals("1024"); code_v1("return pow(5, 3)").equals("125"); - code_v2("return pow(5, 3)").equals("125.0"); + code_v2_("return pow(5, 3)").equals("125.0"); code_v1("return pow(2, 10)").equals("1 024"); - code_v2("return pow(2, 10)").equals("1024.0"); + code_v2_("return pow(2, 10)").equals("1024.0"); // code("pow([10, ''][0], 5)").equals("100000"); // code("3000.pow(3)").equals("2147483648"); // code("return pow(3000, 3)").equals("2147483648"); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 35a861cc..f8cfeb0c 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -10,222 +10,222 @@ public void run() { // code("return Object()").equals("{}"); // code("return new Object").equals("{}"); // code("return new Object()").equals("{}"); - code_v2("return {}").equals("{}"); - code_v2("return {a: 12}").equals("{a: 12}"); - code_v2("return {a: 12, b: 5}").equals("{a: 12, b: 5}"); - code_v2("return {a: {}, b: []}").equals("{a: {}, b: []}"); - code_v2("var a = {} return a").equals("{}"); - code_v2("var a = {b: 12, c: 5} return a").equals("{b: 12, c: 5}"); + code_v2_("return {}").equals("{}"); + code_v2_("return {a: 12}").equals("{a: 12}"); + code_v2_("return {a: 12, b: 5}").equals("{a: 12, b: 5}"); + code_v2_("return {a: {}, b: []}").equals("{a: {}, b: []}"); + code_v2_("var a = {} return a").equals("{}"); + code_v2_("var a = {b: 12, c: 5} return a").equals("{b: 12, c: 5}"); section("Objects with functions"); - code_v2("var f = function(obj) { return obj.a } return f({a: 'foo'})").equals("foo"); - code_v2("var f = function(obj) { return obj.a } return [f({a: 'foo'}), f({a: 'bar'})]").equals("[foo, bar]"); + code_v2_("var f = function(obj) { return obj.a } return f({a: 'foo'})").equals("foo"); + code_v2_("var f = function(obj) { return obj.a } return [f({a: 'foo'}), f({a: 'bar'})]").equals("[foo, bar]"); //code("var f = function(obj) { return obj.a } [f(12), f({a: 'bar'})]").error(ls::Error::NO_SUCH_ATTRIBUTE, {"a", "Number"}); section("No commas"); - code_v2("return {a: 12 b: 5}").equals("{a: 12, b: 5}"); - code_v2("return {a: 12 - 2 yo: -6}").equals("{a: 10, yo: -6}"); - code_v2("return {a: 12 b: 'yo' c: true d: [1 2 3]}").equals("{a: 12, b: yo, c: true, d: [1, 2, 3]}"); + code_v2_("return {a: 12 b: 5}").equals("{a: 12, b: 5}"); + code_v2_("return {a: 12 - 2 yo: -6}").equals("{a: 10, yo: -6}"); + code_v2_("return {a: 12 b: 'yo' c: true d: [1 2 3]}").equals("{a: 12, b: yo, c: true, d: [1, 2, 3]}"); section("Classes"); - code_v2("class A { } return new A();").equals("A {}"); - code_v2("class A { a = 10 } var a = [new A()]; a[0].a++ return a[0].a").equals("11"); - code_v2("class A { a = 10 } var a = [new A()]; a[0].a-- return a[0].a").equals("9"); - code_v2("class A { a = 10 } var a = [new A()]; ++a[0].a return a[0].a").equals("11"); - code_v2("class A { a = 10 } var a = [new A()]; --a[0].a return a[0].a").equals("9"); - code_v2("class A { a = 10 m() { return 12 } } var a = new A(); return a.m()").equals("12"); - code_v2("class A { a = 10 m() { return 13 } } var a = new A(); return a['m']()").equals("13"); - code_v2("class A { a = 10 m() { return 13 } } var a = new A(); var m = 'm' return a[m]()").equals("13"); - code_v2("class A { a = 10 m() { return a } } var a = new A(); var array = [a.m] return array[0](a)").equals("10"); - code_v2("class A { a = 10 m() { return a } } var a = new A(); var array = [a['m']] return array[0](a)").equals("10"); + code_v2_("class A { } return new A();").equals("A {}"); + code_v2_("class A { a = 10 } var a = [new A()]; a[0].a++ return a[0].a").equals("11"); + code_v2_("class A { a = 10 } var a = [new A()]; a[0].a-- return a[0].a").equals("9"); + code_v2_("class A { a = 10 } var a = [new A()]; ++a[0].a return a[0].a").equals("11"); + code_v2_("class A { a = 10 } var a = [new A()]; --a[0].a return a[0].a").equals("9"); + code_v2_("class A { a = 10 m() { return 12 } } var a = new A(); return a.m()").equals("12"); + code_v2_("class A { a = 10 m() { return 13 } } var a = new A(); return a['m']()").equals("13"); + code_v2_("class A { a = 10 m() { return 13 } } var a = new A(); var m = 'm' return a[m]()").equals("13"); + code_v2_("class A { a = 10 m() { return a } } var a = new A(); var array = [a.m] return array[0](a)").equals("10"); + code_v2_("class A { a = 10 m() { return a } } var a = new A(); var array = [a['m']] return array[0](a)").equals("10"); section("Static fields"); - code_v2("class A { static x }").equals("null"); - code_v2("class A { static x } return A.x").equals("null"); - code_v2("class A { static x = 10 } return A.x").equals("10"); - code_v2("class A { static x = 'hello' } return A.x").equals("hello"); - code_v2("class A { static x = [1, 2, 3] } return A.x").equals("[1, 2, 3]"); - code_v2("class A { static x = null } return A.x").equals("null"); - code_v2("class Affiche { static COULEUR = getColor(42, 125, 78) } return Affiche.COULEUR").equals("2784590"); + code_v2_("class A { static x }").equals("null"); + code_v2_("class A { static x } return A.x").equals("null"); + code_v2_("class A { static x = 10 } return A.x").equals("10"); + code_v2_("class A { static x = 'hello' } return A.x").equals("hello"); + code_v2_("class A { static x = [1, 2, 3] } return A.x").equals("[1, 2, 3]"); + code_v2_("class A { static x = null } return A.x").equals("null"); + code_v2_("class Affiche { static COULEUR = getColor(42, 125, 78) } return Affiche.COULEUR").equals("2784590"); section("Operators on field"); - code_v2("class A { a = 10 } var a = new A(); return --a.a").equals("9"); - code_v2("class A { a = 10 } var a = new A(); a.a-- return a.a").equals("9"); - code_v2("class A { a = 10 } var a = new A(); return ++a.a").equals("11"); - code_v2("class A { a = 10 } var a = new A(); a.a++ return a.a").equals("11"); - code_v2("class A { a = 10 } var a = new A(); return a.a += 5").equals("15"); - code_v2("class A { a = 10 } var a = new A(); return a.a -= 5").equals("5"); - code_v2("class A { a = 10 } var a = new A(); return a.a *= 5").equals("50"); - code_v2("class A { a = 10 } var a = new A(); return a.a /= 5").equals("2.0"); - code_v2("class A { a = 10 } var a = new A(); return a.a %= 5").equals("0"); - code_v2("class A { a = 10 } var a = new A(); return a.a **= 5").equals("100000"); - code_v2("class A { a = 10 } var a = new A(); return a.a |= 5").equals("15"); - code_v2("class A { a = 10 } var a = new A(); return a.a &= 5").equals("0"); - code_v2("class A { a = 10 } var a = new A(); return a.a ^= 5").equals("15"); - code_v2("class A { a = 10 } var a = new A(); return a.a <<= 5").equals("320"); - code_v2("class A { a = 10 } var a = new A(); return a.a >>= 5").equals("0"); - code_v2("class A { a = 10 } var a = new A(); return a.a >>>= 5").equals("0"); + code_v2_("class A { a = 10 } var a = new A(); return --a.a").equals("9"); + code_v2_("class A { a = 10 } var a = new A(); a.a-- return a.a").equals("9"); + code_v2_("class A { a = 10 } var a = new A(); return ++a.a").equals("11"); + code_v2_("class A { a = 10 } var a = new A(); a.a++ return a.a").equals("11"); + code_v2_("class A { a = 10 } var a = new A(); return a.a += 5").equals("15"); + code_v2_("class A { a = 10 } var a = new A(); return a.a -= 5").equals("5"); + code_v2_("class A { a = 10 } var a = new A(); return a.a *= 5").equals("50"); + code_v2_("class A { a = 10 } var a = new A(); return a.a /= 5").equals("2.0"); + code_v2_("class A { a = 10 } var a = new A(); return a.a %= 5").equals("0"); + code_v2_("class A { a = 10 } var a = new A(); return a.a **= 5").equals("100000"); + code_v2_("class A { a = 10 } var a = new A(); return a.a |= 5").equals("15"); + code_v2_("class A { a = 10 } var a = new A(); return a.a &= 5").equals("0"); + code_v2_("class A { a = 10 } var a = new A(); return a.a ^= 5").equals("15"); + code_v2_("class A { a = 10 } var a = new A(); return a.a <<= 5").equals("320"); + code_v2_("class A { a = 10 } var a = new A(); return a.a >>= 5").equals("0"); + code_v2_("class A { a = 10 } var a = new A(); return a.a >>>= 5").equals("0"); section("Operators on field in method"); - code_v2("class A { a = 10 m() { return --a } } return new A().m()").equals("9"); - code_v2("class A { a = 10 m() { a-- return a } } return new A().m()").equals("9"); - code_v2("class A { a = 10 m() { return ++a } } return new A().m()").equals("11"); - code_v2("class A { a = 10 m() { a++ return a } } return new A().m()").equals("11"); - code_v2("class A { a = 10 m() { return a += 5 } } return new A().m()").equals("15"); - code_v2("class A { a = 10 m() { return a -= 5 } } return new A().m()").equals("5"); - code_v2("class A { a = 10 m() { return a *= 5 } } return new A().m()").equals("50"); - code_v2("class A { a = 10 m() { return a /= 5 } } return new A().m()").equals("2.0"); - code_v2("class A { a = 10 m() { return a %= 5 } } return new A().m()").equals("0"); - code_v2("class A { a = 10 m() { return a **= 5 } } return new A().m()").equals("100000"); - code_v2("class A { a = 10 m() { return a |= 5 } } return new A().m()").equals("15"); - code_v2("class A { a = 10 m() { return a &= 5 } } return new A().m()").equals("0"); - code_v2("class A { a = 10 m() { return a ^= 5 } } return new A().m()").equals("15"); - code_v2("class A { a = 10 m() { return a <<= 5 } } return new A().m()").equals("320"); - code_v2("class A { a = 10 m() { return a >>= 5 } } return new A().m()").equals("0"); - code_v2("class A { a = 10 m() { return a >>>= 5 } } return new A().m()").equals("0"); + code_v2_("class A { a = 10 m() { return --a } } return new A().m()").equals("9"); + code_v2_("class A { a = 10 m() { a-- return a } } return new A().m()").equals("9"); + code_v2_("class A { a = 10 m() { return ++a } } return new A().m()").equals("11"); + code_v2_("class A { a = 10 m() { a++ return a } } return new A().m()").equals("11"); + code_v2_("class A { a = 10 m() { return a += 5 } } return new A().m()").equals("15"); + code_v2_("class A { a = 10 m() { return a -= 5 } } return new A().m()").equals("5"); + code_v2_("class A { a = 10 m() { return a *= 5 } } return new A().m()").equals("50"); + code_v2_("class A { a = 10 m() { return a /= 5 } } return new A().m()").equals("2.0"); + code_v2_("class A { a = 10 m() { return a %= 5 } } return new A().m()").equals("0"); + code_v2_("class A { a = 10 m() { return a **= 5 } } return new A().m()").equals("100000"); + code_v2_("class A { a = 10 m() { return a |= 5 } } return new A().m()").equals("15"); + code_v2_("class A { a = 10 m() { return a &= 5 } } return new A().m()").equals("0"); + code_v2_("class A { a = 10 m() { return a ^= 5 } } return new A().m()").equals("15"); + code_v2_("class A { a = 10 m() { return a <<= 5 } } return new A().m()").equals("320"); + code_v2_("class A { a = 10 m() { return a >>= 5 } } return new A().m()").equals("0"); + code_v2_("class A { a = 10 m() { return a >>>= 5 } } return new A().m()").equals("0"); section("Operators on static field"); - code_v2("class A { static a = 10 } return --A.a").equals("9"); - code_v2("class A { static a = 10 } A.a-- return A.a").equals("9"); - code_v2("class A { static a = 10 } return ++A.a").equals("11"); - code_v2("class A { static a = 10 } A.a++ return A.a").equals("11"); - code_v2("class A { static a = 10 } return A.a += 5").equals("15"); - code_v2("class A { static a = 10 } return A.a -= 5").equals("5"); - code_v2("class A { static a = 10 } return A.a *= 5").equals("50"); - code_v2("class A { static a = 10 } return A.a /= 5").equals("2.0"); - code_v2("class A { static a = 10 } return A.a %= 5").equals("0"); - code_v2("class A { static a = 10 } return A.a **= 5").equals("100000"); - code_v2("class A { static a = 10 } return A.a |= 5").equals("15"); - code_v2("class A { static a = 10 } return A.a &= 5").equals("0"); - code_v2("class A { static a = 10 } return A.a ^= 5").equals("15"); - code_v2("class A { static a = 10 } return A.a <<= 5").equals("320"); - code_v2("class A { static a = 10 } return A.a >>= 5").equals("0"); - code_v2("class A { static a = 10 } return A.a >>>= 5").equals("0"); + code_v2_("class A { static a = 10 } return --A.a").equals("9"); + code_v2_("class A { static a = 10 } A.a-- return A.a").equals("9"); + code_v2_("class A { static a = 10 } return ++A.a").equals("11"); + code_v2_("class A { static a = 10 } A.a++ return A.a").equals("11"); + code_v2_("class A { static a = 10 } return A.a += 5").equals("15"); + code_v2_("class A { static a = 10 } return A.a -= 5").equals("5"); + code_v2_("class A { static a = 10 } return A.a *= 5").equals("50"); + code_v2_("class A { static a = 10 } return A.a /= 5").equals("2.0"); + code_v2_("class A { static a = 10 } return A.a %= 5").equals("0"); + code_v2_("class A { static a = 10 } return A.a **= 5").equals("100000"); + code_v2_("class A { static a = 10 } return A.a |= 5").equals("15"); + code_v2_("class A { static a = 10 } return A.a &= 5").equals("0"); + code_v2_("class A { static a = 10 } return A.a ^= 5").equals("15"); + code_v2_("class A { static a = 10 } return A.a <<= 5").equals("320"); + code_v2_("class A { static a = 10 } return A.a >>= 5").equals("0"); + code_v2_("class A { static a = 10 } return A.a >>>= 5").equals("0"); section("Operators on static field in method"); - code_v2("class A { static a = 10 static m() { return --a } } return A.m()").equals("9"); - code_v2("class A { static a = 10 static m() { a-- return a } } return A.m()").equals("9"); - code_v2("class A { static a = 10 static m() { return ++a } } return A.m()").equals("11"); - code_v2("class A { static a = 10 static m() { a++ return a } } return A.m()").equals("11"); - code_v2("class A { static a = 10 static m() { return a += 5 } } return A.m()").equals("15"); - code_v2("class A { static a = 10 static m() { return a -= 5 } } return A.m()").equals("5"); - code_v2("class A { static a = 10 static m() { return a *= 5 } } return A.m()").equals("50"); - code_v2("class A { static a = 10 static m() { return a /= 5 } } return A.m()").equals("2.0"); - code_v2("class A { static a = 10 static m() { return a %= 5 } } return A.m()").equals("0"); - code_v2("class A { static a = 10 static m() { return a **= 5 } } return A.m()").equals("100000"); - code_v2("class A { static a = 10 static m() { return a |= 5 } } return A.m()").equals("15"); - code_v2("class A { static a = 10 static m() { return a &= 5 } } return A.m()").equals("0"); - code_v2("class A { static a = 10 static m() { return a ^= 5 } } return A.m()").equals("15"); - code_v2("class A { static a = 10 static m() { return a <<= 5 } } return A.m()").equals("320"); - code_v2("class A { static a = 10 static m() { return a >>= 5 } } return A.m()").equals("0"); - code_v2("class A { static a = 10 static m() { return a >>>= 5 } } return A.m()").equals("0"); + code_v2_("class A { static a = 10 static m() { return --a } } return A.m()").equals("9"); + code_v2_("class A { static a = 10 static m() { a-- return a } } return A.m()").equals("9"); + code_v2_("class A { static a = 10 static m() { return ++a } } return A.m()").equals("11"); + code_v2_("class A { static a = 10 static m() { a++ return a } } return A.m()").equals("11"); + code_v2_("class A { static a = 10 static m() { return a += 5 } } return A.m()").equals("15"); + code_v2_("class A { static a = 10 static m() { return a -= 5 } } return A.m()").equals("5"); + code_v2_("class A { static a = 10 static m() { return a *= 5 } } return A.m()").equals("50"); + code_v2_("class A { static a = 10 static m() { return a /= 5 } } return A.m()").equals("2.0"); + code_v2_("class A { static a = 10 static m() { return a %= 5 } } return A.m()").equals("0"); + code_v2_("class A { static a = 10 static m() { return a **= 5 } } return A.m()").equals("100000"); + code_v2_("class A { static a = 10 static m() { return a |= 5 } } return A.m()").equals("15"); + code_v2_("class A { static a = 10 static m() { return a &= 5 } } return A.m()").equals("0"); + code_v2_("class A { static a = 10 static m() { return a ^= 5 } } return A.m()").equals("15"); + code_v2_("class A { static a = 10 static m() { return a <<= 5 } } return A.m()").equals("320"); + code_v2_("class A { static a = 10 static m() { return a >>= 5 } } return A.m()").equals("0"); + code_v2_("class A { static a = 10 static m() { return a >>>= 5 } } return A.m()").equals("0"); section("Inheritance"); - code_v2("class A { x = 10 } class B extends A {} var a = new B() return a.x").equals("10"); - code_v2("class A { m() { return 'ok' } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("ok"); - code_v2("class A { x = 10 } class B extends A {} class C extends B {} var a = new C() return a.x").equals("10"); - code_v2("class A { m() { return 'ok' } } class B extends A {} class C extends B {} var a = new C() return a.m()").equals("ok"); - code_v2("class A { m() { return 'ok' } } class B extends A { m() { return super.m() }} class C extends B { m() { return super.m() } } var a = new C() return a.m()").equals("ok"); - code_v2("class A { m() { return 'ok' } } class B extends A {} class C extends B { m() { return super.m() } } var a = new C() return a.m()").equals("ok"); - code_v2("class A { m() { return 'okA' } } class B extends A { m() { return super.m() + 'B' }} class C extends B { m() { return super.m() + 'C' } } var a = new C()return a.m()").equals("okABC"); - code_v2("class A { items } class B extends A { constructor() { this.items = [] } } var x = new B() return x").equals("B {items: []}"); - code_v2("class A { items } class B extends A { constructor() { this.items = [] super() } } var x = new B() return x").equals("B {items: []}"); - code_v2("class A { m() { return 'parent' } t() { return this.m() } } class B extends A { m() { return 'enfant' } } return new B().t()").equals("enfant"); - code_v2("class A { m() { return 'parent' } t() { return m() } } class B extends A { m() { return 'enfant' } } return new B().t()").equals("enfant"); - code_v2("class A { public id; } class W extends A {} class H extends W { constructor(id){ this.id=id } }").equals("null"); + code_v2_("class A { x = 10 } class B extends A {} var a = new B() return a.x").equals("10"); + code_v2_("class A { m() { return 'ok' } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("ok"); + code_v2_("class A { x = 10 } class B extends A {} class C extends B {} var a = new C() return a.x").equals("10"); + code_v2_("class A { m() { return 'ok' } } class B extends A {} class C extends B {} var a = new C() return a.m()").equals("ok"); + code_v2_("class A { m() { return 'ok' } } class B extends A { m() { return super.m() }} class C extends B { m() { return super.m() } } var a = new C() return a.m()").equals("ok"); + code_v2_("class A { m() { return 'ok' } } class B extends A {} class C extends B { m() { return super.m() } } var a = new C() return a.m()").equals("ok"); + code_v2_("class A { m() { return 'okA' } } class B extends A { m() { return super.m() + 'B' }} class C extends B { m() { return super.m() + 'C' } } var a = new C()return a.m()").equals("okABC"); + code_v2_("class A { items } class B extends A { constructor() { this.items = [] } } var x = new B() return x").equals("B {items: []}"); + code_v2_("class A { items } class B extends A { constructor() { this.items = [] super() } } var x = new B() return x").equals("B {items: []}"); + code_v2_("class A { m() { return 'parent' } t() { return this.m() } } class B extends A { m() { return 'enfant' } } return new B().t()").equals("enfant"); + code_v2_("class A { m() { return 'parent' } t() { return m() } } class B extends A { m() { return 'enfant' } } return new B().t()").equals("enfant"); + code_v2_("class A { public id; } class W extends A {} class H extends W { constructor(id){ this.id=id } }").equals("null"); section("Access levels: fields"); - code_v2("class A { x = 10 } var a = new A() return a.x").equals("10"); - code_v2("class A { public x = 10 } var a = new A() return a.x").equals("10"); - code_v2("class A { protected x = 10 } var a = new A() return a.x").equals("null"); - code_v2("class A { private x = 10 } var a = new A() return a.x").equals("null"); - code_v2("class A { private x = 10 m() { return x } } var a = new A() return a.m()").equals("10"); - code_v2("class A { private x = 10 } class B extends A {} var a = new B() return a.x").equals("null"); - code_v2("class A { protected x = 10 } class B extends A {} var a = new B() return a.x").equals("null"); - code_v2("class A { protected x = 10 } class B extends A { m() { return x } } var a = new B() return a.m()").equals("10"); - code_v2("class A { private x = 10 constructor() { x = 15 } } var a = new A() return a").equals("A {x: 15}"); - code_v2("class A { private x; constructor() { this.x = []; } } return new A()").equals("A {x: []}"); - code_v2("class Parent { private chaine = 'Nawak'; public get_chaine_parent() { return this.chaine; } } class Enfant extends Parent { public get_chaine_enfant() { return this.get_chaine_parent() } } var e = Enfant() return [e.get_chaine_parent(), e.get_chaine_enfant() ]").equals("[Nawak, Nawak]"); - code_v2("class Parent { protected chaine = 'Nawak'; public get_chaine_parent() { return this.chaine; } } class Enfant extends Parent { public get_chaine_enfant() { return this.get_chaine_parent() } } var e = Enfant() return [e.get_chaine_parent(), e.get_chaine_enfant() ]").equals("[Nawak, Nawak]"); - code_v2("class A { private x; constructor() { this.x = [] push(this.x, 10); } } return new A()").equals("A {x: [10]}"); - - code_v2("class A { private x = 10 m() { return x } } var a = new A() return a.m()").equals("10"); + code_v2_("class A { x = 10 } var a = new A() return a.x").equals("10"); + code_v2_("class A { public x = 10 } var a = new A() return a.x").equals("10"); + code_v2_("class A { protected x = 10 } var a = new A() return a.x").equals("null"); + code_v2_("class A { private x = 10 } var a = new A() return a.x").equals("null"); + code_v2_("class A { private x = 10 m() { return x } } var a = new A() return a.m()").equals("10"); + code_v2_("class A { private x = 10 } class B extends A {} var a = new B() return a.x").equals("null"); + code_v2_("class A { protected x = 10 } class B extends A {} var a = new B() return a.x").equals("null"); + code_v2_("class A { protected x = 10 } class B extends A { m() { return x } } var a = new B() return a.m()").equals("10"); + code_v2_("class A { private x = 10 constructor() { x = 15 } } var a = new A() return a").equals("A {x: 15}"); + code_v2_("class A { private x; constructor() { this.x = []; } } return new A()").equals("A {x: []}"); + code_v2_("class Parent { private chaine = 'Nawak'; public get_chaine_parent() { return this.chaine; } } class Enfant extends Parent { public get_chaine_enfant() { return this.get_chaine_parent() } } var e = Enfant() return [e.get_chaine_parent(), e.get_chaine_enfant() ]").equals("[Nawak, Nawak]"); + code_v2_("class Parent { protected chaine = 'Nawak'; public get_chaine_parent() { return this.chaine; } } class Enfant extends Parent { public get_chaine_enfant() { return this.get_chaine_parent() } } var e = Enfant() return [e.get_chaine_parent(), e.get_chaine_enfant() ]").equals("[Nawak, Nawak]"); + code_v2_("class A { private x; constructor() { this.x = [] push(this.x, 10); } } return new A()").equals("A {x: [10]}"); + + code_v2_("class A { private x = 10 m() { return x } } var a = new A() return a.m()").equals("10"); section("Access levels: static fields"); - code_v2("class A { static x = 10 } return A.x").equals("10"); - code_v2("class A { public static x = 10 } return A.x").equals("10"); - code_v2("class A { protected static x = 10 } return A.x").equals("null"); - code_v2("class A { private static x = 10 } return A.x").equals("null"); - code_v2("class A { private static x = 10 static m() { return x } } return A.m()").equals("10"); - code_v2("class A { private static x = 10 } class B extends A {} return B.x").equals("null"); - code_v2("class A { protected static x = 10 } class B extends A {} return B.x").equals("null"); - code_v2("class A { protected static x = 10 } class B extends A { static m() { return x } } return B.m()").equals("10"); - code_v2("class A { private static x = 10 static m() { return A.x } } return A.m()").equals("10"); + code_v2_("class A { static x = 10 } return A.x").equals("10"); + code_v2_("class A { public static x = 10 } return A.x").equals("10"); + code_v2_("class A { protected static x = 10 } return A.x").equals("null"); + code_v2_("class A { private static x = 10 } return A.x").equals("null"); + code_v2_("class A { private static x = 10 static m() { return x } } return A.m()").equals("10"); + code_v2_("class A { private static x = 10 } class B extends A {} return B.x").equals("null"); + code_v2_("class A { protected static x = 10 } class B extends A {} return B.x").equals("null"); + code_v2_("class A { protected static x = 10 } class B extends A { static m() { return x } } return B.m()").equals("10"); + code_v2_("class A { private static x = 10 static m() { return A.x } } return A.m()").equals("10"); section("Access levels: methods"); - code_v2("class A { m() { return 10 } } var a = new A() return a.m()").equals("10"); - code_v2("class A { public m() { return 10 } } var a = new A() return a.m()").equals("10"); - code_v2("class A { protected m() { return 10 } } var a = new A() return a.m()").equals("null"); - code_v2("class A { private m() { return 10 } } var a = new A() return a.m()").equals("null"); - code_v2("class A { public m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("10"); - code_v2("class A { protected m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("null"); - code_v2("class A { private m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("null"); - code_v2("class A { protected m() { return 10 } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("10"); + code_v2_("class A { m() { return 10 } } var a = new A() return a.m()").equals("10"); + code_v2_("class A { public m() { return 10 } } var a = new A() return a.m()").equals("10"); + code_v2_("class A { protected m() { return 10 } } var a = new A() return a.m()").equals("null"); + code_v2_("class A { private m() { return 10 } } var a = new A() return a.m()").equals("null"); + code_v2_("class A { public m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("10"); + code_v2_("class A { protected m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("null"); + code_v2_("class A { private m() { return 10 } } class B extends A {} var a = new B() return a.m()").equals("null"); + code_v2_("class A { protected m() { return 10 } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("10"); section("Access levels: constructors"); - code_v2("class A { constructor() { } } return new A()").equals("A {}"); - code_v2("class A { public constructor() { } } return new A()").equals("A {}"); - code_v2("class A { protected constructor() { } } return new A()").error(Error.PROTECTED_CONSTRUCTOR); - code_v2("class A { private constructor() { } } return new A()").error(Error.PRIVATE_CONSTRUCTOR); - code_v2("class A { public constructor() { } } class B extends A {} return new B()").equals("B {}"); - code_v2("class A { x protected constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").equals("10"); - code_v2("class A { x private constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").error(Error.PRIVATE_CONSTRUCTOR); - code_v2("class A { private constructor() { } } class B extends A {} return new B()").equals("B {}"); - code_v2("class A { private constructor() {} static getInstance() { return new A() } } return A.getInstance()").equals("A {}"); + code_v2_("class A { constructor() { } } return new A()").equals("A {}"); + code_v2_("class A { public constructor() { } } return new A()").equals("A {}"); + code_v2_("class A { protected constructor() { } } return new A()").error(Error.PROTECTED_CONSTRUCTOR); + code_v2_("class A { private constructor() { } } return new A()").error(Error.PRIVATE_CONSTRUCTOR); + code_v2_("class A { public constructor() { } } class B extends A {} return new B()").equals("B {}"); + code_v2_("class A { x protected constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").equals("10"); + code_v2_("class A { x private constructor() { x = 10 } } class B extends A { constructor() { super() } } return new B().x").error(Error.PRIVATE_CONSTRUCTOR); + code_v2_("class A { private constructor() { } } class B extends A {} return new B()").equals("B {}"); + code_v2_("class A { private constructor() {} static getInstance() { return new A() } } return A.getInstance()").equals("A {}"); section("Access levels: static methods"); - code_v2("class A { static m() { return 10 } } return A.m()").equals("10"); - code_v2("class A { public static m() { return 10 } } return A.m()").equals("10"); - code_v2("class A { protected static m() { return 10 } } return A.m()").error(Error.PROTECTED_STATIC_METHOD); - code_v2("class A { private static m() { return 10 } } return A.m()").error(Error.PRIVATE_STATIC_METHOD); - code_v2("class A { public static m() { return 10 } } class B extends A {} return B.m()").equals("10"); - code_v2("class A { protected static m() { return 10 } } class B extends A {} return B.m()").error(Error.PROTECTED_STATIC_METHOD); - code_v2("class A { private static m() { return 10 } } class B extends A {} return B.m()").error(Error.PRIVATE_STATIC_METHOD); + code_v2_("class A { static m() { return 10 } } return A.m()").equals("10"); + code_v2_("class A { public static m() { return 10 } } return A.m()").equals("10"); + code_v2_("class A { protected static m() { return 10 } } return A.m()").error(Error.PROTECTED_STATIC_METHOD); + code_v2_("class A { private static m() { return 10 } } return A.m()").error(Error.PRIVATE_STATIC_METHOD); + code_v2_("class A { public static m() { return 10 } } class B extends A {} return B.m()").equals("10"); + code_v2_("class A { protected static m() { return 10 } } class B extends A {} return B.m()").error(Error.PROTECTED_STATIC_METHOD); + code_v2_("class A { private static m() { return 10 } } class B extends A {} return B.m()").error(Error.PRIVATE_STATIC_METHOD); section("Initialization of fields"); - code_v2("class A { x = [1, 2, 3] } var a = new A() return a.x").equals("[1, 2, 3]"); - code_v2("class A { x = [1, 2, 3] } var a = new A() push(a.x, 4) var b = new A() return b.x").equals("[1, 2, 3]"); - code_v2("class B { y = 10 } class A { x = new B() } var a = new A() return a.x").equals("B {y: 10}"); - code_v2("class B { y = 10 } class A { x = new B() } var a = new A() return a.x.y").equals("10"); - code_v2("class B { y = 10 } class A { static x = new B() } return A.x").equals("B {y: 10}"); + code_v2_("class A { x = [1, 2, 3] } var a = new A() return a.x").equals("[1, 2, 3]"); + code_v2_("class A { x = [1, 2, 3] } var a = new A() push(a.x, 4) var b = new A() return b.x").equals("[1, 2, 3]"); + code_v2_("class B { y = 10 } class A { x = new B() } var a = new A() return a.x").equals("B {y: 10}"); + code_v2_("class B { y = 10 } class A { x = new B() } var a = new A() return a.x.y").equals("10"); + code_v2_("class B { y = 10 } class A { static x = new B() } return A.x").equals("B {y: 10}"); section("Initialization of static fields"); - code_v2("class A { public static x = arrayMap([1, 3, 5], function(y) { return y ** 3 }) } return A.x").equals("[1, 27, 125]"); - code_v2("class A { static x = arrayMap([1, 3, 5], function(y) { return y ** 3 }) } return A.x").equals("[1, 27, 125]"); - code_v2("class Map { public static obstacles = toUpper('hello') } return Map.obstacles").equals("HELLO"); + code_v2_("class A { public static x = arrayMap([1, 3, 5], function(y) { return y ** 3 }) } return A.x").equals("[1, 27, 125]"); + code_v2_("class A { static x = arrayMap([1, 3, 5], function(y) { return y ** 3 }) } return A.x").equals("[1, 27, 125]"); + code_v2_("class Map { public static obstacles = toUpper('hello') } return Map.obstacles").equals("HELLO"); section("Method is a system method"); - code_v2("class A { sqrt() { return sqrt(25) } }").equals("null"); - DISABLED_code_v2("class A { sqrt() { return sqrt(25) } } return new A().sqrt()").equals("5"); + code_v2_("class A { sqrt() { return sqrt(25) } }").equals("null"); + DISABLED_code_v2_("class A { sqrt() { return sqrt(25) } } return new A().sqrt()").equals("5"); section("Return of field"); - code_v2("class R { f = [] m(k, r) { return this.f[k] = r } } var x = new R() return x.m(1, 2)").equals("2"); - code_v2("class R { private f = [] m(k, r) { return this.f[k] = r } } var x = new R() return x.m(1, 'hello')").equals("hello"); + code_v2_("class R { f = [] m(k, r) { return this.f[k] = r } } var x = new R() return x.m(1, 2)").equals("2"); + code_v2_("class R { private f = [] m(k, r) { return this.f[k] = r } } var x = new R() return x.m(1, 'hello')").equals("hello"); section("Constant in static field"); - code_v2("class A { static bulbsNameChip = ['puny_bulb': PI] } return A.bulbsNameChip").equals("[puny_bulb : 3.141592653589793]"); + code_v2_("class A { static bulbsNameChip = ['puny_bulb': PI] } return A.bulbsNameChip").equals("[puny_bulb : 3.141592653589793]"); section("Object.string()"); - code_v2("return string({x: 1, y: 2, z: 3})").equals("{x: 1, y: 2, z: 3}"); - code_v2("return string({z: 1, y: 2, x: 3})").equals("{z: 1, y: 2, x: 3}"); - code_v2("class A { z = 1 y = 2 x = 3 } return string(new A())").equals("A {z: 1, y: 2, x: 3}"); - code_v2("class A { x = 1 y = 2 z = 3 } return string(new A())").equals("A {x: 1, y: 2, z: 3}"); + code_v2_("return string({x: 1, y: 2, z: 3})").equals("{x: 1, y: 2, z: 3}"); + code_v2_("return string({z: 1, y: 2, x: 3})").equals("{z: 1, y: 2, x: 3}"); + code_v2_("class A { z = 1 y = 2 x = 3 } return string(new A())").equals("A {z: 1, y: 2, x: 3}"); + code_v2_("class A { x = 1 y = 2 z = 3 } return string(new A())").equals("A {x: 1, y: 2, z: 3}"); /* * Operators */ section("Object.operator !"); - code_v2("return !{}").equals("true"); - code_v2("return !{a: 32}").equals("false"); + code_v2_("return !{}").equals("true"); + code_v2_("return !{a: 32}").equals("false"); section("Object.operator | |"); // code_v11("var a = {a: 32, b: 'toto', c: false}; return |a|").equals("3"); @@ -235,32 +235,32 @@ public void run() { // code_v11("return 12 in {x: 5, y: 'yo'}").equals("false"); section("Object.operator . ()"); - code_v2("return { v: 12 }.v").equals("12"); - code_v2("var a = {b: 12, c: 5} return a.b").equals("12"); - code_v2("var a = {v: 5} return a.v = 12").equals("12"); - code_v2("var a = {v: 5} a.v = 12 return a").equals("{v: 12}"); - code_v2("var a = {v: 5} return a.v = 'salut'").equals("salut"); - code_v2("var a = {v: 5} a.v = 'salut' return a").equals("{v: salut}"); - code_v2("var a = {b: 12} return a.b += 10").equals("22"); - code_v2("var a = {b: 12} return a.b -= 10").equals("2"); - code_v2("var a = {b: 12} return a.b *= 10").equals("120"); - code_v2("var a = {b: 12} return a.b /= 10").almost(1.2); - code_v2("var a = {b: 12} return a.b %= 10").equals("2"); - code_v2("var o = {} o.new_val = 12 return o").equals("{new_val: 12}"); - code_v2("var o = {a: 'a'} o.b = 'b' return o").equals("{a: a, b: b}"); + code_v2_("return { v: 12 }.v").equals("12"); + code_v2_("var a = {b: 12, c: 5} return a.b").equals("12"); + code_v2_("var a = {v: 5} return a.v = 12").equals("12"); + code_v2_("var a = {v: 5} a.v = 12 return a").equals("{v: 12}"); + code_v2_("var a = {v: 5} return a.v = 'salut'").equals("salut"); + code_v2_("var a = {v: 5} a.v = 'salut' return a").equals("{v: salut}"); + code_v2_("var a = {b: 12} return a.b += 10").equals("22"); + code_v2_("var a = {b: 12} return a.b -= 10").equals("2"); + code_v2_("var a = {b: 12} return a.b *= 10").equals("120"); + code_v2_("var a = {b: 12} return a.b /= 10").almost(1.2); + code_v2_("var a = {b: 12} return a.b %= 10").equals("2"); + code_v2_("var o = {} o.new_val = 12 return o").equals("{new_val: 12}"); + code_v2_("var o = {a: 'a'} o.b = 'b' return o").equals("{a: a, b: b}"); // DISABLED_code("Object.readonly.v = 5").exception(ls::vm::Exception::CANT_MODIFY_READONLY_OBJECT); // code_v11("var o = [{}, ''][0] return o.values").equals(""); - code_v2("var pq = [{p: 22, v: 55}] return pq[0].p").equals("22"); - code_v2("var pq = [{p: 22, v: 55}] var o = pq[0] return o.v").equals("55"); + code_v2_("var pq = [{p: 22, v: 55}] return pq[0].p").equals("22"); + code_v2_("var pq = [{p: 22, v: 55}] var o = pq[0] return o.v").equals("55"); section("Object.operator =="); - code_v2("class A {} return {} == new A").equals("false"); - code_v2("class A { }; class B { }; return new A() == new B();").equals("false"); - code_v2("class A {} return new A == new A").equals("true"); - code_v2("return {a: 2} == {}").equals("false"); - code_v2("return {a: 2} == {a: 1}").equals("false"); - code_v2("return {a: 2} == {b: 2}").equals("false"); - code_v2("return {a: 2} == {a: 2}").equals("false"); + code_v2_("class A {} return {} == new A").equals("false"); + code_v2_("class A { }; class B { }; return new A() == new B();").equals("false"); + code_v2_("class A {} return new A == new A").equals("true"); + code_v2_("return {a: 2} == {}").equals("false"); + code_v2_("return {a: 2} == {a: 1}").equals("false"); + code_v2_("return {a: 2} == {b: 2}").equals("false"); + code_v2_("return {a: 2} == {a: 2}").equals("false"); section("Object.operator <"); // code("return {} < {}").equals("false"); @@ -299,11 +299,11 @@ public void run() { // code("return {a: 5, b: 'toto', c: true, d: -> 5}.values()").equals("[5, 'toto', true, ]"); section("Object.isTrue()"); - code_v2("if ({x: 12}) { return 5 } else { return 12 }").equals("5"); - code_v2("if ({}) { return 5 } else { return 12 }").equals("12"); + code_v2_("if ({x: 12}) { return 5 } else { return 12 }").equals("5"); + code_v2_("if ({}) { return 5 } else { return 12 }").equals("12"); section("Object.clone()"); - code_v2("var a = {v: 12} return [a]").equals("[{v: 12}]"); + code_v2_("var a = {v: 12} return [a]").equals("[{v: 12}]"); section("Object.map()"); // code("return {}.map(x -> x + 1)").equals("{}"); diff --git a/src/test/java/test/TestOperators.java b/src/test/java/test/TestOperators.java index f98852ae..9851229f 100644 --- a/src/test/java/test/TestOperators.java +++ b/src/test/java/test/TestOperators.java @@ -141,9 +141,9 @@ public void run() throws Exception { code("return null == [null]").equals("false"); code("return null != [null]").equals("true"); code_v1("return [null] == null").equals("true"); // Bug in LS1.0 - code_v2("return [null] == null").equals("false"); // Fixed in 1.1 + code_v2_("return [null] == null").equals("false"); // Fixed in 1.1 code_v1("return [null] != null").equals("false"); // Bug in LS1.0 - code_v2("return [null] != null").equals("true"); // Fixed in 1.1 + code_v2_("return [null] != null").equals("true"); // Fixed in 1.1 code("var a = 1; var result = -10 + (1- (a-1)); return result").equals("-9"); code("var a = 1; var result = 0; result = -10 + (1- (a-1)); return result").equals("-9"); From 73c6a1e4f1775f0714d33d0d98e3c7d3debfde1e Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 29 Nov 2021 21:01:15 +0100 Subject: [PATCH 301/319] [object] Add keys() and values() --- .../runner/values/ObjectLeekValue.java | 16 ++++++++++++++++ src/test/java/test/TestObject.java | 19 +++++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index ef59c3e2..3bf3b99e 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -239,6 +239,22 @@ public Box getOrCreate(AI ai, Object value) throws LeekRunException { } public Object callMethod(String method, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { + if (clazz.ai.getVersion() >= 3 && method.equals("keys_0")) { + String[] values = new String[fields.size()]; + int i = 0; + for (var key : fields.keySet()) { + values[i++] = key; + } + return new ArrayLeekValue(clazz.ai, values); + } + if (clazz.ai.getVersion() >= 3 && method.equals("values_0")) { + Object[] values = new Object[fields.size()]; + int i = 0; + for (var value : fields.values()) { + values[i++] = value; + } + return new ArrayLeekValue(clazz.ai, values); + } var result = clazz.getMethod(clazz.ai, method, fromClass); if (result == null) { int underscore = method.lastIndexOf("_"); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index f8cfeb0c..ae13a4cc 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -287,16 +287,19 @@ public void run() { * Methods */ section("Object.keys()"); - // code("return {}.keys()").equals("[]"); - // code("return {a: 5, b: 'toto', c: true, d: -> 5}.keys()").equals("['a', 'b', 'c', 'd']"); - // code("return 'x' in {x: 5, y: 'yo'}.keys()").equals("true"); - // code("return 'x' in {a: 5, y: 'yo'}.keys()").equals("false"); + code_v3_("return {}.keys()").equals("[]"); + code_v3_("return {a: 5, b: 'toto', c: true, d: function() { return 5 } }.keys()").equals("[a, b, c, d]"); + code_v3_("class A { x y z } return new A().keys()").equals("[x, y, z]"); + code_v3_("class A { z y x } return new A().keys()").equals("[z, y, x]"); + // code_v2_("return 'x' in {x: 5, y: 'yo'}.keys()").equals("true"); + // code_v2_("return 'x' in {a: 5, y: 'yo'}.keys()").equals("false"); section("Object.values()"); - // code("return {}.values()").equals("[]"); - // code("return {a: 1}.values()").equals("[1]"); - // code("return {a: 1, b: 1}.values()").equals("[1, 1]"); - // code("return {a: 5, b: 'toto', c: true, d: -> 5}.values()").equals("[5, 'toto', true, ]"); + code_v3_("return {}.values()").equals("[]"); + code_v3_("return {a: 1}.values()").equals("[1]"); + code_v3_("return {a: 1, b: 1}.values()").equals("[1, 1]"); + code_v3_("return {a: 5, b: 'toto', c: true, d: function() { return 5 } }.values()").equals("[5, toto, true, #Anonymous Function]"); + code_v3_("return {c: 5, a: 'toto', d: true, b: function() { return 5 } }.values()").equals("[5, toto, true, #Anonymous Function]"); section("Object.isTrue()"); code_v2_("if ({x: 12}) { return 5 } else { return 12 }").equals("5"); From ccbba29304511bf6cb8cf468930b112ce485bca6 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 29 Nov 2021 21:01:15 +0100 Subject: [PATCH 302/319] [poo] Base classes, reflexion, property order etc. --- src/main/java/leekscript/common/Error.java | 1 + .../leekscript/compiler/WordCompiler.java | 13 +++- .../compiler/bloc/MainLeekBlock.java | 13 ++++ .../compiler/expression/LeekObjectAccess.java | 35 ++++++--- .../ClassDeclarationInstruction.java | 12 +++- src/main/java/leekscript/runner/AI.java | 40 ++++++++++- .../leekscript/runner/LeekValueManager.java | 4 ++ .../runner/values/ClassLeekValue.java | 40 ++++++++--- .../runner/values/ObjectLeekValue.java | 30 ++++---- src/test/java/test/TestCommon.java | 7 +- src/test/java/test/TestObject.java | 72 +++++++++++++++++++ 11 files changed, 225 insertions(+), 42 deletions(-) diff --git a/src/main/java/leekscript/common/Error.java b/src/main/java/leekscript/common/Error.java index 128008e2..56914cf6 100644 --- a/src/main/java/leekscript/common/Error.java +++ b/src/main/java/leekscript/common/Error.java @@ -92,4 +92,5 @@ public enum Error { CANNOT_LOAD_AI, // 88 TRANSPILE_TO_JAVA, // 89 CANNOT_WRITE_AI, // 90 + RESERVED_FIELD, // 91 } \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index d2cb7ad9..cbdb0d65 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -684,9 +684,9 @@ public void classDeclaration() throws LeekCompilerException { if (word.getType() != WordParser.T_STRING) { throw new LeekCompilerException(word, Error.VAR_NAME_EXPECTED); } - // if (!isAvailable(word.getWord(), true)) { - // throw new LeekCompilerException(word, Error.VARIABLE_NAME_UNAVAILABLE); - // } + if (mMain.hasUserClass(word.getWord())) { + throw new LeekCompilerException(word, Error.VARIABLE_NAME_UNAVAILABLE); + } ClassDeclarationInstruction classDeclaration = new ClassDeclarationInstruction(word, mLine, mAI); mMain.addClass(classDeclaration); mCurrentClass = classDeclaration; @@ -747,6 +747,9 @@ public void classAccessLevelMember(ClassDeclarationInstruction classDeclaration, classStaticMember(classDeclaration, accessLevel); return; } + if (name.getWord().equals("class") || name.getWord().equals("super")) { + errors.add(new AnalyzeError(name, AnalyzeErrorLevel.ERROR, Error.RESERVED_FIELD, new String[] { name.getWord() })); + } IAWord word2 = mCompiler.getWord(); if (word2.getType() == WordParser.T_PAR_LEFT) { // Méthode @@ -767,6 +770,7 @@ public void classAccessLevelMember(ClassDeclarationInstruction classDeclaration, public void classStaticMember(ClassDeclarationInstruction classDeclaration, AccessLevel accessLevel) throws LeekCompilerException { IAWord name = mCompiler.readWord(); + // Static field AbstractExpression expr = null; if (mCompiler.getWord().getType() == WordParser.T_OPERATOR && mCompiler.getWord().getWord().equals("=")) { @@ -780,6 +784,9 @@ public void classStaticMember(ClassDeclarationInstruction classDeclaration, Acce mCompiler.skipWord(); return; } + if (name.getWord().equals("name") || name.getWord().equals("super") || name.getWord().equals("fields") || name.getWord().equals("staticFields") || name.getWord().equals("methods") || name.getWord().equals("staticMethods")) { + errors.add(new AnalyzeError(name, AnalyzeErrorLevel.ERROR, Error.RESERVED_FIELD, new String[] { name.getWord() })); + } classDeclaration.addStaticField(name, expr, accessLevel); if (mCompiler.getWord().getType() == WordParser.T_END_INSTRUCTION) diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 2beae36d..390ffe1c 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -9,6 +9,7 @@ import leekscript.compiler.AIFile; import leekscript.compiler.IACompiler; +import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; import leekscript.compiler.LeekScript; import leekscript.compiler.WordCompiler; @@ -54,6 +55,18 @@ public MainLeekBlock(IACompiler compiler, AIFile ai) { mAIName = ai.getPath(); mCompiler = compiler; mCompiler.setCurrentAI(ai); + if (ai.getVersion() >= 3) { + addClass(new ClassDeclarationInstruction(new IAWord("Value"), 0, ai)); + addClass(new ClassDeclarationInstruction(new IAWord("Null"), 0, ai)); + addClass(new ClassDeclarationInstruction(new IAWord("Integer"), 0, ai)); + addClass(new ClassDeclarationInstruction(new IAWord("Real"), 0, ai)); + addClass(new ClassDeclarationInstruction(new IAWord("Number"), 0, ai)); + addClass(new ClassDeclarationInstruction(new IAWord("Array"), 0, ai)); + addClass(new ClassDeclarationInstruction(new IAWord("String"), 0, ai)); + addClass(new ClassDeclarationInstruction(new IAWord("Object"), 0, ai)); + addClass(new ClassDeclarationInstruction(new IAWord("Function"), 0, ai)); + addClass(new ClassDeclarationInstruction(new IAWord("Class"), 0, ai)); + } } public void addRedefinedFunction(String function) { diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index db6b06d6..d935f83a 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -61,6 +61,10 @@ public void analyze(WordCompiler compiler) { object.analyze(compiler); operations = 1 + object.operations; + if (field.getWord().equals("class")) { + return; // .class is available everywhere + } + if (object instanceof LeekVariable) { var v = (LeekVariable) object; if (v.getName().equals("this")) { @@ -71,6 +75,9 @@ public void analyze(WordCompiler compiler) { } } else if (v.getVariableType() == VariableType.CLASS && v.getClassDeclaration() != null) { operations -= 1; + if (field.getWord().equals("name") || field.getWord().equals("super") || field.getWord().equals("fields") || field.getWord().equals("staticFields") || field.getWord().equals("methods") || field.getWord().equals("staticMethods")) { + return; // OK + } if (!v.getClassDeclaration().hasStaticMember(field.getWord())) { compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, Error.CLASS_STATIC_MEMBER_DOES_NOT_EXIST, new String[] { v.getClassDeclaration().getName(), field.getWord() })); } @@ -88,20 +95,32 @@ public IAWord getFieldToken() { @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { - writer.addCode("getField("); - object.writeJavaCode(mainblock, writer); - var from_class = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; - writer.addCode(", \"" + field.getWord() + "\", " + from_class + ")"); + if (mainblock.getWordCompiler().getVersion() >= 3 && field.getWord().equals("class")) { + writer.addCode("getClass("); + object.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("getField("); + object.writeJavaCode(mainblock, writer); + var from_class = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; + writer.addCode(", \"" + field.getWord() + "\", " + from_class + ")"); + } } @Override public void compileL(MainLeekBlock mainblock, JavaWriter writer) { assert (object.isLeftValue() && !object.nullable()); - writer.addCode("getField("); - object.writeJavaCode(mainblock, writer); - var from_class = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; - writer.addCode(", \"" + field.getWord() + "\", " + from_class + ")"); + if (mainblock.getWordCompiler().getVersion() >= 3 && field.getWord().equals("class")) { + writer.addCode("getClass("); + object.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } else { + writer.addCode("getField("); + object.writeJavaCode(mainblock, writer); + var from_class = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; + writer.addCode(", \"" + field.getWord() + "\", " + from_class + ")"); + } } @Override diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 70ac1788..a589407b 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -1,5 +1,6 @@ package leekscript.compiler.instruction; +import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map.Entry; @@ -47,7 +48,7 @@ public ClassDeclarationMethod(ClassMethodBlock block, AccessLevel level) { private IAWord parentToken; private ClassDeclarationInstruction parent; private LinkedHashMap fields = new LinkedHashMap<>(); - private HashMap staticFields = new HashMap<>(); + private LinkedHashMap staticFields = new LinkedHashMap<>(); private HashMap fieldVariables = new HashMap<>(); private HashMap staticFieldVariables = new HashMap<>(); private HashMap methodVariables = new HashMap<>(); @@ -389,8 +390,14 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(className + ".initFields = new LeekAnonymousFunction() {"); writer.addLine("public Object run(ObjectLeekValue u_this, Object... values) throws LeekRunException {"); ClassDeclarationInstruction current = this; + ArrayList classes = new ArrayList<>(); while (current != null) { - for (var field : current.fields.entrySet()) { + classes.add(current); + current = current.parent; + } + for (int i = classes.size() - 1; i >= 0; --i) { + var clazz = classes.get(i); + for (var field : clazz.fields.entrySet()) { writer.addCode("u_this.addField(" + writer.getAIThis() + ", \"" + field.getKey() + "\", "); if (field.getValue().expression != null) { field.getValue().expression.writeJavaCode(mainblock, writer); @@ -399,7 +406,6 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { } writer.addLine(", AccessLevel." + field.getValue().level + ");"); } - current = current.parent; } writer.addLine("return null;"); writer.addLine("}};"); diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 175abd3f..05c5130c 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -57,14 +57,37 @@ public abstract class AI { private long compileTime; private long loadTime; private File filesLines; - public ClassLeekValue objectClass; + + public final ClassLeekValue valueClass; + public final ClassLeekValue nullClass; + public final ClassLeekValue booleanClass; + public final ClassLeekValue integerClass; + public final ClassLeekValue realClass; + public final ClassLeekValue numberClass; + public final ClassLeekValue arrayClass; + public final ClassLeekValue stringClass; + public final ClassLeekValue objectClass; + public final ClassLeekValue functionClass; + public final ClassLeekValue classClass; public AI(int instructions, int version) { this.mInstructions = instructions; this.version = version; logs = new AILog(); randomGenerator = LeekScript.getRandom(); - objectClass = new ClassLeekValue(this, "Object"); + + valueClass = new ClassLeekValue(this, "Value"); + nullClass = new ClassLeekValue(this, "Null", valueClass); + booleanClass = new ClassLeekValue(this, "Boolean", valueClass); + numberClass = new ClassLeekValue(this, "Number", valueClass); + integerClass = new ClassLeekValue(this, "Integer", numberClass); + realClass= new ClassLeekValue(this, "Real", numberClass); + arrayClass = new ClassLeekValue(this, "Array", valueClass); + stringClass = new ClassLeekValue(this, "String", valueClass); + objectClass = new ClassLeekValue(this, "Object", valueClass); + functionClass = new ClassLeekValue(this, "Function", valueClass); + classClass = new ClassLeekValue(this, "Class", valueClass); + try { init(); } catch (Exception e) {} @@ -1682,6 +1705,19 @@ public static boolean isType(Object value, int type) { return true; } + public ClassLeekValue getClass(Object value) { + if (value == null) return nullClass; + if (value instanceof Integer) return integerClass; + if (value instanceof Double) return realClass; + if (value instanceof Boolean) return booleanClass; + if (value instanceof ArrayLeekValue) return arrayClass; + if (value instanceof String) return stringClass; + if (value instanceof ObjectLeekValue) return ((ObjectLeekValue) value).clazz; + if (value instanceof FunctionLeekValue) return functionClass; + if (value instanceof ClassLeekValue) return classClass; + return valueClass; + } + public boolean instanceOf(Object value, Object clazz) throws LeekRunException { ops(2); clazz = LeekValueManager.getValue(clazz); diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index 6cd4ee71..a509fad4 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -116,6 +116,8 @@ public static String getString(AI ai, Object value) throws LeekRunException { return ((FunctionLeekValue) value).getString(ai); } else if (value instanceof Box) { return getString(ai, ((Box) value).getValue()); + } else if (value instanceof ClassLeekValue) { + return ((ClassLeekValue) value).name; } return "null"; } @@ -136,6 +138,8 @@ public static String getString(AI ai, Object value, Set visited) throws return (String) value; } else if (value instanceof Box) { return getString(ai, ((Box) value).getValue()); + } else if (value instanceof ClassLeekValue) { + return ((ClassLeekValue) value).name; } return "null"; } diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index e0616921..6a2ab4e0 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -44,7 +44,7 @@ public ClassStaticMethod(LeekFunction value, AccessLevel level) { public String name; public ClassLeekValue parent; public LinkedHashMap fields = new LinkedHashMap<>(); - public HashMap staticFields = new HashMap<>(); + public LinkedHashMap staticFields = new LinkedHashMap<>(); public HashMap constructors = new HashMap<>(); public HashMap methods = new HashMap<>(); public HashMap genericMethods = new HashMap<>(); @@ -61,6 +61,12 @@ public ClassLeekValue(AI ai, String name) { this.parent = null; } + public ClassLeekValue(AI ai, String name, ClassLeekValue parent) { + this.ai = ai; + this.name = name; + this.parent = parent; + } + public void setParent(ClassLeekValue parent) { this.parent = parent; } @@ -118,6 +124,17 @@ public Object getField(String field) throws LeekRunException { } public Object getField(AI ai, String field, ClassLeekValue fromClass) throws LeekRunException { + if (field.equals("fields")) { + return getFieldsArray(); + } else if (field.equals("staticFields")) { + return getStaticFieldsArray(); + } else if (field.equals("methods")) { + return getMethodsArray(); + } else if (field.equals("name")) { + return name; + } else if (field.equals("super")) { + return parent; + } // Private var result = staticFields.get(field); if (result != null) { @@ -141,15 +158,6 @@ public Object getField(AI ai, String field, ClassLeekValue fromClass) throws Lee } } } - if (field.equals("name")) { - return name; - } else if (field.equals("fields")) { - return getFieldsArray(); - } else if (field.equals("methods")) { - return getMethodsArray(); - } else if (field.equals("parent")) { - return parent; - } if (parent instanceof ClassLeekValue) { return parent.getField(ai, field, fromClass); } @@ -369,6 +377,18 @@ private ArrayLeekValue getFieldsArray() throws LeekRunException { return fieldsArray; } + private ArrayLeekValue getStaticFieldsArray() throws LeekRunException { + if (fieldsArray == null) { + Object[] values = new Object[staticFields.size()]; + int i = 0; + for (var f : staticFields.entrySet()) { + values[i++] = f.getKey(); + } + fieldsArray = new ArrayLeekValue(ai, values); + } + return fieldsArray; + } + private ArrayLeekValue getMethodsArray() throws LeekRunException { if (methodsArray == null) { Object[] values = new Object[genericMethods.size()]; diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 3bf3b99e..6eaeb6d1 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -239,23 +239,25 @@ public Box getOrCreate(AI ai, Object value) throws LeekRunException { } public Object callMethod(String method, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { - if (clazz.ai.getVersion() >= 3 && method.equals("keys_0")) { - String[] values = new String[fields.size()]; - int i = 0; - for (var key : fields.keySet()) { - values[i++] = key; + var result = clazz.getMethod(clazz.ai, method, fromClass); + if (result == null) { + if (method.equals("keys_0")) { + String[] values = new String[fields.size()]; + int i = 0; + for (var key : fields.keySet()) { + values[i++] = key; + } + return new ArrayLeekValue(clazz.ai, values); } - return new ArrayLeekValue(clazz.ai, values); - } - if (clazz.ai.getVersion() >= 3 && method.equals("values_0")) { - Object[] values = new Object[fields.size()]; - int i = 0; - for (var value : fields.values()) { - values[i++] = value; + if (method.equals("values_0")) { + Object[] values = new Object[fields.size()]; + int i = 0; + for (var value : fields.values()) { + values[i++] = value; + } + return new ArrayLeekValue(clazz.ai, values); } - return new ArrayLeekValue(clazz.ai, values); } - var result = clazz.getMethod(clazz.ai, method, fromClass); if (result == null) { int underscore = method.lastIndexOf("_"); int argCount = Integer.parseInt(method.substring(underscore + 1)); diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index 8d504c29..0571b0c1 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -154,10 +154,10 @@ public String run_version(int version, Checker checker) { // long referenceOperations = operationsReference.get(operationsReferenceIndex++); if (checker.check(result)) { - System.out.println(GREEN_BOLD + " [OK] " + END_COLOR + "[v" + version + "] " + code + " === " + checker.getResult(result) + " " + C_GREY + compile_time + "ms + " + fn(result.exec_time) + "µs" + ", " + fn(result.operations) + " ops" + END_COLOR); + System.out.println(GREEN_BOLD + " [OK] " + END_COLOR + "[v" + version_min + "-" + version_max + "] " + code + " === " + checker.getResult(result) + " " + C_GREY + compile_time + "ms + " + fn(result.exec_time) + "µs" + ", " + fn(result.operations) + " ops" + END_COLOR); success++; } else { - var err = C_RED + "[FAIL] " + END_COLOR + "[v" + version + "] " + code + " =/= " + checker.getExpected() + " got " + checker.getResult(result) + "\n" + + var err = C_RED + "[FAIL] " + END_COLOR + "[v" + version_min + "-" + version_max + "] " + code + " =/= " + checker.getExpected() + " got " + checker.getResult(result) + "\n" + "/home/pierre/dev/leek-wars/server/daemon/generator-v1/leekscript-v1/ai/AI_" + aiID + ".java"; System.out.println(err); failedTests.add(err); @@ -209,6 +209,9 @@ public Case DISABLED_file_v2_(String code) { public Case code_v1(String code) { return new Case(code, true, 1, 1); } + public Case code_v2(String code) { + return new Case(code, true, 2, 2); + } public Case code_v2_(String code) { return new Case(code, true, 2, LATEST_VERSION); } diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index ae13a4cc..39c39a76 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -214,6 +214,78 @@ public void run() { section("Constant in static field"); code_v2_("class A { static bulbsNameChip = ['puny_bulb': PI] } return A.bulbsNameChip").equals("[puny_bulb : 3.141592653589793]"); + section("Base classes"); + code_v3_("return Value").equals("Value"); + code_v3_("return Null").equals("Null"); + code_v3_("return Number").equals("Number"); + code_v3_("return Integer").equals("Integer"); + code_v3_("return Real").equals("Real"); + code_v3_("return String").equals("String"); + code_v3_("return Array").equals("Array"); + code_v3_("return Object").equals("Object"); + code_v3_("return Function").equals("Function"); + code_v3_("return Class").equals("Class"); + + section(".class"); + code_v2("return null.class").equals("null"); + code_v3_("return null.class").equals("Null"); + code_v2("return true.class").equals("null"); + code_v3_("return true.class").equals("Boolean"); + code_v2("return (12).class").equals("null"); + code_v3_("return (12).class").equals("Integer"); + code_v2("return (12.5).class").equals("null"); + code_v3_("return (12.5).class").equals("Real"); + code_v2("return 'salut'.class").equals("null"); + code_v3_("return 'salut'.class").equals("String"); + code_v2("return [].class").equals("null"); + code_v3_("return [].class").equals("Array"); + code_v2_("return {}.class").equals("Object"); + code_v2("return (function() {}).class").equals("null"); + code_v3_("return (function() {}).class").equals("Function"); + code_v2("class A {} return A.class").equals("null"); + code_v3_("class A {} return A.class").equals("Class"); + code_v2_("class A {} return new A().class").equals("A"); + + section("Class.class"); + code_v2_("class A { class }").error(Error.RESERVED_FIELD); + code_v2_("class A { class() {} }").error(Error.RESERVED_FIELD); + code_v2_("class A { } return new A().class").equals("A"); + code_v2_("class A { } return A.class").equals("Class"); + + section("Class.super"); + code_v2_("class A { super }").error(Error.RESERVED_FIELD); + code_v2_("class A { super() {} }").error(Error.RESERVED_FIELD); + code_v2_("class A { } class B extends A {} return B.super").equals("A"); + code_v2_("class A { } class B extends A {} return B.super.name").equals("A"); + code_v2_("class A { } class B extends A {} return new B().class.super.name").equals("A"); + code_v2_("class A { } return A.class.super").equals("Value"); + + section("Class.name"); + code_v2_("class A { static name }").error(Error.RESERVED_FIELD); + code_v2_("class A { static name() {} }").error(Error.NONE); + code_v2_("class A {} return A.name").equals("A"); + code_v2_("class A {} return new A().class.name").equals("A"); + + section("Class.fields"); + code_v2_("class A { static fields }").error(Error.RESERVED_FIELD); + code_v2_("class A { } return A.fields").equals("[]"); + code_v2_("class A { x y z } return A.fields").equals("[x, y, z]"); + code_v2_("class A { z y x } return A.fields").equals("[z, y, x]"); + code_v2_("class A { a b c static d m() {} n() {} o() {} } return A.fields").equals("[a, b, c]"); + + section("Class.staticFields"); + code_v2_("class A { static staticFields }").error(Error.RESERVED_FIELD); + code_v2_("class A { } return A.staticFields").equals("[]"); + code_v2_("class A { static x static y static z } return A.staticFields").equals("[x, y, z]"); + code_v2_("class A { static z static y static x } return A.staticFields").equals("[z, y, x]"); + code_v2_("class A { static a static b c d m() {} n() {} o() {} } return A.staticFields").equals("[a, b]"); + + section("Class.methods"); + code_v2_("class A { static methods }").error(Error.RESERVED_FIELD); + + section("Class.staticMethods"); + code_v2_("class A { static staticMethods }").error(Error.RESERVED_FIELD); + section("Object.string()"); code_v2_("return string({x: 1, y: 2, z: 3})").equals("{x: 1, y: 2, z: 3}"); code_v2_("return string({z: 1, y: 2, x: 3})").equals("{z: 1, y: 2, x: 3}"); From f637207fe3c9ab2cc80666cd8873168bda46ae95 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 29 Nov 2021 21:01:15 +0100 Subject: [PATCH 303/319] [keyword] Add new keywords + case-sensitive keywords --- src/main/java/leekscript/compiler/IAWord.java | 1 + .../leekscript/compiler/WordCompiler.java | 67 +++++++++++-------- .../java/leekscript/compiler/WordParser.java | 38 ++++++++--- .../leekscript/runner/LeekValueManager.java | 2 + src/test/java/test/TestBoolean.java | 38 +++++++++++ src/test/java/test/TestCommon.java | 17 ++++- src/test/java/test/TestFunction.java | 8 +++ src/test/java/test/TestGeneral.java | 28 ++++++++ src/test/java/test/TestGlobals.java | 2 + src/test/java/test/TestObject.java | 9 ++- 10 files changed, 167 insertions(+), 43 deletions(-) create mode 100644 src/test/java/test/TestBoolean.java diff --git a/src/main/java/leekscript/compiler/IAWord.java b/src/main/java/leekscript/compiler/IAWord.java index ff28bdb6..4deb8206 100644 --- a/src/main/java/leekscript/compiler/IAWord.java +++ b/src/main/java/leekscript/compiler/IAWord.java @@ -1,6 +1,7 @@ package leekscript.compiler; public class IAWord { + private final int type; private final String word; private final int line; diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index cbdb0d65..737776d3 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -74,7 +74,7 @@ public void readCode() throws LeekCompilerException { mCompiler.skipWord(); var global = mCompiler.readWord(); // System.out.println("global = " + global.getWord() + " " + global.getLine()); - if (!isGlobalAvailable(global.getWord()) || mMain.hasDeclaredGlobal(global.getWord())) { + if (!isGlobalAvailable(global) || mMain.hasDeclaredGlobal(global.getWord())) { addError(new AnalyzeError(global, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); } else { mMain.addGlobal(global.getWord()); @@ -86,7 +86,7 @@ public void readCode() throws LeekCompilerException { while (mCompiler.haveWords() && mCompiler.getWord().getType() == WordParser.T_VIRG) { mCompiler.skipWord(); global = mCompiler.readWord(); - if (!isGlobalAvailable(global.getWord()) || mMain.hasDeclaredGlobal(global.getWord())) { + if (!isGlobalAvailable(global) || mMain.hasDeclaredGlobal(global.getWord())) { addError(new AnalyzeError(global, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); } else { mMain.addGlobal(global.getWord()); @@ -98,8 +98,8 @@ public void readCode() throws LeekCompilerException { } } else if (mCompiler.getWord().getWord().equals("function")) { mCompiler.skipWord(); - String funcName = mCompiler.readWord().getWord(); - if (funcName.equals("(")) + var funcName = mCompiler.readWord(); + if (funcName.getWord().equals("(")) continue; if (!isAvailable(funcName, false)) throw new LeekCompilerException(mCompiler.getWord(), Error.FUNCTION_NAME_UNAVAILABLE); @@ -130,7 +130,7 @@ public void readCode() throws LeekCompilerException { throw new LeekCompilerException(mCompiler.getWord(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS); } - mMain.addFunctionDeclaration(funcName, param_count); + mMain.addFunctionDeclaration(funcName.getWord(), param_count); } else mCompiler.skipWord(); } @@ -330,7 +330,7 @@ private void functionBlock() throws LeekCompilerException { if (mCompiler.getWord().getType() != WordParser.T_STRING) throw new LeekCompilerException(mCompiler.getWord(), Error.FUNCTION_NAME_EXPECTED); IAWord funcName = mCompiler.readWord(); - if (!isAvailable(funcName.getWord(), false)) + if (!isAvailable(funcName, false)) throw new LeekCompilerException(mCompiler.getWord(), Error.FUNCTION_NAME_UNAVAILABLE); if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { @@ -643,10 +643,12 @@ private void globalDeclaration() throws LeekCompilerException { private void variableDeclaration() throws LeekCompilerException { // Il y a au moins une premiere variable IAWord word = mCompiler.readWord(); - if (word.getType() != WordParser.T_STRING) + if (word.getType() != WordParser.T_STRING) { throw new LeekCompilerException(word, Error.VAR_NAME_EXPECTED); - // if (!isAvailable(word.getWord(), true)) - // throw new LeekCompilerException(word, Error.VARIABLE_NAME_UNAVAILABLE); + } + if (getVersion() >= 3 && isKeyword(word)) { + addError(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); + } LeekVariableDeclarationInstruction variable = new LeekVariableDeclarationInstruction(this, word, mLine, mAI, getCurrentFunction()); // On regarde si une valeur est assignée if (mCompiler.getWord().getWord().equals("=")) { @@ -1008,17 +1010,17 @@ else if (type == 2) if (mMain.hasGlobal(word.getWord())) { retour.addExpression(new LeekVariable(this, word, VariableType.GLOBAL)); - } else if (word.getWord().equalsIgnoreCase("function")) { + } else if (wordEquals(word, "function")) { retour.addExpression(readAnonymousFunction()); - } else if (word.getWord().equalsIgnoreCase("true")) + } else if (wordEquals(word, "true")) retour.addExpression(new LeekBoolean(true)); - else if (word.getWord().equalsIgnoreCase("false")) + else if (wordEquals(word, "false")) retour.addExpression(new LeekBoolean(false)); - else if (word.getWord().equalsIgnoreCase("null")) + else if (wordEquals(word, "null")) retour.addExpression(new LeekNull()); - else if (word.getWord().equalsIgnoreCase("not")) + else if (wordEquals(word, "not")) retour.addUnaryPrefix(Operators.NOT, word); - else if (getVersion() >= 2 && word.getWord().equalsIgnoreCase("new")) { + else if (getVersion() >= 2 && word.getWord().equals("new")) { retour.addUnaryPrefix(Operators.NEW, word); } else if (getVersion() >= 2 && word.getWord().equals("super")) { // super doit être dans une méthode @@ -1036,8 +1038,7 @@ else if (getVersion() >= 2 && word.getWord().equalsIgnoreCase("new")) { // throw new LeekCompilerException(word, Error.UNKNOWN_VARIABLE_OR_FUNCTION); } } else if (word.getType() == WordParser.T_PAR_LEFT) { - mCompiler.skipWord();// On avance le curseur pour bien être - // au début de l'expression + mCompiler.skipWord(); // On avance le curseur pour bien être au début de l'expression AbstractExpression exp = readExpression(); if (mCompiler.haveWords() && mCompiler.getWord().getType() != WordParser.T_PAR_RIGHT) { @@ -1092,6 +1093,13 @@ else if (operator == Operators.INCREMENT) return result; } + private boolean wordEquals(IAWord word, String expected) { + if (getVersion() <= 2) { + return word.getWord().equalsIgnoreCase(expected); + } + return word.getWord().equals(expected); + } + private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerException { mCompiler.skipWord(); if (mCompiler.readWord().getType() != WordParser.T_PAR_LEFT) { @@ -1170,27 +1178,28 @@ private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerExcepti return new LeekAnonymousFunction(block); } - public boolean isAvailable(String word, boolean allFunctions) { - if (word.equalsIgnoreCase("in") || word.equalsIgnoreCase("global") || word.equalsIgnoreCase("var") || word.equalsIgnoreCase("for") || word.equalsIgnoreCase("else") - || word.equalsIgnoreCase("if") || word.equalsIgnoreCase("break") || word.equalsIgnoreCase("return") || word.equalsIgnoreCase("do") || word.equalsIgnoreCase("while") - || word.equalsIgnoreCase("function") || word.equalsIgnoreCase("true") || word.equalsIgnoreCase("false") || word.equalsIgnoreCase("null")) - return false; + public boolean isKeyword(IAWord word) { + for (var w : WordParser.reservedWords) { + if (wordEquals(word, w)) return true; + } + return false; + } + + public boolean isAvailable(IAWord word, boolean allFunctions) { + if (isKeyword(word)) return false; // if(LeekFunctions.isFunction(word) >= 0 || mMain.hasGlobal(word) || // mMain.hasUserFunction(word, allFunctions) || // mCurentBlock.hasVariable(word)) return false; - if (mMain.hasGlobal(word) || mMain.hasUserFunction(word, allFunctions) || mCurentBlock.hasVariable(word)) + if (mMain.hasGlobal(word.getWord()) || mMain.hasUserFunction(word.getWord(), allFunctions) || mCurentBlock.hasVariable(word.getWord())) return false; return true; } - public boolean isGlobalAvailable(String word) { - if (word.equalsIgnoreCase("in") || word.equalsIgnoreCase("global") || word.equalsIgnoreCase("var") || word.equalsIgnoreCase("for") || word.equalsIgnoreCase("else") - || word.equalsIgnoreCase("if") || word.equalsIgnoreCase("break") || word.equalsIgnoreCase("return") || word.equalsIgnoreCase("do") || word.equalsIgnoreCase("while") - || word.equalsIgnoreCase("function") || word.equalsIgnoreCase("true") || word.equalsIgnoreCase("false") || word.equalsIgnoreCase("null")) - return false; + public boolean isGlobalAvailable(IAWord word) { + if (isKeyword(word)) return false; // if(LeekFunctions.isFunction(word) >= 0 || mMain.hasUserFunction(word, // false) || mCurentBlock.hasVariable(word)) return false; - if (mMain.hasUserFunction(word, false) || mCurentBlock.hasVariable(word)) + if (mMain.hasUserFunction(word.getWord(), false) || mCurentBlock.hasVariable(word.getWord())) return false; return true; } diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index f258841c..0e169c00 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -6,11 +6,22 @@ import leekscript.compiler.exceptions.LeekCompilerException; import leekscript.common.Error; +/** + * Son but est de convertir le LeekCode en un "bytecode" plus rapide à + * exécuter Il doit aussi trouver les erreurs dans le LeekCode + */ public class WordParser { - /** - * Son but est de convertir le LeekCode en un "bytecode" plus rapide à - * exécuter Il doit aussi trouver les erreurs dans le LeekCode - */ + + public static final String[] reservedWords = new String[] { + "abstract", "arguments", "await", "break", "byte", "case", "catch", + "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "eval", + "export", "extends", "false", "final", "finally", "float", "for", "function", + "goto", "if", "implements", "import", "in", "instanceof", "int", "interface", + "let", "long", "native", "new", "null", "package", "private", "protected", + "public", "return", "short", "static", "super", "switch", "synchronized", "this", + "throw", "throws", "transient", "true", "try", "typeof", "var", "void", + "volatile", "while", "with", "yield" + }; /** * Instructions byte(0) (0-255) byte => instruction @@ -358,17 +369,24 @@ else if(c == ','){ // } } + private boolean wordEquals(String word, String expected) { + if (version <= 2) { + return word.equalsIgnoreCase(expected); + } + return word.equals(expected); + } + private void newWord(String word, int type) { - if(type == T_STRING){ - if(word.equalsIgnoreCase("or")){ + if (type == T_STRING) { + if (wordEquals(word, "or")) { type = T_OPERATOR; word = "||"; } - else if(word.equalsIgnoreCase("and")){ + else if (wordEquals(word, "and")) { type = T_OPERATOR; word = "&&"; } - else if (word.equalsIgnoreCase("instanceof")) { + else if (wordEquals(word, "instanceof")) { type = T_OPERATOR; word = "instanceof"; } @@ -379,8 +397,8 @@ else if (word.equalsIgnoreCase("instanceof")) { * } */ } - else if(type == T_OPERATOR){ - if(word.equals("=!")){ + else if (type == T_OPERATOR) { + if (word.equals("=!")) { words.add(new IAWord(mAI, type, "=", line_counter, char_counter)); words.add(new IAWord(mAI, type, "!", line_counter, char_counter)); return; diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index a509fad4..55d9a81f 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -136,6 +136,8 @@ public static String getString(AI ai, Object value, Set visited) throws return ((ArrayLeekValue) value).getString(ai, visited); } else if (value instanceof String) { return (String) value; + } else if (value instanceof FunctionLeekValue) { + return ((FunctionLeekValue) value).getString(ai); } else if (value instanceof Box) { return getString(ai, ((Box) value).getValue()); } else if (value instanceof ClassLeekValue) { diff --git a/src/test/java/test/TestBoolean.java b/src/test/java/test/TestBoolean.java new file mode 100644 index 00000000..40024a7e --- /dev/null +++ b/src/test/java/test/TestBoolean.java @@ -0,0 +1,38 @@ +package test; + +import leekscript.common.Error; + +public class TestBoolean extends TestCommon { + + public void run() { + + section("Boolean"); + code_v1_2("return true").equals("true"); + code_v1_2("return True").equals("true"); + code_v1_2("return TRUE").equals("true"); + code_v3_("return true").equals("true"); + code_v3_("return True").error(Error.UNKNOWN_VARIABLE_OR_FUNCTION); + code_v3_("return TRUE").error(Error.UNKNOWN_VARIABLE_OR_FUNCTION); + + code_v1_2("return false").equals("false"); + code_v1_2("return False").equals("false"); + code_v1_2("return FALSE").equals("false"); + code_v3_("return false").equals("false"); + code_v3_("return False").error(Error.UNKNOWN_VARIABLE_OR_FUNCTION); + code_v3_("return FALSE").error(Error.UNKNOWN_VARIABLE_OR_FUNCTION); + + section("Boolean.operator !"); + code_v1_2("return not true").equals("false"); + code_v1_2("return not false").equals("true"); + code_v1_2("return Not true").equals("false"); + code_v1_2("return Not false").equals("true"); + code_v1_2("return NOT true").equals("false"); + code_v1_2("return NOT false").equals("true"); + code_v3_("return not true").equals("false"); + code_v3_("return not false").equals("true"); + code_v3_("return Not true").error(Error.CANT_ADD_INSTRUCTION_AFTER_BREAK); + code_v3_("return Not false").error(Error.CANT_ADD_INSTRUCTION_AFTER_BREAK); + code_v3_("return NOT true").error(Error.CANT_ADD_INSTRUCTION_AFTER_BREAK); + code_v3_("return NOT false").error(Error.CANT_ADD_INSTRUCTION_AFTER_BREAK); + } +} diff --git a/src/test/java/test/TestCommon.java b/src/test/java/test/TestCommon.java index 0571b0c1..efb3a3d0 100644 --- a/src/test/java/test/TestCommon.java +++ b/src/test/java/test/TestCommon.java @@ -79,6 +79,16 @@ public boolean check(Result result) { }); } + public String any_error() { + return run(new Checker() { + public boolean check(Result result) { + return result.error != Error.NONE; + } + public String getExpected() { return "no error"; } + public String getResult(Result result) { return result.error.name(); } + }); + } + public void almost(double expected) { almost(expected, 1e-10); } @@ -154,10 +164,10 @@ public String run_version(int version, Checker checker) { // long referenceOperations = operationsReference.get(operationsReferenceIndex++); if (checker.check(result)) { - System.out.println(GREEN_BOLD + " [OK] " + END_COLOR + "[v" + version_min + "-" + version_max + "] " + code + " === " + checker.getResult(result) + " " + C_GREY + compile_time + "ms + " + fn(result.exec_time) + "µs" + ", " + fn(result.operations) + " ops" + END_COLOR); + System.out.println(GREEN_BOLD + " [OK] " + END_COLOR + "[v" + version + "] " + code + " === " + checker.getResult(result) + " " + C_GREY + compile_time + "ms + " + fn(result.exec_time) + "µs" + ", " + fn(result.operations) + " ops" + END_COLOR); success++; } else { - var err = C_RED + "[FAIL] " + END_COLOR + "[v" + version_min + "-" + version_max + "] " + code + " =/= " + checker.getExpected() + " got " + checker.getResult(result) + "\n" + + var err = C_RED + "[FAIL] " + END_COLOR + "[v" + version + "] " + code + " =/= " + checker.getExpected() + " got " + checker.getResult(result) + "\n" + "/home/pierre/dev/leek-wars/server/daemon/generator-v1/leekscript-v1/ai/AI_" + aiID + ".java"; System.out.println(err); failedTests.add(err); @@ -209,6 +219,9 @@ public Case DISABLED_file_v2_(String code) { public Case code_v1(String code) { return new Case(code, true, 1, 1); } + public Case code_v1_2(String code) { + return new Case(code, true, 1, 2); + } public Case code_v2(String code) { return new Case(code, true, 2, 2); } diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index bc8b6306..ce4b1ce0 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -6,6 +6,14 @@ public class TestFunction extends TestCommon { public void run() { + section("Function"); + code_v1_2("return function() {}").equals("#Anonymous Function"); + code_v1_2("return Function() {}").equals("#Anonymous Function"); + code_v1_2("return FUNCTION() {}").equals("#Anonymous Function"); + code_v3_("return function() {}").equals("#Anonymous Function"); + code_v3_("return Function() {}").error(Error.CANT_ADD_INSTRUCTION_AFTER_BREAK); + code_v3_("return FUNCTION() {}").error(Error.CANT_ADD_INSTRUCTION_AFTER_BREAK); + section("Recursive"); code("var fact = function(x) { if (x == 1) { return 1 } else { return fact(x - 1) * x } } return fact(8);").equals("40320"); // code("var fact = function(x) { if (x == 1) { return 1m } else { return fact(x - 1) * x } } return fact(30m);").equals("265252859812191058636308480000000"); diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index 0d72fe5c..c711f1b3 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -1,11 +1,21 @@ package test; import leekscript.runner.LeekConstants; +import leekscript.common.Error; +import leekscript.compiler.WordParser; public class TestGeneral extends TestCommon { public void run() { + section("null"); + code_v1_2("return null").equals("null"); + code_v1_2("return Null").equals("null"); + code_v1_2("return NULL").equals("null"); + code_v3_("return null").equals("null"); + code_v3_("return Null").equals("Null"); + code_v3_("return NULL").error(Error.UNKNOWN_VARIABLE_OR_FUNCTION); + section("typeOf()"); // Test nombre code("return typeOf(255)").equals(String.valueOf(LeekConstants.TYPE_NUMBER.getIntValue())); @@ -35,6 +45,24 @@ public void run() { // Blue code("return getBlue(" + 0xAD + ")").equals("173"); + section("Variables with keywords"); + for (var word : WordParser.reservedWords) { + if (word.equals("this")) { + code_v1("var " + word + " = 2;").error(Error.NONE); + code_v2("var " + word + " = 2;").error(Error.THIS_NOT_ALLOWED_HERE); + code_v3_("var " + word + " = 2;").error(Error.VARIABLE_NAME_UNAVAILABLE); + } else if (word.equals("instanceof")) { + code_v1_2("var " + word + " = 2;").error(Error.VAR_NAME_EXPECTED); + code_v3_("var " + word + " = 2;").error(Error.VAR_NAME_EXPECTED); + } else if (word.equals("function")) { + code_v1_2("var " + word + " = 2;").error(Error.OPENING_PARENTHESIS_EXPECTED); + code_v3_("var " + word + " = 2;").error(Error.OPENING_PARENTHESIS_EXPECTED); + } else { + code_v1_2("var " + word + " = 2;").error(Error.NONE); + code_v3_("var " + word + " = 2;").error(Error.VARIABLE_NAME_UNAVAILABLE); + } + } + section("Type changes"); code("var a return a = 12").equals("12"); code("var a a = 12 return a").equals("12"); diff --git a/src/test/java/test/TestGlobals.java b/src/test/java/test/TestGlobals.java index 66b89feb..c6b0b16f 100644 --- a/src/test/java/test/TestGlobals.java +++ b/src/test/java/test/TestGlobals.java @@ -1,5 +1,7 @@ package test; +import leekscript.common.Error; + public class TestGlobals extends TestCommon { public void run() throws Exception { diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 39c39a76..1d89d7cb 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -226,6 +226,9 @@ public void run() { code_v3_("return Function").equals("Function"); code_v3_("return Class").equals("Class"); + code_v2("return Array").equals("null"); + code_v2("class Array {} return Array").equals("Array"); + section(".class"); code_v2("return null.class").equals("null"); code_v3_("return null.class").equals("Null"); @@ -250,7 +253,8 @@ public void run() { code_v2_("class A { class }").error(Error.RESERVED_FIELD); code_v2_("class A { class() {} }").error(Error.RESERVED_FIELD); code_v2_("class A { } return new A().class").equals("A"); - code_v2_("class A { } return A.class").equals("Class"); + code_v2("class A { } return A.class").equals("null"); + code_v3_("class A { } return A.class").equals("Class"); section("Class.super"); code_v2_("class A { super }").error(Error.RESERVED_FIELD); @@ -258,7 +262,8 @@ public void run() { code_v2_("class A { } class B extends A {} return B.super").equals("A"); code_v2_("class A { } class B extends A {} return B.super.name").equals("A"); code_v2_("class A { } class B extends A {} return new B().class.super.name").equals("A"); - code_v2_("class A { } return A.class.super").equals("Value"); + code_v2("class A { } return A.class.super").equals("null"); + code_v3_("class A { } return A.class.super").equals("Value"); section("Class.name"); code_v2_("class A { static name }").error(Error.RESERVED_FIELD); From b4ac24009daacbb081b3c7160c1116a9cb7d32e9 Mon Sep 17 00:00:00 2001 From: Pilow Date: Tue, 30 Nov 2021 19:17:06 +0100 Subject: [PATCH 304/319] [class] Clases and reflexion, field access --- .../leekscript/compiler/WordCompiler.java | 2 +- .../compiler/bloc/MainLeekBlock.java | 24 ++-- .../compiler/expression/LeekExpression.java | 12 +- .../expression/LeekExpressionFunction.java | 48 ++++++-- .../compiler/expression/LeekObjectAccess.java | 8 +- .../compiler/expression/LeekVariable.java | 16 ++- .../ClassDeclarationInstruction.java | 13 ++- src/main/java/leekscript/runner/AI.java | 42 ++++--- .../leekscript/runner/LeekValueManager.java | 8 +- .../runner/values/ClassLeekValue.java | 31 +++-- .../runner/values/FunctionLeekValue.java | 29 +++-- .../runner/values/ObjectLeekValue.java | 19 ++++ src/test/java/test/TestArray.java | 32 +++--- src/test/java/test/TestGeneral.java | 2 +- src/test/java/test/TestNumber.java | 2 +- src/test/java/test/TestObject.java | 106 ++++++++++++------ 16 files changed, 285 insertions(+), 109 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 737776d3..9fb5f907 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -689,7 +689,7 @@ public void classDeclaration() throws LeekCompilerException { if (mMain.hasUserClass(word.getWord())) { throw new LeekCompilerException(word, Error.VARIABLE_NAME_UNAVAILABLE); } - ClassDeclarationInstruction classDeclaration = new ClassDeclarationInstruction(word, mLine, mAI); + ClassDeclarationInstruction classDeclaration = new ClassDeclarationInstruction(word, mLine, mAI, false); mMain.addClass(classDeclaration); mCurrentClass = classDeclaration; diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index 390ffe1c..b3c21c2a 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -56,16 +56,18 @@ public MainLeekBlock(IACompiler compiler, AIFile ai) { mCompiler = compiler; mCompiler.setCurrentAI(ai); if (ai.getVersion() >= 3) { - addClass(new ClassDeclarationInstruction(new IAWord("Value"), 0, ai)); - addClass(new ClassDeclarationInstruction(new IAWord("Null"), 0, ai)); - addClass(new ClassDeclarationInstruction(new IAWord("Integer"), 0, ai)); - addClass(new ClassDeclarationInstruction(new IAWord("Real"), 0, ai)); - addClass(new ClassDeclarationInstruction(new IAWord("Number"), 0, ai)); - addClass(new ClassDeclarationInstruction(new IAWord("Array"), 0, ai)); - addClass(new ClassDeclarationInstruction(new IAWord("String"), 0, ai)); - addClass(new ClassDeclarationInstruction(new IAWord("Object"), 0, ai)); - addClass(new ClassDeclarationInstruction(new IAWord("Function"), 0, ai)); - addClass(new ClassDeclarationInstruction(new IAWord("Class"), 0, ai)); + addClass(new ClassDeclarationInstruction(new IAWord("Value"), 0, ai, true)); + addClass(new ClassDeclarationInstruction(new IAWord("Null"), 0, ai, true)); + addClass(new ClassDeclarationInstruction(new IAWord("Integer"), 0, ai, true)); + addClass(new ClassDeclarationInstruction(new IAWord("Real"), 0, ai, true)); + addClass(new ClassDeclarationInstruction(new IAWord("Number"), 0, ai, true)); + addClass(new ClassDeclarationInstruction(new IAWord("Array"), 0, ai, true)); + addClass(new ClassDeclarationInstruction(new IAWord("String"), 0, ai, true)); + addClass(new ClassDeclarationInstruction(new IAWord("Object"), 0, ai, true)); + addClass(new ClassDeclarationInstruction(new IAWord("Function"), 0, ai, true)); + addClass(new ClassDeclarationInstruction(new IAWord("Class"), 0, ai, true)); + addClass(new ClassDeclarationInstruction(new IAWord("JSON"), 0, ai, true)); + addClass(new ClassDeclarationInstruction(new IAWord("System"), 0, ai, true)); } } @@ -201,6 +203,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { // Classes for (var clazz : mUserClassesList) { + if (clazz.internal) continue; clazz.declareJava(this, writer); } @@ -209,6 +212,7 @@ public void writeJavaCode(JavaWriter writer, String className, String AIClass) { writer.addLine("super(" + mInstructions.size() + ", " + mCompiler.getCurrentAI().getVersion() + ");"); for (var clazz : mUserClassesList) { + if (clazz.internal) continue; clazz.createJava(this, writer); } writer.addLine("}"); diff --git a/src/main/java/leekscript/compiler/expression/LeekExpression.java b/src/main/java/leekscript/compiler/expression/LeekExpression.java index 92424a38..8f7b719f 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpression.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpression.java @@ -697,7 +697,17 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } return; case Operators.NEW: - mExpression2.writeJavaCode(mainblock, writer); + if (mExpression2 instanceof LeekVariable) { + if (mainblock.getWordCompiler().getVersion() >= 3 && ((LeekVariable) mExpression2).getString().equals("Array")) { + writer.addCode("new ArrayLeekValue()"); + } else { + writer.addCode("execute("); + mExpression2.writeJavaCode(mainblock, writer); + writer.addCode(")"); + } + } else { + mExpression2.writeJavaCode(mainblock, writer); + } return; // Les unaires suffixés (++, --), Il a été vérifié au préalable // qu'on avait bien une L-Value diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 4f03bed1..5bf6bcc6 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -14,6 +14,7 @@ import leekscript.runner.CallableVersion; import leekscript.runner.ILeekFunction; import leekscript.runner.LeekFunctions; +import leekscript.runner.values.ClassLeekValue.ClassMethod; import leekscript.common.AccessLevel; import leekscript.common.Error; import leekscript.common.Type; @@ -81,28 +82,31 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { boolean addBrace = false; FunctionBlock user_function = null; ILeekFunction system_function = null; + if (mExpression instanceof LeekObjectAccess) { + // Object access : object.field() var object = ((LeekObjectAccess) mExpression).getObject(); var field = ((LeekObjectAccess) mExpression).getField(); + if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.SUPER) { + // super.field() var from_class = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; writer.addCode("u_this.callSuperMethod(this, \"" + field + "_" + mParameters.size() + "\", " + from_class); } else if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.CLASS) { - // Méthode statique connue + // Class.method() : Méthode statique connue var v = (LeekVariable) object; String methodName = "u_" + v.getClassDeclaration().getStaticMethodName(field, mParameters.size()); writer.addCode(methodName + "("); addComma = false; } else if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.THIS) { - // Méthode connue - // String methodName = "u_" + mainblock.getWordCompiler().getCurrentClass().getMethodName(field, mParameters.size()); - // writer.addCode(methodName + "(u_this"); - writer.addCode("callMethod(u_this, \"" + field + "_" + mParameters.size() + "\", u_class"); + // this.method() : Méthode connue + writer.addCode("callObjectAccess(u_this, \"" + field + "\", \"" + field + "_" + mParameters.size() + "\", u_class"); } else { - writer.addCode("callMethod("); + // object.field() : Méthode ou bien appel d'un champ + writer.addCode("callObjectAccess("); object.writeJavaCode(mainblock, writer); var from_class = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; - writer.addCode(", \"" + field + "_" + mParameters.size() + "\", " + from_class); + writer.addCode(", \"" + field + "\", \"" + field + "_" + mParameters.size() + "\", " + from_class); } } else if (mExpression instanceof LeekTabularValue) { var object = ((LeekTabularValue) mExpression).getTabular(); @@ -230,7 +234,28 @@ public void analyze(WordCompiler compiler) { if (mExpression instanceof LeekVariable) { var v = (LeekVariable) mExpression; - if (v.getVariableType() == VariableType.FUNCTION) { + + if (v.getVariableType() == VariableType.METHOD) { // La variable est analysée comme une méthode, mais ça peut être une fonction système, + + // on regarde si le nombre d'arguments est correct + var methods = compiler.getCurrentClass().getMethod(v.getName()); + for (var count : methods.keySet()) { + if (count == mParameters.size()) { + return; // OK + } + } + // Est-ce que c'est une fonction système ? + var f = LeekFunctions.getValue(v.getName()); + if (f != null) { + if (mParameters.size() >= f.getArgumentsMin() && mParameters.size() <= f.getArguments()) { + v.setVariableType(VariableType.SYSTEM_FUNCTION); + return; // OK, fonction système + } + } + // Sinon, erreur de méthode + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.INVALID_PARAMETER_COUNT)); + + } else if (v.getVariableType() == VariableType.FUNCTION) { int nb_params = LeekFunctions.isFunction(v.getName()); if (nb_params == -1) { nb_params = compiler.getMainBlock().getUserFunctionParametersCount(v.getName()); @@ -248,6 +273,13 @@ public void analyze(WordCompiler compiler) { } } } else if (v.getVariableType() == VariableType.SYSTEM_FUNCTION) { + + if (compiler.getVersion() >= 3) { + var f = LeekFunctions.getValue(v.getName()); + if (mParameters.size() > f.getArguments() || mParameters.size() < f.getArgumentsMin()) { + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.INVALID_PARAMETER_COUNT)); + } + } var system_function = LeekFunctions.getValue(v.getName()); if (system_function.getReturnType() != null) { type = system_function.getReturnType(); diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index d935f83a..377b14ab 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -78,9 +78,13 @@ public void analyze(WordCompiler compiler) { if (field.getWord().equals("name") || field.getWord().equals("super") || field.getWord().equals("fields") || field.getWord().equals("staticFields") || field.getWord().equals("methods") || field.getWord().equals("staticMethods")) { return; // OK } - if (!v.getClassDeclaration().hasStaticMember(field.getWord())) { - compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, Error.CLASS_STATIC_MEMBER_DOES_NOT_EXIST, new String[] { v.getClassDeclaration().getName(), field.getWord() })); + if (v.getClassDeclaration().hasStaticMember(field.getWord())) { + return; // OK + } + if (v.getClassDeclaration().hasMethod(field.getWord())) { + return; // OK } + compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, Error.CLASS_STATIC_MEMBER_DOES_NOT_EXIST, new String[] { v.getClassDeclaration().getName(), field.getWord() })); } } } diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index 73f62109..8158eddd 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -100,6 +100,10 @@ public VariableType getVariableType() { return type; } + public void setVariableType(VariableType type) { + this.type = type; + } + public String getName() { return token.getWord(); } @@ -206,7 +210,11 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode("g_" + token.getWord()); } } else if (type == VariableType.CLASS) { - writer.addCode("u_" + token.getWord()); + if (classDeclaration.internal) { + writer.addCode(token.getWord().toLowerCase() + "Class"); + } else { + writer.addCode("u_" + token.getWord()); + } } else { if (isWrapper()) { writer.addCode("u_" + token.getWord() + ".getValue()"); @@ -250,6 +258,12 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { } else if (type == VariableType.FUNCTION) { FunctionBlock user_function = mainblock.getUserFunction(token.getWord()); writer.addCode("new FunctionLeekValue(" + user_function.getId() + ")"); + } else if (type == VariableType.CLASS) { + if (classDeclaration.internal) { + writer.addCode(token.getWord().toLowerCase() + "Class"); + } else { + writer.addCode("u_" + token.getWord()); + } } else { if (isWrapper()) { writer.addCode("u_" + token.getWord() + ".getVariable()"); diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index a589407b..79fc641c 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -17,6 +17,7 @@ import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.runner.values.ClassLeekValue.ClassMethod; import leekscript.common.AccessLevel; import leekscript.common.Error; @@ -47,6 +48,7 @@ public ClassDeclarationMethod(ClassMethodBlock block, AccessLevel level) { private final IAWord token; private IAWord parentToken; private ClassDeclarationInstruction parent; + public boolean internal; private LinkedHashMap fields = new LinkedHashMap<>(); private LinkedHashMap staticFields = new LinkedHashMap<>(); private HashMap fieldVariables = new HashMap<>(); @@ -57,8 +59,9 @@ public ClassDeclarationMethod(ClassMethodBlock block, AccessLevel level) { private HashMap> methods = new HashMap<>(); private HashMap> staticMethods = new HashMap<>(); - public ClassDeclarationInstruction(IAWord token, int line, AIFile ai) { + public ClassDeclarationInstruction(IAWord token, int line, AIFile ai, boolean internal) { this.token = token; + this.internal = internal; } public HashMap getFields() { @@ -188,6 +191,10 @@ public boolean hasMethod(String name, int paramCount) { return methods.containsKey(name + "_" + paramCount); } + public boolean hasMethod(String name) { + return methods.containsKey(name); + } + public void addStaticMethod(WordCompiler compiler, IAWord token, ClassMethodBlock method, AccessLevel level) { // On regarde si il n'y a pas déjà une méthode du même nom if (methods.containsKey(token.getWord())) { @@ -547,6 +554,10 @@ public LeekVariable getStaticMember(String token) { return null; } + public HashMap getMethod(String name) { + return methods.get(name); + } + public String getMethodName(String name, int argumentCount) { var versions = methods.get(name); if (versions != null) { diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 05c5130c..374777a6 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -69,6 +69,8 @@ public abstract class AI { public final ClassLeekValue objectClass; public final ClassLeekValue functionClass; public final ClassLeekValue classClass; + public final ClassLeekValue jsonClass; + public final ClassLeekValue systemClass; public AI(int instructions, int version) { this.mInstructions = instructions; @@ -87,6 +89,8 @@ public AI(int instructions, int version) { objectClass = new ClassLeekValue(this, "Object", valueClass); functionClass = new ClassLeekValue(this, "Function", valueClass); classClass = new ClassLeekValue(this, "Class", valueClass); + jsonClass = new ClassLeekValue(this, "JSON"); + systemClass = new ClassLeekValue(this, "System"); try { init(); @@ -476,14 +480,13 @@ public ArrayLeekValue arrayMap(ArrayLeekValue array, FunctionLeekValue function) ArrayLeekValue retour = new ArrayLeekValue(); ArrayIterator iterator = array.getArrayIterator(); int nb = function.getArgumentsCount(this); - if (nb != 1 && nb != 2) - return retour; while (!iterator.ended()) { var value = iterator.value(); - if (nb == 1) - retour.getOrCreate(this, iterator.getKey(this)).set(LeekValueManager.execute(this, function, value)); - else - retour.getOrCreate(this, iterator.getKey(this)).set(LeekValueManager.execute(this, function, iterator.getKey(this), value)); + if (nb >= 2) { + retour.getOrCreate(this, iterator.getKey(this)).set(function.execute(this, iterator.getKey(this), value)); + } else { + retour.getOrCreate(this, iterator.getKey(this)).set(function.execute(this, value)); + } iterator.next(); } return retour; @@ -493,14 +496,12 @@ public ArrayLeekValue arrayMapV1(ArrayLeekValue array, FunctionLeekValue functio ArrayLeekValue retour = new ArrayLeekValue(); ArrayIterator iterator = array.getArrayIterator(); int nb = function.getArgumentsCount(this); - if (nb != 1 && nb != 2) - return retour; while (!iterator.ended()) { var value = iterator.getValueBox(); - if (nb == 1) - retour.getOrCreate(this, iterator.getKey(this)).setRef(LeekValueManager.execute(this, function, value)); - else + if (nb >= 2) retour.getOrCreate(this, iterator.getKey(this)).setRef(LeekValueManager.execute(this, function, iterator.getKey(this), value)); + else + retour.getOrCreate(this, iterator.getKey(this)).setRef(LeekValueManager.execute(this, function, value)); iterator.next(); } return retour; @@ -888,8 +889,6 @@ public boolean bool(Object value) { return !s.isEmpty(); } else if (value instanceof Box) { return bool(((Box) value).getValue()); - // } else if (value instanceof ReferenceLeekValue) { - // return bool(((ReferenceLeekValue) value).getValue()); } return false; } @@ -1424,6 +1423,10 @@ public Object put(Object array, Object key, Object value) throws LeekRunExceptio if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put(this, key, value); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).setField(field, value); + } if (array instanceof ClassLeekValue) { var field = string(key); return ((ClassLeekValue) array).setField(field, value); @@ -1643,10 +1646,20 @@ public Object callMethod(Object value, String method, ClassLeekValue fromClass, return null; } + public Object callObjectAccess(Object value, String field, String method, ClassLeekValue fromClass, Object... args) throws LeekRunException { + if (value instanceof ObjectLeekValue) { + return ((ObjectLeekValue) value).callAccess(field, method, fromClass, args); + } + return null; + } + public Object execute(Object function, Object... args) throws LeekRunException { if (function instanceof FunctionLeekValue) { return ((FunctionLeekValue) function).execute(this, args); } + if (function == arrayClass) { + return new ArrayLeekValue(); + } if (function instanceof ClassLeekValue) { return ((ClassLeekValue) function).execute(args); } @@ -1654,7 +1667,6 @@ public Object execute(Object function, Object... args) throws LeekRunException { return null; } - public Object sysexec(ILeekFunction function, Object... arguments) throws LeekRunException { // Vérification parametres int[] parameters = function.getParameters(); @@ -1713,8 +1725,8 @@ public ClassLeekValue getClass(Object value) { if (value instanceof ArrayLeekValue) return arrayClass; if (value instanceof String) return stringClass; if (value instanceof ObjectLeekValue) return ((ObjectLeekValue) value).clazz; - if (value instanceof FunctionLeekValue) return functionClass; if (value instanceof ClassLeekValue) return classClass; + if (value instanceof FunctionLeekValue) return functionClass; return valueClass; } diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index 55d9a81f..1449932f 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -112,12 +112,12 @@ public static String getString(AI ai, Object value) throws LeekRunException { return ((ArrayLeekValue) value).getString(ai, new HashSet()); } else if (value instanceof String) { return (String) value; + } else if (value instanceof ClassLeekValue) { + return ((ClassLeekValue) value).getString(ai); } else if (value instanceof FunctionLeekValue) { return ((FunctionLeekValue) value).getString(ai); } else if (value instanceof Box) { return getString(ai, ((Box) value).getValue()); - } else if (value instanceof ClassLeekValue) { - return ((ClassLeekValue) value).name; } return "null"; } @@ -136,12 +136,12 @@ public static String getString(AI ai, Object value, Set visited) throws return ((ArrayLeekValue) value).getString(ai, visited); } else if (value instanceof String) { return (String) value; + } else if (value instanceof ClassLeekValue) { + return ((ClassLeekValue) value).getString(ai); } else if (value instanceof FunctionLeekValue) { return ((FunctionLeekValue) value).getString(ai); } else if (value instanceof Box) { return getString(ai, ((Box) value).getValue()); - } else if (value instanceof ClassLeekValue) { - return ((ClassLeekValue) value).name; } return "null"; } diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 6a2ab4e0..55276b6f 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -1,5 +1,6 @@ package leekscript.runner.values; +import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; @@ -11,7 +12,7 @@ import leekscript.runner.LeekFunction; import leekscript.common.Error; -public class ClassLeekValue { +public class ClassLeekValue extends FunctionLeekValue { public static class ClassField { Object value; @@ -56,12 +57,17 @@ public ClassStaticMethod(LeekFunction value, AccessLevel level) { private ArrayLeekValue methodsArray; public ClassLeekValue(AI ai, String name) { - this.ai = ai; - this.name = name; - this.parent = null; + this(ai, name, null); } public ClassLeekValue(AI ai, String name, ClassLeekValue parent) { + super(null, FunctionLeekValue.STATIC_METHOD, -1); + this.mAnonymous = new LeekAnonymousFunction() { + @Override + public Object run(ObjectLeekValue thiz, Object... values) throws LeekRunException { + return execute(values); + } + }; this.ai = ai; this.name = name; this.parent = parent; @@ -98,7 +104,7 @@ public Object run(ObjectLeekValue thiz, Object... arguments) throws LeekRunExcep ai.addSystemLog(leekscript.AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { name, createMethodError(methodCode) }); return null; } - })); + }, FunctionLeekValue.METHOD, -1)); } public void addStaticMethod(String method, int argCount, LeekFunction function, AccessLevel level) { @@ -109,14 +115,14 @@ public void addGenericStaticMethod(String method) { genericMethods.put(method, new FunctionLeekValue(new LeekAnonymousFunction() { public Object run(ObjectLeekValue thiz, Object... arguments) throws LeekRunException { final var methodCode = method + "_" + arguments.length; - final var m = methods.get(methodCode); + final var m = staticMethods.get(methodCode); if (m != null) { return m.value.run(null, arguments); } ai.addSystemLog(leekscript.AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { name, createMethodError(methodCode) }); return null; } - })); + }, FunctionLeekValue.STATIC_METHOD, -1)); } public Object getField(String field) throws LeekRunException { @@ -158,6 +164,9 @@ public Object getField(AI ai, String field, ClassLeekValue fromClass) throws Lee } } } + var generic = genericMethods.get(field); + if (generic != null) return generic; + if (parent instanceof ClassLeekValue) { return parent.getField(ai, field, fromClass); } @@ -352,7 +361,9 @@ public Object execute(Object... arguments) throws LeekRunException { ai.ops(1); ObjectLeekValue object = new ObjectLeekValue(this); // Init fields - this.initFields.run(object); + if (this.initFields != null) { + this.initFields.run(object); + } int arg_count = arguments.length; if (constructors.containsKey(arg_count)) { @@ -365,6 +376,10 @@ public Object execute(Object... arguments) throws LeekRunException { } } + public Object run(ObjectLeekValue thiz, Object... arguments) throws LeekRunException { + return execute(ai, arguments); + } + private ArrayLeekValue getFieldsArray() throws LeekRunException { if (fieldsArray == null) { Object[] values = new Object[fields.size()]; diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index 5e7207b1..99a36c27 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -13,15 +13,17 @@ public class FunctionLeekValue { - private final static int LEEK_FUNCTION = 1; - private final static int USER_FUNCTION = 2; - private final static int ANONYMOUS_FUNCTION = 3; - private final static int METHOD = 4; + public final static int LEEK_FUNCTION = 1; + public final static int USER_FUNCTION = 2; + public final static int ANONYMOUS_FUNCTION = 3; + public final static int METHOD = 4; + public final static int STATIC_METHOD = 5; private final int mType; private final int mId; private ILeekFunction mFunction; - private LeekAnonymousFunction mAnonymous; + protected LeekAnonymousFunction mAnonymous; + protected int mParametersCount = -1; public FunctionLeekValue(int id) { mType = USER_FUNCTION; @@ -40,13 +42,14 @@ public FunctionLeekValue(ILeekFunction fonction) { mId = 0; } - public FunctionLeekValue(LeekAnonymousFunction fonction) { + public FunctionLeekValue(LeekAnonymousFunction fonction, int type, int parametersCount) { mAnonymous = fonction; - mType = METHOD; + mType = type; mId = 0; + mParametersCount = parametersCount; } - public boolean equals(AI ai, Object comp) { + public boolean equals(AI ai, Object comp) throws LeekRunException { if (LeekValueManager.getType(comp) != LeekValue.FUNCTION) { return false; } @@ -89,7 +92,7 @@ else if (mType == USER_FUNCTION) return ai.userFunctionCount(mId); else if (mType == ANONYMOUS_FUNCTION) return ai.anonymousFunctionCount(mId); - return -1; + return mParametersCount; } public Object execute(AI ai, Object... values) throws LeekRunException { @@ -113,9 +116,11 @@ else if (mType == USER_FUNCTION) { } else { return mAnonymous.run(null, values); } + } else if (mType == STATIC_METHOD) { + return mAnonymous.run(null, values); } else if (mType == METHOD) { if (values.length == 0) { - ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { "", "1+" }); + ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { LeekValue.getParamString(values), "1+" }); } else { return mAnonymous.run((ObjectLeekValue) values[0], Arrays.copyOfRange(values, 1, values.length)); } @@ -146,4 +151,8 @@ else if (mType == USER_FUNCTION) public Object toJSON(AI ai) { return ""; } + + public String toString() { + return ""; + } } diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 6eaeb6d1..277c494d 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -238,6 +238,25 @@ public Box getOrCreate(AI ai, Object value) throws LeekRunException { return getFieldL(LeekValueManager.getString(ai, value)); } + public Object callAccess(String field, String method, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { + var result = fields.get(field); + if (result != null) { + // Private : Access from same class + if (result.level == AccessLevel.PRIVATE && fromClass != clazz) { + clazz.ai.addSystemLog(AILog.ERROR, Error.PRIVATE_FIELD, new String[] { clazz.name, field }); + return null; + } + // Protected : Access from descendant + if (result.level == AccessLevel.PROTECTED && (fromClass != clazz && !clazz.descendsFrom(fromClass))) { + clazz.ai.addSystemLog(AILog.ERROR, result.level == AccessLevel.PROTECTED ? Error.PROTECTED_FIELD : Error.PRIVATE_FIELD, new String[] { clazz.name, field }); + return null; + } + // Call the value + return clazz.ai.execute(result.mValue, arguments); + } + return callMethod(method, fromClass, arguments); + } + public Object callMethod(String method, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { var result = clazz.getMethod(clazz.ai, method, fromClass); if (result == null) { diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index de5ca1f7..0f8a2097 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -5,11 +5,11 @@ public class TestArray extends TestCommon { public void run() throws Exception { section("Array.constructor()"); - // DISABLED_code("Array").equals(""); - // DISABLED_code("Array()").equals("[]"); - // DISABLED_code("new Array").equals("[]"); - // DISABLED_code("new Array()").equals("[]"); - // DISABLED_code("new Array() + 1").equals("[1]"); + code_v3_("return Array").equals(""); + code_v3_("return Array()").equals("[]"); + code_v3_("return new Array").equals("[]"); + code_v3_("return new Array()").equals("[]"); + code_v3_("return new Array() + 1").equals("[1]"); code("return [];").equals("[]"); code("return [1];").equals("[1]"); code("return [1, 2, 3];").equals("[1, 2, 3]"); @@ -30,16 +30,20 @@ public void run() throws Exception { section("Array.operator +"); code("return [1, 2, 3] + [4, 5, 6];").equals("[1, 2, 3, 4, 5, 6]"); - // DISABLED_code("return [] + 1;").equals("[1]"); - // DISABLED_code("return [] + 1 + 2 + 3;").equals("[1, 2, 3]"); - // DISABLED_code("return [1] + 2;").equals("[1, 2]"); - // DISABLED_code("return [1] + 0.5;").equals("[1, 0.5]"); - // DISABLED_code("return [0.5] + 'a';").equals("[0.5, 'a']"); + code("return [] + 1;").equals("[1]"); + code("return [] + 1 + 2 + 3;").equals("[1, 2, 3]"); + code("return [1] + 2;").equals("[1, 2]"); + code_v1("return [1] + 0.5;").equals("[1, 0,5]"); + code_v2_("return [1] + 0.5;").equals("[1, 0.5]"); + // code_v1("return [0.5] + 'a';").equals("[0,5, a]"); + // code_v2_("return [0.5] + 'a';").equals("[0.5, a]"); code("return ['a'] + ['b'];").equals("[a, b]"); - // DISABLED_code("return [1] + 0.5 + 'a';").equals("[1, 0.5, 'a']"); - // DISABLED_code("return [1] + 0.5 + 'a' + 'b';").equals("[1, 0.5, 'a', 'b']"); - // DISABLED_code("return [1] + null;").equals("[1, null]"); - // DISABLED_code("return [1] + true;").equals("[1, true]"); + // code_v1("return [1] + 0.5 + 'a';").equals("[1, 0,5, a]"); + // code_v2_("return [1] + 0.5 + 'a';").equals("[1, 0.5, a]"); + // code_v1("return [1] + 0.5 + 'a' + 'b';").equals("[1, 0,5, a, b]"); + // code_v2_("return [1] + 0.5 + 'a' + 'b';").equals("[1, 0.5, a, b]"); + code("return [1] + null;").equals("[1, null]"); + code("return [1] + true;").equals("[1, true]"); code("return [1] + [2] + [3];").equals("[1, 2, 3]"); code_v1("return [1] + [2.5] + ['a'];").equals("[1, 2,5, a]"); code_v2_("return [1] + [2.5] + ['a'];").equals("[1, 2.5, a]"); diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index c711f1b3..8888d9bc 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -13,7 +13,7 @@ public void run() { code_v1_2("return Null").equals("null"); code_v1_2("return NULL").equals("null"); code_v3_("return null").equals("null"); - code_v3_("return Null").equals("Null"); + code_v3_("return Null").equals(""); code_v3_("return NULL").error(Error.UNKNOWN_VARIABLE_OR_FUNCTION); section("typeOf()"); diff --git a/src/test/java/test/TestNumber.java b/src/test/java/test/TestNumber.java index 563dc6cd..aa3e21bd 100644 --- a/src/test/java/test/TestNumber.java +++ b/src/test/java/test/TestNumber.java @@ -143,7 +143,7 @@ public void run() throws Exception { */ // header("Number standard library"); section("Constructor"); - // DISABLED_code("Number").equals(""); + code_v3_("return Number").equals(""); // DISABLED_code("Number()").equals("0"); // DISABLED_code("Number(12)").equals("12"); // DISABLED_code("Number(12.5)").equals("12.5"); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 1d89d7cb..7252eb33 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -7,9 +7,9 @@ public class TestObject extends TestCommon { public void run() { section("Objects"); - // code("return Object()").equals("{}"); - // code("return new Object").equals("{}"); - // code("return new Object()").equals("{}"); + code_v3_("return Object()").equals("{}"); + code_v3_("return new Object").equals("{}"); + code_v3_("return new Object()").equals("{}"); code_v2_("return {}").equals("{}"); code_v2_("return {a: 12}").equals("{a: 12}"); code_v2_("return {a: 12, b: 5}").equals("{a: 12, b: 5}"); @@ -120,6 +120,17 @@ public void run() { code_v2_("class A { static a = 10 static m() { return a >>= 5 } } return A.m()").equals("0"); code_v2_("class A { static a = 10 static m() { return a >>>= 5 } } return A.m()").equals("0"); + section("Field access by array access"); + code_v2_("var test = {} test['a'] = 8 return test").equals("{a: 8}"); + code_v2_("var test = {} test['a'] = 8 test['b'] = 12 return test").equals("{a: 8, b: 12}"); + code_v2_("class Test { a b c } var test2 = new Test() test2['a'] = 8 return test2").equals("Test {a: 8, b: null, c: null}"); + code_v2_("class Test { a b c } var test2 = new Test() for (var field in Test.fields) { test2[field] = 8 } return test2").equals("Test {a: 8, b: 8, c: 8}"); + code_v2_("class Test { a b c constructor(a, b, c) { this.a = a this.b = b this.c = c } } var test1 = new Test(1, 2, 3) var test2 = new Test() for (var field in test1.class.fields) { test2[field] = test1[field] } return test2").equals("Test {a: 1, b: 2, c: 3}"); + code_v2_("class Test { a b c constructor(a, b, c) { this.a = a this.b = b this.c = c } } var test1 = new Test(1, 2, 3) var test2 = new Test() for (var field in test2.class.fields) { test2[field] = test1[field] } return test2").equals("Test {a: 1, b: 2, c: 3}"); + + section("Static field access by array access"); + code_v2_("class Test { static a static b static c } Test['a'] = 12 Test['b'] = 15 Test['c'] = 20 return [Test.a, Test.b, Test.c]").equals("[12, 15, 20]"); + section("Inheritance"); code_v2_("class A { x = 10 } class B extends A {} var a = new B() return a.x").equals("10"); code_v2_("class A { m() { return 'ok' } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("ok"); @@ -182,6 +193,10 @@ public void run() { code_v2_("class A { private constructor() { } } class B extends A {} return new B()").equals("B {}"); code_v2_("class A { private constructor() {} static getInstance() { return new A() } } return A.getInstance()").equals("A {}"); + section("Constructor as function"); + code_v2_("class A { x constructor(x) { this.x = x } } var f = A var o = {c: f} return o.c('a')").equals("A {x: a}"); + code_v2_("class A { x constructor(x) { this.x = x } } var a = [1, 2, 3, 4] return arrayMap(a, A)").equals("[A {x: 1}, A {x: 2}, A {x: 3}, A {x: 4}]"); + section("Access levels: static methods"); code_v2_("class A { static m() { return 10 } } return A.m()").equals("10"); code_v2_("class A { public static m() { return 10 } } return A.m()").equals("10"); @@ -205,7 +220,32 @@ public void run() { section("Method is a system method"); code_v2_("class A { sqrt() { return sqrt(25) } }").equals("null"); - DISABLED_code_v2_("class A { sqrt() { return sqrt(25) } } return new A().sqrt()").equals("5"); + code_v2("return sqrt(25, 12)").error(Error.NONE); + code_v3_("return sqrt(25, 12)").error(Error.INVALID_PARAMETER_COUNT); + code_v2_("class A {} return new A().sqrt()").equals("null"); + code_v2_("class A { sqrt() { return sqrt(25) } } return new A().sqrt()").equals("5.0"); + code_v2_("class A { sqrt() { return sqrt(10, 15) } sqrt(x, y) { return sqrt(x + y) } } return new A().sqrt()").equals("5.0"); + + section("Method as value"); + code_v2_("class A { x = 12 m() { return x } } var o = new A() var r = [A.m] return r[0](o)").equals("12"); + code_v2_("class A { m() { return 12 } } var o = new A() var r = {x: A.m} return r.x(o)").equals("12"); + code_v2_("class A { m() { return 12 } } var o = new A() var r = [A.m] var m = r[0] return m(o)").equals("12"); + code_v2_("class A { m() { return [1, 2, 3] } } var o = new A() var r = [A.m] var m = r[0] return m(o)").equals("[1, 2, 3]"); + code_v2_("class A { m(x, y) { return x * y } } class B { x = A.m } return new B().x(new A(), 5, 12)").equals("60"); + code_v2_("class A { m(x, y) { return x * y } } var f = A.m return f(new A(), 5, 12)").equals("60"); + code_v2_("class A { m(x, y) { return x * y } } var f = new A().m return f(new A(), 5, 12)").equals("60"); + code_v2_("class A { m(x, y) { return x * y } } var f = A.m return f(new A(), 5)").equals("null"); + + section("Static method as value"); + code_v2_("class A { static m() { return 12 } } var r = [A.m] return r[0]()").equals("12"); + code_v2_("class A { static m() { return 12 } } var r = {x: A.m} return r.x()").equals("12"); + code_v2_("class A { static m() { return 12 } } var r = [A.m] var m = r[0] return m()").equals("12"); + code_v2_("class A { static m() { return [1, 2, 3] } } var r = [A.m] var m = r[0] return m()").equals("[1, 2, 3]"); + code_v2_("class a { static method() { return '42' } } class b { toto constructor() { this.toto = a.method } } return new b().toto()").equals("42"); + code_v2_("class a { static method() { return '42' } } class b { toto constructor() { this.toto = a.method } } var o = new b() return o.toto()").equals("42"); + code_v2_("class a { static method() { return '42' } } class b { toto constructor() { this.toto = a.method } m() { return this.toto() } } var o = new b() return o.m()").equals("42"); + code_v2_("class Test { private static method_1() { return 4 } private static method_2() { return 9 } public static array = [1: Test.method_1, 2: Test.method_2] } return [Test.array[1](), Test.array[2]()]").equals("[4, 9]"); + code_v2_("class Test { private static method_1() { return 4 } private static method_2() { return 9 } public static array = [1: Test.method_1, 2: Test.method_2] } return arrayMap(Test.array, function(x) { return x() })").equals("[1 : 4, 2 : 9]"); section("Return of field"); code_v2_("class R { f = [] m(k, r) { return this.f[k] = r } } var x = new R() return x.m(1, 2)").equals("2"); @@ -215,55 +255,57 @@ public void run() { code_v2_("class A { static bulbsNameChip = ['puny_bulb': PI] } return A.bulbsNameChip").equals("[puny_bulb : 3.141592653589793]"); section("Base classes"); - code_v3_("return Value").equals("Value"); - code_v3_("return Null").equals("Null"); - code_v3_("return Number").equals("Number"); - code_v3_("return Integer").equals("Integer"); - code_v3_("return Real").equals("Real"); - code_v3_("return String").equals("String"); - code_v3_("return Array").equals("Array"); - code_v3_("return Object").equals("Object"); - code_v3_("return Function").equals("Function"); - code_v3_("return Class").equals("Class"); - - code_v2("return Array").equals("null"); - code_v2("class Array {} return Array").equals("Array"); + code_v3_("return Value").equals(""); + code_v3_("return Null").equals(""); + code_v3_("return Number").equals(""); + code_v3_("return Integer").equals(""); + code_v3_("return Real").equals(""); + code_v3_("return String").equals(""); + code_v3_("return Array").equals(""); + code_v3_("return Object").equals(""); + code_v3_("return Function").equals(""); + code_v3_("return Class").equals(""); + code_v3_("return JSON").equals(""); + code_v3_("return System").equals(""); + + code_v2("return Array").error(Error.UNKNOWN_VARIABLE_OR_FUNCTION); + code_v2("class Array {} return Array").equals(""); section(".class"); code_v2("return null.class").equals("null"); - code_v3_("return null.class").equals("Null"); + code_v3_("return null.class").equals(""); code_v2("return true.class").equals("null"); - code_v3_("return true.class").equals("Boolean"); + code_v3_("return true.class").equals(""); code_v2("return (12).class").equals("null"); - code_v3_("return (12).class").equals("Integer"); + code_v3_("return (12).class").equals(""); code_v2("return (12.5).class").equals("null"); - code_v3_("return (12.5).class").equals("Real"); + code_v3_("return (12.5).class").equals(""); code_v2("return 'salut'.class").equals("null"); - code_v3_("return 'salut'.class").equals("String"); + code_v3_("return 'salut'.class").equals(""); code_v2("return [].class").equals("null"); - code_v3_("return [].class").equals("Array"); - code_v2_("return {}.class").equals("Object"); + code_v3_("return [].class").equals(""); + code_v2_("return {}.class").equals(""); code_v2("return (function() {}).class").equals("null"); - code_v3_("return (function() {}).class").equals("Function"); + code_v3_("return (function() {}).class").equals(""); code_v2("class A {} return A.class").equals("null"); - code_v3_("class A {} return A.class").equals("Class"); - code_v2_("class A {} return new A().class").equals("A"); + code_v3_("class A {} return A.class").equals(""); + code_v2_("class A {} return new A().class").equals(""); section("Class.class"); code_v2_("class A { class }").error(Error.RESERVED_FIELD); code_v2_("class A { class() {} }").error(Error.RESERVED_FIELD); - code_v2_("class A { } return new A().class").equals("A"); + code_v2_("class A { } return new A().class").equals(""); code_v2("class A { } return A.class").equals("null"); - code_v3_("class A { } return A.class").equals("Class"); + code_v3_("class A { } return A.class").equals(""); section("Class.super"); code_v2_("class A { super }").error(Error.RESERVED_FIELD); code_v2_("class A { super() {} }").error(Error.RESERVED_FIELD); - code_v2_("class A { } class B extends A {} return B.super").equals("A"); + code_v2_("class A { } class B extends A {} return B.super").equals(""); code_v2_("class A { } class B extends A {} return B.super.name").equals("A"); code_v2_("class A { } class B extends A {} return new B().class.super.name").equals("A"); code_v2("class A { } return A.class.super").equals("null"); - code_v3_("class A { } return A.class.super").equals("Value"); + code_v3_("class A { } return A.class.super").equals(""); section("Class.name"); code_v2_("class A { static name }").error(Error.RESERVED_FIELD); @@ -333,7 +375,7 @@ public void run() { section("Object.operator =="); code_v2_("class A {} return {} == new A").equals("false"); code_v2_("class A { }; class B { }; return new A() == new B();").equals("false"); - code_v2_("class A {} return new A == new A").equals("true"); + code_v2_("class A {} return new A == new A").equals("false"); code_v2_("return {a: 2} == {}").equals("false"); code_v2_("return {a: 2} == {a: 1}").equals("false"); code_v2_("return {a: 2} == {b: 2}").equals("false"); From 9be53b5441fec9991f97a44442190ebe7044da51 Mon Sep 17 00:00:00 2001 From: Pilow Date: Thu, 23 Dec 2021 14:04:00 +0100 Subject: [PATCH 305/319] [class] Multiple OOP improvements and errors --- src/main/java/leekscript/common/Error.java | 1 + .../leekscript/compiler/WordCompiler.java | 25 +- .../java/leekscript/compiler/WordParser.java | 2 +- .../compiler/bloc/ClassMethodBlock.java | 8 +- .../compiler/bloc/MainLeekBlock.java | 1 + .../expression/LeekExpressionFunction.java | 49 +++- .../compiler/expression/LeekObjectAccess.java | 9 +- .../compiler/expression/LeekVariable.java | 4 +- .../ClassDeclarationInstruction.java | 14 +- .../instruction/LeekReturnInstruction.java | 6 +- src/main/java/leekscript/runner/AI.java | 227 +++++++++++++----- .../java/leekscript/runner/LeekFunctions.java | 3 +- .../leekscript/runner/LeekRunException.java | 3 - .../leekscript/runner/LeekValueManager.java | 3 +- .../java/leekscript/runner/values/Box.java | 19 +- .../runner/values/ClassLeekValue.java | 128 ++++------ .../runner/values/FunctionLeekValue.java | 2 + .../runner/values/ObjectLeekValue.java | 65 +++-- src/test/java/test/TestArray.java | 1 + src/test/java/test/TestGeneral.java | 17 ++ src/test/java/test/TestGlobals.java | 2 - src/test/java/test/TestObject.java | 127 +++++++++- src/test/java/test/TestString.java | 2 + 23 files changed, 508 insertions(+), 210 deletions(-) diff --git a/src/main/java/leekscript/common/Error.java b/src/main/java/leekscript/common/Error.java index 56914cf6..2caa3e66 100644 --- a/src/main/java/leekscript/common/Error.java +++ b/src/main/java/leekscript/common/Error.java @@ -93,4 +93,5 @@ public enum Error { TRANSPILE_TO_JAVA, // 89 CANNOT_WRITE_AI, // 90 RESERVED_FIELD, // 91 + VALUE_IS_NOT_AN_ARRAY, // 92 } \ No newline at end of file diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 9fb5f907..b15c6c5b 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -221,7 +221,7 @@ private void compileWord() throws LeekCompilerException { mCompiler.skipWord(); globalDeclaration(); return; - } else if (version >= 2 && word.getWord().equals("class")) { + } else if (version >= 2 && getCurrentBlock() instanceof MainLeekBlock && word.getWord().equals("class")) { // Déclaration de classe mCompiler.skipWord(); classDeclaration(); @@ -663,8 +663,9 @@ private void variableDeclaration() throws LeekCompilerException { word = mCompiler.readWord(); if (word.getType() != WordParser.T_STRING) throw new LeekCompilerException(word, Error.VAR_NAME_EXPECTED); - // if (!isAvailable(word.getWord(), true)) - // throw new LeekCompilerException(word, Error.VARIABLE_NAME_UNAVAILABLE); + if (getVersion() >= 3 && isKeyword(word)) { + addError(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE)); + } variable = new LeekVariableDeclarationInstruction(this, word, mLine, mAI, getCurrentFunction()); // On regarde si une valeur est assignée if (mCompiler.getWord().getWord().equals("=")) { @@ -689,6 +690,9 @@ public void classDeclaration() throws LeekCompilerException { if (mMain.hasUserClass(word.getWord())) { throw new LeekCompilerException(word, Error.VARIABLE_NAME_UNAVAILABLE); } + if (getVersion() >= 3 && isKeyword(word)) { + errors.add(new AnalyzeError(word, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE, new String[] { word.getWord() })); + } ClassDeclarationInstruction classDeclaration = new ClassDeclarationInstruction(word, mLine, mAI, false); mMain.addClass(classDeclaration); mCurrentClass = classDeclaration; @@ -696,9 +700,6 @@ public void classDeclaration() throws LeekCompilerException { if (mCompiler.getWord().getWord().equals("extends")) { mCompiler.skipWord(); IAWord parent = mCompiler.readWord(); - // if (!mMain.hasUserClass(parentName)) { - // throw new LeekCompilerException(word, Error.NO_SUCH_CLASS); - // } classDeclaration.setParent(parent); } if (mCompiler.getWord().getType() != WordParser.T_ACCOLADE_LEFT) { @@ -751,6 +752,8 @@ public void classAccessLevelMember(ClassDeclarationInstruction classDeclaration, } if (name.getWord().equals("class") || name.getWord().equals("super")) { errors.add(new AnalyzeError(name, AnalyzeErrorLevel.ERROR, Error.RESERVED_FIELD, new String[] { name.getWord() })); + } else if (getVersion() >= 3 && isKeyword(name)) { + errors.add(new AnalyzeError(name, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE, new String[] { name.getWord() })); } IAWord word2 = mCompiler.getWord(); if (word2.getType() == WordParser.T_PAR_LEFT) { @@ -788,6 +791,8 @@ public void classStaticMember(ClassDeclarationInstruction classDeclaration, Acce } if (name.getWord().equals("name") || name.getWord().equals("super") || name.getWord().equals("fields") || name.getWord().equals("staticFields") || name.getWord().equals("methods") || name.getWord().equals("staticMethods")) { errors.add(new AnalyzeError(name, AnalyzeErrorLevel.ERROR, Error.RESERVED_FIELD, new String[] { name.getWord() })); + } else if (getVersion() >= 3 && isKeyword(name)) { + errors.add(new AnalyzeError(name, AnalyzeErrorLevel.ERROR, Error.VARIABLE_NAME_UNAVAILABLE, new String[] { name.getWord() })); } classDeclaration.addStaticField(name, expr, accessLevel); @@ -1186,7 +1191,7 @@ public boolean isKeyword(IAWord word) { } public boolean isAvailable(IAWord word, boolean allFunctions) { - if (isKeyword(word)) return false; + if (getVersion() >= 3 && isKeyword(word)) return false; // if(LeekFunctions.isFunction(word) >= 0 || mMain.hasGlobal(word) || // mMain.hasUserFunction(word, allFunctions) || // mCurentBlock.hasVariable(word)) return false; @@ -1196,7 +1201,11 @@ public boolean isAvailable(IAWord word, boolean allFunctions) { } public boolean isGlobalAvailable(IAWord word) { - if (isKeyword(word)) return false; + if (getVersion() <= 2) { + if (word.getWord().equalsIgnoreCase("in") || word.getWord().equalsIgnoreCase("global") || word.getWord().equalsIgnoreCase("var") || word.getWord().equalsIgnoreCase("for") || word.getWord().equalsIgnoreCase("else") || word.getWord().equalsIgnoreCase("if") || word.getWord().equalsIgnoreCase("break") || word.getWord().equalsIgnoreCase("return") || word.getWord().equalsIgnoreCase("do") || word.getWord().equalsIgnoreCase("while") || word.getWord().equalsIgnoreCase("function") || word.getWord().equalsIgnoreCase("true") || word.getWord().equalsIgnoreCase("false") || word.getWord().equalsIgnoreCase("null")) + return false; + } + if (getVersion() >= 3 && isKeyword(word)) return false; // if(LeekFunctions.isFunction(word) >= 0 || mMain.hasUserFunction(word, // false) || mCurentBlock.hasVariable(word)) return false; if (mMain.hasUserFunction(word.getWord(), false) || mCurentBlock.hasVariable(word.getWord())) diff --git a/src/main/java/leekscript/compiler/WordParser.java b/src/main/java/leekscript/compiler/WordParser.java index 0e169c00..817c3d9a 100644 --- a/src/main/java/leekscript/compiler/WordParser.java +++ b/src/main/java/leekscript/compiler/WordParser.java @@ -14,7 +14,7 @@ public class WordParser { public static final String[] reservedWords = new String[] { "abstract", "arguments", "await", "break", "byte", "case", "catch", - "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "eval", + "char", "class", "const", "constructor", "continue", "default", "do", "double", "else", "enum", "eval", "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new", "null", "package", "private", "protected", diff --git a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java index 0813b4f1..4dc249a9 100644 --- a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java @@ -61,9 +61,9 @@ public LeekVariable getVariable(String variable, boolean includeClassMembers) { if (v != null) return v; // Search in fields + if (variable.equals("class")) return new LeekVariable(new IAWord("class"), VariableType.THIS_CLASS); if (!isStatic) { if (variable.equals("this")) return new LeekVariable(new IAWord("this"), VariableType.THIS); - if (variable.equals("class")) return new LeekVariable(new IAWord("class"), VariableType.THIS_CLASS); if (includeClassMembers) { v = clazz.getMember(variable); if (v != null) return v; @@ -99,11 +99,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { super.writeJavaCode(mainblock, writer); if (mEndInstruction == 0) { - if (isStatic) { - writer.addLine("return null;"); - } else { - writer.addLine("return u_this;"); - } + writer.addLine("return null;"); } } diff --git a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java index b3c21c2a..ace06bea 100644 --- a/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java +++ b/src/main/java/leekscript/compiler/bloc/MainLeekBlock.java @@ -58,6 +58,7 @@ public MainLeekBlock(IACompiler compiler, AIFile ai) { if (ai.getVersion() >= 3) { addClass(new ClassDeclarationInstruction(new IAWord("Value"), 0, ai, true)); addClass(new ClassDeclarationInstruction(new IAWord("Null"), 0, ai, true)); + addClass(new ClassDeclarationInstruction(new IAWord("Boolean"), 0, ai, true)); addClass(new ClassDeclarationInstruction(new IAWord("Integer"), 0, ai, true)); addClass(new ClassDeclarationInstruction(new IAWord("Real"), 0, ai, true)); addClass(new ClassDeclarationInstruction(new IAWord("Number"), 0, ai, true)); diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index 5bf6bcc6..eda2cfb4 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -14,7 +14,6 @@ import leekscript.runner.CallableVersion; import leekscript.runner.ILeekFunction; import leekscript.runner.LeekFunctions; -import leekscript.runner.values.ClassLeekValue.ClassMethod; import leekscript.common.AccessLevel; import leekscript.common.Error; import leekscript.common.Type; @@ -87,7 +86,7 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { // Object access : object.field() var object = ((LeekObjectAccess) mExpression).getObject(); var field = ((LeekObjectAccess) mExpression).getField(); - + if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.SUPER) { // super.field() var from_class = writer.currentBlock instanceof ClassMethodBlock ? "u_class" : "null"; @@ -235,14 +234,46 @@ public void analyze(WordCompiler compiler) { if (mExpression instanceof LeekVariable) { var v = (LeekVariable) mExpression; - if (v.getVariableType() == VariableType.METHOD) { // La variable est analysée comme une méthode, mais ça peut être une fonction système, + if (v.getVariableType() == VariableType.METHOD) { // La variable est analysée comme une méthode, mais ça peut être une fonction système, + + // on regarde si le nombre d'arguments est correct + var current = compiler.getCurrentClass(); + while (current != null) { + var methods = current.getMethod(v.getName()); + if (methods != null) { + for (var count : methods.keySet()) { + if (count == mParameters.size()) { + return; // OK + } + } + } + current = current.getParent(); + } + // Est-ce que c'est une fonction système ? + var f = LeekFunctions.getValue(v.getName()); + if (f != null) { + if (mParameters.size() >= f.getArgumentsMin() && mParameters.size() <= f.getArguments()) { + v.setVariableType(VariableType.SYSTEM_FUNCTION); + return; // OK, fonction système + } + } + // Sinon, erreur de méthode + compiler.addError(new AnalyzeError(v.getToken(), AnalyzeErrorLevel.ERROR, Error.INVALID_PARAMETER_COUNT)); + + } else if (v.getVariableType() == VariableType.STATIC_METHOD) { // on regarde si le nombre d'arguments est correct - var methods = compiler.getCurrentClass().getMethod(v.getName()); - for (var count : methods.keySet()) { - if (count == mParameters.size()) { - return; // OK + var current = compiler.getCurrentClass(); + while (current != null) { + var methods = current.getStaticMethod(v.getName()); + if (methods != null) { + for (var count : methods.keySet()) { + if (count == mParameters.size()) { + return; // OK + } + } } + current = current.getParent(); } // Est-ce que c'est une fonction système ? var f = LeekFunctions.getValue(v.getName()); @@ -316,8 +347,8 @@ public void analyze(WordCompiler compiler) { var oa = (LeekObjectAccess) mExpression; if (oa.getObject() instanceof LeekVariable) { var v = (LeekVariable) oa.getObject(); - if (v.getVariableType() == VariableType.CLASS) { - var clazz = v.getClassDeclaration(); + if (v.getVariableType() == VariableType.CLASS || v.getVariableType() == VariableType.THIS_CLASS) { + var clazz = v.getVariableType() == VariableType.CLASS ? v.getClassDeclaration() : compiler.getCurrentClass(); var staticMethod = clazz.getStaticMethod(oa.getField(), mParameters.size()); operations += 1; if (staticMethod == null) { diff --git a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java index 377b14ab..f8885fb6 100644 --- a/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java +++ b/src/main/java/leekscript/compiler/expression/LeekObjectAccess.java @@ -73,18 +73,19 @@ public void analyze(WordCompiler compiler) { if (clazz != null && !clazz.hasMember(field.getWord())) { compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, Error.CLASS_MEMBER_DOES_NOT_EXIST, new String[] { clazz.getName(), field.getWord() })); } - } else if (v.getVariableType() == VariableType.CLASS && v.getClassDeclaration() != null) { + } else if (v.getVariableType() == VariableType.CLASS || v.getVariableType() == VariableType.THIS_CLASS) { + var clazz = v.getVariableType() == VariableType.CLASS ? v.getClassDeclaration() : compiler.getCurrentClass(); operations -= 1; if (field.getWord().equals("name") || field.getWord().equals("super") || field.getWord().equals("fields") || field.getWord().equals("staticFields") || field.getWord().equals("methods") || field.getWord().equals("staticMethods")) { return; // OK } - if (v.getClassDeclaration().hasStaticMember(field.getWord())) { + if (clazz.hasStaticMember(field.getWord())) { return; // OK } - if (v.getClassDeclaration().hasMethod(field.getWord())) { + if (clazz.hasMethod(field.getWord())) { return; // OK } - compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, Error.CLASS_STATIC_MEMBER_DOES_NOT_EXIST, new String[] { v.getClassDeclaration().getName(), field.getWord() })); + compiler.addError(new AnalyzeError(field, AnalyzeErrorLevel.ERROR, Error.CLASS_STATIC_MEMBER_DOES_NOT_EXIST, new String[] { clazz.getName(), field.getWord() })); } } } diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index 8158eddd..7463f8f2 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -182,7 +182,9 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } else if (type == VariableType.STATIC_FIELD) { writer.addCode("u_class.getField(\"" + token.getWord() + "\")"); } else if (type == VariableType.METHOD) { - writer.addCode("###"); + writer.addCode("u_class.getField(\"" + token.getWord() + "\")"); + } else if (type == VariableType.STATIC_METHOD) { + writer.addCode("u_class.getField(\"" + token.getWord() + "\")"); } else if (mainblock.isRedefinedFunction(token.getWord())) { writer.addCode("rfunction_" + token.getWord()); } else if (type == VariableType.FUNCTION) { diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 79fc641c..1bd9ed3c 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -17,7 +17,6 @@ import leekscript.compiler.expression.AbstractExpression; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; -import leekscript.runner.values.ClassLeekValue.ClassMethod; import leekscript.common.AccessLevel; import leekscript.common.Error; @@ -365,9 +364,6 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addCode(", Object u_" + arg); } } - // if (construct.getValue().getParameters().size() == 0) { - // writer.addCode(", Object __"); - // } writer.addCode(") throws LeekRunException {"); writer.addLine("final var u_class = " + className + ";"); if (parent != null) { @@ -376,7 +372,7 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { if (construct.getValue().block != null) { construct.getValue().block.writeJavaCode(mainblock, writer); } else { - writer.addLine("return u_this;"); + writer.addLine("return null;"); } writer.addLine("}"); writer.currentBlock = null; @@ -440,14 +436,14 @@ public void createJava(MainLeekBlock mainblock, JavaWriter writer) { for (var construct : constructors.entrySet()) { String methodName = className + "_" + construct.getKey(); writer.addCode(className); - writer.addCode(".addConstructor(" + construct.getKey() + ", new LeekAnonymousFunction() { public Object run(ObjectLeekValue thiz, Object... args) throws LeekRunException { return " + methodName + "(thiz"); + writer.addCode(".addConstructor(" + construct.getKey() + ", new LeekAnonymousFunction() { public Object run(ObjectLeekValue thiz, Object... args) throws LeekRunException { " + methodName + "(thiz"); int i = 0; if (construct.getValue().block != null) { for (var a = 0; a < construct.getValue().block.getParameters().size(); ++a) { writer.addCode(", args[" + i++ + "]"); } } - writer.addLine("); }}, AccessLevel." + construct.getValue().level + ");"); + writer.addLine("); return thiz; }}, AccessLevel." + construct.getValue().level + ");"); } for (var method : methods.entrySet()) { @@ -569,6 +565,10 @@ public String getMethodName(String name, int argumentCount) { return null; } + public HashMap getStaticMethod(String name) { + return staticMethods.get(name); + } + public String getStaticMethodName(String name, int argumentCount) { var versions = staticMethods.get(name); if (versions != null) { diff --git a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java index 3652ad2f..e1730a63 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekReturnInstruction.java @@ -31,7 +31,11 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { } else { if (mExpression.getOperations() > 0) writer.addCode("ops("); var finalExpression = mExpression.trim(); - finalExpression.compileL(mainblock, writer); + if (mainblock.getWordCompiler().getVersion() == 1) { + finalExpression.compileL(mainblock, writer); + } else { + finalExpression.writeJavaCode(mainblock, writer); + } if (finalExpression.getOperations() > 0) writer.addCode(", " + finalExpression.getOperations() + ")"); writer.addLine(";", mLine, mAI); } diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 374777a6..863dca0f 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -82,8 +82,8 @@ public AI(int instructions, int version) { nullClass = new ClassLeekValue(this, "Null", valueClass); booleanClass = new ClassLeekValue(this, "Boolean", valueClass); numberClass = new ClassLeekValue(this, "Number", valueClass); - integerClass = new ClassLeekValue(this, "Integer", numberClass); - realClass= new ClassLeekValue(this, "Real", numberClass); + realClass = new ClassLeekValue(this, "Real", numberClass); + integerClass = new ClassLeekValue(this, "Integer", realClass); arrayClass = new ClassLeekValue(this, "Array", valueClass); stringClass = new ClassLeekValue(this, "String", valueClass); objectClass = new ClassLeekValue(this, "Object", valueClass); @@ -1226,6 +1226,7 @@ public Object toJSON(Object v) throws LeekRunException { public boolean isPrimitive(Object value) { return !(value instanceof ArrayLeekValue || value instanceof ObjectLeekValue); } + public boolean isIterable(Object value) throws LeekRunException { boolean ok = value instanceof ArrayLeekValue; if (!ok) { @@ -1233,6 +1234,7 @@ public boolean isIterable(Object value) throws LeekRunException { } return ok; } + public boolean getBooleanTernary(Object value) throws LeekRunException { ops(1); return bool(value); @@ -1256,7 +1258,8 @@ public Object setField(Object object, String field, Object value) throws LeekRun if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).setField(field, value); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_inc(Object object, String field) throws LeekRunException { @@ -1266,7 +1269,8 @@ public Object field_inc(Object object, String field) throws LeekRunException { if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).increment(); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_pre_inc(Object object, String field) throws LeekRunException { @@ -1276,7 +1280,8 @@ public Object field_pre_inc(Object object, String field) throws LeekRunException if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).pre_increment(); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_dec(Object object, String field) throws LeekRunException { @@ -1286,7 +1291,8 @@ public Object field_dec(Object object, String field) throws LeekRunException { if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).decrement(); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_pre_dec(Object object, String field) throws LeekRunException { @@ -1296,7 +1302,8 @@ public Object field_pre_dec(Object object, String field) throws LeekRunException if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).pre_decrement(); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_add_eq(Object object, String field, Object value) throws LeekRunException { @@ -1306,7 +1313,8 @@ public Object field_add_eq(Object object, String field, Object value) throws Lee if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).add_eq(value); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_sub_eq(Object object, String field, Object value) throws LeekRunException { @@ -1316,7 +1324,8 @@ public Object field_sub_eq(Object object, String field, Object value) throws Lee if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).sub_eq(value); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_mul_eq(Object object, String field, Object value) throws LeekRunException { @@ -1326,7 +1335,8 @@ public Object field_mul_eq(Object object, String field, Object value) throws Lee if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).mul_eq(value); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_pow_eq(Object object, String field, Object value) throws LeekRunException { @@ -1336,7 +1346,8 @@ public Object field_pow_eq(Object object, String field, Object value) throws Lee if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).pow_eq(value); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_div_eq(Object object, String field, Object value) throws LeekRunException { @@ -1346,7 +1357,8 @@ public Object field_div_eq(Object object, String field, Object value) throws Lee if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).div_eq(value); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_mod_eq(Object object, String field, Object value) throws LeekRunException { @@ -1356,7 +1368,8 @@ public Object field_mod_eq(Object object, String field, Object value) throws Lee if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).mod_eq(value); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_bor_eq(Object object, String field, Object value) throws LeekRunException { @@ -1366,7 +1379,8 @@ public Object field_bor_eq(Object object, String field, Object value) throws Lee if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).bor_eq(value); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_band_eq(Object object, String field, Object value) throws LeekRunException { @@ -1376,7 +1390,8 @@ public Object field_band_eq(Object object, String field, Object value) throws Le if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).band_eq(value); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_bxor_eq(Object object, String field, Object value) throws LeekRunException { @@ -1386,7 +1401,8 @@ public Object field_bxor_eq(Object object, String field, Object value) throws Le if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).bxor_eq(value); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_shl_eq(Object object, String field, Object value) throws LeekRunException { @@ -1396,7 +1412,8 @@ public Object field_shl_eq(Object object, String field, Object value) throws Lee if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).shl_eq(value); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_shr_eq(Object object, String field, Object value) throws LeekRunException { @@ -1406,7 +1423,8 @@ public Object field_shr_eq(Object object, String field, Object value) throws Lee if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).shr_eq(value); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object field_ushr_eq(Object object, String field, Object value) throws LeekRunException { @@ -1416,7 +1434,8 @@ public Object field_ushr_eq(Object object, String field, Object value) throws Le if (object instanceof ClassLeekValue) { return ((ClassLeekValue) object).getFieldL(field).ushr_eq(value); } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(object), field }); + return null; } public Object put(Object array, Object key, Object value) throws LeekRunException { @@ -1431,6 +1450,7 @@ public Object put(Object array, Object key, Object value) throws LeekRunExceptio var field = string(key); return ((ClassLeekValue) array).setField(field, value); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } @@ -1438,10 +1458,15 @@ public Object put_inc(Object array, Object key) throws LeekRunException { if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_inc(this, key); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_inc(field); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_inc(field); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1449,10 +1474,15 @@ public Object put_pre_inc(Object array, Object key) throws LeekRunException { if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_pre_inc(this, key); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_pre_inc(field); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_pre_inc(field); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1460,10 +1490,15 @@ public Object put_dec(Object array, Object key) throws LeekRunException { if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_dec(this, key); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_dec(field); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_dec(field); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1471,10 +1506,15 @@ public Object put_pre_dec(Object array, Object key) throws LeekRunException { if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_pre_dec(this, key); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_pre_dec(field); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_pre_dec(field); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1482,10 +1522,15 @@ public Object put_add_eq(Object array, Object key, Object value) throws LeekRunE if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_add_eq(this, key, value); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_add_eq(field, value); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_add_eq(field, value); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } @@ -1493,20 +1538,31 @@ public Object put_sub_eq(Object array, Object key, Object value) throws LeekRunE if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_sub_eq(this, key, value); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_sub_eq(field, value); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_sub_eq(field, value); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } + public Object put_mul_eq(Object array, Object key, Object value) throws LeekRunException { if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_mul_eq(this, key, value); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_mul_eq(field, value); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_mul_eq(field, value); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } @@ -1514,10 +1570,15 @@ public Object put_pow_eq(Object array, Object key, Object value) throws LeekRunE if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_pow_eq(this, key, value); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_pow_eq(field, value); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_pow_eq(field, value); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } @@ -1525,10 +1586,15 @@ public Object put_mod_eq(Object array, Object key, Object value) throws LeekRunE if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_mod_eq(this, key, value); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_mod_eq(field, value); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_mod_eq(field, value); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } @@ -1536,34 +1602,47 @@ public Object put_div_eq(Object array, Object key, Object value) throws LeekRunE if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_div_eq(this, key, value); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_div_eq(field, value); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_div_eq(field, value); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } - public Object put_bor_eq(Object array, Object key, Object value) throws LeekRunException { if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_bor_eq(this, key, value); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_bor_eq(field, value); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_bor_eq(field, value); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } - public Object put_band_eq(Object array, Object key, Object value) throws LeekRunException { if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_band_eq(this, key, value); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_band_eq(field, value); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_band_eq(field, value); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } @@ -1571,10 +1650,15 @@ public Object put_shl_eq(Object array, Object key, Object value) throws LeekRunE if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_shl_eq(this, key, value); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_shl_eq(field, value); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_shl_eq(field, value); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } @@ -1582,10 +1666,15 @@ public Object put_shr_eq(Object array, Object key, Object value) throws LeekRunE if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_shr_eq(this, key, value); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_shr_eq(field, value); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_shr_eq(field, value); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } @@ -1593,10 +1682,15 @@ public Object put_ushr_eq(Object array, Object key, Object value) throws LeekRun if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_ushr_eq(this, key, value); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_ushr_eq(field, value); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_ushr_eq(field, value); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } @@ -1604,10 +1698,15 @@ public Object put_bxor_eq(Object array, Object key, Object value) throws LeekRun if (array instanceof ArrayLeekValue) { return ((ArrayLeekValue) array).put_bxor_eq(this, key, value); } + if (array instanceof ObjectLeekValue) { + var field = string(key); + return ((ObjectLeekValue) array).field_bxor_eq(field, value); + } if (array instanceof ClassLeekValue) { - // var field = string(key); - // return ((ClassLeekValue) array).getField(field), value); + var field = string(key); + return ((ClassLeekValue) array).field_bxor_eq(field, value); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } @@ -1626,6 +1725,11 @@ public Object get(Object value, Object index, ClassLeekValue fromClass) throws L ops(1); return ((ObjectLeekValue) value).getField(string(index), fromClass); } + if (value instanceof ClassLeekValue) { + ops(1); + return ((ClassLeekValue) value).getField(string(index)); + } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } @@ -1633,6 +1737,7 @@ public Box getBox(Object value, Object index) throws LeekRunException { if (value instanceof ArrayLeekValue) { return ((ArrayLeekValue) value).getBox(this, index); } + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } @@ -1647,22 +1752,23 @@ public Object callMethod(Object value, String method, ClassLeekValue fromClass, } public Object callObjectAccess(Object value, String field, String method, ClassLeekValue fromClass, Object... args) throws LeekRunException { + if (value instanceof ClassLeekValue) { + return ((ClassLeekValue) value).callMethod(method, fromClass, args); + } if (value instanceof ObjectLeekValue) { return ((ObjectLeekValue) value).callAccess(field, method, fromClass, args); } + addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(value), field }); return null; } public Object execute(Object function, Object... args) throws LeekRunException { - if (function instanceof FunctionLeekValue) { - return ((FunctionLeekValue) function).execute(this, args); - } - if (function == arrayClass) { - return new ArrayLeekValue(); - } if (function instanceof ClassLeekValue) { return ((ClassLeekValue) function).execute(args); } + if (function instanceof FunctionLeekValue) { + return ((FunctionLeekValue) function).execute(this, args); + } addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_VALUE, new String[] { string(function) }); return null; } @@ -1738,7 +1844,8 @@ public boolean instanceOf(Object value, Object clazz) throws LeekRunException { return false; } var v = load(value); - if (v instanceof ObjectLeekValue && ((ObjectLeekValue) v).getClazz().descendsFrom((ClassLeekValue) clazz)) { + var vClass = getClass(v); + if (vClass.descendsFrom((ClassLeekValue) clazz)) { return true; } return false; diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 32ecd6b3..160b55f2 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -1,5 +1,6 @@ package leekscript.runner; +import java.util.regex.Matcher; import java.util.regex.Pattern; import leekscript.AILog; @@ -323,7 +324,7 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le String s = LeekValueManager.getString(ai, parameters[0]); String pattern = LeekValueManager.getString(ai, parameters[1]); String replacement = LeekValueManager.getString(ai, parameters[2]); - return s.replaceAll(Pattern.quote(pattern), replacement); + return s.replaceAll(Pattern.quote(pattern), Matcher.quoteReplacement(replacement)); } @Override diff --git a/src/main/java/leekscript/runner/LeekRunException.java b/src/main/java/leekscript/runner/LeekRunException.java index f33e4562..36757e5c 100644 --- a/src/main/java/leekscript/runner/LeekRunException.java +++ b/src/main/java/leekscript/runner/LeekRunException.java @@ -10,7 +10,6 @@ public class LeekRunException extends Exception { public final static int ARRAY_EMPTY = 2; public final static int INVALID_INDEX = 3; public final static int UNKNOWN_FUNCTION = 4; - public final static int INVALID_OPERATOR = 5; public final static int INVALID_LEVEL = 6; public final static int OUT_OF_MEMORY = 7; public final static int UNKNOWN_FIELD = 8; @@ -38,8 +37,6 @@ public String getMessage() { return "Erreur d'exécution : Indice invalide"; case UNKNOWN_FUNCTION: return "Erreur d'exécution : Fonction inconnue"; - case INVALID_OPERATOR: - return "Erreur d'exécution : Impossible d'utiliser cet opérateur"; case INVALID_LEVEL: return "Erreur d'exécution : Niveau invalide"; case OUT_OF_MEMORY: diff --git a/src/main/java/leekscript/runner/LeekValueManager.java b/src/main/java/leekscript/runner/LeekValueManager.java index 1449932f..b66d798f 100644 --- a/src/main/java/leekscript/runner/LeekValueManager.java +++ b/src/main/java/leekscript/runner/LeekValueManager.java @@ -52,7 +52,8 @@ public static Object parseJSON(Object o, AI ai) throws LeekRunException { return o; } if (o instanceof BigInteger) { - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + ai.addSystemLog(AILog.ERROR, Error.INVALID_OPERATOR, new String[] { "jsonDecode(" + LeekValueManager.getString(ai, o) + ")" }); + return null; } if (o instanceof BigDecimal) { return ((BigDecimal) o).doubleValue(); diff --git a/src/main/java/leekscript/runner/values/Box.java b/src/main/java/leekscript/runner/values/Box.java index 90e144d6..45761644 100644 --- a/src/main/java/leekscript/runner/values/Box.java +++ b/src/main/java/leekscript/runner/values/Box.java @@ -1,9 +1,11 @@ package leekscript.runner.values; +import leekscript.AILog; import leekscript.runner.AI; import leekscript.runner.LeekOperations; import leekscript.runner.LeekRunException; import leekscript.runner.LeekValueManager; +import leekscript.common.Error; public class Box { @@ -67,7 +69,6 @@ public void initGlobal(Object value) throws LeekRunException { } public Object increment() throws LeekRunException { - // mUAI.ops(1); if (mValue instanceof Integer) { int value = (Integer) mValue; mValue = value + 1; @@ -78,12 +79,11 @@ public Object increment() throws LeekRunException { mValue = value + 1; return value; } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); - // ai.addSystemLog(AILog.ERROR, Error.INVALID_OPERATOR, new String[] { LeekValueManager.getString(ai, mValue), "++" }); + mUAI.addSystemLog(AILog.ERROR, Error.INVALID_OPERATOR, new String[] { LeekValueManager.getString(mUAI, mValue), "++" }); + return null; } public Object decrement() throws LeekRunException { - // mUAI.ops(1); if (mValue instanceof Integer) { int value = (Integer) mValue; mValue = value - 1; @@ -94,29 +94,30 @@ public Object decrement() throws LeekRunException { mValue = value - 1; return value; } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + mUAI.addSystemLog(AILog.ERROR, Error.INVALID_OPERATOR, new String[] { LeekValueManager.getString(mUAI, mValue) + "--" }); + return null; } public Object pre_increment() throws LeekRunException { - // mUAI.ops(1); if (mValue instanceof Integer) { return mValue = (Integer) mValue + 1; } if (mValue instanceof Double) { return mValue = (Double) mValue + 1; } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + mUAI.addSystemLog(AILog.ERROR, Error.INVALID_OPERATOR, new String[] { "++" + LeekValueManager.getString(mUAI, mValue) }); + return null; } public Object pre_decrement() throws LeekRunException { - // mUAI.ops(1); if (mValue instanceof Integer) { return mValue = (Integer) mValue - 1; } if (mValue instanceof Double) { return mValue = (Double) mValue - 1; } - throw new LeekRunException(LeekRunException.INVALID_OPERATOR); + mUAI.addSystemLog(AILog.ERROR, Error.INVALID_OPERATOR, new String[] { "--" + LeekValueManager.getString(mUAI, mValue) }); + return null; } public Object not() throws LeekRunException { diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index 55276b6f..b0b09c37 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -1,6 +1,5 @@ package leekscript.runner.values; -import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; @@ -193,131 +192,83 @@ public Object setField(String field, Object value) throws LeekRunException { } public Object field_inc(String field) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.increment(); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.increment(); } public Object field_pre_inc(String field) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.pre_increment(); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.pre_increment(); } public Object field_dec(String field) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.decrement(); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.decrement(); } public Object field_pre_dec(String field) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.pre_decrement(); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.pre_decrement(); } public Object field_add_eq(String field, Object value) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.add_eq(value); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.add_eq(value); } public Object field_sub_eq(String field, Object value) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.sub_eq(value); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.sub_eq(value); } public Object field_mul_eq(String field, Object value) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.mul_eq(value); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.mul_eq(value); } public Object field_pow_eq(String field, Object value) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.pow_eq(value); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.pow_eq(value); } public Object field_div_eq(String field, Object value) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.div_eq(value); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.div_eq(value); } public Object field_mod_eq(String field, Object value) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.mod_eq(value); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.mod_eq(value); } public Object field_bor_eq(String field, Object value) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.bor_eq(value); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.bor_eq(value); } public Object field_bxor_eq(String field, Object value) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.bxor_eq(value); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.bxor_eq(value); } public Object field_band_eq(String field, Object value) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.band_eq(value); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.band_eq(value); } public Object field_shl_eq(String field, Object value) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.shl_eq(value); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.shl_eq(value); } public Object field_shr_eq(String field, Object value) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.shr_eq(value); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.shr_eq(value); } public Object field_ushr_eq(String field, Object value) throws LeekRunException { - var result = staticFields.get(field); - if (result != null) { - return result.ushr_eq(value); - } - throw new LeekRunException(LeekRunException.UNKNOWN_FIELD); + var result = getFieldL(field); + return result.ushr_eq(value); } public Object callMethod(String method, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { @@ -357,6 +308,18 @@ public static String createMethodError(String method) { * Constructors */ public Object execute(Object... arguments) throws LeekRunException { + if (this == ai.valueClass || this == ai.jsonClass || this == ai.systemClass || this == ai.functionClass || this == ai.classClass) { + ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_CONSTRUCTOR, new String[] { name, String.valueOf(arguments.length) }); + return null; + } + if (this == ai.nullClass) return null; + if (this == ai.booleanClass) return false; + if (this == ai.integerClass) return 0; + if (this == ai.realClass || this == ai.numberClass) return 0.0; + if (this == ai.stringClass) return ""; + if (this == ai.arrayClass) return new ArrayLeekValue(); + if (this == ai.objectClass) return new ObjectLeekValue(ai.objectClass); + // Create the actual object ai.ops(1); ObjectLeekValue object = new ObjectLeekValue(this); @@ -367,7 +330,8 @@ public Object execute(Object... arguments) throws LeekRunException { int arg_count = arguments.length; if (constructors.containsKey(arg_count)) { - return constructors.get(arg_count).value.run(object, arguments); + constructors.get(arg_count).value.run(object, arguments); + return object; } else { if (arg_count > 0) { ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_CONSTRUCTOR, new String[] { name, String.valueOf(arguments.length) }); diff --git a/src/main/java/leekscript/runner/values/FunctionLeekValue.java b/src/main/java/leekscript/runner/values/FunctionLeekValue.java index 99a36c27..8220407b 100644 --- a/src/main/java/leekscript/runner/values/FunctionLeekValue.java +++ b/src/main/java/leekscript/runner/values/FunctionLeekValue.java @@ -121,6 +121,8 @@ else if (mType == USER_FUNCTION) { } else if (mType == METHOD) { if (values.length == 0) { ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { LeekValue.getParamString(values), "1+" }); + } else if (!(values[0] instanceof ObjectLeekValue)) { + ai.addSystemLog(AILog.ERROR, Error.CAN_NOT_EXECUTE_WITH_ARGUMENTS, new String[] { LeekValue.getParamString(values), "object" }); } else { return mAnonymous.run((ObjectLeekValue) values[0], Arrays.copyOfRange(values, 1, values.length)); } diff --git a/src/main/java/leekscript/runner/values/ObjectLeekValue.java b/src/main/java/leekscript/runner/values/ObjectLeekValue.java index 277c494d..7d0a7938 100644 --- a/src/main/java/leekscript/runner/values/ObjectLeekValue.java +++ b/src/main/java/leekscript/runner/values/ObjectLeekValue.java @@ -99,11 +99,14 @@ public Object setField(String field, Object value) throws LeekRunException { // Pour un objet anonyme (classe Object), on peut rajouter des proprietés à la volée if (result == null && clazz == clazz.ai.objectClass) { addField(clazz.ai, field, value, AccessLevel.PUBLIC); + return value; } if (result != null) { result.set(value); + return value; } - return value; + clazz.ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { clazz.name, field }); + return null; } public Object field_inc(String field) throws LeekRunException { @@ -239,22 +242,56 @@ public Box getOrCreate(AI ai, Object value) throws LeekRunException { } public Object callAccess(String field, String method, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { - var result = fields.get(field); - if (result != null) { - // Private : Access from same class - if (result.level == AccessLevel.PRIVATE && fromClass != clazz) { - clazz.ai.addSystemLog(AILog.ERROR, Error.PRIVATE_FIELD, new String[] { clazz.name, field }); - return null; + var resultM = clazz.getMethod(clazz.ai, method, fromClass); + if (resultM == null) { + if (method.equals("keys_0")) { + String[] values = new String[fields.size()]; + int i = 0; + for (var key : fields.keySet()) { + values[i++] = key; + } + return new ArrayLeekValue(clazz.ai, values); } - // Protected : Access from descendant - if (result.level == AccessLevel.PROTECTED && (fromClass != clazz && !clazz.descendsFrom(fromClass))) { - clazz.ai.addSystemLog(AILog.ERROR, result.level == AccessLevel.PROTECTED ? Error.PROTECTED_FIELD : Error.PRIVATE_FIELD, new String[] { clazz.name, field }); - return null; + if (method.equals("values_0")) { + Object[] values = new Object[fields.size()]; + int i = 0; + for (var value : fields.values()) { + values[i++] = value; + } + return new ArrayLeekValue(clazz.ai, values); } - // Call the value - return clazz.ai.execute(result.mValue, arguments); } - return callMethod(method, fromClass, arguments); + if (resultM == null) { + var result = fields.get(field); + if (result != null) { + // Private : Access from same class + if (result.level == AccessLevel.PRIVATE && fromClass != clazz) { + clazz.ai.addSystemLog(AILog.ERROR, Error.PRIVATE_FIELD, new String[] { clazz.name, field }); + return null; + } + // Protected : Access from descendant + if (result.level == AccessLevel.PROTECTED && (fromClass != clazz && !clazz.descendsFrom(fromClass))) { + clazz.ai.addSystemLog(AILog.ERROR, result.level == AccessLevel.PROTECTED ? Error.PROTECTED_FIELD : Error.PRIVATE_FIELD, new String[] { clazz.name, field }); + return null; + } + // Call the value + return clazz.ai.execute(result.mValue, arguments); + } + // Pas de méthode + int underscore = method.lastIndexOf("_"); + int argCount = Integer.parseInt(method.substring(underscore + 1)); + String methodRealName = method.substring(0, underscore) + "("; + for (int i = 0; i < argCount; ++i) { + if (i > 0) methodRealName += ", "; + methodRealName += "x"; + } + methodRealName += ")"; + clazz.ai.addSystemLog(AILog.ERROR, Error.UNKNOWN_METHOD, new String[] { clazz.name, methodRealName }); + return null; + } + + // Call method with new arguments, add the object at the beginning + return resultM.run(this, arguments); } public Object callMethod(String method, ClassLeekValue fromClass, Object... arguments) throws LeekRunException { diff --git a/src/test/java/test/TestArray.java b/src/test/java/test/TestArray.java index 0f8a2097..c8559a8b 100644 --- a/src/test/java/test/TestArray.java +++ b/src/test/java/test/TestArray.java @@ -129,6 +129,7 @@ public void run() throws Exception { code("var a = [] return a[0] + 2").equals("2"); code("var a = 5 return a[0] + 2").equals("2"); code("var a = [1] return a[0] = 10").equals("10"); + code("var a = null return a[0]").equals("null"); section("[] operator on unknown arrays"); code("var v = [['a', 'b'], 12] return v[0][0]").equals("a"); diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index 8888d9bc..d1458d51 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -63,6 +63,23 @@ public void run() { } } + section("Globals with keywords"); + code_v1_2("global break = 2").error(Error.VARIABLE_NAME_UNAVAILABLE); + for (var word : WordParser.reservedWords) { + if (word.equals("this")) { + code_v3_("global " + word + " = 2;").error(Error.VARIABLE_NAME_UNAVAILABLE); + } else if (word.equals("instanceof")) { + code_v3_("global " + word + " = 2;").error(Error.VAR_NAME_EXPECTED); + } else if (word.equals("function")) { + code_v3_("global " + word + " = 2;").error(Error.OPENING_PARENTHESIS_EXPECTED); + } else { + code_v3_("global " + word + " = 2;").error(Error.VARIABLE_NAME_UNAVAILABLE); + } + } + + code_v1("var new = 12 var b = @new return b").equals("12"); + code_v1("global final = 2").error(Error.NONE); + section("Type changes"); code("var a return a = 12").equals("12"); code("var a a = 12 return a").equals("12"); diff --git a/src/test/java/test/TestGlobals.java b/src/test/java/test/TestGlobals.java index c6b0b16f..66b89feb 100644 --- a/src/test/java/test/TestGlobals.java +++ b/src/test/java/test/TestGlobals.java @@ -1,7 +1,5 @@ package test; -import leekscript.common.Error; - public class TestGlobals extends TestCommon { public void run() throws Exception { diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 7252eb33..1af54895 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -39,6 +39,19 @@ public void run() { code_v2_("class A { a = 10 m() { return a } } var a = new A(); var array = [a.m] return array[0](a)").equals("10"); code_v2_("class A { a = 10 m() { return a } } var a = new A(); var array = [a['m']] return array[0](a)").equals("10"); + section("Reserved fields"); + code_v2("class A { for while if var this }").error(Error.NONE); + code_v3_("class A { for }").error(Error.VARIABLE_NAME_UNAVAILABLE); + code_v3_("class A { if }").error(Error.VARIABLE_NAME_UNAVAILABLE); + code_v3_("class A { while }").error(Error.VARIABLE_NAME_UNAVAILABLE); + code_v3_("class A { var }").error(Error.VARIABLE_NAME_UNAVAILABLE); + code_v3_("class A { this }").error(Error.VARIABLE_NAME_UNAVAILABLE); + + section("Constructors"); + code_v2_("class A {} var a = new A() return a").equals("A {}"); + code_v2_("class A { constructor() {} } var a = new A() return a").equals("A {}"); + code_v2_("class A { constructor() { return; } } var a = new A() return a").equals("A {}"); + section("Static fields"); code_v2_("class A { static x }").equals("null"); code_v2_("class A { static x } return A.x").equals("null"); @@ -47,6 +60,16 @@ public void run() { code_v2_("class A { static x = [1, 2, 3] } return A.x").equals("[1, 2, 3]"); code_v2_("class A { static x = null } return A.x").equals("null"); code_v2_("class Affiche { static COULEUR = getColor(42, 125, 78) } return Affiche.COULEUR").equals("2784590"); + code_v2_("class A { static b } A.c").error(Error.CLASS_STATIC_MEMBER_DOES_NOT_EXIST); + code_v2_("class A { static b static m() { class.c } }").error(Error.CLASS_STATIC_MEMBER_DOES_NOT_EXIST); + + section("Reserved static fields"); + code_v2("class A { static for static while static if static var static this }").error(Error.NONE); + code_v3_("class A { static for }").error(Error.VARIABLE_NAME_UNAVAILABLE); + code_v3_("class A { static if }").error(Error.VARIABLE_NAME_UNAVAILABLE); + code_v3_("class A { static while }").error(Error.VARIABLE_NAME_UNAVAILABLE); + code_v3_("class A { static var }").error(Error.VARIABLE_NAME_UNAVAILABLE); + code_v3_("class A { static this }").error(Error.VARIABLE_NAME_UNAVAILABLE); section("Operators on field"); code_v2_("class A { a = 10 } var a = new A(); return --a.a").equals("9"); @@ -120,6 +143,35 @@ public void run() { code_v2_("class A { static a = 10 static m() { return a >>= 5 } } return A.m()").equals("0"); code_v2_("class A { static a = 10 static m() { return a >>>= 5 } } return A.m()").equals("0"); + section("Operators on static field in method with class."); + code_v2_("class A { static a = 10 static m() { return --class.a } } return A.m()").equals("9"); + code_v2_("class A { static a = 10 static m() { class.a-- return class.a } } return A.m()").equals("9"); + code_v2_("class A { static a = 10 static m() { return ++class.a } } return A.m()").equals("11"); + code_v2_("class A { static a = 10 static m() { class.a++ return class.a } } return A.m()").equals("11"); + code_v2_("class A { static a = 10 static m() { return class.a += 5 } } return A.m()").equals("15"); + code_v2_("class A { static a = 10 static m() { return class.a -= 5 } } return A.m()").equals("5"); + code_v2_("class A { static a = 10 static m() { return class.a *= 5 } } return A.m()").equals("50"); + code_v2_("class A { static a = 10 static m() { return class.a /= 5 } } return A.m()").equals("2.0"); + code_v2_("class A { static a = 10 static m() { return class.a %= 5 } } return A.m()").equals("0"); + code_v2_("class A { static a = 10 static m() { return class.a **= 5 } } return A.m()").equals("100000"); + code_v2_("class A { static a = 10 static m() { return class.a |= 5 } } return A.m()").equals("15"); + code_v2_("class A { static a = 10 static m() { return class.a &= 5 } } return A.m()").equals("0"); + code_v2_("class A { static a = 10 static m() { return class.a ^= 5 } } return A.m()").equals("15"); + code_v2_("class A { static a = 10 static m() { return class.a <<= 5 } } return A.m()").equals("320"); + code_v2_("class A { static a = 10 static m() { return class.a >>= 5 } } return A.m()").equals("0"); + code_v2_("class A { static a = 10 static m() { return class.a >>>= 5 } } return A.m()").equals("0"); + + section("Static methods"); + code_v2_("class A { static a() { return 12 } } return A.a()").equals("12"); + code_v2_("class A { static a(x) { return 12 } } return A.a()").error(Error.UNKNOWN_STATIC_METHOD); + code_v2_("class A { static a() { return 12 } } return A.b()").error(Error.CLASS_STATIC_MEMBER_DOES_NOT_EXIST); + code_v2_("class A { static f(x) {} static g() { f(1) } }").error(Error.NONE); + code_v2_("class A { static f(x) {} static g() { f() } }").error(Error.INVALID_PARAMETER_COUNT); + + section("Static method calls with with class."); + code_v2_("class A { static m() { return 'x' } t() { return class.m() } } var a = new A() return a.t()").equals("x"); + code_v2_("class A { static m() { return 'x' } t() { return class.zz() } } var a = new A() return a.t()").error(Error.CLASS_STATIC_MEMBER_DOES_NOT_EXIST); + section("Field access by array access"); code_v2_("var test = {} test['a'] = 8 return test").equals("{a: 8}"); code_v2_("var test = {} test['a'] = 8 test['b'] = 12 return test").equals("{a: 8, b: 12}"); @@ -127,9 +179,47 @@ public void run() { code_v2_("class Test { a b c } var test2 = new Test() for (var field in Test.fields) { test2[field] = 8 } return test2").equals("Test {a: 8, b: 8, c: 8}"); code_v2_("class Test { a b c constructor(a, b, c) { this.a = a this.b = b this.c = c } } var test1 = new Test(1, 2, 3) var test2 = new Test() for (var field in test1.class.fields) { test2[field] = test1[field] } return test2").equals("Test {a: 1, b: 2, c: 3}"); code_v2_("class Test { a b c constructor(a, b, c) { this.a = a this.b = b this.c = c } } var test1 = new Test(1, 2, 3) var test2 = new Test() for (var field in test2.class.fields) { test2[field] = test1[field] } return test2").equals("Test {a: 1, b: 2, c: 3}"); + code_v2_("class A { a = 6 m() { return this['a'] } } return new A().m()").equals("6"); + + section("Operators on field by array access"); + code_v2_("class A { a = 10 } var a = new A(); return --a['a']").equals("9"); + code_v2_("class A { a = 10 } var a = new A(); a['a']-- return a['a']").equals("9"); + code_v2_("class A { a = 10 } var a = new A(); return ++a['a']").equals("11"); + code_v2_("class A { a = 10 } var a = new A(); a['a']++ return a['a']").equals("11"); + code_v2_("class A { a = 10 } var a = new A(); return a['a'] += 5").equals("15"); + code_v2_("class A { a = 10 } var a = new A(); return a['a'] -= 5").equals("5"); + code_v2_("class A { a = 10 } var a = new A(); return a['a'] *= 5").equals("50"); + code_v2_("class A { a = 10 } var a = new A(); return a['a'] /= 5").equals("2.0"); + code_v2_("class A { a = 10 } var a = new A(); return a['a'] %= 5").equals("0"); + code_v2_("class A { a = 10 } var a = new A(); return a['a'] **= 5").equals("100000"); + code_v2_("class A { a = 10 } var a = new A(); return a['a'] |= 5").equals("15"); + code_v2_("class A { a = 10 } var a = new A(); return a['a'] &= 5").equals("0"); + code_v2_("class A { a = 10 } var a = new A(); return a['a'] ^= 5").equals("15"); + code_v2_("class A { a = 10 } var a = new A(); return a['a'] <<= 5").equals("320"); + code_v2_("class A { a = 10 } var a = new A(); return a['a'] >>= 5").equals("0"); + code_v2_("class A { a = 10 } var a = new A(); return a['a'] >>>= 5").equals("0"); section("Static field access by array access"); code_v2_("class Test { static a static b static c } Test['a'] = 12 Test['b'] = 15 Test['c'] = 20 return [Test.a, Test.b, Test.c]").equals("[12, 15, 20]"); + code_v2_("class A { static a = 6 static m() { return class['a'] } } return A.m()").equals("6"); + + section("Operators on static field by array access"); + code_v2_("class A { static a = 10 } return --A['a']").equals("9"); + code_v2_("class A { static a = 10 } A['a']-- return A['a']").equals("9"); + code_v2_("class A { static a = 10 } return ++A['a']").equals("11"); + code_v2_("class A { static a = 10 } A['a']++ return A['a']").equals("11"); + code_v2_("class A { static a = 10 } return A['a'] += 5").equals("15"); + code_v2_("class A { static a = 10 } return A['a'] -= 5").equals("5"); + code_v2_("class A { static a = 10 } return A['a'] *= 5").equals("50"); + code_v2_("class A { static a = 10 } return A['a'] /= 5").equals("2.0"); + code_v2_("class A { static a = 10 } return A['a'] %= 5").equals("0"); + code_v2_("class A { static a = 10 } return A['a'] **= 5").equals("100000"); + code_v2_("class A { static a = 10 } return A['a'] |= 5").equals("15"); + code_v2_("class A { static a = 10 } return A['a'] &= 5").equals("0"); + code_v2_("class A { static a = 10 } return A['a'] ^= 5").equals("15"); + code_v2_("class A { static a = 10 } return A['a'] <<= 5").equals("320"); + code_v2_("class A { static a = 10 } return A['a'] >>= 5").equals("0"); + code_v2_("class A { static a = 10 } return A['a'] >>>= 5").equals("0"); section("Inheritance"); code_v2_("class A { x = 10 } class B extends A {} var a = new B() return a.x").equals("10"); @@ -144,6 +234,7 @@ public void run() { code_v2_("class A { m() { return 'parent' } t() { return this.m() } } class B extends A { m() { return 'enfant' } } return new B().t()").equals("enfant"); code_v2_("class A { m() { return 'parent' } t() { return m() } } class B extends A { m() { return 'enfant' } } return new B().t()").equals("enfant"); code_v2_("class A { public id; } class W extends A {} class H extends W { constructor(id){ this.id=id } }").equals("null"); + code_v2_("class A { public x(a) { return a } } class B extends A { public x(a, b) { return x(a + b) } } return new B().x(5, 7)").equals("12"); section("Access levels: fields"); code_v2_("class A { x = 10 } var a = new A() return a.x").equals("10"); @@ -193,6 +284,16 @@ public void run() { code_v2_("class A { private constructor() { } } class B extends A {} return new B()").equals("B {}"); code_v2_("class A { private constructor() {} static getInstance() { return new A() } } return A.getInstance()").equals("A {}"); + section("Inheritance fields"); + code_v2_("class A { a = 7 } class B extends A { } return new B().a").equals("7"); + code_v2_("class A { a = 7 } class B extends A { } return new B()['a']").equals("7"); + code_v2_("class A { a = 7 } class B extends A { } return new B()['a']++").equals("7"); + + section("Inheritance static fields"); + code_v2_("class A { static a = 7 } class B extends A { } return B.a").equals("7"); + code_v2_("class A { static a = 7 } class B extends A { } return B['a']").equals("7"); + code_v2_("class A { static a = 7 } class B extends A { } return B['a']++").equals("7"); + section("Constructor as function"); code_v2_("class A { x constructor(x) { this.x = x } } var f = A var o = {c: f} return o.c('a')").equals("A {x: a}"); code_v2_("class A { x constructor(x) { this.x = x } } var a = [1, 2, 3, 4] return arrayMap(a, A)").equals("[A {x: 1}, A {x: 2}, A {x: 3}, A {x: 4}]"); @@ -226,6 +327,12 @@ public void run() { code_v2_("class A { sqrt() { return sqrt(25) } } return new A().sqrt()").equals("5.0"); code_v2_("class A { sqrt() { return sqrt(10, 15) } sqrt(x, y) { return sqrt(x + y) } } return new A().sqrt()").equals("5.0"); + section("Static method is a system method"); + code_v2_("class A { static sqrt() { return sqrt(25) } }").equals("null"); + code_v2_("class A {} return new A().sqrt()").equals("null"); + code_v2_("class A { static sqrt() { return sqrt(25) } } return A.sqrt()").equals("5.0"); + code_v2_("class A { static sqrt() { return sqrt(10, 15) } static sqrt(x, y) { return sqrt(x + y) } } return A.sqrt()").equals("5.0"); + section("Method as value"); code_v2_("class A { x = 12 m() { return x } } var o = new A() var r = [A.m] return r[0](o)").equals("12"); code_v2_("class A { m() { return 12 } } var o = new A() var r = {x: A.m} return r.x(o)").equals("12"); @@ -235,7 +342,7 @@ public void run() { code_v2_("class A { m(x, y) { return x * y } } var f = A.m return f(new A(), 5, 12)").equals("60"); code_v2_("class A { m(x, y) { return x * y } } var f = new A().m return f(new A(), 5, 12)").equals("60"); code_v2_("class A { m(x, y) { return x * y } } var f = A.m return f(new A(), 5)").equals("null"); - + section("Static method as value"); code_v2_("class A { static m() { return 12 } } var r = [A.m] return r[0]()").equals("12"); code_v2_("class A { static m() { return 12 } } var r = {x: A.m} return r.x()").equals("12"); @@ -246,6 +353,7 @@ public void run() { code_v2_("class a { static method() { return '42' } } class b { toto constructor() { this.toto = a.method } m() { return this.toto() } } var o = new b() return o.m()").equals("42"); code_v2_("class Test { private static method_1() { return 4 } private static method_2() { return 9 } public static array = [1: Test.method_1, 2: Test.method_2] } return [Test.array[1](), Test.array[2]()]").equals("[4, 9]"); code_v2_("class Test { private static method_1() { return 4 } private static method_2() { return 9 } public static array = [1: Test.method_1, 2: Test.method_2] } return arrayMap(Test.array, function(x) { return x() })").equals("[1 : 4, 2 : 9]"); + code_v2_("class A { a a() { return 12 } } return new A().a()").equals("12"); section("Return of field"); code_v2_("class R { f = [] m(k, r) { return this.f[k] = r } } var x = new R() return x.m(1, 2)").equals("2"); @@ -254,6 +362,10 @@ public void run() { section("Constant in static field"); code_v2_("class A { static bulbsNameChip = ['puny_bulb': PI] } return A.bulbsNameChip").equals("[puny_bulb : 3.141592653589793]"); + section("Misc"); + code_v2_("class A { static x() {} static m(item) { return x == item } } return A.m(12)").equals("false"); + code_v2_("class A { static x() {} static m(item) { return x == item } } return A.m(A.x)").equals("true"); + section("Base classes"); code_v3_("return Value").equals(""); code_v3_("return Null").equals(""); @@ -397,6 +509,19 @@ public void run() { // code("class A {} return {} < new A").equals("true"); // code("class A {} return new A < {}").equals("false"); + section("Operator instanceof"); + code_v3_("return null instanceof Null").equals("true"); + code_v3_("return true instanceof Boolean").equals("true"); + code_v3_("return false instanceof Boolean").equals("true"); + code_v3_("return 12 instanceof Integer").equals("true"); + code_v3_("return 12 instanceof Real").equals("true"); + code_v3_("return 12.5 instanceof Integer").equals("false"); + code_v3_("return 'hello' instanceof String").equals("true"); + code_v3_("return [] instanceof Array").equals("true"); + code_v3_("return {} instanceof Object").equals("true"); + code_v3_("return Number instanceof Class").equals("true"); + code_v3_("return function() {} instanceof Function").equals("true"); + /* * Iteration */ diff --git a/src/test/java/test/TestString.java b/src/test/java/test/TestString.java index 10d040c7..81afadda 100644 --- a/src/test/java/test/TestString.java +++ b/src/test/java/test/TestString.java @@ -15,6 +15,8 @@ public void run() { section("String.replace()"); code("return replace('bonjour','onj','pro')").equals("bproour"); + code("return replace('testtest', 'test', '{id}')").equals("{id}{id}"); + code("return replace('testtest', 'test', '$id')").equals("$id$id"); section("String.indexOf()"); code("return indexOf('bonjour','o')").equals("1"); From e3069b863b92cd9f6ce1cc49f6611bdcbd5da7f4 Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 27 Dec 2021 15:46:36 +0100 Subject: [PATCH 306/319] [array] Add not an array error only in LS3+ --- src/main/java/leekscript/runner/AI.java | 48 ++++++++++++++++--------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 863dca0f..38c05b91 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -1466,7 +1466,8 @@ public Object put_inc(Object array, Object key) throws LeekRunException { var field = string(key); return ((ClassLeekValue) array).field_inc(field); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1482,7 +1483,8 @@ public Object put_pre_inc(Object array, Object key) throws LeekRunException { var field = string(key); return ((ClassLeekValue) array).field_pre_inc(field); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1498,7 +1500,8 @@ public Object put_dec(Object array, Object key) throws LeekRunException { var field = string(key); return ((ClassLeekValue) array).field_dec(field); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1514,7 +1517,8 @@ public Object put_pre_dec(Object array, Object key) throws LeekRunException { var field = string(key); return ((ClassLeekValue) array).field_pre_dec(field); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1530,7 +1534,8 @@ public Object put_add_eq(Object array, Object key, Object value) throws LeekRunE var field = string(key); return ((ClassLeekValue) array).field_add_eq(field, value); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1546,7 +1551,8 @@ public Object put_sub_eq(Object array, Object key, Object value) throws LeekRunE var field = string(key); return ((ClassLeekValue) array).field_sub_eq(field, value); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1562,7 +1568,8 @@ public Object put_mul_eq(Object array, Object key, Object value) throws LeekRunE var field = string(key); return ((ClassLeekValue) array).field_mul_eq(field, value); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1578,7 +1585,8 @@ public Object put_pow_eq(Object array, Object key, Object value) throws LeekRunE var field = string(key); return ((ClassLeekValue) array).field_pow_eq(field, value); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1594,7 +1602,8 @@ public Object put_mod_eq(Object array, Object key, Object value) throws LeekRunE var field = string(key); return ((ClassLeekValue) array).field_mod_eq(field, value); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1610,7 +1619,8 @@ public Object put_div_eq(Object array, Object key, Object value) throws LeekRunE var field = string(key); return ((ClassLeekValue) array).field_div_eq(field, value); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1626,7 +1636,8 @@ public Object put_bor_eq(Object array, Object key, Object value) throws LeekRunE var field = string(key); return ((ClassLeekValue) array).field_bor_eq(field, value); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1642,7 +1653,8 @@ public Object put_band_eq(Object array, Object key, Object value) throws LeekRun var field = string(key); return ((ClassLeekValue) array).field_band_eq(field, value); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1658,7 +1670,8 @@ public Object put_shl_eq(Object array, Object key, Object value) throws LeekRunE var field = string(key); return ((ClassLeekValue) array).field_shl_eq(field, value); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1674,7 +1687,8 @@ public Object put_shr_eq(Object array, Object key, Object value) throws LeekRunE var field = string(key); return ((ClassLeekValue) array).field_shr_eq(field, value); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1690,7 +1704,8 @@ public Object put_ushr_eq(Object array, Object key, Object value) throws LeekRun var field = string(key); return ((ClassLeekValue) array).field_ushr_eq(field, value); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1706,7 +1721,8 @@ public Object put_bxor_eq(Object array, Object key, Object value) throws LeekRun var field = string(key); return ((ClassLeekValue) array).field_bxor_eq(field, value); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } From 4c30a499b48961597af67ab1af81616b76fad0ba Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 31 Dec 2021 13:19:51 +0100 Subject: [PATCH 307/319] [ai] Functions and classes are now equivalent to true --- src/main/java/leekscript/runner/AI.java | 4 ++++ src/test/java/test/TestClass.java | 11 +++++++++++ src/test/java/test/TestFunction.java | 4 ++++ src/test/java/test/TestMain.java | 1 + 4 files changed, 20 insertions(+) create mode 100644 src/test/java/test/TestClass.java diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 38c05b91..52fc4aa5 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -887,6 +887,10 @@ public boolean bool(Object value) { return false; } return !s.isEmpty(); + } else if (value instanceof FunctionLeekValue) { + return true; + } else if (value instanceof ClassLeekValue) { + return true; } else if (value instanceof Box) { return bool(((Box) value).getValue()); } diff --git a/src/test/java/test/TestClass.java b/src/test/java/test/TestClass.java new file mode 100644 index 00000000..a517184a --- /dev/null +++ b/src/test/java/test/TestClass.java @@ -0,0 +1,11 @@ +package test; + +public class TestClass extends TestCommon { + + public void run() { + + section("Class toBoolean"); + code_v2_("class A {} return !!A").equals("true"); + code_v2_("class A {} if (A) { return 12 } return null").equals("12"); + } +} diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index ce4b1ce0..bb50cae5 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -14,6 +14,10 @@ public void run() { code_v3_("return Function() {}").error(Error.CANT_ADD_INSTRUCTION_AFTER_BREAK); code_v3_("return FUNCTION() {}").error(Error.CANT_ADD_INSTRUCTION_AFTER_BREAK); + section("Function toBoolean"); + code("var a = function() {} return !!a").equals("true"); + code("var a = function() {} if (a) { return 12 } return null").equals("12"); + section("Recursive"); code("var fact = function(x) { if (x == 1) { return 1 } else { return fact(x - 1) * x } } return fact(8);").equals("40320"); // code("var fact = function(x) { if (x == 1) { return 1m } else { return fact(x - 1) * x } } return fact(30m);").equals("265252859812191058636308480000000"); diff --git a/src/test/java/test/TestMain.java b/src/test/java/test/TestMain.java index 2fc03e95..280d420a 100644 --- a/src/test/java/test/TestMain.java +++ b/src/test/java/test/TestMain.java @@ -30,6 +30,7 @@ public static void main(String[] args) throws Exception { new TestArray().run(); new TestMap().run(); new TestObject().run(); + new TestClass().run(); new TestComments().run(); new TestOperators().run(); new TestReference().run(); From c71e18f5cd4cbb261a16e08cfb5bfbe335ffb651 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 31 Dec 2021 13:20:32 +0100 Subject: [PATCH 308/319] [class] Fix .methods and .staticMethods --- .../runner/values/ClassLeekValue.java | 18 +++++++++++++++++- src/test/java/test/TestObject.java | 2 ++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/values/ClassLeekValue.java b/src/main/java/leekscript/runner/values/ClassLeekValue.java index b0b09c37..85d892e9 100644 --- a/src/main/java/leekscript/runner/values/ClassLeekValue.java +++ b/src/main/java/leekscript/runner/values/ClassLeekValue.java @@ -111,7 +111,7 @@ public void addStaticMethod(String method, int argCount, LeekFunction function, } public void addGenericStaticMethod(String method) { - genericMethods.put(method, new FunctionLeekValue(new LeekAnonymousFunction() { + genericStaticMethods.put(method, new FunctionLeekValue(new LeekAnonymousFunction() { public Object run(ObjectLeekValue thiz, Object... arguments) throws LeekRunException { final var methodCode = method + "_" + arguments.length; final var m = staticMethods.get(methodCode); @@ -135,6 +135,8 @@ public Object getField(AI ai, String field, ClassLeekValue fromClass) throws Lee return getStaticFieldsArray(); } else if (field.equals("methods")) { return getMethodsArray(); + } else if (field.equals("staticMethods")) { + return getStaticMethodsArray(); } else if (field.equals("name")) { return name; } else if (field.equals("super")) { @@ -165,6 +167,8 @@ public Object getField(AI ai, String field, ClassLeekValue fromClass) throws Lee } var generic = genericMethods.get(field); if (generic != null) return generic; + generic = genericStaticMethods.get(field); + if (generic != null) return generic; if (parent instanceof ClassLeekValue) { return parent.getField(ai, field, fromClass); @@ -380,6 +384,18 @@ private ArrayLeekValue getMethodsArray() throws LeekRunException { return methodsArray; } + private ArrayLeekValue getStaticMethodsArray() throws LeekRunException { + if (methodsArray == null) { + Object[] values = new Object[genericStaticMethods.size()]; + int i = 0; + for (var f : genericStaticMethods.entrySet()) { + values[i++] = f.getKey(); + } + methodsArray = new ArrayLeekValue(ai, values); + } + return methodsArray; + } + public LeekAnonymousFunction getMethod(AI ai, String method, ClassLeekValue fromClass) throws LeekRunException { var m = methods.get(method); if (m != null) { diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 1af54895..5c65a8dc 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -441,9 +441,11 @@ public void run() { section("Class.methods"); code_v2_("class A { static methods }").error(Error.RESERVED_FIELD); + code_v2_("class A { a() {} b() {} static c() {} } return A.methods").equals("[a, b]"); section("Class.staticMethods"); code_v2_("class A { static staticMethods }").error(Error.RESERVED_FIELD); + code_v2_("class A { a() {} b() {} static c() {} static d() {} } return A.staticMethods").equals("[c, d]"); section("Object.string()"); code_v2_("return string({x: 1, y: 2, z: 3})").equals("{x: 1, y: 2, z: 3}"); From 1e0ba0a47ef42a2fa89ced54de8c37062a9a0757 Mon Sep 17 00:00:00 2001 From: Pilow Date: Fri, 15 Apr 2022 17:25:25 +0200 Subject: [PATCH 309/319] [class] Improvements --- .../leekscript/compiler/WordCompiler.java | 2 +- .../expression/LeekExpressionFunction.java | 57 ++++++++++++++++--- .../compiler/expression/LeekVariable.java | 3 + .../ClassDeclarationInstruction.java | 14 +++++ src/main/java/leekscript/runner/AI.java | 10 ++-- src/test/java/test/TestClass.java | 9 +++ src/test/java/test/TestFunction.java | 2 + src/test/java/test/TestGeneral.java | 4 +- src/test/java/test/TestIf.java | 1 - src/test/java/test/TestMain.java | 2 +- src/test/java/test/TestObject.java | 12 +++- 11 files changed, 99 insertions(+), 17 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index b15c6c5b..575e5db1 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -657,7 +657,7 @@ private void variableDeclaration() throws LeekCompilerException { variable.setValue(readExpression()); } mCurentBlock.addInstruction(this, variable); - while (mCompiler.getWord().getType() == WordParser.T_VIRG) { + while (mCompiler.haveWords() && mCompiler.getWord().getType() == WordParser.T_VIRG) { // On regarde si y'en a d'autres mCompiler.skipWord();// On passe la virgule word = mCompiler.readWord(); diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index eda2cfb4..c06d7789 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -1,6 +1,7 @@ package leekscript.compiler.expression; import java.util.ArrayList; +import java.util.HashMap; import leekscript.compiler.AnalyzeError; import leekscript.compiler.IAWord; @@ -11,6 +12,7 @@ import leekscript.compiler.bloc.FunctionBlock; import leekscript.compiler.bloc.MainLeekBlock; import leekscript.compiler.expression.LeekVariable.VariableType; +import leekscript.compiler.instruction.ClassDeclarationInstruction.ClassDeclarationMethod; import leekscript.runner.CallableVersion; import leekscript.runner.ILeekFunction; import leekscript.runner.LeekFunctions; @@ -347,16 +349,57 @@ public void analyze(WordCompiler compiler) { var oa = (LeekObjectAccess) mExpression; if (oa.getObject() instanceof LeekVariable) { var v = (LeekVariable) oa.getObject(); - if (v.getVariableType() == VariableType.CLASS || v.getVariableType() == VariableType.THIS_CLASS) { + + if (v.getVariableType() == VariableType.THIS) { + + // on regarde si le nombre d'arguments est correct + var current = compiler.getCurrentClass(); + while (current != null) { + var methods = current.getMethod(oa.getField()); + if (methods != null) { + for (var count : methods.keySet()) { + if (count == mParameters.size()) { + return; // OK + } + } + } + current = current.getParent(); + } + // Si la classe a un field du même nom, pas d'erreur + if (!compiler.getCurrentClass().hasField(oa.getField())) { + compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.INVALID_PARAMETER_COUNT)); + } + + } else if (v.getVariableType() == VariableType.CLASS || v.getVariableType() == VariableType.THIS_CLASS) { + var clazz = v.getVariableType() == VariableType.CLASS ? v.getClassDeclaration() : compiler.getCurrentClass(); - var staticMethod = clazz.getStaticMethod(oa.getField(), mParameters.size()); operations += 1; - if (staticMethod == null) { + // on regarde si le nombre d'arguments est correct + var current = clazz; + HashMap methods = null; + while (current != null) { + methods = current.getStaticMethod(oa.getField()); + if (methods != null) { + for (var count : methods.keySet()) { + if (count == mParameters.size()) { + var staticMethod = methods.get(count); + + if (staticMethod.level == AccessLevel.PRIVATE && compiler.getCurrentClass() != clazz) { + compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.PRIVATE_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); + } else if (staticMethod.level == AccessLevel.PROTECTED && (compiler.getCurrentClass() == null || !compiler.getCurrentClass().descendsFrom(clazz))) { + compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.PROTECTED_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); + } + return; // OK + } + } + } + current = current.getParent(); + } + + if (methods != null) { // Trouvée mais mauvais nombre d'arguments + compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.INVALID_PARAMETER_COUNT, new String[] { clazz.getName(), oa.getField() })); + } else { // Pas trouvée compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.UNKNOWN_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); - } else if (staticMethod.level == AccessLevel.PRIVATE && compiler.getCurrentClass() != clazz) { - compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.PRIVATE_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); - } else if (staticMethod.level == AccessLevel.PROTECTED && (compiler.getCurrentClass() == null || !compiler.getCurrentClass().descendsFrom(clazz))) { - compiler.addError(new AnalyzeError(oa.getFieldToken(), AnalyzeErrorLevel.ERROR, Error.PROTECTED_STATIC_METHOD, new String[] { clazz.getName(), oa.getField() })); } } } diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index 7463f8f2..884cc8d6 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -87,6 +87,9 @@ public boolean validExpression(WordCompiler compiler, MainLeekBlock mainblock) t } public boolean isLeftValue() { + if (type == VariableType.CLASS || type == VariableType.THIS || type == VariableType.THIS_CLASS || type == VariableType.SUPER || type == VariableType.SYSTEM_CONSTANT) { + return false; + } return true; } diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 1bd9ed3c..856675df 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -608,4 +608,18 @@ public boolean descendsFrom(ClassDeclarationInstruction clazz) { } return false; } + + public boolean hasField(String field) { + return getField(field) != null; + } + + public LeekVariable getField(String token) { + var f = fieldVariables.get(token); + if (f != null) return f; + + if (parent != null) { + return parent.getField(token); + } + return null; + } } diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 52fc4aa5..ba9e002d 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -1233,7 +1233,7 @@ public boolean isPrimitive(Object value) { public boolean isIterable(Object value) throws LeekRunException { boolean ok = value instanceof ArrayLeekValue; - if (!ok) { + if (!ok && version >= 2) { addSystemLog(AILog.ERROR, Error.NOT_ITERABLE, new String[] { string(value) }); } return ok; @@ -1454,7 +1454,7 @@ public Object put(Object array, Object key, Object value) throws LeekRunExceptio var field = string(key); return ((ClassLeekValue) array).setField(field, value); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(array) }); return null; } @@ -1749,7 +1749,8 @@ public Object get(Object value, Object index, ClassLeekValue fromClass) throws L ops(1); return ((ClassLeekValue) value).getField(string(index)); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } @@ -1757,7 +1758,8 @@ public Box getBox(Object value, Object index) throws LeekRunException { if (value instanceof ArrayLeekValue) { return ((ArrayLeekValue) value).getBox(this, index); } - addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); + if (version >= 3) + addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new String[] { string(value) }); return null; } diff --git a/src/test/java/test/TestClass.java b/src/test/java/test/TestClass.java index a517184a..6808eb10 100644 --- a/src/test/java/test/TestClass.java +++ b/src/test/java/test/TestClass.java @@ -1,5 +1,7 @@ package test; +import leekscript.common.Error; + public class TestClass extends TestCommon { public void run() { @@ -7,5 +9,12 @@ public void run() { section("Class toBoolean"); code_v2_("class A {} return !!A").equals("true"); code_v2_("class A {} if (A) { return 12 } return null").equals("12"); + + section("Class and variable"); + code_v2_("class A {} var A = 12;").error(Error.VARIABLE_NAME_UNAVAILABLE); + code_v2_("var A = 12; class A {}").error(Error.VARIABLE_NAME_UNAVAILABLE); + code_v2_("class A {} function f(A) { A = 1 return A } return f(2)").equals("1"); + code_v2_("class A {} function f() { var A = 1 return A } return f()").equals("1"); + code_v2_("class A {} A = 12").error(Error.CANT_ASSIGN_VALUE); } } diff --git a/src/test/java/test/TestFunction.java b/src/test/java/test/TestFunction.java index bb50cae5..2d3aca16 100644 --- a/src/test/java/test/TestFunction.java +++ b/src/test/java/test/TestFunction.java @@ -36,6 +36,8 @@ public void run() { section("Redefinition"); code("var count = count([1, 2, 3]) return count;").equals("3"); code("var d = debug d('salut')").equals("null"); + code("abs = 2 return abs").equals("2"); + code("arrayFoldRight = 'salut' return arrayFoldRight").equals("salut"); section("System function as argument"); code_v1("function t(@f) { return function(@a) { return arrayMap(a, f); } } return t(sqrt)([1, 4, 9, 16, 25]);").equals("[1, 2, 3, 4, 5]"); diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index d1458d51..7a4d89e6 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -142,9 +142,9 @@ public void run() { code("var x = 5 if (true) if (true) if (true) if (true) if (true) x = 'a' return x").equals("a"); // code("var x = 2 var y = { if (x == 0) { return 'error' } 7 * x } return y").equals("14"); code("var y if (false) { if (true) {;} else { y = 2 } } else { y = 5 } return y").equals("5"); - DISABLED_code("PI = PI + 12; return PI").equals("3,142"); - DISABLED_code("PI = PI + 12; return PI").equals("3.141592653589793"); + code("PI = PI + 12; return PI").error(Error.CANT_ASSIGN_VALUE); code_v1("var grow = []; var n = []; grow = @n; return grow").equals("[]"); + code("var PI = 3 return PI").equals("3"); section("Assignments with +="); code_v1("var a = 10 a += 0.5 return a").equals("10,5"); diff --git a/src/test/java/test/TestIf.java b/src/test/java/test/TestIf.java index 2849dec6..d9807169 100644 --- a/src/test/java/test/TestIf.java +++ b/src/test/java/test/TestIf.java @@ -21,7 +21,6 @@ public void run() throws Exception { code("if (true) null else {}").equals("null"); // code("if true").error(ls::Error::UNEXPECTED_TOKEN, {""}); // code("if true else").error(ls::Error::UNEXPECTED_TOKEN, {"else"}); - DISABLED_code_v2_("if (true) {a: 12} else {b: 5}").equals("{a: 12}"); code_v2_("if (true) { return {a: 12} } else { return {b: 5} }").equals("{a: 12}"); code("if (true) return 12 else return 5;").equals("12"); code("if (false) return 12 else return 5;").equals("5"); diff --git a/src/test/java/test/TestMain.java b/src/test/java/test/TestMain.java index 280d420a..0028ea01 100644 --- a/src/test/java/test/TestMain.java +++ b/src/test/java/test/TestMain.java @@ -23,7 +23,7 @@ public static void main(String[] args) throws Exception { // TestCommon.loadReferenceOperations(); - // new TestCommon().code_v11("return 5 + 5;").equals("10"); + // new TestCommon().code("abs = 2").equals("10"); new TestGeneral().run(); new TestNumber().run(); new TestString().run(); diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 5c65a8dc..2792a556 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -163,15 +163,20 @@ public void run() { section("Static methods"); code_v2_("class A { static a() { return 12 } } return A.a()").equals("12"); - code_v2_("class A { static a(x) { return 12 } } return A.a()").error(Error.UNKNOWN_STATIC_METHOD); + code_v2_("class A { static a(x) { return 12 } } return A.a()").error(Error.INVALID_PARAMETER_COUNT); code_v2_("class A { static a() { return 12 } } return A.b()").error(Error.CLASS_STATIC_MEMBER_DOES_NOT_EXIST); code_v2_("class A { static f(x) {} static g() { f(1) } }").error(Error.NONE); code_v2_("class A { static f(x) {} static g() { f() } }").error(Error.INVALID_PARAMETER_COUNT); + code_v2_("class A { static f(x) {} static g() { class.f() } }").error(Error.INVALID_PARAMETER_COUNT); section("Static method calls with with class."); code_v2_("class A { static m() { return 'x' } t() { return class.m() } } var a = new A() return a.t()").equals("x"); code_v2_("class A { static m() { return 'x' } t() { return class.zz() } } var a = new A() return a.t()").error(Error.CLASS_STATIC_MEMBER_DOES_NOT_EXIST); + section("Methods"); + code_v2_("class A { a(x) { b(x) } b(x, y) {} }").error(Error.INVALID_PARAMETER_COUNT); + code_v2_("class A { a(x) { this.b(x) } b(x, y) {} }").error(Error.INVALID_PARAMETER_COUNT); + section("Field access by array access"); code_v2_("var test = {} test['a'] = 8 return test").equals("{a: 8}"); code_v2_("var test = {} test['a'] = 8 test['b'] = 12 return test").equals("{a: 8, b: 12}"); @@ -221,6 +226,11 @@ public void run() { code_v2_("class A { static a = 10 } return A['a'] >>= 5").equals("0"); code_v2_("class A { static a = 10 } return A['a'] >>>= 5").equals("0"); + section("Assign this/class/super"); + code_v2_("class A { m() { this = 12 } }").error(Error.CANT_ASSIGN_VALUE); + code_v2_("class A { m() { class = 12 } }").error(Error.CANT_ASSIGN_VALUE); + code_v2_("class B {} class A extends B { m() { super = 12 } }").error(Error.CANT_ASSIGN_VALUE); + section("Inheritance"); code_v2_("class A { x = 10 } class B extends A {} var a = new B() return a.x").equals("10"); code_v2_("class A { m() { return 'ok' } } class B extends A { m() { return super.m() } } var a = new B() return a.m()").equals("ok"); From 8e284901d73bc085c33e3b3664960a6ab2f64e64 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 21 May 2022 14:10:41 +0200 Subject: [PATCH 310/319] [function] Remove 1 op for each param --- src/main/java/leekscript/compiler/bloc/FunctionBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java index 9c5a71c6..dde5de97 100644 --- a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java @@ -123,7 +123,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { if (mainblock.getCompiler().getCurrentAI().getVersion() <= 1) { sb.append("new Box(" + writer.getAIThis() + ", copy(p_").append(parameter).append("));"); } else { - sb.append("p_").append(parameter).append("; ops(1); "); + sb.append("p_").append(parameter).append(";"); } } } From f6664a23d147e68296cd636961c9b8578f49ed2e Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 21 May 2022 14:11:44 +0200 Subject: [PATCH 311/319] [ai] Use one random generator for each AI --- src/main/java/leekscript/runner/AI.java | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index ba9e002d..038e52f9 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -19,6 +19,7 @@ import java.nio.file.Files; import java.util.Comparator; import java.util.HashSet; +import java.util.Random; import java.util.Set; import java.util.TreeMap; import java.util.stream.Stream; @@ -76,7 +77,27 @@ public AI(int instructions, int version) { this.mInstructions = instructions; this.version = version; logs = new AILog(); - randomGenerator = LeekScript.getRandom(); + + randomGenerator = new RandomGenerator() { + private Random random = new Random(); + + @Override + public void seed(long seed) { + random.setSeed(seed); + } + + @Override + public int getInt(int min, int max) { + if (max - min + 1 <= 0) + return 0; + return min + random.nextInt(max - min + 1); + } + + @Override + public double getDouble() { + return random.nextDouble(); + } + }; valueClass = new ClassLeekValue(this, "Value"); nullClass = new ClassLeekValue(this, "Null", valueClass); From e3dacb358efa967297ae2a0b99a0f95384f29a3d Mon Sep 17 00:00:00 2001 From: Pilow Date: Sat, 21 May 2022 14:11:54 +0200 Subject: [PATCH 312/319] [ai] Remove useless function --- src/main/java/leekscript/runner/AI.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index 038e52f9..ef1007cb 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -1260,11 +1260,6 @@ public boolean isIterable(Object value) throws LeekRunException { return ok; } - public boolean getBooleanTernary(Object value) throws LeekRunException { - ops(1); - return bool(value); - } - public Object getField(Object value, String field, ClassLeekValue fromClass) throws LeekRunException { if (value instanceof ObjectLeekValue) { return ((ObjectLeekValue) value).getField(field, fromClass); From 6c54e6411247dd35c4294f2f0506d9657f588173 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 5 Jun 2022 00:40:54 +0200 Subject: [PATCH 313/319] [build] Fix warnings --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 1830fa47..de0b209d 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ jar { } repositories { - jcenter() + mavenCentral() } dependencies { From b61139375cecf55941264a1943a4d5e3a19c60bd Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 6 Jun 2022 18:28:34 +0200 Subject: [PATCH 314/319] Fix errors --- src/test/java/test/TestGeneral.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/test/TestGeneral.java b/src/test/java/test/TestGeneral.java index 7a4d89e6..eedb8b77 100644 --- a/src/test/java/test/TestGeneral.java +++ b/src/test/java/test/TestGeneral.java @@ -69,9 +69,9 @@ public void run() { if (word.equals("this")) { code_v3_("global " + word + " = 2;").error(Error.VARIABLE_NAME_UNAVAILABLE); } else if (word.equals("instanceof")) { - code_v3_("global " + word + " = 2;").error(Error.VAR_NAME_EXPECTED); + code_v3_("global " + word + " = 2;").error(Error.VAR_NAME_EXPECTED_AFTER_GLOBAL); } else if (word.equals("function")) { - code_v3_("global " + word + " = 2;").error(Error.OPENING_PARENTHESIS_EXPECTED); + code_v3_("global " + word + " = 2;").error(Error.VARIABLE_NAME_UNAVAILABLE); } else { code_v3_("global " + word + " = 2;").error(Error.VARIABLE_NAME_UNAVAILABLE); } From 264e6bf2c7e98387a5c76a3a6b1f139a7f782c7b Mon Sep 17 00:00:00 2001 From: Pilow Date: Mon, 6 Jun 2022 18:59:30 +0200 Subject: [PATCH 315/319] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d5d9306..ab081901 100644 --- a/README.md +++ b/README.md @@ -19,4 +19,4 @@ gradle jar test ``` ### Credits -Developed by Dawyde & Pilow © 2012-2021 +Developed by Dawyde & Pilow © 2012-2022 From 06df1406100103728eba75f0c00187589cff154c Mon Sep 17 00:00:00 2001 From: Pilow Date: Thu, 9 Jun 2022 13:05:00 +0200 Subject: [PATCH 316/319] [object] Fix captures in classes methods + simplify --- .../leekscript/compiler/WordCompiler.java | 6 +++- .../compiler/bloc/ClassMethodBlock.java | 13 +++++-- .../compiler/bloc/ForeachKeyBlock.java | 4 +-- .../compiler/bloc/FunctionBlock.java | 4 +-- .../compiler/expression/LeekVariable.java | 1 - .../ClassDeclarationInstruction.java | 35 +++++++++++++------ .../LeekVariableDeclarationInstruction.java | 2 +- src/test/java/test/TestObject.java | 3 ++ 8 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/main/java/leekscript/compiler/WordCompiler.java b/src/main/java/leekscript/compiler/WordCompiler.java index 575e5db1..252074ff 100644 --- a/src/main/java/leekscript/compiler/WordCompiler.java +++ b/src/main/java/leekscript/compiler/WordCompiler.java @@ -821,7 +821,7 @@ public ClassMethodBlock classMethod(ClassDeclarationInstruction classDeclaration } if (mCompiler.getWord().getType() != WordParser.T_STRING) throw new LeekCompilerException(mCompiler.getWord(), Error.PARAMETER_NAME_EXPECTED); - method.addParameter(mCompiler.getWord()); + method.addParameter(this, mCompiler.getWord()); mCompiler.skipWord(); param_count++; if (mCompiler.getWord().getType() == WordParser.T_VIRG) @@ -1264,4 +1264,8 @@ public void setCurrentClass(ClassDeclarationInstruction clazz) { public void setCurrentFunction(AbstractLeekBlock block) { this.mCurrentFunction = block; } + + public AIFile getAI() { + return mAI; + } } diff --git a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java index 4dc249a9..734b848f 100644 --- a/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ClassMethodBlock.java @@ -6,15 +6,18 @@ import leekscript.compiler.AIFile; import leekscript.compiler.IAWord; import leekscript.compiler.JavaWriter; +import leekscript.compiler.WordCompiler; import leekscript.compiler.expression.LeekVariable; import leekscript.compiler.expression.LeekVariable.VariableType; import leekscript.compiler.instruction.ClassDeclarationInstruction; +import leekscript.compiler.instruction.LeekVariableDeclarationInstruction; public class ClassMethodBlock extends AbstractLeekBlock { private final ClassDeclarationInstruction clazz; private final boolean isStatic; private final ArrayList mParameters = new ArrayList<>(); + private final ArrayList mParameterDeclarations = new ArrayList<>(); private int mId = 0; public ClassMethodBlock(ClassDeclarationInstruction clazz, boolean isStatic, AbstractLeekBlock parent, MainLeekBlock main, int line, AIFile ai) { @@ -44,9 +47,11 @@ public String referenceArray() { return str + "}"; } - public void addParameter(IAWord token) { + public void addParameter(WordCompiler compiler, IAWord token) { mParameters.add(token); - addVariable(new LeekVariable(token, VariableType.ARGUMENT)); + var declaration = new LeekVariableDeclarationInstruction(compiler, token, token.getLine(), token.getAI(), this); + mParameterDeclarations.add(declaration); + addVariable(new LeekVariable(token, VariableType.ARGUMENT, declaration)); } public LeekVariable getVariable(String variable, boolean includeClassMembers) { @@ -110,4 +115,8 @@ public ClassDeclarationInstruction getClassDeclaration() { public List getParameters() { return mParameters; } + + public ArrayList getParametersDeclarations() { + return mParameterDeclarations; + } } diff --git a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java index 1f14f8f5..024b4dbc 100644 --- a/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java +++ b/src/main/java/leekscript/compiler/bloc/ForeachKeyBlock.java @@ -35,7 +35,7 @@ public ForeachKeyBlock(AbstractLeekBlock parent, MainLeekBlock main, boolean isK public void setValueIterator(WordCompiler compiler, IAWord iterator, boolean declaration) { if (declaration) { - iteratorDeclaration = new LeekVariableDeclarationInstruction(compiler, iterator, 0, null, compiler.getCurrentFunction()); + iteratorDeclaration = new LeekVariableDeclarationInstruction(compiler, iterator, 0, compiler.getAI(), compiler.getCurrentFunction()); // addVariable(new LeekVariable(iterator, VariableType.ITERATOR, iteratorDeclaration)); } mIterator = iterator; @@ -43,7 +43,7 @@ public void setValueIterator(WordCompiler compiler, IAWord iterator, boolean dec public void setKeyIterator(WordCompiler compiler, IAWord iterator, boolean declaration) { if (declaration) { - iteratorKeyDeclaration = new LeekVariableDeclarationInstruction(compiler, iterator, 0, null, compiler.getCurrentFunction()); + iteratorKeyDeclaration = new LeekVariableDeclarationInstruction(compiler, iterator, 0, compiler.getAI(), compiler.getCurrentFunction()); // addVariable(new LeekVariable(iterator, VariableType.ITERATOR, iteratorKeyDeclaration)); } mKeyIterator = iterator; diff --git a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java index dde5de97..c4bfc269 100644 --- a/src/main/java/leekscript/compiler/bloc/FunctionBlock.java +++ b/src/main/java/leekscript/compiler/bloc/FunctionBlock.java @@ -100,15 +100,15 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { var parameter = mParameters.get(i); var declaration = mParameterDeclarations.get(i); if (declaration.isCaptured()) { - sb.append("final var u_").append(parameter).append(" = new Wrapper("); if (mainblock.getCompiler().getCurrentAI().getVersion() <= 1) { + sb.append("final var u_").append(parameter).append(" = new Wrapper("); if (mReferences.get(i)) { sb.append("(p_").append(parameter).append(" instanceof Box) ? (Box) p_").append(parameter).append(" : new Box(" + writer.getAIThis() + ", ").append("p_").append(parameter).append("));"); } else { sb.append("new Box(").append(writer.getAIThis()).append(", copy(p_").append(parameter).append(")));"); } } else { - sb.append("new Box(").append(writer.getAIThis()).append(", p_").append(parameter).append("));"); + sb.append("final var u_").append(parameter).append(" = new Box(").append(writer.getAIThis()).append(", p_").append(parameter).append(");"); } } else { sb.append("var u_").append(parameter).append(" = "); diff --git a/src/main/java/leekscript/compiler/expression/LeekVariable.java b/src/main/java/leekscript/compiler/expression/LeekVariable.java index 884cc8d6..c1642d03 100644 --- a/src/main/java/leekscript/compiler/expression/LeekVariable.java +++ b/src/main/java/leekscript/compiler/expression/LeekVariable.java @@ -171,7 +171,6 @@ public boolean isWrapper() { return declaration != null && declaration.isWrapper(); } - @Override public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { if (type == VariableType.THIS) { diff --git a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java index 856675df..857381a7 100644 --- a/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/ClassDeclarationInstruction.java @@ -315,15 +315,21 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { String methodName = className + "_" + method.getKey() + "_" + version.getKey(); writer.addCode("private final Object " + methodName + "("); int i = 0; - for (var arg : version.getValue().block.getParameters()) { + for (var arg : version.getValue().block.getParametersDeclarations()) { if (i++ > 0) writer.addCode(", "); - writer.addCode("Object u_" + arg); + var letter = arg.isCaptured() ? "p" : "u"; + writer.addCode("Object " + letter + "_" + arg.getToken()); } - writer.addCode(") throws LeekRunException {"); + writer.addLine(") throws LeekRunException {"); writer.addLine("final var u_class = " + className + ";", version.getValue().block.getLine(), version.getValue().block.getFile()); if (parent != null) { writer.addLine("final var u_super = u_" + parent.token.getWord() + ";"); } + for (var arg : version.getValue().block.getParametersDeclarations()) { + if (arg.isCaptured()) { + writer.addLine("final var u_" + arg.getToken() + " = new Box(" + writer.getAIThis() + ", p_" + arg.getToken() + ");"); + } + } version.getValue().block.writeJavaCode(mainblock, writer); writer.addLine("}"); writer.currentBlock = null; @@ -336,17 +342,20 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { writer.currentBlock = version.getValue().block; String methodName = className + "_" + method.getKey() + "_" + version.getKey(); writer.addCode("private final Object " + methodName + "(ObjectLeekValue u_this"); - for (var arg : version.getValue().block.getParameters()) { - writer.addCode(", Object u_" + arg); + for (var arg : version.getValue().block.getParametersDeclarations()) { + var letter = arg.isCaptured() ? "p" : "u"; + writer.addCode(", Object " + letter + "_" + arg.getToken()); } - // if (version.getValue().getParameters().size() == 0) { - // writer.addCode(", Object __"); - // } writer.addCode(") throws LeekRunException {"); writer.addLine("final var u_class = " + className + ";", version.getValue().block.getLine(), version.getValue().block.getFile()); if (parent != null) { writer.addLine("final var u_super = u_" + parent.token.getWord() + ";"); } + for (var arg : version.getValue().block.getParametersDeclarations()) { + if (arg.isCaptured()) { + writer.addLine("final var u_" + arg.getToken() + " = new Box(" + writer.getAIThis() + ", p_" + arg.getToken() + ");"); + } + } writer.addCounter(1); version.getValue().block.writeJavaCode(mainblock, writer); writer.addLine("}"); @@ -360,8 +369,9 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { String methodName = className + "_" + construct.getKey(); writer.addCode("private final Object " + methodName + "(ObjectLeekValue u_this"); if (construct.getValue().block != null) { - for (var arg : construct.getValue().block.getParameters()) { - writer.addCode(", Object u_" + arg); + for (var arg : construct.getValue().block.getParametersDeclarations()) { + var letter = arg.isCaptured() ? "p" : "u"; + writer.addCode(", Object " + letter + "_" + arg.getToken()); } } writer.addCode(") throws LeekRunException {"); @@ -370,6 +380,11 @@ public void declareJava(MainLeekBlock mainblock, JavaWriter writer) { writer.addLine("final var u_super = u_" + parent.token.getWord() + ";"); } if (construct.getValue().block != null) { + for (var arg : construct.getValue().block.getParametersDeclarations()) { + if (arg.isCaptured()) { + writer.addLine("final var u_" + arg.getToken() + " = new Box(" + writer.getAIThis() + ", p_" + arg.getToken() + ");"); + } + } construct.getValue().block.writeJavaCode(mainblock, writer); } else { writer.addLine("return null;"); diff --git a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java index 1726f3b9..69263e03 100644 --- a/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java +++ b/src/main/java/leekscript/compiler/instruction/LeekVariableDeclarationInstruction.java @@ -52,7 +52,7 @@ public boolean isBox() { } public boolean isWrapper() { - return this.captured; + return mAI.getVersion() == 1 && this.captured; } @Override diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 2792a556..5033fe77 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -375,6 +375,9 @@ public void run() { section("Misc"); code_v2_("class A { static x() {} static m(item) { return x == item } } return A.m(12)").equals("false"); code_v2_("class A { static x() {} static m(item) { return x == item } } return A.m(A.x)").equals("true"); + code_v2_("class A { static f(x) { x = 2 var g = function() { f(x) } } }").equals("null"); + code_v2_("class A { f(x) { x = 2 var g = function() { f(x) } } }").equals("null"); + code_v2_("class A { constructor(x) { x = 2 var g = function() { f(x) } } }").equals("null"); section("Base classes"); code_v3_("return Value").equals(""); From d9002ceb4b6d1001eab0fabc21b00723e4108cc7 Mon Sep 17 00:00:00 2001 From: Pilow Date: Thu, 9 Jun 2022 13:05:11 +0200 Subject: [PATCH 317/319] [function] Fix arrayMin cost --- src/main/java/leekscript/runner/LeekFunctions.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/leekscript/runner/LeekFunctions.java b/src/main/java/leekscript/runner/LeekFunctions.java index 160b55f2..6703a0db 100644 --- a/src/main/java/leekscript/runner/LeekFunctions.java +++ b/src/main/java/leekscript/runner/LeekFunctions.java @@ -736,6 +736,12 @@ public Object run(AI ai, ILeekFunction function, Object... parameters) throws Le } return null; } + + @Override + public void addOperations(AI ai, ILeekFunction function, Object parameters[], Object retour) throws LeekRunException { + var array = (ArrayLeekValue) parameters[0]; + ai.ops(hasVariableOperations() ? mVariableOperations.getOperations(array.size() + 1) : 1); + } }, arrayMax(1, new int[] { AI.ARRAY }) { @Override From f84aa591ba76c20b6273583cc2da1ae565f49c06 Mon Sep 17 00:00:00 2001 From: Pilow Date: Sun, 12 Jun 2022 02:12:40 +0200 Subject: [PATCH 318/319] [test] Fix --- src/test/java/test/TestObject.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/test/TestObject.java b/src/test/java/test/TestObject.java index 5033fe77..75c71259 100644 --- a/src/test/java/test/TestObject.java +++ b/src/test/java/test/TestObject.java @@ -377,7 +377,7 @@ public void run() { code_v2_("class A { static x() {} static m(item) { return x == item } } return A.m(A.x)").equals("true"); code_v2_("class A { static f(x) { x = 2 var g = function() { f(x) } } }").equals("null"); code_v2_("class A { f(x) { x = 2 var g = function() { f(x) } } }").equals("null"); - code_v2_("class A { constructor(x) { x = 2 var g = function() { f(x) } } }").equals("null"); + code_v2_("class A { f(x) {} constructor(x) { x = 2 var g = function() { f(x) } } }").equals("null"); section("Base classes"); code_v3_("return Value").equals(""); From 3fdaa2b0dd6aa13b8fa6946720f0ad8757c0e2d8 Mon Sep 17 00:00:00 2001 From: Karang Date: Wed, 22 Jun 2022 21:47:28 +0200 Subject: [PATCH 319/319] [profiler] Instrument code to record function calls --- .../expression/LeekExpressionFunction.java | 6 ++ src/main/java/leekscript/runner/AI.java | 82 ++++++++++++++++++- 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java index c06d7789..06e7eae6 100644 --- a/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java +++ b/src/main/java/leekscript/compiler/expression/LeekExpressionFunction.java @@ -81,6 +81,7 @@ public void writeJavaCode(MainLeekBlock mainblock, JavaWriter writer) { public void compileL(MainLeekBlock mainblock, JavaWriter writer) { boolean addComma = true; boolean addBrace = false; + boolean addParen = false; FunctionBlock user_function = null; ILeekFunction system_function = null; @@ -97,8 +98,10 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { // Class.method() : Méthode statique connue var v = (LeekVariable) object; String methodName = "u_" + v.getClassDeclaration().getStaticMethodName(field, mParameters.size()); + writer.addCode("profileStatic(\"" + methodName + "\", getOperations(), "); writer.addCode(methodName + "("); addComma = false; + addParen = true; } else if (object instanceof LeekVariable && ((LeekVariable) object).getVariableType() == VariableType.THIS) { // this.method() : Méthode connue writer.addCode("callObjectAccess(u_this, \"" + field + "\", \"" + field + "_" + mParameters.size() + "\", u_class"); @@ -219,6 +222,9 @@ public void compileL(MainLeekBlock mainblock, JavaWriter writer) { if (addBrace) { writer.addCode("}"); } + if (addParen) { + writer.addCode(")"); + } writer.addCode(")"); writer.addPosition(openParenthesis); } diff --git a/src/main/java/leekscript/runner/AI.java b/src/main/java/leekscript/runner/AI.java index ef1007cb..325ce647 100644 --- a/src/main/java/leekscript/runner/AI.java +++ b/src/main/java/leekscript/runner/AI.java @@ -15,6 +15,7 @@ import leekscript.common.Error; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; import java.util.Comparator; @@ -22,6 +23,11 @@ import java.util.Random; import java.util.Set; import java.util.TreeMap; +import java.util.Map; +import java.util.HashMap; +import java.util.Collections; +import java.util.List; +import java.util.ArrayList; import java.util.stream.Stream; import com.alibaba.fastjson.JSON; @@ -73,6 +79,9 @@ public abstract class AI { public final ClassLeekValue jsonClass; public final ClassLeekValue systemClass; + private final Map callstackOperations = new HashMap(); + private boolean doProfile = false; + public AI(int instructions, int version) { this.mInstructions = instructions; this.version = version; @@ -144,6 +153,14 @@ public int getOperations() throws LeekRunException { return mOperations; } + public boolean isProfileEnabled() { + return doProfile; + } + + public void enableProfile(boolean p) { + doProfile = p; + } + public AILog getLogs() { return logs; } @@ -1770,6 +1787,49 @@ public Object get(Object value, Object index, ClassLeekValue fromClass) throws L return null; } + public void profile(String function, long operations) { + if (!doProfile) return; + + String key = function; + for (StackTraceElement element : Thread.currentThread().getStackTrace()) { + if (element.getClassName().startsWith("AI_") && element.getMethodName() != "run") { + key = element.getMethodName() + ";" + key; + } + } + if (callstackOperations.containsKey(key)) { + callstackOperations.put(key, callstackOperations.get(key) + operations); + } else { + callstackOperations.put(key, operations); + } + } + + public Object profileStatic(String name, int startOp, Object value) { + profile(name, mOperations - startOp); + return value; + } + + public void generateProfile(String path) { + if (!doProfile) return; + List callstacks = new ArrayList<>(callstackOperations.keySet()); + Collections.sort(callstacks); + for (String key : callstacks) { + String parent = key.substring(0, key.lastIndexOf(";")); + if (callstackOperations.containsKey(parent)) { + callstackOperations.put(parent, callstackOperations.get(parent) - callstackOperations.get(key)); + } + } + try { + FileWriter myWriter = new FileWriter(path); + for (String key : callstacks) { + myWriter.write(key + " " + callstackOperations.get(key) + "\n"); + } + myWriter.close(); + } catch (IOException e) { + System.out.println("An error occurred."); + e.printStackTrace(); + } + } + public Box getBox(Object value, Object index) throws LeekRunException { if (value instanceof ArrayLeekValue) { return ((ArrayLeekValue) value).getBox(this, index); @@ -1781,7 +1841,10 @@ public Box getBox(Object value, Object index) throws LeekRunException { public Object callMethod(Object value, String method, ClassLeekValue fromClass, Object... args) throws LeekRunException { if (value instanceof ObjectLeekValue) { - return ((ObjectLeekValue) value).callMethod(method, fromClass, args); + int startOp = mOperations; + Object retvalue = ((ObjectLeekValue) value).callMethod(method, fromClass, args); + profile("u_"+fromClass.name+"_"+method, mOperations - startOp); + return retvalue; } // if (value instanceof ClassLeekValue) { // return ((ClassLeekValue) value).callMethod(method, args); @@ -1791,10 +1854,16 @@ public Object callMethod(Object value, String method, ClassLeekValue fromClass, public Object callObjectAccess(Object value, String field, String method, ClassLeekValue fromClass, Object... args) throws LeekRunException { if (value instanceof ClassLeekValue) { - return ((ClassLeekValue) value).callMethod(method, fromClass, args); + int startOp = mOperations; + Object retvalue = ((ClassLeekValue) value).callMethod(method, fromClass, args); + profile("u_"+fromClass.name+"_"+method, mOperations - startOp); + return retvalue; } if (value instanceof ObjectLeekValue) { - return ((ObjectLeekValue) value).callAccess(field, method, fromClass, args); + int startOp = mOperations; + Object retvalue = ((ObjectLeekValue) value).callAccess(field, method, fromClass, args); + profile("u_"+((ObjectLeekValue) value).clazz.name+"_"+method, mOperations - startOp); + return retvalue; } addSystemLog(AILog.ERROR, Error.UNKNOWN_FIELD, new String[] { string(value), field }); return null; @@ -1802,7 +1871,10 @@ public Object callObjectAccess(Object value, String field, String method, ClassL public Object execute(Object function, Object... args) throws LeekRunException { if (function instanceof ClassLeekValue) { - return ((ClassLeekValue) function).execute(args); + int startOp = mOperations; + Object retvalue = ((ClassLeekValue) function).execute(args); + profile("u_"+((ClassLeekValue) function).name+"_"+args.length, mOperations - startOp); + return retvalue; } if (function instanceof FunctionLeekValue) { return ((FunctionLeekValue) function).execute(this, args); @@ -1816,7 +1888,9 @@ public Object sysexec(ILeekFunction function, Object... arguments) throws LeekRu int[] parameters = function.getParameters(); if (parameters == null || verifyParameters(parameters, arguments)) { Object retour = function.run(this, function, arguments); + int startOp = mOperations; function.addOperations(this, function, arguments, retour); + profile(((Enum)function).name(), mOperations - startOp); return retour; } else { // Message d'erreur