Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / tests / js1_8_5 / extensions / reflect-parse.js
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * Any copyright is dedicated to the Public Domain.
4  * http://creativecommons.org/licenses/publicdomain/
5  */
6
7 var { Pattern, MatchError } = Match;
8
9 var _ = Pattern.ANY;
10
11 function program(elts) Pattern({ type: "Program", body: elts })
12 function exprStmt(expr) Pattern({ type: "ExpressionStatement", expression: expr })
13 function throwStmt(expr) Pattern({ type: "ThrowStatement", argument: expr })
14 function returnStmt(expr) Pattern({ type: "ReturnStatement", argument: expr })
15 function yieldExpr(expr) Pattern({ type: "YieldExpression", argument: expr })
16 function lit(val) Pattern({ type: "Literal", value: val })
17 var thisExpr = Pattern({ type: "ThisExpression" });
18 function funDecl(id, params, body) Pattern({ type: "FunctionDeclaration",
19                                              id: id,
20                                              params: params,
21                                              body: body,
22                                              generator: false })
23 function genFunDecl(id, params, body) Pattern({ type: "FunctionDeclaration",
24                                                 id: id,
25                                                 params: params,
26                                                 body: body,
27                                                 generator: true })
28 function varDecl(decls) Pattern({ type: "VariableDeclaration", declarations: decls, kind: "var" })
29 function letDecl(decls) Pattern({ type: "VariableDeclaration", declarations: decls, kind: "let" })
30 function constDecl(decls) Pattern({ type: "VariableDeclaration", declarations: decls, kind: "const" })
31 function ident(name) Pattern({ type: "Identifier", name: name })
32 function dotExpr(obj, id) Pattern({ type: "MemberExpression", computed: false, object: obj, property: id })
33 function memExpr(obj, id) Pattern({ type: "MemberExpression", computed: true, object: obj, property: id })
34 function forStmt(init, test, update, body) Pattern({ type: "ForStatement", init: init, test: test, update: update, body: body })
35 function forInStmt(lhs, rhs, body) Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: false })
36 function forEachInStmt(lhs, rhs, body) Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: true })
37 function breakStmt(lab) Pattern({ type: "BreakStatement", label: lab })
38 function continueStmt(lab) Pattern({ type: "ContinueStatement", label: lab })
39 function blockStmt(body) Pattern({ type: "BlockStatement", body: body })
40 var emptyStmt = Pattern({ type: "EmptyStatement" })
41 function ifStmt(test, cons, alt) Pattern({ type: "IfStatement", test: test, alternate: alt, consequent: cons })
42 function labStmt(lab, stmt) Pattern({ type: "LabeledStatement", label: lab, body: stmt })
43 function withStmt(obj, stmt) Pattern({ type: "WithStatement", object: obj, body: stmt })
44 function whileStmt(test, stmt) Pattern({ type: "WhileStatement", test: test, body: stmt })
45 function doStmt(stmt, test) Pattern({ type: "DoWhileStatement", test: test, body: stmt })
46 function switchStmt(disc, cases) Pattern({ type: "SwitchStatement", discriminant: disc, cases: cases })
47 function caseClause(test, stmts) Pattern({ type: "SwitchCase", test: test, consequent: stmts })
48 function defaultClause(stmts) Pattern({ type: "SwitchCase", test: null, consequent: stmts })
49 function catchClause(id, guard, body) Pattern({ type: "CatchClause", param: id, guard: guard, body: body })
50 function tryStmt(body, catches, fin) Pattern({ type: "TryStatement", block: body, handler: catches, finalizer: fin })
51 function letStmt(head, body) Pattern({ type: "LetStatement", head: head, body: body })
52 function funExpr(id, args, body, gen) Pattern({ type: "FunctionExpression",
53                                                 id: id,
54                                                 params: args,
55                                                 body: body,
56                                                 generator: false })
57 function genFunExpr(id, args, body) Pattern({ type: "FunctionExpression",
58                                               id: id,
59                                               params: args,
60                                               body: body,
61                                               generator: true })
62
63 function unExpr(op, arg) Pattern({ type: "UnaryExpression", operator: op, argument: arg })
64 function binExpr(op, left, right) Pattern({ type: "BinaryExpression", operator: op, left: left, right: right })
65 function aExpr(op, left, right) Pattern({ type: "AssignmentExpression", operator: op, left: left, right: right })
66 function updExpr(op, arg, prefix) Pattern({ type: "UpdateExpression", operator: op, argument: arg, prefix: prefix })
67 function logExpr(op, left, right) Pattern({ type: "LogicalExpression", operator: op, left: left, right: right })
68
69 function condExpr(test, cons, alt) Pattern({ type: "ConditionalExpression", test: test, consequent: cons, alternate: alt })
70 function seqExpr(exprs) Pattern({ type: "SequenceExpression", expressions: exprs })
71 function newExpr(callee, args) Pattern({ type: "NewExpression", callee: callee, arguments: args })
72 function callExpr(callee, args) Pattern({ type: "CallExpression", callee: callee, arguments: args })
73 function arrExpr(elts) Pattern({ type: "ArrayExpression", elements: elts })
74 function objExpr(elts) Pattern({ type: "ObjectExpression", properties: elts })
75 function compExpr(body, blocks, filter) Pattern({ type: "ComprehensionExpression", body: body, blocks: blocks, filter: filter })
76 function genExpr(body, blocks, filter) Pattern({ type: "GeneratorExpression", body: body, blocks: blocks, filter: filter })
77 function graphExpr(idx, body) Pattern({ type: "GraphExpression", index: idx, expression: body })
78 function letExpr(head, body) Pattern({ type: "LetExpression", head: head, body: body })
79 function idxExpr(idx) Pattern({ type: "GraphIndexExpression", index: idx })
80
81 function compBlock(left, right) Pattern({ type: "ComprehensionBlock", left: left, right: right, each: false })
82 function compEachBlock(left, right) Pattern({ type: "ComprehensionBlock", left: left, right: right, each: true })
83
84 function arrPatt(elts) Pattern({ type: "ArrayPattern", elements: elts })
85 function objPatt(elts) Pattern({ type: "ObjectPattern", properties: elts })
86
87 function localSrc(src) "(function(){ " + src + " })"
88 function localPatt(patt) program([exprStmt(funExpr(null, [], blockStmt([patt])))])
89 function blockSrc(src) "(function(){ { " + src + " } })"
90 function blockPatt(patt) program([exprStmt(funExpr(null, [], blockStmt([blockStmt([patt])])))])
91
92 var xmlAnyName = Pattern({ type: "XMLAnyName" });
93
94 function xmlQualId(left, right, computed) Pattern({ type: "XMLQualifiedIdentifier", left: left, right: right, computed: computed })
95 function xmlFuncQualId(right, computed) Pattern({ type: "XMLFunctionQualifiedIdentifier", right: right, computed: computed })
96 function xmlAttrSel(id) Pattern({ type: "XMLAttributeSelector", attribute: id })
97 function xmlFilter(left, right) Pattern({ type: "XMLFilterExpression", left: left, right: right })
98 function xmlPointTag(contents) Pattern({ type: "XMLPointTag", contents: contents })
99 function xmlStartTag(contents) Pattern({ type: "XMLStartTag", contents: contents })
100 function xmlEndTag(contents) Pattern({ type: "XMLEndTag", contents: contents })
101 function xmlEscape(expr) Pattern({ type: "XMLEscape", expression: expr })
102 function xmlElt(contents) Pattern({ type: "XMLElement", contents: contents })
103 function xmlAttr(value) Pattern({ type: "XMLAttribute", value: value })
104 function xmlText(text) Pattern({ type: "XMLText", text: text })
105 function xmlPI(target, contents) Pattern({ type: "XMLProcessingInstruction", target: target, contents: contents })
106 function xmlDefNS(ns) Pattern({ type: "XMLDefaultDeclaration", namespace: ns })
107 function xmlName(name) Pattern({ type: "XMLName", contents: name })
108 function xmlComment(contents) Pattern({ type: "XMLComment", contents: contents })
109 function xmlCdata(cdata) Pattern({ type: "XMLCdata", contents: cdata })
110
111 function assertBlockStmt(src, patt) {
112     blockPatt(patt).assert(Reflect.parse(blockSrc(src)));
113 }
114
115 function assertBlockExpr(src, patt) {
116     assertBlockStmt(src, exprStmt(patt));
117 }
118
119 function assertBlockDecl(src, patt, builder) {
120     blockPatt(patt).assert(Reflect.parse(blockSrc(src), {builder: builder}));
121 }
122
123 function assertLocalStmt(src, patt) {
124     localPatt(patt).assert(Reflect.parse(localSrc(src)));
125 }
126
127 function assertLocalExpr(src, patt) {
128     assertLocalStmt(src, exprStmt(patt));
129 }
130
131 function assertLocalDecl(src, patt) {
132     localPatt(patt).assert(Reflect.parse(localSrc(src)));
133 }
134
135 function assertGlobalStmt(src, patt, builder) {
136     program([patt]).assert(Reflect.parse(src, {builder: builder}));
137 }
138
139 function assertGlobalExpr(src, patt, builder) {
140     program([exprStmt(patt)]).assert(Reflect.parse(src, {builder: builder}));
141     //assertStmt(src, exprStmt(patt));
142 }
143
144 function assertGlobalDecl(src, patt) {
145     program([patt]).assert(Reflect.parse(src));
146 }
147
148 function assertStmt(src, patt) {
149     assertLocalStmt(src, patt);
150     assertGlobalStmt(src, patt);
151     assertBlockStmt(src, patt);
152 }
153
154 function assertExpr(src, patt) {
155     assertLocalExpr(src, patt);
156     assertGlobalExpr(src, patt);
157     assertBlockExpr(src, patt);
158 }
159
160 function assertDecl(src, patt) {
161     assertLocalDecl(src, patt);
162     assertGlobalDecl(src, patt);
163     assertBlockDecl(src, patt);
164 }
165
166 function assertError(src, errorType) {
167     try {
168         Reflect.parse(src);
169     } catch (expected if expected instanceof errorType) {
170         return;
171     }
172     throw new Error("expected " + errorType.name + " for " + uneval(src));
173 }
174
175
176 // general tests
177
178 // NB: These are useful but for now jit-test doesn't do I/O reliably.
179
180 //program(_).assert(Reflect.parse(snarf('data/flapjax.txt')));
181 //program(_).assert(Reflect.parse(snarf('data/jquery-1.4.2.txt')));
182 //program(_).assert(Reflect.parse(snarf('data/prototype.js')));
183 //program(_).assert(Reflect.parse(snarf('data/dojo.js.uncompressed.js')));
184 //program(_).assert(Reflect.parse(snarf('data/mootools-1.2.4-core-nc.js')));
185
186
187 // declarations
188
189 assertDecl("var x = 1, y = 2, z = 3",
190            varDecl([{ id: ident("x"), init: lit(1) },
191                     { id: ident("y"), init: lit(2) },
192                     { id: ident("z"), init: lit(3) }]));
193 assertDecl("var x, y, z",
194            varDecl([{ id: ident("x"), init: null },
195                     { id: ident("y"), init: null },
196                     { id: ident("z"), init: null }]));
197 assertDecl("function foo() { }",
198            funDecl(ident("foo"), [], blockStmt([])));
199 assertDecl("function foo() { return 42 }",
200            funDecl(ident("foo"), [], blockStmt([returnStmt(lit(42))])));
201
202
203 // Bug 591437: rebound args have their defs turned into uses
204 assertDecl("function f(a) { function a() { } }",
205            funDecl(ident("f"), [ident("a")], blockStmt([funDecl(ident("a"), [], blockStmt([]))])));
206 assertDecl("function f(a,b,c) { function b() { } }",
207            funDecl(ident("f"), [ident("a"),ident("b"),ident("c")], blockStmt([funDecl(ident("b"), [], blockStmt([]))])));
208 assertDecl("function f(a,[x,y]) { function a() { } }",
209            funDecl(ident("f"),
210                    [ident("a"), arrPatt([ident("x"), ident("y")])],
211                    blockStmt([funDecl(ident("a"), [], blockStmt([]))])));
212
213 // Bug 591450: this test currently crashes because of a bug in jsparse
214 // assertDecl("function f(a,[x,y],b,[w,z],c) { function b() { } }",
215 //            funDecl(ident("f"),
216 //                    [ident("a"), arrPatt([ident("x"), ident("y")]), ident("b"), arrPatt([ident("w"), ident("z")]), ident("c")],
217 //                    blockStmt([funDecl(ident("b"), [], blockStmt([]))])));
218
219
220 // expressions
221
222 assertExpr("true", lit(true));
223 assertExpr("false", lit(false));
224 assertExpr("42", lit(42));
225 assertExpr("(/asdf/)", lit(/asdf/));
226 assertExpr("this", thisExpr);
227 assertExpr("foo", ident("foo"));
228 assertExpr("foo.bar", dotExpr(ident("foo"), ident("bar")));
229 assertExpr("foo[bar]", memExpr(ident("foo"), ident("bar")));
230 assertExpr("(function(){})", funExpr(null, [], blockStmt([])));
231 assertExpr("(function f() {})", funExpr(ident("f"), [], blockStmt([])));
232 assertExpr("(function f(x,y,z) {})", funExpr(ident("f"), [ident("x"),ident("y"),ident("z")], blockStmt([])));
233 assertExpr("(++x)", updExpr("++", ident("x"), true));
234 assertExpr("(x++)", updExpr("++", ident("x"), false));
235 assertExpr("(+x)", unExpr("+", ident("x")));
236 assertExpr("(-x)", unExpr("-", ident("x")));
237 assertExpr("(!x)", unExpr("!", ident("x")));
238 assertExpr("(~x)", unExpr("~", ident("x")));
239 assertExpr("(delete x)", unExpr("delete", ident("x")));
240 assertExpr("(typeof x)", unExpr("typeof", ident("x")));
241 assertExpr("(void x)", unExpr("void", ident("x")));
242 assertExpr("(x == y)", binExpr("==", ident("x"), ident("y")));
243 assertExpr("(x != y)", binExpr("!=", ident("x"), ident("y")));
244 assertExpr("(x === y)", binExpr("===", ident("x"), ident("y")));
245 assertExpr("(x !== y)", binExpr("!==", ident("x"), ident("y")));
246 assertExpr("(x < y)", binExpr("<", ident("x"), ident("y")));
247 assertExpr("(x <= y)", binExpr("<=", ident("x"), ident("y")));
248 assertExpr("(x > y)", binExpr(">", ident("x"), ident("y")));
249 assertExpr("(x >= y)", binExpr(">=", ident("x"), ident("y")));
250 assertExpr("(x << y)", binExpr("<<", ident("x"), ident("y")));
251 assertExpr("(x >> y)", binExpr(">>", ident("x"), ident("y")));
252 assertExpr("(x >>> y)", binExpr(">>>", ident("x"), ident("y")));
253 assertExpr("(x + y)", binExpr("+", ident("x"), ident("y")));
254 assertExpr("(w + x + y + z)", binExpr("+", ident("w"), binExpr("+", ident("x", binExpr("+", ident("y"), ident("z"))))))
255 assertExpr("(x - y)", binExpr("-", ident("x"), ident("y")));
256 assertExpr("(x * y)", binExpr("*", ident("x"), ident("y")));
257 assertExpr("(x / y)", binExpr("/", ident("x"), ident("y")));
258 assertExpr("(x % y)", binExpr("%", ident("x"), ident("y")));
259 assertExpr("(x | y)", binExpr("|", ident("x"), ident("y")));
260 assertExpr("(x ^ y)", binExpr("^", ident("x"), ident("y")));
261 assertExpr("(x & y)", binExpr("&", ident("x"), ident("y")));
262 assertExpr("(x in y)", binExpr("in", ident("x"), ident("y")));
263 assertExpr("(x instanceof y)", binExpr("instanceof", ident("x"), ident("y")));
264 assertExpr("(x = y)", aExpr("=", ident("x"), ident("y")));
265 assertExpr("(x += y)", aExpr("+=", ident("x"), ident("y")));
266 assertExpr("(x -= y)", aExpr("-=", ident("x"), ident("y")));
267 assertExpr("(x *= y)", aExpr("*=", ident("x"), ident("y")));
268 assertExpr("(x /= y)", aExpr("/=", ident("x"), ident("y")));
269 assertExpr("(x %= y)", aExpr("%=", ident("x"), ident("y")));
270 assertExpr("(x <<= y)", aExpr("<<=", ident("x"), ident("y")));
271 assertExpr("(x >>= y)", aExpr(">>=", ident("x"), ident("y")));
272 assertExpr("(x >>>= y)", aExpr(">>>=", ident("x"), ident("y")));
273 assertExpr("(x |= y)", aExpr("|=", ident("x"), ident("y")));
274 assertExpr("(x ^= y)", aExpr("^=", ident("x"), ident("y")));
275 assertExpr("(x &= y)", aExpr("&=", ident("x"), ident("y")));
276 assertExpr("(x || y)", logExpr("||", ident("x"), ident("y")));
277 assertExpr("(x && y)", logExpr("&&", ident("x"), ident("y")));
278 assertExpr("(w || x || y || z)", logExpr("||", ident("w"), logExpr("||", ident("x", logExpr("||", ident("y"), ident("z"))))))
279 assertExpr("(x ? y : z)", condExpr(ident("x"), ident("y"), ident("z")));
280 assertExpr("(x,y)", seqExpr([ident("x"),ident("y")]))
281 assertExpr("(x,y,z)", seqExpr([ident("x"),ident("y"),ident("z")]))
282 assertExpr("(a,b,c,d,e,f,g)", seqExpr([ident("a"),ident("b"),ident("c"),ident("d"),ident("e"),ident("f"),ident("g")]));
283 assertExpr("(new Object)", newExpr(ident("Object"), []));
284 assertExpr("(new Object())", newExpr(ident("Object"), []));
285 assertExpr("(new Object(42))", newExpr(ident("Object"), [lit(42)]));
286 assertExpr("(new Object(1,2,3))", newExpr(ident("Object"), [lit(1),lit(2),lit(3)]));
287 assertExpr("(String())", callExpr(ident("String"), []));
288 assertExpr("(String(42))", callExpr(ident("String"), [lit(42)]));
289 assertExpr("(String(1,2,3))", callExpr(ident("String"), [lit(1),lit(2),lit(3)]));
290 assertExpr("[]", arrExpr([]));
291 assertExpr("[1]", arrExpr([lit(1)]));
292 assertExpr("[1,2]", arrExpr([lit(1),lit(2)]));
293 assertExpr("[1,2,3]", arrExpr([lit(1),lit(2),lit(3)]));
294 assertExpr("[1,,2,3]", arrExpr([lit(1),,lit(2),lit(3)]));
295 assertExpr("[1,,,2,3]", arrExpr([lit(1),,,lit(2),lit(3)]));
296 assertExpr("[1,,,2,,3]", arrExpr([lit(1),,,lit(2),,lit(3)]));
297 assertExpr("[1,,,2,,,3]", arrExpr([lit(1),,,lit(2),,,lit(3)]));
298 assertExpr("[,1,2,3]", arrExpr([,lit(1),lit(2),lit(3)]));
299 assertExpr("[,,1,2,3]", arrExpr([,,lit(1),lit(2),lit(3)]));
300 assertExpr("[,,,1,2,3]", arrExpr([,,,lit(1),lit(2),lit(3)]));
301 assertExpr("[,,,1,2,3,]", arrExpr([,,,lit(1),lit(2),lit(3)]));
302 assertExpr("[,,,1,2,3,,]", arrExpr([,,,lit(1),lit(2),lit(3),]));
303 assertExpr("[,,,1,2,3,,,]", arrExpr([,,,lit(1),lit(2),lit(3),,]));
304 assertExpr("[,,,,,]", arrExpr([,,,,]));
305 assertExpr("({})", objExpr([]));
306 assertExpr("({x:1})", objExpr([{ key: ident("x"), value: lit(1) }]));
307 assertExpr("({x:1, y:2})", objExpr([{ key: ident("x"), value: lit(1) },
308                                     { key: ident("y"), value: lit(2) } ]));
309 assertExpr("({x:1, y:2, z:3})", objExpr([{ key: ident("x"), value: lit(1) },
310                                          { key: ident("y"), value: lit(2) },
311                                          { key: ident("z"), value: lit(3) } ]));
312 assertExpr("({x:1, 'y':2, z:3})", objExpr([{ key: ident("x"), value: lit(1) },
313                                            { key: lit("y"), value: lit(2) },
314                                            { key: ident("z"), value: lit(3) } ]));
315 assertExpr("({'x':1, 'y':2, z:3})", objExpr([{ key: lit("x"), value: lit(1) },
316                                              { key: lit("y"), value: lit(2) },
317                                              { key: ident("z"), value: lit(3) } ]));
318 assertExpr("({'x':1, 'y':2, 3:3})", objExpr([{ key: lit("x"), value: lit(1) },
319                                              { key: lit("y"), value: lit(2) },
320                                              { key: lit(3), value: lit(3) } ]));
321
322 // statements
323
324 assertStmt("throw 42", throwStmt(lit(42)));
325 assertStmt("for (;;) break", forStmt(null, null, null, breakStmt(null)));
326 assertStmt("for (x; y; z) break", forStmt(ident("x"), ident("y"), ident("z"), breakStmt(null)));
327 assertStmt("for (var x; y; z) break", forStmt(varDecl([{ id: ident("x"), init: null }]), ident("y"), ident("z")));
328 assertStmt("for (var x = 42; y; z) break", forStmt(varDecl([{ id: ident("x"), init: lit(42) }]), ident("y"), ident("z")));
329 assertStmt("for (x; ; z) break", forStmt(ident("x"), null, ident("z"), breakStmt(null)));
330 assertStmt("for (var x; ; z) break", forStmt(varDecl([{ id: ident("x"), init: null }]), null, ident("z")));
331 assertStmt("for (var x = 42; ; z) break", forStmt(varDecl([{ id: ident("x"), init: lit(42) }]), null, ident("z")));
332 assertStmt("for (x; y; ) break", forStmt(ident("x"), ident("y"), null, breakStmt(null)));
333 assertStmt("for (var x; y; ) break", forStmt(varDecl([{ id: ident("x"), init: null }]), ident("y"), null, breakStmt(null)));
334 assertStmt("for (var x = 42; y; ) break", forStmt(varDecl([{ id: ident("x"), init: lit(42) }]), ident("y"), null, breakStmt(null)));
335 assertStmt("for (var x in y) break", forInStmt(varDecl([{ id: ident("x"), init: null }]), ident("y"), breakStmt(null)));
336 assertStmt("for (x in y) break", forInStmt(ident("x"), ident("y"), breakStmt(null)));
337 assertStmt("{ }", blockStmt([]));
338 assertStmt("{ throw 1; throw 2; throw 3; }", blockStmt([ throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]));
339 assertStmt(";", emptyStmt);
340 assertStmt("if (foo) throw 42;", ifStmt(ident("foo"), throwStmt(lit(42)), null));
341 assertStmt("if (foo) throw 42; else true;", ifStmt(ident("foo"), throwStmt(lit(42)), exprStmt(lit(true))));
342 assertStmt("if (foo) { throw 1; throw 2; throw 3; }",
343            ifStmt(ident("foo"),
344                   blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]),
345                   null));
346 assertStmt("if (foo) { throw 1; throw 2; throw 3; } else true;",
347            ifStmt(ident("foo"),
348                   blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]),
349                   exprStmt(lit(true))));
350 assertStmt("foo: for(;;) break foo;", labStmt(ident("foo"), forStmt(null, null, null, breakStmt(ident("foo")))));
351 assertStmt("foo: for(;;) continue foo;", labStmt(ident("foo"), forStmt(null, null, null, continueStmt(ident("foo")))));
352 assertStmt("with (obj) { }", withStmt(ident("obj"), blockStmt([])));
353 assertStmt("with (obj) { obj; }", withStmt(ident("obj"), blockStmt([exprStmt(ident("obj"))])));
354 assertStmt("while (foo) { }", whileStmt(ident("foo"), blockStmt([])));
355 assertStmt("while (foo) { foo; }", whileStmt(ident("foo"), blockStmt([exprStmt(ident("foo"))])));
356 assertStmt("do { } while (foo);", doStmt(blockStmt([]), ident("foo")));
357 assertStmt("do { foo; } while (foo)", doStmt(blockStmt([exprStmt(ident("foo"))]), ident("foo")));
358 assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; }",
359            switchStmt(ident("foo"),
360                       [ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]),
361                         caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]),
362                         defaultClause([ exprStmt(lit(3)) ]) ]));
363 assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; case 42: 42; }",
364            switchStmt(ident("foo"),
365                       [ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]),
366                         caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]),
367                         defaultClause([ exprStmt(lit(3)) ]),
368                         caseClause(lit(42), [ exprStmt(lit(42)) ]) ]));
369 assertStmt("try { } catch (e) { }",
370            tryStmt(blockStmt([]),
371                    catchClause(ident("e"), null, blockStmt([])),
372                    null));
373 assertStmt("try { } catch (e) { } finally { }",
374            tryStmt(blockStmt([]),
375                    catchClause(ident("e"), null, blockStmt([])),
376                    blockStmt([])));
377 assertStmt("try { } finally { }",
378            tryStmt(blockStmt([]),
379                    null,
380                    blockStmt([])));
381 assertStmt("try { } catch (e if foo) { } catch (e if bar) { } finally { }",
382            tryStmt(blockStmt([]),
383                    [ catchClause(ident("e"), ident("foo"), blockStmt([])),
384                      catchClause(ident("e"), ident("bar"), blockStmt([])) ],
385                    blockStmt([])));
386 assertStmt("try { } catch (e if foo) { } catch (e if bar) { } catch (e) { } finally { }",
387            tryStmt(blockStmt([]),
388                    [ catchClause(ident("e"), ident("foo"), blockStmt([])),
389                      catchClause(ident("e"), ident("bar"), blockStmt([])),
390                      catchClause(ident("e"), null, blockStmt([])) ],
391                    blockStmt([])));
392
393 // redeclarations (TOK_NAME nodes with lexdef)
394
395 assertStmt("function f() { function g() { } function g() { } }",
396            funDecl(ident("f"), [], blockStmt([funDecl(ident("g"), [], blockStmt([])),
397                                               funDecl(ident("g"), [], blockStmt([]))])));
398
399 assertStmt("function f() { function g() { } function g() { return 42 } }",
400            funDecl(ident("f"), [], blockStmt([funDecl(ident("g"), [], blockStmt([])),
401                                               funDecl(ident("g"), [], blockStmt([returnStmt(lit(42))]))])));
402
403 assertStmt("function f() { var x = 42; var x = 43; }",
404            funDecl(ident("f"), [], blockStmt([varDecl([{ id: ident("x"), init: lit(42) }]),
405                                               varDecl([{ id: ident("x"), init: lit(43) }])])));
406
407
408 assertDecl("var {x:y} = foo;", varDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
409                                           init: ident("foo") }]));
410
411 // global let is var
412 assertGlobalDecl("let {x:y} = foo;", varDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
413                                                 init: ident("foo") }]));
414 // function-global let is var
415 assertLocalDecl("let {x:y} = foo;", varDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
416                                                init: ident("foo") }]));
417 // block-local let is let
418 assertBlockDecl("let {x:y} = foo;", letDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
419                                                init: ident("foo") }]));
420
421 assertDecl("const {x:y} = foo;", constDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
422                                               init: ident("foo") }]));
423
424
425 // various combinations of identifiers and destructuring patterns:
426 function makePatternCombinations(id, destr)
427     [
428       [ id(1)                                            ],
429       [ id(1),    id(2)                                  ],
430       [ id(1),    id(2),    id(3)                        ],
431       [ id(1),    id(2),    id(3),    id(4)              ],
432       [ id(1),    id(2),    id(3),    id(4),    id(5)    ],
433
434       [ destr(1)                                         ],
435       [ destr(1), destr(2)                               ],
436       [ destr(1), destr(2), destr(3)                     ],
437       [ destr(1), destr(2), destr(3), destr(4)           ],
438       [ destr(1), destr(2), destr(3), destr(4), destr(5) ],
439
440       [ destr(1), id(2)                                  ],
441
442       [ destr(1), id(2),    id(3)                        ],
443       [ destr(1), id(2),    id(3),    id(4)              ],
444       [ destr(1), id(2),    id(3),    id(4),    id(5)    ],
445       [ destr(1), id(2),    id(3),    id(4),    destr(5) ],
446       [ destr(1), id(2),    id(3),    destr(4)           ],
447       [ destr(1), id(2),    id(3),    destr(4), id(5)    ],
448       [ destr(1), id(2),    id(3),    destr(4), destr(5) ],
449
450       [ destr(1), id(2),    destr(3)                     ],
451       [ destr(1), id(2),    destr(3), id(4)              ],
452       [ destr(1), id(2),    destr(3), id(4),    id(5)    ],
453       [ destr(1), id(2),    destr(3), id(4),    destr(5) ],
454       [ destr(1), id(2),    destr(3), destr(4)           ],
455       [ destr(1), id(2),    destr(3), destr(4), id(5)    ],
456       [ destr(1), id(2),    destr(3), destr(4), destr(5) ],
457
458       [ id(1),    destr(2)                               ],
459
460       [ id(1),    destr(2), id(3)                        ],
461       [ id(1),    destr(2), id(3),    id(4)              ],
462       [ id(1),    destr(2), id(3),    id(4),    id(5)    ],
463       [ id(1),    destr(2), id(3),    id(4),    destr(5) ],
464       [ id(1),    destr(2), id(3),    destr(4)           ],
465       [ id(1),    destr(2), id(3),    destr(4), id(5)    ],
466       [ id(1),    destr(2), id(3),    destr(4), destr(5) ],
467
468       [ id(1),    destr(2), destr(3)                     ],
469       [ id(1),    destr(2), destr(3), id(4)              ],
470       [ id(1),    destr(2), destr(3), id(4),    id(5)    ],
471       [ id(1),    destr(2), destr(3), id(4),    destr(5) ],
472       [ id(1),    destr(2), destr(3), destr(4)           ],
473       [ id(1),    destr(2), destr(3), destr(4), id(5)    ],
474       [ id(1),    destr(2), destr(3), destr(4), destr(5) ]
475     ]
476
477 // destructuring function parameters
478
479 function testParamPatternCombinations(makePattSrc, makePattPatt) {
480     var pattSrcs = makePatternCombinations(function(n) ("x" + n), makePattSrc);
481     var pattPatts = makePatternCombinations(function(n) (ident("x" + n)), makePattPatt);
482
483     for (var i = 0; i < pattSrcs.length; i++) {
484         function makeSrc(body) ("(function(" + pattSrcs[i].join(",") + ") " + body + ")")
485         function makePatt(body) (funExpr(null, pattPatts[i], body))
486
487         // no upvars, block body
488         assertExpr(makeSrc("{ }", makePatt(blockStmt([]))));
489         // upvars, block body
490         assertExpr(makeSrc("{ return [x1,x2,x3,x4,x5]; }"),
491                    makePatt(blockStmt([returnStmt(arrExpr([ident("x1"), ident("x2"), ident("x3"), ident("x4"), ident("x5")]))])));
492         // no upvars, expression body
493         assertExpr(makeSrc("(0)"), makePatt(lit(0)));
494         // upvars, expression body
495         assertExpr(makeSrc("[x1,x2,x3,x4,x5]"),
496                    makePatt(arrExpr([ident("x1"), ident("x2"), ident("x3"), ident("x4"), ident("x5")])));
497     }
498 }
499
500 testParamPatternCombinations(function(n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "}"),
501                              function(n) (objPatt([{ key: ident("a" + n), value: ident("x" + n) },
502                                                    { key: ident("b" + n), value: ident("y" + n) },
503                                                    { key: ident("c" + n), value: ident("z" + n) }])));
504
505 testParamPatternCombinations(function(n) ("[x" + n + "," + "y" + n + "," + "z" + n + "]"),
506                              function(n) (arrPatt([ident("x" + n), ident("y" + n), ident("z" + n)])));
507
508
509 // destructuring variable declarations
510
511 function testVarPatternCombinations(makePattSrc, makePattPatt) {
512     var pattSrcs = makePatternCombinations(function(n) ("x" + n), makePattSrc);
513     var pattPatts = makePatternCombinations(function(n) ({ id: ident("x" + n), init: null }), makePattPatt);
514
515     for (var i = 0; i < pattSrcs.length; i++) {
516         // variable declarations in blocks
517         assertDecl("var " + pattSrcs[i].join(",") + ";", varDecl(pattPatts[i]));
518
519         assertGlobalDecl("let " + pattSrcs[i].join(",") + ";", varDecl(pattPatts[i]));
520         assertLocalDecl("let " + pattSrcs[i].join(",") + ";", varDecl(pattPatts[i]));
521         assertBlockDecl("let " + pattSrcs[i].join(",") + ";", letDecl(pattPatts[i]));
522
523         assertDecl("const " + pattSrcs[i].join(",") + ";", constDecl(pattPatts[i]));
524
525         // variable declarations in for-loop heads
526         assertStmt("for (var " + pattSrcs[i].join(",") + "; foo; bar);",
527                    forStmt(varDecl(pattPatts[i]), ident("foo"), ident("bar"), emptyStmt));
528         assertStmt("for (let " + pattSrcs[i].join(",") + "; foo; bar);",
529                    forStmt(letDecl(pattPatts[i]), ident("foo"), ident("bar"), emptyStmt));
530         assertStmt("for (const " + pattSrcs[i].join(",") + "; foo; bar);",
531                    forStmt(constDecl(pattPatts[i]), ident("foo"), ident("bar"), emptyStmt));
532     }
533 }
534
535 testVarPatternCombinations(function (n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "} = 0"),
536                            function (n) ({ id: objPatt([{ key: ident("a" + n), value: ident("x" + n) },
537                                                         { key: ident("b" + n), value: ident("y" + n) },
538                                                         { key: ident("c" + n), value: ident("z" + n) }]),
539                                            init: lit(0) }));
540
541 testVarPatternCombinations(function(n) ("[x" + n + "," + "y" + n + "," + "z" + n + "] = 0"),
542                            function(n) ({ id: arrPatt([ident("x" + n), ident("y" + n), ident("z" + n)]),
543                                           init: lit(0) }));
544
545 // destructuring assignment
546
547 function testAssignmentCombinations(makePattSrc, makePattPatt) {
548     var pattSrcs = makePatternCombinations(function(n) ("x" + n + " = 0"), makePattSrc);
549     var pattPatts = makePatternCombinations(function(n) (aExpr("=", ident("x" + n), lit(0))), makePattPatt);
550
551     for (var i = 0; i < pattSrcs.length; i++) {
552         var src = pattSrcs[i].join(",");
553         var patt = pattPatts[i].length === 1 ? pattPatts[i][0] : seqExpr(pattPatts[i]);
554
555         // assignment expression statement
556         assertExpr("(" + src + ")", patt);
557
558         // for-loop head assignment
559         assertStmt("for (" + src + "; foo; bar);",
560                    forStmt(patt, ident("foo"), ident("bar"), emptyStmt));
561     }
562 }
563
564 testAssignmentCombinations(function (n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "} = 0"),
565                            function (n) (aExpr("=",
566                                                objPatt([{ key: ident("a" + n), value: ident("x" + n) },
567                                                         { key: ident("b" + n), value: ident("y" + n) },
568                                                         { key: ident("c" + n), value: ident("z" + n) }]),
569                                                lit(0))));
570
571
572 // destructuring in for-in and for-each-in loop heads
573
574 var axbycz = objPatt([{ key: ident("a"), value: ident("x") },
575                       { key: ident("b"), value: ident("y") },
576                       { key: ident("c"), value: ident("z") }]);
577 var xyz = arrPatt([ident("x"), ident("y"), ident("z")]);
578
579 assertStmt("for (var {a:x,b:y,c:z} in foo);", forInStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
580 assertStmt("for (let {a:x,b:y,c:z} in foo);", forInStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
581 assertStmt("for ({a:x,b:y,c:z} in foo);", forInStmt(axbycz, ident("foo"), emptyStmt));
582 assertStmt("for (var [x,y,z] in foo);", forInStmt(varDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
583 assertStmt("for (let [x,y,z] in foo);", forInStmt(letDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
584 assertStmt("for ([x,y,z] in foo);", forInStmt(xyz, ident("foo"), emptyStmt));
585 assertStmt("for each (var {a:x,b:y,c:z} in foo);", forEachInStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
586 assertStmt("for each (let {a:x,b:y,c:z} in foo);", forEachInStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
587 assertStmt("for each ({a:x,b:y,c:z} in foo);", forEachInStmt(axbycz, ident("foo"), emptyStmt));
588 assertStmt("for each (var [x,y,z] in foo);", forEachInStmt(varDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
589 assertStmt("for each (let [x,y,z] in foo);", forEachInStmt(letDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
590 assertStmt("for each ([x,y,z] in foo);", forEachInStmt(xyz, ident("foo"), emptyStmt));
591 assertError("for (const x in foo);", SyntaxError);
592 assertError("for (const {a:x,b:y,c:z} in foo);", SyntaxError);
593 assertError("for (const [x,y,z] in foo);", SyntaxError);
594 assertError("for each (const x in foo);", SyntaxError);
595 assertError("for each (const {a:x,b:y,c:z} in foo);", SyntaxError);
596 assertError("for each (const [x,y,z] in foo);", SyntaxError);
597
598 // destructuring in for-in and for-each-in loop heads with initializers
599
600 assertStmt("for (var {a:x,b:y,c:z} = 22 in foo);", forInStmt(varDecl([{ id: axbycz, init: lit(22) }]), ident("foo"), emptyStmt));
601 assertStmt("for (var [x,y,z] = 22 in foo);", forInStmt(varDecl([{ id: xyz, init: lit(22) }]), ident("foo"), emptyStmt));
602 assertStmt("for each (var {a:x,b:y,c:z} = 22 in foo);", forEachInStmt(varDecl([{ id: axbycz, init: lit(22) }]), ident("foo"), emptyStmt));
603 assertStmt("for each (var [x,y,z] = 22 in foo);", forEachInStmt(varDecl([{ id: xyz, init: lit(22) }]), ident("foo"), emptyStmt));
604 assertError("for (x = 22 in foo);", SyntaxError);
605 assertError("for ({a:x,b:y,c:z} = 22 in foo);", SyntaxError);
606 assertError("for ([x,y,z] = 22 in foo);", SyntaxError);
607 assertError("for (const x = 22 in foo);", SyntaxError);
608 assertError("for (const {a:x,b:y,c:z} = 22 in foo);", SyntaxError);
609 assertError("for (const [x,y,z] = 22 in foo);", SyntaxError);
610 assertError("for each (const x = 22 in foo);", SyntaxError);
611 assertError("for each (const {a:x,b:y,c:z} = 22 in foo);", SyntaxError);
612 assertError("for each (const [x,y,z] = 22 in foo);", SyntaxError);
613
614 // expression closures
615
616 assertDecl("function inc(x) (x + 1)", funDecl(ident("inc"), [ident("x")], binExpr("+", ident("x"), lit(1))));
617 assertExpr("(function(x) (x+1))", funExpr(null, [ident("x")], binExpr("+"), ident("x"), lit(1)));
618
619 // generators
620
621 assertDecl("function gen(x) { yield }", genFunDecl(ident("gen"), [ident("x")], blockStmt([exprStmt(yieldExpr(null))])));
622 assertExpr("(function(x) { yield })", genFunExpr(null, [ident("x")], blockStmt([exprStmt(yieldExpr(null))])));
623 assertDecl("function gen(x) { yield 42 }", genFunDecl(ident("gen"), [ident("x")], blockStmt([exprStmt(yieldExpr(lit(42)))])));
624 assertExpr("(function(x) { yield 42 })", genFunExpr(null, [ident("x")], blockStmt([exprStmt(yieldExpr(lit(42)))])));
625
626 // getters and setters
627
628 assertExpr("({ get x() { return 42 } })",
629            objExpr([ { key: ident("x"),
630                        value: funExpr(null, [], blockStmt([returnStmt(lit(42))])),
631                        kind: "get" } ]));
632 assertExpr("({ set x(v) { return 42 } })",
633            objExpr([ { key: ident("x"),
634                        value: funExpr(null, [ident("v")], blockStmt([returnStmt(lit(42))])),
635                        kind: "set" } ]));
636
637 // comprehensions
638
639 assertExpr("[ x         for (x in foo)]",
640            compExpr(ident("x"), [compBlock(ident("x"), ident("foo"))], null));
641 assertExpr("[ [x,y]     for (x in foo) for (y in bar)]",
642            compExpr(arrExpr([ident("x"), ident("y")]), [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar"))], null));
643 assertExpr("[ [x,y,z] for (x in foo) for (y in bar) for (z in baz)]",
644            compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
645                     [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar")), compBlock(ident("z"), ident("baz"))],
646                     null));
647
648 assertExpr("[ x         for (x in foo) if (p)]",
649            compExpr(ident("x"), [compBlock(ident("x"), ident("foo"))], ident("p")));
650 assertExpr("[ [x,y]     for (x in foo) for (y in bar) if (p)]",
651            compExpr(arrExpr([ident("x"), ident("y")]), [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar"))], ident("p")));
652 assertExpr("[ [x,y,z] for (x in foo) for (y in bar) for (z in baz) if (p) ]",
653            compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
654                     [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar")), compBlock(ident("z"), ident("baz"))],
655                     ident("p")));
656
657 assertExpr("[ x         for each (x in foo)]",
658            compExpr(ident("x"), [compEachBlock(ident("x"), ident("foo"))], null));
659 assertExpr("[ [x,y]     for each (x in foo) for each (y in bar)]",
660            compExpr(arrExpr([ident("x"), ident("y")]), [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar"))], null));
661 assertExpr("[ [x,y,z] for each (x in foo) for each (y in bar) for each (z in baz)]",
662            compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
663                     [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar")), compEachBlock(ident("z"), ident("baz"))],
664                     null));
665
666 assertExpr("[ x         for each (x in foo) if (p)]",
667            compExpr(ident("x"), [compEachBlock(ident("x"), ident("foo"))], ident("p")));
668 assertExpr("[ [x,y]     for each (x in foo) for each (y in bar) if (p)]",
669            compExpr(arrExpr([ident("x"), ident("y")]), [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar"))], ident("p")));
670 assertExpr("[ [x,y,z] for each (x in foo) for each (y in bar) for each (z in baz) if (p) ]",
671            compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
672                     [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar")), compEachBlock(ident("z"), ident("baz"))],
673                     ident("p")));
674
675 // generator expressions
676
677 assertExpr("( x         for (x in foo))",
678            genExpr(ident("x"), [compBlock(ident("x"), ident("foo"))], null));
679 assertExpr("( [x,y]     for (x in foo) for (y in bar))",
680            genExpr(arrExpr([ident("x"), ident("y")]), [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar"))], null));
681 assertExpr("( [x,y,z] for (x in foo) for (y in bar) for (z in baz))",
682            genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
683                    [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar")), compBlock(ident("z"), ident("baz"))],
684                    null));
685
686 assertExpr("( x         for (x in foo) if (p))",
687            genExpr(ident("x"), [compBlock(ident("x"), ident("foo"))], ident("p")));
688 assertExpr("( [x,y]     for (x in foo) for (y in bar) if (p))",
689            genExpr(arrExpr([ident("x"), ident("y")]), [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar"))], ident("p")));
690 assertExpr("( [x,y,z] for (x in foo) for (y in bar) for (z in baz) if (p) )",
691            genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
692                    [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar")), compBlock(ident("z"), ident("baz"))],
693                    ident("p")));
694
695 assertExpr("( x         for each (x in foo))",
696            genExpr(ident("x"), [compEachBlock(ident("x"), ident("foo"))], null));
697 assertExpr("( [x,y]     for each (x in foo) for each (y in bar))",
698            genExpr(arrExpr([ident("x"), ident("y")]), [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar"))], null));
699 assertExpr("( [x,y,z] for each (x in foo) for each (y in bar) for each (z in baz))",
700            genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
701                    [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar")), compEachBlock(ident("z"), ident("baz"))],
702                    null));
703
704 assertExpr("( x         for each (x in foo) if (p))",
705            genExpr(ident("x"), [compEachBlock(ident("x"), ident("foo"))], ident("p")));
706 assertExpr("( [x,y]     for each (x in foo) for each (y in bar) if (p))",
707            genExpr(arrExpr([ident("x"), ident("y")]), [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar"))], ident("p")));
708 assertExpr("( [x,y,z] for each (x in foo) for each (y in bar) for each (z in baz) if (p) )",
709            genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
710                    [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar")), compEachBlock(ident("z"), ident("baz"))],
711                    ident("p")));
712
713 // NOTE: it would be good to test generator expressions both with and without upvars, just like functions above.
714
715
716 // sharp variables
717
718 assertExpr("#1={me:#1#}", graphExpr(1, objExpr([{ key: ident("me"), value: idxExpr(1) }])));
719
720 // let expressions
721
722 assertExpr("(let (x=1) x)", letExpr([{ id: ident("x"), init: lit(1) }], ident("x")));
723 assertExpr("(let (x=1,y=2) y)", letExpr([{ id: ident("x"), init: lit(1) },
724                                          { id: ident("y"), init: lit(2) }],
725                                         ident("y")));
726 assertExpr("(let (x=1,y=2,z=3) z)", letExpr([{ id: ident("x"), init: lit(1) },
727                                              { id: ident("y"), init: lit(2) },
728                                              { id: ident("z"), init: lit(3) }],
729                                             ident("z")));
730 assertExpr("(let (x) x)", letExpr([{ id: ident("x"), init: null }], ident("x")));
731 assertExpr("(let (x,y) y)", letExpr([{ id: ident("x"), init: null },
732                                      { id: ident("y"), init: null }],
733                                     ident("y")));
734 assertExpr("(let (x,y,z) z)", letExpr([{ id: ident("x"), init: null },
735                                        { id: ident("y"), init: null },
736                                        { id: ident("z"), init: null }],
737                                       ident("z")));
738 assertExpr("(let (x = 1, y = x) y)", letExpr([{ id: ident("x"), init: lit(1) },
739                                               { id: ident("y"), init: ident("x") }],
740                                              ident("y")));
741 assertError("(let (x = 1, x = 2) x)", TypeError);
742
743 // let statements
744
745 assertStmt("let (x=1) { }", letStmt([{ id: ident("x"), init: lit(1) }], blockStmt([])));
746 assertStmt("let (x=1,y=2) { }", letStmt([{ id: ident("x"), init: lit(1) },
747                                          { id: ident("y"), init: lit(2) }],
748                                         blockStmt([])));
749 assertStmt("let (x=1,y=2,z=3) { }", letStmt([{ id: ident("x"), init: lit(1) },
750                                              { id: ident("y"), init: lit(2) },
751                                              { id: ident("z"), init: lit(3) }],
752                                             blockStmt([])));
753 assertStmt("let (x) { }", letStmt([{ id: ident("x"), init: null }], blockStmt([])));
754 assertStmt("let (x,y) { }", letStmt([{ id: ident("x"), init: null },
755                                      { id: ident("y"), init: null }],
756                                     blockStmt([])));
757 assertStmt("let (x,y,z) { }", letStmt([{ id: ident("x"), init: null },
758                                        { id: ident("y"), init: null },
759                                        { id: ident("z"), init: null }],
760                                       blockStmt([])));
761 assertStmt("let (x = 1, y = x) { }", letStmt([{ id: ident("x"), init: lit(1) },
762                                               { id: ident("y"), init: ident("x") }],
763                                              blockStmt([])));
764 assertError("let (x = 1, x = 2) { }", TypeError);
765
766
767 // E4X
768
769 assertExpr("x..tagName", binExpr("..", ident("x"), lit("tagName")));
770 assertExpr("x.*", memExpr(ident("x"), xmlAnyName));
771 assertExpr("x[*]", memExpr(ident("x"), xmlAnyName));
772 assertExpr("x::y", xmlQualId(ident("x"), ident("y"), false));
773 assertExpr("x::[foo]", xmlQualId(ident("x"), ident("foo"), true));
774 assertExpr("x::[foo()]", xmlQualId(ident("x"), callExpr(ident("foo"), []), true));
775 assertExpr("*::*", xmlQualId(xmlAnyName, ident("*"), false));
776 assertExpr("*::[foo]", xmlQualId(xmlAnyName, ident("foo"), true));
777 assertExpr("*::[foo()]", xmlQualId(xmlAnyName, callExpr(ident("foo"), []), true));
778 assertExpr("function::x", xmlFuncQualId(ident("x"), false));
779 assertExpr("function::[foo]", xmlFuncQualId(ident("foo"), true));
780 assertExpr("@foo", xmlAttrSel(ident("foo")));
781 assertExpr("x.(p)", xmlFilter(ident("x"), ident("p")));
782 assertExpr("<{foo}/>", xmlPointTag([xmlEscape(ident("foo"))]));
783 assertExpr("<{foo}></{foo}>", xmlElt([xmlStartTag([xmlEscape(ident("foo"))]),
784                                       xmlEndTag([xmlEscape(ident("foo"))])]));
785 assertExpr("<{foo} {attr}='attr'/>", xmlPointTag([xmlEscape(ident("foo")),
786                                                   xmlEscape(ident("attr")),
787                                                   xmlAttr("attr")]));
788 assertExpr("<{foo}>text</{foo}>", xmlElt([xmlStartTag([xmlEscape(ident("foo"))]),
789                                           xmlText("text"),
790                                           xmlEndTag([xmlEscape(ident("foo"))])]));
791 assertExpr("<?xml?>", xmlPI("xml", ""));
792 assertExpr("<?xml version='1.0'?>", xmlPI("xml", "version='1.0'"));
793 assertDecl("default xml namespace = 'js';", xmlDefNS(lit("js")));
794 assertDecl("default xml namespace = foo;", xmlDefNS(ident("foo")));
795
796 // The parser turns these into TOK_UNARY nodes with pn_op == JSOP_SETXMLNAME.
797
798 assertExpr("x::y = foo", aExpr("=", xmlQualId(ident("x"), ident("y"), false), ident("foo")));
799 assertExpr("function::x = foo", aExpr("=", xmlFuncQualId(ident("x"), false), ident("foo")));
800 assertExpr("@x = foo", aExpr("=", xmlAttrSel(ident("x")), ident("foo")));
801 assertExpr("x::* = foo", aExpr("=", xmlQualId(ident("x"), ident("*"), false), ident("foo")));
802 assertExpr("*::* = foo", aExpr("=", xmlQualId(xmlAnyName, ident("*"), false), ident("foo")));
803 assertExpr("x.* = foo", aExpr("=", memExpr(ident("x"), xmlAnyName), ident("foo")));
804 assertExpr("x[*] = foo", aExpr("=", memExpr(ident("x"), xmlAnyName), ident("foo")));
805
806 assertExpr("x::y += foo", aExpr("+=", xmlQualId(ident("x"), ident("y"), false), ident("foo")));
807 assertExpr("function::x += foo", aExpr("+=", xmlFuncQualId(ident("x"), false), ident("foo")));
808 assertExpr("@x += foo", aExpr("+=", xmlAttrSel(ident("x")), ident("foo")));
809 assertExpr("x::* += foo", aExpr("+=", xmlQualId(ident("x"), ident("*"), false), ident("foo")));
810 assertExpr("*::* += foo", aExpr("+=", xmlQualId(xmlAnyName, ident("*"), false), ident("foo")));
811 assertExpr("x.* += foo", aExpr("+=", memExpr(ident("x"), xmlAnyName), ident("foo")));
812 assertExpr("x[*] += foo", aExpr("+=", memExpr(ident("x"), xmlAnyName), ident("foo")));
813
814 assertExpr("x::y++", updExpr("++", xmlQualId(ident("x"), ident("y"), false), false));
815 assertExpr("function::x++", updExpr("++", xmlFuncQualId(ident("x"), false), false));
816 assertExpr("@x++", updExpr("++", xmlAttrSel(ident("x")), false));
817 assertExpr("x::*++", updExpr("++", xmlQualId(ident("x"), ident("*"), false), false));
818 assertExpr("*::*++", updExpr("++", xmlQualId(xmlAnyName, ident("*"), false), false));
819 assertExpr("x.*++", updExpr("++", memExpr(ident("x"), xmlAnyName), false));
820 assertExpr("x[*]++", updExpr("++", memExpr(ident("x"), xmlAnyName), false));
821
822 assertExpr("++x::y", updExpr("++", xmlQualId(ident("x"), ident("y"), false), true));
823 assertExpr("++function::x", updExpr("++", xmlFuncQualId(ident("x"), false), true));
824 assertExpr("++@x", updExpr("++", xmlAttrSel(ident("x")), true));
825 assertExpr("++x::*", updExpr("++", xmlQualId(ident("x"), ident("*"), false), true));
826 assertExpr("++*::*", updExpr("++", xmlQualId(xmlAnyName, ident("*"), false), true));
827 assertExpr("++x.*", updExpr("++", memExpr(ident("x"), xmlAnyName), true));
828 assertExpr("++x[*]", updExpr("++", memExpr(ident("x"), xmlAnyName), true));
829
830
831 // The parser turns these into TOK_UNARY nodes with pn_op == JSOP_BINDXMLNAME.
832
833 function singletonObjPatt(name, val) objPatt([{ key: ident(name), value: val }])
834
835 assertExpr("({a:x::y}) = foo", aExpr("=", singletonObjPatt("a", xmlQualId(ident("x"), ident("y"), false)), ident("foo")));
836 assertExpr("({a:function::x}) = foo", aExpr("=", singletonObjPatt("a", xmlFuncQualId(ident("x"), false)), ident("foo")));
837 assertExpr("({a:@x}) = foo", aExpr("=", singletonObjPatt("a", xmlAttrSel(ident("x"))), ident("foo")));
838 assertExpr("({a:x::*}) = foo", aExpr("=", singletonObjPatt("a", xmlQualId(ident("x"), ident("*"), false)), ident("foo")));
839 assertExpr("({a:*::*}) = foo", aExpr("=", singletonObjPatt("a", xmlQualId(xmlAnyName, ident("*"), false)), ident("foo")));
840 assertExpr("({a:x.*}) = foo", aExpr("=", singletonObjPatt("a", memExpr(ident("x"), xmlAnyName)), ident("foo")));
841 assertExpr("({a:x[*]}) = foo", aExpr("=", singletonObjPatt("a", memExpr(ident("x"), xmlAnyName)), ident("foo")));
842
843 function emptyForInPatt(val, rhs) forInStmt(val, rhs, emptyStmt)
844
845 assertStmt("for (x::y in foo);", emptyForInPatt(xmlQualId(ident("x"), ident("y"), false), ident("foo")));
846 assertStmt("for (function::x in foo);", emptyForInPatt(xmlFuncQualId(ident("x"), false), ident("foo")));
847 assertStmt("for (@x in foo);", emptyForInPatt(xmlAttrSel(ident("x")), ident("foo")));
848 assertStmt("for (x::* in foo);", emptyForInPatt(xmlQualId(ident("x"), ident("*"), false), ident("foo")));
849 assertStmt("for (*::* in foo);", emptyForInPatt(xmlQualId(xmlAnyName, ident("*"), false), ident("foo")));
850 assertStmt("for (x.* in foo);", emptyForInPatt(memExpr(ident("x"), xmlAnyName), ident("foo")));
851 assertStmt("for (x[*] in foo);", emptyForInPatt(memExpr(ident("x"), xmlAnyName), ident("foo")));
852
853
854 // I'm not quite sure why, but putting XML in the callee of a call expression is
855 // the only way I've found to be able to preserve TOK_XMLNAME, TOK_XMLSPACE,
856 // TOK_XMLCDATA, and TOK_XMLCOMMENT parse nodes.
857
858 assertExpr("(<x> </x>)()", callExpr(xmlElt([xmlStartTag([xmlName("x")]),
859                                             xmlText(" "),
860                                             xmlEndTag([xmlName("x")])]),
861                                     []));
862 assertExpr("(<x>    </x>)()", callExpr(xmlElt([xmlStartTag([xmlName("x")]),
863                                                xmlText("    "),
864                                                xmlEndTag([xmlName("x")])]),
865                                        []));
866 assertExpr("(<x><![CDATA[hello, world]]></x>)()", callExpr(xmlElt([xmlStartTag([xmlName("x")]),
867                                                                    xmlCdata("hello, world"),
868                                                                    xmlEndTag([xmlName("x")])]),
869                                                            []));
870 assertExpr("(<x><!-- hello, world --></x>)()", callExpr(xmlElt([xmlStartTag([xmlName("x")]),
871                                                                 xmlComment(" hello, world "),
872                                                                 xmlEndTag([xmlName("x")])]),
873                                                         []));
874
875
876 // Source location information
877
878
879 var withoutFileOrLine = Reflect.parse("42");
880 var withFile = Reflect.parse("42", {source:"foo.js"});
881 var withFileAndLine = Reflect.parse("42", {source:"foo.js", line:111});
882
883 Pattern({ source: null, start: { line: 1, column: 0 }, end: { line: 1, column: 2 } }).match(withoutFileOrLine.loc);
884 Pattern({ source: "foo.js", start: { line: 1, column: 0 }, end: { line: 1, column: 2 } }).match(withFile.loc);
885 Pattern({ source: "foo.js", start: { line: 111, column: 0 }, end: { line: 111, column: 2 } }).match(withFileAndLine.loc);
886
887 var withoutFileOrLine2 = Reflect.parse("foo +\nbar");
888 var withFile2 = Reflect.parse("foo +\nbar", {source:"foo.js"});
889 var withFileAndLine2 = Reflect.parse("foo +\nbar", {source:"foo.js", line:111});
890
891 Pattern({ source: null, start: { line: 1, column: 0 }, end: { line: 2, column: 3 } }).match(withoutFileOrLine2.loc);
892 Pattern({ source: "foo.js", start: { line: 1, column: 0 }, end: { line: 2, column: 3 } }).match(withFile2.loc);
893 Pattern({ source: "foo.js", start: { line: 111, column: 0 }, end: { line: 112, column: 3 } }).match(withFileAndLine2.loc);
894
895 var nested = Reflect.parse("(-b + sqrt(sqr(b) - 4 * a * c)) / (2 * a)", {source:"quad.js"});
896 var fourAC = nested.body[0].expression.left.right.arguments[0].right;
897
898 Pattern({ source: "quad.js", start: { line: 1, column: 20 }, end: { line: 1, column: 29 } }).match(fourAC.loc);
899
900
901 // No source location
902
903 assertEq(Reflect.parse("42", {loc:false}).loc, null);
904 program([exprStmt(lit(42))]).assert(Reflect.parse("42", {loc:false}));
905
906
907 // Builder tests
908
909 Pattern("program").match(Reflect.parse("42", {builder:{program:function()"program"}}));
910
911 assertGlobalStmt("throw 42", 1, { throwStatement: function() 1 });
912 assertGlobalStmt("for (;;);", 2, { forStatement: function() 2 });
913 assertGlobalStmt("for (x in y);", 3, { forInStatement: function() 3 });
914 assertGlobalStmt("{ }", 4, { blockStatement: function() 4 });
915 assertGlobalStmt("foo: { }", 5, { labeledStatement: function() 5 });
916 assertGlobalStmt("with (o) { }", 6, { withStatement: function() 6 });
917 assertGlobalStmt("while (x) { }", 7, { whileStatement: function() 7 });
918 assertGlobalStmt("do { } while(false);", 8, { doWhileStatement: function() 8 });
919 assertGlobalStmt("switch (x) { }", 9, { switchStatement: function() 9 });
920 assertGlobalStmt("try { } catch(e) { }", 10, { tryStatement: function() 10 });
921 assertGlobalStmt(";", 11, { emptyStatement: function() 11 });
922 assertGlobalStmt("debugger;", 12, { debuggerStatement: function() 12 });
923 assertGlobalStmt("42;", 13, { expressionStatement: function() 13 });
924 assertGlobalStmt("for (;;) break", forStmt(null, null, null, 14), { breakStatement: function() 14 });
925 assertGlobalStmt("for (;;) continue", forStmt(null, null, null, 15), { continueStatement: function() 15 });
926
927 assertBlockDecl("var x", "var", { variableDeclaration: function(kind) kind });
928 assertBlockDecl("let x", "let", { variableDeclaration: function(kind) kind });
929 assertBlockDecl("const x", "const", { variableDeclaration: function(kind) kind });
930 assertBlockDecl("function f() { }", "function", { functionDeclaration: function() "function" });
931
932 assertGlobalExpr("(x,y,z)", 1, { sequenceExpression: function() 1 });
933 assertGlobalExpr("(x ? y : z)", 2, { conditionalExpression: function() 2 });
934 assertGlobalExpr("x + y", 3, { binaryExpression: function() 3 });
935 assertGlobalExpr("delete x", 4, { unaryExpression: function() 4 });
936 assertGlobalExpr("x = y", 5, { assignmentExpression: function() 5 });
937 assertGlobalExpr("x || y", 6, { logicalExpression: function() 6 });
938 assertGlobalExpr("x++", 7, { updateExpression: function() 7 });
939 assertGlobalExpr("new x", 8, { newExpression: function() 8 });
940 assertGlobalExpr("x()", 9, { callExpression: function() 9 });
941 assertGlobalExpr("x.y", 10, { memberExpression: function() 10 });
942 assertGlobalExpr("(function() { })", 11, { functionExpression: function() 11 });
943 assertGlobalExpr("[1,2,3]", 12, { arrayExpression: function() 12 });
944 assertGlobalExpr("({ x: y })", 13, { objectExpression: function() 13 });
945 assertGlobalExpr("this", 14, { thisExpression: function() 14 });
946 assertGlobalExpr("#1={ }", 15, { graphExpression: function() 15 });
947 assertGlobalExpr("#1={ self: #1# }", graphExpr(1, objExpr([{ key: ident("self"), value: 16 }])), { graphIndexExpression: function() 16 });
948 assertGlobalExpr("[x for (x in y)]", 17, { comprehensionExpression: function() 17 });
949 assertGlobalExpr("(x for (x in y))", 18, { generatorExpression: function() 18 });
950 assertGlobalExpr("(function() { yield 42 })", genFunExpr(null, [], blockStmt([exprStmt(19)])), { yieldExpression: function() 19 });
951 assertGlobalExpr("(let (x) x)", 20, { letExpression: function() 20 });
952
953 assertGlobalStmt("switch (x) { case y: }", switchStmt(ident("x"), [1]), { switchCase: function() 1 });
954 assertGlobalStmt("try { } catch (e) { }", tryStmt(blockStmt([]), 2, null), { catchClause: function() 2 });
955 assertGlobalStmt("try { } catch (e if e instanceof A) { } catch (e if e instanceof B) { }",
956                  tryStmt(blockStmt([]), [2, 2], null),
957                  { catchClause: function() 2 });
958 assertGlobalExpr("[x for (y in z) for (x in y)]", compExpr(ident("x"), [3, 3], null), { comprehensionBlock: function() 3 });
959
960 assertGlobalExpr("({ x: y } = z)", aExpr("=", 1, ident("z")), { objectPattern: function() 1 });
961 assertGlobalExpr("({ x: y } = z)", aExpr("=", objPatt([2]), ident("z")), { propertyPattern: function() 2 });
962 assertGlobalExpr("[ x ] = y", aExpr("=", 3, ident("y")), { arrayPattern: function() 3 });
963
964 assertGlobalExpr("({a:x::y}) = foo", aExpr("=", singletonObjPatt("a", 1), ident("foo")), { xmlQualifiedIdentifier: function() 1 });
965 assertGlobalExpr("({a:function::x}) = foo", aExpr("=", singletonObjPatt("a", 2), ident("foo")), { xmlFunctionQualifiedIdentifier: function() 2 });
966 assertGlobalExpr("({a:@x}) = foo", aExpr("=", singletonObjPatt("a", 3), ident("foo")), { xmlAttributeSelector: function() 3 });
967 assertGlobalExpr("({a:x.*}) = foo", aExpr("=", singletonObjPatt("a", memExpr(ident("x"), 4)), ident("foo")), { xmlAnyName: function() 4 });
968
969 assertGlobalExpr("(<x> </x>)()", callExpr(xmlElt([5, xmlText(" "), xmlEndTag([xmlName("x")])]), []), { xmlStartTag: function() 5 });
970 assertGlobalExpr("(<x> </x>)()", callExpr(xmlElt([xmlStartTag([6]), xmlText(" "), xmlEndTag([6])]), []), { xmlName: function() 6 });
971 assertGlobalExpr("(<x> </x>)()", callExpr(xmlElt([xmlStartTag([xmlName("x")]), 7, xmlEndTag([xmlName("x")])]), []), { xmlText: function() 7 });
972 assertGlobalExpr("(<x> </x>)()", callExpr(xmlElt([xmlStartTag([xmlName("x")]), xmlText(" "), 8]), []), { xmlEndTag: function() 8 });
973 assertGlobalExpr("(<x><![CDATA[hello, world]]></x>)()", callExpr(xmlElt([xmlStartTag([xmlName("x")]), 9, xmlEndTag([xmlName("x")])]), []), { xmlCdata: function() 9 });
974 assertGlobalExpr("(<x><!-- hello, world --></x>)()", callExpr(xmlElt([xmlStartTag([xmlName("x")]), 10, xmlEndTag([xmlName("x")])]), []), { xmlComment: function() 10 });
975
976
977 // Ensure that exceptions thrown by builder methods propagate.
978 var thrown = false;
979 try {
980     Reflect.parse("42", { builder: { program: function() { throw "expected" } } });
981 } catch (e if e === "expected") {
982     thrown = true;
983 }
984 if (!thrown)
985     throw new Error("builder exception not propagated");
986
987
988 // A simple proof-of-concept that the builder API can be used to generate other
989 // formats, such as JsonMLAst:
990 // 
991 //     http://code.google.com/p/es-lab/wiki/JsonMLASTFormat
992 // 
993 // It's incomplete (e.g., it doesn't convert source-location information and
994 // doesn't use all the direct-eval rules), but I think it proves the point.
995
996 var JsonMLAst = (function() {
997 function reject() {
998     throw new SyntaxError("node type not supported");
999 }
1000
1001 function isDirectEval(expr) {
1002     // an approximation to the actual rules. you get the idea
1003     return (expr[0] === "IdExpr" && expr[1].name === "eval");
1004 }
1005
1006 function functionNode(type) {
1007     return function(id, args, body, isGenerator, isExpression) {
1008         if (isExpression)
1009             body = ["ReturnStmt", {}, body];
1010
1011         if (!id)
1012             id = ["Empty"];
1013
1014         // Patch up the argument node types: s/IdExpr/IdPatt/g
1015         for (var i = 0; i < args.length; i++) {
1016             args[i][0] = "IdPatt";
1017         }
1018
1019         args.unshift("ParamDecl", {});
1020
1021         return [type, {}, id, args, body];
1022     }
1023 }
1024
1025 return {
1026     program: function(stmts) {
1027         stmts.unshift("Program", {});
1028         return stmts;
1029     },
1030     identifier: function(name) {
1031         return ["IdExpr", { name: name }];
1032     },
1033     literal: function(val) {
1034         return ["LiteralExpr", { value: val }];
1035     },
1036     expressionStatement: function(expr) expr,
1037     conditionalExpression: function(test, cons, alt) {
1038         return ["ConditionalExpr", {}, test, cons, alt];
1039     },
1040     unaryExpression: function(op, expr) {
1041         return ["UnaryExpr", {op: op}, expr];
1042     },
1043     binaryExpression: function(op, left, right) {
1044         return ["BinaryExpr", {op: op}, left, right];
1045     },
1046     property: function(kind, key, val) {
1047         return [kind === "init"
1048                 ? "DataProp"
1049                 : kind === "get"
1050                 ? "GetterProp"
1051                 : "SetterProp",
1052                 {name: key[1].name}, val];
1053     },
1054     functionDeclaration: functionNode("FunctionDecl"),
1055     variableDeclaration: function(kind, elts) {
1056         if (kind === "let" || kind === "const")
1057             throw new SyntaxError("let and const not supported");
1058         elts.unshift("VarDecl", {});
1059         return elts;
1060     },
1061     variableDeclarator: function(id, init) {
1062         id[0] = "IdPatt";
1063         if (!init)
1064             return id;
1065         return ["InitPatt", {}, id, init];
1066     },
1067     sequenceExpression: function(exprs) {
1068         var length = exprs.length;
1069         var result = ["BinaryExpr", {op:","}, exprs[exprs.length - 2], exprs[exprs.length - 1]];
1070         for (var i = exprs.length - 3; i >= 0; i--) {
1071             result = ["BinaryExpr", {op:","}, exprs[i], result];
1072         }
1073         return result;
1074     },
1075     assignmentExpression: function(op, lhs, expr) {
1076         return ["AssignExpr", {op: op}, lhs, expr];
1077     },
1078     logicalExpression: function(op, left, right) {
1079         return [op === "&&" ? "LogicalAndExpr" : "LogicalOrExpr", {}, left, right];
1080     },
1081     updateExpression: function(expr, op, isPrefix) {
1082         return ["CountExpr", {isPrefix:isPrefix, op:op}, expr];
1083     },
1084     newExpression: function(callee, args) {
1085         args.unshift("NewExpr", {}, callee);
1086         return args;
1087     },
1088     callExpression: function(callee, args) {
1089         args.unshift(isDirectEval(callee) ? "EvalExpr" : "CallExpr", {}, callee);
1090         return args;
1091     },
1092     memberExpression: function(isComputed, expr, member) {
1093         return ["MemberExpr", {}, expr, isComputed ? member : ["LiteralExpr", {type: "string", value: member[1].name}]];
1094     },
1095     functionExpression: functionNode("FunctionExpr"),
1096     arrayExpression: function(elts) {
1097         for (var i = 0; i < elts.length; i++) {
1098             if (!elts[i])
1099                 elts[i] = ["Empty"];
1100         }
1101         elts.unshift("ArrayExpr", {});
1102         return elts;
1103     },
1104     objectExpression: function(props) {
1105         props.unshift("ObjectExpr", {});
1106         return props;
1107     },
1108     thisExpression: function() {
1109         return ["ThisExpr", {}];
1110     },
1111
1112     graphExpression: reject,
1113     graphIndexExpression: reject,
1114     comprehensionExpression: reject,
1115     generatorExpression: reject,
1116     yieldExpression: reject,
1117     letExpression: reject,
1118
1119     emptyStatement: function() ["EmptyStmt", {}],
1120     blockStatement: function(stmts) {
1121         stmts.unshift("BlockStmt", {});
1122         return stmts;
1123     },
1124     labeledStatement: function(lab, stmt) {
1125         return ["LabelledStmt", {label: lab}, stmt];
1126     },
1127     ifStatement: function(test, cons, alt) {
1128         return ["IfStmt", {}, test, cons, alt || ["EmptyStmt", {}]];
1129     },
1130     switchStatement: function(test, clauses, isLexical) {
1131         clauses.unshift("SwitchStmt", {}, test);
1132         return clauses;
1133     },
1134     whileStatement: function(expr, stmt) {
1135         return ["WhileStmt", {}, expr, stmt];
1136     },
1137     doWhileStatement: function(stmt, expr) {
1138         return ["DoWhileStmt", {}, stmt, expr];
1139     },
1140     forStatement: function(init, test, update, body) {
1141         return ["ForStmt", {}, init || ["Empty"], test || ["Empty"], update || ["Empty"], body];
1142     },
1143     forInStatement: function(lhs, rhs, body) {
1144         return ["ForInStmt", {}, lhs, rhs, body];
1145     },
1146     breakStatement: function(lab) {
1147         return lab ? ["BreakStmt", {}, lab] : ["BreakStmt", {}];
1148     },
1149     continueStatement: function(lab) {
1150         return lab ? ["ContinueStmt", {}, lab] : ["ContinueStmt", {}];
1151     },
1152     withStatement: function(expr, stmt) {
1153         return ["WithStmt", {}, expr, stmt];
1154     },
1155     returnStatement: function(expr) {
1156         return expr ? ["ReturnStmt", {}, expr] : ["ReturnStmt", {}];
1157     },
1158     tryStatement: function(body, catches, fin) {
1159         if (catches.length > 1)
1160             throw new SyntaxError("multiple catch clauses not supported");
1161         var node = ["TryStmt", body, catches[0] || ["Empty"]];
1162         if (fin)
1163             node.push(fin);
1164         return node;
1165     },
1166     throwStatement: function(expr) {
1167         return ["ThrowStmt", {}, expr];
1168     },
1169     debuggerStatement: function() ["DebuggerStmt", {}],
1170     letStatement: reject,
1171     switchCase: function(expr, stmts) {
1172         if (expr)
1173             stmts.unshift("SwitchCase", {}, expr);
1174         else
1175             stmts.unshift("DefaultCase", {});
1176         return stmts;
1177     },
1178     catchClause: function(param, guard, body) {
1179         if (guard)
1180             throw new SyntaxError("catch guards not supported");
1181         param[0] = "IdPatt";
1182         return ["CatchClause", {}, param, body];
1183     },
1184     comprehensionBlock: reject,
1185
1186     arrayPattern: reject,
1187     objectPattern: reject,
1188     propertyPattern: reject,
1189
1190     xmlAnyName: reject,
1191     xmlAttributeSelector: reject,
1192     xmlEscape: reject,
1193     xmlFilterExpression: reject,
1194     xmlDefaultDeclaration: reject,
1195     xmlQualifiedIdentifier: reject,
1196     xmlFunctionQualifiedIdentifier: reject,
1197     xmlElement: reject,
1198     xmlText: reject,
1199     xmlList: reject,
1200     xmlStartTag: reject,
1201     xmlEndTag: reject,
1202     xmlPointTag: reject,
1203     xmlName: reject,
1204     xmlAttribute: reject,
1205     xmlCdata: reject,
1206     xmlComment: reject,
1207     xmlProcessingInstruction: reject
1208 };
1209 })();
1210
1211 Pattern(["Program", {},
1212          ["BinaryExpr", {op: "+"},
1213           ["LiteralExpr", {value: 2}],
1214           ["BinaryExpr", {op: "*"},
1215            ["UnaryExpr", {op: "-"}, ["IdExpr", {name: "x"}]],
1216            ["IdExpr", {name: "y"}]]]]).match(Reflect.parse("2 + (-x * y)", {loc: false, builder: JsonMLAst}));
1217
1218 reportCompare(true, true);