regress: remove ES6 nodes
This commit is contained in:
parent
50eb204da7
commit
5644966dd7
@ -1,244 +0,0 @@
|
||||
package me.topchetoeu.jscript.compilation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.SyntaxException;
|
||||
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
|
||||
import me.topchetoeu.jscript.common.environment.Environment;
|
||||
import me.topchetoeu.jscript.common.environment.Key;
|
||||
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.members.FieldMemberNode;
|
||||
import me.topchetoeu.jscript.compilation.members.Member;
|
||||
import me.topchetoeu.jscript.compilation.members.MethodMemberNode;
|
||||
import me.topchetoeu.jscript.compilation.members.PropertyMemberNode;
|
||||
import me.topchetoeu.jscript.compilation.scope.FunctionScope;
|
||||
|
||||
public abstract class ClassNode extends FunctionNode {
|
||||
public static final class ClassBody {
|
||||
public final List<Member> staticMembers;
|
||||
public final List<FieldMemberNode> protoFields;
|
||||
public final List<Member> protoMembers;
|
||||
public final Parameters constructorParameters;
|
||||
public final CompoundNode constructorBody;
|
||||
public final Node superExpr;
|
||||
public final boolean hasConstr;
|
||||
|
||||
public ClassBody(
|
||||
List<Member> staticMembers, List<FieldMemberNode> protoFields, List<Member> protoMembers,
|
||||
Parameters constructorParameters, CompoundNode constructorBody,
|
||||
Node superExpr, boolean hasConstr
|
||||
) {
|
||||
this.staticMembers = staticMembers;
|
||||
this.protoFields = protoFields;
|
||||
this.protoMembers = protoMembers;
|
||||
this.constructorParameters = constructorParameters;
|
||||
this.constructorBody = constructorBody;
|
||||
this.superExpr = superExpr;
|
||||
this.hasConstr = hasConstr;
|
||||
}
|
||||
}
|
||||
|
||||
public static final Key<Environment> CLASS_ROOT = Key.of();
|
||||
public static final Key<Consumer<CompileResult>> SUPER = Key.of();
|
||||
public static final Key<Consumer<CompileResult>> SUPER_PROTO = Key.of();
|
||||
public static final Key<Consumer<CompileResult>> SUPER_CONSTR = Key.of();
|
||||
public static final Key<Consumer<CompileResult>> ON_SUPER_CALL = Key.of();
|
||||
|
||||
public final ClassBody body;
|
||||
public final String name;
|
||||
|
||||
@Override public String name() { return name; }
|
||||
|
||||
public void compileStatic(CompileResult target) {
|
||||
for (var member : body.staticMembers) {
|
||||
member.compile(target, true, false);
|
||||
}
|
||||
}
|
||||
public void compilePrototype(CompileResult target) {
|
||||
if (body.protoMembers.size() > 0) {
|
||||
target.add(Instruction.dup());
|
||||
target.add(Instruction.loadMember("prototype"));
|
||||
|
||||
for (var i = 0; i < body.protoMembers.size() - 1; i++) {
|
||||
body.protoMembers.get(i).compile(target, true, false);
|
||||
}
|
||||
|
||||
body.protoMembers.get(body.protoMembers.size() - 1).compile(target, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void compileFieldInits(CompileResult target) {
|
||||
for (var member : body.protoFields) {
|
||||
target.add(Instruction.loadThis());
|
||||
member.compile(target, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override protected void compilePreBody(CompileResult target) {
|
||||
if (target.env.hasNotNull(SUPER_PROTO)) {
|
||||
if (!body.hasConstr) {
|
||||
throw new SyntaxException(loc(), "Default constructors in derived classes not supported");
|
||||
// compileFieldInits(target);
|
||||
}
|
||||
}
|
||||
else compileFieldInits(target);
|
||||
}
|
||||
|
||||
@Override public void compile(CompileResult target, boolean pollute, String name, BreakpointType bp) {
|
||||
if (body.superExpr == null) {
|
||||
var id = target.addChild(compileBody(target, name, null));
|
||||
target.add(_i -> Instruction.loadFunc(id, false, true, false, false, name, captures(id, target)));
|
||||
compileStatic(target);
|
||||
compilePrototype(target);
|
||||
}
|
||||
else {
|
||||
var subtarget = target.subtarget().rootEnvironment(JavaScript.COMPILE_ROOT);
|
||||
subtarget.scope.singleEntry = true;
|
||||
subtarget.beginScope();
|
||||
var protoVar = target.scope.defineTemp();
|
||||
var constrVar = target.scope.defineTemp();
|
||||
|
||||
subtarget.env.add(SUPER_PROTO, t -> {
|
||||
var i = t.scope.get(protoVar, false);
|
||||
t.add(_i -> i.index().toGet());
|
||||
});
|
||||
subtarget.env.add(SUPER_CONSTR, t -> {
|
||||
var i = t.scope.get(constrVar, false);
|
||||
t.add(_i -> i.index().toGet());
|
||||
});
|
||||
|
||||
var staticTarget = subtarget.subEnvironment();
|
||||
staticTarget.env.add(SUPER, subtarget.env.get(SUPER_CONSTR));
|
||||
staticTarget.env.add(CLASS_ROOT, staticTarget.env);
|
||||
|
||||
var protoTarget = subtarget.subEnvironment();
|
||||
protoTarget.env.add(SUPER, subtarget.env.get(SUPER_PROTO));
|
||||
protoTarget.env.add(CLASS_ROOT, protoTarget.env);
|
||||
|
||||
var constrEnv = subtarget.env.child();
|
||||
constrEnv.add(SUPER, subtarget.env.get(SUPER_PROTO));
|
||||
constrEnv.add(ON_SUPER_CALL, this::compileFieldInits);
|
||||
constrEnv.add(CLASS_ROOT, constrEnv);
|
||||
|
||||
var id = target.addChild(compileBody(constrEnv, new FunctionScope(subtarget.scope), false, name, null));
|
||||
target.add(_i -> Instruction.loadFunc(id, false, true, false, true, name, captures(id, target)));
|
||||
|
||||
body.superExpr.compile(target, true);
|
||||
|
||||
target.add(Instruction.extend());
|
||||
target.add(Instruction.dup(1, 0));
|
||||
target.add(Instruction.loadMember("prototype"));
|
||||
target.add(_i -> protoVar.index().toInit());
|
||||
target.add(_i -> constrVar.index().toInit());
|
||||
|
||||
compileStatic(staticTarget);
|
||||
compilePrototype(protoTarget);
|
||||
subtarget.endScope();
|
||||
}
|
||||
}
|
||||
|
||||
public ClassNode(Location loc, Location end, String name, ClassBody body) {
|
||||
super(loc, end, body.constructorParameters, body.constructorBody);
|
||||
|
||||
this.name = name;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public static ParseRes<Member> parseMember(Source src, int i) {
|
||||
return ParseRes.first(src, i,
|
||||
PropertyMemberNode::parse,
|
||||
FieldMemberNode::parseClass,
|
||||
MethodMemberNode::parse
|
||||
);
|
||||
}
|
||||
|
||||
public static ParseRes<ClassBody> parseBody(Source src, int i) {
|
||||
var n = Parsing.skipEmpty(src, i);
|
||||
var loc = src.loc(i + n);
|
||||
|
||||
ParseRes<Node> superExpr = ParseRes.failed();
|
||||
|
||||
if (Parsing.isIdentifier(src, i + n, "extends")) {
|
||||
n += 7;
|
||||
|
||||
superExpr = JavaScript.parseExpression(src, i + n, 14);
|
||||
if (!superExpr.isSuccess()) return superExpr.chainError(src.loc(i + n), "Expected an expression after 'extends'");
|
||||
n += superExpr.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
}
|
||||
|
||||
if (!src.is(i + n, "{")) return ParseRes.error(src.loc(i + n), "Expected a class body");
|
||||
n++;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
var fields = new LinkedList<FieldMemberNode>();
|
||||
var members = new LinkedList<Member>();
|
||||
var statics = new LinkedList<Member>();
|
||||
|
||||
var params = new Parameters(new ArrayList<>());
|
||||
var body = new CompoundNode(loc, false);
|
||||
var hasConstr = false;
|
||||
|
||||
if (src.is(i + n, "}")) {
|
||||
n++;
|
||||
return ParseRes.res(new ClassBody(statics, fields, members, params, body, superExpr.result, false), n);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
ParseRes<Member> prop = parseMember(src, i + n);
|
||||
|
||||
if (prop.isSuccess()) {
|
||||
n += prop.n;
|
||||
|
||||
if (prop.result instanceof FieldMemberNode field) fields.add(field);
|
||||
else if (prop.result instanceof MethodMemberNode method && method.name().equals("constructor")) {
|
||||
if (hasConstr) return ParseRes.error(loc, "A class may only have one constructor");
|
||||
|
||||
params = method.params;
|
||||
body = method.body;
|
||||
hasConstr = true;
|
||||
}
|
||||
else members.add(prop.result);
|
||||
}
|
||||
else if (Parsing.isIdentifier(src, i + n, "static")) {
|
||||
n += 6;
|
||||
|
||||
var staticProp = parseMember(src, i + n);
|
||||
if (!staticProp.isSuccess()) {
|
||||
if (prop.isError()) return prop.chainError();
|
||||
else return staticProp.chainError(src.loc(i + n), "Expected a member after 'static' keyword");
|
||||
}
|
||||
n += staticProp.n;
|
||||
|
||||
statics.add(staticProp.result);
|
||||
}
|
||||
else {
|
||||
var end = JavaScript.parseStatementEnd(src, i + n);
|
||||
if (end.isSuccess()) n += end.n;
|
||||
else return ParseRes.error(src.loc(i + n), "Expected a member, end of statement or a closing colon");
|
||||
}
|
||||
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (src.is(i + n, "}")) {
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
// else return ParseRes.error(src.loc(i + n), "Expected a comma or a closing brace.");
|
||||
}
|
||||
|
||||
return ParseRes.res(new ClassBody(statics, fields, members, params, body, superExpr.result, hasConstr), n);
|
||||
}
|
||||
|
||||
// public FunctionStatementNode(Location loc, Location end, Parameters params, CompoundNode body, String name) {
|
||||
// super(loc, end, params, body);
|
||||
// this.name = name;
|
||||
// }
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
package me.topchetoeu.jscript.compilation;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
|
||||
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;
|
||||
|
||||
public class ClassStatementNode extends ClassNode {
|
||||
@Override public void compile(CompileResult target, boolean pollute, String name, BreakpointType bp) {
|
||||
super.compile(target, pollute, name, bp);
|
||||
var i = target.scope.define(DeclarationType.LET, name(), loc());
|
||||
target.add(_i -> i.index().toInit());
|
||||
if (pollute) target.add(Instruction.pushUndefined());
|
||||
}
|
||||
|
||||
public ClassStatementNode(Location loc, Location end, String name, ClassBody body) {
|
||||
super(loc, end, name, body);
|
||||
}
|
||||
|
||||
public static ParseRes<ClassStatementNode> parse(Source src, int i) {
|
||||
var n = Parsing.skipEmpty(src, i);
|
||||
var loc = src.loc(i + n);
|
||||
|
||||
if (!Parsing.isIdentifier(src, i + n, "class")) return ParseRes.failed();
|
||||
n += 5;
|
||||
|
||||
var name = Parsing.parseIdentifier(src, i + n);
|
||||
if (!name.isSuccess()) return name.chainError(src.loc(i + n), "Expected a class name");
|
||||
n += name.n;
|
||||
|
||||
var body = parseBody(src, i + n);
|
||||
if (!body.isSuccess()) return body.chainError(src.loc(i + n), "Expected a class body");
|
||||
n += body.n;
|
||||
|
||||
return ParseRes.res(new ClassStatementNode(loc, src.loc(i + n), name.result, body.result), n);
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
package me.topchetoeu.jscript.compilation;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
|
||||
import me.topchetoeu.jscript.common.environment.Environment;
|
||||
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.control.ReturnNode;
|
||||
import me.topchetoeu.jscript.compilation.patterns.Pattern;
|
||||
|
||||
public class FunctionArrowNode extends FunctionNode {
|
||||
@Override public String name() { return null; }
|
||||
|
||||
@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, false, true, false, null, captures(id, target)));
|
||||
}
|
||||
|
||||
@Override protected Environment rootEnv(Environment env) {
|
||||
return env.getWith(ClassNode.CLASS_ROOT, () -> super.rootEnv(env));
|
||||
}
|
||||
|
||||
public FunctionArrowNode(Location loc, Location end, Parameters params, Node body) {
|
||||
super(loc, end, params, expToBody(body));
|
||||
}
|
||||
|
||||
private static final CompoundNode expToBody(Node node) {
|
||||
if (node instanceof CompoundNode res) return res;
|
||||
else return new CompoundNode(node.loc(), false, new ReturnNode(node.loc(), node));
|
||||
}
|
||||
|
||||
public static ParseRes<FunctionArrowNode> parse(Source src, int i) {
|
||||
var n = Parsing.skipEmpty(src, i);
|
||||
var loc = src.loc(i + n);
|
||||
|
||||
Parameters params;
|
||||
|
||||
if (src.is(i + n, "(")) {
|
||||
var paramsRes = Parameters.parseParameters(src, i + n);
|
||||
if (!paramsRes.isSuccess()) return paramsRes.chainError();
|
||||
n += paramsRes.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
params = paramsRes.result;
|
||||
}
|
||||
else {
|
||||
var singleParam = Pattern.parse(src, i + n, true);
|
||||
if (!singleParam.isSuccess()) return ParseRes.failed();
|
||||
n += singleParam.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
params = new Parameters(Arrays.asList(singleParam.result));
|
||||
}
|
||||
|
||||
if (!src.is(i + n, "=>")) return ParseRes.failed();
|
||||
n += 2;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (src.is(i + n, "{")) {
|
||||
var body = CompoundNode.parse(src, i + n);
|
||||
if (!body.isSuccess()) return body.chainError(src.loc(i + n), "Expected a compount statement after '=>'");
|
||||
n += body.n;
|
||||
|
||||
return ParseRes.res(new FunctionArrowNode(loc, src.loc(i + n - 1), params, body.result), n);
|
||||
}
|
||||
else {
|
||||
var body = JavaScript.parseExpression(src, i + n, 2);
|
||||
if (!body.isSuccess()) return body.chainError(src.loc(i + n), "Expected a compount statement after '=>'");
|
||||
n += body.n;
|
||||
|
||||
return ParseRes.res(new FunctionArrowNode(loc, src.loc(i + n - 1), params, body.result), n);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
package me.topchetoeu.jscript.compilation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
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.patterns.Pattern;
|
||||
import me.topchetoeu.jscript.compilation.values.operations.AssignNode;
|
||||
|
||||
public final class Parameters {
|
||||
public final int length;
|
||||
public final List<Pattern> params;
|
||||
public final Pattern rest;
|
||||
|
||||
public Parameters(List<Pattern> params, Pattern rest) {
|
||||
var len = params.size();
|
||||
|
||||
for (var i = params.size() - 1; i >= 0; i--) {
|
||||
if (!(params.get(i) instanceof AssignNode)) break;
|
||||
len--;
|
||||
}
|
||||
|
||||
this.params = params;
|
||||
this.length = len;
|
||||
this.rest = rest;
|
||||
}
|
||||
public Parameters(List<Pattern> params) {
|
||||
this(params, null);
|
||||
}
|
||||
|
||||
public static ParseRes<Parameters> parseParameters(Source src, int i) {
|
||||
var n = Parsing.skipEmpty(src, i);
|
||||
|
||||
var openParen = Parsing.parseOperator(src, i + n, "(");
|
||||
if (!openParen.isSuccess()) return openParen.chainError(src.loc(i + n), "Expected a parameter list");
|
||||
n += openParen.n;
|
||||
|
||||
var params = new ArrayList<Pattern>();
|
||||
|
||||
var closeParen = Parsing.parseOperator(src, i + n, ")");
|
||||
n += closeParen.n;
|
||||
|
||||
if (!closeParen.isSuccess()) {
|
||||
while (true) {
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (src.is(i + n, "...")) {
|
||||
n += 3;
|
||||
|
||||
var rest = Pattern.parse(src, i + n, true);
|
||||
if (!rest.isSuccess()) return ParseRes.error(src.loc(i + n), "Expected a rest parameter");
|
||||
n += rest.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (!src.is(i + n, ")")) return ParseRes.error(src.loc(i + n), "Expected an end of parameters list after rest parameter");
|
||||
n++;
|
||||
|
||||
return ParseRes.res(new Parameters(params, rest.result), n);
|
||||
}
|
||||
|
||||
var param = Pattern.parse(src, i + n, true);
|
||||
if (!param.isSuccess()) return ParseRes.error(src.loc(i + n), "Expected a parameter or a closing brace");
|
||||
n += param.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
params.add(param.result);
|
||||
|
||||
if (src.is(i + n, ",")) {
|
||||
n++;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
}
|
||||
|
||||
if (src.is(i + n, ")")) {
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ParseRes.res(new Parameters(params), n);
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
package me.topchetoeu.jscript.compilation.control;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
|
||||
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.CompileResult;
|
||||
import me.topchetoeu.jscript.compilation.CompoundNode;
|
||||
import me.topchetoeu.jscript.compilation.DeferredIntSupplier;
|
||||
import me.topchetoeu.jscript.compilation.JavaScript;
|
||||
import me.topchetoeu.jscript.compilation.LabelContext;
|
||||
import me.topchetoeu.jscript.compilation.Node;
|
||||
import me.topchetoeu.jscript.compilation.patterns.Binding;
|
||||
|
||||
public class ForOfNode extends Node {
|
||||
public final Binding binding;
|
||||
public final Node iterable, body;
|
||||
public final String label;
|
||||
|
||||
@Override public void resolve(CompileResult target) {
|
||||
body.resolve(target);
|
||||
binding.resolve(target);
|
||||
}
|
||||
|
||||
@Override public void compile(CompileResult target, boolean pollute) {
|
||||
binding.declareLateInit(target);
|
||||
|
||||
iterable.compile(target, true, BreakpointType.STEP_OVER);
|
||||
target.add(Instruction.dup());
|
||||
target.add(Instruction.loadIntrinsics("it_key"));
|
||||
target.add(Instruction.loadMember()).setLocation(iterable.loc());
|
||||
target.add(Instruction.call(0, true)).setLocation(iterable.loc());
|
||||
|
||||
int start = target.size();
|
||||
target.add(Instruction.dup(2, 0));
|
||||
target.add(Instruction.loadMember("next")).setLocation(iterable.loc());
|
||||
target.add(Instruction.call(0, true)).setLocation(iterable.loc());
|
||||
target.add(Instruction.dup());
|
||||
target.add(Instruction.loadMember("done")).setLocation(iterable.loc());
|
||||
int mid = target.temp();
|
||||
|
||||
target.add(Instruction.loadMember("value")).setLocation(binding.loc);
|
||||
binding.assign(target, false);
|
||||
|
||||
var end = new DeferredIntSupplier();
|
||||
|
||||
LabelContext.pushLoop(target.env, loc(), label, end, start);
|
||||
CompoundNode.compileMultiEntry(body, target, false, BreakpointType.STEP_OVER);
|
||||
LabelContext.popLoop(target.env, label);
|
||||
|
||||
int endI = target.size();
|
||||
end.set(endI);
|
||||
|
||||
target.add(Instruction.jmp(start - endI));
|
||||
target.add(Instruction.discard());
|
||||
target.add(Instruction.discard());
|
||||
target.set(mid, Instruction.jmpIf(endI - mid + 1));
|
||||
if (pollute) target.add(Instruction.pushUndefined());
|
||||
}
|
||||
|
||||
public ForOfNode(Location loc, String label, Binding binding, Node object, Node body) {
|
||||
super(loc);
|
||||
this.label = label;
|
||||
this.binding = binding;
|
||||
this.iterable = object;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public static ParseRes<ForOfNode> parse(Source src, int i) {
|
||||
var n = Parsing.skipEmpty(src, i);
|
||||
var loc = src.loc(i + n);
|
||||
|
||||
var label = JavaScript.parseLabel(src, i + n);
|
||||
n += label.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (!Parsing.isIdentifier(src, i + n, "for")) return ParseRes.failed();
|
||||
n += 3;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (!src.is(i + n, "(")) return ParseRes.error(src.loc(i + n), "Expected an opening paren");
|
||||
n++;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
var binding = Binding.parse(src, i + n);
|
||||
if (!binding.isSuccess()) return ParseRes.error(src.loc(i + n), "Expected a binding in for-of loop");
|
||||
n += binding.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (!Parsing.isIdentifier(src, i + n, "of")) return ParseRes.error(src.loc(i + n), "Expected 'of' keyword after variable declaration");
|
||||
n += 2;
|
||||
|
||||
var obj = JavaScript.parseExpression(src, i + n, 0);
|
||||
if (!obj.isSuccess()) return obj.chainError(src.loc(i + n), "Expected a value");
|
||||
n += obj.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (!src.is(i + n, ")")) return ParseRes.error(src.loc(i + n), "Expected a closing paren");
|
||||
n++;
|
||||
|
||||
var bodyRes = JavaScript.parseStatement(src, i + n);
|
||||
if (!bodyRes.isSuccess()) return bodyRes.chainError(src.loc(i + n), "Expected a for-of body");
|
||||
n += bodyRes.n;
|
||||
|
||||
return ParseRes.res(new ForOfNode(loc, label.result, binding.result, obj.result, bodyRes.result), n);
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package me.topchetoeu.jscript.compilation.members;
|
||||
|
||||
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;
|
||||
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.patterns.AssignTarget;
|
||||
import me.topchetoeu.jscript.compilation.values.VariableNode;
|
||||
import me.topchetoeu.jscript.compilation.values.constants.StringNode;
|
||||
import me.topchetoeu.jscript.compilation.values.operations.AssignNode;
|
||||
|
||||
public class AssignShorthandNode implements Member {
|
||||
public final Location loc;
|
||||
public final Node key;
|
||||
public final AssignTarget target;
|
||||
public final Node value;
|
||||
|
||||
@Override public Location loc() { return loc; }
|
||||
|
||||
@Override public void compile(CompileResult target, boolean pollute, boolean enumerable) {
|
||||
throw new SyntaxException(loc(), "Unexpected assign shorthand in non-destructor context");
|
||||
}
|
||||
|
||||
public AssignShorthandNode(Location loc, Node key, AssignTarget target, Node value) {
|
||||
this.loc = loc;
|
||||
this.key = key;
|
||||
this.target = target;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public AssignTarget target() {
|
||||
return new AssignNode(loc(), target, value);
|
||||
}
|
||||
|
||||
public static ParseRes<AssignShorthandNode> parse(Source src, int i) {
|
||||
var n = Parsing.skipEmpty(src, i);
|
||||
var loc = src.loc(i + n);
|
||||
|
||||
var var = VariableNode.parse(src, i + n);
|
||||
if (!var.isSuccess()) return var.chainError();
|
||||
n += var.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (!src.is(i + n, "=")) return ParseRes.failed();
|
||||
n++;
|
||||
|
||||
var value = JavaScript.parseExpression(src, i + n, 2);
|
||||
if (!value.isSuccess()) return value.chainError(src.loc(i + n), "Expected a shorthand initializer");
|
||||
n += value.n;
|
||||
|
||||
return ParseRes.res(new AssignShorthandNode(loc, new StringNode(loc, var.result.name), var.result, value.result), n);
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
package me.topchetoeu.jscript.compilation.members;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
|
||||
import me.topchetoeu.jscript.common.environment.Environment;
|
||||
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.CompileResult;
|
||||
import me.topchetoeu.jscript.compilation.CompoundNode;
|
||||
import me.topchetoeu.jscript.compilation.FunctionNode;
|
||||
import me.topchetoeu.jscript.compilation.Node;
|
||||
import me.topchetoeu.jscript.compilation.Parameters;
|
||||
import me.topchetoeu.jscript.compilation.values.ObjectNode;
|
||||
import me.topchetoeu.jscript.compilation.values.constants.StringNode;
|
||||
|
||||
public class MethodMemberNode extends FunctionNode implements Member {
|
||||
public final Node key;
|
||||
|
||||
@Override public String name() {
|
||||
if (key instanceof StringNode str) return str.value;
|
||||
else return null;
|
||||
}
|
||||
|
||||
@Override protected Environment rootEnv(Environment env) {
|
||||
return env;
|
||||
}
|
||||
|
||||
@Override public void compile(CompileResult target, boolean pollute, String name, BreakpointType bp) {
|
||||
if (pollute) target.add(Instruction.dup());
|
||||
key.compile(target, true);
|
||||
|
||||
var id = target.addChild(compileBody(target, name, null));
|
||||
target.add(_i -> Instruction.loadFunc(id, true, false, false, false, null, captures(id, target)));
|
||||
}
|
||||
|
||||
@Override public void compile(CompileResult target, boolean pollute, boolean enumerable) {
|
||||
compile(target, pollute);
|
||||
target.add(Instruction.defField(enumerable));
|
||||
}
|
||||
|
||||
public MethodMemberNode(Location loc, Location end, Node key, Parameters params, CompoundNode body) {
|
||||
super(loc, end, params, body);
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public static ParseRes<MethodMemberNode> parse(Source src, int i) {
|
||||
var n = Parsing.skipEmpty(src, i);
|
||||
var loc = src.loc(i + n);
|
||||
|
||||
var name = ObjectNode.parsePropName(src, i + n);
|
||||
if (!name.isSuccess()) return name.chainError();
|
||||
n += name.n;
|
||||
|
||||
var params = Parameters.parseParameters(src, i + n);
|
||||
if (!params.isSuccess()) return params.chainError(src.loc(i + n), "Expected an argument list");
|
||||
n += params.n;
|
||||
|
||||
var body = CompoundNode.parse(src, i + n);
|
||||
if (!body.isSuccess()) return body.chainError(src.loc(i + n), "Expected a compound statement for property accessor.");
|
||||
n += body.n;
|
||||
|
||||
var end = src.loc(i + n - 1);
|
||||
|
||||
return ParseRes.res(new MethodMemberNode(
|
||||
loc, end, name.result, params.result, body.result
|
||||
), n);
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
package me.topchetoeu.jscript.compilation.patterns;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.Operation;
|
||||
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;
|
||||
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;
|
||||
|
||||
public class AssignPattern implements Pattern {
|
||||
public final Location loc;
|
||||
public final AssignTarget assignable;
|
||||
public final Node value;
|
||||
|
||||
@Override public Location loc() { return loc; }
|
||||
|
||||
@Override public void destructDeclResolve(CompileResult target) {
|
||||
if (!(assignable instanceof Pattern p)) throw new SyntaxException(assignable.loc(), "Unexpected non-pattern in destruct context");
|
||||
p.destructDeclResolve(target);
|
||||
}
|
||||
|
||||
private void common(CompileResult target) {
|
||||
target.add(Instruction.dup());
|
||||
target.add(Instruction.pushUndefined());
|
||||
target.add(Instruction.operation(Operation.EQUALS));
|
||||
var start = target.temp();
|
||||
target.add(Instruction.discard());
|
||||
|
||||
value.compile(target, true);
|
||||
|
||||
target.set(start, Instruction.jmpIfNot(target.size() - start));
|
||||
}
|
||||
|
||||
@Override public void declare(CompileResult target, DeclarationType decl, boolean lateInitializer) {
|
||||
if (lateInitializer) {
|
||||
if (assignable instanceof Pattern p) p.declare(target, decl, lateInitializer);
|
||||
else throw new SyntaxException(assignable.loc(), "Unexpected non-pattern in destruct context");
|
||||
}
|
||||
else throw new SyntaxException(loc(), "Expected an assignment value for destructor declaration");
|
||||
}
|
||||
@Override public void destruct(CompileResult target, DeclarationType decl, boolean shouldDeclare) {
|
||||
if (!(assignable instanceof Pattern p)) throw new SyntaxException(assignable.loc(), "Unexpected non-pattern in destruct context");
|
||||
common(target);
|
||||
p.destruct(target, decl, shouldDeclare);
|
||||
}
|
||||
|
||||
@Override public void beforeAssign(CompileResult target) {
|
||||
assignable.beforeAssign(target);
|
||||
}
|
||||
@Override public void afterAssign(CompileResult target, boolean pollute) {
|
||||
common(target);
|
||||
assignable.afterAssign(target, false);
|
||||
}
|
||||
|
||||
public AssignPattern(Location loc, Pattern assignable, Node value) {
|
||||
this.loc = loc;
|
||||
this.assignable = assignable;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static ParseRes<AssignPattern> parse(Source src, int i) {
|
||||
var n = Parsing.skipEmpty(src, i);
|
||||
var loc = src.loc(i + n);
|
||||
|
||||
var pattern = Pattern.parse(src, i + n, false);
|
||||
if (!pattern.isSuccess()) return pattern.chainError();
|
||||
n += pattern.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (!src.is(i + n, "=")) return ParseRes.failed();
|
||||
n++;
|
||||
|
||||
var value = JavaScript.parseExpression(src, i + n, 2);
|
||||
if (!value.isSuccess()) return value.chainError(src.loc(i + n), "Expected a default value");
|
||||
n += value.n;
|
||||
|
||||
return ParseRes.res(new AssignPattern(loc, pattern.result, value.result), n);
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
package me.topchetoeu.jscript.compilation.patterns;
|
||||
|
||||
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;
|
||||
import me.topchetoeu.jscript.common.parsing.Source;
|
||||
import me.topchetoeu.jscript.compilation.CompileResult;
|
||||
import me.topchetoeu.jscript.compilation.JavaScript;
|
||||
import me.topchetoeu.jscript.compilation.JavaScript.DeclarationType;
|
||||
|
||||
public class Binding implements Pattern {
|
||||
public final Location loc;
|
||||
public final DeclarationType type;
|
||||
public final AssignTarget assignable;
|
||||
|
||||
@Override public Location loc() { return loc; }
|
||||
|
||||
@Override public void destructDeclResolve(CompileResult target) {
|
||||
if (type != null && !type.strict) {
|
||||
if (!(assignable instanceof Pattern p)) throw new SyntaxException(assignable.loc(), "Unexpected non-pattern in destruct context");
|
||||
p.destructDeclResolve(target);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void destruct(CompileResult target, DeclarationType decl, boolean shouldDeclare) {
|
||||
if (!(assignable instanceof Pattern p)) throw new SyntaxException(assignable.loc(), "Unexpected non-pattern in destruct context");
|
||||
p.destruct(target, decl, shouldDeclare);
|
||||
}
|
||||
@Override public void declare(CompileResult target, DeclarationType decl, boolean lateInitializer) {
|
||||
if (!(assignable instanceof Pattern p)) throw new SyntaxException(assignable.loc(), "Unexpected non-pattern in destruct context");
|
||||
p.declare(target, decl, lateInitializer);
|
||||
}
|
||||
|
||||
public void resolve(CompileResult target) {
|
||||
if (type != null) destructDeclResolve(target);
|
||||
}
|
||||
|
||||
public void declare(CompileResult target, boolean hasInit) {
|
||||
if (type != null) destructVar(target, type, hasInit);
|
||||
}
|
||||
public void declareLateInit(CompileResult target) {
|
||||
if (type != null) declare(target, type, true);
|
||||
}
|
||||
|
||||
@Override public void afterAssign(CompileResult target, boolean pollute) {
|
||||
assignable.assign(target, pollute);
|
||||
}
|
||||
|
||||
public Binding(Location loc, DeclarationType type, AssignTarget assignable) {
|
||||
this.loc = loc;
|
||||
this.type = type;
|
||||
this.assignable = assignable;
|
||||
}
|
||||
|
||||
public static ParseRes<Binding> parse(Source src, int i) {
|
||||
var n = Parsing.skipEmpty(src, i);
|
||||
var loc = src.loc(i + n);
|
||||
|
||||
var declType = JavaScript.parseDeclarationType(src, i + n);
|
||||
if (!declType.isSuccess()) {
|
||||
var res = JavaScript.parseExpression(src, i + n, 13);
|
||||
if (res.isSuccess() && res.result instanceof AssignTargetLike target) {
|
||||
n += res.n;
|
||||
return ParseRes.res(new Binding(loc, null, target.toAssignTarget()), n);
|
||||
}
|
||||
else return ParseRes.failed();
|
||||
}
|
||||
else {
|
||||
n += declType.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
var res = Pattern.parse(src, i + n, false);
|
||||
if (!res.isSuccess()) return ParseRes.failed();
|
||||
n += res.n;
|
||||
|
||||
return ParseRes.res(new Binding(loc, declType.result, res.result), n);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,161 +0,0 @@
|
||||
package me.topchetoeu.jscript.compilation.patterns;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
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;
|
||||
import me.topchetoeu.jscript.common.parsing.Source;
|
||||
import me.topchetoeu.jscript.compilation.CompileResult;
|
||||
import me.topchetoeu.jscript.compilation.Node;
|
||||
import me.topchetoeu.jscript.compilation.JavaScript.DeclarationType;
|
||||
import me.topchetoeu.jscript.compilation.values.ObjectNode;
|
||||
import me.topchetoeu.jscript.compilation.values.VariableNode;
|
||||
import me.topchetoeu.jscript.compilation.values.constants.StringNode;
|
||||
import me.topchetoeu.jscript.compilation.values.operations.IndexNode;
|
||||
|
||||
public class ObjectPattern extends Node implements Pattern {
|
||||
public static final class Member {
|
||||
public final Node key;
|
||||
public final AssignTarget consumable;
|
||||
|
||||
public Member(Node key, AssignTarget consumer) {
|
||||
this.key = key;
|
||||
this.consumable = consumer;
|
||||
}
|
||||
}
|
||||
|
||||
public final List<Member> members;
|
||||
|
||||
public void compile(CompileResult target, Consumer<AssignTarget> consumer, boolean pollute) {
|
||||
for (var el : members) {
|
||||
target.add(Instruction.dup());
|
||||
IndexNode.indexLoad(target, el.key, true);
|
||||
consumer.accept(el.consumable);
|
||||
}
|
||||
|
||||
if (!pollute) target.add(Instruction.discard());
|
||||
}
|
||||
|
||||
@Override public void destructDeclResolve(CompileResult target) {
|
||||
for (var t : members) {
|
||||
if (t.consumable instanceof Pattern p) p.destructDeclResolve(target);
|
||||
else throw new SyntaxException(t.consumable.loc(), "Unexpected non-pattern in destruct context");
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void destruct(CompileResult target, DeclarationType decl, boolean shouldDeclare) {
|
||||
compile(target, t -> {
|
||||
if (t instanceof Pattern p) p.destruct(target, decl, shouldDeclare);
|
||||
else throw new SyntaxException(t.loc(), "Unexpected non-pattern in destruct context");
|
||||
}, false);
|
||||
}
|
||||
|
||||
@Override public void afterAssign(CompileResult target, boolean pollute) {
|
||||
compile(target, t -> t.assign(target, false), pollute);
|
||||
}
|
||||
|
||||
@Override public void declare(CompileResult target, DeclarationType decl, boolean lateInitializer) {
|
||||
if (lateInitializer) {
|
||||
for (var t : members) {
|
||||
if (t.consumable instanceof Pattern p) p.declare(target, decl, lateInitializer);
|
||||
else throw new SyntaxException(t.consumable.loc(), "Unexpected non-pattern in destruct context");
|
||||
}
|
||||
}
|
||||
else throw new SyntaxException(loc(), "Object pattern must be initialized");
|
||||
}
|
||||
|
||||
public ObjectPattern(Location loc, List<Member> members) {
|
||||
super(loc);
|
||||
this.members = members;
|
||||
}
|
||||
|
||||
private static ParseRes<Member> parseShorthand(Source src, int i) {
|
||||
ParseRes<Pattern> res = ParseRes.first(src, i,
|
||||
AssignPattern::parse,
|
||||
VariableNode::parse
|
||||
);
|
||||
|
||||
if (res.isSuccess()) {
|
||||
if (res.result instanceof AssignPattern assign) {
|
||||
if (assign.assignable instanceof VariableNode var) {
|
||||
return ParseRes.res(new Member(new StringNode(var.loc(), var.name), res.result), res.n);
|
||||
}
|
||||
}
|
||||
else if (res.result instanceof VariableNode var) {
|
||||
return ParseRes.res(new Member(new StringNode(var.loc(), var.name), res.result), res.n);
|
||||
}
|
||||
}
|
||||
|
||||
return res.chainError();
|
||||
}
|
||||
private static ParseRes<Member> parseKeyed(Source src, int i) {
|
||||
var n = Parsing.skipEmpty(src, i);
|
||||
|
||||
var key = ObjectNode.parsePropName(src, i + n);
|
||||
if (!key.isSuccess()) return key.chainError();
|
||||
n += key.n;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (!src.is(i + n , ":")) return ParseRes.failed();
|
||||
n++;
|
||||
|
||||
ParseRes<Pattern> res = Pattern.parse(src, i + n, true);
|
||||
if (!res.isSuccess()) return ParseRes.error(src.loc(i + n), "Expected a pattern after colon");
|
||||
n += res.n;
|
||||
|
||||
return ParseRes.res(new Member(key.result, res.result), n);
|
||||
}
|
||||
|
||||
public static ParseRes<ObjectPattern> parse(Source src, int i) {
|
||||
var n = Parsing.skipEmpty(src, i);
|
||||
var loc = src.loc(i + n);
|
||||
|
||||
if (!src.is(i + n, "{")) return ParseRes.failed();
|
||||
n++;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
var members = new LinkedList<Member>();
|
||||
|
||||
if (src.is(i + n, "}")) {
|
||||
n++;
|
||||
return ParseRes.res(new ObjectPattern(loc, members), n);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
ParseRes<Member> prop = ParseRes.first(src, i + n,
|
||||
ObjectPattern::parseKeyed,
|
||||
ObjectPattern::parseShorthand
|
||||
);
|
||||
|
||||
if (!prop.isSuccess()) return prop.chainError(src.loc(i + n), "Expected a member in object pattern");
|
||||
n += prop.n;
|
||||
|
||||
members.add(prop.result);
|
||||
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
if (src.is(i + n, ",")) {
|
||||
n++;
|
||||
n += Parsing.skipEmpty(src, i + n);
|
||||
|
||||
if (src.is(i + n, "}")) {
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (src.is(i + n, "}")) {
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
else ParseRes.error(src.loc(i + n), "Expected a comma or a closing brace.");
|
||||
}
|
||||
|
||||
return ParseRes.res(new ObjectPattern(loc, members), n);
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package me.topchetoeu.jscript.compilation.patterns;
|
||||
|
||||
import me.topchetoeu.jscript.common.parsing.Location;
|
||||
import me.topchetoeu.jscript.common.parsing.ParseRes;
|
||||
import me.topchetoeu.jscript.common.parsing.Source;
|
||||
import me.topchetoeu.jscript.compilation.CompileResult;
|
||||
import me.topchetoeu.jscript.compilation.JavaScript.DeclarationType;
|
||||
import me.topchetoeu.jscript.compilation.values.VariableNode;
|
||||
|
||||
/**
|
||||
* Represents all nodes that can be a destructors (note that all destructors are assign targets, too)
|
||||
*/
|
||||
public interface Pattern extends AssignTarget {
|
||||
Location loc();
|
||||
|
||||
/**
|
||||
* Called when the destructor has to declare
|
||||
* @param target
|
||||
*/
|
||||
void destructDeclResolve(CompileResult target);
|
||||
|
||||
/**
|
||||
* Called when a declaration-like is being destructed
|
||||
* @param decl The variable type the destructor must declare, if it is a named pne
|
||||
*/
|
||||
void destruct(CompileResult target, DeclarationType decl, boolean shouldDeclare);
|
||||
|
||||
/**
|
||||
* Run when destructing a declaration without an initializer
|
||||
*/
|
||||
void declare(CompileResult target, DeclarationType decl, boolean lateInitializer);
|
||||
|
||||
public default void destructArg(CompileResult target, DeclarationType decl) {
|
||||
destruct(target, decl, false);
|
||||
}
|
||||
public default void destructVar(CompileResult target, DeclarationType decl, boolean hasInitializer) {
|
||||
if (hasInitializer) {
|
||||
if (decl == null || !decl.strict) destruct(target, null, true);
|
||||
else destruct(target, decl, true);
|
||||
}
|
||||
else {
|
||||
if (decl == null || !decl.strict) declare(target, null, false);
|
||||
else declare(target, decl, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static ParseRes<Pattern> parse(Source src, int i, boolean withDefault) {
|
||||
return withDefault ?
|
||||
ParseRes.first(src, i,
|
||||
AssignPattern::parse,
|
||||
ObjectPattern::parse,
|
||||
VariableNode::parse
|
||||
) :
|
||||
ParseRes.first(src, i,
|
||||
ObjectPattern::parse,
|
||||
VariableNode::parse
|
||||
);
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package me.topchetoeu.jscript.compilation.values;
|
||||
|
||||
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.JavaScript;
|
||||
|
||||
public class ClassValueNode extends ClassNode {
|
||||
public ClassValueNode(Location loc, Location end, String name, ClassBody body) {
|
||||
super(loc, end, name, body);
|
||||
}
|
||||
|
||||
public static ParseRes<ClassValueNode> parse(Source src, int i) {
|
||||
var n = Parsing.skipEmpty(src, i);
|
||||
var loc = src.loc(i + n);
|
||||
|
||||
if (!Parsing.isIdentifier(src, i + n, "class")) return ParseRes.failed();
|
||||
n += 5;
|
||||
|
||||
var name = Parsing.parseIdentifier(src, i + n);
|
||||
if (name.isSuccess() && !JavaScript.checkVarName(name.result)) {
|
||||
name = ParseRes.error(src.loc(i + n), "Unexpected keyword '" + name.result + "'");
|
||||
}
|
||||
n += name.n;
|
||||
|
||||
var body = parseBody(src, i + n);
|
||||
if (!body.isSuccess()) return body.chainError(name).chainError(src.loc(i + n), "Expected a class body");
|
||||
n += body.n;
|
||||
|
||||
return ParseRes.res(new ClassValueNode(loc, src.loc(i + n), name.result, body.result), n);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user