some final stuff in parsing

This commit is contained in:
TopchetoEU 2024-11-23 20:10:47 +02:00
parent 54fe16393a
commit fe8f65faf5
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
5 changed files with 54 additions and 82 deletions

View File

@ -1,5 +1,7 @@
package me.topchetoeu.jscript.compilation; package me.topchetoeu.jscript.compilation;
import java.util.List;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Instruction;
import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.common.Instruction.BreakpointType;
import me.topchetoeu.jscript.common.environment.Environment; 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.ParseRes;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.jscript.common.parsing.Parsing;
import me.topchetoeu.jscript.common.parsing.Source; 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.FunctionScope;
import me.topchetoeu.jscript.compilation.scope.Variable; import me.topchetoeu.jscript.compilation.values.VariableNode;
public abstract class FunctionNode extends Node { public abstract class FunctionNode extends Node {
public final CompoundNode body; public final CompoundNode body;
public final Parameters params; public final List<VariableNode> params;
public final Location end; public final Location end;
public abstract String name(); 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) { 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 final Environment rootEnv(Environment env) {
protected Environment rootEnv(Environment env) {
return env.get(JavaScript.COMPILE_ROOT); return env.get(JavaScript.COMPILE_ROOT);
} }
public final CompileResult compileBody(Environment env, FunctionScope scope, boolean lastReturn, String _name, String selfName) { 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 -> { for (var param : params) {
compilePreBody(target); var index = scope.define(param.name);
if (params.params.size() > 0) { target.add(Instruction.loadArg(i++));
target.add(Instruction.loadArgs(true)); target.add(index.index().toInit());
if (params.params.size() > 1) target.add(Instruction.dup(params.params.size() - 1, 0)); }
var i = 0;
for (var param : params.params) { // if (selfName != null && !scope.has(selfName, false)) {
target.add(Instruction.loadMember(i++)); // var i = scope.defineSpecial(new Variable(selfName, true), end);
param.destruct(target, DeclarationType.VAR, true);
}
}
if (params.rest != null) { // target.add(Instruction.loadCalled());
target.add(Instruction.loadRestArgs(params.params.size())); // target.add(_i -> i.index().toInit());
params.rest.destruct(target, DeclarationType.VAR, true); // }
}
if (selfName != null && !scope.has(name, false)) { body.resolve(target);
var i = scope.defineSpecial(new Variable(selfName, true), end); body.compile(target, lastReturn, BreakpointType.NONE);
target.add(Instruction.loadCallee()); return target;
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();
});
} }
public final CompileResult compileBody(CompileResult parent, String name, String selfName) { public final CompileResult compileBody(CompileResult parent, String name, String selfName) {
return compileBody(rootEnv(parent.env).child(), new FunctionScope(parent.scope), false, name, 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); 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); super(loc);
this.end = end; this.end = end;
this.params = params; this.params = params;
this.body = body; this.body = body;
this.body.hasScope = false;
} }
public static void compileWithName(Node stm, CompileResult target, boolean pollute, String name) { 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 += name.n;
n += Parsing.skipEmpty(src, i + 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"); if (!params.isSuccess()) return params.chainError(src.loc(i + n), "Expected a parameter list");
n += params.n; n += params.n;

View File

@ -1,5 +1,7 @@
package me.topchetoeu.jscript.compilation; package me.topchetoeu.jscript.compilation;
import java.util.List;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Instruction;
import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.common.Instruction.BreakpointType;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.jscript.common.parsing.Location;
@ -12,17 +14,17 @@ public class FunctionStatementNode extends FunctionNode {
@Override public String name() { return name; } @Override public String name() { return name; }
@Override public void resolve(CompileResult target) { @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) { @Override public void compile(CompileResult target, boolean pollute, String name, BreakpointType bp) {
var id = target.addChild(compileBody(target, name, null)); 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)); target.add(VariableNode.toInit(target, end, this.name));
if (pollute) target.add(Instruction.pushUndefined()); 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); super(loc, end, params, body);
this.name = name; this.name = name;
} }

View File

