regress: remove infrastructure for super references

This commit is contained in:
TopchetoEU 2024-11-23 20:10:11 +02:00
parent 14e4aade35
commit 54fe16393a
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
3 changed files with 31 additions and 189 deletions

View File

@ -1,9 +1,6 @@
package me.topchetoeu.jscript.compilation.values;
import java.util.function.IntFunction;
import me.topchetoeu.jscript.common.Instruction;
import me.topchetoeu.jscript.common.SyntaxException;
import me.topchetoeu.jscript.common.parsing.Location;
import me.topchetoeu.jscript.common.parsing.ParseRes;
import me.topchetoeu.jscript.common.parsing.Parsing;
@ -11,12 +8,9 @@ import me.topchetoeu.jscript.common.parsing.Source;
import me.topchetoeu.jscript.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.JavaScript;
import me.topchetoeu.jscript.compilation.Node;
import me.topchetoeu.jscript.compilation.JavaScript.DeclarationType;
import me.topchetoeu.jscript.compilation.patterns.ChangeTarget;
import me.topchetoeu.jscript.compilation.patterns.Pattern;
import me.topchetoeu.jscript.compilation.scope.Variable;
public class VariableNode extends Node implements Pattern, ChangeTarget {
public class VariableNode extends Node implements ChangeTarget {
public final String name;
public String assignName() { return name; }
@ -25,88 +19,38 @@ public class VariableNode extends Node implements Pattern, ChangeTarget {
target.add(VariableNode.toGet(target, loc(), name));
}
@Override public void destructDeclResolve(CompileResult target) {
var i = target.scope.define(new Variable(name, false), loc());
if (i != null) target.add(_i -> i.index().toUndefinedInit(false));
}
@Override public void afterAssign(CompileResult target, boolean pollute) {
target.add(VariableNode.toSet(target, loc(), name, pollute));
}
@Override public void declare(CompileResult target, DeclarationType decl, boolean lateInitializer) {
if (decl != null) {
var i = target.scope.define(decl, name, loc());
target.add(_i -> i.index().toUndefinedInit(decl.strict));
}
else target.add(_i -> {
var i = target.scope.get(name, false);
if (i == null) return Instruction.globDef(name);
else return Instruction.nop();
});
target.setLocation(loc());
}
@Override public void destruct(CompileResult target, DeclarationType decl, boolean shouldDeclare) {
if (!shouldDeclare || decl == null) {
if (shouldDeclare) target.add(VariableNode.toInit(target, loc(), name));
else target.add(VariableNode.toInit(target, loc(), name));
}
else {
if (decl == DeclarationType.VAR && target.scope.has(name, false)) throw new SyntaxException(loc(), "Duplicate parameter name not allowed");
var v = target.scope.define(decl, name, loc());
target.add(_i -> v.index().toInit());
}
target.setLocation(loc());
}
@Override public void compile(CompileResult target, boolean pollute) {
target.add(toGet(target, loc(), name, true, false)).setLocation(loc());
}
public static IntFunction<Instruction> toGet(CompileResult target, Location loc, String name, boolean keep, boolean forceGet) {
var oldI = target.scope.get(name, false);
public static Instruction toGet(CompileResult target, Location loc, String name, boolean keep, boolean forceGet) {
var i = target.scope.get(name, false);
if (oldI != null) {
if (keep) return _i -> oldI.index().toGet();
else return _i -> Instruction.nop();
}
else return _i -> {
var newI = target.scope.get(name, false);
if (newI == null) return Instruction.globGet(name, forceGet);
else if (keep) return newI.index().toGet();
if (i != null) {
if (keep) return i.index().toGet();
else return Instruction.nop();
};
}
public static IntFunction<Instruction> toGet(CompileResult target, Location loc, String name) {
else return Instruction.globGet(name, forceGet);
}
public static Instruction toGet(CompileResult target, Location loc, String name) {
return toGet(target, loc, name, true, false);
}
public static IntFunction<Instruction> toInit(CompileResult target, Location loc, String name) {
var oldI = target.scope.get(name, false);
if (oldI != null) return _i -> oldI.index().toInit();
else return _i -> {
public static Instruction toInit(CompileResult target, Location loc, String name) {
var i = target.scope.get(name, false);
if (i == null) return Instruction.globSet(name, false, true);
else return i.index().toInit();
};
if (i != null) return i.index().toInit();
else return Instruction.globSet(name, false, true);
}
public static IntFunction<Instruction> toSet(CompileResult target, Location loc, String name, boolean keep) {
var oldI = target.scope.get(name, false);
if (oldI != null) return _i -> oldI.index().toSet(keep);
else return _i -> {
public static Instruction toSet(CompileResult target, Location loc, String name, boolean keep) {
var i = target.scope.get(name, false);
if (i == null) return Instruction.globSet(name, keep, false);
else return i.index().toSet(keep);
};
if (i != null) return i.index().toSet(keep);
else return Instruction.globSet(name, keep, false);
}
public VariableNode(Location loc, String name) {

View File

@ -4,134 +4,40 @@ import java.util.ArrayList;
import me.topchetoeu.jscript.common.Instruction;
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
import me.topchetoeu.jscript.common.json.JSON;
import me.topchetoeu.jscript.common.json.JSONElement;
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.ClassNode;
import me.topchetoeu.jscript.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.JavaScript;
import me.topchetoeu.jscript.compilation.Node;
import me.topchetoeu.jscript.compilation.values.ArgumentsNode;
import me.topchetoeu.jscript.compilation.values.ArrayNode;
import me.topchetoeu.jscript.compilation.values.ObjectNode;
import me.topchetoeu.jscript.compilation.values.SuperNode;
import me.topchetoeu.jscript.compilation.values.ThisNode;
import me.topchetoeu.jscript.compilation.values.VariableNode;
import me.topchetoeu.jscript.compilation.values.constants.BoolNode;
import me.topchetoeu.jscript.compilation.values.constants.NumberNode;
import me.topchetoeu.jscript.compilation.values.constants.StringNode;
public class CallNode extends Node {
public static boolean ATTACH_NAME = true;
public final Node func;
public final Node[] args;
public final boolean isNew;
private String generateName(Node func, Node index) {
String res = "(intermediate value)";
boolean shouldParen = false;
if (func instanceof ObjectNode) {
var obj = (ObjectNode)func;
shouldParen = true;
if (obj.members.size() > 0) res = "{}";
else res = "{(intermediate value)}";
}
else if (func instanceof StringNode) {
res = JSON.stringify(JSONElement.string(((StringNode)func).value));
}
else if (func instanceof NumberNode) {
res = JSON.stringify(JSONElement.number(((NumberNode)func).value));
}
else if (func instanceof BoolNode) {
res = ((BoolNode)func).value ? "true" : "false";
}
else if (func instanceof VariableNode) {
res = ((VariableNode)func).name;
}
else if (func instanceof ThisNode) {
res = "this";
}
else if (func instanceof ArgumentsNode) {
res = "arguments";
}
else if (func instanceof ArrayNode) {
var els = new ArrayList<String>();
for (var el : ((ArrayNode)func).statements) {
if (el != null) els.add(generateName(el, null));
else els.add("(intermediate value)");
}
res = "[" + String.join(",", els) + "]";
}
if (index == null) return res;
if (shouldParen) res = "(" + res + ")";
if (index instanceof StringNode) {
var val = ((StringNode)index).value;
var bracket = JSON.stringify(JSONElement.string(val));
if (!bracket.substring(1, bracket.length() - 1).equals(val)) return res + "[" + bracket + "]";
if (Parsing.parseIdentifier(new Source(val), 0).n != val.length()) return res + "[" + bracket + "]";
return res + "." + val;
}
return res + "[" + generateName(index, null) + "]";
}
@Override public void compile(CompileResult target, boolean pollute, BreakpointType type) {
var superInstr = target.env.get(ClassNode.SUPER);
if (!isNew && func instanceof IndexNode indexNode) {
var obj = indexNode.object;
var index = indexNode.index;
if (!isNew && func instanceof SuperNode && superInstr != null && target.env.hasNotNull(ClassNode.ON_SUPER_CALL)) {
target.env.get(ClassNode.SUPER_CONSTR).accept(target);
for (var arg : args) arg.compile(target, true);
target.add(Instruction.callSuper(args.length));
target.env.get(ClassNode.ON_SUPER_CALL).accept(target);
}
else if (!isNew && func instanceof IndexNode indexn) {
var obj = indexn.object;
var index = indexn.index;
String name = "";
if (superInstr != null && obj instanceof SuperNode) {
new ThisNode(null).compile(target, true);
target.env.get(ClassNode.SUPER).accept(target);
IndexNode.indexLoad(target, index, true);
}
else {
obj.compile(target, true);
target.add(Instruction.dup());
IndexNode.indexLoad(target, index, true);
}
for (var arg : args) arg.compile(target, true);
if (ATTACH_NAME) name = generateName(obj, index);
target.add(Instruction.call(args.length, true, name));
target.add(Instruction.call(args.length, true));
target.setLocationAndDebug(loc(), type);
}
else {
String name = "";
func.compile(target, true);
for (var arg : args) arg.compile(target, true);
if (ATTACH_NAME) name = generateName(func, null);
if (isNew) target.add(Instruction.callNew(args.length, name)).setLocationAndDebug(loc(), type);
else target.add(Instruction.call(args.length, false, name)).setLocationAndDebug(loc(), type);
if (isNew) target.add(Instruction.callNew(args.length)).setLocationAndDebug(loc(), type);
else target.add(Instruction.call(args.length, false)).setLocationAndDebug(loc(), type);
}
if (!pollute) target.add(Instruction.discard());
}
@ -168,7 +74,8 @@ public class CallNode extends Node {
prevArg = true;
}
else if (argRes.isError()) return argRes.chainError();
else if (prevArg && src.is(i + n, ",")) {
if (prevArg && src.is(i + n, ",")) {
prevArg = false;
n++;
}

View File

@ -6,12 +6,10 @@ 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.ClassNode;
import me.topchetoeu.jscript.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.JavaScript;
import me.topchetoeu.jscript.compilation.Node;
import me.topchetoeu.jscript.compilation.patterns.ChangeTarget;
import me.topchetoeu.jscript.compilation.values.SuperNode;
import me.topchetoeu.jscript.compilation.values.constants.NumberNode;
import me.topchetoeu.jscript.compilation.values.constants.StringNode;
@ -20,11 +18,11 @@ public class IndexNode extends Node implements ChangeTarget {
public final Node index;
@Override public void beforeAssign(CompileResult target) {
compileObj(target, object);
object.compile(target, true);
indexStorePushKey(target, index);
}
@Override public void beforeChange(CompileResult target) {
compileObj(target, object);
object.compile(target, true);
if (index instanceof NumberNode num && (int)num.value == num.value) {
target.add(Instruction.dup());
@ -44,7 +42,7 @@ public class IndexNode extends Node implements ChangeTarget {
}
@Override public void assign(CompileResult target, boolean pollute) {
compileObj(target, object);
object.compile(target, true);
target.add(Instruction.dup(1, 1));
indexStorePushKey(target, index);
indexStore(target, index, pollute);
@ -55,7 +53,7 @@ public class IndexNode extends Node implements ChangeTarget {
}
public void compile(CompileResult target, boolean dupObj, boolean pollute) {
compileObj(target, object);
object.compile(target, true);
if (dupObj) target.add(Instruction.dup());
if (index instanceof NumberNode num && (int)num.value == num.value) {
@ -83,13 +81,6 @@ public class IndexNode extends Node implements ChangeTarget {
this.index = index;
}
private static void compileObj(CompileResult target, Node obj) {
if (obj instanceof SuperNode && target.env.hasNotNull(ClassNode.SUPER)) {
target.env.get(ClassNode.SUPER).accept(target);
}
else obj.compile(target, true);
}
public static ParseRes<IndexNode> parseIndex(Source src, int i, Node prev, int precedence) {
if (precedence > 18) return ParseRes.failed();