Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 418 lines (373 sloc) 11.824 kB
fccc685 Initial open-source release
MLstate authored
1 (*
2 Copyright © 2011 MLstate
3
4 This file is part of OPA.
5
6 OPA is free software: you can redistribute it and/or modify it under the
7 terms of the GNU Affero General Public License, version 3, as published by
8 the Free Software Foundation.
9
10 OPA is distributed in the hope that it will be useful, but WITHOUT ANY
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
16 along with OPA. If not, see <http://www.gnu.org/licenses/>.
17 *)
18
19 (**
20 Javascript Complete Ast
21 @author Mathieu Barbin, adapted for OPA from ocamljs/jslib
22 *)
23
24 (**
25 location in source, and annotation
26 *)
27 type loc = Annot.label
28
29 (**
30 label used in statement
31 *)
32 type label = string
33
34 (**
35 Native identfiers:
36 They are used for:
37 -generated code
38 -parsed code from external js files
39
40 The parser build only {[Native (Local ident)]}, and code generator
41 as well.
42 There is a pass for transforming [Local] native to [Global] native,
43 so that these identifiers can be serialized, and renamed
44 since we clean the jsbsl.
45 *)
46 type native_ident = [ `global | `local ]
47
48 (**
49 Javascript Identifiers.
50 ExprIdent are classical identifier, from the compilation of qml code.
51 *)
52 type ident = JsIdent.t =
53 | ExprIdent of Ident.t
54 | Native of native_ident * string
55
56 (**
57 Unary operators
58 *)
59 type unop =
60 | Ju_delete (** {[ delete ]} *)
61 | Ju_void (** {[ void ]} *)
62 | Ju_typeof (** {[ typeof ]} *)
63 | Ju_add2_pre (** {[ ++x ]} *)
64 | Ju_sub2_pre (** {[ --x ]} *)
65 | Ju_add_pre (** {[ +x ]} *)
66 | Ju_sub_pre (** {[ -x ]} *)
67 | Ju_tilde (** {[ ~x ]} *)
68 | Ju_not (** {[ !x ]} *)
69 | Ju_add2_post (** {[ x++ ]} *)
70 | Ju_sub2_post (** {[ x-- ]} *)
71
72 (**
73 Binary operators
74 *)
75 type binop =
76 | Jb_hashref (** {[ x[y] ]} *)
77 | Jb_mul (** {[ * ]} *)
78 | Jb_div (** {[ / ]} *)
79 | Jb_mod (** {[ % ]} *)
80 | Jb_add (** {[ + ]} *)
81 | Jb_sub (** {[ - ]} *)
82 | Jb_lt (** {[ < ]} *)
83 | Jb_gt (** {[ > ]} *)
84 | Jb_leq (** {[ <= ]} *)
85 | Jb_geq (** {[ >= ]} *)
86 | Jb_lsr (** {[ >> ]} *)
87 | Jb_lsl (** {[ << ]} *)
88 | Jb_asr (** {[ >>> ]} *)
89 | Jb_eq (** {[ == ]} *)
90 | Jb_neq (** {[ != ]} *)
91 | Jb_in (** {[ in ]} *)
92 | Jb_instanceof (** {[ instanceof ]} *)
93 | Jb_seq (** {[ === ]} *)
94 | Jb_sneq (** {[ !== ]} *)
95 | Jb_land (** {[ && ]} *)
96 | Jb_lor (** {[ || ]} *)
97 | Jb_and (** {[ & ]} *)
98 | Jb_xor (** {[ ^ ]} *)
99 | Jb_or (** {[ | ]} *)
100 | Jb_assign (** {[ = ]} *)
101 | Jb_mul_assign (** {[ *= ]} *)
102 | Jb_div_assign (** {[ /= ]} *)
103 | Jb_mod_assign (** {[ %= ]} *)
104 | Jb_add_assign (** {[ += ]} *)
105 | Jb_sub_assign (** {[ -+ ]} *)
106 | Jb_lsl_assign (** {[ <<= ]} *)
107 | Jb_lsr_assign (** {[ >>= ]} *)
108 | Jb_asr_assign (** {[ >>>= ]} *)
109 | Jb_and_assign (** {[ &= ]} *)
110 | Jb_xor_assign (** {[ ^= ]} *)
111 | Jb_or_assign (** {[ |= ]} *)
112
113 (**
114 Expressions
115
116 GUIDELINES for matching expressions
117 {[
118 | J.Je_this _ ->
119 | J.Je_ident (_, ident) ->
120 | J.Je_array (_, list) ->
121 | J.Je_comma (_, list, last) ->
122 | J.Je_object (_, fields) ->
123 | J.Je_string (_, string, double_quote) ->
124 | J.Je_num (_, num) ->
125 | J.Je_null _ ->
126 | J.Je_undefined _ ->
127 | J.Je_bool (_, bool) ->
128 | J.Je_regexp (_, body, flags) ->
129 | J.Je_function (_, ident, params, body) ->
130 | J.Je_dot (_, expr, field) ->
131 | J.Je_unop (_, op, expr) ->
132 | J.Je_binop (_, op, expr1, expr2) ->
133 | J.Je_cond (_, cond, then_, else_) ->
134 | J.Je_call (_, fun_, args, _) ->
135 | J.Je_new (_, obj, args) ->
136 | J.Je_hole (_, qml) ->
137 ]}
138
139 *)
140 type expr =
141 | Je_this of loc
142 | Je_ident of loc * ident
143 | Je_array of loc * expr list
144 | Je_comma of loc * expr list * expr
145 | Je_object of loc * (string * expr) list
146 | Je_string of loc * string * bool
147 (**
148 true if double-quoted,
149 else simple-quoted
150 *)
151
152 | Je_num of loc * string
153 | Je_null of loc
154 | Je_undefined of loc
155 (**
156 <!> Beware, in js, [undefined] is not a keyword,
157 so, we assume it will not be redefined.
158 *)
159
160 | Je_bool of loc * bool
161 | Je_regexp of loc * string * string
162 | Je_function of loc * ident option * ident list * statement list
163 | Je_dot of loc * expr * string
164 | Je_unop of loc * unop * expr
165 | Je_binop of loc * binop * expr * expr
166 | Je_cond of loc * expr * expr * expr
167 | Je_call of loc * expr * expr list * bool
168 (**
169 Function call.
170 bool flag:
171 -true: pure;
172 -false: possible side effects
173 *)
174
175 | Je_new of loc * expr * expr list
176 | Je_hole of loc * QmlAst.expr
177 (**
178 Qml Hole, DynamicExpr computed on the server side
179 + cf hybrid values.
180 Resolved at runtime (initialization of the server)
181 Compilation of hybrid_value directive.
182 *)
183
184 | Je_runtime of loc * JsAstRuntime.expr
185 (**
186 This node allows to build expression of the runtime
187 ast directly
188 *)
189
190 (**
191 Statements.
192
193 GUIDELINES for matching statements
194 {[
195 | J.Js_var (_, ident, expr) ->
196 | J.Js_function (_, ident, params, body) ->
197 | J.Js_return (_, expr) ->
198 | J.Js_continue (_, label) ->
199 | J.Js_break (_, label) ->
200 | J.Js_switch (_, expr, cases, default) ->
201 | J.Js_if (_, cond, then_, else_) ->
202 | J.Js_throw (_, expr) ->
203 | J.Js_expr (_, expr) ->
204 | J.Js_trycatch (_, body, catches, finally) ->
205 | J.Js_for (_, init, cond, incr, body) ->
206 | J.Js_forin (_, lhs, rhs, body) ->
207 | J.Js_dowhile (_, body, cond) ->
208 | J.Js_while (_, cond, body) ->
209 | J.Js_block (_, body) ->
210 | J.Js_with (_, expr, body) ->
211 | J.Js_label (_, label, stmt) ->
212 | J.Js_comment (_, kind, string) ->
213 ]}
214
215 *)
216 and statement =
217 | Js_var of loc * ident * expr option
218 (**
219 Please be careful because [var x = undefined]
220 and [var x] is not the same
221 Think about [x = 1; var x] and [x = 1; var x = undefined]
222
223 The printer will regroup successive variable definitions,
224 except in the toplevel.
225 {[
226 function foo() {
227 var x = 5, y, z;
228 }
229 ]}
230 *)
231
232 | Js_function of loc * ident * ident list * statement list
233 | Js_return of loc * expr option
234 | Js_continue of loc * label option
235 | Js_break of loc * label option
236 | Js_switch of loc * expr * (expr * statement) list * statement option
237 | Js_if of loc * expr * statement * statement option
238 | Js_throw of loc * expr
239 | Js_expr of loc * expr
240 | Js_trycatch of loc * statement
241 * (ident * expr option * statement) list
242 * statement option
243 | Js_for of loc * expr option * expr option * expr option * statement
244 | Js_forin of loc * expr * expr * statement
245 | Js_dowhile of loc * statement * expr
246 | Js_while of loc * expr * statement
247 | Js_block of loc * statement list
248 | Js_with of loc * expr * statement
249 | Js_label of loc * string * statement
250 | Js_comment of loc * [ `doc | `simple | `one_line ] * string
251
252 (**
253 A code element is simply a statement
254 *)
255 type code_elt = statement
256
257 (**
258 Code
259 *)
260 type code = code_elt list
261
262
263 let is_assignment_unop = function
264 | Ju_add2_pre (** {[ ++x ]} *)
265 | Ju_sub2_pre (** {[ --x ]} *)
266 | Ju_add2_post (** {[ x++ ]} *)
267 | Ju_sub2_post (** {[ x-- ]} *)
268 -> true
269 | Ju_delete (** {[ delete ]} *)
270 | Ju_void (** {[ void ]} *)
271 | Ju_typeof (** {[ typeof ]} *)
272 | Ju_add_pre (** {[ +x ]} *)
273 | Ju_sub_pre (** {[ -x ]} *)
274 | Ju_tilde (** {[ ~x ]} *)
275 | Ju_not (** {[ !x ]} *)
276 -> false
277
278 (**
279 Tell if a unary operator makes a side effect
280 *)
281 let is_side_effect_unop = function
282 | Ju_delete (** {[ delete ]} *)
283 | Ju_add2_pre (** {[ ++x ]} *)
284 | Ju_sub2_pre (** {[ --x ]} *)
285 | Ju_add2_post (** {[ x++ ]} *)
286 | Ju_sub2_post (** {[ x-- ]} *)
287 -> true
288
289 | Ju_void (** {[ void ]} *)
290 | Ju_typeof (** {[ typeof ]} *)
291 | Ju_add_pre (** {[ +x ]} *)
292 | Ju_sub_pre (** {[ -x ]} *)
293 | Ju_tilde (** {[ ~x ]} *)
294 | Ju_not (** {[ !x ]} *)
295 -> false
296
297 let is_assignment_binop = function
298 | Jb_hashref (** {[ x[y] ]} *)
299 | Jb_mul (** {[ * ]} *)
300 | Jb_div (** {[ / ]} *)
301 | Jb_mod (** {[ % ]} *)
302 | Jb_add (** {[ + ]} *)
303 | Jb_sub (** {[ - ]} *)
304 | Jb_lt (** {[ < ]} *)
305 | Jb_gt (** {[ > ]} *)
306 | Jb_leq (** {[ <= ]} *)
307 | Jb_geq (** {[ >= ]} *)
308 | Jb_lsr (** {[ >> ]} *)
309 | Jb_lsl (** {[ << ]} *)
310 | Jb_asr (** {[ >>> ]} *)
311 | Jb_eq (** {[ == ]} *)
312 | Jb_neq (** {[ != ]} *)
313 | Jb_in (** {[ in ]} *)
314 | Jb_instanceof (** {[ instanceof ]} *)
315 | Jb_seq (** {[ === ]} *)
316 | Jb_sneq (** {[ !== ]} *)
317 | Jb_land (** {[ && ]} *)
318 | Jb_lor (** {[ || ]} *)
319 | Jb_and (** {[ & ]} *)
320 | Jb_xor (** {[ ^ ]} *)
321 | Jb_or (** {[ | ]} *)
322 -> false
323 | Jb_assign (** {[ = ]} *)
324 | Jb_mul_assign (** {[ *= ]} *)
325 | Jb_div_assign (** {[ /= ]} *)
326 | Jb_mod_assign (** {[ %= ]} *)
327 | Jb_add_assign (** {[ += ]} *)
328 | Jb_sub_assign (** {[ -+ ]} *)
329 | Jb_lsl_assign (** {[ <<= ]} *)
330 | Jb_lsr_assign (** {[ >>= ]} *)
331 | Jb_asr_assign (** {[ >>>= ]} *)
332 | Jb_and_assign (** {[ &= ]} *)
333 | Jb_xor_assign (** {[ ^= ]} *)
334 | Jb_or_assign (** {[ |= ]} *)
335 -> true
336
337 (**
338 Tell if a binary operator makes a side effect
339 *)
340 let is_side_effect_binop = is_assignment_binop
341
342
343
344 (**
345 Tell if a string is a reserved javascript keyword.
346 list from http://www.georgehernandez.com/h/xComputers/Cs/ReservedKeywords.asp
347 *)
348 let is_keyword id =
349 match id with
350 | "abstract"
351 | "boolean" | "break" | "byte"
352 | "case" | "catch" | "char" | "class" | "const" | "continue"
353 | "debugger" | "default" | "delete" | "do" | "double"
354 | "else" | "enum" | "export" | "extends"
355 | "false" | "final" | "finally" | "float" | "for" | "function"
356 | "goto"
357 | "if" | "implements" | "import" | "in" | "instanceof" | "int" | "interface"
358 | "long"
359 | "native" | "new" | "null"
360 | "package" | "private" | "protected" | "public"
361 | "return"
362 | "short" | "static" | "super" | "switch" | "synchronized"
363 | "this" | "throw" | "throws" | "transient" | "true" | "try" | "typeof"
364
365 | "undefined"
366 (*
367 Although this is not a keyword, the printer use it,
368 so this should not be redefined.
369 *)
370
371 | "var" | "void" | "volatile"
372 | "while" | "with" -> true
373 | _ -> false
374
375 let (|>) = InfixOperator.(|>)
376
377 type runtime_error =
378 | Match_failure of string
379
380 module TTIdent =
381 struct
382 type t = ident
383 let compare = compare
384 end
385
386 module IdentMap = BaseMap.Make(TTIdent)
387 module IdentSet = BaseSet.Make(TTIdent)
388
389 module JLabel :
390 sig
391 val stm : statement -> Annot.label
392 val expr : expr -> Annot.label
393 end =
394 struct
395 let stm = Annot.Magic.label
396 let expr = Annot.Magic.label
397 end
398
399 module JPos :
400 sig
401 val stm : statement -> FilePos.pos
402 val expr : expr -> FilePos.pos
403 end =
404 struct
405 let stm = Annot.Magic.pos
406 let expr = Annot.Magic.pos
407 end
408
409 module JNewAnnot :
410 sig
411 val stm : statement -> Annot.t -> statement
412 val expr : expr -> Annot.t -> expr
413 end =
414 struct
415 let stm = Annot.Magic.new_annot
416 let expr = Annot.Magic.new_annot
417 end
Something went wrong with that request. Please try again.