@ -1,8 +1,11 @@
package me.topchetoeu.jscript.compilation; package me.topchetoeu.jscript.compilation;
import java.util.List;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Instruction;
import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.common.Instruction.BreakpointType;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.jscript.common.parsing.Location;
import me.topchetoeu.jscript.compilation.values.VariableNode;
public class FunctionValueNode extends FunctionNode { public class FunctionValueNode extends FunctionNode {
public final String name; public final String name;
@ -10,11 +13,11 @@ public class FunctionValueNode extends FunctionNode {
@Override public String name() { return name; } @Override public String name() { return name; }
@Override public void compile(CompileResult target, boolean pollute, String name, BreakpointType bp) { @Override public void compile(CompileResult target, boolean pollute, String name, BreakpointType bp) {
var id = target.addChild(compileBody(target, name, null)); var id = target.addChild(compileBody(target, name, name));
target.add(_i -> Instruction.loadFunc(id, true, true, false, false, name, captures(id, target))); 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); super(loc, end, params, body);
this.name = name; this.name = name;
} }

View File

@ -3,58 +3,40 @@ package me.topchetoeu.jscript.compilation;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.github.bsideup.jabel.Desugar;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Instruction;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.jscript.common.parsing.Location;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.jscript.common.parsing.ParseRes;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.jscript.common.parsing.Parsing;
import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.jscript.common.parsing.Source;
import me.topchetoeu.jscript.compilation.JavaScript.DeclarationType; import me.topchetoeu.jscript.compilation.values.VariableNode;
import me.topchetoeu.jscript.compilation.patterns.Pattern;
public class VariableDeclareNode extends Node { public class VariableDeclareNode extends Node {
public static class Pair { @Desugar
public final Pattern destructor; public static record Pair(VariableNode var, Node value) { }
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;
}
}
public final List<Pair> values; public final List<Pair> values;
public final DeclarationType declType;
@Override public void resolve(CompileResult target) { @Override public void resolve(CompileResult target) {
if (!declType.strict) { for (var entry : values) {
for (var entry : values) { target.scope.define(entry.var.name);
entry.destructor.destructDeclResolve(target); }
}
}
} }
@Override public void compile(CompileResult target, boolean pollute) { @Override public void compile(CompileResult target, boolean pollute) {
for (var entry : values) { for (var entry : values) {
if (entry.value == null) { if (entry.value != null) {
if (declType == DeclarationType.VAR) entry.destructor.declare(target, null, false);
else entry.destructor.declare(target, declType, false);
}
else {
entry.value.compile(target, true); entry.value.compile(target, true);
target.add(VariableNode.toInit(target, loc(), entry.var.name));
if (declType == DeclarationType.VAR) entry.destructor.destruct(target, null, true);
else entry.destructor.destruct(target, declType, true);
} }
} }
if (pollute) target.add(Instruction.pushUndefined()); if (pollute) target.add(Instruction.pushUndefined());
} }
public VariableDeclareNode(Location loc, DeclarationType declType, List<Pair> values) { public VariableDeclareNode(Location loc, List<Pair> values) {
super(loc); super(loc);
this.values = values; this.values = values;
this.declType = declType;
} }
public static ParseRes<VariableDeclareNode> parse(Source src, int i) { 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); var end = JavaScript.parseStatementEnd(src, i + n);
if (end.isSuccess()) { if (end.isSuccess()) {
n += end.n; n += end.n;
return ParseRes.res(new VariableDeclareNode(loc, declType.result, res), n); return ParseRes.res(new VariableDeclareNode(loc, res), n);
} }
while (true) { while (true) {
var nameLoc = src.loc(i + n); var nameLoc = src.loc(i + n);
var name = Pattern.parse(src, i + n, false); var name = Parsing.parseIdentifier(src, i + n);
if (!name.isSuccess()) return name.chainError(nameLoc, "Expected a variable name or a destructor"); if (!name.isSuccess()) return name.chainError(nameLoc, "Expected a variable name");
n += name.n; n += name.n;
Node val = null; Node val = null;
@ -96,7 +78,7 @@ public class VariableDeclareNode extends Node {
val = valRes.result; 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, ",")) { if (src.is(i + n, ",")) {
n++; n++;
@ -107,7 +89,7 @@ public class VariableDeclareNode extends Node {
if (end.isSuccess()) { if (end.isSuccess()) {
n += end.n + endN - n; 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"); else return end.chainError(src.loc(i + n), "Expected a comma or end of statement");
} }

View File

@ -8,7 +8,7 @@ import me.topchetoeu.jscript.compilation.Node;
public class ArgumentsNode extends Node { public class ArgumentsNode extends Node {
@Override public void compile(CompileResult target, boolean pollute) { @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) { public ArgumentsNode(Location loc) {