regress: remove infrastructure for super references
This commit is contained in:
parent
14e4aade35
commit
54fe16393a
@ -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();
|
||||
};
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
public static IntFunction<Instruction> toInit(CompileResult target, Location loc, String name) {
|
||||
var oldI = target.scope.get(name, false);
|
||||
public static Instruction toInit(CompileResult target, Location loc, String name) {
|
||||
var i = target.scope.get(name, false);
|
||||
|
||||
if (oldI != null) return _i -> oldI.index().toInit();
|
||||
else return _i -> {
|
||||
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);
|
||||
public static Instruction toSet(CompileResult target, Location loc, String name, boolean keep) {
|
||||
var i = target.scope.get(name, false);
|
||||
|
||||
if (oldI != null) return _i -> oldI.index().toSet(keep);
|
||||
else return _i -> {
|
||||
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) {
|
||||
|
@ -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);
|
||||
}
|
||||
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++;
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user