AAST cleanup: Remove the Any node
[hiphop-php.git] / hphp / hack / src / annotated_ast / aast.ml
blobeddefbed246ca8e1afc19d561153a87f14c1e177
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 *)
10 include Aast_defs
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
24 [@@deriving
25 show { with_path = false },
26 eq,
27 visitors
29 variety = "iter";
30 nude = true;
31 visit_prefix = "on_";
32 ancestors = ["iter_defs"];
34 visitors
36 variety = "reduce";
37 nude = true;
38 visit_prefix = "on_";
39 ancestors = ["reduce_defs"];
41 visitors
43 variety = "map";
44 nude = true;
45 visit_prefix = "on_";
46 ancestors = ["map_defs"];
48 visitors
50 variety = "endo";
51 nude = true;
52 visit_prefix = "on_";
53 ancestors = ["endo_defs"];
56 and ('ex, 'fb, 'en, 'hi) stmt = pos * ('ex, 'fb, 'en, 'hi) stmt_
58 and ('ex, 'fb, 'en, 'hi) stmt_ =
59 | Fallthrough
60 (** Marker for a switch statement that falls through.
62 // FALLTHROUGH *)
63 | Expr of ('ex, 'fb, 'en, 'hi) expr
64 (** Standalone expression.
66 1 + 2; *)
67 | Break
68 (** Break inside a loop or switch statement.
70 break; *)
71 | Continue
72 (** Continue inside a loop or switch statement.
74 continue; *)
75 | Throw of ('ex, 'fb, 'en, 'hi) expr
76 (** Throw an exception.
78 throw $foo; *)
79 | Return of ('ex, 'fb, 'en, 'hi) expr option
80 (** Return, with an optional value.
82 return;
83 return $foo; *)
84 | Yield_break
85 (** Yield break, terminating the current generator. This behaves like
86 return; but is more explicit, and ensures the function is treated
87 as a generator.
89 yield break; *)
90 | Awaitall of
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; }
103 concurrent {
104 $foo = await f();
105 $bar = await g();
106 await h();
107 } *)
108 | If of
109 ('ex, 'fb, 'en, 'hi) expr
110 * ('ex, 'fb, 'en, 'hi) block
111 * ('ex, 'fb, 'en, 'hi) block
112 (** If statement.
114 if ($foo) { ... } else { ... } *)
115 | Do of ('ex, 'fb, 'en, 'hi) block * ('ex, 'fb, 'en, 'hi) expr
116 (** Do-while loop.
118 do {
119 bar();
120 } while($foo) *)
121 | While of ('ex, 'fb, 'en, 'hi) expr * ('ex, 'fb, 'en, 'hi) block
122 (** While loop.
124 while ($foo) {
125 bar();
126 } *)
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 *)
132 | For of
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
139 optional.
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.
146 switch ($foo) {
147 case X:
148 bar();
149 break;
150 default:
151 baz();
152 break;
153 } *)
154 | Foreach of
155 ('ex, 'fb, 'en, 'hi) expr
156 * ('ex, 'fb, 'en, 'hi) as_expr
157 * ('ex, 'fb, 'en, 'hi) block
158 (** For-each loop.
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<_> *)
164 | Try of
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.
170 try {
171 foo();
172 } catch (SomeException $e) {
173 bar();
174 } finally {
175 baz();
176 } *)
177 | Noop
178 (** No-op, the empty statement.
181 while (true) ;
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.
186 { $foo = 42; } *)
187 | Markup of pstring
188 (** The mode tag at the beginning of a file.
189 TODO: this really belongs in def.
191 <?hh *)
192 | AssertEnv of env_annot * 'ex local_id_map
193 (** Used in IFC to track type inference environments. Not user
194 denotable. *)
196 and env_annot =
197 | Join
198 | Refinement
200 and ('ex, 'fb, 'en, 'hi) using_stmt = {
201 us_is_block_scoped: bool;
202 us_has_await: 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_ =
219 | CIparent
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.
224 parent::some_meth()
225 parent::$prop = 1;
226 new parent(); *)
227 | CIself
228 (** The class ID of the lexically scoped class.
230 In a trait, it is the class ID of the using class.
232 self::some_meth()
233 self::$prop = 1;
234 new self(); *)
235 | CIstatic
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.
242 static::some_meth()
243 static::$prop = 1;
244 new static(); *)
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.
252 $d::some_meth();
253 $d::$prop = 1;
254 new $d(); *)
255 | CI of sid
256 (** Explicit class name. This is the common case.
258 Foop::some_meth()
259 Foo::$prop = 1;
260 new Foo(); *)
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 =
269 | FP_id of sid
270 | FP_class_const of ('ex, 'fb, 'en, 'hi) class_id * pstring
272 and ('ex, 'fb, 'en, 'hi) expression_tree = {
273 et_hint: hint;
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_ =
280 | Darray of
281 ('hi targ * 'hi targ) option
282 * (('ex, 'fb, 'en, 'hi) expr * ('ex, 'fb, 'en, 'hi) expr) list
283 (** darray literal.
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
288 (** varray literal.
290 varray['hello', 'world']
291 varray<string>['hello', 'world'] *)
292 | Shape of (Ast_defs.shape_field_name * ('ex, 'fb, 'en, 'hi) expr) list
293 (** Shape literal.
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.
299 Vector {1, 2}
300 ImmVector {}
301 Set<string> {'foo', 'bar'}
302 vec[1, 2]
303 keyset[] *)
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]
309 Map<int, string> {}
310 ImmMap {} *)
311 | Null
312 (** Null literal.
314 null *)
315 | This
316 (** The local variable representing the current class instance.
318 $this *)
319 | True
320 (** Boolean literal.
322 true *)
323 | False
324 (** Boolean literal.
326 false *)
327 | Omitted
328 (** The empty expression.
330 list(, $y) = vec[1, 2] // Omitted is the first expression inside list() *)
331 | Id of sid
332 (** An identifier. Used for method names and global constants.
334 SOME_CONST
335 $x->foo() // id: "foo" *)
336 | Lvar of lid
337 (** Local variable.
339 $foo *)
340 | Dollardollar of lid
341 (** The extra variable in a pipe expression.
343 $$ *)
344 | Clone of ('ex, 'fb, 'en, 'hi) expr
345 (** Clone expression.
347 clone $foo *)
348 | Array_get of ('ex, 'fb, 'en, 'hi) expr * ('ex, 'fb, 'en, 'hi) expr option
349 (** Array indexing.
351 $foo[]
352 $foo[$bar] *)
353 | Obj_get of
354 ('ex, 'fb, 'en, 'hi) expr
355 * ('ex, 'fb, 'en, 'hi) expr
356 * og_null_flavor
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 *)
365 | Class_get of
366 ('ex, 'fb, 'en, 'hi) class_id
367 * ('ex, 'fb, 'en, 'hi) class_get_expr
368 * (* is_prop_call *) bool
369 (** Static property access.
371 Foo::$bar
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
377 method call.
379 This is not ambiguous, because constants are not allowed to
380 contain functions.
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() *)
390 | Call of
391 (* function *)
392 ('ex, 'fb, 'en, 'hi) expr
393 * (* explicit type annotations *)
394 'hi targ list
395 * (* positional args *)
396 ('ex, 'fb, 'en, 'hi) expr list
397 * (* unpacked arg *)
398 ('ex, 'fb, 'en, 'hi) expr option
399 (** Function or method call.
401 foo()
402 $x()
403 foo<int>(1, 2, ...$rest)
404 $x->foo()
406 async { return 1; }
407 // lowered to:
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.
412 foo_fun<>
413 FooCls::meth<int> *)
414 | Int of string
415 (** Integer literal.
418 0123 // octal
419 0xBEEF // hexadecimal
420 0b11111111 // binary *)
421 | Float of string
422 (** Float literal.
425 1.2e3
426 7E-10 *)
427 | String of byte_string
428 (** String literal.
430 "foo"
431 'foo'
433 <<<DOC
437 <<<'DOC'
439 DOC *)
440 | String2 of ('ex, 'fb, 'en, 'hi) expr list
441 (** Interpolated string literal.
443 "hello $foo $bar"
445 <<<DOC
446 hello $foo $bar
447 DOC *)
448 | PrefixedString of string * ('ex, 'fb, 'en, 'hi) expr
449 (** Prefixed string literal. Only used for regular expressions.
451 re"foo" *)
452 | Yield of ('ex, 'fb, 'en, 'hi) afield
453 (** Yield expression. The enclosing function should have an Iterator
454 return type.
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.
461 await $foo *)
462 | ReadonlyExpr of ('ex, 'fb, 'en, 'hi) expr
463 (** Readonly expression.
465 readonly $foo *)
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.
482 (int)$foo
483 (string)$foo *)
484 | Unop of Ast_defs.uop * ('ex, 'fb, 'en, 'hi) expr
485 (** Unary operator.
487 !$foo
488 -$foo
489 +$foo *)
490 | Binop of
491 Ast_defs.bop * ('ex, 'fb, 'en, 'hi) expr * ('ex, 'fb, 'en, 'hi) expr
492 (** Binary operator.
494 $foo + $bar *)
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) *)
503 | Eif of
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
512 (** Is operator.
514 $foo is SomeType *)
515 | As of ('ex, 'fb, 'en, 'hi) expr * hint * (* is nullable *) bool
516 (** As operator.
518 $foo as int
519 $foo ?as int *)
520 | New of
521 ('ex, 'fb, 'en, 'hi) class_id
522 * 'hi targ list
523 * ('ex, 'fb, 'en, 'hi) expr list
524 * ('ex, 'fb, 'en, 'hi) expr option
525 * (* constructor *)
527 (** Instantiation.
529 new Foo(1, 2);
530 new Foo<int, T>();
531 new Foo('blah', ...$rest); *)
532 | Record of sid * (('ex, 'fb, 'en, 'hi) expr * ('ex, 'fb, 'en, 'hi) expr) list
533 (** Record literal.
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
538 specified.
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.
549 $x ==> $x
550 (int $x): int ==> $x + $other
551 ($x, $y) ==> { return $x + $y; } *)
552 | Xml of
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.
564 foo(inout $x[0]) *)
565 | Import of import_flavor * ('ex, 'fb, 'en, 'hi) expr
566 (** Include or require expression.
568 require('foo.php')
569 require_once('foo.php')
570 include('foo.php')
571 include_once('foo.php') *)
572 | Collection of
573 sid * 'hi collection_targ option * ('ex, 'fb, 'en, 'hi) afield list
574 (** Collection literal.
576 TODO: T38184446 this is redundant with ValCollection/KeyValCollection.
578 Vector {} *)
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.
583 Foo`1 + bar()`
584 Foo`$x ==> $x * ${$value}` // splicing $value *)
585 | Lplaceholder of pos
586 (** Placeholder local variable.
588 $_ *)
589 | Fun_id of sid
590 (** Global function reference.
592 fun('foo') *)
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<> *)
614 | Pair of
615 ('hi targ * 'hi targ) option
616 * ('ex, 'fb, 'en, 'hi) expr
617 * ('ex, 'fb, 'en, 'hi) expr
618 (** Pair literal.
620 Pair {$foo, $bar} *)
621 | ET_Splice of ('ex, 'fb, 'en, 'hi) expr
622 (** Expression tree splice expression. Only valid inside an
623 expression tree literal (backticks).
625 ${$foo} *)
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
648 Call
649 ( ( (..., function(int $x): void), Id (..., "\f"))
650 , []
651 , [ ( (..., int)
652 , Hole
653 ( ((..., float), Lvar (..., $x))
654 , float
655 , int
656 , UnsafeCast
660 , None
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 = {
683 xs_name: pstring;
684 xs_type: 'hi;
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;
698 param_pos: pos;
699 param_name: string;
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 {} *)
713 | FVellipsis of pos
714 (** Unnamed variaidic argument. Partial mode only.
716 function foo(...): void {} *)
717 | FVnonVariadic
718 (** Function is not variadic, takes an exact number of arguments. *)
720 and ('ex, 'fb, 'en, 'hi) fun_ = {
721 f_span: pos;
722 f_readonly_this: Ast_defs.readonly_kind option;
723 f_annotation: 'en;
724 f_readonly_ret: Ast_defs.readonly_kind option;
725 (* Whether the return value is readonly *)
726 f_ret: 'hi type_hint;
727 f_name: sid;
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;
737 f_external: bool;
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;
753 fb_annotation: 'fb;
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.
762 * 'hi = unit in NAST
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 = {
771 ua_name: sid;
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;
778 fa_namespace: nsenv;
781 and ('ex, 'fb, 'en, 'hi) tparam = {
782 tp_variance: Ast_defs.variance;
783 tp_name: sid;
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
796 and emit_id =
797 (* For globally defined type, the ID used in the .main function. *)
798 | Emit_id of int
799 (* Closures are hoisted to classes, but they don't get an entry in .main. *)
800 | Anonymous
802 and ('ex, 'fb, 'en, 'hi) class_ = {
803 c_span: pos;
804 c_annotation: 'en;
805 c_mode: FileInfo.mode; [@visitors.opaque]
806 c_final: bool;
807 c_is_xhp: bool;
808 c_has_xhp_keyword: bool;
809 c_kind: Ast_defs.class_kind;
810 c_name: sid;
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;
834 c_namespace: nsenv;
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
848 and xhp_attr_tag =
849 | Required
850 | LateInit
852 and ('ex, 'fb, 'en, 'hi) xhp_attr =
853 'hi type_hint
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 =
859 | CA_name of sid
860 | CA_field of ('ex, 'fb, 'en, 'hi) ca_field
862 and ('ex, 'fb, 'en, 'hi) ca_field = {
863 ca_type: ca_type;
864 ca_id: sid;
865 ca_value: ('ex, 'fb, 'en, 'hi) expr option;
866 ca_required: bool;
869 and ca_type =
870 | CA_hint of hint
871 | CA_enum of string list
873 and ('ex, 'fb, 'en, 'hi) class_const = {
874 cc_type: hint option;
875 cc_id: sid;
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;
900 c_patc_type: 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;
910 c_tconst_name: sid;
911 c_tconst_kind: class_typeconst;
912 c_tconst_span: pos;
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 = {
923 cv_final: bool;
924 cv_xhp_attr: xhp_attr_info option;
925 cv_abstract: bool;
926 cv_readonly: bool;
927 cv_visibility: visibility;
928 cv_type: 'hi type_hint;
929 cv_id: sid;
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;
934 cv_is_static: bool;
935 cv_span: pos;
938 and ('ex, 'fb, 'en, 'hi) method_ = {
939 m_span: pos;
940 m_annotation: 'en;
941 m_final: bool;
942 m_abstract: bool;
943 m_static: bool;
944 m_readonly_this: bool;
945 m_visibility: visibility;
946 m_name: sid;
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;
958 m_external: bool;
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 = {
967 t_annotation: 'en;
968 t_name: sid;
969 t_tparams: ('ex, 'fb, 'en, 'hi) tparam list;
970 t_constraint: hint option;
971 t_kind: hint;
972 t_user_attributes: ('ex, 'fb, 'en, 'hi) user_attribute list;
973 t_mode: FileInfo.mode; [@visitors.opaque]
974 t_vis: typedef_visibility;
975 t_namespace: nsenv;
976 t_span: pos;
977 t_emit_id: emit_id option;
980 and ('ex, 'fb, 'en, 'hi) gconst = {
981 cst_annotation: 'en;
982 cst_mode: FileInfo.mode; [@visitors.opaque]
983 cst_name: sid;
984 cst_type: hint option;
985 cst_value: ('ex, 'fb, 'en, 'hi) expr;
986 cst_namespace: nsenv;
987 cst_span: pos;
988 cst_emit_id: emit_id option;
991 and ('ex, 'fb, 'en, 'hi) record_def = {
992 rd_annotation: 'en;
993 rd_name: sid;
994 rd_extends: record_hint option;
995 rd_abstract: bool;
996 rd_fields: (sid * hint * ('ex, 'fb, 'en, 'hi) expr option) list;
997 rd_user_attributes: ('ex, 'fb, 'en, 'hi) user_attribute list;
998 rd_namespace: nsenv;
999 rd_span: pos;
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
1025 and ns_kind =
1026 | NSNamespace
1027 | NSClass
1028 | NSClassAndNamespace
1029 | NSFun
1030 | NSConst
1032 and hole_source =
1033 | Typing
1034 | UnsafeCast
1035 | EnforcedCast
1037 and doc_comment = (Doc_comment.t[@visitors.opaque])
1039 let is_erased = function
1040 | Erased -> true
1041 | SoftReified
1042 | Reified ->
1043 false
1045 let is_reified = function
1046 | Reified -> true
1047 | Erased
1048 | SoftReified ->
1049 false
1051 let is_soft_reified = function
1052 | SoftReified -> true
1053 | Erased
1054 | Reified ->
1055 false
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) =
1065 List.fold_left
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)
1071 else
1072 (constr, statics, m :: rest))
1073 (None, [], [])
1074 class_.c_methods
1076 (constr, List.rev statics, List.rev res)
1078 (* Splits class properties into statics, dynamics *)
1079 let split_vars class_ =
1080 let (statics, res) =
1081 List.fold_left
1082 (fun (statics, rest) v ->
1083 if v.cv_is_static then
1084 (v :: statics, rest)
1085 else
1086 (statics, v :: rest))
1087 ([], [])
1088 class_.c_vars
1090 (List.rev statics, List.rev res)
1092 (* Splits `require`s into extends, implements *)
1093 let split_reqs class_ =
1094 let (extends, implements) =
1095 List.fold_left
1096 (fun (extends, implements) (h, is_extends) ->
1097 if is_extends then
1098 (h :: extends, implements)
1099 else
1100 (extends, h :: implements))
1101 ([], [])
1102 class_.c_reqs
1104 (List.rev extends, List.rev implements)
1106 type break_continue_level =
1107 | Level_ok of int option
1108 | Level_non_literal
1109 | Level_non_positive
1111 let get_break_continue_level level_opt =
1112 match level_opt with
1113 | (_, Int s) ->
1114 let i = int_of_string s in
1115 if i <= 0 then
1116 Level_non_positive
1117 else
1118 Level_ok (Some i)
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 =
1130 let mapped_hint =
1131 match hint_of_type_hint ta with
1132 | Some hint -> Some (f hint)
1133 | None -> None
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 =
1139 match includes with
1140 | None -> default
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
1146 | (_, _) -> false