Allow to interleave visibility and function modifiers
[hiphop-php.git] / hphp / hack / src / parser / coroutine / coroutine_syntax.ml
blobf4235639abf715facf9400f5d56d8ad14cf86611
1 (**
2 * Copyright (c) 2017, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the "hack" directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
8 *)
10 (**
11 * Contains syntaxes used in coroutine code generation.
14 module Syntax = Full_fidelity_editable_positioned_syntax
15 module Token = Syntax.Token
16 module TokenKind = Full_fidelity_token_kind
17 module SourceText = Full_fidelity_source_text
19 open Syntax
21 let make_list = make_list SourceText.empty 0
22 let make_missing () = make_missing SourceText.empty 0
23 let from_children = from_children SourceText.empty 0
25 (* Common factories *)
27 let make_syntax syntax =
28 (* TODO(tingley): When possible, we should synthesize syntaxes from existing
29 syntaxes, instead of minting a purely synthetic syntax. *)
30 make syntax Value.Synthetic
32 let single_space = " "
34 let make_token_syntax ?text token_kind =
35 let text = Option.value text ~default:(TokenKind.to_string token_kind) in
36 make_syntax @@
37 Token (Token.synthesize_new token_kind text single_space single_space)
39 let make_name_syntax text =
40 make_token_syntax TokenKind.Name ~text
42 let make_variable_syntax text =
43 make_token_syntax TokenKind.Variable ~text
45 let make_variable_expression_syntax text =
46 text
47 |> make_variable_syntax
48 |> make_variable_expression
50 let make_suspend_syntax operand =
51 let token = make_token_syntax TokenKind.Suspend in
52 make_prefix_unary_expression token operand
54 (* General syntaxes *)
56 let left_brace_syntax =
57 make_token_syntax TokenKind.LeftBrace
59 let right_brace_syntax =
60 make_token_syntax TokenKind.RightBrace
62 let left_paren_syntax =
63 make_token_syntax TokenKind.LeftParen
65 let right_paren_syntax =
66 make_token_syntax TokenKind.RightParen
68 let left_angle_syntax =
69 make_token_syntax TokenKind.LessThan
71 let right_angle_syntax =
72 make_token_syntax TokenKind.GreaterThan
74 let comma_syntax =
75 make_token_syntax TokenKind.Comma
77 let colon_colon_syntax =
78 make_token_syntax TokenKind.ColonColon
80 let lambda_arrow_syntax =
81 make_token_syntax TokenKind.EqualEqualGreaterThan
83 let semicolon_syntax =
84 make_token_syntax TokenKind.Semicolon
86 let colon_syntax =
87 make_token_syntax TokenKind.Colon
89 let assignment_operator_syntax =
90 make_token_syntax TokenKind.Equal
92 let not_syntax =
93 make_token_syntax TokenKind.Exclamation
95 let identical_syntax =
96 make_token_syntax TokenKind.EqualEqual
98 let not_identical_syntax =
99 make_token_syntax TokenKind.ExclamationEqualEqual
101 let nullable_syntax =
102 make_token_syntax TokenKind.Question
104 let mixed_syntax =
105 make_token_syntax TokenKind.Mixed
106 |> make_simple_type_specifier
108 let global_syntax =
109 make_name_syntax "Global"
111 let unit_syntax =
112 make_name_syntax "\\CoroutineUnit"
114 let unit_type_syntax =
115 make_simple_type_specifier unit_syntax
117 let int_syntax =
118 make_token_syntax TokenKind.Int
120 let minus_syntax =
121 make_token_syntax TokenKind.Minus
123 let void_syntax =
124 make_token_syntax TokenKind.Void
126 let null_syntax =
127 make_token_syntax TokenKind.NullLiteral
128 |> make_literal_expression
130 let true_expression_syntax =
131 make_token_syntax TokenKind.BooleanLiteral ~text:"true"
132 |> make_literal_expression
134 let private_syntax =
135 make_token_syntax TokenKind.Private
137 let public_syntax =
138 make_token_syntax TokenKind.Public
140 let final_syntax =
141 make_token_syntax TokenKind.Final
143 let static_syntax =
144 make_token_syntax TokenKind.Static
146 let try_keyword_syntax =
147 make_token_syntax TokenKind.Try
149 let finally_keyword_syntax =
150 make_token_syntax TokenKind.Finally
152 let if_keyword_syntax =
153 make_token_syntax TokenKind.If
155 let else_keyword_syntax =
156 make_token_syntax TokenKind.Else
158 let while_keyword_syntax =
159 make_token_syntax TokenKind.While
161 let switch_keyword_syntax =
162 make_token_syntax TokenKind.Switch
164 let case_keyword_syntax =
165 make_token_syntax TokenKind.Case
167 let class_keyword_syntax =
168 make_token_syntax TokenKind.Class
170 let default_keyword_syntax =
171 make_token_syntax TokenKind.Default
173 let function_keyword_syntax =
174 make_token_syntax TokenKind.Function
176 let goto_keyword_syntax =
177 make_token_syntax TokenKind.Goto
179 let extends_syntax =
180 make_token_syntax TokenKind.Extends
182 let parent_syntax =
183 make_token_syntax TokenKind.Parent
185 let return_keyword_syntax =
186 make_token_syntax TokenKind.Return
188 let throw_keyword_syntax =
189 make_token_syntax TokenKind.Throw
191 let break_statement_syntax =
192 make_break_statement
193 (make_token_syntax TokenKind.Break)
194 (* break_level *) (make_missing ())
195 semicolon_syntax
197 let new_keyword_syntax =
198 make_token_syntax TokenKind.New
200 let member_selection_syntax =
201 make_token_syntax TokenKind.MinusGreaterThan
203 let this_syntax =
204 make_variable_expression_syntax "$this"
206 let this_type_syntax =
207 make_name_syntax "this"
208 |> make_simple_type_specifier
210 let unset_syntax =
211 make_name_syntax "unset"
213 let exception_type_syntax =
214 make_name_syntax "\\Exception"
215 |> make_simple_type_specifier
217 let constructor_member_name =
218 "__construct"
220 (* Syntax helper functions *)
222 let rec delimit delimit_syntax = function
223 | [] -> []
224 | hd :: [] -> [make_list_item hd (make_missing ())]
225 | hd :: tl -> (make_list_item hd delimit_syntax) :: delimit delimit_syntax tl
227 let make_delimited_list delimit_syntax items =
228 make_list (delimit delimit_syntax items)
230 let make_comma_list items =
231 make_delimited_list comma_syntax items
233 let prepend_to_comma_delimited_syntax_list prepend_syntax syntax_list_syntax =
234 let list_item = make_list_item prepend_syntax comma_syntax in
235 let syntax_list = list_item :: syntax_node_to_list syntax_list_syntax in
236 make_list syntax_list
238 let get_list_item node =
239 match syntax node with
240 | ListItem { list_item; _; } -> list_item
241 | _ -> failwith "get_list_item: Was not a ListItem"
243 let get_function_declaration node =
244 match syntax node with
245 | FunctionDeclaration function_declaration -> function_declaration
246 | _ -> failwith "get_function_declaration: Was not a FunctionDeclaration"
248 let get_lambda_expression node =
249 match syntax node with
250 | LambdaExpression lambda_expression -> lambda_expression
251 | _ -> failwith "get_lambda_expression: Was not a LambdaExpression"
253 let get_anonymous_function node =
254 match syntax node with
255 | AnonymousFunction anonymous_function -> anonymous_function
256 | _ -> failwith "get_anonymous_function: Was not an AnonymousFunction"
258 let get_methodish_declaration node =
259 match syntax node with
260 | MethodishDeclaration methodish_declaration -> methodish_declaration
261 | _ -> failwith "get_methodish_declaration: Was not a MethodishDeclaration"
263 let get_type_parameter node =
264 match syntax node with
265 | TypeParameter type_parameter -> type_parameter
266 | _ -> failwith "get_type_parameter: Was not a TypeParameter"
268 let get_type_parameter_list node =
269 match syntax node with
270 | TypeParameters { type_parameters_parameters; _; } ->
271 type_parameters_parameters
272 |> syntax_node_to_list
273 |> Core_list.map ~f:get_list_item
274 | Missing -> []
275 | _ -> failwith "get_type_parameter_list: Was not a TypeParameters"
277 let get_type_arguments node =
278 node
279 |> get_type_parameter_list
280 |> Core_list.map ~f:get_type_parameter
281 |> Core_list.map
282 ~f:(fun { type_name; _; } -> make_simple_type_specifier type_name)
284 let is_static_method { methodish_function_decl_header = header; _; } =
285 match syntax header with
286 | FunctionDeclarationHeader { function_modifiers; _ } ->
287 function_modifiers
288 |> syntax_node_to_list
289 |> Core_list.exists ~f:is_static
290 | _ -> false
292 let string_of_name_token node =
293 match syntax node with
294 | Token ({ Token.kind = TokenKind.Name; _; } as token) -> Token.text token
295 | _ -> failwith "string_of_name_token: Was not a Name Token"
297 let string_of_variable_token node =
298 match syntax node with
299 | Token ({ Token.kind = TokenKind.Variable; _; } as token) -> Token.text token
300 | _ -> failwith "string_of_variable_token: Was not a Variable Token"
302 (* Syntax creation functions *)
304 let make_parenthesized_expression_syntax expression_syntax =
305 make_parenthesized_expression
306 left_paren_syntax
307 expression_syntax
308 right_paren_syntax
310 let make_nullable_type_specifier_syntax type_syntax =
311 make_nullable_type_specifier nullable_syntax type_syntax
313 let make_string_literal_syntax string_literal =
314 make_literal_expression
315 (make_token_syntax
316 TokenKind.DoubleQuotedStringLiteral
317 ~text:(Printf.sprintf "\"%s\"" string_literal))
319 let rec make_int_literal_syntax value =
320 if value < 0 then
321 (* Negative values are parsed as the positive numeric value, wrapped in a
322 unary negation expression. *)
323 make_prefix_unary_expression
324 minus_syntax
325 (make_int_literal_syntax (abs value))
326 else
327 make_literal_expression
328 (make_token_syntax TokenKind.DecimalLiteral ~text:(string_of_int value))
330 let make_qualified_name_syntax name =
331 make_qualified_name_expression (make_name_syntax name)
333 let make_expression_statement_syntax expression_syntax =
334 make_expression_statement expression_syntax semicolon_syntax
336 let make_compound_statement_syntax compound_statements =
337 make_compound_statement
338 left_brace_syntax
339 (make_list compound_statements)
340 right_brace_syntax
342 let make_try_finally_statement_syntax try_compound_statement finally_body =
343 make_try_statement
344 try_keyword_syntax
345 try_compound_statement
346 (make_missing()) (* catches *)
347 (make_finally_clause
348 finally_keyword_syntax
349 finally_body)
351 let make_return_statement_syntax expression_syntax =
352 make_return_statement return_keyword_syntax expression_syntax semicolon_syntax
354 let make_return_missing_statement_syntax =
355 make_return_statement_syntax (make_missing())
357 let make_throw_statement_syntax expression_syntax =
358 make_throw_statement throw_keyword_syntax expression_syntax semicolon_syntax
360 let make_assignment_expression_syntax left assignment_expression_syntax =
361 make_binary_expression
362 left
363 assignment_operator_syntax
364 assignment_expression_syntax
366 let make_unary_not_syntax expr =
367 make_prefix_unary_expression not_syntax expr
369 let make_assignment_syntax_variable left assignment_expression_syntax =
370 let assignment_binary_expression =
371 make_assignment_expression_syntax left assignment_expression_syntax in
372 make_expression_statement_syntax assignment_binary_expression
374 let make_is_null_syntax operand =
375 make_binary_expression operand identical_syntax null_syntax
377 let make_not_null_syntax operand =
378 make_binary_expression operand not_identical_syntax null_syntax
380 let make_assignment_syntax receiver_variable assignment_expression_syntax =
381 let receiver_variable_syntax =
382 make_variable_expression_syntax receiver_variable in
383 make_assignment_syntax_variable
384 receiver_variable_syntax assignment_expression_syntax
386 let make_function_call_expression_syntax receiver_syntax argument_list =
387 let argument_list_syntax = make_comma_list argument_list in
388 make_function_call_expression
389 receiver_syntax
390 left_paren_syntax
391 argument_list_syntax
392 right_paren_syntax
394 let make_function_call_statement_syntax receiver_syntax argument_list =
395 let function_call_expression =
396 make_function_call_expression_syntax receiver_syntax argument_list in
397 make_expression_statement function_call_expression semicolon_syntax
399 let make_static_function_call_expression_syntax
400 receiver_syntax
401 member_name
402 argument_list =
403 let member_syntax = make_name_syntax member_name in
404 let receiver_syntax =
405 make_scope_resolution_expression
406 receiver_syntax
407 colon_colon_syntax
408 member_syntax in
409 make_function_call_expression_syntax receiver_syntax argument_list
412 * parent::__construct(argument_list);
414 let make_construct_parent_syntax argument_list =
415 let expression_syntax =
416 make_static_function_call_expression_syntax
417 parent_syntax
418 constructor_member_name
419 argument_list in
420 make_expression_statement_syntax expression_syntax
422 let make_conditional_expression_syntax test consequence alternate =
423 make_conditional_expression
424 test
425 (make_token_syntax TokenKind.Question)
426 consequence
427 (make_token_syntax TokenKind.Colon)
428 alternate
430 let make_member_selection_expression_syntax receiver_syntax member_syntax =
431 make_member_selection_expression
432 receiver_syntax
433 member_selection_syntax
434 member_syntax
436 let make_parameter_declaration_syntax
437 ?(visibility_syntax = make_missing ())
438 parameter_type_syntax
439 parameter_variable =
440 let parameter_variable_syntax =
441 make_variable_syntax parameter_variable in
442 make_parameter_declaration
443 (* attribute *) (make_missing ())
444 visibility_syntax
445 (* call convention *) (make_missing ())
446 parameter_type_syntax
447 parameter_variable_syntax
448 (* default value *) (make_missing ())
450 let make_closure_parameter_type_syntax parameter_type_syntax =
451 make_closure_parameter_type_specifier
452 (* call convention *) (make_missing ())
453 parameter_type_syntax
455 let make_type_arguments_syntax = function
456 | [] ->
457 make_missing ()
458 | type_arguments_list ->
459 make_type_arguments
460 left_angle_syntax
461 (make_comma_list type_arguments_list)
462 right_angle_syntax
464 let make_type_parameters_syntax type_parameter_list =
465 match type_parameter_list with
466 | [] ->
467 make_missing ()
468 | _ ->
469 make_type_parameters
470 left_angle_syntax
471 (make_comma_list type_parameter_list)
472 right_angle_syntax
474 let make_type_specifier_syntax classname type_parameter_list =
475 let classname_syntax = make_name_syntax classname in
476 let type_arguments_syntax =
477 make_type_arguments_syntax type_parameter_list in
478 if is_missing type_arguments_syntax then
479 make_simple_type_specifier classname_syntax
480 else
481 make_generic_type_specifier classname_syntax type_arguments_syntax
483 let make_typed_object_creation_expression_syntax
484 type_specifier_syntax
485 arguments =
486 let arguments_syntax = make_comma_list arguments in
487 let constructor_call_syntax = make_constructor_call
488 type_specifier_syntax
489 left_paren_syntax
490 arguments_syntax
491 right_paren_syntax in
492 make_object_creation_expression
493 new_keyword_syntax
494 constructor_call_syntax
496 let make_object_creation_expression_syntax classname arguments =
497 let type_specifier_syntax = make_type_specifier_syntax classname [] in
498 make_typed_object_creation_expression_syntax type_specifier_syntax arguments
500 let make_functional_type_syntax argument_types return_type_syntax =
501 let argument_list_syntax =
502 argument_types
503 |> Core_list.map ~f:make_closure_parameter_type_syntax
504 |> make_comma_list in
505 make_closure_type_specifier
506 left_paren_syntax
507 (* coroutine *) (make_missing ())
508 function_keyword_syntax
509 left_paren_syntax
510 argument_list_syntax
511 right_paren_syntax
512 colon_syntax
513 return_type_syntax
514 right_paren_syntax
516 (* TODO(tingley): Determine if it's worth tightening visibility here. *)
517 let make_classish_declaration_syntax
518 classname
519 type_parameter_list
520 extends_list
521 classish_body =
522 let classname_syntax = make_name_syntax classname in
523 let extends_list_syntax =
524 make_comma_list extends_list in
525 let classish_body =
526 make_classish_body
527 left_brace_syntax
528 (make_list classish_body)
529 right_brace_syntax in
530 make_classish_declaration
531 (* classish_attribute *) (make_missing ())
532 (* classish_modifiers *) (make_missing ())
533 class_keyword_syntax
534 classname_syntax
535 (make_type_parameters_syntax type_parameter_list)
536 (if is_missing extends_list_syntax then
537 make_missing ()
538 else
539 extends_syntax)
540 extends_list_syntax
541 (* classish_implements_keyword *) (make_missing ())
542 (* classish_implements_list *) (make_missing ())
543 classish_body
545 let make_lambda_signature_from_method_syntax
546 existing_node
547 lambda_parameters
548 lambda_type =
549 synthesize_from
550 existing_node
551 (LambdaSignature {
552 lambda_left_paren = left_paren_syntax;
553 lambda_parameters = make_delimited_list comma_syntax lambda_parameters;
554 lambda_right_paren = right_paren_syntax;
555 lambda_colon =
556 if is_missing lambda_type then make_missing () else colon_syntax;
557 lambda_type;
560 let make_lambda_from_method_syntax existing_node lambda_signature lambda_body =
561 synthesize_from
562 existing_node
563 (LambdaExpression {
564 lambda_async = make_missing();
565 lambda_coroutine = make_missing();
566 lambda_signature = lambda_signature;
567 lambda_arrow = lambda_arrow_syntax;
568 lambda_body = lambda_body;
571 let make_function_decl_header_syntax
572 ~modifiers
573 name
574 parameter_list
575 return_type_syntax =
576 let modifiers_syntax = make_list modifiers in
577 let name_syntax = make_name_syntax name in
578 let parameter_list_syntax = make_comma_list parameter_list in
579 make_function_declaration_header
580 modifiers_syntax
581 function_keyword_syntax
582 (* function_ampersand *) (make_missing ())
583 name_syntax
584 (* function_type_parameter_list *) (make_missing ())
585 left_paren_syntax
586 parameter_list_syntax
587 right_paren_syntax
588 (if is_missing return_type_syntax then make_missing () else colon_syntax)
589 return_type_syntax
590 (* function_where_clause *) (make_missing ())
592 let make_methodish_declaration_with_body_syntax
593 ?(modifiers = [ public_syntax; ])
594 name
595 parameter_list
596 return_type_syntax
597 function_body =
598 let function_decl_header_syntax =
599 make_function_decl_header_syntax
600 modifiers name parameter_list return_type_syntax in
601 make_methodish_declaration
602 (* methodish_attribute *) (make_missing ())
603 function_decl_header_syntax
604 function_body
605 (* methodish_semicolon *) (make_missing ())
607 let make_methodish_declaration_syntax
608 ?modifiers
609 name
610 parameter_list
611 return_type_syntax
612 function_body =
613 make_methodish_declaration_with_body_syntax
614 ?modifiers
615 name
616 parameter_list
617 return_type_syntax
618 (make_compound_statement_syntax function_body)
620 let make_constructor_syntax parameter_list call_parent_syntax =
621 make_methodish_declaration_syntax
622 ~modifiers:[ public_syntax; final_syntax; ]
623 constructor_member_name
624 parameter_list
625 (make_missing ())
626 [ call_parent_syntax; ]
628 let make_property_declaration_syntax type_syntax declaration_syntax =
629 make_property_declaration
630 (make_list [ public_syntax; ])
631 type_syntax
632 (make_comma_list [ declaration_syntax; ])
633 semicolon_syntax
635 let make_if_else_syntax condition_syntax true_statements false_statements =
636 let else_clause =
637 match false_statements with
638 | [] ->
639 make_missing ()
640 | l ->
641 make_else_clause else_keyword_syntax (make_compound_statement_syntax l)
643 make_if_statement
644 if_keyword_syntax
645 left_paren_syntax
646 condition_syntax
647 right_paren_syntax
648 (make_compound_statement_syntax true_statements)
649 (make_missing ())
650 else_clause
652 let make_if_syntax condition_syntax true_statements =
653 make_if_else_syntax condition_syntax true_statements []
655 let make_while_syntax condition_syntax body_statements =
656 make_while_statement
657 while_keyword_syntax
658 left_paren_syntax
659 condition_syntax
660 right_paren_syntax
661 (make_compound_statement_syntax body_statements)
664 * while (true) {
665 * body
668 let make_while_true_syntax =
669 make_while_syntax true_expression_syntax
671 let make_not_syntax operand_syntax =
672 make_prefix_unary_expression
673 not_syntax
674 (make_parenthesized_expression_syntax operand_syntax)
677 * if (!condition_syntax) {
678 * break;
681 let make_break_unless_syntax do_not_break_condition_syntax =
682 make_if_syntax
683 (make_not_syntax do_not_break_condition_syntax)
684 [ break_statement_syntax; ]
686 let make_label_declaration_syntax label_name_syntax =
687 make_goto_label label_name_syntax colon_syntax
689 let make_goto_statement_syntax label_name_syntax =
690 make_goto_statement goto_keyword_syntax label_name_syntax semicolon_syntax
692 (* case 0: *)
693 let make_int_case_label_syntax number =
694 let number = make_int_literal_syntax number in
695 make_case_label case_keyword_syntax number colon_syntax
697 (* default: *)
698 let default_label_syntax =
699 make_default_label default_keyword_syntax colon_syntax
702 (* Coroutine-specific syntaxes *)
704 let continuation_member_name =
705 "coroutineContinuation_generated"
707 let continuation_member_name_syntax =
708 make_name_syntax continuation_member_name
710 let continuation_variable =
711 "$" ^ continuation_member_name
713 let continuation_variable_syntax =
714 make_variable_expression_syntax continuation_variable
716 let make_closure_base_type_syntax function_type =
717 make_type_specifier_syntax "\\ClosureBase" [ function_type; ]
719 let make_continuation_type_syntax function_type =
720 make_type_specifier_syntax
721 "\\InternalCoroutineContinuation"
722 [ function_type; ]
724 let make_continuation_parameter_syntax
725 ?visibility_syntax
726 function_type =
727 make_parameter_declaration_syntax
728 ?visibility_syntax
729 (make_continuation_type_syntax function_type)
730 continuation_variable
732 let make_continuation_closure_parameter_syntax function_type =
733 make_closure_parameter_type_syntax
734 (make_continuation_type_syntax function_type)
736 let make_coroutine_result_type_syntax function_type =
737 make_type_specifier_syntax "\\CoroutineResult" [ function_type; ]
739 let suspended_coroutine_result_classname_syntax =
740 make_qualified_name_syntax "\\SuspendedCoroutineResult"
742 let suspended_member_name =
743 "create"
745 let is_suspended_member_name =
746 "isSuspended"
748 let is_suspended_member_syntax =
749 make_name_syntax is_suspended_member_name
751 let get_result_member_name =
752 "getResult"
754 let get_result_member_syntax =
755 make_name_syntax get_result_member_name
757 (* SuspendedCoroutineResult::create() *)
758 let create_suspended_coroutine_result_syntax =
759 make_static_function_call_expression_syntax
760 suspended_coroutine_result_classname_syntax
761 suspended_member_name
764 (* ClassName_FunctionName_Lambda_1_GeneratedClosure *)
765 let make_closure_classname context =
766 let classish_name = context.Coroutine_context.classish_name in
767 (* TODO: Is there a better thing to do for coroutines that are inside no
768 class? *)
769 let classish_name = if is_missing classish_name then
770 global_syntax else classish_name in
771 let function_name = context.Coroutine_context.function_name in
772 let lambda_name = match context.Coroutine_context.lambda_count with
773 | None -> ""
774 | Some c -> Printf.sprintf "Lambda_%i_" c in
775 Printf.sprintf
776 "%s_%s_%sGeneratedClosure"
777 (string_of_name_token classish_name)
778 (string_of_name_token function_name)
779 lambda_name
782 * Given a list of TypeParameters syntaxes, combines them into a single
783 * list of type_parameters.
784 TODO: What if there is a name collision?
786 let make_closure_type_parameters context =
787 let classish_type_parameters =
788 context.Coroutine_context.classish_type_parameters in
789 let function_type_parameter_list =
790 context.Coroutine_context.function_type_parameter_list in
791 (get_type_parameter_list classish_type_parameters) @
792 (get_type_parameter_list function_type_parameter_list)
794 let make_closure_type_arguments context =
795 let classish_type_parameters =
796 context.Coroutine_context.classish_type_parameters in
797 let function_type_parameter_list =
798 context.Coroutine_context.function_type_parameter_list in
799 (get_type_arguments classish_type_parameters) @
800 (get_type_arguments function_type_parameter_list)
803 ClassName_FunctionName_GeneratedClosure<TClass, TFunc>
805 let make_closure_type_syntax context =
806 make_type_specifier_syntax
807 (make_closure_classname context)
808 (make_closure_type_arguments context)
810 let closure_variable =
811 "$closure"
813 (* $closure *)
814 let closure_variable_syntax =
815 make_variable_expression_syntax closure_variable
817 (* $closure->name *)
818 let closure_name_syntax name =
819 let name_syntax = make_name_syntax name in
820 make_member_selection_expression_syntax closure_variable_syntax name_syntax
822 let make_closure_parameter_syntax context =
823 make_parameter_declaration_syntax
824 (make_closure_type_syntax context)
825 closure_variable
827 let resume_member_name =
828 "resume"
830 let resume_member_name_syntax =
831 make_name_syntax resume_member_name
833 let resume_with_exception_member_name =
834 "resumeWithException"
836 let do_resume_member_name =
837 "doResume"
839 let do_resume_member_name_syntax =
840 make_name_syntax do_resume_member_name
842 let do_resume_with_reentry_guard_member_name_syntax =
843 make_name_syntax "doResumeWithReentryGuard"
845 let clone_member_name =
846 "clone"
848 let clone_member_name_syntax =
849 make_name_syntax clone_member_name
851 let coroutine_data_variable =
852 "$coroutineData"
854 let coroutine_data_variable_syntax =
855 make_variable_expression_syntax coroutine_data_variable
857 let coroutine_result_variable =
858 "$coroutineResult"
860 let coroutine_result_variable_syntax =
861 make_variable_expression_syntax coroutine_result_variable
863 let make_coroutine_result_data_member_name index =
864 Printf.sprintf "coroutineResultData%d" index
866 let make_coroutine_result_data_variable index =
867 "$" ^ (make_coroutine_result_data_member_name index)
869 let make_coroutine_result_data_member_name_syntax index =
870 make_name_syntax (make_coroutine_result_data_member_name index)
872 let make_closure_result_data_member_name_syntax index =
873 closure_name_syntax (make_coroutine_result_data_member_name index)
875 let coroutine_data_type_syntax =
876 mixed_syntax
878 let coroutine_data_parameter_syntax =
879 make_parameter_declaration_syntax
880 coroutine_data_type_syntax
881 coroutine_data_variable
883 let exception_variable =
884 "$exception_generated"
886 let exception_variable_syntax =
887 make_variable_expression_syntax exception_variable
889 let nullable_exception_type_syntax =
890 make_nullable_type_specifier_syntax exception_type_syntax
892 let exception_parameter_syntax =
893 make_parameter_declaration_syntax
894 exception_type_syntax
895 exception_variable
897 let nullable_exception_parameter_syntax =
898 make_parameter_declaration_syntax
899 nullable_exception_type_syntax
900 exception_variable
902 let throw_unimplemented_syntax reason =
903 let create_exception_syntax =
904 make_object_creation_expression_syntax
905 "\\Exception"
906 [make_string_literal_syntax reason] in
907 make_throw_statement_syntax create_exception_syntax
909 let make_state_machine_method_name function_name =
910 Printf.sprintf "%s_GeneratedStateMachine" function_name
912 let state_machine_member_name =
913 "stateMachineFunction"
915 let state_machine_member_name_syntax =
916 make_name_syntax state_machine_member_name
918 let state_machine_variable_name =
919 "$" ^ state_machine_member_name
921 let state_machine_variable_name_syntax =
922 make_variable_expression_syntax state_machine_variable_name
924 let make_state_machine_parameter_syntax context function_type =
925 let state_machine_type_syntax =
926 make_functional_type_syntax
928 make_closure_type_syntax context;
929 mixed_syntax;
930 nullable_exception_type_syntax;
932 (make_coroutine_result_type_syntax function_type) in
933 make_parameter_declaration_syntax
934 ~visibility_syntax:private_syntax
935 state_machine_type_syntax
936 state_machine_variable_name
938 let inst_meth_syntax =
939 make_qualified_name_syntax "inst_meth"
941 let class_meth_syntax =
942 make_qualified_name_syntax "class_meth"
944 let make_member_with_unknown_type_declaration_syntax variable_name =
945 let variable_syntax = make_variable_syntax variable_name in
946 let declaration_syntax =
947 make_property_declarator variable_syntax (make_missing ()) in
948 make_property_declaration_syntax (make_missing ()) declaration_syntax
950 let coroutine_unit_classname_syntax =
951 make_qualified_name_syntax "\\CoroutineUnit"
953 (* CoroutineUnit::create() *)
954 let coroutine_unit_call_syntax =
955 make_static_function_call_expression_syntax
956 coroutine_unit_classname_syntax
957 "create"
960 let next_label =
961 "nextLabel"
963 (* $closure->nextLabel *)
964 let label_syntax =
965 closure_name_syntax next_label
967 (* nextLabel *)
968 let label_name_syntax =
969 make_name_syntax next_label
971 (* $closure->nextLabel = x; *)
972 let set_next_label_syntax number =
973 let number = make_int_literal_syntax number in
974 make_assignment_syntax_variable label_syntax number
976 type label =
977 | StateLabel of int
978 | ErrorStateLabel
979 | LoopLabel of int
981 let get_label_string = function
982 | StateLabel number -> Printf.sprintf "state_label_%d" number
983 | ErrorStateLabel -> "state_label_error"
984 | LoopLabel number -> Printf.sprintf "loop_label_%d" number
986 let get_label_name label =
987 make_name_syntax (get_label_string label)
989 let make_label_declaration_syntax label =
990 make_label_declaration_syntax (get_label_name label)
992 let make_goto_statement_syntax label =
993 make_goto_statement_syntax (get_label_name label)
995 let make_if_statement_syntax if_stmt =
996 make_syntax (IfStatement if_stmt)
998 let make_switch_statement_syntax switch_stmt =
999 make_syntax (SwitchStatement switch_stmt)
1001 let make_foreach_statement_syntax foreach_stmt =
1002 make_syntax (ForeachStatement foreach_stmt)
1004 let make_echo_statement_syntax echo_stmt =
1005 make_syntax (EchoStatement echo_stmt)
1007 let make_unset_statement_syntax unset_stmt =
1008 make_syntax (UnsetStatement unset_stmt)
1010 let boolval_syntax =
1011 make_qualified_name_syntax "boolval"