some final stuff in parsing
This commit is contained in:
parent
54fe16393a
commit
fe8f65faf5
@ -1,5 +1,7 @@
|
||||
package me.topchetoeu.jscript.compilation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
|
||||
import me.topchetoeu.jscript.common.environment.Environment;
|
||||
@ -7,65 +9,49 @@ import me.topchetoeu.jscript.common.parsing.Location;
|
||||
import me.topchetoeu.jscript.common.parsing.ParseRes;
|
||||
import me.topchetoeu.jscript.common.parsing.Parsing;
|
||||
import me.topchetoeu.jscript.common.parsing.Source;
|
||||
import me.topchetoeu.jscript.compilation.JavaScript.DeclarationType;
|
||||
import me.topchetoeu.jscript.compilation.scope.FunctionScope;
|
||||
import me.topchetoeu.jscript.compilation.scope.Variable;
|
||||
import me.topchetoeu.jscript.compilation.values.VariableNode;
|
||||
|
||||
public abstract class FunctionNode extends Node {
|
||||
public final CompoundNode body;
|
||||
public final Parameters params;
|
||||
public final List<VariableNode> params;
|
||||
public final Location end;
|
||||
|
||||
public abstract String name();
|
||||
public final String name(String fallback) {
|
||||
return this.name() != null ? this.name() : fallback;
|
||||
}
|
||||
|
||||
protected final int[] captures(int id, CompileResult target) {
|
||||
return ((FunctionScope)target.children.get(id).scope).getCaptureIndices();
|
||||
return target.children.get(id).scope.getCaptureIndices();
|
||||
}
|
||||
|
||||
protected void compilePreBody(CompileResult target) { }
|
||||
|
||||
protected Environment rootEnv(Environment env) {
|
||||
protected final Environment rootEnv(Environment env) {
|
||||
return env.get(JavaScript.COMPILE_ROOT);
|
||||
}
|
||||
|
||||
public final CompileResult compileBody(Environment env, FunctionScope scope, boolean lastReturn, String _name, String selfName) {
|
||||
var name = this.name() != null ? this.name() : _name;
|
||||
var target = new CompileResult(env, scope, params.size());
|
||||
var i = 0;
|
||||
|
||||
return new CompileResult(env, scope, params.params.size(), target -> {
|
||||
compilePreBody(target);
|
||||
for (var param : params) {
|
||||
var index = scope.define(param.name);
|
||||
|
||||
if (params.params.size() > 0) {
|
||||
target.add(Instruction.loadArgs(true));
|
||||
if (params.params.size() > 1) target.add(Instruction.dup(params.params.size() - 1, 0));
|
||||
var i = 0;
|
||||
target.add(Instruction.loadArg(i++));
|
||||
target.add(index.index().toInit());
|
||||
}
|
||||
|
||||
for (var param : params.params) {
|
||||
target.add(Instruction.loadMember(i++));
|
||||
param.destruct(target, DeclarationType.VAR, true);
|
||||
}
|
||||
}
|
||||
// if (selfName != null && !scope.has(selfName, false)) {
|
||||
// var i = scope.defineSpecial(new Variable(selfName, true), end);
|
||||
|
||||
if (params.rest != null) {
|
||||
target.add(Instruction.loadRestArgs(params.params.size()));
|
||||
params.rest.destruct(target, DeclarationType.VAR, true);
|
||||
}
|
||||
// target.add(Instruction.loadCalled());
|
||||
// target.add(_i -> i.index().toInit());
|
||||
// }
|
||||
|
||||
if (selfName != null && !scope.has(name, false)) {
|
||||
var i = scope.defineSpecial(new Variable(selfName, true), end);
|
||||
body.resolve(target);
|
||||
body.compile(target, lastReturn, BreakpointType.NONE);
|
||||
|
||||
target.add(Instruction.loadCallee());
|
||||
target.add(_i -> i.index().toInit());
|
||||
}
|
||||
|
||||
body.resolve(target);
|
||||
body.compile(target, lastReturn, BreakpointType.NONE);
|
||||
|
||||
scope.end();
|
||||
|
||||
for (var child : target.children) child.buildTask.run();
|
||||
|
||||
scope.finish();
|
||||
});
|
||||
return target;
|
||||
}
|
||||
public final CompileResult compileBody(CompileResult parent, String name, String selfName) {
|
||||
return compileBody(rootEnv(parent.env).child(), new FunctionScope(parent.scope), false, name, selfName);
|
||||
@ -82,13 +68,12 @@ public abstract class FunctionNode extends Node {
|
||||
compile(target, pollute, (String)null, BreakpointType.NONE);
|
||||
}
|
||||
|
||||
public FunctionNode(Location loc, Location end, Parameters params, CompoundNode body) {
|
||||
public FunctionNode(Location loc, Location end, List<VariableNode> params, CompoundNode body) {
|
||||
super(loc);
|
||||
|
||||
this.end = end;
|
||||
this.params = params;
|
||||
this.body = body;
|
||||
this.body.hasScope = false;
|
||||
}
|
||||
|
||||
public static void compileWithName(Node stm, CompileResult target, boolean pollute, String name) {
|
||||
@ -112,7 +97,7 @@ public abstract class FunctionNode extends Node {
|
||||
n += name.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
var params = Parameters.parseParameters(src, i + 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;
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
package me.topchetoeu.jscript.compilation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
|
||||
import me.topchetoeu.jscript.common.parsing.Location;
|
||||
@ -12,17 +14,17 @@ public class FunctionStatementNode extends FunctionNode {
|
||||
@Override public String name() { return name; }
|
||||
|
||||
@Override public void resolve(CompileResult target) {
|
||||
target.scope.define(new Variable(name, false), end);
|
||||
target.scope.define(new Variable(name, false));
|
||||
}
|
||||
|
||||
@Override public void compile(CompileResult target, boolean pollute, String name, BreakpointType bp) {
|
||||
var id = target.addChild(compileBody(target, name, null));
|
||||
target.add(_i -> Instruction.loadFunc(id, true, true, false, false, name, captures(id, target)));
|
||||
target.add(Instruction.loadFunc(id, name, captures(id, target)));
|
||||
target.add(VariableNode.toInit(target, end, this.name));
|
||||
if (pollute) target.add(Instruction.pushUndefined());
|
||||
}
|
||||
|
||||
public FunctionStatementNode(Location loc, Location end, Parameters params, CompoundNode body, String name) {
|
||||
public FunctionStatementNode(Location loc, Location end, List<VariableNode> params, CompoundNode body, String name) {
|
||||
super(loc, end, params, body);
|
||||
this.name = name;
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
package me.topchetoeu.jscript.compilation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
|
||||
import me.topchetoeu.jscript.common.parsing.Location;
|
||||
import me.topchetoeu.jscript.compilation.values.VariableNode;
|
||||
|
||||
public class FunctionValueNode extends FunctionNode {
|
||||
public final String name;
|
||||
@ -10,11 +13,11 @@ public class FunctionValueNode extends FunctionNode {
|
||||
@Override public String name() { return name; }
|
||||
|
||||
@Override public void compile(CompileResult target, boolean pollute, String name, BreakpointType bp) {
|
||||
var id = target.addChild(compileBody(target, name, null));
|
||||
target.add(_i -> Instruction.loadFunc(id, true, true, false, false, name, captures(id, target)));
|
||||
var id = target.addChild(compileBody(target, name, name));
|
||||
target.add(Instruction.loadFunc(id, name, captures(id, target)));
|
||||
}
|
||||
|
||||
public FunctionValueNode(Location loc, Location end, Parameters params, CompoundNode body, String name) {
|
||||
public FunctionValueNode(Location loc, Location end, List<VariableNode> params, CompoundNode body, String name) {
|
||||
super(loc, end, params, body);
|
||||
this.name = name;
|
||||
}
|
||||
|
@ -3,58 +3,40 @@ package me.topchetoeu.jscript.compilation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.github.bsideup.jabel.Desugar;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.parsing.Location;
|
||||
import me.topchetoeu.jscript.common.parsing.ParseRes;
|
||||
import me.topchetoeu.jscript.common.parsing.Parsing;
|
||||
import me.topchetoeu.jscript.common.parsing.Source;
|
||||
import me.topchetoeu.jscript.compilation.JavaScript.DeclarationType;
|
||||
import me.topchetoeu.jscript.compilation.patterns.Pattern;
|
||||
import me.topchetoeu.jscript.compilation.values.VariableNode;
|
||||
|
||||
public class VariableDeclareNode extends Node {
|
||||
public static class Pair {
|
||||
public final Pattern destructor;
|
||||
public final Node value;
|
||||
public final Location location;
|
||||
|
||||
public Pair(Pattern destr, Node value, Location location) {
|
||||
this.destructor = destr;
|
||||
this.value = value;
|
||||
this.location = location;
|
||||
}
|
||||
}
|
||||
@Desugar
|
||||
public static record Pair(VariableNode var, Node value) { }
|
||||
|
||||
public final List<Pair> values;
|
||||
public final DeclarationType declType;
|
||||
|
||||
@Override public void resolve(CompileResult target) {
|
||||
if (!declType.strict) {
|
||||
for (var entry : values) {
|
||||
entry.destructor.destructDeclResolve(target);
|
||||
}
|
||||
}
|
||||
for (var entry : values) {
|
||||
target.scope.define(entry.var.name);
|
||||
}
|
||||
}
|
||||
@Override public void compile(CompileResult target, boolean pollute) {
|
||||
for (var entry : values) {
|
||||
if (entry.value == null) {
|
||||
if (declType == DeclarationType.VAR) entry.destructor.declare(target, null, false);
|
||||
else entry.destructor.declare(target, declType, false);
|
||||
}
|
||||
else {
|
||||
if (entry.value != null) {
|
||||
entry.value.compile(target, true);
|
||||
|
||||
if (declType == DeclarationType.VAR) entry.destructor.destruct(target, null, true);
|
||||
else entry.destructor.destruct(target, declType, true);
|
||||
target.add(VariableNode.toInit(target, loc(), entry.var.name));
|
||||
}
|
||||
}
|
||||
|
||||
if (pollute) target.add(Instruction.pushUndefined());
|
||||
}
|
||||
|
||||
public VariableDeclareNode(Location loc, DeclarationType declType, List<Pair> values) {
|
||||
public VariableDeclareNode(Location loc, List<Pair> values) {
|
||||
super(loc);
|
||||
this.values = values;
|
||||
this.declType = declType;
|
||||
}
|
||||
|
||||
public static ParseRes<VariableDeclareNode> parse(Source src, int i) {
|
||||
@ -70,14 +52,14 @@ public class VariableDeclareNode extends Node {
|
||||
var end = JavaScript.parseStatementEnd(src, i + n);
|
||||
if (end.isSuccess()) {
|
||||
n += end.n;
|
||||
return ParseRes.res(new VariableDeclareNode(loc, declType.result, res), n);
|
||||
return ParseRes.res(new VariableDeclareNode(loc, res), n);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
var nameLoc = src.loc(i + n);
|
||||
|
||||
var name = Pattern.parse(src, i + n, false);
|
||||
if (!name.isSuccess()) return name.chainError(nameLoc, "Expected a variable name or a destructor");
|
||||
var name = Parsing.parseIdentifier(src, i + n);
|
||||
if (!name.isSuccess()) return name.chainError(nameLoc, "Expected a variable name");
|
||||
n += name.n;
|
||||
|
||||
Node val = null;
|
||||
@ -96,7 +78,7 @@ public class VariableDeclareNode extends Node {
|
||||
val = valRes.result;
|
||||
}
|
||||
|
||||
res.add(new Pair(name.result, val, nameLoc));
|
||||
res.add(new Pair(new VariableNode(nameLoc, name.result), val));
|
||||
|
||||
if (src.is(i + n, ",")) {
|
||||
n++;
|
||||
@ -107,7 +89,7 @@ public class VariableDeclareNode extends Node {
|
||||
|
||||
if (end.isSuccess()) {
|
||||
n += end.n + endN - n;
|
||||
return ParseRes.res(new VariableDeclareNode(loc, declType.result, res), n);
|
||||
return ParseRes.res(new VariableDeclareNode(loc, res), n);
|
||||
}
|
||||
else return end.chainError(src.loc(i + n), "Expected a comma or end of statement");
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import me.topchetoeu.jscript.compilation.Node;
|
||||
|
||||
public class ArgumentsNode extends Node {
|
||||
@Override public void compile(CompileResult target, boolean pollute) {
|
||||
if (pollute) target.add(Instruction.loadArgs(false));
|
||||
if (pollute) target.add(Instruction.loadArgs());
|
||||
}
|
||||
|
||||
public ArgumentsNode(Location loc) {
|
||||
|
Loading…
Reference in New Issue
Block a user