diff --git a/src/me/topchetoeu/jscript/compilation/CompileTarget.java b/src/me/topchetoeu/jscript/compilation/CompileTarget.java new file mode 100644 index 0000000..0a207ec --- /dev/null +++ b/src/me/topchetoeu/jscript/compilation/CompileTarget.java @@ -0,0 +1,27 @@ +package me.topchetoeu.jscript.compilation; + +import java.util.Map; +import java.util.Vector; + +public class CompileTarget { + public final Vector target = new Vector<>(); + public final Map functions; + + public Instruction add(Instruction instr) { + target.add(instr); + return instr; + } + public Instruction set(int i, Instruction instr) { + return target.set(i, instr); + } + public Instruction get(int i) { + return target.get(i); + } + public int size() { return target.size(); } + + public Instruction[] array() { return target.toArray(Instruction[]::new); } + + public CompileTarget(Map functions) { + this.functions = functions; + } +} diff --git a/src/me/topchetoeu/jscript/compilation/CompoundStatement.java b/src/me/topchetoeu/jscript/compilation/CompoundStatement.java index 07fc640..c76f6ce 100644 --- a/src/me/topchetoeu/jscript/compilation/CompoundStatement.java +++ b/src/me/topchetoeu/jscript/compilation/CompoundStatement.java @@ -1,7 +1,6 @@ package me.topchetoeu.jscript.compilation; -import java.util.ArrayList; -import java.util.List; +import java.util.Vector; import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.compilation.control.ContinueStatement; @@ -21,7 +20,7 @@ public class CompoundStatement extends Statement { } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { for (var stm : statements) { if (stm instanceof FunctionStatement) { int start = target.size(); @@ -42,7 +41,7 @@ public class CompoundStatement extends Statement { @Override public Statement optimize() { - var res = new ArrayList(); + var res = new Vector(statements.length); for (var i = 0; i < statements.length; i++) { var stm = statements[i].optimize(); diff --git a/src/me/topchetoeu/jscript/compilation/DiscardStatement.java b/src/me/topchetoeu/jscript/compilation/DiscardStatement.java index 67ad9f8..6e54b4c 100644 --- a/src/me/topchetoeu/jscript/compilation/DiscardStatement.java +++ b/src/me/topchetoeu/jscript/compilation/DiscardStatement.java @@ -1,7 +1,5 @@ package me.topchetoeu.jscript.compilation; -import java.util.List; - import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.compilation.values.ConstantStatement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -10,7 +8,7 @@ public class DiscardStatement extends Statement { public final Statement value; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { value.compile(target, scope, false); } diff --git a/src/me/topchetoeu/jscript/compilation/Instruction.java b/src/me/topchetoeu/jscript/compilation/Instruction.java index bc588d8..4e3efe5 100644 --- a/src/me/topchetoeu/jscript/compilation/Instruction.java +++ b/src/me/topchetoeu/jscript/compilation/Instruction.java @@ -214,9 +214,9 @@ public class Instruction { public static Instruction loadRegex(String pattern, String flags) { return new Instruction(null, Type.LOAD_REGEX, pattern, flags); } - public static Instruction loadFunc(int instrN, int varN, int len, int[] captures) { + public static Instruction loadFunc(long id, int varN, int len, int[] captures) { var args = new Object[3 + captures.length]; - args[0] = instrN; + args[0] = id; args[1] = varN; args[2] = len; for (var i = 0; i < captures.length; i++) args[i + 3] = captures[i]; diff --git a/src/me/topchetoeu/jscript/compilation/Statement.java b/src/me/topchetoeu/jscript/compilation/Statement.java index 88d9644..7b51b38 100644 --- a/src/me/topchetoeu/jscript/compilation/Statement.java +++ b/src/me/topchetoeu/jscript/compilation/Statement.java @@ -1,7 +1,5 @@ package me.topchetoeu.jscript.compilation; -import java.util.List; - import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -9,11 +7,11 @@ public abstract class Statement { private Location _loc; public boolean pure() { return false; } - public abstract void compile(List target, ScopeRecord scope, boolean pollute); + public abstract void compile(CompileTarget target, ScopeRecord scope, boolean pollute); public void declare(ScopeRecord varsScope) { } public Statement optimize() { return this; } - public void compileWithDebug(List target, ScopeRecord scope, boolean pollute) { + public void compileWithDebug(CompileTarget target, ScopeRecord scope, boolean pollute) { int start = target.size(); compile(target, scope, pollute); if (target.size() != start) target.get(start).setDebug(true); diff --git a/src/me/topchetoeu/jscript/compilation/VariableDeclareStatement.java b/src/me/topchetoeu/jscript/compilation/VariableDeclareStatement.java index ca91393..667a982 100644 --- a/src/me/topchetoeu/jscript/compilation/VariableDeclareStatement.java +++ b/src/me/topchetoeu/jscript/compilation/VariableDeclareStatement.java @@ -26,7 +26,7 @@ public class VariableDeclareStatement extends Statement { } } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { for (var entry : values) { if (entry.name == null) continue; var key = scope.getKey(entry.name); diff --git a/src/me/topchetoeu/jscript/compilation/control/ArrayStatement.java b/src/me/topchetoeu/jscript/compilation/control/ArrayStatement.java index 7c4f1ce..e819baa 100644 --- a/src/me/topchetoeu/jscript/compilation/control/ArrayStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/ArrayStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.control; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -14,7 +13,7 @@ public class ArrayStatement extends Statement { public boolean pure() { return true; } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { target.add(Instruction.loadArr(statements.length).locate(loc())); var i = 0; for (var el : statements) { diff --git a/src/me/topchetoeu/jscript/compilation/control/BreakStatement.java b/src/me/topchetoeu/jscript/compilation/control/BreakStatement.java index 7e84fac..88be1ab 100644 --- a/src/me/topchetoeu/jscript/compilation/control/BreakStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/BreakStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.control; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -11,7 +10,7 @@ public class BreakStatement extends Statement { public final String label; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { target.add(Instruction.nop("break", label).locate(loc())); if (pollute) target.add(Instruction.loadValue(null).locate(loc())); } diff --git a/src/me/topchetoeu/jscript/compilation/control/ContinueStatement.java b/src/me/topchetoeu/jscript/compilation/control/ContinueStatement.java index a0c8b6b..6828502 100644 --- a/src/me/topchetoeu/jscript/compilation/control/ContinueStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/ContinueStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.control; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -11,7 +10,7 @@ public class ContinueStatement extends Statement { public final String label; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { target.add(Instruction.nop("cont", label).locate(loc())); if (pollute) target.add(Instruction.loadValue(null).locate(loc())); } diff --git a/src/me/topchetoeu/jscript/compilation/control/DebugStatement.java b/src/me/topchetoeu/jscript/compilation/control/DebugStatement.java index 3edb6c0..f98a434 100644 --- a/src/me/topchetoeu/jscript/compilation/control/DebugStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/DebugStatement.java @@ -1,15 +1,14 @@ package me.topchetoeu.jscript.compilation.control; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; public class DebugStatement extends Statement { @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { target.add(Instruction.debug().locate(loc())); if (pollute) target.add(Instruction.loadValue(null).locate(loc())); } diff --git a/src/me/topchetoeu/jscript/compilation/control/DeleteStatement.java b/src/me/topchetoeu/jscript/compilation/control/DeleteStatement.java index 9907524..526ff74 100644 --- a/src/me/topchetoeu/jscript/compilation/control/DeleteStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/DeleteStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.control; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -12,7 +11,7 @@ public class DeleteStatement extends Statement { public final Statement value; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { value.compile(target, scope, true); key.compile(target, scope, true); diff --git a/src/me/topchetoeu/jscript/compilation/control/DoWhileStatement.java b/src/me/topchetoeu/jscript/compilation/control/DoWhileStatement.java index 49621d5..41f9dfe 100644 --- a/src/me/topchetoeu/jscript/compilation/control/DoWhileStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/DoWhileStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.control; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.CompoundStatement; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; @@ -20,7 +19,7 @@ public class DoWhileStatement extends Statement { } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { if (condition instanceof ConstantStatement) { int start = target.size(); body.compile(target, scope, false); diff --git a/src/me/topchetoeu/jscript/compilation/control/ForInStatement.java b/src/me/topchetoeu/jscript/compilation/control/ForInStatement.java index fb82218..7ce5d6d 100644 --- a/src/me/topchetoeu/jscript/compilation/control/ForInStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/ForInStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.control; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.Operation; @@ -21,7 +20,7 @@ public class ForInStatement extends Statement { } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { var key = scope.getKey(varName); if (key instanceof String) target.add(Instruction.makeVar((String)key)); diff --git a/src/me/topchetoeu/jscript/compilation/control/ForStatement.java b/src/me/topchetoeu/jscript/compilation/control/ForStatement.java index e135a74..726e05e 100644 --- a/src/me/topchetoeu/jscript/compilation/control/ForStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/ForStatement.java @@ -1,9 +1,8 @@ package me.topchetoeu.jscript.compilation.control; -import java.util.List; - import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.compilation.Statement; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.CompoundStatement; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.values.ConstantStatement; @@ -20,7 +19,7 @@ public class ForStatement extends Statement { body.declare(globScope); } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { declaration.compile(target, scope, false); if (condition instanceof ConstantStatement) { diff --git a/src/me/topchetoeu/jscript/compilation/control/IfStatement.java b/src/me/topchetoeu/jscript/compilation/control/IfStatement.java index 1f2921b..96c94ac 100644 --- a/src/me/topchetoeu/jscript/compilation/control/IfStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/IfStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.control; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.CompoundStatement; import me.topchetoeu.jscript.compilation.DiscardStatement; import me.topchetoeu.jscript.compilation.Instruction; @@ -21,7 +20,7 @@ public class IfStatement extends Statement { } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { if (condition instanceof ConstantStatement) { if (Values.not(((ConstantStatement)condition).value)) { if (elseBody != null) elseBody.compileWithDebug(target, scope, pollute); diff --git a/src/me/topchetoeu/jscript/compilation/control/ReturnStatement.java b/src/me/topchetoeu/jscript/compilation/control/ReturnStatement.java index 8d10211..896f33c 100644 --- a/src/me/topchetoeu/jscript/compilation/control/ReturnStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/ReturnStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.control; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -11,7 +10,7 @@ public class ReturnStatement extends Statement { public final Statement value; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { if (value == null) target.add(Instruction.loadValue(null).locate(loc())); else value.compile(target, scope, true); target.add(Instruction.ret().locate(loc())); diff --git a/src/me/topchetoeu/jscript/compilation/control/SwitchStatement.java b/src/me/topchetoeu/jscript/compilation/control/SwitchStatement.java index a9b0993..5ed0a1d 100644 --- a/src/me/topchetoeu/jscript/compilation/control/SwitchStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/SwitchStatement.java @@ -1,9 +1,9 @@ package me.topchetoeu.jscript.compilation.control; import java.util.HashMap; -import java.util.List; import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.compilation.Instruction.Type; @@ -32,7 +32,7 @@ public class SwitchStatement extends Statement { } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { var caseMap = new HashMap(); var stmIndexMap = new HashMap(); diff --git a/src/me/topchetoeu/jscript/compilation/control/ThrowStatement.java b/src/me/topchetoeu/jscript/compilation/control/ThrowStatement.java index ea68d47..cf424ad 100644 --- a/src/me/topchetoeu/jscript/compilation/control/ThrowStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/ThrowStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.control; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -11,7 +10,7 @@ public class ThrowStatement extends Statement { public final Statement value; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { value.compile(target, scope, true); target.add(Instruction.throwInstr().locate(loc())); } diff --git a/src/me/topchetoeu/jscript/compilation/control/TryStatement.java b/src/me/topchetoeu/jscript/compilation/control/TryStatement.java index f25fdf2..1855f1b 100644 --- a/src/me/topchetoeu/jscript/compilation/control/TryStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/TryStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.control; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.GlobalScope; @@ -23,7 +22,7 @@ public class TryStatement extends Statement { } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { target.add(Instruction.nop()); int start = target.size(), tryN, catchN = -1, finN = -1; diff --git a/src/me/topchetoeu/jscript/compilation/control/WhileStatement.java b/src/me/topchetoeu/jscript/compilation/control/WhileStatement.java index 84dbde8..68a9e1b 100644 --- a/src/me/topchetoeu/jscript/compilation/control/WhileStatement.java +++ b/src/me/topchetoeu/jscript/compilation/control/WhileStatement.java @@ -1,9 +1,8 @@ package me.topchetoeu.jscript.compilation.control; -import java.util.List; - import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.compilation.Statement; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.CompoundStatement; import me.topchetoeu.jscript.compilation.DiscardStatement; import me.topchetoeu.jscript.compilation.Instruction; @@ -21,7 +20,7 @@ public class WhileStatement extends Statement { body.declare(globScope); } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { if (condition instanceof ConstantStatement) { if (Values.toBoolean(((ConstantStatement)condition).value)) { int start = target.size(); @@ -68,7 +67,7 @@ public class WhileStatement extends Statement { this.body = body; } - public static void replaceBreaks(List target, String label, int start, int end, int continuePoint, int breakPoint) { + public static void replaceBreaks(CompileTarget target, String label, int start, int end, int continuePoint, int breakPoint) { for (int i = start; i < end; i++) { var instr = target.get(i); if (instr.type == Type.NOP && instr.is(0, "cont") && (instr.get(1) == null || instr.is(1, label))) { diff --git a/src/me/topchetoeu/jscript/compilation/values/CallStatement.java b/src/me/topchetoeu/jscript/compilation/values/CallStatement.java index 8908179..b63a93d 100644 --- a/src/me/topchetoeu/jscript/compilation/values/CallStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/CallStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -12,7 +11,7 @@ public class CallStatement extends Statement { public final Statement[] args; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { if (func instanceof IndexStatement) { ((IndexStatement)func).compile(target, scope, true, true); } diff --git a/src/me/topchetoeu/jscript/compilation/values/ChangeStatement.java b/src/me/topchetoeu/jscript/compilation/values/ChangeStatement.java index 0d97f15..4642c40 100644 --- a/src/me/topchetoeu/jscript/compilation/values/ChangeStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/ChangeStatement.java @@ -1,9 +1,8 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.compilation.AssignableStatement; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.Operation; @@ -15,7 +14,7 @@ public class ChangeStatement extends Statement { public final boolean postfix; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { value.toAssign(new ConstantStatement(loc(), -addAmount), Operation.SUBTRACT).compile(target, scope, postfix); if (!pollute) target.add(Instruction.discard().locate(loc())); } diff --git a/src/me/topchetoeu/jscript/compilation/values/ConstantStatement.java b/src/me/topchetoeu/jscript/compilation/values/ConstantStatement.java index 563175b..f0458ae 100644 --- a/src/me/topchetoeu/jscript/compilation/values/ConstantStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/ConstantStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -14,7 +13,7 @@ public class ConstantStatement extends Statement { public boolean pure() { return true; } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { if (pollute) target.add(Instruction.loadValue(value).locate(loc())); } diff --git a/src/me/topchetoeu/jscript/compilation/values/FunctionStatement.java b/src/me/topchetoeu/jscript/compilation/values/FunctionStatement.java index 60cb65b..ca11b27 100644 --- a/src/me/topchetoeu/jscript/compilation/values/FunctionStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/FunctionStatement.java @@ -1,8 +1,9 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; +import java.util.Random; import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.CompoundStatement; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; @@ -15,6 +16,8 @@ public class FunctionStatement extends Statement { public final String name; public final String[] args; + private static Random rand = new Random(); + @Override public boolean pure() { return name == null; } @@ -23,7 +26,7 @@ public class FunctionStatement extends Statement { if (name != null) scope.define(name); } - public static void checkBreakAndCont(List target, int start) { + public static void checkBreakAndCont(CompileTarget target, int start) { for (int i = start; i < target.size(); i++) { if (target.get(i).type == Type.NOP) { if (target.get(i).is(0, "break") ) { @@ -36,7 +39,7 @@ public class FunctionStatement extends Statement { } } - public void compile(List target, ScopeRecord scope, String name, boolean isStatement) { + public void compile(CompileTarget target, ScopeRecord scope, String name, boolean isStatement) { for (var i = 0; i < args.length; i++) { for (var j = 0; j < i; j++) { if (args[i].equals(args[j])){ @@ -48,32 +51,33 @@ public class FunctionStatement extends Statement { var subscope = scope.child(); int start = target.size(); + var funcTarget = new CompileTarget(target.functions); - target.add(Instruction.nop()); subscope.define("this"); var argsVar = subscope.define("arguments"); if (args.length > 0) { for (var i = 0; i < args.length; i++) { - target.add(Instruction.loadVar(argsVar).locate(loc())); - target.add(Instruction.loadMember(i).locate(loc())); - target.add(Instruction.storeVar(subscope.define(args[i])).locate(loc())); + funcTarget.add(Instruction.loadVar(argsVar).locate(loc())); + funcTarget.add(Instruction.loadMember(i).locate(loc())); + funcTarget.add(Instruction.storeVar(subscope.define(args[i])).locate(loc())); } } if (!isStatement && this.name != null) { - target.add(Instruction.storeSelfFunc((int)subscope.define(this.name))); + funcTarget.add(Instruction.storeSelfFunc((int)subscope.define(this.name))); } body.declare(subscope); - target.add(Instruction.debugVarNames(subscope.locals())); - body.compile(target, subscope, false); + funcTarget.add(Instruction.debugVarNames(subscope.locals())); + body.compile(funcTarget, subscope, false); + funcTarget.add(Instruction.ret().locate(loc())); + checkBreakAndCont(funcTarget, start); - checkBreakAndCont(target, start); + var id = rand.nextLong(); - if (!(body instanceof CompoundStatement)) target.add(Instruction.ret().locate(loc())); - - target.set(start, Instruction.loadFunc(target.size() - start, subscope.localsCount(), args.length, subscope.getCaptures()).locate(loc())); + target.add(Instruction.loadFunc(id, subscope.localsCount(), args.length, subscope.getCaptures()).locate(loc())); + target.functions.put(id, funcTarget.array()); if (name == null) name = this.name; @@ -90,9 +94,10 @@ public class FunctionStatement extends Statement { if (key instanceof String) target.add(Instruction.makeVar((String)key).locate(loc())); target.add(Instruction.storeVar(scope.getKey(this.name), false).locate(loc())); } + } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { compile(target, scope, null, false); if (!pollute) target.add(Instruction.discard().locate(loc())); } diff --git a/src/me/topchetoeu/jscript/compilation/values/GlobalThisStatement.java b/src/me/topchetoeu/jscript/compilation/values/GlobalThisStatement.java index 0b8479c..354d09d 100644 --- a/src/me/topchetoeu/jscript/compilation/values/GlobalThisStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/GlobalThisStatement.java @@ -1,9 +1,8 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.compilation.Statement; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -12,7 +11,7 @@ public class GlobalThisStatement extends Statement { public boolean pure() { return true; } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { if (pollute) target.add(Instruction.loadGlob().locate(loc())); } diff --git a/src/me/topchetoeu/jscript/compilation/values/IndexAssignStatement.java b/src/me/topchetoeu/jscript/compilation/values/IndexAssignStatement.java index b14b70f..55a99cd 100644 --- a/src/me/topchetoeu/jscript/compilation/values/IndexAssignStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/IndexAssignStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.Operation; @@ -15,7 +14,7 @@ public class IndexAssignStatement extends Statement { public final Operation operation; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { if (operation != null) { object.compile(target, scope, true); index.compile(target, scope, true); diff --git a/src/me/topchetoeu/jscript/compilation/values/IndexStatement.java b/src/me/topchetoeu/jscript/compilation/values/IndexStatement.java index ff913aa..6159f4f 100644 --- a/src/me/topchetoeu/jscript/compilation/values/IndexStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/IndexStatement.java @@ -1,9 +1,8 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.compilation.AssignableStatement; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.Operation; @@ -20,7 +19,7 @@ public class IndexStatement extends AssignableStatement { public Statement toAssign(Statement val, Operation operation) { return new IndexAssignStatement(loc(), object, index, val, operation); } - public void compile(List target, ScopeRecord scope, boolean dupObj, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean dupObj, boolean pollute) { int start = 0; object.compile(target, scope, true); if (dupObj) target.add(Instruction.dup().locate(loc())); @@ -35,7 +34,7 @@ public class IndexStatement extends AssignableStatement { if (!pollute) target.add(Instruction.discard().locate(loc())); } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { compile(target, scope, false, pollute); } diff --git a/src/me/topchetoeu/jscript/compilation/values/LazyAndStatement.java b/src/me/topchetoeu/jscript/compilation/values/LazyAndStatement.java index 0517dcf..d71ab81 100644 --- a/src/me/topchetoeu/jscript/compilation/values/LazyAndStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/LazyAndStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -17,7 +16,7 @@ public class LazyAndStatement extends Statement { } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { if (first instanceof ConstantStatement) { if (Values.not(((ConstantStatement)first).value)) { first.compile(target, scope, pollute); diff --git a/src/me/topchetoeu/jscript/compilation/values/LazyOrStatement.java b/src/me/topchetoeu/jscript/compilation/values/LazyOrStatement.java index d601429..476a546 100644 --- a/src/me/topchetoeu/jscript/compilation/values/LazyOrStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/LazyOrStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -17,7 +16,7 @@ public class LazyOrStatement extends Statement { } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { if (first instanceof ConstantStatement) { if (Values.not(((ConstantStatement)first).value)) { second.compile(target, scope, pollute); diff --git a/src/me/topchetoeu/jscript/compilation/values/NewStatement.java b/src/me/topchetoeu/jscript/compilation/values/NewStatement.java index 4f50098..dbb632c 100644 --- a/src/me/topchetoeu/jscript/compilation/values/NewStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/NewStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -12,7 +11,7 @@ public class NewStatement extends Statement { public final Statement[] args; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { func.compile(target, scope, true); for (var arg : args) arg.compile(target, scope, true); diff --git a/src/me/topchetoeu/jscript/compilation/values/ObjectStatement.java b/src/me/topchetoeu/jscript/compilation/values/ObjectStatement.java index 7a2e9cc..abcec8d 100644 --- a/src/me/topchetoeu/jscript/compilation/values/ObjectStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/ObjectStatement.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.compilation.values; import java.util.ArrayList; -import java.util.List; import java.util.Map; import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -15,7 +15,7 @@ public class ObjectStatement extends Statement { public final Map setters; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { target.add(Instruction.loadObj().locate(loc())); for (var el : map.entrySet()) { diff --git a/src/me/topchetoeu/jscript/compilation/values/OperationStatement.java b/src/me/topchetoeu/jscript/compilation/values/OperationStatement.java index 96d12ab..3016ee2 100644 --- a/src/me/topchetoeu/jscript/compilation/values/OperationStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/OperationStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.compilation.control.ThrowStatement; @@ -16,7 +15,7 @@ public class OperationStatement extends Statement { public final Operation operation; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { for (var arg : args) { arg.compile(target, scope, true); } diff --git a/src/me/topchetoeu/jscript/compilation/values/RegexStatement.java b/src/me/topchetoeu/jscript/compilation/values/RegexStatement.java index 162c71c..26f83b4 100644 --- a/src/me/topchetoeu/jscript/compilation/values/RegexStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/RegexStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -14,7 +13,7 @@ public class RegexStatement extends Statement { public boolean pure() { return true; } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { target.add(Instruction.loadRegex(pattern, flags).locate(loc())); if (!pollute) target.add(Instruction.discard().locate(loc())); } diff --git a/src/me/topchetoeu/jscript/compilation/values/TypeofStatement.java b/src/me/topchetoeu/jscript/compilation/values/TypeofStatement.java index 50a0183..41eb2a1 100644 --- a/src/me/topchetoeu/jscript/compilation/values/TypeofStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/TypeofStatement.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.compilation.control.ArrayStatement; @@ -16,7 +15,7 @@ public class TypeofStatement extends Statement { public boolean pure() { return true; } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { if (value instanceof VariableStatement) { var i = scope.getKey(((VariableStatement)value).name); if (i instanceof String) { diff --git a/src/me/topchetoeu/jscript/compilation/values/VariableAssignStatement.java b/src/me/topchetoeu/jscript/compilation/values/VariableAssignStatement.java index 749f939..2644233 100644 --- a/src/me/topchetoeu/jscript/compilation/values/VariableAssignStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/VariableAssignStatement.java @@ -1,9 +1,8 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.compilation.Statement; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.engine.Operation; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -14,7 +13,7 @@ public class VariableAssignStatement extends Statement { public final Operation operation; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { var i = scope.getKey(name); if (operation != null) { target.add(Instruction.loadVar(i).locate(loc())); diff --git a/src/me/topchetoeu/jscript/compilation/values/VariableIndexStatement.java b/src/me/topchetoeu/jscript/compilation/values/VariableIndexStatement.java index e02a5fd..a916407 100644 --- a/src/me/topchetoeu/jscript/compilation/values/VariableIndexStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/VariableIndexStatement.java @@ -1,9 +1,8 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.compilation.Statement; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.engine.scope.ScopeRecord; @@ -14,7 +13,7 @@ public class VariableIndexStatement extends Statement { public boolean pure() { return true; } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { if (pollute) target.add(Instruction.loadVar(index).locate(loc())); } diff --git a/src/me/topchetoeu/jscript/compilation/values/VariableStatement.java b/src/me/topchetoeu/jscript/compilation/values/VariableStatement.java index 1059014..947d029 100644 --- a/src/me/topchetoeu/jscript/compilation/values/VariableStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/VariableStatement.java @@ -1,9 +1,8 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.compilation.AssignableStatement; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.Operation; @@ -21,7 +20,7 @@ public class VariableStatement extends AssignableStatement { } @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { var i = scope.getKey(name); target.add(Instruction.loadVar(i).locate(loc())); if (!pollute) target.add(Instruction.discard().locate(loc())); diff --git a/src/me/topchetoeu/jscript/compilation/values/VoidStatement.java b/src/me/topchetoeu/jscript/compilation/values/VoidStatement.java index 21b5bb2..fbf0b63 100644 --- a/src/me/topchetoeu/jscript/compilation/values/VoidStatement.java +++ b/src/me/topchetoeu/jscript/compilation/values/VoidStatement.java @@ -1,17 +1,16 @@ package me.topchetoeu.jscript.compilation.values; -import java.util.List; - import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.compilation.Statement; import me.topchetoeu.jscript.engine.scope.ScopeRecord; +import me.topchetoeu.jscript.compilation.CompileTarget; import me.topchetoeu.jscript.compilation.Instruction; public class VoidStatement extends Statement { public final Statement value; @Override - public void compile(List target, ScopeRecord scope, boolean pollute) { + public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { if (value != null) value.compile(target, scope, false); if (pollute) target.add(Instruction.loadValue(null).locate(loc())); } diff --git a/src/me/topchetoeu/jscript/engine/Context.java b/src/me/topchetoeu/jscript/engine/Context.java index 882e7ce..480453f 100644 --- a/src/me/topchetoeu/jscript/engine/Context.java +++ b/src/me/topchetoeu/jscript/engine/Context.java @@ -10,7 +10,7 @@ public class Context { public FunctionValue compile(String filename, String raw) throws InterruptedException { var res = Values.toString(this, env.compile.call(this, null, raw, filename)); - return Parsing.compile(env, filename, res); + return Parsing.compile(message.engine.functions, env, filename, res); } public Context setEnv(Environment env) { diff --git a/src/me/topchetoeu/jscript/engine/Engine.java b/src/me/topchetoeu/jscript/engine/Engine.java index 013b66e..ae4b3a7 100644 --- a/src/me/topchetoeu/jscript/engine/Engine.java +++ b/src/me/topchetoeu/jscript/engine/Engine.java @@ -1,7 +1,9 @@ package me.topchetoeu.jscript.engine; +import java.util.HashMap; import java.util.concurrent.LinkedBlockingDeque; +import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.engine.values.FunctionValue; import me.topchetoeu.jscript.events.Awaitable; import me.topchetoeu.jscript.events.DataNotifier; @@ -49,6 +51,7 @@ public class Engine { private LinkedBlockingDeque microTasks = new LinkedBlockingDeque<>(); public final int id = ++nextId; + public final HashMap functions = new HashMap<>(); private void runTask(Task task) throws InterruptedException { try { diff --git a/src/me/topchetoeu/jscript/engine/frame/Runners.java b/src/me/topchetoeu/jscript/engine/frame/Runners.java index 2869eda..ba56ad2 100644 --- a/src/me/topchetoeu/jscript/engine/frame/Runners.java +++ b/src/me/topchetoeu/jscript/engine/frame/Runners.java @@ -182,7 +182,7 @@ public class Runners { return NO_RETURN; } public static Object execLoadFunc(Context ctx, Instruction instr, CodeFrame frame) { - int n = (Integer)instr.get(0); + long id = (Long)instr.get(0); int localsN = (Integer)instr.get(1); int len = (Integer)instr.get(2); var captures = new ValueVariable[instr.params.length - 3]; @@ -191,15 +191,12 @@ public class Runners { captures[i - 3] = frame.scope.get(instr.get(i)); } - var start = frame.codePtr + 1; - var end = start + n - 1; - var body = new Instruction[end - start]; - System.arraycopy(frame.function.body, start, body, 0, end - start); - + var body = ctx.message.engine.functions.get(id); var func = new CodeFunction(ctx.env, "", localsN, len, captures, body); + frame.push(ctx, func); - frame.codePtr += n; + frame.codePtr++; return NO_RETURN; } public static Object execLoadMember(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException { diff --git a/src/me/topchetoeu/jscript/parsing/Parsing.java b/src/me/topchetoeu/jscript/parsing/Parsing.java index 5962f42..aa74e01 100644 --- a/src/me/topchetoeu/jscript/parsing/Parsing.java +++ b/src/me/topchetoeu/jscript/parsing/Parsing.java @@ -2,6 +2,7 @@ package me.topchetoeu.jscript.parsing; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; @@ -39,6 +40,8 @@ public class Parsing { } } + public static final HashMap> functions = new HashMap<>(); + private static final HashSet reserved = new HashSet(); static { reserved.add("true"); @@ -1871,12 +1874,11 @@ public class Parsing { return list.toArray(Statement[]::new); } - public static CodeFunction compile(Environment environment, Statement ...statements) { + public static CodeFunction compile(HashMap funcs, Environment environment, Statement ...statements) { var target = environment.global.globalChild(); var subscope = target.child(); - var res = new ArrayList(); + var res = new CompileTarget(funcs); var body = new CompoundStatement(null, statements); - // var optimized = body.optimize(); if (body instanceof CompoundStatement) body = (CompoundStatement)body; else body = new CompoundStatement(null, new Statement[] { body }); @@ -1890,7 +1892,7 @@ public class Parsing { FunctionStatement.checkBreakAndCont(res, 0); } catch (SyntaxException e) { - res.clear(); + res.target.clear(); res.add(Instruction.throwSyntax(e)); } @@ -1899,11 +1901,11 @@ public class Parsing { } else res.add(Instruction.ret()); - return new CodeFunction(environment, "", subscope.localsCount(), 0, new ValueVariable[0], res.toArray(Instruction[]::new)); + return new CodeFunction(environment, "", subscope.localsCount(), 0, new ValueVariable[0], res.array()); } - public static CodeFunction compile(Environment environment, String filename, String raw) { + public static CodeFunction compile(HashMap funcs, Environment environment, String filename, String raw) { try { - return compile(environment, parse(filename, raw)); + return compile(funcs, environment, parse(filename, raw)); } catch (SyntaxException e) { return new CodeFunction(environment, null, 2, 0, new ValueVariable[0], new Instruction[] { Instruction.throwSyntax(e) });