js/src/tests/js1_8_5/extensions/reflect-parse.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/tests/js1_8_5/extensions/reflect-parse.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1205 @@
     1.4 +// |reftest| skip-if(!xulRuntime.shell)
     1.5 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.6 +/*
     1.7 + * Any copyright is dedicated to the Public Domain.
     1.8 + * http://creativecommons.org/licenses/publicdomain/
     1.9 + */
    1.10 +
    1.11 +(function runtest(main) {
    1.12 +    try {
    1.13 +        main();
    1.14 +    } catch (exc) {
    1.15 +        print(exc.stack);
    1.16 +        throw exc;
    1.17 +    }
    1.18 +})(function main() {
    1.19 +
    1.20 +var { Pattern, MatchError } = Match;
    1.21 +
    1.22 +var _ = Pattern.ANY;
    1.23 +
    1.24 +function program(elts) Pattern({ type: "Program", body: elts })
    1.25 +function exprStmt(expr) Pattern({ type: "ExpressionStatement", expression: expr })
    1.26 +function throwStmt(expr) Pattern({ type: "ThrowStatement", argument: expr })
    1.27 +function returnStmt(expr) Pattern({ type: "ReturnStatement", argument: expr })
    1.28 +function yieldExpr(expr) Pattern({ type: "YieldExpression", argument: expr })
    1.29 +function lit(val) Pattern({ type: "Literal", value: val })
    1.30 +function spread(val) Pattern({ type: "SpreadExpression", expression: val})
    1.31 +var thisExpr = Pattern({ type: "ThisExpression" });
    1.32 +function funDecl(id, params, body, defaults=[], rest=null) Pattern(
    1.33 +    { type: "FunctionDeclaration",
    1.34 +      id: id,
    1.35 +      params: params,
    1.36 +      defaults: defaults,
    1.37 +      body: body,
    1.38 +      rest: rest,
    1.39 +      generator: false })
    1.40 +function genFunDecl(id, params, body) Pattern({ type: "FunctionDeclaration",
    1.41 +                                                id: id,
    1.42 +                                                params: params,
    1.43 +                                                defaults: [],
    1.44 +                                                body: body,
    1.45 +                                                generator: true })
    1.46 +function varDecl(decls) Pattern({ type: "VariableDeclaration", declarations: decls, kind: "var" })
    1.47 +function letDecl(decls) Pattern({ type: "VariableDeclaration", declarations: decls, kind: "let" })
    1.48 +function constDecl(decls) Pattern({ type: "VariableDeclaration", declarations: decls, kind: "const" })
    1.49 +function ident(name) Pattern({ type: "Identifier", name: name })
    1.50 +function dotExpr(obj, id) Pattern({ type: "MemberExpression", computed: false, object: obj, property: id })
    1.51 +function memExpr(obj, id) Pattern({ type: "MemberExpression", computed: true, object: obj, property: id })
    1.52 +function forStmt(init, test, update, body) Pattern({ type: "ForStatement", init: init, test: test, update: update, body: body })
    1.53 +function forOfStmt(lhs, rhs, body) Pattern({ type: "ForOfStatement", left: lhs, right: rhs, body: body })
    1.54 +function forInStmt(lhs, rhs, body) Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: false })
    1.55 +function forEachInStmt(lhs, rhs, body) Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: true })
    1.56 +function breakStmt(lab) Pattern({ type: "BreakStatement", label: lab })
    1.57 +function continueStmt(lab) Pattern({ type: "ContinueStatement", label: lab })
    1.58 +function blockStmt(body) Pattern({ type: "BlockStatement", body: body })
    1.59 +var emptyStmt = Pattern({ type: "EmptyStatement" })
    1.60 +function ifStmt(test, cons, alt) Pattern({ type: "IfStatement", test: test, alternate: alt, consequent: cons })
    1.61 +function labStmt(lab, stmt) Pattern({ type: "LabeledStatement", label: lab, body: stmt })
    1.62 +function withStmt(obj, stmt) Pattern({ type: "WithStatement", object: obj, body: stmt })
    1.63 +function whileStmt(test, stmt) Pattern({ type: "WhileStatement", test: test, body: stmt })
    1.64 +function doStmt(stmt, test) Pattern({ type: "DoWhileStatement", test: test, body: stmt })
    1.65 +function switchStmt(disc, cases) Pattern({ type: "SwitchStatement", discriminant: disc, cases: cases })
    1.66 +function caseClause(test, stmts) Pattern({ type: "SwitchCase", test: test, consequent: stmts })
    1.67 +function defaultClause(stmts) Pattern({ type: "SwitchCase", test: null, consequent: stmts })
    1.68 +function catchClause(id, guard, body) Pattern({ type: "CatchClause", param: id, guard: guard, body: body })
    1.69 +function tryStmt(body, guarded, unguarded, fin) Pattern({ type: "TryStatement", block: body, guardedHandlers: guarded, handler: unguarded, finalizer: fin })
    1.70 +function letStmt(head, body) Pattern({ type: "LetStatement", head: head, body: body })
    1.71 +function funExpr(id, args, body, gen) Pattern({ type: "FunctionExpression",
    1.72 +                                                id: id,
    1.73 +                                                params: args,
    1.74 +                                                body: body,
    1.75 +                                                generator: false })
    1.76 +function genFunExpr(id, args, body) Pattern({ type: "FunctionExpression",
    1.77 +                                              id: id,
    1.78 +                                              params: args,
    1.79 +                                              body: body,
    1.80 +                                              generator: true })
    1.81 +function arrowExpr(args, body) Pattern({ type: "ArrowExpression",
    1.82 +                                         params: args,
    1.83 +                                         body: body })
    1.84 +
    1.85 +function unExpr(op, arg) Pattern({ type: "UnaryExpression", operator: op, argument: arg })
    1.86 +function binExpr(op, left, right) Pattern({ type: "BinaryExpression", operator: op, left: left, right: right })
    1.87 +function aExpr(op, left, right) Pattern({ type: "AssignmentExpression", operator: op, left: left, right: right })
    1.88 +function updExpr(op, arg, prefix) Pattern({ type: "UpdateExpression", operator: op, argument: arg, prefix: prefix })
    1.89 +function logExpr(op, left, right) Pattern({ type: "LogicalExpression", operator: op, left: left, right: right })
    1.90 +
    1.91 +function condExpr(test, cons, alt) Pattern({ type: "ConditionalExpression", test: test, consequent: cons, alternate: alt })
    1.92 +function seqExpr(exprs) Pattern({ type: "SequenceExpression", expressions: exprs })
    1.93 +function newExpr(callee, args) Pattern({ type: "NewExpression", callee: callee, arguments: args })
    1.94 +function callExpr(callee, args) Pattern({ type: "CallExpression", callee: callee, arguments: args })
    1.95 +function arrExpr(elts) Pattern({ type: "ArrayExpression", elements: elts })
    1.96 +function objExpr(elts) Pattern({ type: "ObjectExpression", properties: elts })
    1.97 +function compExpr(body, blocks, filter) Pattern({ type: "ComprehensionExpression", body: body, blocks: blocks, filter: filter })
    1.98 +function genExpr(body, blocks, filter) Pattern({ type: "GeneratorExpression", body: body, blocks: blocks, filter: filter })
    1.99 +function graphExpr(idx, body) Pattern({ type: "GraphExpression", index: idx, expression: body })
   1.100 +function letExpr(head, body) Pattern({ type: "LetExpression", head: head, body: body })
   1.101 +function idxExpr(idx) Pattern({ type: "GraphIndexExpression", index: idx })
   1.102 +
   1.103 +function compBlock(left, right) Pattern({ type: "ComprehensionBlock", left: left, right: right, each: false, of: false })
   1.104 +function compEachBlock(left, right) Pattern({ type: "ComprehensionBlock", left: left, right: right, each: true, of: false })
   1.105 +function compOfBlock(left, right) Pattern({ type: "ComprehensionBlock", left: left, right: right, each: false, of: true })
   1.106 +
   1.107 +function arrPatt(elts) Pattern({ type: "ArrayPattern", elements: elts })
   1.108 +function objPatt(elts) Pattern({ type: "ObjectPattern", properties: elts })
   1.109 +
   1.110 +function localSrc(src) "(function(){ " + src + " })"
   1.111 +function localPatt(patt) program([exprStmt(funExpr(null, [], blockStmt([patt])))])
   1.112 +function blockSrc(src) "(function(){ { " + src + " } })"
   1.113 +function blockPatt(patt) program([exprStmt(funExpr(null, [], blockStmt([blockStmt([patt])])))])
   1.114 +
   1.115 +function assertBlockStmt(src, patt) {
   1.116 +    blockPatt(patt).assert(Reflect.parse(blockSrc(src)));
   1.117 +}
   1.118 +
   1.119 +function assertBlockExpr(src, patt) {
   1.120 +    assertBlockStmt(src, exprStmt(patt));
   1.121 +}
   1.122 +
   1.123 +function assertBlockDecl(src, patt, builder) {
   1.124 +    blockPatt(patt).assert(Reflect.parse(blockSrc(src), {builder: builder}));
   1.125 +}
   1.126 +
   1.127 +function assertLocalStmt(src, patt) {
   1.128 +    localPatt(patt).assert(Reflect.parse(localSrc(src)));
   1.129 +}
   1.130 +
   1.131 +function assertLocalExpr(src, patt) {
   1.132 +    assertLocalStmt(src, exprStmt(patt));
   1.133 +}
   1.134 +
   1.135 +function assertLocalDecl(src, patt) {
   1.136 +    localPatt(patt).assert(Reflect.parse(localSrc(src)));
   1.137 +}
   1.138 +
   1.139 +function assertGlobalStmt(src, patt, builder) {
   1.140 +    program([patt]).assert(Reflect.parse(src, {builder: builder}));
   1.141 +}
   1.142 +
   1.143 +function assertGlobalExpr(src, patt, builder) {
   1.144 +    program([exprStmt(patt)]).assert(Reflect.parse(src, {builder: builder}));
   1.145 +    //assertStmt(src, exprStmt(patt));
   1.146 +}
   1.147 +
   1.148 +function assertGlobalDecl(src, patt) {
   1.149 +    program([patt]).assert(Reflect.parse(src));
   1.150 +}
   1.151 +
   1.152 +function assertProg(src, patt) {
   1.153 +    program(patt).assert(Reflect.parse(src));
   1.154 +}
   1.155 +
   1.156 +function assertStmt(src, patt) {
   1.157 +    assertLocalStmt(src, patt);
   1.158 +    assertGlobalStmt(src, patt);
   1.159 +    assertBlockStmt(src, patt);
   1.160 +}
   1.161 +
   1.162 +function assertExpr(src, patt) {
   1.163 +    assertLocalExpr(src, patt);
   1.164 +    assertGlobalExpr(src, patt);
   1.165 +    assertBlockExpr(src, patt);
   1.166 +}
   1.167 +
   1.168 +function assertDecl(src, patt) {
   1.169 +    assertLocalDecl(src, patt);
   1.170 +    assertGlobalDecl(src, patt);
   1.171 +    assertBlockDecl(src, patt);
   1.172 +}
   1.173 +
   1.174 +function assertError(src, errorType) {
   1.175 +    try {
   1.176 +        Reflect.parse(src);
   1.177 +    } catch (expected if expected instanceof errorType) {
   1.178 +        return;
   1.179 +    }
   1.180 +    throw new Error("expected " + errorType.name + " for " + uneval(src));
   1.181 +}
   1.182 +
   1.183 +
   1.184 +// general tests
   1.185 +
   1.186 +// NB: These are useful but for now jit-test doesn't do I/O reliably.
   1.187 +
   1.188 +//program(_).assert(Reflect.parse(snarf('data/flapjax.txt')));
   1.189 +//program(_).assert(Reflect.parse(snarf('data/jquery-1.4.2.txt')));
   1.190 +//program(_).assert(Reflect.parse(snarf('data/prototype.js')));
   1.191 +//program(_).assert(Reflect.parse(snarf('data/dojo.js.uncompressed.js')));
   1.192 +//program(_).assert(Reflect.parse(snarf('data/mootools-1.2.4-core-nc.js')));
   1.193 +
   1.194 +
   1.195 +// declarations
   1.196 +
   1.197 +assertDecl("var x = 1, y = 2, z = 3",
   1.198 +           varDecl([{ id: ident("x"), init: lit(1) },
   1.199 +                    { id: ident("y"), init: lit(2) },
   1.200 +                    { id: ident("z"), init: lit(3) }]));
   1.201 +assertDecl("var x, y, z",
   1.202 +           varDecl([{ id: ident("x"), init: null },
   1.203 +                    { id: ident("y"), init: null },
   1.204 +                    { id: ident("z"), init: null }]));
   1.205 +assertDecl("function foo() { }",
   1.206 +           funDecl(ident("foo"), [], blockStmt([])));
   1.207 +assertDecl("function foo() { return 42 }",
   1.208 +           funDecl(ident("foo"), [], blockStmt([returnStmt(lit(42))])));
   1.209 +
   1.210 +assertDecl("function foo(...rest) { }",
   1.211 +           funDecl(ident("foo"), [], blockStmt([]), [], ident("rest")));
   1.212 +
   1.213 +assertDecl("function foo(a=4) { }", funDecl(ident("foo"), [ident("a")], blockStmt([]), [lit(4)]));
   1.214 +assertDecl("function foo(a, b=4) { }", funDecl(ident("foo"), [ident("a"), ident("b")], blockStmt([]), [lit(4)]));
   1.215 +assertDecl("function foo(a, b=4, ...rest) { }",
   1.216 +           funDecl(ident("foo"), [ident("a"), ident("b")], blockStmt([]), [lit(4)], ident("rest")));
   1.217 +assertDecl("function foo(a=(function () {})) { function a() {} }",
   1.218 +           funDecl(ident("foo"), [ident("a")], blockStmt([funDecl(ident("a"), [], blockStmt([]))]),
   1.219 +                   [funExpr(ident("a"), [], blockStmt([]))]));
   1.220 +
   1.221 +
   1.222 +// Bug 591437: rebound args have their defs turned into uses
   1.223 +assertDecl("function f(a) { function a() { } }",
   1.224 +           funDecl(ident("f"), [ident("a")], blockStmt([funDecl(ident("a"), [], blockStmt([]))])));
   1.225 +assertDecl("function f(a,b,c) { function b() { } }",
   1.226 +           funDecl(ident("f"), [ident("a"),ident("b"),ident("c")], blockStmt([funDecl(ident("b"), [], blockStmt([]))])));
   1.227 +assertDecl("function f(a,[x,y]) { function a() { } }",
   1.228 +           funDecl(ident("f"),
   1.229 +                   [ident("a"), arrPatt([ident("x"), ident("y")])],
   1.230 +                   blockStmt([funDecl(ident("a"), [], blockStmt([]))])));
   1.231 +
   1.232 +// Bug 632027: array holes should reflect as null
   1.233 +assertExpr("[,]=[,]", aExpr("=", arrPatt([null]), arrExpr([null])));
   1.234 +
   1.235 +// Bug 591450: this test currently crashes because of a bug in jsparse
   1.236 +// assertDecl("function f(a,[x,y],b,[w,z],c) { function b() { } }",
   1.237 +//            funDecl(ident("f"),
   1.238 +//                    [ident("a"), arrPatt([ident("x"), ident("y")]), ident("b"), arrPatt([ident("w"), ident("z")]), ident("c")],
   1.239 +//                    blockStmt([funDecl(ident("b"), [], blockStmt([]))])));
   1.240 +
   1.241 +
   1.242 +// expressions
   1.243 +
   1.244 +assertExpr("true", lit(true));
   1.245 +assertExpr("false", lit(false));
   1.246 +assertExpr("42", lit(42));
   1.247 +assertExpr("(/asdf/)", lit(/asdf/));
   1.248 +assertExpr("this", thisExpr);
   1.249 +assertExpr("foo", ident("foo"));
   1.250 +assertExpr("foo.bar", dotExpr(ident("foo"), ident("bar")));
   1.251 +assertExpr("foo[bar]", memExpr(ident("foo"), ident("bar")));
   1.252 +assertExpr("foo['bar']", memExpr(ident("foo"), lit("bar")));
   1.253 +assertExpr("foo[42]", memExpr(ident("foo"), lit(42)));
   1.254 +assertExpr("(function(){})", funExpr(null, [], blockStmt([])));
   1.255 +assertExpr("(function f() {})", funExpr(ident("f"), [], blockStmt([])));
   1.256 +assertExpr("(function f(x,y,z) {})", funExpr(ident("f"), [ident("x"),ident("y"),ident("z")], blockStmt([])));
   1.257 +assertExpr("a => a", arrowExpr([ident("a")], ident("a")));
   1.258 +assertExpr("(a) => a", arrowExpr([ident("a")], ident("a")));
   1.259 +assertExpr("a => b => a", arrowExpr([ident("a")], arrowExpr([ident("b")], ident("a"))));
   1.260 +assertExpr("a => {}", arrowExpr([ident("a")], blockStmt([])));
   1.261 +assertExpr("a => ({})", arrowExpr([ident("a")], objExpr([])));
   1.262 +assertExpr("(a, b, c) => {}", arrowExpr([ident("a"), ident("b"), ident("c")], blockStmt([])));
   1.263 +assertExpr("([a, b]) => {}", arrowExpr([arrPatt([ident("a"), ident("b")])], blockStmt([])));
   1.264 +assertExpr("(++x)", updExpr("++", ident("x"), true));
   1.265 +assertExpr("(x++)", updExpr("++", ident("x"), false));
   1.266 +assertExpr("(+x)", unExpr("+", ident("x")));
   1.267 +assertExpr("(-x)", unExpr("-", ident("x")));
   1.268 +assertExpr("(!x)", unExpr("!", ident("x")));
   1.269 +assertExpr("(~x)", unExpr("~", ident("x")));
   1.270 +assertExpr("(delete x)", unExpr("delete", ident("x")));
   1.271 +assertExpr("(typeof x)", unExpr("typeof", ident("x")));
   1.272 +assertExpr("(void x)", unExpr("void", ident("x")));
   1.273 +assertExpr("(x == y)", binExpr("==", ident("x"), ident("y")));
   1.274 +assertExpr("(x != y)", binExpr("!=", ident("x"), ident("y")));
   1.275 +assertExpr("(x === y)", binExpr("===", ident("x"), ident("y")));
   1.276 +assertExpr("(x !== y)", binExpr("!==", ident("x"), ident("y")));
   1.277 +assertExpr("(x < y)", binExpr("<", ident("x"), ident("y")));
   1.278 +assertExpr("(x <= y)", binExpr("<=", ident("x"), ident("y")));
   1.279 +assertExpr("(x > y)", binExpr(">", ident("x"), ident("y")));
   1.280 +assertExpr("(x >= y)", binExpr(">=", ident("x"), ident("y")));
   1.281 +assertExpr("(x << y)", binExpr("<<", ident("x"), ident("y")));
   1.282 +assertExpr("(x >> y)", binExpr(">>", ident("x"), ident("y")));
   1.283 +assertExpr("(x >>> y)", binExpr(">>>", ident("x"), ident("y")));
   1.284 +assertExpr("(x + y)", binExpr("+", ident("x"), ident("y")));
   1.285 +assertExpr("(w + x + y + z)", binExpr("+", binExpr("+", binExpr("+", ident("w"), ident("x")), ident("y")), ident("z")));
   1.286 +assertExpr("(x - y)", binExpr("-", ident("x"), ident("y")));
   1.287 +assertExpr("(w - x - y - z)", binExpr("-", binExpr("-", binExpr("-", ident("w"), ident("x")), ident("y")), ident("z")));
   1.288 +assertExpr("(x * y)", binExpr("*", ident("x"), ident("y")));
   1.289 +assertExpr("(x / y)", binExpr("/", ident("x"), ident("y")));
   1.290 +assertExpr("(x % y)", binExpr("%", ident("x"), ident("y")));
   1.291 +assertExpr("(x | y)", binExpr("|", ident("x"), ident("y")));
   1.292 +assertExpr("(x ^ y)", binExpr("^", ident("x"), ident("y")));
   1.293 +assertExpr("(x & y)", binExpr("&", ident("x"), ident("y")));
   1.294 +assertExpr("(x in y)", binExpr("in", ident("x"), ident("y")));
   1.295 +assertExpr("(x instanceof y)", binExpr("instanceof", ident("x"), ident("y")));
   1.296 +assertExpr("(x = y)", aExpr("=", ident("x"), ident("y")));
   1.297 +assertExpr("(x += y)", aExpr("+=", ident("x"), ident("y")));
   1.298 +assertExpr("(x -= y)", aExpr("-=", ident("x"), ident("y")));
   1.299 +assertExpr("(x *= y)", aExpr("*=", ident("x"), ident("y")));
   1.300 +assertExpr("(x /= y)", aExpr("/=", ident("x"), ident("y")));
   1.301 +assertExpr("(x %= y)", aExpr("%=", ident("x"), ident("y")));
   1.302 +assertExpr("(x <<= y)", aExpr("<<=", ident("x"), ident("y")));
   1.303 +assertExpr("(x >>= y)", aExpr(">>=", ident("x"), ident("y")));
   1.304 +assertExpr("(x >>>= y)", aExpr(">>>=", ident("x"), ident("y")));
   1.305 +assertExpr("(x |= y)", aExpr("|=", ident("x"), ident("y")));
   1.306 +assertExpr("(x ^= y)", aExpr("^=", ident("x"), ident("y")));
   1.307 +assertExpr("(x &= y)", aExpr("&=", ident("x"), ident("y")));
   1.308 +assertExpr("(x || y)", logExpr("||", ident("x"), ident("y")));
   1.309 +assertExpr("(x && y)", logExpr("&&", ident("x"), ident("y")));
   1.310 +assertExpr("(w || x || y || z)", logExpr("||", logExpr("||", logExpr("||", ident("w"), ident("x")), ident("y")), ident("z")))
   1.311 +assertExpr("(x ? y : z)", condExpr(ident("x"), ident("y"), ident("z")));
   1.312 +assertExpr("(x,y)", seqExpr([ident("x"),ident("y")]))
   1.313 +assertExpr("(x,y,z)", seqExpr([ident("x"),ident("y"),ident("z")]))
   1.314 +assertExpr("(a,b,c,d,e,f,g)", seqExpr([ident("a"),ident("b"),ident("c"),ident("d"),ident("e"),ident("f"),ident("g")]));
   1.315 +assertExpr("(new Object)", newExpr(ident("Object"), []));
   1.316 +assertExpr("(new Object())", newExpr(ident("Object"), []));
   1.317 +assertExpr("(new Object(42))", newExpr(ident("Object"), [lit(42)]));
   1.318 +assertExpr("(new Object(1,2,3))", newExpr(ident("Object"), [lit(1),lit(2),lit(3)]));
   1.319 +assertExpr("(String())", callExpr(ident("String"), []));
   1.320 +assertExpr("(String(42))", callExpr(ident("String"), [lit(42)]));
   1.321 +assertExpr("(String(1,2,3))", callExpr(ident("String"), [lit(1),lit(2),lit(3)]));
   1.322 +assertExpr("[]", arrExpr([]));
   1.323 +assertExpr("[1]", arrExpr([lit(1)]));
   1.324 +assertExpr("[1,2]", arrExpr([lit(1),lit(2)]));
   1.325 +assertExpr("[1,2,3]", arrExpr([lit(1),lit(2),lit(3)]));
   1.326 +assertExpr("[1,,2,3]", arrExpr([lit(1),null,lit(2),lit(3)]));
   1.327 +assertExpr("[1,,,2,3]", arrExpr([lit(1),null,null,lit(2),lit(3)]));
   1.328 +assertExpr("[1,,,2,,3]", arrExpr([lit(1),null,null,lit(2),null,lit(3)]));
   1.329 +assertExpr("[1,,,2,,,3]", arrExpr([lit(1),null,null,lit(2),null,null,lit(3)]));
   1.330 +assertExpr("[,1,2,3]", arrExpr([null,lit(1),lit(2),lit(3)]));
   1.331 +assertExpr("[,,1,2,3]", arrExpr([null,null,lit(1),lit(2),lit(3)]));
   1.332 +assertExpr("[,,,1,2,3]", arrExpr([null,null,null,lit(1),lit(2),lit(3)]));
   1.333 +assertExpr("[,,,1,2,3,]", arrExpr([null,null,null,lit(1),lit(2),lit(3)]));
   1.334 +assertExpr("[,,,1,2,3,,]", arrExpr([null,null,null,lit(1),lit(2),lit(3),null]));
   1.335 +assertExpr("[,,,1,2,3,,,]", arrExpr([null,null,null,lit(1),lit(2),lit(3),null,null]));
   1.336 +assertExpr("[,,,,,]", arrExpr([null,null,null,null,null]));
   1.337 +assertExpr("[1, ...a, 2]", arrExpr([lit(1), spread(ident("a")), lit(2)]));
   1.338 +assertExpr("[,, ...a,, ...b, 42]", arrExpr([null,null, spread(ident("a")),, spread(ident("b")), lit(42)]));
   1.339 +assertExpr("[1,(2,3)]", arrExpr([lit(1),seqExpr([lit(2),lit(3)])]));
   1.340 +assertExpr("[,(2,3)]", arrExpr([null,seqExpr([lit(2),lit(3)])]));
   1.341 +assertExpr("({})", objExpr([]));
   1.342 +assertExpr("({x:1})", objExpr([{ key: ident("x"), value: lit(1) }]));
   1.343 +assertExpr("({x:1, y:2})", objExpr([{ key: ident("x"), value: lit(1) },
   1.344 +                                    { key: ident("y"), value: lit(2) } ]));
   1.345 +assertExpr("({x:1, y:2, z:3})", objExpr([{ key: ident("x"), value: lit(1) },
   1.346 +                                         { key: ident("y"), value: lit(2) },
   1.347 +                                         { key: ident("z"), value: lit(3) } ]));
   1.348 +assertExpr("({x:1, 'y':2, z:3})", objExpr([{ key: ident("x"), value: lit(1) },
   1.349 +                                           { key: lit("y"), value: lit(2) },
   1.350 +                                           { key: ident("z"), value: lit(3) } ]));
   1.351 +assertExpr("({'x':1, 'y':2, z:3})", objExpr([{ key: lit("x"), value: lit(1) },
   1.352 +                                             { key: lit("y"), value: lit(2) },
   1.353 +                                             { key: ident("z"), value: lit(3) } ]));
   1.354 +assertExpr("({'x':1, 'y':2, 3:3})", objExpr([{ key: lit("x"), value: lit(1) },
   1.355 +                                             { key: lit("y"), value: lit(2) },
   1.356 +                                             { key: lit(3), value: lit(3) } ]));
   1.357 +
   1.358 +// Bug 571617: eliminate constant-folding
   1.359 +assertExpr("2 + 3", binExpr("+", lit(2), lit(3)));
   1.360 +
   1.361 +// Bug 632026: constant-folding
   1.362 +assertExpr("typeof(0?0:a)", unExpr("typeof", condExpr(lit(0), lit(0), ident("a"))));
   1.363 +
   1.364 +// Bug 632029: constant-folding
   1.365 +assertExpr("[x for each (x in y) if (false)]", compExpr(ident("x"), [compEachBlock(ident("x"), ident("y"))], lit(false)));
   1.366 +
   1.367 +// Bug 632056: constant-folding
   1.368 +program([exprStmt(ident("f")),
   1.369 +         ifStmt(lit(1),
   1.370 +                funDecl(ident("f"), [], blockStmt([])),
   1.371 +                null)]).assert(Reflect.parse("f; if (1) function f(){}"));
   1.372 +
   1.373 +// statements
   1.374 +
   1.375 +assertStmt("throw 42", throwStmt(lit(42)));
   1.376 +assertStmt("for (;;) break", forStmt(null, null, null, breakStmt(null)));
   1.377 +assertStmt("for (x; y; z) break", forStmt(ident("x"), ident("y"), ident("z"), breakStmt(null)));
   1.378 +assertStmt("for (var x; y; z) break", forStmt(varDecl([{ id: ident("x"), init: null }]), ident("y"), ident("z")));
   1.379 +assertStmt("for (var x = 42; y; z) break", forStmt(varDecl([{ id: ident("x"), init: lit(42) }]), ident("y"), ident("z")));
   1.380 +assertStmt("for (x; ; z) break", forStmt(ident("x"), null, ident("z"), breakStmt(null)));
   1.381 +assertStmt("for (var x; ; z) break", forStmt(varDecl([{ id: ident("x"), init: null }]), null, ident("z")));
   1.382 +assertStmt("for (var x = 42; ; z) break", forStmt(varDecl([{ id: ident("x"), init: lit(42) }]), null, ident("z")));
   1.383 +assertStmt("for (x; y; ) break", forStmt(ident("x"), ident("y"), null, breakStmt(null)));
   1.384 +assertStmt("for (var x; y; ) break", forStmt(varDecl([{ id: ident("x"), init: null }]), ident("y"), null, breakStmt(null)));
   1.385 +assertStmt("for (var x = 42; y; ) break", forStmt(varDecl([{ id: ident("x"), init: lit(42) }]), ident("y"), null, breakStmt(null)));
   1.386 +assertStmt("for (var x in y) break", forInStmt(varDecl([{ id: ident("x"), init: null }]), ident("y"), breakStmt(null)));
   1.387 +assertStmt("for (x in y) break", forInStmt(ident("x"), ident("y"), breakStmt(null)));
   1.388 +assertStmt("{ }", blockStmt([]));
   1.389 +assertStmt("{ throw 1; throw 2; throw 3; }", blockStmt([ throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]));
   1.390 +assertStmt(";", emptyStmt);
   1.391 +assertStmt("if (foo) throw 42;", ifStmt(ident("foo"), throwStmt(lit(42)), null));
   1.392 +assertStmt("if (foo) throw 42; else true;", ifStmt(ident("foo"), throwStmt(lit(42)), exprStmt(lit(true))));
   1.393 +assertStmt("if (foo) { throw 1; throw 2; throw 3; }",
   1.394 +           ifStmt(ident("foo"),
   1.395 +                  blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]),
   1.396 +                  null));
   1.397 +assertStmt("if (foo) { throw 1; throw 2; throw 3; } else true;",
   1.398 +           ifStmt(ident("foo"),
   1.399 +                  blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]),
   1.400 +                  exprStmt(lit(true))));
   1.401 +assertStmt("foo: for(;;) break foo;", labStmt(ident("foo"), forStmt(null, null, null, breakStmt(ident("foo")))));
   1.402 +assertStmt("foo: for(;;) continue foo;", labStmt(ident("foo"), forStmt(null, null, null, continueStmt(ident("foo")))));
   1.403 +assertStmt("with (obj) { }", withStmt(ident("obj"), blockStmt([])));
   1.404 +assertStmt("with (obj) { obj; }", withStmt(ident("obj"), blockStmt([exprStmt(ident("obj"))])));
   1.405 +assertStmt("while (foo) { }", whileStmt(ident("foo"), blockStmt([])));
   1.406 +assertStmt("while (foo) { foo; }", whileStmt(ident("foo"), blockStmt([exprStmt(ident("foo"))])));
   1.407 +assertStmt("do { } while (foo);", doStmt(blockStmt([]), ident("foo")));
   1.408 +assertStmt("do { foo; } while (foo)", doStmt(blockStmt([exprStmt(ident("foo"))]), ident("foo")));
   1.409 +assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; }",
   1.410 +           switchStmt(ident("foo"),
   1.411 +                      [ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]),
   1.412 +                        caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]),
   1.413 +                        defaultClause([ exprStmt(lit(3)) ]) ]));
   1.414 +assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; case 42: 42; }",
   1.415 +           switchStmt(ident("foo"),
   1.416 +                      [ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]),
   1.417 +                        caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]),
   1.418 +                        defaultClause([ exprStmt(lit(3)) ]),
   1.419 +                        caseClause(lit(42), [ exprStmt(lit(42)) ]) ]));
   1.420 +assertStmt("try { } catch (e) { }",
   1.421 +           tryStmt(blockStmt([]),
   1.422 +                   [],
   1.423 +		   catchClause(ident("e"), null, blockStmt([])),
   1.424 +                   null));
   1.425 +assertStmt("try { } catch (e) { } finally { }",
   1.426 +           tryStmt(blockStmt([]),
   1.427 +                   [],
   1.428 +		   catchClause(ident("e"), null, blockStmt([])),
   1.429 +                   blockStmt([])));
   1.430 +assertStmt("try { } finally { }",
   1.431 +           tryStmt(blockStmt([]),
   1.432 +                   [],
   1.433 +		   null,
   1.434 +                   blockStmt([])));
   1.435 +assertStmt("try { } catch (e if foo) { } catch (e if bar) { } finally { }",
   1.436 +           tryStmt(blockStmt([]),
   1.437 +                   [ catchClause(ident("e"), ident("foo"), blockStmt([])),
   1.438 +                     catchClause(ident("e"), ident("bar"), blockStmt([])) ],
   1.439 +		   null,
   1.440 +                   blockStmt([])));
   1.441 +assertStmt("try { } catch (e if foo) { } catch (e if bar) { } catch (e) { } finally { }",
   1.442 +           tryStmt(blockStmt([]),
   1.443 +                   [ catchClause(ident("e"), ident("foo"), blockStmt([])),
   1.444 +                     catchClause(ident("e"), ident("bar"), blockStmt([])) ],
   1.445 +                   catchClause(ident("e"), null, blockStmt([])),
   1.446 +                   blockStmt([])));
   1.447 +
   1.448 +// Bug 632028: yield outside of a function should throw
   1.449 +(function() {
   1.450 +    var threw = false;
   1.451 +    try {
   1.452 +        Reflect.parse("yield 0");
   1.453 +    } catch (expected) {
   1.454 +        threw = true;
   1.455 +    }
   1.456 +    assertEq(threw, true);
   1.457 +})();
   1.458 +
   1.459 +// redeclarations (TOK_NAME nodes with lexdef)
   1.460 +
   1.461 +assertStmt("function f() { function g() { } function g() { } }",
   1.462 +           funDecl(ident("f"), [], blockStmt([emptyStmt,
   1.463 +                                              funDecl(ident("g"), [], blockStmt([]))])));
   1.464 +
   1.465 +// Fails due to parser quirks (bug 638577)
   1.466 +//assertStmt("function f() { function g() { } function g() { return 42 } }",
   1.467 +//           funDecl(ident("f"), [], blockStmt([funDecl(ident("g"), [], blockStmt([])),
   1.468 +//                                              funDecl(ident("g"), [], blockStmt([returnStmt(lit(42))]))])));
   1.469 +
   1.470 +assertStmt("function f() { var x = 42; var x = 43; }",
   1.471 +           funDecl(ident("f"), [], blockStmt([varDecl([{ id: ident("x"), init: lit(42) }]),
   1.472 +                                              varDecl([{ id: ident("x"), init: lit(43) }])])));
   1.473 +
   1.474 +
   1.475 +assertDecl("var {x:y} = foo;", varDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
   1.476 +                                          init: ident("foo") }]));
   1.477 +
   1.478 +// Bug 632030: redeclarations between var and funargs, var and function
   1.479 +assertStmt("function g(x) { var x }",
   1.480 +           funDecl(ident("g"), [ident("x")], blockStmt([varDecl[{ id: ident("x"), init: null }]])));
   1.481 +assertProg("f.p = 1; var f; f.p; function f(){}",
   1.482 +           [exprStmt(aExpr("=", dotExpr(ident("f"), ident("p")), lit(1))),
   1.483 +            varDecl([{ id: ident("f"), init: null }]),
   1.484 +            exprStmt(dotExpr(ident("f"), ident("p"))),
   1.485 +            funDecl(ident("f"), [], blockStmt([]))]);
   1.486 +
   1.487 +// global let is var
   1.488 +assertGlobalDecl("let {x:y} = foo;", varDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
   1.489 +                                                init: ident("foo") }]));
   1.490 +// function-global let is var
   1.491 +assertLocalDecl("let {x:y} = foo;", varDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
   1.492 +                                               init: ident("foo") }]));
   1.493 +// block-local let is let
   1.494 +assertBlockDecl("let {x:y} = foo;", letDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
   1.495 +                                               init: ident("foo") }]));
   1.496 +
   1.497 +assertDecl("const {x:y} = foo;", constDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
   1.498 +                                              init: ident("foo") }]));
   1.499 +
   1.500 +
   1.501 +// various combinations of identifiers and destructuring patterns:
   1.502 +function makePatternCombinations(id, destr)
   1.503 +    [
   1.504 +      [ id(1)                                            ],
   1.505 +      [ id(1),    id(2)                                  ],
   1.506 +      [ id(1),    id(2),    id(3)                        ],
   1.507 +      [ id(1),    id(2),    id(3),    id(4)              ],
   1.508 +      [ id(1),    id(2),    id(3),    id(4),    id(5)    ],
   1.509 +
   1.510 +      [ destr(1)                                         ],
   1.511 +      [ destr(1), destr(2)                               ],
   1.512 +      [ destr(1), destr(2), destr(3)                     ],
   1.513 +      [ destr(1), destr(2), destr(3), destr(4)           ],
   1.514 +      [ destr(1), destr(2), destr(3), destr(4), destr(5) ],
   1.515 +
   1.516 +      [ destr(1), id(2)                                  ],
   1.517 +
   1.518 +      [ destr(1), id(2),    id(3)                        ],
   1.519 +      [ destr(1), id(2),    id(3),    id(4)              ],
   1.520 +      [ destr(1), id(2),    id(3),    id(4),    id(5)    ],
   1.521 +      [ destr(1), id(2),    id(3),    id(4),    destr(5) ],
   1.522 +      [ destr(1), id(2),    id(3),    destr(4)           ],
   1.523 +      [ destr(1), id(2),    id(3),    destr(4), id(5)    ],
   1.524 +      [ destr(1), id(2),    id(3),    destr(4), destr(5) ],
   1.525 +
   1.526 +      [ destr(1), id(2),    destr(3)                     ],
   1.527 +      [ destr(1), id(2),    destr(3), id(4)              ],
   1.528 +      [ destr(1), id(2),    destr(3), id(4),    id(5)    ],
   1.529 +      [ destr(1), id(2),    destr(3), id(4),    destr(5) ],
   1.530 +      [ destr(1), id(2),    destr(3), destr(4)           ],
   1.531 +      [ destr(1), id(2),    destr(3), destr(4), id(5)    ],
   1.532 +      [ destr(1), id(2),    destr(3), destr(4), destr(5) ],
   1.533 +
   1.534 +      [ id(1),    destr(2)                               ],
   1.535 +
   1.536 +      [ id(1),    destr(2), id(3)                        ],
   1.537 +      [ id(1),    destr(2), id(3),    id(4)              ],
   1.538 +      [ id(1),    destr(2), id(3),    id(4),    id(5)    ],
   1.539 +      [ id(1),    destr(2), id(3),    id(4),    destr(5) ],
   1.540 +      [ id(1),    destr(2), id(3),    destr(4)           ],
   1.541 +      [ id(1),    destr(2), id(3),    destr(4), id(5)    ],
   1.542 +      [ id(1),    destr(2), id(3),    destr(4), destr(5) ],
   1.543 +
   1.544 +      [ id(1),    destr(2), destr(3)                     ],
   1.545 +      [ id(1),    destr(2), destr(3), id(4)              ],
   1.546 +      [ id(1),    destr(2), destr(3), id(4),    id(5)    ],
   1.547 +      [ id(1),    destr(2), destr(3), id(4),    destr(5) ],
   1.548 +      [ id(1),    destr(2), destr(3), destr(4)           ],
   1.549 +      [ id(1),    destr(2), destr(3), destr(4), id(5)    ],
   1.550 +      [ id(1),    destr(2), destr(3), destr(4), destr(5) ]
   1.551 +    ]
   1.552 +
   1.553 +// destructuring function parameters
   1.554 +
   1.555 +function testParamPatternCombinations(makePattSrc, makePattPatt) {
   1.556 +    var pattSrcs = makePatternCombinations(function(n) ("x" + n), makePattSrc);
   1.557 +    var pattPatts = makePatternCombinations(function(n) (ident("x" + n)), makePattPatt);
   1.558 +
   1.559 +    for (var i = 0; i < pattSrcs.length; i++) {
   1.560 +        function makeSrc(body) ("(function(" + pattSrcs[i].join(",") + ") " + body + ")")
   1.561 +        function makePatt(body) (funExpr(null, pattPatts[i], body))
   1.562 +
   1.563 +        // no upvars, block body
   1.564 +        assertExpr(makeSrc("{ }", makePatt(blockStmt([]))));
   1.565 +        // upvars, block body
   1.566 +        assertExpr(makeSrc("{ return [x1,x2,x3,x4,x5]; }"),
   1.567 +                   makePatt(blockStmt([returnStmt(arrExpr([ident("x1"), ident("x2"), ident("x3"), ident("x4"), ident("x5")]))])));
   1.568 +        // no upvars, expression body
   1.569 +        assertExpr(makeSrc("(0)"), makePatt(lit(0)));
   1.570 +        // upvars, expression body
   1.571 +        assertExpr(makeSrc("[x1,x2,x3,x4,x5]"),
   1.572 +                   makePatt(arrExpr([ident("x1"), ident("x2"), ident("x3"), ident("x4"), ident("x5")])));
   1.573 +    }
   1.574 +}
   1.575 +
   1.576 +testParamPatternCombinations(function(n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "}"),
   1.577 +                             function(n) (objPatt([{ key: ident("a" + n), value: ident("x" + n) },
   1.578 +                                                   { key: ident("b" + n), value: ident("y" + n) },
   1.579 +                                                   { key: ident("c" + n), value: ident("z" + n) }])));
   1.580 +
   1.581 +testParamPatternCombinations(function(n) ("[x" + n + "," + "y" + n + "," + "z" + n + "]"),
   1.582 +                             function(n) (arrPatt([ident("x" + n), ident("y" + n), ident("z" + n)])));
   1.583 +
   1.584 +
   1.585 +// destructuring variable declarations
   1.586 +
   1.587 +function testVarPatternCombinations(makePattSrc, makePattPatt) {
   1.588 +    var pattSrcs = makePatternCombinations(function(n) ("x" + n), makePattSrc);
   1.589 +    var pattPatts = makePatternCombinations(function(n) ({ id: ident("x" + n), init: null }), makePattPatt);
   1.590 +
   1.591 +    for (var i = 0; i < pattSrcs.length; i++) {
   1.592 +        // variable declarations in blocks
   1.593 +        assertDecl("var " + pattSrcs[i].join(",") + ";", varDecl(pattPatts[i]));
   1.594 +
   1.595 +        assertGlobalDecl("let " + pattSrcs[i].join(",") + ";", varDecl(pattPatts[i]));
   1.596 +        assertLocalDecl("let " + pattSrcs[i].join(",") + ";", varDecl(pattPatts[i]));
   1.597 +        assertBlockDecl("let " + pattSrcs[i].join(",") + ";", letDecl(pattPatts[i]));
   1.598 +
   1.599 +        assertDecl("const " + pattSrcs[i].join(",") + ";", constDecl(pattPatts[i]));
   1.600 +
   1.601 +        // variable declarations in for-loop heads
   1.602 +        assertStmt("for (var " + pattSrcs[i].join(",") + "; foo; bar);",
   1.603 +                   forStmt(varDecl(pattPatts[i]), ident("foo"), ident("bar"), emptyStmt));
   1.604 +        assertStmt("for (let " + pattSrcs[i].join(",") + "; foo; bar);",
   1.605 +                   letStmt(pattPatts[i], forStmt(null, ident("foo"), ident("bar"), emptyStmt)));
   1.606 +        assertStmt("for (const " + pattSrcs[i].join(",") + "; foo; bar);",
   1.607 +                   forStmt(constDecl(pattPatts[i]), ident("foo"), ident("bar"), emptyStmt));
   1.608 +    }
   1.609 +}
   1.610 +
   1.611 +testVarPatternCombinations(function (n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "} = 0"),
   1.612 +                           function (n) ({ id: objPatt([{ key: ident("a" + n), value: ident("x" + n) },
   1.613 +                                                        { key: ident("b" + n), value: ident("y" + n) },
   1.614 +                                                        { key: ident("c" + n), value: ident("z" + n) }]),
   1.615 +                                           init: lit(0) }));
   1.616 +
   1.617 +testVarPatternCombinations(function(n) ("[x" + n + "," + "y" + n + "," + "z" + n + "] = 0"),
   1.618 +                           function(n) ({ id: arrPatt([ident("x" + n), ident("y" + n), ident("z" + n)]),
   1.619 +                                          init: lit(0) }));
   1.620 +
   1.621 +// destructuring assignment
   1.622 +
   1.623 +function testAssignmentCombinations(makePattSrc, makePattPatt) {
   1.624 +    var pattSrcs = makePatternCombinations(function(n) ("x" + n + " = 0"), makePattSrc);
   1.625 +    var pattPatts = makePatternCombinations(function(n) (aExpr("=", ident("x" + n), lit(0))), makePattPatt);
   1.626 +
   1.627 +    for (var i = 0; i < pattSrcs.length; i++) {
   1.628 +        var src = pattSrcs[i].join(",");
   1.629 +        var patt = pattPatts[i].length === 1 ? pattPatts[i][0] : seqExpr(pattPatts[i]);
   1.630 +
   1.631 +        // assignment expression statement
   1.632 +        assertExpr("(" + src + ")", patt);
   1.633 +
   1.634 +        // for-loop head assignment
   1.635 +        assertStmt("for (" + src + "; foo; bar);",
   1.636 +                   forStmt(patt, ident("foo"), ident("bar"), emptyStmt));
   1.637 +    }
   1.638 +}
   1.639 +
   1.640 +testAssignmentCombinations(function (n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "} = 0"),
   1.641 +                           function (n) (aExpr("=",
   1.642 +                                               objPatt([{ key: ident("a" + n), value: ident("x" + n) },
   1.643 +                                                        { key: ident("b" + n), value: ident("y" + n) },
   1.644 +                                                        { key: ident("c" + n), value: ident("z" + n) }]),
   1.645 +                                               lit(0))));
   1.646 +
   1.647 +
   1.648 +// destructuring in for-in and for-each-in loop heads
   1.649 +
   1.650 +var axbycz = objPatt([{ key: ident("a"), value: ident("x") },
   1.651 +                      { key: ident("b"), value: ident("y") },
   1.652 +                      { key: ident("c"), value: ident("z") }]);
   1.653 +var xyz = arrPatt([ident("x"), ident("y"), ident("z")]);
   1.654 +
   1.655 +assertStmt("for (var {a:x,b:y,c:z} in foo);", forInStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
   1.656 +assertStmt("for (let {a:x,b:y,c:z} in foo);", forInStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
   1.657 +assertStmt("for ({a:x,b:y,c:z} in foo);", forInStmt(axbycz, ident("foo"), emptyStmt));
   1.658 +assertStmt("for (var [x,y,z] in foo);", forInStmt(varDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
   1.659 +assertStmt("for (let [x,y,z] in foo);", forInStmt(letDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
   1.660 +assertStmt("for ([x,y,z] in foo);", forInStmt(xyz, ident("foo"), emptyStmt));
   1.661 +assertStmt("for (var {a:x,b:y,c:z} of foo);", forOfStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
   1.662 +assertStmt("for (let {a:x,b:y,c:z} of foo);", forOfStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
   1.663 +assertStmt("for ({a:x,b:y,c:z} of foo);", forOfStmt(axbycz, ident("foo"), emptyStmt));
   1.664 +assertStmt("for (var [x,y,z] of foo);", forOfStmt(varDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
   1.665 +assertStmt("for (let [x,y,z] of foo);", forOfStmt(letDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
   1.666 +assertStmt("for ([x,y,z] of foo);", forOfStmt(xyz, ident("foo"), emptyStmt));
   1.667 +assertStmt("for each (var {a:x,b:y,c:z} in foo);", forEachInStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
   1.668 +assertStmt("for each (let {a:x,b:y,c:z} in foo);", forEachInStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
   1.669 +assertStmt("for each ({a:x,b:y,c:z} in foo);", forEachInStmt(axbycz, ident("foo"), emptyStmt));
   1.670 +assertStmt("for each (var [x,y,z] in foo);", forEachInStmt(varDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
   1.671 +assertStmt("for each (let [x,y,z] in foo);", forEachInStmt(letDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
   1.672 +assertStmt("for each ([x,y,z] in foo);", forEachInStmt(xyz, ident("foo"), emptyStmt));
   1.673 +assertError("for (const x in foo);", SyntaxError);
   1.674 +assertError("for (const {a:x,b:y,c:z} in foo);", SyntaxError);
   1.675 +assertError("for (const [x,y,z] in foo);", SyntaxError);
   1.676 +assertError("for (const x of foo);", SyntaxError);
   1.677 +assertError("for (const {a:x,b:y,c:z} of foo);", SyntaxError);
   1.678 +assertError("for (const [x,y,z] of foo);", SyntaxError);
   1.679 +assertError("for each (const x in foo);", SyntaxError);
   1.680 +assertError("for each (const {a:x,b:y,c:z} in foo);", SyntaxError);
   1.681 +assertError("for each (const [x,y,z] in foo);", SyntaxError);
   1.682 +
   1.683 +// destructuring in for-in and for-each-in loop heads with initializers
   1.684 +
   1.685 +assertStmt("for (var {a:x,b:y,c:z} = 22 in foo);", forInStmt(varDecl([{ id: axbycz, init: lit(22) }]), ident("foo"), emptyStmt));
   1.686 +assertStmt("for (var [x,y,z] = 22 in foo);", forInStmt(varDecl([{ id: xyz, init: lit(22) }]), ident("foo"), emptyStmt));
   1.687 +assertStmt("for each (var {a:x,b:y,c:z} = 22 in foo);", forEachInStmt(varDecl([{ id: axbycz, init: lit(22) }]), ident("foo"), emptyStmt));
   1.688 +assertStmt("for each (var [x,y,z] = 22 in foo);", forEachInStmt(varDecl([{ id: xyz, init: lit(22) }]), ident("foo"), emptyStmt));
   1.689 +assertError("for (x = 22 in foo);", SyntaxError);
   1.690 +assertError("for ({a:x,b:y,c:z} = 22 in foo);", SyntaxError);
   1.691 +assertError("for ([x,y,z] = 22 in foo);", SyntaxError);
   1.692 +assertError("for (const x = 22 in foo);", SyntaxError);
   1.693 +assertError("for (const {a:x,b:y,c:z} = 22 in foo);", SyntaxError);
   1.694 +assertError("for (const [x,y,z] = 22 in foo);", SyntaxError);
   1.695 +assertError("for each (const x = 22 in foo);", SyntaxError);
   1.696 +assertError("for each (const {a:x,b:y,c:z} = 22 in foo);", SyntaxError);
   1.697 +assertError("for each (const [x,y,z] = 22 in foo);", SyntaxError);
   1.698 +
   1.699 +// expression closures
   1.700 +
   1.701 +assertDecl("function inc(x) (x + 1)", funDecl(ident("inc"), [ident("x")], binExpr("+", ident("x"), lit(1))));
   1.702 +assertExpr("(function(x) (x+1))", funExpr(null, [ident("x")], binExpr("+"), ident("x"), lit(1)));
   1.703 +
   1.704 +// generators
   1.705 +
   1.706 +assertDecl("function gen(x) { yield }", genFunDecl(ident("gen"), [ident("x")], blockStmt([exprStmt(yieldExpr(null))])));
   1.707 +assertExpr("(function(x) { yield })", genFunExpr(null, [ident("x")], blockStmt([exprStmt(yieldExpr(null))])));
   1.708 +assertDecl("function gen(x) { yield 42 }", genFunDecl(ident("gen"), [ident("x")], blockStmt([exprStmt(yieldExpr(lit(42)))])));
   1.709 +assertExpr("(function(x) { yield 42 })", genFunExpr(null, [ident("x")], blockStmt([exprStmt(yieldExpr(lit(42)))])));
   1.710 +
   1.711 +// getters and setters
   1.712 +
   1.713 +assertExpr("({ get x() { return 42 } })",
   1.714 +           objExpr([ { key: ident("x"),
   1.715 +                       value: funExpr(null, [], blockStmt([returnStmt(lit(42))])),
   1.716 +                       kind: "get" } ]));
   1.717 +assertExpr("({ set x(v) { return 42 } })",
   1.718 +           objExpr([ { key: ident("x"),
   1.719 +                       value: funExpr(null, [ident("v")], blockStmt([returnStmt(lit(42))])),
   1.720 +                       kind: "set" } ]));
   1.721 +
   1.722 +// comprehensions
   1.723 +
   1.724 +assertExpr("[ x         for (x in foo)]",
   1.725 +           compExpr(ident("x"), [compBlock(ident("x"), ident("foo"))], null));
   1.726 +assertExpr("[ [x,y]     for (x in foo) for (y in bar)]",
   1.727 +           compExpr(arrExpr([ident("x"), ident("y")]), [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar"))], null));
   1.728 +assertExpr("[ [x,y,z] for (x in foo) for (y in bar) for (z in baz)]",
   1.729 +           compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
   1.730 +                    [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar")), compBlock(ident("z"), ident("baz"))],
   1.731 +                    null));
   1.732 +
   1.733 +assertExpr("[ x         for (x in foo) if (p)]",
   1.734 +           compExpr(ident("x"), [compBlock(ident("x"), ident("foo"))], ident("p")));
   1.735 +assertExpr("[ [x,y]     for (x in foo) for (y in bar) if (p)]",
   1.736 +           compExpr(arrExpr([ident("x"), ident("y")]), [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar"))], ident("p")));
   1.737 +assertExpr("[ [x,y,z] for (x in foo) for (y in bar) for (z in baz) if (p) ]",
   1.738 +           compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
   1.739 +                    [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar")), compBlock(ident("z"), ident("baz"))],
   1.740 +                    ident("p")));
   1.741 +
   1.742 +assertExpr("[ x         for each (x in foo)]",
   1.743 +           compExpr(ident("x"), [compEachBlock(ident("x"), ident("foo"))], null));
   1.744 +assertExpr("[ [x,y]     for each (x in foo) for each (y in bar)]",
   1.745 +           compExpr(arrExpr([ident("x"), ident("y")]), [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar"))], null));
   1.746 +assertExpr("[ [x,y,z] for each (x in foo) for each (y in bar) for each (z in baz)]",
   1.747 +           compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
   1.748 +                    [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar")), compEachBlock(ident("z"), ident("baz"))],
   1.749 +                    null));
   1.750 +
   1.751 +assertExpr("[ x         for each (x in foo) if (p)]",
   1.752 +           compExpr(ident("x"), [compEachBlock(ident("x"), ident("foo"))], ident("p")));
   1.753 +assertExpr("[ [x,y]     for each (x in foo) for each (y in bar) if (p)]",
   1.754 +           compExpr(arrExpr([ident("x"), ident("y")]), [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar"))], ident("p")));
   1.755 +assertExpr("[ [x,y,z] for each (x in foo) for each (y in bar) for each (z in baz) if (p) ]",
   1.756 +           compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
   1.757 +                    [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar")), compEachBlock(ident("z"), ident("baz"))],
   1.758 +                    ident("p")));
   1.759 +
   1.760 +assertExpr("[ x         for (x of foo)]",
   1.761 +           compExpr(ident("x"), [compOfBlock(ident("x"), ident("foo"))], null));
   1.762 +assertExpr("[ [x,y]     for (x of foo) for (y of bar)]",
   1.763 +           compExpr(arrExpr([ident("x"), ident("y")]), [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar"))], null));
   1.764 +assertExpr("[ [x,y,z] for (x of foo) for (y of bar) for (z of baz)]",
   1.765 +           compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
   1.766 +                    [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar")), compOfBlock(ident("z"), ident("baz"))],
   1.767 +                    null));
   1.768 +
   1.769 +assertExpr("[ x         for (x of foo) if (p)]",
   1.770 +           compExpr(ident("x"), [compOfBlock(ident("x"), ident("foo"))], ident("p")));
   1.771 +assertExpr("[ [x,y]     for (x of foo) for (y of bar) if (p)]",
   1.772 +           compExpr(arrExpr([ident("x"), ident("y")]), [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar"))], ident("p")));
   1.773 +assertExpr("[ [x,y,z] for (x of foo) for (y of bar) for (z of baz) if (p) ]",
   1.774 +           compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
   1.775 +                    [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar")), compOfBlock(ident("z"), ident("baz"))],
   1.776 +                    ident("p")));
   1.777 +
   1.778 +// generator expressions
   1.779 +
   1.780 +assertExpr("( x         for (x in foo))",
   1.781 +           genExpr(ident("x"), [compBlock(ident("x"), ident("foo"))], null));
   1.782 +assertExpr("( [x,y]     for (x in foo) for (y in bar))",
   1.783 +           genExpr(arrExpr([ident("x"), ident("y")]), [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar"))], null));
   1.784 +assertExpr("( [x,y,z] for (x in foo) for (y in bar) for (z in baz))",
   1.785 +           genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
   1.786 +                   [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar")), compBlock(ident("z"), ident("baz"))],
   1.787 +                   null));
   1.788 +
   1.789 +assertExpr("( x         for (x in foo) if (p))",
   1.790 +           genExpr(ident("x"), [compBlock(ident("x"), ident("foo"))], ident("p")));
   1.791 +assertExpr("( [x,y]     for (x in foo) for (y in bar) if (p))",
   1.792 +           genExpr(arrExpr([ident("x"), ident("y")]), [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar"))], ident("p")));
   1.793 +assertExpr("( [x,y,z] for (x in foo) for (y in bar) for (z in baz) if (p) )",
   1.794 +           genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
   1.795 +                   [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar")), compBlock(ident("z"), ident("baz"))],
   1.796 +                   ident("p")));
   1.797 +
   1.798 +assertExpr("( x         for each (x in foo))",
   1.799 +           genExpr(ident("x"), [compEachBlock(ident("x"), ident("foo"))], null));
   1.800 +assertExpr("( [x,y]     for each (x in foo) for each (y in bar))",
   1.801 +           genExpr(arrExpr([ident("x"), ident("y")]), [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar"))], null));
   1.802 +assertExpr("( [x,y,z] for each (x in foo) for each (y in bar) for each (z in baz))",
   1.803 +           genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
   1.804 +                   [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar")), compEachBlock(ident("z"), ident("baz"))],
   1.805 +                   null));
   1.806 +
   1.807 +assertExpr("( x         for each (x in foo) if (p))",
   1.808 +           genExpr(ident("x"), [compEachBlock(ident("x"), ident("foo"))], ident("p")));
   1.809 +assertExpr("( [x,y]     for each (x in foo) for each (y in bar) if (p))",
   1.810 +           genExpr(arrExpr([ident("x"), ident("y")]), [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar"))], ident("p")));
   1.811 +assertExpr("( [x,y,z] for each (x in foo) for each (y in bar) for each (z in baz) if (p) )",
   1.812 +           genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
   1.813 +                   [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar")), compEachBlock(ident("z"), ident("baz"))],
   1.814 +                   ident("p")));
   1.815 +
   1.816 +assertExpr("( x         for (x of foo))",
   1.817 +           genExpr(ident("x"), [compOfBlock(ident("x"), ident("foo"))], null));
   1.818 +assertExpr("( [x,y]     for (x of foo) for (y of bar))",
   1.819 +           genExpr(arrExpr([ident("x"), ident("y")]), [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar"))], null));
   1.820 +assertExpr("( [x,y,z] for (x of foo) for (y of bar) for (z of baz))",
   1.821 +           genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
   1.822 +                   [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar")), compOfBlock(ident("z"), ident("baz"))],
   1.823 +                   null));
   1.824 +
   1.825 +assertExpr("( x         for (x of foo) if (p))",
   1.826 +           genExpr(ident("x"), [compOfBlock(ident("x"), ident("foo"))], ident("p")));
   1.827 +assertExpr("( [x,y]     for (x of foo) for (y of bar) if (p))",
   1.828 +           genExpr(arrExpr([ident("x"), ident("y")]), [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar"))], ident("p")));
   1.829 +assertExpr("( [x,y,z] for (x of foo) for (y of bar) for (z of baz) if (p) )",
   1.830 +           genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
   1.831 +                   [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar")), compOfBlock(ident("z"), ident("baz"))],
   1.832 +                   ident("p")));
   1.833 +
   1.834 +// NOTE: it would be good to test generator expressions both with and without upvars, just like functions above.
   1.835 +
   1.836 +
   1.837 +// let expressions
   1.838 +
   1.839 +assertExpr("(let (x=1) x)", letExpr([{ id: ident("x"), init: lit(1) }], ident("x")));
   1.840 +assertExpr("(let (x=1,y=2) y)", letExpr([{ id: ident("x"), init: lit(1) },
   1.841 +                                         { id: ident("y"), init: lit(2) }],
   1.842 +                                        ident("y")));
   1.843 +assertExpr("(let (x=1,y=2,z=3) z)", letExpr([{ id: ident("x"), init: lit(1) },
   1.844 +                                             { id: ident("y"), init: lit(2) },
   1.845 +                                             { id: ident("z"), init: lit(3) }],
   1.846 +                                            ident("z")));
   1.847 +assertExpr("(let (x) x)", letExpr([{ id: ident("x"), init: null }], ident("x")));
   1.848 +assertExpr("(let (x,y) y)", letExpr([{ id: ident("x"), init: null },
   1.849 +                                     { id: ident("y"), init: null }],
   1.850 +                                    ident("y")));
   1.851 +assertExpr("(let (x,y,z) z)", letExpr([{ id: ident("x"), init: null },
   1.852 +                                       { id: ident("y"), init: null },
   1.853 +                                       { id: ident("z"), init: null }],
   1.854 +                                      ident("z")));
   1.855 +assertExpr("(let (x = 1, y = x) y)", letExpr([{ id: ident("x"), init: lit(1) },
   1.856 +                                              { id: ident("y"), init: ident("x") }],
   1.857 +                                             ident("y")));
   1.858 +assertError("(let (x = 1, x = 2) x)", TypeError);
   1.859 +
   1.860 +// let statements
   1.861 +
   1.862 +assertStmt("let (x=1) { }", letStmt([{ id: ident("x"), init: lit(1) }], blockStmt([])));
   1.863 +assertStmt("let (x=1,y=2) { }", letStmt([{ id: ident("x"), init: lit(1) },
   1.864 +                                         { id: ident("y"), init: lit(2) }],
   1.865 +                                        blockStmt([])));
   1.866 +assertStmt("let (x=1,y=2,z=3) { }", letStmt([{ id: ident("x"), init: lit(1) },
   1.867 +                                             { id: ident("y"), init: lit(2) },
   1.868 +                                             { id: ident("z"), init: lit(3) }],
   1.869 +                                            blockStmt([])));
   1.870 +assertStmt("let (x) { }", letStmt([{ id: ident("x"), init: null }], blockStmt([])));
   1.871 +assertStmt("let (x,y) { }", letStmt([{ id: ident("x"), init: null },
   1.872 +                                     { id: ident("y"), init: null }],
   1.873 +                                    blockStmt([])));
   1.874 +assertStmt("let (x,y,z) { }", letStmt([{ id: ident("x"), init: null },
   1.875 +                                       { id: ident("y"), init: null },
   1.876 +                                       { id: ident("z"), init: null }],
   1.877 +                                      blockStmt([])));
   1.878 +assertStmt("let (x = 1, y = x) { }", letStmt([{ id: ident("x"), init: lit(1) },
   1.879 +                                              { id: ident("y"), init: ident("x") }],
   1.880 +                                             blockStmt([])));
   1.881 +assertError("let (x = 1, x = 2) { }", TypeError);
   1.882 +
   1.883 +
   1.884 +// Bug 632024: no crashing on stack overflow
   1.885 +try {
   1.886 +    Reflect.parse(Array(3000).join("x + y - ") + "z")
   1.887 +} catch (e) { }
   1.888 +
   1.889 +
   1.890 +// Source location information
   1.891 +
   1.892 +
   1.893 +var withoutFileOrLine = Reflect.parse("42");
   1.894 +var withFile = Reflect.parse("42", {source:"foo.js"});
   1.895 +var withFileAndLine = Reflect.parse("42", {source:"foo.js", line:111});
   1.896 +
   1.897 +Pattern({ source: null, start: { line: 1, column: 0 }, end: { line: 1, column: 2 } }).match(withoutFileOrLine.loc);
   1.898 +Pattern({ source: "foo.js", start: { line: 1, column: 0 }, end: { line: 1, column: 2 } }).match(withFile.loc);
   1.899 +Pattern({ source: "foo.js", start: { line: 111, column: 0 }, end: { line: 111, column: 2 } }).match(withFileAndLine.loc);
   1.900 +
   1.901 +var withoutFileOrLine2 = Reflect.parse("foo +\nbar");
   1.902 +var withFile2 = Reflect.parse("foo +\nbar", {source:"foo.js"});
   1.903 +var withFileAndLine2 = Reflect.parse("foo +\nbar", {source:"foo.js", line:111});
   1.904 +
   1.905 +Pattern({ source: null, start: { line: 1, column: 0 }, end: { line: 2, column: 3 } }).match(withoutFileOrLine2.loc);
   1.906 +Pattern({ source: "foo.js", start: { line: 1, column: 0 }, end: { line: 2, column: 3 } }).match(withFile2.loc);
   1.907 +Pattern({ source: "foo.js", start: { line: 111, column: 0 }, end: { line: 112, column: 3 } }).match(withFileAndLine2.loc);
   1.908 +
   1.909 +var nested = Reflect.parse("(-b + sqrt(sqr(b) - 4 * a * c)) / (2 * a)", {source:"quad.js"});
   1.910 +var fourAC = nested.body[0].expression.left.right.arguments[0].right;
   1.911 +
   1.912 +Pattern({ source: "quad.js", start: { line: 1, column: 20 }, end: { line: 1, column: 29 } }).match(fourAC.loc);
   1.913 +
   1.914 +
   1.915 +// No source location
   1.916 +
   1.917 +assertEq(Reflect.parse("42", {loc:false}).loc, null);
   1.918 +program([exprStmt(lit(42))]).assert(Reflect.parse("42", {loc:false}));
   1.919 +
   1.920 +
   1.921 +// Builder tests
   1.922 +
   1.923 +Pattern("program").match(Reflect.parse("42", {builder:{program:function()"program"}}));
   1.924 +
   1.925 +assertGlobalStmt("throw 42", 1, { throwStatement: function() 1 });
   1.926 +assertGlobalStmt("for (;;);", 2, { forStatement: function() 2 });
   1.927 +assertGlobalStmt("for (x in y);", 3, { forInStatement: function() 3 });
   1.928 +assertGlobalStmt("{ }", 4, { blockStatement: function() 4 });
   1.929 +assertGlobalStmt("foo: { }", 5, { labeledStatement: function() 5 });
   1.930 +assertGlobalStmt("with (o) { }", 6, { withStatement: function() 6 });
   1.931 +assertGlobalStmt("while (x) { }", 7, { whileStatement: function() 7 });
   1.932 +assertGlobalStmt("do { } while(false);", 8, { doWhileStatement: function() 8 });
   1.933 +assertGlobalStmt("switch (x) { }", 9, { switchStatement: function() 9 });
   1.934 +assertGlobalStmt("try { } catch(e) { }", 10, { tryStatement: function() 10 });
   1.935 +assertGlobalStmt(";", 11, { emptyStatement: function() 11 });
   1.936 +assertGlobalStmt("debugger;", 12, { debuggerStatement: function() 12 });
   1.937 +assertGlobalStmt("42;", 13, { expressionStatement: function() 13 });
   1.938 +assertGlobalStmt("for (;;) break", forStmt(null, null, null, 14), { breakStatement: function() 14 });
   1.939 +assertGlobalStmt("for (;;) continue", forStmt(null, null, null, 15), { continueStatement: function() 15 });
   1.940 +
   1.941 +assertBlockDecl("var x", "var", { variableDeclaration: function(kind) kind });
   1.942 +assertBlockDecl("let x", "let", { variableDeclaration: function(kind) kind });
   1.943 +assertBlockDecl("const x", "const", { variableDeclaration: function(kind) kind });
   1.944 +assertBlockDecl("function f() { }", "function", { functionDeclaration: function() "function" });
   1.945 +
   1.946 +assertGlobalExpr("(x,y,z)", 1, { sequenceExpression: function() 1 });
   1.947 +assertGlobalExpr("(x ? y : z)", 2, { conditionalExpression: function() 2 });
   1.948 +assertGlobalExpr("x + y", 3, { binaryExpression: function() 3 });
   1.949 +assertGlobalExpr("delete x", 4, { unaryExpression: function() 4 });
   1.950 +assertGlobalExpr("x = y", 5, { assignmentExpression: function() 5 });
   1.951 +assertGlobalExpr("x || y", 6, { logicalExpression: function() 6 });
   1.952 +assertGlobalExpr("x++", 7, { updateExpression: function() 7 });
   1.953 +assertGlobalExpr("new x", 8, { newExpression: function() 8 });
   1.954 +assertGlobalExpr("x()", 9, { callExpression: function() 9 });
   1.955 +assertGlobalExpr("x.y", 10, { memberExpression: function() 10 });
   1.956 +assertGlobalExpr("(function() { })", 11, { functionExpression: function() 11 });
   1.957 +assertGlobalExpr("[1,2,3]", 12, { arrayExpression: function() 12 });
   1.958 +assertGlobalExpr("({ x: y })", 13, { objectExpression: function() 13 });
   1.959 +assertGlobalExpr("this", 14, { thisExpression: function() 14 });
   1.960 +assertGlobalExpr("[x for (x in y)]", 17, { comprehensionExpression: function() 17 });
   1.961 +assertGlobalExpr("(x for (x in y))", 18, { generatorExpression: function() 18 });
   1.962 +assertGlobalExpr("(function() { yield 42 })", genFunExpr(null, [], blockStmt([exprStmt(19)])), { yieldExpression: function() 19 });
   1.963 +assertGlobalExpr("(let (x) x)", 20, { letExpression: function() 20 });
   1.964 +
   1.965 +assertGlobalStmt("switch (x) { case y: }", switchStmt(ident("x"), [1]), { switchCase: function() 1 });
   1.966 +assertGlobalStmt("try { } catch (e) { }", 2, { tryStatement: (function(b, g, u, f) u), catchClause: function() 2 });
   1.967 +assertGlobalStmt("try { } catch (e if e instanceof A) { } catch (e if e instanceof B) { }", [2, 2], { tryStatement: (function(b, g, u, f) g), catchClause: function() 2 });
   1.968 +assertGlobalStmt("try { } catch (e) { }", tryStmt(blockStmt([]), [], 2, null), { catchClause: function() 2 });
   1.969 +assertGlobalStmt("try { } catch (e if e instanceof A) { } catch (e if e instanceof B) { }",
   1.970 +                 tryStmt(blockStmt([]), [2, 2], null, null),
   1.971 +                 { catchClause: function() 2 });
   1.972 +assertGlobalExpr("[x for (y in z) for (x in y)]", compExpr(ident("x"), [3, 3], null), { comprehensionBlock: function() 3 });
   1.973 +
   1.974 +assertGlobalExpr("({ x: y } = z)", aExpr("=", 1, ident("z")), { objectPattern: function() 1 });
   1.975 +assertGlobalExpr("({ x: y } = z)", aExpr("=", objPatt([2]), ident("z")), { propertyPattern: function() 2 });
   1.976 +assertGlobalExpr("[ x ] = y", aExpr("=", 3, ident("y")), { arrayPattern: function() 3 });
   1.977 +
   1.978 +// Ensure that exceptions thrown by builder methods propagate.
   1.979 +var thrown = false;
   1.980 +try {
   1.981 +    Reflect.parse("42", { builder: { program: function() { throw "expected" } } });
   1.982 +} catch (e if e === "expected") {
   1.983 +    thrown = true;
   1.984 +}
   1.985 +if (!thrown)
   1.986 +    throw new Error("builder exception not propagated");
   1.987 +
   1.988 +// Missing property RHS's in an object literal should throw.
   1.989 +try {
   1.990 +    Reflect.parse("({foo})");
   1.991 +    throw new Error("object literal missing property RHS didn't throw");
   1.992 +} catch (e if e instanceof SyntaxError) { }
   1.993 +
   1.994 +
   1.995 +// A simple proof-of-concept that the builder API can be used to generate other
   1.996 +// formats, such as JsonMLAst:
   1.997 +// 
   1.998 +//     http://code.google.com/p/es-lab/wiki/JsonMLASTFormat
   1.999 +// 
  1.1000 +// It's incomplete (e.g., it doesn't convert source-location information and
  1.1001 +// doesn't use all the direct-eval rules), but I think it proves the point.
  1.1002 +
  1.1003 +var JsonMLAst = (function() {
  1.1004 +function reject() {
  1.1005 +    throw new SyntaxError("node type not supported");
  1.1006 +}
  1.1007 +
  1.1008 +function isDirectEval(expr) {
  1.1009 +    // an approximation to the actual rules. you get the idea
  1.1010 +    return (expr[0] === "IdExpr" && expr[1].name === "eval");
  1.1011 +}
  1.1012 +
  1.1013 +function functionNode(type) {
  1.1014 +    return function(id, args, body, isGenerator, isExpression) {
  1.1015 +        if (isExpression)
  1.1016 +            body = ["ReturnStmt", {}, body];
  1.1017 +
  1.1018 +        if (!id)
  1.1019 +            id = ["Empty"];
  1.1020 +
  1.1021 +        // Patch up the argument node types: s/IdExpr/IdPatt/g
  1.1022 +        for (var i = 0; i < args.length; i++) {
  1.1023 +            args[i][0] = "IdPatt";
  1.1024 +        }
  1.1025 +
  1.1026 +        args.unshift("ParamDecl", {});
  1.1027 +
  1.1028 +        return [type, {}, id, args, body];
  1.1029 +    }
  1.1030 +}
  1.1031 +
  1.1032 +return {
  1.1033 +    program: function(stmts) {
  1.1034 +        stmts.unshift("Program", {});
  1.1035 +        return stmts;
  1.1036 +    },
  1.1037 +    identifier: function(name) {
  1.1038 +        return ["IdExpr", { name: name }];
  1.1039 +    },
  1.1040 +    literal: function(val) {
  1.1041 +        return ["LiteralExpr", { value: val }];
  1.1042 +    },
  1.1043 +    expressionStatement: function(expr) expr,
  1.1044 +    conditionalExpression: function(test, cons, alt) {
  1.1045 +        return ["ConditionalExpr", {}, test, cons, alt];
  1.1046 +    },
  1.1047 +    unaryExpression: function(op, expr) {
  1.1048 +        return ["UnaryExpr", {op: op}, expr];
  1.1049 +    },
  1.1050 +    binaryExpression: function(op, left, right) {
  1.1051 +        return ["BinaryExpr", {op: op}, left, right];
  1.1052 +    },
  1.1053 +    property: function(kind, key, val) {
  1.1054 +        return [kind === "init"
  1.1055 +                ? "DataProp"
  1.1056 +                : kind === "get"
  1.1057 +                ? "GetterProp"
  1.1058 +                : "SetterProp",
  1.1059 +                {name: key[1].name}, val];
  1.1060 +    },
  1.1061 +    functionDeclaration: functionNode("FunctionDecl"),
  1.1062 +    variableDeclaration: function(kind, elts) {
  1.1063 +        if (kind === "let" || kind === "const")
  1.1064 +            throw new SyntaxError("let and const not supported");
  1.1065 +        elts.unshift("VarDecl", {});
  1.1066 +        return elts;
  1.1067 +    },
  1.1068 +    variableDeclarator: function(id, init) {
  1.1069 +        id[0] = "IdPatt";
  1.1070 +        if (!init)
  1.1071 +            return id;
  1.1072 +        return ["InitPatt", {}, id, init];
  1.1073 +    },
  1.1074 +    sequenceExpression: function(exprs) {
  1.1075 +        var length = exprs.length;
  1.1076 +        var result = ["BinaryExpr", {op:","}, exprs[exprs.length - 2], exprs[exprs.length - 1]];
  1.1077 +        for (var i = exprs.length - 3; i >= 0; i--) {
  1.1078 +            result = ["BinaryExpr", {op:","}, exprs[i], result];
  1.1079 +        }
  1.1080 +        return result;
  1.1081 +    },
  1.1082 +    assignmentExpression: function(op, lhs, expr) {
  1.1083 +        return ["AssignExpr", {op: op}, lhs, expr];
  1.1084 +    },
  1.1085 +    logicalExpression: function(op, left, right) {
  1.1086 +        return [op === "&&" ? "LogicalAndExpr" : "LogicalOrExpr", {}, left, right];
  1.1087 +    },
  1.1088 +    updateExpression: function(expr, op, isPrefix) {
  1.1089 +        return ["CountExpr", {isPrefix:isPrefix, op:op}, expr];
  1.1090 +    },
  1.1091 +    newExpression: function(callee, args) {
  1.1092 +        args.unshift("NewExpr", {}, callee);
  1.1093 +        return args;
  1.1094 +    },
  1.1095 +    callExpression: function(callee, args) {
  1.1096 +        args.unshift(isDirectEval(callee) ? "EvalExpr" : "CallExpr", {}, callee);
  1.1097 +        return args;
  1.1098 +    },
  1.1099 +    memberExpression: function(isComputed, expr, member) {
  1.1100 +        return ["MemberExpr", {}, expr, isComputed ? member : ["LiteralExpr", {type: "string", value: member[1].name}]];
  1.1101 +    },
  1.1102 +    functionExpression: functionNode("FunctionExpr"),
  1.1103 +    arrayExpression: function(elts) {
  1.1104 +        for (var i = 0; i < elts.length; i++) {
  1.1105 +            if (!elts[i])
  1.1106 +                elts[i] = ["Empty"];
  1.1107 +        }
  1.1108 +        elts.unshift("ArrayExpr", {});
  1.1109 +        return elts;
  1.1110 +    },
  1.1111 +    objectExpression: function(props) {
  1.1112 +        props.unshift("ObjectExpr", {});
  1.1113 +        return props;
  1.1114 +    },
  1.1115 +    thisExpression: function() {
  1.1116 +        return ["ThisExpr", {}];
  1.1117 +    },
  1.1118 +
  1.1119 +    graphExpression: reject,
  1.1120 +    graphIndexExpression: reject,
  1.1121 +    comprehensionExpression: reject,
  1.1122 +    generatorExpression: reject,
  1.1123 +    yieldExpression: reject,
  1.1124 +    letExpression: reject,
  1.1125 +
  1.1126 +    emptyStatement: function() ["EmptyStmt", {}],
  1.1127 +    blockStatement: function(stmts) {
  1.1128 +        stmts.unshift("BlockStmt", {});
  1.1129 +        return stmts;
  1.1130 +    },
  1.1131 +    labeledStatement: function(lab, stmt) {
  1.1132 +        return ["LabelledStmt", {label: lab}, stmt];
  1.1133 +    },
  1.1134 +    ifStatement: function(test, cons, alt) {
  1.1135 +        return ["IfStmt", {}, test, cons, alt || ["EmptyStmt", {}]];
  1.1136 +    },
  1.1137 +    switchStatement: function(test, clauses, isLexical) {
  1.1138 +        clauses.unshift("SwitchStmt", {}, test);
  1.1139 +        return clauses;
  1.1140 +    },
  1.1141 +    whileStatement: function(expr, stmt) {
  1.1142 +        return ["WhileStmt", {}, expr, stmt];
  1.1143 +    },
  1.1144 +    doWhileStatement: function(stmt, expr) {
  1.1145 +        return ["DoWhileStmt", {}, stmt, expr];
  1.1146 +    },
  1.1147 +    forStatement: function(init, test, update, body) {
  1.1148 +        return ["ForStmt", {}, init || ["Empty"], test || ["Empty"], update || ["Empty"], body];
  1.1149 +    },
  1.1150 +    forInStatement: function(lhs, rhs, body) {
  1.1151 +        return ["ForInStmt", {}, lhs, rhs, body];
  1.1152 +    },
  1.1153 +    breakStatement: function(lab) {
  1.1154 +        return lab ? ["BreakStmt", {}, lab] : ["BreakStmt", {}];
  1.1155 +    },
  1.1156 +    continueStatement: function(lab) {
  1.1157 +        return lab ? ["ContinueStmt", {}, lab] : ["ContinueStmt", {}];
  1.1158 +    },
  1.1159 +    withStatement: function(expr, stmt) {
  1.1160 +        return ["WithStmt", {}, expr, stmt];
  1.1161 +    },
  1.1162 +    returnStatement: function(expr) {
  1.1163 +        return expr ? ["ReturnStmt", {}, expr] : ["ReturnStmt", {}];
  1.1164 +    },
  1.1165 +    tryStatement: function(body, catches, fin) {
  1.1166 +        if (catches.length > 1)
  1.1167 +            throw new SyntaxError("multiple catch clauses not supported");
  1.1168 +        var node = ["TryStmt", body, catches[0] || ["Empty"]];
  1.1169 +        if (fin)
  1.1170 +            node.push(fin);
  1.1171 +        return node;
  1.1172 +    },
  1.1173 +    throwStatement: function(expr) {
  1.1174 +        return ["ThrowStmt", {}, expr];
  1.1175 +    },
  1.1176 +    debuggerStatement: function() ["DebuggerStmt", {}],
  1.1177 +    letStatement: reject,
  1.1178 +    switchCase: function(expr, stmts) {
  1.1179 +        if (expr)
  1.1180 +            stmts.unshift("SwitchCase", {}, expr);
  1.1181 +        else
  1.1182 +            stmts.unshift("DefaultCase", {});
  1.1183 +        return stmts;
  1.1184 +    },
  1.1185 +    catchClause: function(param, guard, body) {
  1.1186 +        if (guard)
  1.1187 +            throw new SyntaxError("catch guards not supported");
  1.1188 +        param[0] = "IdPatt";
  1.1189 +        return ["CatchClause", {}, param, body];
  1.1190 +    },
  1.1191 +    comprehensionBlock: reject,
  1.1192 +
  1.1193 +    arrayPattern: reject,
  1.1194 +    objectPattern: reject,
  1.1195 +    propertyPattern: reject,
  1.1196 +};
  1.1197 +})();
  1.1198 +
  1.1199 +Pattern(["Program", {},
  1.1200 +         ["BinaryExpr", {op: "+"},
  1.1201 +          ["LiteralExpr", {value: 2}],
  1.1202 +          ["BinaryExpr", {op: "*"},
  1.1203 +           ["UnaryExpr", {op: "-"}, ["IdExpr", {name: "x"}]],
  1.1204 +           ["IdExpr", {name: "y"}]]]]).match(Reflect.parse("2 + (-x * y)", {loc: false, builder: JsonMLAst}));
  1.1205 +
  1.1206 +reportCompare(true, true);
  1.1207 +
  1.1208 +});

mercurial