summaryrefslogtreecommitdiffstats
path: root/js/src/tests/js1_8_5/reflect-parse/alternateBuilder.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/js1_8_5/reflect-parse/alternateBuilder.js')
-rw-r--r--js/src/tests/js1_8_5/reflect-parse/alternateBuilder.js224
1 files changed, 224 insertions, 0 deletions
diff --git a/js/src/tests/js1_8_5/reflect-parse/alternateBuilder.js b/js/src/tests/js1_8_5/reflect-parse/alternateBuilder.js
new file mode 100644
index 000000000..74f0e3e4e
--- /dev/null
+++ b/js/src/tests/js1_8_5/reflect-parse/alternateBuilder.js
@@ -0,0 +1,224 @@
+// |reftest| skip-if(!xulRuntime.shell)
+// A simple proof-of-concept that the builder API can be used to generate other
+// formats, such as JsonMLAst:
+//
+// http://code.google.com/p/es-lab/wiki/JsonMLASTFormat
+//
+// It's incomplete (e.g., it doesn't convert source-location information and
+// doesn't use all the direct-eval rules), but I think it proves the point.
+
+function test() {
+
+var JsonMLAst = (function() {
+function reject() {
+ throw new SyntaxError("node type not supported");
+}
+
+function isDirectEval(expr) {
+ // an approximation to the actual rules. you get the idea
+ return (expr[0] === "IdExpr" && expr[1].name === "eval");
+}
+
+function functionNode(type) {
+ return function(id, args, body, isGenerator, isExpression) {
+ if (isExpression)
+ body = ["ReturnStmt", {}, body];
+
+ if (!id)
+ id = ["Empty"];
+
+ // Patch up the argument node types: s/IdExpr/IdPatt/g
+ for (var i = 0; i < args.length; i++) {
+ args[i][0] = "IdPatt";
+ }
+
+ args.unshift("ParamDecl", {});
+
+ return [type, {}, id, args, body];
+ }
+}
+
+return {
+ program: function(stmts) {
+ stmts.unshift("Program", {});
+ return stmts;
+ },
+ identifier: function(name) {
+ return ["IdExpr", { name: name }];
+ },
+ literal: function(val) {
+ return ["LiteralExpr", { value: val }];
+ },
+ expressionStatement: expr => expr,
+ conditionalExpression: function(test, cons, alt) {
+ return ["ConditionalExpr", {}, test, cons, alt];
+ },
+ unaryExpression: function(op, expr) {
+ return ["UnaryExpr", {op: op}, expr];
+ },
+ binaryExpression: function(op, left, right) {
+ return ["BinaryExpr", {op: op}, left, right];
+ },
+ property: function(kind, key, val) {
+ return [kind === "init"
+ ? "DataProp"
+ : kind === "get"
+ ? "GetterProp"
+ : "SetterProp",
+ {name: key[1].name}, val];
+ },
+ functionDeclaration: functionNode("FunctionDecl"),
+ variableDeclaration: function(kind, elts) {
+ if (kind === "let" || kind === "const")
+ throw new SyntaxError("let and const not supported");
+ elts.unshift("VarDecl", {});
+ return elts;
+ },
+ variableDeclarator: function(id, init) {
+ id[0] = "IdPatt";
+ if (!init)
+ return id;
+ return ["InitPatt", {}, id, init];
+ },
+ sequenceExpression: function(exprs) {
+ var length = exprs.length;
+ var result = ["BinaryExpr", {op:","}, exprs[exprs.length - 2], exprs[exprs.length - 1]];
+ for (var i = exprs.length - 3; i >= 0; i--) {
+ result = ["BinaryExpr", {op:","}, exprs[i], result];
+ }
+ return result;
+ },
+ assignmentExpression: function(op, lhs, expr) {
+ return ["AssignExpr", {op: op}, lhs, expr];
+ },
+ logicalExpression: function(op, left, right) {
+ return [op === "&&" ? "LogicalAndExpr" : "LogicalOrExpr", {}, left, right];
+ },
+ updateExpression: function(expr, op, isPrefix) {
+ return ["CountExpr", {isPrefix:isPrefix, op:op}, expr];
+ },
+ newExpression: function(callee, args) {
+ args.unshift("NewExpr", {}, callee);
+ return args;
+ },
+ callExpression: function(callee, args) {
+ args.unshift(isDirectEval(callee) ? "EvalExpr" : "CallExpr", {}, callee);
+ return args;
+ },
+ memberExpression: function(isComputed, expr, member) {
+ return ["MemberExpr", {}, expr, isComputed ? member : ["LiteralExpr", {type: "string", value: member[1].name}]];
+ },
+ functionExpression: functionNode("FunctionExpr"),
+ arrayExpression: function(elts) {
+ for (var i = 0; i < elts.length; i++) {
+ if (!elts[i])
+ elts[i] = ["Empty"];
+ }
+ elts.unshift("ArrayExpr", {});
+ return elts;
+ },
+ objectExpression: function(props) {
+ props.unshift("ObjectExpr", {});
+ return props;
+ },
+ thisExpression: function() {
+ return ["ThisExpr", {}];
+ },
+ templateLiteral: function(elts) {
+ for (var i = 0; i < elts.length; i++) {
+ if (!elts[i])
+ elts[i] = ["Empty"];
+ }
+ elts.unshift("TemplateLit", {});
+ return elts;
+ },
+
+ graphExpression: reject,
+ graphIndexExpression: reject,
+ comprehensionExpression: reject,
+ generatorExpression: reject,
+ yieldExpression: reject,
+
+ emptyStatement: () => ["EmptyStmt", {}],
+ blockStatement: function(stmts) {
+ stmts.unshift("BlockStmt", {});
+ return stmts;
+ },
+ labeledStatement: function(lab, stmt) {
+ return ["LabelledStmt", {label: lab}, stmt];
+ },
+ ifStatement: function(test, cons, alt) {
+ return ["IfStmt", {}, test, cons, alt || ["EmptyStmt", {}]];
+ },
+ switchStatement: function(test, clauses, isLexical) {
+ clauses.unshift("SwitchStmt", {}, test);
+ return clauses;
+ },
+ whileStatement: function(expr, stmt) {
+ return ["WhileStmt", {}, expr, stmt];
+ },
+ doWhileStatement: function(stmt, expr) {
+ return ["DoWhileStmt", {}, stmt, expr];
+ },
+ forStatement: function(init, test, update, body) {
+ return ["ForStmt", {}, init || ["Empty"], test || ["Empty"], update || ["Empty"], body];
+ },
+ forInStatement: function(lhs, rhs, body) {
+ return ["ForInStmt", {}, lhs, rhs, body];
+ },
+ breakStatement: function(lab) {
+ return lab ? ["BreakStmt", {}, lab] : ["BreakStmt", {}];
+ },
+ continueStatement: function(lab) {
+ return lab ? ["ContinueStmt", {}, lab] : ["ContinueStmt", {}];
+ },
+ withStatement: function(expr, stmt) {
+ return ["WithStmt", {}, expr, stmt];
+ },
+ returnStatement: function(expr) {
+ return expr ? ["ReturnStmt", {}, expr] : ["ReturnStmt", {}];
+ },
+ tryStatement: function(body, catches, fin) {
+ if (catches.length > 1)
+ throw new SyntaxError("multiple catch clauses not supported");
+ var node = ["TryStmt", body, catches[0] || ["Empty"]];
+ if (fin)
+ node.push(fin);
+ return node;
+ },
+ throwStatement: function(expr) {
+ return ["ThrowStmt", {}, expr];
+ },
+ debuggerStatement: () => ["DebuggerStmt", {}],
+ letStatement: reject,
+ switchCase: function(expr, stmts) {
+ if (expr)
+ stmts.unshift("SwitchCase", {}, expr);
+ else
+ stmts.unshift("DefaultCase", {});
+ return stmts;
+ },
+ catchClause: function(param, guard, body) {
+ if (guard)
+ throw new SyntaxError("catch guards not supported");
+ param[0] = "IdPatt";
+ return ["CatchClause", {}, param, body];
+ },
+ comprehensionBlock: reject,
+
+ arrayPattern: reject,
+ objectPattern: reject,
+ propertyPattern: reject,
+};
+})();
+
+Pattern(["Program", {},
+ ["BinaryExpr", {op: "+"},
+ ["LiteralExpr", {value: 2}],
+ ["BinaryExpr", {op: "*"},
+ ["UnaryExpr", {op: "-"}, ["IdExpr", {name: "x"}]],
+ ["IdExpr", {name: "y"}]]]]).match(Reflect.parse("2 + (-x * y)", {loc: false, builder: JsonMLAst}));
+
+}
+
+runtest(test);