Introduce new parser token PU_identifier
[hiphop-php.git] / hphp / hack / src / naming / ast_to_nast.ml
blobbde6e71cfec4060931c870ddca15283655b27e1b
1 (**
2 * Copyright (c) 2015, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
8 *)
9 open Ast
10 module Aast = Nast
11 module SN = Naming_special_names
13 type class_body =
15 c_uses : Aast.hint list ;
16 c_method_redeclarations : Aast.method_redeclaration list;
17 c_xhp_attr_uses : Aast.hint list ;
18 c_xhp_category : pstring list ;
19 c_req_extends : Aast.hint list ;
20 c_req_implements : Aast.hint list ;
21 c_consts : Aast.class_const list ;
22 c_typeconsts : Aast.class_typeconst list ;
23 c_static_vars : Aast.static_var list ;
24 c_vars : Aast.class_var list ;
25 c_constructor : Aast.constructor option ;
26 c_static_methods : Aast.static_method list ;
27 c_methods : Aast.method_ list ;
28 c_attributes : Aast.class_attr list ;
29 c_xhp_children : (pos * Aast.xhp_child) list ;
30 c_xhp_attrs : Aast.xhp_attr list ;
31 c_pu_enums : Aast.pu_enum list ;
34 let make_empty_class_body = {
35 c_uses = [];
36 c_method_redeclarations = [];
37 c_xhp_attr_uses = [];
38 c_xhp_category = [];
39 c_req_extends = [];
40 c_req_implements = [];
41 c_consts = [];
42 c_typeconsts = [];
43 c_static_vars = [];
44 c_vars = [];
45 c_constructor = None;
46 c_static_methods = [];
47 c_methods = [];
48 c_attributes = [];
49 c_xhp_children = [];
50 c_xhp_attrs = [];
51 c_pu_enums = [];
54 let on_list f l = List.map f l
56 let on_list_append_acc acc f l =
57 List.fold_left
58 (fun acc li -> f li :: acc)
59 acc
61 let optional f = function
62 | None -> None
63 | Some x -> Some (f x)
65 let both f (p1, p2) = (f p1, f p2)
67 let rec on_variadic_hint h =
68 match h with
69 | Hvariadic h -> Aast.Hvariadic (optional on_hint h)
70 | Hnon_variadic -> Aast.Hnon_variadic
72 and get_pos_shape_name name =
73 match name with
74 | SFlit_int (pos, _)
75 | SFlit_str (pos, _)
76 | SFclass_const (_, (pos, _)) -> pos
78 and on_shape_info info =
79 let on_shape_field sf =
80 Aast.{ sfi_optional = sf.sf_optional; sfi_hint = on_hint sf.sf_hint } in
81 let nfm =
82 List.fold_left
83 (fun acc sf ->
84 if ShapeMap.mem sf.sf_name acc
85 then Errors.fd_name_already_bound (get_pos_shape_name sf.sf_name);
86 ShapeMap.add sf.sf_name (on_shape_field sf) acc)
87 ShapeMap.empty
88 info.si_shape_field_list in
89 Aast.{
90 nsi_allows_unknown_fields = info.si_allows_unknown_fields;
91 nsi_field_map = nfm;
94 and on_haccess (pos, root_id) id ids =
95 let root_ty = Aast.Happly ((pos, root_id), []) in
96 Aast.Haccess ((pos, root_ty), id :: ids)
98 and on_hint (p, h) : Aast.hint =
99 match h with
100 | Hoption h -> (p, Aast.Hoption (on_hint h))
101 | Hfun (is_coroutine, hl, param_kinds, variadic, h) ->
102 (p, Aast.Hfun
103 (Aast.FNonreactive,
104 is_coroutine,
105 (on_list on_hint hl),
106 param_kinds,
108 (on_variadic_hint variadic),
109 (on_hint h),
110 true
113 | Htuple (hl) -> (p, Aast.Htuple (on_list on_hint hl))
114 | Happly (x, hl) -> (p, Aast.Happly (x, on_list on_hint hl))
115 | Hshape s -> (p, Aast.Hshape (on_shape_info s))
116 | Haccess (root, id, ids) -> (p, on_haccess root id ids)
117 | Hsoft h -> (p, Aast.Hsoft (on_hint h))
119 and on_class_elt trait_or_interface body elt : class_body =
120 match elt with
121 | Attributes attrs ->
122 let attrs = on_list_append_acc body.c_attributes on_class_attr attrs in
123 { body with c_attributes = attrs; }
124 | Const (hopt, el) ->
125 let hopt = optional on_hint hopt in
126 let consts = on_list_append_acc body.c_consts (fun (id, e) ->
127 (hopt, id, Some (on_expr e))
128 ) el in
129 { body with c_consts = consts; }
130 | AbsConst (hopt, id) ->
131 let consts = (optional on_hint hopt, id, None) :: body.c_consts in
132 { body with c_consts = consts; }
133 | ClassUse h ->
134 let hints = on_hint h :: body.c_uses in
135 { body with c_uses = hints; }
136 | ClassUseAlias (_, (p, _), _, _) ->
137 Errors.unsupported_feature p "Trait use aliasing"; body
138 | ClassUsePrecedence (_, (p, _), _) ->
139 Errors.unsupported_feature p "The insteadof keyword"; body
140 | MethodTraitResolution res ->
141 let redecls = on_method_trait_resolution res :: body.c_method_redeclarations in
142 { body with c_method_redeclarations = redecls; }
143 | XhpAttrUse h ->
144 let hints = on_hint h :: body.c_xhp_attr_uses in
145 { body with c_xhp_attr_uses = hints }
146 | ClassTraitRequire (MustExtend, h) ->
147 let hints = on_hint h :: body.c_req_extends in
148 { body with c_req_extends = hints; }
149 | ClassTraitRequire (MustImplement, h) ->
150 let hints = on_hint h :: body.c_req_implements in
151 { body with c_req_implements = hints; }
152 | ClassVars cv when List.mem Static cv.cv_kinds ->
153 let attrs = on_list on_user_attribute cv.cv_user_attributes in
154 let vars =
155 on_list_append_acc
156 body.c_static_vars
157 (on_class_var false (optional on_hint cv.cv_hint) attrs cv.cv_kinds)
158 cv.cv_names in
159 { body with c_static_vars = vars; }
160 | ClassVars { cv_names; cv_user_attributes; cv_hint; cv_kinds; _ } ->
161 let attrs = on_list on_user_attribute cv_user_attributes in
162 let vars =
163 on_list_append_acc
164 body.c_vars
165 (on_class_var false (optional on_hint cv_hint) attrs cv_kinds)
166 cv_names in
167 { body with c_vars = vars; }
168 | XhpAttr (hopt, var, is_required, maybe_enum) ->
169 (* TODO: T37984688 Updating naming.ml to use c_xhp_attrs *)
170 let hopt = optional on_hint hopt in
171 let attrs =
172 (hopt,
173 on_class_var true hopt [] [] var,
174 is_required,
175 optional on_xhp_attr maybe_enum) :: body.c_xhp_attrs in
176 { body with c_xhp_attrs = attrs; }
177 | XhpCategory (_, cs) ->
178 if body.c_xhp_category <> [] && cs <> []
179 then Errors.multiple_xhp_category (fst (List.hd cs));
180 { body with c_xhp_category = cs; }
181 | XhpChild (p, c) ->
182 let children = (p, on_xhp_child c) :: body.c_xhp_children in
183 { body with c_xhp_children = children; }
184 | Method m when snd m.m_name = SN.Members.__construct ->
185 if body.c_constructor <> None
186 then Errors.method_name_already_bound (fst m.m_name) (snd m.m_name);
187 { body with c_constructor = Some (on_method ~trait_or_interface m) }
188 | Method m when List.mem Static m.m_kind ->
189 let statics = on_method m :: body.c_static_methods in
190 { body with c_static_methods = statics; }
191 | Method m ->
192 let methods = on_method m :: body.c_methods in
193 { body with c_methods = methods; }
194 | TypeConst tc ->
195 let typeconsts = on_class_typeconst tc :: body.c_typeconsts in
196 { body with c_typeconsts = typeconsts; }
197 | ClassEnum (pu_is_final, pu_name, fields) ->
198 let pu_enum = on_pu pu_name pu_is_final fields in
199 let pu_enums = pu_enum :: body.c_pu_enums in
200 { body with c_pu_enums = pu_enums }
202 and on_as_expr aw e : Aast.as_expr =
203 match aw, e with
204 | None, As_v ev -> Aast.As_v (on_expr ev)
205 | Some p, As_v ev -> Aast.Await_as_v (p, on_expr ev)
206 | None, As_kv (k, ev) -> Aast.As_kv (on_expr k, on_expr ev)
207 | Some p, As_kv (k, ev) -> Aast.Await_as_kv (p, on_expr k, on_expr ev)
209 and on_afield f : Aast.afield =
210 match f with
211 | AFvalue e -> Aast.AFvalue (on_expr e)
212 | AFkvalue (e1, e2) -> Aast.AFkvalue (on_expr e1, on_expr e2)
214 and on_darray_element (e1, e2) =
215 (on_expr e1, on_expr e2)
217 and on_shape (sfn, e) =
218 (sfn, on_expr e)
220 and on_awaitall_expr (e1, e2) =
221 let e2 = on_expr e2 in
222 let e1 =
223 match e1 with
224 | Some (pos, name) ->
225 let e = pos, Local_id.make_unscoped name in
226 Some e
227 | None -> None
229 (e1, e2)
231 and on_xhp_attribute a : Aast.xhp_attribute =
232 match a with
233 | Xhp_simple (id, e) -> Aast.Xhp_simple (id, on_expr e)
234 | Xhp_spread e -> Aast.Xhp_spread (on_expr e)
236 and on_targ h : Aast.targ = on_hint h
238 and on_collection_targ targ = match targ with
239 | Some CollectionTKV (tk, tv) -> Some (Aast.CollectionTKV (on_targ tk, on_targ tv))
240 | Some CollectionTV tv -> Some (Aast.CollectionTV (on_targ tv))
241 | None -> None
243 and on_expr (p, e) : Aast.expr =
244 let node = match e with
245 | Array al -> Aast.Array (on_list on_afield al)
246 | Varray (ta, el) -> Aast.Varray (optional on_targ ta, on_list on_expr el)
247 | Darray (tap, d) -> Aast.Darray (optional (both on_targ) tap, on_list on_darray_element d)
248 | Shape s -> Aast.Shape (on_list on_shape s)
249 | Collection (id, tal, al) -> Aast.Collection (id, on_collection_targ tal, on_list on_afield al)
250 | Null -> Aast.Null
251 | True -> Aast.True
252 | False -> Aast.False
253 | Omitted -> Aast.Omitted
254 | Id id -> Aast.Id id
255 | Lvar id ->
256 let lid = Local_id.make_unscoped (snd id) in
257 Aast.Lvar (p, lid)
258 | Clone e -> Aast.Clone (on_expr e)
259 | Obj_get (e1, e2, f) -> Aast.Obj_get (on_expr e1, on_expr e2, f)
260 | Array_get (e, opt_e) -> Aast.Array_get (on_expr e, optional on_expr opt_e)
261 | Class_get (e1, (_, (Id x2 | Lvar x2))) ->
262 Aast.Class_get((p, Aast.CIexpr (on_expr e1)), Aast.CGstring x2)
263 | Class_get (e1, e2) -> Aast.Class_get ((p, Aast.CIexpr (on_expr e1)), Aast.CGexpr (on_expr e2))
264 | Class_const (e, s) -> Aast.Class_const ((p, Aast.CIexpr (on_expr e)), s)
265 | Call (e, tl, el, uel) ->
266 Aast.Call (Aast.Cnormal, on_expr e, on_list on_targ tl, on_list on_expr el, on_list on_expr uel)
267 | Int s -> Aast.Int s
268 | Float s -> Aast.Float s
269 | String s -> Aast.String s
270 | String2 el -> Aast.String2 (on_list on_expr el)
271 | PrefixedString (s, e) -> Aast.PrefixedString (s, on_expr e)
272 | Yield f -> Aast.Yield (on_afield f)
273 | Yield_break -> Aast.Yield_break
274 | Yield_from e -> Aast.Yield_from (on_expr e)
275 | Await e -> Aast.Await (on_expr e)
276 | Suspend e -> Aast.Suspend (on_expr e)
277 | List el -> Aast.List (on_list on_expr el)
278 | Expr_list el -> Aast.Expr_list (on_list on_expr el)
279 | Cast (h, e) -> Aast.Cast (on_hint h, on_expr e)
280 | Unop (op, e) -> Aast.Unop (op, on_expr e)
281 | Binop (op, e1, e2) -> Aast.Binop (op, on_expr e1, on_expr e2)
282 | Pipe (e1, e2) ->
283 let id = Local_id.make_scoped SN.SpecialIdents.dollardollar in
284 Aast.Pipe ((p, id), on_expr e1, on_expr e2)
285 | Eif (e1, opt_e, e2) -> Aast.Eif (on_expr e1, optional on_expr opt_e, on_expr e2)
286 | InstanceOf (e1, e2) -> Aast.InstanceOf (on_expr e1, (p, Aast.CIexpr (on_expr e2)))
287 | Is (e, h) -> Aast.Is (on_expr e, on_hint h)
288 | As (e, h, b) -> Aast.As (on_expr e, on_hint h, b)
289 | New (e, tl, el1, el2) ->
290 Aast.New (
291 (p, Aast.CIexpr (on_expr e)),
292 on_list on_targ tl,
293 on_list on_expr el1,
294 on_list on_expr el2,
297 | Efun (f, use_list) ->
298 let ids = List.map
299 (fun ((p, id), is_ref) ->
300 if is_ref then Errors.unsupported_feature p "References in use list";
301 (p, Local_id.make_unscoped id)
303 use_list
305 Aast.Efun (on_fun f, ids)
306 | Lfun f -> Aast.Lfun (on_fun f)
307 | BracedExpr e -> Aast.BracedExpr (on_expr e)
308 | ParenthesizedExpr e -> Aast.ParenthesizedExpr (on_expr e)
309 | Xml (id, xhpl, el) -> Aast.Xml (id, on_list on_xhp_attribute xhpl, on_list on_expr el)
310 | Unsafeexpr e -> Aast.Unsafe_expr (on_expr e)
311 | Import (f, e) -> Aast.Import (on_import_flavor f, on_expr e)
312 | Callconv (k, e) -> Aast.Callconv (k, on_expr e)
313 | PU_atom id -> Aast.PU_atom (snd id)
314 | PU_identifier (e, id1, id2) ->
315 Aast.PU_identifier ((p, Aast.CIexpr (on_expr e)), id1, id2)
317 (p, node)
319 and on_import_flavor f =
320 match f with
321 | Include -> Aast.Include
322 | Require -> Aast.Require
323 | IncludeOnce -> Aast.IncludeOnce
324 | RequireOnce -> Aast.RequireOnce
326 and on_case c : Aast.case =
327 match c with
328 | Default b -> Aast.Default (on_block b)
329 | Case (e, b) -> Aast.Case (on_expr e, on_block b)
331 and on_catch (id1, id2, b) : Aast.catch =
332 let lid = Local_id.make_unscoped (snd id2) in
333 (id1, ((fst id2), lid), on_block b)
335 and on_stmt (p, st) : Aast.stmt =
336 p, on_stmt_ p st
338 and on_stmt_ p st : Aast.stmt_ =
339 match st with
340 | Let (id, h, e) ->
341 let lid = Local_id.make_unscoped (snd id) in
342 Aast.Let ((p, lid), optional on_hint h, on_expr e)
343 | Block sl -> Aast.Block (on_block sl)
344 | Unsafe -> failwith "Unsafe statements should be removed in on_block"
345 | Fallthrough -> Aast.Fallthrough
346 | Noop -> Aast.Noop
347 | Markup (s, e) -> Aast.Markup (s, optional on_expr e)
348 | Break (Some _) -> Errors.break_continue_n_not_supported p; Aast.Break p
349 | Break None -> Aast.Break p
350 | Continue (Some _) -> Errors.break_continue_n_not_supported p; Aast.Continue p
351 | Continue None -> Aast.Continue p
352 | Throw e -> Aast.Throw (false, on_expr e)
353 | Return e -> Aast.Return (p, optional on_expr e)
354 | GotoLabel label -> Aast.GotoLabel label
355 | Goto label -> Aast.Goto label
356 | Global_var el -> Aast.Global_var (on_list on_expr el)
357 | Awaitall el -> Aast.Awaitall (p, on_list on_awaitall_expr el)
358 | If (e, b1, b2) -> Aast.If (on_expr e, on_block b1, on_block b2)
359 | Do (b, e) -> Aast.Do (on_block b, on_expr e)
360 | While (e, b) -> Aast.While (on_expr e, on_block b)
361 | Declare (is_blk, e, b) -> Aast.Declare (is_blk, on_expr e, on_block b)
362 | Using s ->
363 Aast.Using Aast.{
364 us_expr = on_expr s.us_expr;
365 us_block = on_block s.us_block;
366 us_has_await = s.us_has_await;
367 us_is_block_scoped = s.us_is_block_scoped;
369 | For (st1, e, st2, b) -> Aast.For (on_expr st1, on_expr e, on_expr st2, on_block b)
370 | Switch (e, cl) -> Aast.Switch (on_expr e, on_list on_case cl)
371 | Foreach (e, aw, ae, b) -> Aast.Foreach (on_expr e, on_as_expr aw ae, on_block b)
372 | Try (b, cl, fb) -> Aast.Try (on_block b, on_list on_catch cl, on_block fb)
373 | Def_inline d -> Aast.Def_inline (on_def d)
374 | Expr e -> Aast.Expr (on_expr e)
376 and on_block stmt_list : Aast.stmt list =
377 match stmt_list with
378 | [] -> []
379 | (p, Unsafe) :: rest -> [p, Aast.Unsafe_block (on_block rest)]
380 | x :: rest -> (on_stmt x) :: (on_block rest)
382 and on_tparam_constraint (kind, hint) : (constraint_kind * Aast.hint) =
383 (kind, on_hint hint)
385 and on_tparam t : Aast.tparam =
386 { Aast.tp_variance = t.tp_variance;
387 tp_name = t.tp_name;
388 tp_constraints = on_list on_tparam_constraint t.tp_constraints;
389 tp_reified = t.tp_reified;
390 tp_user_attributes = on_list on_user_attribute t.tp_user_attributes;
393 and on_fun_param ?(trait_or_interface=false) param : Aast.fun_param =
394 let p, name = param.param_id in
395 if trait_or_interface && param.param_modifier <> None
396 then Errors.trait_interface_constructor_promo p;
397 { Aast.param_annotation = p;
398 param_hint = optional on_hint param.param_hint;
399 param_is_reference = param.param_is_reference;
400 param_is_variadic = param.param_is_variadic;
401 param_pos = p;
402 param_name = name;
403 param_expr = optional on_expr param.param_expr;
404 param_callconv = param.param_callconv;
405 param_user_attributes = on_list on_user_attribute param.param_user_attributes;
408 and determine_variadicity params =
409 match params with
410 | [] -> Aast.FVnonVariadic
411 | [x] ->
412 begin
413 match x.param_is_variadic, x.param_id with
414 | false, _ -> Aast.FVnonVariadic
415 | true, (p, "...") -> Aast.FVellipsis p
416 | true, _ -> Aast.FVvariadicArg (on_fun_param x)
418 | _ :: rl ->
419 determine_variadicity rl
421 and on_user_attribute attribute : Aast.user_attribute =
422 let ua_params = on_list on_expr attribute.ua_params in
423 Aast.{ ua_name = attribute.ua_name; ua_params; }
425 and on_file_attribute (attribute:Ast.file_attributes) : Aast.file_attribute =
426 Aast.
427 { fa_user_attributes = on_list on_user_attribute attribute.fa_user_attributes
428 ; fa_namespace = attribute.fa_namespace
431 and on_fun f : Aast.fun_ =
432 let body = on_block f.f_body in
433 let body = {
434 Aast.fb_ast = body;
435 (* Still seems incorrect to have this as a Named body... *)
436 Aast.fb_annotation = Aast.BodyNamingAnnotation.NamedWithUnsafeBlocks;
437 } in
438 let named_fun = {
439 Aast.f_annotation = ();
440 f_span = f.f_span;
441 f_mode = f.f_mode;
442 f_ret = (optional on_hint f.f_ret);
443 f_name = f.f_name;
444 f_tparams =
445 on_list on_tparam f.f_tparams;
446 f_where_constraints = on_list on_constr f.f_constrs;
447 f_params = on_list on_fun_param f.f_params;
448 f_body = body;
449 f_fun_kind = f.f_fun_kind;
450 f_variadic = determine_variadicity f.f_params;
451 f_user_attributes = on_list on_user_attribute f.f_user_attributes;
452 f_file_attributes = on_list on_file_attribute f.f_file_attributes;
453 f_external = f.f_external;
454 f_namespace = f.f_namespace;
455 f_doc_comment = f.f_doc_comment;
456 f_static = f.f_static;
457 } in
458 named_fun
460 and on_enum (e : enum_) : Aast.enum_ =
461 Aast.{
462 e_base = on_hint e.e_base;
463 e_constraint = optional on_hint e.e_constraint
466 and on_class_attr attr : Aast.class_attr =
467 match attr with
468 | CA_name id -> Aast.CA_name id
469 | CA_field f -> Aast.CA_field Aast.{
470 ca_type = on_ca_type f.ca_type;
471 ca_id = f.ca_id;
472 ca_value = optional on_expr f.ca_value;
473 ca_required = f.ca_required;
476 and on_ca_type ty : Aast.ca_type =
477 match ty with
478 | CA_hint h -> Aast.CA_hint (on_hint h)
479 | CA_enum sl -> Aast.CA_enum (sl)
481 and on_class_typeconst (tc: Ast.typeconst) : Aast.class_typeconst =
482 let tconst_type =
483 match tc.tconst_type, tc.tconst_abstract with
484 | None, false ->
485 Errors.not_abstract_without_typeconst tc.tconst_name;
486 tc.tconst_constraint
487 | Some _, true ->
488 Errors.abstract_with_typeconst tc.tconst_name;
489 None
490 | h, _ -> h in
491 Aast.{
492 c_tconst_name = tc.tconst_name;
493 c_tconst_constraint = optional on_hint tc.tconst_constraint;
494 c_tconst_type = optional on_hint tconst_type;
495 c_tconst_user_attributes = on_list on_user_attribute tc.tconst_user_attributes;
498 and on_class_var is_xhp h attrs kinds (_, id, eopt) : Aast.class_var =
499 let cv_final = List.mem Final kinds in
500 let cv_visibility = List.fold_left
501 begin
502 fun acc k ->
503 match k with
504 | Private -> Aast.Private
505 | Public -> Aast.Public
506 | Protected -> Aast.Protected
507 | _ -> acc
509 Aast.Public
510 kinds in
511 Aast.{
512 cv_final;
513 cv_is_xhp = is_xhp;
514 cv_visibility;
515 cv_type = h;
516 cv_id = id;
517 cv_expr = optional on_expr eopt;
518 cv_user_attributes = attrs;
521 and on_xhp_attr (p, b, el) = (p, b, on_list on_expr el)
523 and on_constr (h1, k, h2) = (on_hint h1, k, on_hint h2)
525 and on_method_trait_resolution res : Aast.method_redeclaration =
526 let acc = false, false, false, None in
527 let final, abs, static, vis = List.fold_left kind acc res.mt_kind in
528 let vis =
529 match vis with
530 | None ->
531 Errors.method_needs_visibility (fst res.mt_name);
532 Aast.Public
533 | Some v -> v in
534 Aast.{
535 mt_final = final;
536 mt_abstract = abs;
537 mt_static = static;
538 mt_visibility = vis;
539 mt_name = res.mt_name;
540 mt_tparams = on_list on_tparam res.mt_tparams;
541 mt_where_constraints = on_list on_constr res.mt_constrs;
542 mt_variadic = determine_variadicity res.mt_params;
543 mt_params = on_list on_fun_param res.mt_params;
544 mt_fun_kind = res.mt_fun_kind;
545 mt_ret = optional on_hint res.mt_ret;
546 mt_trait = on_hint res.mt_trait;
547 mt_method = res.mt_method;
548 mt_user_attributes = on_list on_user_attribute res.mt_user_attributes;
551 and on_xhp_child c : Aast.xhp_child =
552 match c with
553 | ChildName id -> Aast.ChildName id
554 | ChildList cl -> Aast.ChildList (on_list on_xhp_child cl)
555 | ChildUnary (c, op) -> Aast.ChildUnary (on_xhp_child c, on_xhp_child_op op)
556 | ChildBinary (c1, c2) -> Aast.ChildBinary (on_xhp_child c1, on_xhp_child c2)
558 and on_xhp_child_op op : Aast.xhp_child_op =
559 match op with
560 | ChildStar -> Aast.ChildStar
561 | ChildPlus -> Aast.ChildPlus
562 | ChildQuestion -> Aast.ChildQuestion
564 and kind (final, abs, static, vis) = function
565 | Final -> true, abs, static, vis
566 | Static -> final, abs, true, vis
567 | Abstract -> final, true, static, vis
568 | Private -> final, abs, static, Some Aast.Private
569 | Public -> final, abs, static, Some Aast.Public
570 | Protected -> final, abs, static, Some Aast.Protected
572 and on_method ?(trait_or_interface=false) m : Aast.method_ =
573 let body = on_block m.m_body in
574 let body = {
575 Aast.fb_ast = body;
576 (* Still seems incorrect to have this as a Named body... *)
577 Aast.fb_annotation = Aast.BodyNamingAnnotation.NamedWithUnsafeBlocks;
578 } in
579 let acc = false, false, false, None in
580 let final, abs, static, vis = List.fold_left kind acc m.m_kind in
581 let vis =
582 match vis with
583 | None -> Errors.method_needs_visibility (fst m.m_name); Aast.Public
584 | Some v -> v in
585 Aast.{
586 m_span = m.m_span;
587 m_annotation = ();
588 m_final = final;
589 m_abstract = abs;
590 m_static = static;
591 m_visibility = vis;
592 m_name = m.m_name;
593 m_tparams = on_list on_tparam m.m_tparams;
594 m_where_constraints = on_list on_constr m.m_constrs;
595 m_variadic = determine_variadicity m.m_params;
596 m_params = on_list (on_fun_param ~trait_or_interface) m.m_params;
597 m_body = body;
598 m_fun_kind = m.m_fun_kind;
599 m_user_attributes = on_list on_user_attribute m.m_user_attributes;
600 m_ret = optional on_hint m.m_ret;
601 m_external = m.m_external;
602 m_doc_comment = m.m_doc_comment;
605 and on_pu_mapping pum_atom mappings =
606 let rec aux types exprs = function
607 | (PUMappingType (id, hint)) :: tl ->
608 aux ((id, on_hint hint) :: types) exprs tl
609 | (PUMappingID (id, expr)) :: tl ->
610 aux types ((id, on_expr expr) :: exprs) tl
611 | [] -> (List.rev types, List.rev exprs) in
612 let (pum_types, pum_exprs) = aux [] [] mappings in
613 Aast.{ pum_atom; pum_types; pum_exprs }
615 and on_pu pu_name pu_is_final fields =
616 let rec aux case_types case_values members = function
617 | (PUCaseType id) :: tl ->
618 aux (id :: case_types) case_values members tl
619 | (PUCaseTypeExpr (h, id)) :: tl ->
620 aux case_types ((id, on_hint h) :: case_values) members tl
621 | (PUAtomDecl (id, maps)) :: tl ->
622 let member = on_pu_mapping id maps in
623 aux case_types case_values (member :: members) tl
624 | [] -> (List.rev case_types, List.rev case_values, List.rev members) in
625 let (pu_case_types, pu_case_values, pu_members) = aux [] [] [] fields in
626 Aast.{ pu_name
627 ; pu_is_final
628 ; pu_case_types
629 ; pu_case_values
630 ; pu_members
633 and on_class_body trait_or_interface cb =
634 let reversed_body = List.fold_left (on_class_elt trait_or_interface) make_empty_class_body cb in
635 { reversed_body with
636 c_uses = List.rev reversed_body.c_uses;
637 c_method_redeclarations = List.rev reversed_body.c_method_redeclarations;
638 c_xhp_attr_uses = List.rev reversed_body.c_xhp_attr_uses;
639 c_xhp_category = List.rev reversed_body.c_xhp_category;
640 c_req_extends = List.rev reversed_body.c_req_extends;
641 c_req_implements = List.rev reversed_body.c_req_implements;
642 c_consts = List.rev reversed_body.c_consts;
643 c_typeconsts = List.rev reversed_body.c_typeconsts;
644 c_static_vars = List.rev reversed_body.c_static_vars;
645 c_vars = List.rev reversed_body.c_vars;
646 c_static_methods = List.rev reversed_body.c_static_methods;
647 c_methods = List.rev reversed_body.c_methods;
648 c_attributes = List.rev reversed_body.c_attributes;
649 c_xhp_children = List.rev reversed_body.c_xhp_children;
650 c_xhp_attrs = List.rev reversed_body.c_xhp_attrs;
651 c_pu_enums = List.rev reversed_body.c_pu_enums;
654 and on_class c : Aast.class_ =
655 let c_tparams = {
656 Aast.c_tparam_list = on_list on_tparam c.c_tparams;
657 Aast.c_tparam_constraints = SMap.empty;
658 } in
659 let trait_or_interface = c.c_kind = Ctrait || c.c_kind = Cinterface in
660 let body = on_class_body trait_or_interface c.c_body in
661 let named_class =
662 Aast.{
663 c_annotation = ();
664 c_span = c.c_span;
665 c_mode = c.c_mode;
666 c_final = c.c_final;
667 c_is_xhp = c.c_is_xhp;
668 c_kind = c.c_kind;
669 c_name = c.c_name;
670 c_tparams = c_tparams;
671 c_extends = on_list on_hint c.c_extends;
672 c_uses = body.c_uses;
673 c_method_redeclarations = body.c_method_redeclarations;
674 c_xhp_attr_uses = body.c_xhp_attr_uses;
675 c_xhp_category = body.c_xhp_category;
676 c_req_extends = body.c_req_extends;
677 c_req_implements = body.c_req_implements;
678 c_implements = on_list on_hint c.c_implements;
679 c_consts = body.c_consts;
680 c_typeconsts = body.c_typeconsts;
681 c_static_vars = body.c_static_vars;
682 c_vars = body.c_vars;
683 c_constructor = body.c_constructor;
684 c_static_methods = body.c_static_methods;
685 c_methods = body.c_methods;
686 c_attributes = body.c_attributes;
687 c_xhp_children = body.c_xhp_children;
688 c_xhp_attrs = body.c_xhp_attrs;
689 c_user_attributes = on_list on_user_attribute c.c_user_attributes;
690 c_file_attributes = on_list on_file_attribute c.c_file_attributes;
691 c_namespace = c.c_namespace;
692 c_enum = optional on_enum c.c_enum;
693 c_doc_comment = c.c_doc_comment;
694 c_pu_enums = body.c_pu_enums
697 named_class
699 and on_typedef t : Aast.typedef =
700 let t_vis = match t.t_kind with
701 | Alias _ -> Aast.Transparent
702 | NewType _ -> Aast.Opaque
704 let t_kind = match t.t_kind with
705 | Alias h -> on_hint h
706 | NewType h -> on_hint h
708 Aast.{
709 t_annotation = ();
710 t_name = t.t_id;
711 t_tparams = on_list on_tparam t.t_tparams;
712 t_constraint = optional on_hint t.t_constraint;
713 t_kind = t_kind;
714 t_user_attributes = on_list on_user_attribute t.t_user_attributes;
715 t_mode = t.t_mode;
716 t_vis = t_vis;
717 t_namespace = t.t_namespace;
720 and on_constant (c : gconst) : Aast.gconst =
721 Aast.{
722 cst_annotation = ();
723 cst_mode = c.cst_mode;
724 cst_name = c.cst_name;
725 cst_type = optional on_hint c.cst_type;
726 cst_value = Some (on_expr c.cst_value);
727 cst_namespace = c.cst_namespace;
730 and on_ns_use (k, id1, id2): (Aast.ns_kind * Aast.sid * Aast.sid) =
731 let kind = match k with
732 | NSNamespace -> Aast.NSNamespace
733 | NSClass -> Aast.NSClass
734 | NSClassAndNamespace -> Aast.NSClassAndNamespace
735 | NSFun -> Aast.NSFun
736 | NSConst -> Aast.NSConst
738 (kind, id1, id2)
740 and on_def : def -> Aast.def = function
741 | Fun f -> Aast.Fun (on_fun f)
742 | Class c -> Aast.Class (on_class c)
743 | Stmt s -> Aast.Stmt (on_stmt s)
744 | Typedef t -> Aast.Typedef (on_typedef t)
745 | Constant c -> Aast.Constant (on_constant c)
746 | Namespace (id, p) -> Aast.Namespace (id, on_program p)
747 | NamespaceUse usel -> Aast.NamespaceUse (on_list on_ns_use usel)
748 | SetNamespaceEnv env -> Aast.SetNamespaceEnv env
749 | FileAttributes _ -> Aast.Stmt (Pos.none, Aast.Noop)
751 and on_program ast = on_list on_def ast
753 let convert ast : Aast.program = on_program ast