Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 544 lines (503 sloc) 20.253 kb
fccc685 Initial open-source release
MLstate authored
1 (*
2 Copyright © 2011 MLstate
3
5bb0f1a @Aqua-Ye [cleanup] compiler: typo on Opa
Aqua-Ye authored
4 This file is part of Opa.
fccc685 Initial open-source release
MLstate authored
5
5bb0f1a @Aqua-Ye [cleanup] compiler: typo on Opa
Aqua-Ye authored
6 Opa is free software: you can redistribute it and/or modify it under the
fccc685 Initial open-source release
MLstate authored
7 terms of the GNU Affero General Public License, version 3, as published by
8 the Free Software Foundation.
9
5bb0f1a @Aqua-Ye [cleanup] compiler: typo on Opa
Aqua-Ye authored
10 Opa is distributed in the hope that it will be useful, but WITHOUT ANY
fccc685 Initial open-source release
MLstate authored
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
13 more details.
14
15 You should have received a copy of the GNU Affero General Public License
5bb0f1a @Aqua-Ye [cleanup] compiler: typo on Opa
Aqua-Ye authored
16 along with Opa. If not, see <http://www.gnu.org/licenses/>.
fccc685 Initial open-source release
MLstate authored
17 *)
18 module J = JsAst
19 module List = Base.List
20
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
21 (*
22 * these functions flatten nested blocks and removes empty blocks
23 *)
24
fccc685 Initial open-source release
MLstate authored
25 let rec clean_block_stm acc stm =
26 match stm with
27 | J.Js_block (_,body) -> clean_block_stms acc body
28 | J.Js_function (label, name, params, statements) ->
29 let statements = clean_block_stms_no_acc statements in
30 J.Js_function (label, name, params, statements) :: acc
31 | _ ->
32 let stm = JsWalk.OnlyStatement.map_nonrec clean_block_stm_no_acc stm in
33 stm :: acc
34
35 and clean_block_stm_no_acc stm =
36 match clean_block_stms_no_acc [stm] with
37 | [stm] -> stm
38 | l -> JsCons.Statement.block l
39 and clean_block_stms acc stms =
40 List.fold_left clean_block_stm acc stms
41 and clean_block_stms_no_acc stms =
42 List.rev (clean_block_stms [] stms)
43
44 (* beware: it doesn't clean statements inside expressions *)
45 let clean_block_stm = clean_block_stm_no_acc
46 let clean_block = clean_block_stms_no_acc
47
48 (* check if you always leave a block with a return
49 * (in a very conservative way) *)
50 let rec always_return = function
51 | J.Js_return _ -> true
52 | J.Js_block (_,stms) -> always_return_stms stms
53 | J.Js_if (_,_,s,o) -> always_return s && Option.default_map false always_return o
54 | _ -> false
55 and always_return_stms stms =
56 List.exists always_return stms
57
58 let compare_label = String.compare
59
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
60 exception ComparisonFailure
61
62 (* cannot use the generic equality because you have annotation
63 * and positions everywhere in the ast
64 * can raise ComparisonFailure when the comparison is not implemented
65 * (this case probably never happens because it happens only on
66 * generated code and not on hand written javascript) *)
fccc685 Initial open-source release
MLstate authored
67 let rec compare_expr e1 e2 =
68 match e1, e2 with
69 | J.Je_this _, J.Je_this _ -> 0
70 | J.Je_this _, _ -> -1
71 | _, J.Je_this _ -> 1
72 | J.Je_ident (_,ident1), J.Je_ident (_,ident2) ->
73 JsIdent.compare ident1 ident2
74 | J.Je_ident _, _ -> -1
75 | _, J.Je_ident _ -> 1
76 | J.Je_array (_,el1), J.Je_array (_,el2) ->
77 List.make_compare compare_expr el1 el2
78 | J.Je_array _, _ -> -1
79 | _, J.Je_array _ -> 1
80 | J.Je_comma (_,el1,e1), J.Je_comma (_,el2,e2) -> (
81 match List.make_compare compare_expr el1 el2 with
82 | 0 -> compare_expr e1 e2
83 | c -> c
84 )
85 | J.Je_comma _, _ -> -1
86 | _, J.Je_comma _ -> 1
87 | J.Je_object (_,sel1), J.Je_object (_,sel2) ->
88 List.make_compare (* could sort the fields *)
89 (fun (s1,e1) (s2,e2) ->
90 match String.compare s1 s2 with
91 | 0 -> compare_expr e1 e2
92 | c -> c
93 ) sel1 sel2
94 | J.Je_object _, _ -> -1
95 | _, J.Je_object _ -> 1
96 | J.Je_string (_,s1,_), J.Je_string (_,s2,_) -> String.compare s1 s2
97 | J.Je_string _, _ -> -1
98 | _, J.Je_string _ -> 1
99 | J.Je_num (_,s1), J.Je_num (_,s2) -> String.compare s1 s2 (* could normalize before comparing *)
100 | J.Je_num _, _ -> -1
101 | _, J.Je_num _ -> 1
102 | J.Je_null _, J.Je_null _ -> 0
103 | J.Je_null _, _ -> -1
104 | _, J.Je_null _ -> 1
105 | J.Je_undefined _, J.Je_undefined _ -> 0
106 | J.Je_undefined _, _ -> -1
107 | _, J.Je_undefined _ -> 1
108 | J.Je_bool (_,b1), J.Je_bool (_,b2) -> Pervasives.compare b1 b2
109 | J.Je_bool _, _ -> -1
110 | _, J.Je_bool _ -> 1
111 | J.Je_regexp (_,l1,r1), J.Je_regexp (_,l2,r2) -> (
112 match String.compare l1 l2 with
113 | 0 -> String.compare r1 r2
114 | c -> c
115 )
116 | J.Je_regexp _, _ -> -1
117 | _, J.Je_regexp _ -> 1
118 | J.Je_function (_,name1,params1,body1), J.Je_function (_,name2,params2,body2) -> (
119 match Option.make_compare JsIdent.compare name1 name2 with
120 | 0 -> (
121 match List.make_compare JsIdent.compare params1 params2 with
122 | 0 -> List.make_compare compare_stm body1 body2
123 | c -> c
124 )
125 | c -> c
126 )
127 | J.Je_function _, _ -> -1
128 | _, J.Je_function _ -> 1
129 | J.Je_dot (_,e1,s1), J.Je_dot (_,e2,s2) -> (
130 match compare_expr e1 e2 with
131 | 0 -> String.compare s1 s2
132 | c -> c
133 )
134 | J.Je_dot _, _ -> -1
135 | _, J.Je_dot _ -> 1
136 | J.Je_unop (_,op1,e1), J.Je_unop (_,op2,e2) -> (
137 match Pervasives.compare op1 op2 with
138 | 0 -> compare_expr e1 e2
139 | c -> c
140 )
141 | J.Je_unop _, _ -> -1
142 | _, J.Je_unop _ -> 1
143 | J.Je_binop (_,op1,l1,r1), J.Je_binop (_,op2,l2,r2) -> (
144 match Pervasives.compare op1 op2 with
145 | 0 -> (
146 match compare_expr l1 l2 with
147 | 0 -> compare_expr r1 r2
148 | c -> c
149 )
150 | c -> c
151 )
152 | J.Je_binop _, _ -> -1
153 | _, J.Je_binop _ -> 1
154 | J.Je_cond (_,t1,l1,r1), J.Je_cond (_,t2,l2,r2) -> (
155 match compare_expr t1 t2 with
156 | 0 -> (
157 match compare_expr l1 l2 with
158 | 0 -> compare_expr r1 r2
159 | c -> c
160 )
161 | c -> c
162 )
163 | J.Je_cond _, _ -> -1
164 | _, J.Je_cond _ -> 1
165 | J.Je_call (_,e1,el1,_), J.Je_call (_,e2,el2,_) -> (
166 match compare_expr e1 e2 with
167 | 0 -> List.make_compare compare_expr el1 el2
168 | c -> c
169 )
170 | J.Je_call _, _ -> -1
171 | _, J.Je_call _ -> 1
172 | J.Je_new (_,e1,el1), J.Je_new (_,e2,el2) -> (
173 match compare_expr e1 e2 with
174 | 0 -> List.make_compare compare_expr el1 el2
175 | c -> c
176 )
177 | J.Je_new _, _ -> -1
178 | _, J.Je_new _ -> 1
179
180 | J.Je_runtime (_, e1), J.Je_runtime (_, e2) ->
181 JsAstRuntime.compare e1 e2
182 | J.Je_runtime _, _ -> -1
183 | _, J.Je_runtime _ -> 1
184
185 | J.Je_hole _, J.Je_hole _ ->
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
186 raise ComparisonFailure
fccc685 Initial open-source release
MLstate authored
187
188 and compare_stm s1 s2 =
189 match s1, s2 with
190 | J.Js_var (_,i1,o1), J.Js_var (_,i2,o2) -> (
191 match JsIdent.compare i1 i2 with
192 | 0 -> Option.make_compare compare_expr o1 o2
193 | c -> c
194 )
195 | J.Js_var _, _ -> -1
196 | _, J.Js_var _ -> 1
197 | J.Js_function (_,name1,params1,body1), J.Js_function (_,name2,params2,body2) -> (
198 match JsIdent.compare name1 name2 with
199 | 0 -> (
200 match List.make_compare JsIdent.compare params1 params2 with
201 | 0 -> List.make_compare compare_stm body1 body2
202 | c -> c
203 )
204 | c -> c
205 )
206 | J.Js_function _, _ -> -1
207 | _, J.Js_function _ -> 1
208 | J.Js_return (_,o1), J.Js_return (_,o2) ->
209 Option.make_compare compare_expr o1 o2
210 | J.Js_return _, _ -> -1
211 | _, J.Js_return _ -> 1
212 | J.Js_continue (_,o1), J.Js_continue (_,o2) ->
213 Option.make_compare compare_label o1 o2
214 | J.Js_continue _, _ -> -1
215 | _, J.Js_continue _ -> 1
216 | J.Js_break (_,o1), J.Js_break (_,o2) ->
217 Option.make_compare compare_label o1 o2
218 | J.Js_break _, _ -> -1
219 | _, J.Js_break _ -> 1
220 | J.Js_switch (_,e1,esl1,o1), J.Js_switch (_,e2,esl2,o2) -> (
221 match compare_expr e1 e2 with
222 | 0 -> (
223 match List.make_compare
224 (fun (e1,s1) (e2,s2) ->
225 match compare_expr e1 e2 with
226 | 0 -> compare_stm s1 s2
227 | c -> c
228 ) esl1 esl2 with
229 | 0 -> Option.make_compare compare_stm o1 o2
230 | c -> c
231 )
232 | c -> c
233 )
234 | J.Js_switch _, _ -> -1
235 | _, J.Js_switch _ -> 1
236 | J.Js_if (_,e1,t1,o1), J.Js_if (_,e2,t2,o2) -> (
237 match compare_expr e1 e2 with
238 | 0 -> (
239 match compare_stm t1 t2 with
240 | 0 -> Option.make_compare compare_stm o1 o2
241 | c -> c
242 )
243 | c -> c
244 )
245 | J.Js_if _, _ -> -1
246 | _, J.Js_if _ -> 1
247 | J.Js_throw (_,e1), J.Js_throw (_,e2) ->
248 compare_expr e1 e2
249 | J.Js_throw _, _ -> -1
250 | _, J.Js_throw _ -> 1
251 | J.Js_expr (_,e1), J.Js_expr (_,e2) ->
252 compare_expr e1 e2
253 | J.Js_expr _, _ -> -1
254 | _, J.Js_expr _ -> 1
255 | J.Js_trycatch (_,s1,iosl1,o1), J.Js_trycatch (_,s2,iosl2,o2) -> (
256 match compare_stm s1 s2 with
257 | 0 -> (
258 match List.make_compare
259 (fun (i1,o1,s1) (i2,o2,s2) ->
260 match JsIdent.compare i1 i2 with
261 | 0 -> (
262 match Option.make_compare compare_expr o1 o2 with
263 | 0 -> compare_stm s1 s2
264 | c -> c
265 )
266 | c -> c
267 ) iosl1 iosl2 with
268 | 0 -> Option.make_compare compare_stm o1 o2
269 | c -> c
270 )
271 | c -> c
272 )
273 | J.Js_trycatch _, _ -> -1
274 | _, J.Js_trycatch _ -> 1
275 | J.Js_for (_,l1,l2,l3,s1), J.Js_for (_,r1,r2,r3,s2) -> (
276 match Option.make_compare compare_expr l1 r1 with
277 | 0 -> (
278 match Option.make_compare compare_expr l2 r2 with
279 | 0 -> (
280 match Option.make_compare compare_expr l3 r3 with
281 | 0 -> compare_stm s1 s2
282 | c -> c
283 )
284 | c -> c
285 )
286 | c -> c
287 )
288 | J.Js_for _, _ -> -1
289 | _, J.Js_for _ -> 1
290 | J.Js_forin (_,i1,e1,s1), J.Js_forin (_,i2,e2,s2) -> (
291 match compare_expr i1 i2 with
292 | 0 -> (
293 match compare_expr e1 e2 with
294 | 0 -> compare_stm s1 s2
295 | c -> c
296 )
297 | c -> c
298 )
299 | J.Js_forin _, _ -> -1
300 | _, J.Js_forin _ -> 1
301 | J.Js_dowhile (_,s1,e1), J.Js_dowhile (_,s2,e2) -> (
302 match compare_stm s1 s2 with
303 | 0 -> compare_expr e1 e2
304 | c -> c
305 )
306 | J.Js_dowhile _, _ -> -1
307 | _, J.Js_dowhile _ -> 1
308 | J.Js_while (_,e1,s1), J.Js_while (_,e2,s2) -> (
309 match compare_expr e1 e2 with
310 | 0 -> compare_stm s1 s2
311 | c -> c
312 )
313 | J.Js_while _, _ -> -1
314 | _, J.Js_while _ -> 1
315 | J.Js_block (_,sl1), J.Js_block (_,sl2) ->
316 List.make_compare compare_stm sl1 sl2
317 | J.Js_block _, _ -> -1
318 | _, J.Js_block _ -> 1
319 | J.Js_with (_,e1,s1), J.Js_with (_,e2,s2) ->(
320 match compare_expr e1 e2 with
321 | 0 -> compare_stm s1 s2
322 | c -> c
323 )
324 | J.Js_with _, _ -> -1
325 | _, J.Js_with _ -> 1
326 | J.Js_label (_,l1,s1), J.Js_label (_,l2,s2) -> (
327 match compare_label l1 l2 with
328 | 0 -> compare_stm s1 s2
329 | c -> c
330 )
331 | J.Js_label _, _ -> -1
332 | _, J.Js_label _ -> 1
668cdfe @arthuraa [enhance] jsast: add empty statement node.
arthuraa authored
333 | J.Js_empty _, _ -> -1
334 | _, J.Js_empty _ -> 1
fccc685 Initial open-source release
MLstate authored
335 | J.Js_comment _, J.Js_comment _ -> 0
336
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
337 (* a simple peep hole pass
338 * this rewriting does not (always) reach a fixpoint *)
fccc685 Initial open-source release
MLstate authored
339 let clean_assign ~use_shortcut_assignment stm =
340 JsWalk.TStatement.map_up
341 (fun s ->
342 match s with
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
343
fccc685 Initial open-source release
MLstate authored
344 | J.Js_expr (_,e) when not (Imp_Common.does_side_effects e) ->
345 JsCons.Statement.block []
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
346
fccc685 Initial open-source release
MLstate authored
347 | J.Js_if (label,J.Je_unop(_,J.Ju_not,e),s1,Some s2) ->
348 (* if (!e) s1 s2 -> if (e) s2 s1 *)
349 J.Js_if (label, e, s2, Some s1)
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
350
fccc685 Initial open-source release
MLstate authored
351 | J.Js_if (_, J.Je_unop (_,J.Ju_not,e1),J.Js_expr (_,e2),None) ->
352 (* if (!e1) { e2 } -> e1 || e2 *)
353 JsCons.Statement.expr (JsCons.Expr.lor_ e1 e2)
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
354
fccc685 Initial open-source release
MLstate authored
355 | J.Js_if (_, e1,J.Js_expr (_,e2),None) ->
356 (* if (e1) { e2 } -> e1 && e2 *)
357 JsCons.Statement.expr (JsCons.Expr.land_ e1 e2)
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
358
359 | J.Js_if (_, e1,J.Js_expr (_,J.Je_binop (_, J.Jb_assign, assign1, value1)),Some J.Js_expr (_,J.Je_binop (_, J.Jb_assign, assign2, value2))) when try compare_expr assign1 assign2 = 0 with ComparisonFailure -> false ->
fccc685 Initial open-source release
MLstate authored
360 (* if (e1) { assign = value1 } else { assign = value2 } -> assign = e1 ? value1 : value2 *)
361 JsCons.Statement.expr (JsCons.Expr.assign assign1 (JsCons.Expr.cond e1 value1 value2))
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
362
fccc685 Initial open-source release
MLstate authored
363 | J.Js_if (_, e1,J.Js_expr (_,e2), Some J.Js_expr (_,e3)) ->
364 (* if (e1) { e2 } else { e3 } -> e1 ? e2 : e3 *)
365 JsCons.Statement.expr (JsCons.Expr.cond e1 e2 e3)
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
366
fccc685 Initial open-source release
MLstate authored
367 | J.Js_if (label1, e1, J.Js_return (label2,Some e2), Some s2) -> (
368 match s2 with
369 | J.Js_comment _
370 | J.Js_block (_,[])
371 | J.Js_block (_,[J.Js_comment _]) ->
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
372 (* if (e1) { return e2 } else { /* comments */ } -> if (e1) { return e2 } *)
373 (* useful because of comments introduced on tail calls
374 * (that may break other rewritings) *)
fccc685 Initial open-source release
MLstate authored
375 J.Js_if (label1, e1, J.Js_return (label2,Some e2), None)
376 | J.Js_block (_,[J.Js_return (_,Some e3)])
377 | J.Js_return (_,Some e3) ->
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
378 (* if (e1) { return e2 } else { return e3 } -> return (e1 ? e2 : e3) *)
fccc685 Initial open-source release
MLstate authored
379 J.Js_return (label1, Some (J.Je_cond (label2, e1, e2, e3)))
380 | _ -> s
381 )
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
382
fccc685 Initial open-source release
MLstate authored
383 | J.Js_while (label, J.Je_bool (label2,true), s) ->
384 let s = clean_block_stm s in
385 (match s with
386 | J.Js_if (_,e, s1, Some s2) when always_return s2 ->
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
387 (* while (true) { if (e) { s1 } else { statement_that_returns }} ->
388 while (e) { s1 }; statement_that_returns *)
fccc685 Initial open-source release
MLstate authored
389 JsCons.Statement.block [J.Js_while (label, e, s1); s2]
390 | J.Js_if (_,e, s1, Some s2) when always_return s1 ->
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
391 (* while (true) { if (e) { statement_that_returns } else { s2 }} ->
392 while (!e) { s2 }; statement_that_returns *)
fccc685 Initial open-source release
MLstate authored
393 JsCons.Statement.block [J.Js_while (label, JsCons.Expr.unop J.Ju_not e, s2); s1]
394 | s -> J.Js_while (label, J.Je_bool (label2,true), s))
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
395
fccc685 Initial open-source release
MLstate authored
396 | _ -> s
397 )
398 (fun e ->
399 match e with
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
400
fccc685 Initial open-source release
MLstate authored
401 | J.Je_unop (_,J.Ju_not,J.Je_binop (label,op,e1,e2)) -> (
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
402 (* !(e1 < e2) -> e1 >= e2
403 * !(e1 == e2) -> e1 != e2 etc.
404 * CHECK: this is probably not working with NaN *)
fccc685 Initial open-source release
MLstate authored
405 match op with
406 | J.Jb_lt -> J.Je_binop (label, J.Jb_geq, e1, e2)
407 | J.Jb_gt -> J.Je_binop (label, J.Jb_leq, e1, e2)
408 | J.Jb_leq -> J.Je_binop (label, J.Jb_gt, e1, e2)
409 | J.Jb_geq -> J.Je_binop (label, J.Jb_lt, e1, e2)
410 | J.Jb_eq -> J.Je_binop (label, J.Jb_neq, e1, e2)
411 | J.Jb_neq -> J.Je_binop (label, J.Jb_eq, e1, e2)
412 | J.Jb_seq -> J.Je_binop (label, J.Jb_sneq, e1, e2)
413 | J.Jb_sneq -> J.Je_binop (label, J.Jb_seq, e1, e2)
414 | _ -> e
415 )
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
416
fccc685 Initial open-source release
MLstate authored
417 | J.Je_binop (label, J.Jb_assign, (J.Je_ident (_,i) as ident),
418 (J.Je_binop (_,op,e1,(J.Je_ident(_,j) as right))
419 |J.Je_binop (_,op,J.Je_ident (_,j), (e1 as right)))) when use_shortcut_assignment && JsIdent.equal i j -> (
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
420 (* i = e1 op i | i = i op e1
421 * i = i + a -> i += a
422 * i = i + 1 -> i += 1 // this one is actually not true
423 * // when i is a string
424 * // but it doesn't happen on generated code
425 * // and, seriously, who would do that in hand written code??
426 * etc. *)
fccc685 Initial open-source release
MLstate authored
427 match op, e1, e1 == right with
428 | J.Jb_add, J.Je_num (_,("1"|"1.")), _ (* now, that's just dirty *) -> J.Je_unop (label, J.Ju_add2_post, ident)
429 | J.Jb_sub, J.Je_num (_,("1"|"1.")), _ -> J.Je_unop (label, J.Ju_sub2_post, ident)
430 | J.Jb_mul, _, _ -> J.Je_binop (label, J.Jb_mul_assign, ident, e1)
431 | J.Jb_div, _, true -> J.Je_binop (label, J.Jb_div_assign, ident, e1)
432 | J.Jb_mod, _, true -> J.Je_binop (label, J.Jb_mod_assign, ident, e1)
433 | J.Jb_add, _, true (* BEWARE: addition is not commutative in js
434 * because it is also string concatenation *)
435 -> J.Je_binop (label, J.Jb_add_assign, ident, e1)
436 | J.Jb_sub, _, true -> J.Je_binop (label, J.Jb_sub_assign, ident, e1)
437 | J.Jb_lsl, _, true -> J.Je_binop (label, J.Jb_lsl_assign, ident, e1)
438 | J.Jb_lsr, _, true -> J.Je_binop (label, J.Jb_lsr_assign, ident, e1)
439 | J.Jb_asr, _, true -> J.Je_binop (label, J.Jb_asr_assign, ident, e1)
440 | J.Jb_and, _, _ -> J.Je_binop (label, J.Jb_and_assign, ident, e1)
441 | J.Jb_xor, _, _ -> J.Je_binop (label, J.Jb_xor_assign, ident, e1)
442 | J.Jb_or, _, _ -> J.Je_binop (label, J.Jb_or_assign, ident, e1)
443 | _ -> e
444 )
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
445
fccc685 Initial open-source release
MLstate authored
446 | J.Je_binop (label,op,J.Je_num (_,i1),J.Je_num (_,i2)) -> (
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
447 (* constant folding
448 * the operations in here should be checked to see
449 * if their behaviour in caml in the same as the one in js
450 * (with overflows, it is very unclear, although the behaviour
451 * of overflows in opa is unclear in the first place) *)
fccc685 Initial open-source release
MLstate authored
452 try
453 let i1 = float_of_string i1 in
454 let i2 = float_of_string i2 in
455 let f = JsCons.Expr.float ~label in
456 let b = JsCons.Expr.bool ~label in
457 match op with
458 | J.Jb_mul -> f (i1 *. i2)
459 | J.Jb_div -> f (i1 /. i2)
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
460 (*| J.Jb_mod -> f (i1 % i2) TODO *)
fccc685 Initial open-source release
MLstate authored
461 | J.Jb_add -> f (i1 +. i2)
462 | J.Jb_sub -> f (i1 -. i2)
463 | J.Jb_lt -> b (i1 < i2)
464 | J.Jb_gt -> b (i1 > i2)
465 | J.Jb_leq -> b (i1 <= i2)
466 | J.Jb_geq -> b (i1 >= i2)
467 (*| J.Jb_lsr -> f (i1 lsr i2)
468 | J.Jb_lsl -> f (i1 lsl i2)
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
469 | J.Jb_asr -> f (l1 asr i2) TODO *)
fccc685 Initial open-source release
MLstate authored
470 | J.Jb_eq -> b (i1 = i2)
471 | J.Jb_neq -> b (i1 <> i2)
472 | J.Jb_land -> f (if i1 <> 0. then i2 else i1)
473 | J.Jb_lor -> f (if i1 <> 0. then i1 else i2)
474 (*| J.Jb_and -> f (i1 & i2)*)
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
475 (*| J.Jb_xor -> i1 *)
476 (*| J.Jb_or -> f (i1 | i2)*) (* TODO *)
fccc685 Initial open-source release
MLstate authored
477 | _ -> e
478 with Failure "float_of_string" ->
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
479 (* can happen with "NaN" for instance *)
fccc685 Initial open-source release
MLstate authored
480 e
481 )
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
482
fccc685 Initial open-source release
MLstate authored
483 | J.Je_binop(label,J.Jb_add,J.Je_string (_,"",style),J.Je_num (_,s)) -> (
484 try
485 (* "" + 0x321 doesn't give "0x321", we need to do some kind of normalization
486 * to convert an int to a string
487 * checking that int_of_string works is a weak attempt to do that *)
488 ignore (int_of_string s);
489 J.Je_string (label,s,style)
490 with Failure "int_of_string" -> e
491 )
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
492
fccc685 Initial open-source release
MLstate authored
493 | J.Je_binop(label,J.Jb_add,J.Je_string (_,s1,style),J.Je_string (_,s2,_)) ->
494 (* FIXME: need to normalize the ast: "a" + ("b" + c) won't be seen
495 * but BEWARE: addition is commutative (on numbers) but not associative in js
496 * (1+(2+"a") -> "12a" vs (1+2)+"a") -> "3a" *)
497 J.Je_string (label,s1^s2,style)
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
498
fccc685 Initial open-source release
MLstate authored
499 | J.Je_cond (label,a,J.Je_bool (_,false), J.Je_bool (_,true)) ->
500 (* a ? false : true -> !a is valid, but a ? true : false -> a is not valid
501 * because a may not be a boolean: [function list_empty(l) { return l.nil ? true : false }] *)
502 JsCons.Expr.not_ ~label a
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
503
fccc685 Initial open-source release
MLstate authored
504 | J.Je_binop (_, J.Jb_assign, (J.Je_ident (_,i) as e), J.Je_ident (_,j)) when JsIdent.equal i j ->
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
505 (* i = i -> i *)
fccc685 Initial open-source release
MLstate authored
506 e
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
507
fccc685 Initial open-source release
MLstate authored
508 | J.Je_cond (_,J.Je_bool (_,b), e1, e2) ->
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
509 (* true ? e1 : e2 -> e1
510 * false ? e1 : e2 -> e2 *)
fccc685 Initial open-source release
MLstate authored
511 if b then e1 else e2
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
512
fccc685 Initial open-source release
MLstate authored
513 | J.Je_cond (label,J.Je_unop(_,J.Ju_not,e), e1, e2) ->
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
514 (* !e ? e1 : e2 -> e ? e2 : e1 *)
fccc685 Initial open-source release
MLstate authored
515 J.Je_cond (label, e, e2, e1)
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
516
fccc685 Initial open-source release
MLstate authored
517 | J.Je_comma (label,el,e) ->
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
518 (* (side_effect_free_expr, e) -> e *)
fccc685 Initial open-source release
MLstate authored
519 let el = List.filter Imp_Common.does_side_effects el in
520 if el = [] then e else J.Je_comma (label,el,e)
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
521
fccc685 Initial open-source release
MLstate authored
522 | J.Je_function (label,name_opt,params,body) ->
523 let body = clean_block body in
524 J.Je_function (label,name_opt,params,body)
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
525
fccc685 Initial open-source release
MLstate authored
526 | J.Je_call (_, J.Je_function (_, None, [], [J.Js_return (_,Some e)]), [], _) ->
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
527 (* function() { return e }() -> e *)
fccc685 Initial open-source release
MLstate authored
528 e
f2ce0c4 [doc] qmljsimp: adding, removing, updating comments
Valentin Gatien-Baron authored
529
fccc685 Initial open-source release
MLstate authored
530 | _ -> e
531 ) stm
532
533 let clean_stm ~use_shortcut_assignment stm =
534 let stm = clean_assign ~use_shortcut_assignment stm in
535 let code = clean_block [stm] in
536 code
537
538 let clean ~use_shortcut_assignment code =
539 (* clean assign generates empty blocks
540 * so it better to clean blocks after *)
541 let code = List.map (clean_assign ~use_shortcut_assignment) code in
542 let code = clean_block code in
543 code
Something went wrong with that request. Please try again.