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; package me.topchetoeu.jscript.compilation.values;
import java.util.function.IntFunction;
import me.topchetoeu.jscript.common.Instruction; 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.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;
@ -11,12 +8,9 @@ import me.topchetoeu.jscript.common.parsing.Source;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.jscript.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.jscript.compilation.JavaScript;
import me.topchetoeu.jscript.compilation.Node; 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.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 final String name;
public String assignName() { return 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)); 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) { @Override public void afterAssign(CompileResult target, boolean pollute) {
target.add(VariableNode.toSet(target, loc(), name, 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) { @Override public void compile(CompileResult target, boolean pollute) {
target.add(toGet(target, loc(), name, true, false)).setLocation(loc()); 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) { public static Instruction toGet(CompileResult target, Location loc, String name, boolean keep, boolean forceGet) {
var oldI = target.scope.get(name, false); var i = target.scope.get(name, false);
if (oldI != null) { if (i != null) {
if (keep) return _i -> oldI.index().toGet(); if (keep) return i.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();
else return Instruction.nop(); else return Instruction.nop();
}; }
else return Instruction.globGet(name, forceGet);
} }
public static IntFunction<Instruction> toGet(CompileResult target, Location loc, String name) { public static Instruction toGet(CompileResult target, Location loc, String name) {
return toGet(target, loc, name, true, false); return toGet(target, loc, name, true, false);
} }
public static IntFunction<Instruction> toInit(CompileResult target, Location loc, String name) { public static Instruction toInit(CompileResult target, Location loc, String name) {
var oldI = target.scope.get(name, false); var i = target.scope.get(name, false);
if (oldI != null) return _i -> oldI.index().toInit(); if (i != null) return i.index().toInit();
else return _i -> { else return Instruction.globSet(name, false, true);
var i = target.scope.get(name, false);
if (i == null) return Instruction.globSet(name, false, true);
else return i.index().toInit();
};
} }
public static IntFunction<Instruction> toSet(CompileResult target, Location loc, String name, boolean keep) { public static Instruction toSet(CompileResult target, Location loc, String name, boolean keep) {
var oldI = target.scope.get(name, false); var i = target.scope.get(name, false);
if (oldI != null) return _i -> oldI.index().toSet(keep); if (i != null) return i.index().toSet(keep);
else return _i -> { else return Instruction.globSet(name, keep, false);
var i = target.scope.get(name, false);
if (i == null) return Instruction.globSet(name, keep, false);
else return i.index().toSet(keep);
};
} }
public VariableNode(Location loc, String name) { 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;
import me.topchetoeu.jscript.common.Instruction.BreakpointType; 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.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.ClassNode;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.jscript.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.jscript.compilation.JavaScript;
import me.topchetoeu.jscript.compilation.Node; 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 class CallNode extends Node {
public static boolean ATTACH_NAME = true;
public final Node func; public final Node func;
public final Node[] args; public final Node[] args;
public final boolean isNew; 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) { @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)) { obj.compile(target, true);
target.env.get(ClassNode.SUPER_CONSTR).accept(target); target.add(Instruction.dup());
for (var arg : args) arg.compile(target, true); IndexNode.indexLoad(target, index, 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); for (var arg : args) arg.compile(target, true);
if (ATTACH_NAME) name = generateName(obj, index); target.add(Instruction.call(args.length, true));
target.add(Instruction.call(args.length, true, name));
target.setLocationAndDebug(loc(), type); target.setLocationAndDebug(loc(), type);
} }
else { else {
String name = "";
func.compile(target, true); func.compile(target, true);
for (var arg : args) arg.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)).setLocationAndDebug(loc(), type);
else target.add(Instruction.call(args.length, false)).setLocationAndDebug(loc(), type);
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 (!pollute) target.add(Instruction.discard()); if (!pollute) target.add(Instruction.discard());
} }
@ -168,7 +74,8 @@ public class CallNode extends Node {
prevArg = true; prevArg = true;
} }
else if (argRes.isError()) return argRes.chainError(); else if (argRes.isError()) return argRes.chainError();
else if (prevArg && src.is(i + n, ",")) {
if (prevArg && src.is(i + n, ",")) {
prevArg = false; prevArg = false;
n++; 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.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.ClassNode;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.jscript.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.jscript.compilation.JavaScript;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.jscript.compilation.Node;
import me.topchetoeu.jscript.compilation.patterns.ChangeTarget; 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.NumberNode;
import me.topchetoeu.jscript.compilation.values.constants.StringNode; import me.topchetoeu.jscript.compilation.values.constants.StringNode;
@ -20,11 +18,11 @@ public class IndexNode extends Node implements ChangeTarget {
public final Node index; public final Node index;
@Override public void beforeAssign(CompileResult target) { @Override public void beforeAssign(CompileResult target) {
compileObj(target, object); object.compile(target, true);
indexStorePushKey(target, index); indexStorePushKey(target, index);
} }
@Override public void beforeChange(CompileResult target) { @Override public void beforeChange(CompileResult target) {
compileObj(target, object); object.compile(target, true);
if (index instanceof NumberNode num && (int)num.value == num.value) { if (index instanceof NumberNode num && (int)num.value == num.value) {
target.add(Instruction.dup()); target.add(Instruction.dup());
@ -44,7 +42,7 @@ public class IndexNode extends Node implements ChangeTarget {
} }
@Override public void assign(CompileResult target, boolean pollute) { @Override public void assign(CompileResult target, boolean pollute) {
compileObj(target, object); object.compile(target, true);
target.add(Instruction.dup(1, 1)); target.add(Instruction.dup(1, 1));
indexStorePushKey(target, index); indexStorePushKey(target, index);
indexStore(target, index, pollute); indexStore(target, index, pollute);
@ -55,7 +53,7 @@ public class IndexNode extends Node implements ChangeTarget {
} }
public void compile(CompileResult target, boolean dupObj, boolean pollute) { public void compile(CompileResult target, boolean dupObj, boolean pollute) {
compileObj(target, object); object.compile(target, true);
if (dupObj) target.add(Instruction.dup()); if (dupObj) target.add(Instruction.dup());
if (index instanceof NumberNode num && (int)num.value == num.value) { if (index instanceof NumberNode num && (int)num.value == num.value) {
@ -83,13 +81,6 @@ public class IndexNode extends Node implements ChangeTarget {
this.index = index; 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) { public static ParseRes<IndexNode> parseIndex(Source src, int i, Node prev, int precedence) {
if (precedence > 18) return ParseRes.failed(); if (precedence > 18) return ParseRes.failed();