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