feat: implement optional arguments
This commit is contained in:
parent
25bd131153
commit
412edc0ebc
@ -3,10 +3,11 @@ package me.topchetoeu.jscript.common;
|
||||
public class FunctionBody {
|
||||
public final FunctionBody[] children;
|
||||
public final Instruction[] instructions;
|
||||
public final int localsN, capturesN, argsN;
|
||||
public final int localsN, capturesN, argsN, length;
|
||||
|
||||
public FunctionBody(int localsN, int capturesN, int argsN, Instruction[] instructions, FunctionBody[] children) {
|
||||
public FunctionBody(int localsN, int capturesN, int length, int argsN, Instruction[] instructions, FunctionBody[] children) {
|
||||
this.children = children;
|
||||
this.length = length;
|
||||
this.argsN = argsN;
|
||||
this.localsN = localsN;
|
||||
this.capturesN = capturesN;
|
||||
|
@ -3,7 +3,7 @@ package me.topchetoeu.jscript.compilation;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.IntFunction;
|
||||
|
||||
import me.topchetoeu.jscript.common.FunctionBody;
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
@ -16,11 +16,11 @@ import me.topchetoeu.jscript.compilation.scope.LocalScope;
|
||||
import me.topchetoeu.jscript.compilation.scope.Scope;
|
||||
|
||||
public final class CompileResult {
|
||||
public final List<Supplier<Instruction>> instructions;
|
||||
public final List<IntFunction<Instruction>> instructions;
|
||||
public final List<CompileResult> children;
|
||||
public final FunctionMapBuilder map;
|
||||
public final Environment env;
|
||||
public int length = 0;
|
||||
public int length, assignN;
|
||||
public final Scope scope;
|
||||
|
||||
public int temp() {
|
||||
@ -29,18 +29,18 @@ public final class CompileResult {
|
||||
}
|
||||
|
||||
public CompileResult add(Instruction instr) {
|
||||
instructions.add(() -> instr);
|
||||
instructions.add(i -> instr);
|
||||
return this;
|
||||
}
|
||||
public CompileResult add(Supplier<Instruction> instr) {
|
||||
public CompileResult add(IntFunction<Instruction> instr) {
|
||||
instructions.add(instr);
|
||||
return this;
|
||||
}
|
||||
public CompileResult set(int i, Instruction instr) {
|
||||
instructions.set(i, () -> instr);
|
||||
instructions.set(i, _i -> instr);
|
||||
return this;
|
||||
}
|
||||
public CompileResult set(int i, Supplier<Instruction>instr) {
|
||||
public CompileResult set(int i, IntFunction<Instruction>instr) {
|
||||
instructions.set(i, instr);
|
||||
return this;
|
||||
}
|
||||
@ -76,7 +76,10 @@ public final class CompileResult {
|
||||
public Instruction[] instructions() {
|
||||
var res = new Instruction[instructions.size()];
|
||||
var i = 0;
|
||||
for (var suppl : instructions) res[i++] = suppl.get();
|
||||
for (var suppl : instructions) {
|
||||
res[i] = suppl.apply(i);
|
||||
i++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -90,10 +93,15 @@ public final class CompileResult {
|
||||
|
||||
var instrRes = new Instruction[instructions.size()];
|
||||
var i = 0;
|
||||
for (var suppl : instructions) instrRes[i++] = suppl.get();
|
||||
|
||||
for (var suppl : instructions) {
|
||||
instrRes[i] = suppl.apply(i);
|
||||
i++;
|
||||
}
|
||||
|
||||
return new FunctionBody(
|
||||
scope.localsCount() + scope.allocCount(), scope.capturesCount(), length,
|
||||
scope.localsCount() + scope.allocCount(), scope.capturesCount(),
|
||||
length, assignN,
|
||||
instrRes, builtChildren
|
||||
);
|
||||
}
|
||||
|
@ -19,11 +19,11 @@ public class CompoundNode extends Node {
|
||||
for (var stm : statements) stm.resolve(target);
|
||||
}
|
||||
|
||||
@Override public void compile(CompileResult target, boolean pollute, BreakpointType type) {
|
||||
public void compile(CompileResult target, boolean pollute, boolean alloc, BreakpointType type) {
|
||||
List<Node> statements = new ArrayList<Node>();
|
||||
|
||||
var subtarget = target.subtarget();
|
||||
subtarget.add(() -> Instruction.stackAlloc(subtarget.scope.allocCount()));
|
||||
if (alloc) subtarget.add(i -> Instruction.stackAlloc(subtarget.scope.allocCount()));
|
||||
|
||||
for (var stm : this.statements) {
|
||||
if (stm instanceof FunctionStatementNode func) {
|
||||
@ -42,13 +42,17 @@ public class CompoundNode extends Node {
|
||||
}
|
||||
|
||||
subtarget.scope.end();
|
||||
subtarget.add(Instruction.stackFree(subtarget.scope.allocCount()));
|
||||
if (alloc) subtarget.add(Instruction.stackFree(subtarget.scope.allocCount()));
|
||||
|
||||
if (!polluted && pollute) {
|
||||
target.add(Instruction.pushUndefined());
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void compile(CompileResult target, boolean pollute, BreakpointType type) {
|
||||
compile(target, pollute, true, type);
|
||||
}
|
||||
|
||||
public CompoundNode setEnd(Location loc) {
|
||||
this.end = loc;
|
||||
return this;
|
||||
|
@ -1,6 +1,7 @@
|
||||
package me.topchetoeu.jscript.compilation;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.Operation;
|
||||
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
|
||||
import me.topchetoeu.jscript.common.parsing.Location;
|
||||
import me.topchetoeu.jscript.common.parsing.ParseRes;
|
||||
@ -12,7 +13,7 @@ import me.topchetoeu.jscript.runtime.exceptions.SyntaxException;
|
||||
|
||||
public abstract class FunctionNode extends Node {
|
||||
public final CompoundNode body;
|
||||
public final String[] args;
|
||||
public final Parameters params;
|
||||
public final Location end;
|
||||
|
||||
public abstract String name();
|
||||
@ -39,14 +40,6 @@ public abstract class FunctionNode extends Node {
|
||||
}
|
||||
|
||||
private CompileResult compileBody(CompileResult target, String name, boolean storeSelf, boolean pollute, BreakpointType bp) {
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
for (var j = 0; j < i; j++) {
|
||||
if (args[i].equals(args[j])) {
|
||||
throw new SyntaxException(loc(), "Duplicate parameter '" + args[i] + "'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var env = target.env.child()
|
||||
.remove(LabelContext.BREAK_CTX)
|
||||
.remove(LabelContext.CONTINUE_CTX);
|
||||
@ -54,16 +47,31 @@ public abstract class FunctionNode extends Node {
|
||||
var funcScope = new FunctionScope(target.scope);
|
||||
var subtarget = new CompileResult(env, new LocalScope(funcScope));
|
||||
|
||||
for (var arg : args) {
|
||||
for (var param : params.params) {
|
||||
// TODO: Implement default values
|
||||
// TODO: Implement argument location
|
||||
funcScope.defineArg(arg, loc());
|
||||
if (funcScope.hasArg(param.name)) throw new SyntaxException(param.loc, "Duplicate parameter name not allowed");
|
||||
var i = funcScope.defineParam(param.name, param.loc);
|
||||
|
||||
if (param.node != null) {
|
||||
var end = new DeferredIntSupplier();
|
||||
|
||||
subtarget.add(_i -> Instruction.loadVar(i.index()));
|
||||
subtarget.add(Instruction.pushUndefined());
|
||||
subtarget.add(Instruction.operation(Operation.EQUALS));
|
||||
subtarget.add(_i -> Instruction.jmpIfNot(end.getAsInt() - _i));
|
||||
param.node.compile(subtarget, pollute);
|
||||
subtarget.add(_i -> Instruction.storeVar(i.index()));
|
||||
|
||||
end.set(subtarget.size());
|
||||
}
|
||||
}
|
||||
|
||||
body.resolve(subtarget);
|
||||
body.compile(subtarget, false);
|
||||
body.compile(subtarget, false, false, BreakpointType.NONE);
|
||||
|
||||
subtarget.length = args.length;
|
||||
subtarget.length = params.length;
|
||||
subtarget.assignN = params.params.size();
|
||||
subtarget.scope.end();
|
||||
funcScope.end();
|
||||
|
||||
@ -88,11 +96,11 @@ public abstract class FunctionNode extends Node {
|
||||
compile(target, pollute, (String)null, BreakpointType.NONE);
|
||||
}
|
||||
|
||||
public FunctionNode(Location loc, Location end, String[] args, CompoundNode body) {
|
||||
public FunctionNode(Location loc, Location end, Parameters params, CompoundNode body) {
|
||||
super(loc);
|
||||
|
||||
this.end = end;
|
||||
this.args = args;
|
||||
this.params = params;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@ -117,21 +125,21 @@ public abstract class FunctionNode extends Node {
|
||||
n += name.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
var args = JavaScript.parseParamList(src, i + n);
|
||||
if (!args.isSuccess()) return args.chainError(src.loc(i + n), "Expected a parameter list");
|
||||
n += args.n;
|
||||
var params = JavaScript.parseParameters(src, i + n);
|
||||
if (!params.isSuccess()) return params.chainError(src.loc(i + n), "Expected a parameter list");
|
||||
n += params.n;
|
||||
|
||||
var body = CompoundNode.parse(src, i + n);
|
||||
if (!body.isSuccess()) return body.chainError(src.loc(i + n), "Expected a compound statement for function.");
|
||||
if (!body.isSuccess()) return body.chainError(src.loc(i + n), "Expected a compound statement for function");
|
||||
n += body.n;
|
||||
|
||||
if (statement) return ParseRes.res(new FunctionStatementNode(
|
||||
loc, src.loc(i + n - 1),
|
||||
args.result.toArray(String[]::new), body.result, name.result
|
||||
params.result, body.result, name.result
|
||||
), n);
|
||||
else return ParseRes.res(new FunctionValueNode(
|
||||
loc, src.loc(i + n - 1),
|
||||
args.result.toArray(String[]::new), body.result, name.result
|
||||
params.result, body.result, name.result
|
||||
), n);
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ public class FunctionStatementNode extends FunctionNode {
|
||||
target.add(VariableNode.toSet(target, end, this.name, pollute, true));
|
||||
}
|
||||
|
||||
public FunctionStatementNode(Location loc, Location end, String[] args, CompoundNode body, String name) {
|
||||
super(loc, end, args, body);
|
||||
public FunctionStatementNode(Location loc, Location end, Parameters params, CompoundNode body, String name) {
|
||||
super(loc, end, params, body);
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,8 @@ public class FunctionValueNode extends FunctionNode {
|
||||
compile(target, pollute, true, name, bp);
|
||||
}
|
||||
|
||||
public FunctionValueNode(Location loc, Location end, String[] args, CompoundNode body, String name) {
|
||||
super(loc, end, args, body);
|
||||
public FunctionValueNode(Location loc, Location end, Parameters params, CompoundNode body, String name) {
|
||||
super(loc, end, params, body);
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package me.topchetoeu.jscript.compilation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
|
||||
import me.topchetoeu.jscript.common.environment.Environment;
|
||||
import me.topchetoeu.jscript.common.parsing.Filename;
|
||||
import me.topchetoeu.jscript.common.parsing.ParseRes;
|
||||
@ -212,40 +212,53 @@ public class JavaScript {
|
||||
return ParseRes.failed();
|
||||
}
|
||||
|
||||
public static ParseRes<List<String>> parseParamList(Source src, int i) {
|
||||
public static ParseRes<Parameters> parseParameters(Source src, int i) {
|
||||
var n = Parsing.skipEmpty(src, i);
|
||||
|
||||
var openParen = Parsing.parseOperator(src, i + n, "(");
|
||||
if (!openParen.isSuccess()) return openParen.chainError(src.loc(i + n), "Expected a parameter list.");
|
||||
if (!openParen.isSuccess()) return openParen.chainError(src.loc(i + n), "Expected a parameter list");
|
||||
n += openParen.n;
|
||||
|
||||
var args = new ArrayList<String>();
|
||||
var params = new ArrayList<Parameter>();
|
||||
|
||||
var closeParen = Parsing.parseOperator(src, i + n, ")");
|
||||
n += closeParen.n;
|
||||
|
||||
if (!closeParen.isSuccess()) {
|
||||
while (true) {
|
||||
var argRes = Parsing.parseIdentifier(src, i + n);
|
||||
if (argRes.isSuccess()) {
|
||||
args.add(argRes.result);
|
||||
n += argRes.n;
|
||||
n += Parsing.skipEmpty(src, i);
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (src.is(i + n, ",")) {
|
||||
n++;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
}
|
||||
if (src.is(i + n, ")")) {
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
var paramLoc = src.loc(i);
|
||||
|
||||
var name = Parsing.parseIdentifier(src, i + n);
|
||||
if (!name.isSuccess()) return ParseRes.error(src.loc(i + n), "Expected an argument or a closing brace");
|
||||
n += name.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (src.is(i + n, "=")) {
|
||||
n++;
|
||||
|
||||
var val = parseExpression(src, i + n, 2);
|
||||
if (!val.isSuccess()) return openParen.chainError(src.loc(i + n), "Expected a default value");
|
||||
n += val.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
params.add(new Parameter(paramLoc, name.result, val.result));
|
||||
}
|
||||
else params.add(new Parameter(paramLoc, name.result, null));
|
||||
|
||||
if (src.is(i + n, ",")) {
|
||||
n++;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
}
|
||||
if (src.is(i + n, ")")) {
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
else return ParseRes.error(src.loc(i + n), "Expected an argument, or a closing brace.");
|
||||
}
|
||||
}
|
||||
|
||||
return ParseRes.res(args, n);
|
||||
return ParseRes.res(new Parameters(params), n);
|
||||
}
|
||||
|
||||
public static Node[] parse(Environment env, Filename filename, String raw) {
|
||||
@ -279,7 +292,7 @@ public class JavaScript {
|
||||
|
||||
try {
|
||||
stm.resolve(target);
|
||||
stm.compile(target, true);
|
||||
stm.compile(target, true, false, BreakpointType.NONE);
|
||||
// FunctionNode.checkBreakAndCont(target, 0);
|
||||
}
|
||||
catch (SyntaxException e) {
|
||||
|
@ -2,8 +2,8 @@ package me.topchetoeu.jscript.compilation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.environment.Environment;
|
||||
@ -25,15 +25,15 @@ public class LabelContext {
|
||||
return map.get(name);
|
||||
}
|
||||
|
||||
public Supplier<Instruction> getJump(int offset) {
|
||||
public IntFunction<Instruction> getJump() {
|
||||
var res = get();
|
||||
if (res == null) return null;
|
||||
else return () -> Instruction.jmp(res.getAsInt() - offset);
|
||||
else return i -> Instruction.jmp(res.getAsInt() - i);
|
||||
}
|
||||
public Supplier<Instruction> getJump(int offset, String name) {
|
||||
public IntFunction<Instruction> getJump(String name) {
|
||||
var res = get(name);
|
||||
if (res == null) return null;
|
||||
else return () -> Instruction.jmp(res.getAsInt() - offset);
|
||||
else return i -> Instruction.jmp(res.getAsInt() - i);
|
||||
}
|
||||
|
||||
public void push(IntSupplier jumpTarget) {
|
||||
|
15
src/java/me/topchetoeu/jscript/compilation/Parameter.java
Normal file
15
src/java/me/topchetoeu/jscript/compilation/Parameter.java
Normal file
@ -0,0 +1,15 @@
|
||||
package me.topchetoeu.jscript.compilation;
|
||||
|
||||
import me.topchetoeu.jscript.common.parsing.Location;
|
||||
|
||||
public final class Parameter {
|
||||
public final Location loc;
|
||||
public final String name;
|
||||
public final Node node;
|
||||
|
||||
public Parameter(Location loc, String name, Node node) {
|
||||
this.name = name;
|
||||
this.node = node;
|
||||
this.loc = loc;
|
||||
}
|
||||
}
|
28
src/java/me/topchetoeu/jscript/compilation/Parameters.java
Normal file
28
src/java/me/topchetoeu/jscript/compilation/Parameters.java
Normal file
@ -0,0 +1,28 @@
|
||||
package me.topchetoeu.jscript.compilation;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public final class Parameters {
|
||||
public final int length;
|
||||
public final List<Parameter> params;
|
||||
public final Set<String> names;
|
||||
|
||||
public Parameters(List<Parameter> params) {
|
||||
this.names = new HashSet<>();
|
||||
var len = params.size();
|
||||
|
||||
for (var i = params.size() - 1; i >= 0; i--) {
|
||||
if (params.get(i).node == null) break;
|
||||
len--;
|
||||
}
|
||||
|
||||
for (var param : params) {
|
||||
this.names.add(param.name);
|
||||
}
|
||||
|
||||
this.params = params;
|
||||
this.length = len;
|
||||
}
|
||||
}
|
@ -40,7 +40,7 @@ public class VariableDeclareNode extends Node {
|
||||
target.add(VariableNode.toSet(target, entry.location, entry.name, false, true));
|
||||
}
|
||||
else {
|
||||
target.add(() -> {
|
||||
target.add(_i -> {
|
||||
var i = target.scope.get(entry.name, true);
|
||||
|
||||
if (i == null) return Instruction.globDef(entry.name);
|
||||
|
@ -15,7 +15,7 @@ public class BreakNode extends Node {
|
||||
public final String label;
|
||||
|
||||
@Override public void compile(CompileResult target, boolean pollute) {
|
||||
var res = LabelContext.getBreak(target.env).getJump(target.size());
|
||||
var res = LabelContext.getBreak(target.env).getJump();
|
||||
if (res == null) {
|
||||
if (label != null) throw new SyntaxException(loc(), String.format("Undefined label '%s'", label));
|
||||
else throw new SyntaxException(loc(), "Illegal break statement");
|
||||
|
@ -15,7 +15,7 @@ public class ContinueNode extends Node {
|
||||
public final String label;
|
||||
|
||||
@Override public void compile(CompileResult target, boolean pollute) {
|
||||
var res = LabelContext.getCont(target.env).getJump(target.size());
|
||||
var res = LabelContext.getCont(target.env).getJump();
|
||||
if (res == null) {
|
||||
if (label != null) throw new SyntaxException(loc(), String.format("Undefined label '%s'", label));
|
||||
else throw new SyntaxException(loc(), "Illegal continue statement");
|
||||
|
@ -44,7 +44,7 @@ public class SwitchNode extends Node {
|
||||
value.compile(target, true, BreakpointType.STEP_OVER);
|
||||
|
||||
var subtarget = target.subtarget();
|
||||
subtarget.add(() -> Instruction.stackAlloc(subtarget.scope.allocCount()));
|
||||
subtarget.add(_i -> Instruction.stackAlloc(subtarget.scope.allocCount()));
|
||||
|
||||
// TODO: create a jump map
|
||||
for (var ccase : cases) {
|
||||
|
@ -27,7 +27,7 @@ public class FunctionScope extends Scope {
|
||||
else if (parent == null) throw new RuntimeException("Strict variables may be defined only in local scopes");
|
||||
else return parent.defineStrict(name, readonly, loc);
|
||||
}
|
||||
public VariableDescriptor defineArg(String name, Location loc) {
|
||||
public VariableDescriptor defineParam(String name, Location loc) {
|
||||
return specials.add(name, false);
|
||||
}
|
||||
public boolean hasArg(String name) {
|
||||
|
@ -97,7 +97,7 @@ public class ObjectNode extends Node {
|
||||
if (!name.isSuccess()) return name.chainError(src.loc(i + n), "Expected a property name after '" + access + "'");
|
||||
n += name.n;
|
||||
|
||||
var params = JavaScript.parseParamList(src, i + n);
|
||||
var params = JavaScript.parseParameters(src, i + n);
|
||||
if (!params.isSuccess()) return params.chainError(src.loc(i + n), "Expected an argument list");
|
||||
n += params.n;
|
||||
|
||||
@ -109,7 +109,7 @@ public class ObjectNode extends Node {
|
||||
|
||||
return ParseRes.res(new ObjProp(
|
||||
name.result, access.result,
|
||||
new FunctionValueNode(loc, end, params.result.toArray(String[]::new), body.result, access + " " + name.result.toString())
|
||||
new FunctionValueNode(loc, end, params.result, body.result, access + " " + name.result.toString())
|
||||
), n);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package me.topchetoeu.jscript.compilation.values;
|
||||
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
@ -33,7 +34,7 @@ public class VariableNode extends Node implements AssignableNode {
|
||||
var i = target.scope.get(name, true);
|
||||
|
||||
if (i == null) {
|
||||
target.add((Supplier<Instruction>)() -> {
|
||||
target.add(_i -> {
|
||||
if (target.scope.has(name)) throw new SyntaxException(loc(), String.format("Cannot access '%s' before initialization", name));
|
||||
return Instruction.globGet(name);
|
||||
});
|
||||
@ -45,28 +46,28 @@ public class VariableNode extends Node implements AssignableNode {
|
||||
}
|
||||
}
|
||||
|
||||
public static Supplier<Instruction> toGet(CompileResult target, Location loc, String name, Supplier<Instruction> onGlobal) {
|
||||
public static IntFunction<Instruction> toGet(CompileResult target, Location loc, String name, Supplier<Instruction> onGlobal) {
|
||||
var i = target.scope.get(name, true);
|
||||
|
||||
if (i == null) return () -> {
|
||||
if (i == null) return _i -> {
|
||||
if (target.scope.has(name)) throw new SyntaxException(loc, String.format("Cannot access '%s' before initialization", name));
|
||||
else return onGlobal.get();
|
||||
};
|
||||
else return () -> Instruction.loadVar(i.index());
|
||||
else return _i -> Instruction.loadVar(i.index());
|
||||
}
|
||||
public static Supplier<Instruction> toGet(CompileResult target, Location loc, String name) {
|
||||
public static IntFunction<Instruction> toGet(CompileResult target, Location loc, String name) {
|
||||
return toGet(target, loc, name, () -> Instruction.globGet(name));
|
||||
}
|
||||
|
||||
|
||||
public static Supplier<Instruction> toSet(CompileResult target, Location loc, String name, boolean keep, boolean define) {
|
||||
public static IntFunction<Instruction> toSet(CompileResult target, Location loc, String name, boolean keep, boolean define) {
|
||||
var i = target.scope.get(name, true);
|
||||
|
||||
if (i == null) return () -> {
|
||||
if (i == null) return _i -> {
|
||||
if (target.scope.has(name)) throw new SyntaxException(loc, String.format("Cannot access '%s' before initialization", name));
|
||||
else return Instruction.globSet(name, keep, define);
|
||||
};
|
||||
else return () -> Instruction.storeVar(i.index(), keep);
|
||||
else return _i -> Instruction.storeVar(i.index(), keep);
|
||||
|
||||
}
|
||||
|
||||
|
@ -420,11 +420,16 @@ public final class Frame {
|
||||
this.argsVal = new ArgumentsValue(this, args);
|
||||
this.captures = func.captures;
|
||||
|
||||
for (var i = 0; i < func.body.argsN; i++) {
|
||||
var i = 0;
|
||||
|
||||
for (; i < func.body.argsN && i < args.length; i++) {
|
||||
this.locals.add(new Value[] { args[i] });
|
||||
}
|
||||
for (; i < args.length; i++) {
|
||||
this.locals.add(new Value[] { Value.UNDEFINED });
|
||||
}
|
||||
|
||||
for (var i = 0; i < func.body.localsN; i++) {
|
||||
for (i = 0; i < func.body.localsN; i++) {
|
||||
this.locals.add(new Value[] { Value.UNDEFINED });
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ public final class CodeFunction extends FunctionValue {
|
||||
}
|
||||
|
||||
public CodeFunction(Environment env, String name, FunctionBody body, Value[][] captures) {
|
||||
super(name, body.argsN);
|
||||
super(name, body.length);
|
||||
this.captures = captures;
|
||||
this.env = env;
|
||||
this.body = body;
|
||||
|
Loading…
Reference in New Issue
Block a user