2 * Copyright (c) 2015, Facebook, Inc.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
12 (* Ensure that doc comments are always on a separate line by
13 requiring a lot of padding for inline doc comments. *)
14 [@@@ocamlformat
"doc-comments-padding=80"]
16 (** Aast.program represents the top-level definitions in a Hack program.
17 ex: Expression annotation type (when typechecking, the inferred type)
18 fb: Function body tag (e.g. has naming occurred)
19 en: Environment (tracking state inside functions and classes)
20 hi: Hint annotation (when typechecking it will be the localized type hint or the
21 inferred missing type if the hint is missing)
23 type ('ex
, 'fb
, 'en
, 'hi
) program
= ('ex
, 'fb
, 'en
, 'hi
) def list
25 show
{ with_path
= false },
32 ancestors
= ["iter_defs"];
39 ancestors
= ["reduce_defs"];
46 ancestors
= ["map_defs"];
53 ancestors
= ["endo_defs"];
56 and ('ex
, 'fb
, 'en
, 'hi
) stmt
= pos
* ('ex
, 'fb
, 'en
, 'hi
) stmt_
58 and ('ex
, 'fb
, 'en
, 'hi
) stmt_
=
60 (** Marker for a switch statement that falls through.
63 | Expr
of ('ex
, 'fb
, 'en
, 'hi
) expr
64 (** Standalone expression.
68 (** Break inside a loop or switch statement.
72 (** Continue inside a loop or switch statement.
75 | Throw
of ('ex
, 'fb
, 'en
, 'hi
) expr
76 (** Throw an exception.
79 | Return
of ('ex
, 'fb
, 'en
, 'hi
) expr
option
80 (** Return, with an optional value.
85 (** Yield break, terminating the current generator. This behaves like
86 return; but is more explicit, and ensures the function is treated
91 (* Temporaries assigned when running awaits. *)
92 (lid
option * ('ex
, 'fb
, 'en
, 'hi
) expr
) list
93 * (* Block assigning temporary to relevant locals. *)
94 ('ex
, 'fb
, 'en
, 'hi
) block
95 (** Concurrent block. All the await expressions are awaited at the
96 same time, similar to genva().
98 We store the desugared form. In the below example, the list is:
99 [('__tmp$1', f()), (__tmp$2, g()), (None, h())]
100 and the block assigns the temporary variables back to the locals.
101 { $foo = __tmp$1; $bar = __tmp$2; }
109 ('ex
, 'fb
, 'en
, 'hi
) expr
110 * ('ex
, 'fb
, 'en
, 'hi
) block
111 * ('ex
, 'fb
, 'en
, 'hi
) block
114 if ($foo) { ... } else { ... } *)
115 | Do
of ('ex
, 'fb
, 'en
, 'hi
) block
* ('ex
, 'fb
, 'en
, 'hi
) expr
121 | While
of ('ex
, 'fb
, 'en
, 'hi
) expr
* ('ex
, 'fb
, 'en
, 'hi
) block
127 | Using
of ('ex
, 'fb
, 'en
, 'hi
) using_stmt
128 (** Initialize a value that is automatically disposed of.
130 using $foo = bar(); // disposed at the end of the function
131 using ($foo = bar(), $baz = quux()) {} // disposed after the block *)
133 ('ex
, 'fb
, 'en
, 'hi
) expr list
134 * ('ex
, 'fb
, 'en
, 'hi
) expr
option
135 * ('ex
, 'fb
, 'en
, 'hi
) expr list
136 * ('ex
, 'fb
, 'en
, 'hi
) block
137 (** For loop. The initializer and increment parts can include
138 multiple comma-separated statements. The termination condition is
141 for ($i = 0; $i < 100; $i++) { ... }
142 for ($x = 0, $y = 0; ; $x++, $y++) { ... } *)
143 | Switch
of ('ex
, 'fb
, 'en
, 'hi
) expr
* ('ex
, 'fb
, 'en
, 'hi
) case list
144 (** Switch statement.
155 ('ex
, 'fb
, 'en
, 'hi
) expr
156 * ('ex
, 'fb
, 'en
, 'hi
) as_expr
157 * ('ex
, 'fb
, 'en
, 'hi
) block
160 foreach ($items as $item) { ... }
161 foreach ($items as $key => value) { ... }
162 foreach ($items await as $item) { ... } // AsyncIterator<_>
163 foreach ($items await as $key => value) { ... } // AsyncKeyedIterator<_> *)
165 ('ex
, 'fb
, 'en
, 'hi
) block
166 * ('ex
, 'fb
, 'en
, 'hi
) catch list
167 * ('ex
, 'fb
, 'en
, 'hi
) block
168 (** Try statement, with catch blocks and a finally block.
172 } catch (SomeException $e) {
178 (** No-op, the empty statement.
182 if ($foo) {} // the else is Noop here *)
183 | Block
of ('ex
, 'fb
, 'en
, 'hi
) block
184 (** Block, a list of statements in curly braces.
188 (** The mode tag at the beginning of a file.
189 TODO: this really belongs in def.
192 | AssertEnv
of env_annot
* 'ex local_id_map
193 (** Used in IFC to track type inference environments. Not user
200 and ('ex
, 'fb
, 'en
, 'hi
) using_stmt
= {
201 us_is_block_scoped
: bool;
203 us_exprs
: pos
* ('ex
, 'fb
, 'en
, 'hi
) expr list
;
204 us_block
: ('ex
, 'fb
, 'en
, 'hi
) block
;
207 and ('ex
, 'fb
, 'en
, 'hi
) as_expr
=
208 | As_v
of ('ex
, 'fb
, 'en
, 'hi
) expr
209 | As_kv
of ('ex
, 'fb
, 'en
, 'hi
) expr
* ('ex
, 'fb
, 'en
, 'hi
) expr
210 | Await_as_v
of pos
* ('ex
, 'fb
, 'en
, 'hi
) expr
211 | Await_as_kv
of pos
* ('ex
, 'fb
, 'en
, 'hi
) expr
* ('ex
, 'fb
, 'en
, 'hi
) expr
213 and ('ex
, 'fb
, 'en
, 'hi
) block
= ('ex
, 'fb
, 'en
, 'hi
) stmt list
215 and ('ex
, 'fb
, 'en
, 'hi
) class_id
= 'ex
* ('ex
, 'fb
, 'en
, 'hi
) class_id_
217 (** Class ID, used in things like instantiation and static property access. *)
218 and ('ex
, 'fb
, 'en
, 'hi
) class_id_
=
220 (** The class ID of the parent of the lexically scoped class.
222 In a trait, it is the parent class ID of the using class.
228 (** The class ID of the lexically scoped class.
230 In a trait, it is the class ID of the using class.
236 (** The class ID of the late static bound class.
238 https://www.php.net/manual/en/language.oop5.late-static-bindings.php
240 In a trait, it is the late static bound class ID of the using class.
245 | CIexpr
of ('ex
, 'fb
, 'en
, 'hi
) expr
246 (** Dynamic class name.
248 TODO: Syntactically this can only be an Lvar/This/Lplacehodller.
249 We should use lid rather than expr.
251 // Assume $d has type dynamic.
256 (** Explicit class name. This is the common case.
262 and ('ex
, 'fb
, 'en
, 'hi
) expr
= 'ex
* ('ex
, 'fb
, 'en
, 'hi
) expr_
264 and 'hi collection_targ
=
265 | CollectionTV
of 'hi targ
266 | CollectionTKV
of 'hi targ
* 'hi targ
268 and ('ex
, 'fb
, 'en
, 'hi
) function_ptr_id
=
270 | FP_class_const
of ('ex
, 'fb
, 'en
, 'hi
) class_id
* pstring
272 and ('ex
, 'fb
, 'en
, 'hi
) expression_tree
= {
274 et_splices
: ('ex
, 'fb
, 'en
, 'hi
) block
;
275 et_virtualized_expr
: ('ex
, 'fb
, 'en
, 'hi
) expr
;
276 et_runtime_expr
: ('ex
, 'fb
, 'en
, 'hi
) expr
;
279 and ('ex
, 'fb
, 'en
, 'hi
) expr_
=
281 ('hi targ
* 'hi targ
) option
282 * (('ex
, 'fb
, 'en
, 'hi
) expr
* ('ex
, 'fb
, 'en
, 'hi
) expr
) list
285 darray['x' => 0, 'y' => 1]
286 darray<string, int>['x' => 0, 'y' => 1] *)
287 | Varray
of 'hi targ
option * ('ex
, 'fb
, 'en
, 'hi
) expr list
290 varray['hello', 'world']
291 varray<string>['hello', 'world'] *)
292 | Shape
of (Ast_defs.shape_field_name
* ('ex
, 'fb
, 'en
, 'hi
) expr
) list
295 shape('x' => 1, 'y' => 2) *)
296 | ValCollection
of vc_kind
* 'hi targ
option * ('ex
, 'fb
, 'en
, 'hi
) expr list
297 (** Collection literal for indexable structures.
301 Set<string> {'foo', 'bar'}
304 | KeyValCollection
of
305 kvc_kind
* ('hi targ
* 'hi targ
) option * ('ex
, 'fb
, 'en
, 'hi
) field list
306 (** Collection literal for key-value structures.
308 dict['x' => 1, 'y' => 2]
316 (** The local variable representing the current class instance.
328 (** The empty expression.
330 list(, $y) = vec[1, 2] // Omitted is the first expression inside list() *)
332 (** An identifier. Used for method names and global constants.
335 $x->foo() // id: "foo" *)
340 | Dollardollar
of lid
341 (** The extra variable in a pipe expression.
344 | Clone
of ('ex
, 'fb
, 'en
, 'hi
) expr
345 (** Clone expression.
348 | Array_get
of ('ex
, 'fb
, 'en
, 'hi
) expr
* ('ex
, 'fb
, 'en
, 'hi
) expr
option
354 ('ex
, 'fb
, 'en
, 'hi
) expr
355 * ('ex
, 'fb
, 'en
, 'hi
) expr
357 * (* is_prop_call *) bool
358 (** Instance property or method access. is_prop_call is always
359 false, except when inside a call is accessing a property.
361 $foo->bar // (Obj_get false) property access
362 $foo->bar() // (Call (Obj_get false)) method call
363 ($foo->bar)() // (Call (Obj_get true)) call lambda stored in property
364 $foo?->bar // nullsafe access *)
366 ('ex
, 'fb
, 'en
, 'hi
) class_id
367 * ('ex
, 'fb
, 'en
, 'hi
) class_get_expr
368 * (* is_prop_call *) bool
369 (** Static property access.
372 $some_classname::$bar
373 Foo::${$bar} // only in partial mode *)
374 | Class_const
of ('ex
, 'fb
, 'en
, 'hi
) class_id
* pstring
375 (** Class constant or static method call. As a standalone expression,
376 this is a class constant. Inside a Call node, this is a static
379 This is not ambiguous, because constants are not allowed to
382 Foo::some_const // Class_const
383 Foo::someStaticMeth() // Call (Class_const)
385 This syntax is used for both static and instance methods when
386 calling the implementation on the superclass.
388 parent::someStaticMeth()
389 parent::someInstanceMeth() *)
392 ('ex
, 'fb
, 'en
, 'hi
) expr
393 * (* explicit type annotations *)
395 * (* positional args *)
396 ('ex
, 'fb
, 'en
, 'hi
) expr list
398 ('ex
, 'fb
, 'en
, 'hi
) expr
option
399 (** Function or method call.
403 foo<int>(1, 2, ...$rest)
408 (async () ==> { return 1; })() *)
409 | FunctionPointer
of ('ex
, 'fb
, 'en
, 'hi
) function_ptr_id
* 'hi targ list
410 (** A reference to a function or method.
419 0xBEEF // hexadecimal
420 0b11111111 // binary *)
427 | String
of byte_string
440 | String2
of ('ex
, 'fb
, 'en
, 'hi
) expr list
441 (** Interpolated string literal.
448 | PrefixedString
of string * ('ex
, 'fb
, 'en
, 'hi
) expr
449 (** Prefixed string literal. Only used for regular expressions.
452 | Yield
of ('ex
, 'fb
, 'en
, 'hi
) afield
453 (** Yield expression. The enclosing function should have an Iterator
456 yield $foo // enclosing function returns an Iterator
457 yield $foo => $bar // enclosing function returns a KeyedIterator *)
458 | Await
of ('ex
, 'fb
, 'en
, 'hi
) expr
459 (** Await expression.
462 | ReadonlyExpr
of ('ex
, 'fb
, 'en
, 'hi
) expr
463 (** Readonly expression.
466 | Tuple
of ('ex
, 'fb
, 'en
, 'hi
) expr list
467 (** Tuple expression.
469 tuple("a", 1, $foo) *)
470 | List
of ('ex
, 'fb
, 'en
, 'hi
) expr list
471 (** List expression, only used in destructuring. Allows any arbitrary
472 lvalue as a subexpression. May also nest.
474 list($x, $y) = vec[1, 2];
475 list(, $y) = vec[1, 2]; // skipping items
476 list(list($x)) = vec[vec[1]]; // nesting
477 list($v[0], $x[], $y->foo) = $blah; *)
478 | Cast
of hint
* ('ex
, 'fb
, 'en
, 'hi
) expr
479 (** Cast expression, converting a value to a different type. Only
480 primitive types are supported in the hint position.
484 | Unop
of Ast_defs.uop
* ('ex
, 'fb
, 'en
, 'hi
) expr
491 Ast_defs.bop
* ('ex
, 'fb
, 'en
, 'hi
) expr
* ('ex
, 'fb
, 'en
, 'hi
) expr
495 | Pipe
of lid
* ('ex
, 'fb
, 'en
, 'hi
) expr
* ('ex
, 'fb
, 'en
, 'hi
) expr
496 (** Pipe expression. The lid is the ID of the $$ that is implicitly
497 declared by this pipe.
499 See also Dollardollar.
501 $foo |> bar() // equivalent: bar($foo)
502 $foo |> bar(1, $$) // equivalent: bar(1, $foo) *)
504 ('ex
, 'fb
, 'en
, 'hi
) expr
505 * ('ex
, 'fb
, 'en
, 'hi
) expr
option
506 * ('ex
, 'fb
, 'en
, 'hi
) expr
507 (** Ternary operator, or elvis operator.
509 $foo ? $bar : $baz // ternary
510 $foo ?: $baz // elvis *)
511 | Is
of ('ex
, 'fb
, 'en
, 'hi
) expr
* hint
515 | As
of ('ex
, 'fb
, 'en
, 'hi
) expr
* hint
* (* is nullable *) bool
521 ('ex
, 'fb
, 'en
, 'hi
) class_id
523 * ('ex
, 'fb
, 'en
, 'hi
) expr list
524 * ('ex
, 'fb
, 'en
, 'hi
) expr
option
531 new Foo('blah', ...$rest); *)
532 | Record
of sid
* (('ex
, 'fb
, 'en
, 'hi
) expr
* ('ex
, 'fb
, 'en
, 'hi
) expr
) list
535 MyRecord['x' => $foo, 'y' => $bar] *)
536 | Efun
of ('ex
, 'fb
, 'en
, 'hi
) fun_
* lid list
537 (** PHP-style lambda. Does not capture variables unless explicitly
540 Mnemonic: 'expanded lambda', since we can desugar Lfun to Efun.
542 function($x) { return $x; }
543 function(int $x): int { return $x; }
544 function($x) use ($y) { return $y; }
545 function($x): int use ($y, $z) { return $x + $y + $z; } *)
546 | Lfun
of ('ex
, 'fb
, 'en
, 'hi
) fun_
* lid list
547 (** Hack lambda. Captures variables automatically.
550 (int $x): int ==> $x + $other
551 ($x, $y) ==> { return $x + $y; } *)
554 * ('ex
, 'fb
, 'en
, 'hi
) xhp_attribute list
555 * ('ex
, 'fb
, 'en
, 'hi
) expr list
556 (** XHP expression. May contain interpolated expressions.
558 <foo x="hello" y={$foo}>hello {$bar}</foo> *)
559 | Callconv
of Ast_defs.param_kind
* ('ex
, 'fb
, 'en
, 'hi
) expr
560 (** Explicit calling convention, used for inout. Inout supports any lvalue.
562 TODO: This could be a flag on parameters in Call.
565 | Import
of import_flavor
* ('ex
, 'fb
, 'en
, 'hi
) expr
566 (** Include or require expression.
569 require_once('foo.php')
571 include_once('foo.php') *)
573 sid
* 'hi collection_targ
option * ('ex
, 'fb
, 'en
, 'hi
) afield list
574 (** Collection literal.
576 TODO: T38184446 this is redundant with ValCollection/KeyValCollection.
579 | ExpressionTree
of ('ex
, 'fb
, 'en
, 'hi
) expression_tree
580 (** Expression tree literal. Expression trees are not evaluated at
581 runtime, but desugared to an expression representing the code.
584 Foo`$x ==> $x * ${$value}` // splicing $value *)
585 | Lplaceholder
of pos
586 (** Placeholder local variable.
590 (** Global function reference.
593 | Method_id
of ('ex
, 'fb
, 'en
, 'hi
) expr
* pstring
594 (** Instance method reference on a specific instance.
596 TODO: This is only created in naming, and ought to happen in
597 lowering or be removed. The emitter just sees a normal Call.
599 inst_meth($f, 'some_meth') // equivalent: $f->some_meth<> *)
600 | Method_caller
of sid
* pstring
601 (** Instance method reference that can be called with an instance.
603 meth_caller(FooClass::class, 'some_meth')
604 meth_caller('FooClass', 'some_meth')
606 These examples are equivalent to:
608 (FooClass $f, ...$args) ==> $f->some_meth(...$args) *)
609 | Smethod_id
of ('ex
, 'fb
, 'en
, 'hi
) class_id
* pstring
610 (** Static method reference.
612 class_meth('FooClass', 'some_static_meth')
613 // equivalent: FooClass::some_static_meth<> *)
615 ('hi targ
* 'hi targ
) option
616 * ('ex
, 'fb
, 'en
, 'hi
) expr
617 * ('ex
, 'fb
, 'en
, 'hi
) expr
621 | ET_Splice
of ('ex
, 'fb
, 'en
, 'hi
) expr
622 (** Expression tree splice expression. Only valid inside an
623 expression tree literal (backticks).
626 | EnumClassLabel
of sid
option * string
627 (** Label used for enum classes.
629 enum_name#label_name or #label_name *)
630 | Hole
of ('ex
, 'fb
, 'en
, 'hi
) expr
* 'hi
* 'hi
* hole_source
631 (** Annotation used to record failure in subtyping or coercion of an
632 expression and calls to [unsafe_cast] or [enforced_cast].
634 The [hole_source] indicates whether this came from an
635 explicit call to [unsafe_cast] or [enforced_cast] or was
636 generated during typing.
638 Given a call to [unsafe_cast]:
640 function f(int $x): void { /* ... */ }
642 function g(float $x): void {
643 f(unsafe_cast<float,int>($x));
646 After typing, this is represented by the following TAST fragment
649 ( ( (..., function(int $x): void), Id (..., "\f"))
653 ( ((..., float), Lvar (..., $x))
665 and ('ex
, 'fb
, 'en
, 'hi
) class_get_expr
=
666 | CGstring
of pstring
667 | CGexpr
of ('ex
, 'fb
, 'en
, 'hi
) expr
669 and ('ex
, 'fb
, 'en
, 'hi
) case
=
670 | Default
of pos
* ('ex
, 'fb
, 'en
, 'hi
) block
671 | Case
of ('ex
, 'fb
, 'en
, 'hi
) expr
* ('ex
, 'fb
, 'en
, 'hi
) block
673 and ('ex
, 'fb
, 'en
, 'hi
) catch
= sid
* lid
* ('ex
, 'fb
, 'en
, 'hi
) block
675 and ('ex
, 'fb
, 'en
, 'hi
) field
=
676 ('ex
, 'fb
, 'en
, 'hi
) expr
* ('ex
, 'fb
, 'en
, 'hi
) expr
678 and ('ex
, 'fb
, 'en
, 'hi
) afield
=
679 | AFvalue
of ('ex
, 'fb
, 'en
, 'hi
) expr
680 | AFkvalue
of ('ex
, 'fb
, 'en
, 'hi
) expr
* ('ex
, 'fb
, 'en
, 'hi
) expr
682 and ('ex
, 'fb
, 'en
, 'hi
) xhp_simple
= {
685 xs_expr
: ('ex
, 'fb
, 'en
, 'hi
) expr
;
688 and ('ex
, 'fb
, 'en
, 'hi
) xhp_attribute
=
689 | Xhp_simple
of ('ex
, 'fb
, 'en
, 'hi
) xhp_simple
690 | Xhp_spread
of ('ex
, 'fb
, 'en
, 'hi
) expr
692 and is_variadic
= bool
694 and ('ex
, 'fb
, 'en
, 'hi
) fun_param
= {
695 param_annotation
: 'ex
;
696 param_type_hint
: 'hi type_hint
;
697 param_is_variadic
: is_variadic
;
700 param_expr
: ('ex
, 'fb
, 'en
, 'hi
) expr
option;
701 param_readonly
: Ast_defs.readonly_kind
option;
702 param_callconv
: Ast_defs.param_kind
option;
703 param_user_attributes
: ('ex
, 'fb
, 'en
, 'hi
) user_attribute list
;
704 param_visibility
: visibility
option;
707 (** Does this function/method take a variable number of arguments? *)
708 and ('ex
, 'fb
, 'en
, 'hi
) fun_variadicity
=
709 | FVvariadicArg
of ('ex
, 'fb
, 'en
, 'hi
) fun_param
710 (** Named variadic argument.
712 function foo(int ...$args): void {} *)
714 (** Unnamed variaidic argument. Partial mode only.
716 function foo(...): void {} *)
718 (** Function is not variadic, takes an exact number of arguments. *)
720 and ('ex
, 'fb
, 'en
, 'hi
) fun_
= {
722 f_readonly_this
: Ast_defs.readonly_kind
option;
724 f_readonly_ret
: Ast_defs.readonly_kind
option;
725 (* Whether the return value is readonly *)
726 f_ret
: 'hi type_hint
;
728 f_tparams
: ('ex
, 'fb
, 'en
, 'hi
) tparam list
;
729 f_where_constraints
: where_constraint_hint list
;
730 f_variadic
: ('ex
, 'fb
, 'en
, 'hi
) fun_variadicity
;
731 f_params
: ('ex
, 'fb
, 'en
, 'hi
) fun_param list
;
732 f_ctxs
: contexts
option;
733 f_unsafe_ctxs
: contexts
option;
734 f_body
: ('ex
, 'fb
, 'en
, 'hi
) func_body
;
735 f_fun_kind
: Ast_defs.fun_kind
;
736 f_user_attributes
: ('ex
, 'fb
, 'en
, 'hi
) user_attribute list
;
738 (** true if this declaration has no body because it is an
739 external function declaration (e.g. from an HHI file)*)
740 f_doc_comment
: doc_comment
option;
744 * Naming has two phases and the annotation helps to indicate the phase.
745 * In the first pass, it will perform naming on everything except for function
746 * and method bodies and collect information needed. Then, another round of
747 * naming is performed where function bodies are named. Thus, naming will
748 * have named and unnamed variants of the annotation.
749 * See BodyNamingAnnotation in nast.ml and the comment in naming.ml
751 and ('ex
, 'fb
, 'en
, 'hi
) func_body
= {
752 fb_ast
: ('ex
, 'fb
, 'en
, 'hi
) block
;
756 (** A type annotation is two things:
757 - the localized hint, or if the hint is missing, the inferred type
758 - The typehint associated to this expression if it exists *)
759 and 'hi type_hint
= 'hi
* type_hint_
761 (** Explicit type argument to function, constructor, or collection literal.
763 * 'hi = Typing_defs.(locl ty) in TAST,
764 * and is used to record inferred type arguments, with wildcard hint.
766 and 'hi targ
= 'hi
* hint
768 and type_hint_
= hint
option
770 and ('ex
, 'fb
, 'en
, 'hi
) user_attribute
= {
772 ua_params
: ('ex
, 'fb
, 'en
, 'hi
) expr list
;
773 (** user attributes are restricted to scalar values *)
776 and ('ex
, 'fb
, 'en
, 'hi
) file_attribute
= {
777 fa_user_attributes
: ('ex
, 'fb
, 'en
, 'hi
) user_attribute list
;
781 and ('ex
, 'fb
, 'en
, 'hi
) tparam
= {
782 tp_variance
: Ast_defs.variance
;
784 tp_parameters
: ('ex
, 'fb
, 'en
, 'hi
) tparam list
;
785 tp_constraints
: (Ast_defs.constraint_kind
* hint
) list
;
786 tp_reified
: reify_kind
;
787 tp_user_attributes
: ('ex
, 'fb
, 'en
, 'hi
) user_attribute list
;
790 and use_as_alias
= sid
option * pstring
* sid
option * use_as_visibility list
792 and insteadof_alias
= sid
* pstring
* sid list
794 and is_extends
= bool
797 (* For globally defined type, the ID used in the .main function. *)
799 (* Closures are hoisted to classes, but they don't get an entry in .main. *)
802 and ('ex
, 'fb
, 'en
, 'hi
) class_
= {
805 c_mode
: FileInfo.mode
; [@visitors
.opaque
]
808 c_has_xhp_keyword
: bool;
809 c_kind
: Ast_defs.class_kind
;
811 c_tparams
: ('ex
, 'fb
, 'en
, 'hi
) tparam list
;
812 (** The type parameters of a class A<T> (T is the parameter) *)
813 c_extends
: class_hint list
;
814 c_uses
: trait_hint list
;
815 c_use_as_alias
: use_as_alias list
;
816 (** PHP feature not supported in hack but required
817 because we have runtime support. *)
818 c_insteadof_alias
: insteadof_alias list
;
819 (** PHP feature not supported in hack but required
820 because we have runtime support. *)
821 c_xhp_attr_uses
: xhp_attr_hint list
;
822 c_xhp_category
: (pos
* pstring list
) option;
823 c_reqs
: (class_hint
* is_extends
) list
;
824 c_implements
: class_hint list
;
825 c_support_dynamic_type
: bool;
826 c_where_constraints
: where_constraint_hint list
;
827 c_consts
: ('ex
, 'fb
, 'en
, 'hi
) class_const list
;
828 c_typeconsts
: ('ex
, 'fb
, 'en
, 'hi
) class_typeconst_def list
;
829 c_vars
: ('ex
, 'fb
, 'en
, 'hi
) class_var list
;
830 c_methods
: ('ex
, 'fb
, 'en
, 'hi
) method_ list
;
831 c_attributes
: ('ex
, 'fb
, 'en
, 'hi
) class_attr list
;
832 c_xhp_children
: (pos
* xhp_child
) list
;
833 c_xhp_attrs
: ('ex
, 'fb
, 'en
, 'hi
) xhp_attr list
;
835 c_user_attributes
: ('ex
, 'fb
, 'en
, 'hi
) user_attribute list
;
836 c_file_attributes
: ('ex
, 'fb
, 'en
, 'hi
) file_attribute list
;
837 c_enum
: enum_
option;
838 c_doc_comment
: doc_comment
option;
839 c_emit_id
: emit_id
option;
842 and class_hint
= hint
844 and trait_hint
= hint
846 and xhp_attr_hint
= hint
852 and ('ex
, 'fb
, 'en
, 'hi
) xhp_attr
=
854 * ('ex
, 'fb
, 'en
, 'hi
) class_var
855 * xhp_attr_tag
option
856 * (pos
* ('ex
, 'fb
, 'en
, 'hi
) expr list
) option
858 and ('ex
, 'fb
, 'en
, 'hi
) class_attr
=
860 | CA_field
of ('ex
, 'fb
, 'en
, 'hi
) ca_field
862 and ('ex
, 'fb
, 'en
, 'hi
) ca_field
= {
865 ca_value
: ('ex
, 'fb
, 'en
, 'hi
) expr
option;
871 | CA_enum
of string list
873 and ('ex
, 'fb
, 'en
, 'hi
) class_const
= {
874 cc_type
: hint
option;
876 cc_expr
: ('ex
, 'fb
, 'en
, 'hi
) expr
option;
877 (** expr = None indicates an abstract const *)
878 cc_doc_comment
: doc_comment
option;
881 (** This represents a type const definition. If a type const is abstract then
882 * then the type hint acts as a constraint. Any concrete definition of the
883 * type const must satisfy the constraint.
885 * If the type const is not abstract then a type must be specified.
888 and class_abstract_typeconst
= {
889 c_atc_as_constraint
: hint
option;
890 c_atc_super_constraint
: hint
option;
891 c_atc_default
: hint
option;
894 and class_concrete_typeconst
= { c_tc_type
: hint
}
896 (* A partially abstract type constant always has a constraint *
897 * and always has a value. *)
898 and class_partially_abstract_typeconst
= {
899 c_patc_constraint
: hint
;
903 and class_typeconst
=
904 | TCAbstract
of class_abstract_typeconst
905 | TCConcrete
of class_concrete_typeconst
906 | TCPartiallyAbstract
of class_partially_abstract_typeconst
908 and ('ex
, 'fb
, 'en
, 'hi
) class_typeconst_def
= {
909 c_tconst_user_attributes
: ('ex
, 'fb
, 'en
, 'hi
) user_attribute list
;
911 c_tconst_kind
: class_typeconst
;
913 c_tconst_doc_comment
: doc_comment
option;
914 c_tconst_is_ctx
: bool;
917 and xhp_attr_info
= {
918 xai_tag
: xhp_attr_tag
option;
919 xai_enum_values
: Ast_defs.xhp_enum_value list
;
922 and ('ex
, 'fb
, 'en
, 'hi
) class_var
= {
924 cv_xhp_attr
: xhp_attr_info
option;
927 cv_visibility
: visibility
;
928 cv_type
: 'hi type_hint
;
930 cv_expr
: ('ex
, 'fb
, 'en
, 'hi
) expr
option;
931 cv_user_attributes
: ('ex
, 'fb
, 'en
, 'hi
) user_attribute list
;
932 cv_doc_comment
: doc_comment
option;
933 cv_is_promoted_variadic
: bool;
938 and ('ex
, 'fb
, 'en
, 'hi
) method_
= {
944 m_readonly_this
: bool;
945 m_visibility
: visibility
;
947 m_tparams
: ('ex
, 'fb
, 'en
, 'hi
) tparam list
;
948 m_where_constraints
: where_constraint_hint list
;
949 m_variadic
: ('ex
, 'fb
, 'en
, 'hi
) fun_variadicity
;
950 m_params
: ('ex
, 'fb
, 'en
, 'hi
) fun_param list
;
951 m_ctxs
: contexts
option;
952 m_unsafe_ctxs
: contexts
option;
953 m_body
: ('ex
, 'fb
, 'en
, 'hi
) func_body
;
954 m_fun_kind
: Ast_defs.fun_kind
;
955 m_user_attributes
: ('ex
, 'fb
, 'en
, 'hi
) user_attribute list
;
956 m_readonly_ret
: Ast_defs.readonly_kind
option;
957 m_ret
: 'hi type_hint
;
959 (** true if this declaration has no body because it is an external method
960 declaration (e.g. from an HHI file) *)
961 m_doc_comment
: doc_comment
option;
964 and nsenv
= (Namespace_env.env
[@visitors
.opaque
])
966 and ('ex
, 'fb
, 'en
, 'hi
) typedef
= {
969 t_tparams
: ('ex
, 'fb
, 'en
, 'hi
) tparam list
;
970 t_constraint
: hint
option;
972 t_user_attributes
: ('ex
, 'fb
, 'en
, 'hi
) user_attribute list
;
973 t_mode
: FileInfo.mode
; [@visitors
.opaque
]
974 t_vis
: typedef_visibility
;
977 t_emit_id
: emit_id
option;
980 and ('ex
, 'fb
, 'en
, 'hi
) gconst
= {
982 cst_mode
: FileInfo.mode
; [@visitors
.opaque
]
984 cst_type
: hint
option;
985 cst_value
: ('ex
, 'fb
, 'en
, 'hi
) expr
;
986 cst_namespace
: nsenv
;
988 cst_emit_id
: emit_id
option;
991 and ('ex
, 'fb
, 'en
, 'hi
) record_def
= {
994 rd_extends
: record_hint
option;
996 rd_fields
: (sid
* hint
* ('ex
, 'fb
, 'en
, 'hi
) expr
option) list
;
997 rd_user_attributes
: ('ex
, 'fb
, 'en
, 'hi
) user_attribute list
;
1000 rd_doc_comment
: doc_comment
option;
1001 rd_emit_id
: emit_id
option;
1004 and record_hint
= hint
1006 and ('ex
, 'fb
, 'en
, 'hi
) fun_def
= {
1007 fd_namespace
: nsenv
;
1008 fd_file_attributes
: ('ex
, 'fb
, 'en
, 'hi
) file_attribute list
;
1009 fd_mode
: FileInfo.mode
; [@visitors
.opaque
]
1010 fd_fun
: ('ex
, 'fb
, 'en
, 'hi
) fun_
;
1013 and ('ex
, 'fb
, 'en
, 'hi
) def
=
1014 | Fun
of ('ex
, 'fb
, 'en
, 'hi
) fun_def
1015 | Class
of ('ex
, 'fb
, 'en
, 'hi
) class_
1016 | RecordDef
of ('ex
, 'fb
, 'en
, 'hi
) record_def
1017 | Stmt
of ('ex
, 'fb
, 'en
, 'hi
) stmt
1018 | Typedef
of ('ex
, 'fb
, 'en
, 'hi
) typedef
1019 | Constant
of ('ex
, 'fb
, 'en
, 'hi
) gconst
1020 | Namespace
of sid
* ('ex
, 'fb
, 'en
, 'hi
) program
1021 | NamespaceUse
of (ns_kind
* sid
* sid
) list
1022 | SetNamespaceEnv
of nsenv
1023 | FileAttributes
of ('ex
, 'fb
, 'en
, 'hi
) file_attribute
1028 | NSClassAndNamespace
1037 and doc_comment
= (Doc_comment.t
[@visitors
.opaque
])
1039 let is_erased = function
1045 let is_reified = function
1051 let is_soft_reified = function
1052 | SoftReified
-> true
1057 (* Splits the methods on a class into the constructor, statics, dynamics *)
1060 * Methods, properties, and requirements are order dependent in bytecode
1061 * emission, which is observable in user code via `ReflectionClass`.
1063 let split_methods class_
=
1064 let (constr
, statics
, res
) =
1066 (fun (constr
, statics
, rest
) m
->
1067 if snd m
.m_name
= "__construct" then
1068 (Some m
, statics
, rest
)
1069 else if m
.m_static
then
1070 (constr
, m
:: statics
, rest
)
1072 (constr
, statics
, m
:: rest
))
1076 (constr
, List.rev statics
, List.rev res
)
1078 (* Splits class properties into statics, dynamics *)
1079 let split_vars class_
=
1080 let (statics
, res
) =
1082 (fun (statics
, rest
) v
->
1083 if v
.cv_is_static
then
1084 (v
:: statics
, rest
)
1086 (statics
, v
:: rest
))
1090 (List.rev statics
, List.rev res
)
1092 (* Splits `require`s into extends, implements *)
1093 let split_reqs class_
=
1094 let (extends
, implements
) =
1096 (fun (extends
, implements
) (h
, is_extends
) ->
1098 (h
:: extends
, implements
)
1100 (extends
, h
:: implements
))
1104 (List.rev extends
, List.rev implements
)
1106 type break_continue_level
=
1107 | Level_ok
of int option
1109 | Level_non_positive
1111 let get_break_continue_level level_opt
=
1112 match level_opt
with
1114 let i = int_of_string s
in
1119 | _
-> Level_non_literal
1120 | exception _
-> Level_non_literal
1122 (* extract the hint from a type annotation *)
1123 let hint_of_type_hint : 'hi
. 'hi type_hint
-> type_hint_
= snd
1125 (* extract the type from a type annotation *)
1126 let type_of_type_hint : 'hi
. 'hi type_hint
-> 'hi
= fst
1128 (* map a function over the second part of a type annotation *)
1129 let type_hint_option_map ~f ta
=
1131 match hint_of_type_hint ta
with
1132 | Some hint
-> Some
(f hint
)
1135 (type_of_type_hint ta
, mapped_hint)
1137 (* helper function to access the list of enums included by an enum *)
1138 let enum_includes_map ?
(default
= []) ~f includes
=
1141 | Some includes
-> f includes
1143 let is_enum_class c
=
1144 match (c
.c_kind
, c
.c_enum
) with
1145 | (Ast_defs.Cenum
, Some enum_
) -> enum_
.e_enum_class