Fix stack overflow bug
[hiphop-php.git] / hphp / hack / src / generate_full_fidelity_data.ml
blob0e54f7687605936b93abe0a50d1cbb0eddd442d6
1 (*
2 * Copyright (c) 2016, 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 module OcamlPrintf = Printf
11 open Hh_prelude
12 open Printf
13 open Full_fidelity_schema
15 let full_fidelity_path_prefix = "hphp/hack/src/parser/"
17 let rust_keywords =
18 [ "as"; "break"; "const"; "continue"; "crate"; "else"; "enum"; "extern";
19 "false"; "fn"; "for"; "if"; "impl"; "in"; "let"; "loop"; "match"; "mod";
20 "move"; "mut"; "pub"; "ref"; "return"; "self"; "Self"; "static"; "struct";
21 "super"; "trait"; "true"; "type"; "unsafe"; "use"; "where"; "while";
22 "async"; "await"; "dyn" ]
23 [@@ocamlformat "disable"]
25 let escape_rust_keyword field_name =
26 if List.mem rust_keywords field_name ~equal:String.equal then
27 sprintf "%s_" field_name
28 else
29 field_name
31 type comment_style =
32 | CStyle
33 | MLStyle
34 [@@deriving show]
36 let make_header comment_style (header_comment : string) : string =
37 let (open_char, close_char) =
38 match comment_style with
39 | CStyle -> ("/*", '/')
40 | MLStyle -> ("(", ')')
42 sprintf
43 "%s*
44 * Copyright (c) 2016, Facebook, Inc.
45 * All rights reserved.
47 * This source code is licensed under the MIT license found in the
48 * LICENSE file in the \"hack\" directory of this source tree. An additional
49 * directory.
53 * THIS FILE IS @%s; DO NOT EDIT IT
54 * To regenerate this file, run
56 * buck run //hphp/hack/src:generate_full_fidelity
59 *%s
60 *%c"
61 open_char
62 (* Any file containing '@' followed by the word 'generated' is considered a
63 * generated file in Phabricator. Cheeky trick to avoid making this script
64 * being seen as generated. *)
65 "generated"
66 header_comment
67 close_char
69 type valign =
70 (string -> string -> string, unit, string, string -> string) format4
72 let all_tokens = given_text_tokens @ variable_text_tokens @ no_text_tokens
74 let align_fmt : 'a. ('a -> string) -> 'a list -> valign =
75 fun f xs ->
76 let folder acc x = max acc (String.length (f x)) in
77 let width = List.fold_left ~f:folder ~init:0 xs in
78 Scanf.format_from_string (sprintf "%%-%ds" width) "%-1s"
80 let kind_name_fmt = align_fmt (fun x -> x.kind_name) schema
82 let type_name_fmt = align_fmt (fun x -> x.type_name) schema
84 let trivia_kind_fmt = align_fmt (fun x -> x.trivia_kind) trivia_kinds
86 let token_kind_fmt = align_fmt (fun x -> x.token_kind) all_tokens
88 let omit_syntax_record =
89 let names =
90 SSet.of_list
92 "anonymous_function";
93 "closure_type_specifier";
94 "function_declaration";
95 "function_declaration_header";
96 "lambda_expression";
97 "lambda_signature";
98 "methodish_declaration";
101 (fun x -> not (SSet.mem x.type_name names))
103 module GenerateFFSyntaxType = struct
104 let to_parse_tree x =
105 if omit_syntax_record x then
107 else
108 let field_width = 50 - String.length x.prefix in
109 let fmt = sprintf "%s_%%-%ds: t\n" x.prefix field_width in
110 let mapper (f, _) = sprintf (Scanf.format_from_string fmt "%-1s") f in
111 let fields = map_and_concat_separated " ; " mapper x.fields in
112 sprintf " and %s =\n { %s }\n" x.type_name fields
114 let to_syntax x =
115 let field_width = 50 - String.length x.prefix in
116 let fmt = sprintf "%s_%%-%ds: t\n" x.prefix field_width in
117 let mapper (f, _) = sprintf (Scanf.format_from_string fmt "%-1s") f in
118 let fields = map_and_concat_separated " ; " mapper x.fields in
119 sprintf
120 (" | " ^^ kind_name_fmt ^^ " of\n { %s }\n")
121 x.kind_name
122 fields
124 let to_aggregate_type x =
125 let aggregated_types = aggregation_of x in
126 let (prefix, trim) = aggregate_type_pfx_trim x in
127 let compact = Str.global_replace (Str.regexp trim) "" in
128 let valign = align_fmt (fun x -> compact x.kind_name) aggregated_types in
129 let type_name = aggregate_type_name x in
130 let make_constructor ty =
131 sprintf
132 ("%s" ^^ valign ^^ " of %s")
133 prefix
134 (compact ty.kind_name)
135 ty.type_name
137 let type_body = List.map ~f:make_constructor aggregated_types in
138 sprintf
139 " and %s =\n | %s\n"
140 type_name
141 (String.concat ~sep:"\n | " type_body)
143 let full_fidelity_syntax_template : string =
144 make_header
145 MLStyle
147 * This module contains the type describing the structure of a syntax tree.
149 * The structure of the syntax tree is described by the collection of recursive
150 * types that makes up the bulk of this file. The type `t` is the type of a node
151 * in the syntax tree; each node has associated with it an arbitrary value of
152 * type `SyntaxValue.t`, and syntax node proper, which has structure given by
153 * the `syntax` type.
155 * Note that every child in the syntax tree is of type `t`, except for the
156 * `Token.t` type. This should be the *only* child of a type other than `t`.
157 * We are explicitly NOT attempting to impose a type structure on the parse
158 * tree beyond what is already implied by the types here. For example,
159 * we are not attempting to put into the type system here the restriction that
160 * the children of a binary operator must be expressions. The reason for this
161 * is because we are potentially parsing code as it is being typed, and we
162 * do not want to restrict our ability to make good error recovery by imposing
163 * a restriction that will only be valid in correct program text.
165 * That said, it would of course be ideal if the only children of a compound
166 * statement were statements, and so on. But those invariants should be
167 * imposed by the design of the parser, not by the type system of the syntax
168 * tree code.
170 * We want to be able to use different kinds of tokens, with different
171 * performance characteristics. Moreover, we want to associate arbitrary values
172 * with the syntax nodes, so that we can construct syntax trees with various
173 * properties -- trees that only know their widths and are thereby cheap to
174 * serialize, trees that have full position data for each node, trees where the
175 * tokens know their text and can therefore be edited, trees that have name
176 * annotations or type annotations, and so on.
178 * We wish to associate arbitrary values with the syntax nodes so that we can
179 * construct syntax trees with various properties -- trees that only know
180 * their widths and are thereby cheap to serialize, trees that have full
181 * position data for each node, trees where the tokens know their text and
182 * can therefore be edited, trees that have name annotations or type
183 * annotations, and so on.
185 * Therefore this module is functorized by the types for token and value to be
186 * associated with the node."
188 open Sexplib.Std
190 module type TokenType = sig
191 module Trivia : Lexable_trivia_sig.LexableTrivia_S
192 type t [@@deriving show, eq, sexp_of]
193 val kind: t -> Full_fidelity_token_kind.t
194 val to_json: t -> Hh_json.json
195 val leading : t -> Trivia.t list
198 module type SyntaxValueType = sig
199 type t [@@deriving show, eq, sexp_of]
200 val to_json: t -> Hh_json.json
203 (* This functor describe the shape of a parse tree that has a particular kind of
204 * token in the leaves, and a particular kind of value associated with each
205 * node.
207 module MakeSyntaxType(Token : TokenType)(SyntaxValue : SyntaxValueType) = struct
208 type value = SyntaxValue.t [@@deriving show, eq, sexp_of]
209 type t = { syntax : syntax ; value : value } [@@deriving show, eq, sexp_of]
210 PARSE_TREE and syntax =
211 | Token of Token.t
212 | Missing
213 | SyntaxList of t list
214 SYNTAX
215 [@@deriving sexp_of]
220 let full_fidelity_syntax_type =
221 Full_fidelity_schema.make_template_file
222 ~transformations:
224 { pattern = "PARSE_TREE"; func = to_parse_tree };
225 { pattern = "SYNTAX"; func = to_syntax };
227 ~aggregate_transformations:
230 aggregate_pattern = "AGGREGATE_TYPES";
231 aggregate_func = to_aggregate_type;
234 ~filename:(full_fidelity_path_prefix ^ "full_fidelity_syntax_type.ml")
235 ~template:full_fidelity_syntax_template
239 module GenerateFFRustSyntaxImplByRef = struct
240 let to_kind x =
241 sprintf
242 " SyntaxVariant::%s {..} => SyntaxKind::%s,\n"
243 x.kind_name
244 x.kind_name
246 let template =
247 make_header CStyle ""
249 use crate::{syntax_kind::SyntaxKind, lexable_token::LexableToken};
250 use super::{syntax::Syntax, syntax_variant_generated::SyntaxVariant};
252 impl<T: LexableToken, V> Syntax<'_, T, V> {
253 pub fn kind(&self) -> SyntaxKind {
254 match &self.children {
255 SyntaxVariant::Missing => SyntaxKind::Missing,
256 SyntaxVariant::Token (t) => SyntaxKind::Token(t.kind()),
257 SyntaxVariant::SyntaxList (_) => SyntaxKind::SyntaxList,
258 TO_KIND }
263 let full_fidelity_syntax =
264 Full_fidelity_schema.make_template_file
265 ~transformations:[{ pattern = "TO_KIND"; func = to_kind }]
266 ~filename:
267 (full_fidelity_path_prefix ^ "syntax_by_ref/syntax_impl_generated.rs")
268 ~template
272 module GenerateSyntaxSerialize = struct
273 let match_arm x =
274 let get_field x = escape_rust_keyword (fst x) in
275 let serialize_fields =
276 map_and_concat_separated
277 "\n"
278 (fun y ->
279 sprintf
280 "ss.serialize_field(\"%s_%s\", &self.with(%s))?;"
281 x.prefix
282 (fst y)
283 (get_field y))
284 x.fields
286 let fields = map_and_concat_separated "," get_field x.fields in
287 sprintf
288 "SyntaxVariant::%s (%sChildren{%s} ) => {
289 let mut ss = s.serialize_struct(\"\", %d)?;
290 ss.serialize_field(\"kind\", \"%s\")?;
292 ss.end()
293 } \n"
294 x.kind_name
295 x.kind_name
296 fields
297 (1 + List.length x.fields)
298 x.description
299 serialize_fields
301 let template =
302 make_header CStyle ""
304 use super::{serialize::WithContext, syntax::Syntax, syntax_variant_generated::*};
305 use serde::{ser::SerializeStruct, Serialize, Serializer};
307 impl<'a, T, V> Serialize for WithContext<'a, Syntax<'a, T, V>>
308 where
309 T: 'a,
310 WithContext<'a, T>: Serialize,
312 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
313 match self.1.children {
314 SyntaxVariant::Missing => {
315 let mut ss = s.serialize_struct(\"\", 1)?;
316 ss.serialize_field(\"kind\", \"missing\")?;
317 ss.end()
319 SyntaxVariant::Token(ref t) => {
320 let mut ss = s.serialize_struct(\"\", 2)?;
321 ss.serialize_field(\"kind\", \"token\")?;
322 ss.serialize_field(\"token\", &self.with(t))?;
323 ss.end()
325 SyntaxVariant::SyntaxList(l) => {
326 let mut ss = s.serialize_struct(\"\", 2)?;
327 ss.serialize_field(\"kind\", \"list\")?;
328 ss.serialize_field(\"elements\", &self.with(l))?;
329 ss.end()
331 MATCH_ARMS
337 let gen =
338 Full_fidelity_schema.make_template_file
339 ~transformations:[{ pattern = "MATCH_ARMS"; func = match_arm }]
340 ~filename:
341 (full_fidelity_path_prefix
342 ^ "syntax_by_ref/syntax_serialize_generated.rs")
343 ~template
347 module GenerateFFRustSyntaxVariantByRef = struct
348 let to_syntax_variant_children x =
349 let mapper (f, _) =
350 sprintf " pub %s: Syntax<'a, T, V>," (escape_rust_keyword f)
352 let fields = map_and_concat_separated "\n" mapper x.fields in
353 sprintf
354 "#[derive(Debug, Clone)]\npub struct %sChildren<'a, T, V> {\n%s\n}\n\n"
355 x.kind_name
356 fields
358 let to_syntax_variant x =
359 sprintf " %s(&'a %sChildren<'a, T, V>),\n" x.kind_name x.kind_name
361 let full_fidelity_syntax_template =
362 make_header CStyle ""
364 use super::{
365 syntax::Syntax,
366 syntax_children_iterator::SyntaxChildrenIterator,
369 #[derive(Debug, Clone)]
370 pub enum SyntaxVariant<'a, T, V> {
371 Token(T),
372 Missing,
373 SyntaxList(&'a [Syntax<'a, T, V>]),
374 SYNTAX_VARIANT}
376 SYNTAX_CHILDREN
378 impl<'a, T, V> SyntaxVariant<'a, T, V> {
379 pub fn iter_children(&'a self) -> SyntaxChildrenIterator<'a, T, V> {
380 SyntaxChildrenIterator {
381 syntax: &self,
382 index: 0,
383 index_back: 0,
389 let full_fidelity_syntax =
390 Full_fidelity_schema.make_template_file
391 ~transformations:
393 { pattern = "SYNTAX_VARIANT"; func = to_syntax_variant };
394 { pattern = "SYNTAX_CHILDREN"; func = to_syntax_variant_children };
396 ~filename:
397 (full_fidelity_path_prefix ^ "syntax_by_ref/syntax_variant_generated.rs")
398 ~template:full_fidelity_syntax_template
402 module GenerateSyntaxChildrenIterator = struct
403 let to_iter_children x =
404 let index = ref 0 in
405 let mapper (f, _) =
406 let res = sprintf "%d => Some(&x.%s)," !index (escape_rust_keyword f) in
407 let () = incr index in
410 let fields =
411 map_and_concat_separated "\n " mapper x.fields
413 sprintf
414 " %s(x) => {
415 get_index(%d).and_then(|index| { match index {
417 _ => None,
420 },\n"
421 x.kind_name
422 (List.length x.fields)
423 fields
425 let full_fidelity_syntax_template =
426 make_header CStyle ""
428 use super::{
429 syntax_children_iterator::*,
430 syntax_variant_generated::*,
431 syntax::*
434 impl<'a, T, V> SyntaxChildrenIterator<'a, T, V> {
435 pub fn next_impl(&mut self, direction : bool) -> Option<&'a Syntax<'a, T, V>> {
436 use SyntaxVariant::*;
437 let get_index = |len| {
438 let back_index_plus_1 = len - self.index_back;
439 if back_index_plus_1 <= self.index {
440 return None
442 if direction {
443 Some (self.index)
444 } else {
445 Some (back_index_plus_1 - 1)
448 let res = match self.syntax {
449 Missing => None,
450 Token (_) => None,
451 SyntaxList(elems) => {
452 get_index(elems.len()).and_then(|x| elems.get(x))
454 ITER_CHILDREN
456 if res.is_some() {
457 if direction {
458 self.index = self.index + 1
459 } else {
460 self.index_back = self.index_back + 1
468 let full_fidelity_syntax =
469 Full_fidelity_schema.make_template_file
470 ~transformations:[{ pattern = "ITER_CHILDREN"; func = to_iter_children }]
471 ~filename:
472 (full_fidelity_path_prefix
473 ^ "syntax_by_ref/syntax_children_iterator_generated.rs")
474 ~template:full_fidelity_syntax_template
478 module GenerateSyntaxTypeImpl = struct
479 let to_syntax_constructors x =
480 let mapper (f, _) = sprintf "%s: Self" (escape_rust_keyword f) in
481 let args = map_and_concat_separated ", " mapper x.fields in
482 let mapper (f, _) = sprintf "%s" (escape_rust_keyword f) in
483 let fields = map_and_concat_separated ",\n " mapper x.fields in
484 sprintf
485 " fn make_%s(ctx: &C, %s) -> Self {
486 let syntax = SyntaxVariant::%s(ctx.get_arena().alloc(%sChildren {
488 }));
489 let value = V::from_values(syntax.iter_children().map(|child| &child.value));
490 Self::make(syntax, value)
491 }\n\n"
492 x.type_name
493 args
494 x.kind_name
495 x.kind_name
496 fields
498 let full_fidelity_syntax_template =
499 make_header CStyle ""
501 use super::{
502 has_arena::HasArena,
503 syntax::*, syntax_variant_generated::*,
505 use crate::{
506 lexable_token::LexableToken,
507 syntax::{SyntaxType, SyntaxValueType},
510 impl<'a, C, T, V> SyntaxType<C> for Syntax<'a, T, V>
511 where
512 T: LexableToken + Copy,
513 V: SyntaxValueType<T>,
514 C: HasArena<'a>,
516 SYNTAX_CONSTRUCTORS }
519 let full_fidelity_syntax =
520 Full_fidelity_schema.make_template_file
521 ~transformations:
522 [{ pattern = "SYNTAX_CONSTRUCTORS"; func = to_syntax_constructors }]
523 ~filename:
524 (full_fidelity_path_prefix
525 ^ "syntax_by_ref/syntax_type_impl_generated.rs")
526 ~template:full_fidelity_syntax_template
530 module GenerateFFRustSyntax = struct
531 let from_children x =
532 let mapper prefix (f, _) =
533 sprintf "%s_%s : (Box::new(ts.pop().unwrap()))" prefix f
535 let fields =
536 map_and_concat_separated ",\n " (mapper x.prefix) x.fields
538 sprintf
539 "SyntaxKind::%s => SyntaxVariant::%s {
542 x.kind_name
543 x.kind_name
544 fields
546 let to_kind x =
547 sprintf
548 " SyntaxVariant::%s {..} => SyntaxKind::%s,\n"
549 x.kind_name
550 x.kind_name
552 let to_children x =
553 let mapper prefix (f, _) = sprintf "&*%s_%s" prefix f in
554 let fields2 =
555 map_and_concat_separated ",\n " (mapper x.prefix) x.fields
557 let mapper prefix (f, _) = sprintf "ref %s_%s" prefix f in
558 let fields =
559 map_and_concat_separated ",\n " (mapper x.prefix) x.fields
561 sprintf
562 "SyntaxVariant::%s {
564 } => vec![%s],"
565 x.kind_name
566 fields
567 fields2
569 let to_iter_children x =
570 let index = ref 0 in
571 let mapper prefix (f, _) =
572 let res = sprintf "%d => Some(&x.%s_%s)," !index prefix f in
573 let () = incr index in
576 let fields =
577 map_and_concat_separated
578 "\n "
579 (mapper x.prefix)
580 x.fields
582 sprintf
583 " %s(x) => {
584 get_index(%d).and_then(|index| { match index {
586 _ => None,
589 },\n"
590 x.kind_name
591 (List.length x.fields)
592 fields
594 let syntax_as_slice x =
595 (* SAFETY: We have `#[repr(C)]` on all the children structs, and all their
596 fields are of type Syntax. So a child struct with 3 fields should have
597 the same layout as the array `[Syntax; 3]`, and it should be valid to
598 take a slice of length 3 from a pointer to its first field. *)
599 sprintf
600 " SyntaxVariant::%s(x) => unsafe { std::slice::from_raw_parts(&x.%s_%s, %d) },\n"
601 x.kind_name
602 x.prefix
603 (fst (List.hd_exn x.fields))
604 (List.length x.fields)
606 let syntax_as_slice_mut x =
607 (* SAFETY: As above in `syntax_as_slice` *)
608 sprintf
609 " SyntaxVariant::%s(x) => unsafe { std::slice::from_raw_parts_mut(&mut x.%s_%s, %d) },\n"
610 x.kind_name
611 x.prefix
612 (fst (List.hd_exn x.fields))
613 (List.length x.fields)
615 let fold_over_owned x =
616 let fold_mapper prefix (f, _) =
617 sprintf "let acc = f(%s_%s, acc)" prefix f
619 let fold_fields =
620 map_and_concat_separated
621 ";\n "
622 (fold_mapper x.prefix)
623 x.fields
625 let destructure_mapper prefix (f, _) = sprintf "%s_%s" prefix f in
626 let destructure_fields =
627 map_and_concat_separated ", " (destructure_mapper x.prefix) x.fields
629 sprintf
630 " SyntaxVariant::%s(x) => {
631 let %sChildren { %s } = *x;
634 },\n"
635 x.kind_name
636 x.kind_name
637 destructure_fields
638 fold_fields
640 let to_syntax_variant x =
641 sprintf " %s(Box<%sChildren<T, V>>),\n" x.kind_name x.kind_name
643 let to_syntax_variant_children x =
644 let mapper prefix (f, _) =
645 sprintf " pub %s_%s: Syntax<T, V>," prefix f
647 let fields = map_and_concat_separated "\n" (mapper x.prefix) x.fields in
648 (* NB: The `#[repr(C)]` here is required for the `from_raw_parts` and
649 `from_raw_parts_mut` above (in `syntax_as_slice` and
650 `syntax_as_slice_mut`) to be valid. *)
651 sprintf
652 "#[derive(Debug, Clone)]\n#[repr(C)]\npub struct %sChildren<T, V> {\n%s\n}\n\n"
653 x.kind_name
654 fields
656 let to_syntax_constructors x =
657 let mapper prefix (f, _) = sprintf "%s_%s: Self" prefix f in
658 let args = map_and_concat_separated ", " (mapper x.prefix) x.fields in
659 let mapper prefix (f, _) = sprintf "%s_%s" prefix f in
660 let fields =
661 map_and_concat_separated ",\n " (mapper x.prefix) x.fields
663 sprintf
664 " fn make_%s(_: &C, %s) -> Self {
665 let syntax = SyntaxVariant::%s(Box::new(%sChildren {
667 }));
668 let value = V::from_values(syntax.iter_children().map(|child| &child.value));
669 Self::make(syntax, value)
670 }\n\n"
671 x.type_name
672 args
673 x.kind_name
674 x.kind_name
675 fields
677 let to_syntax_from_children x =
678 let mapper (f, _) =
679 sprintf "%s_%s: ts.pop().unwrap(),\n " x.prefix f
681 let fields = map_and_concat mapper (List.rev x.fields) in
682 sprintf
683 " (SyntaxKind::%s, %d) => SyntaxVariant::%s(Box::new(%sChildren {
685 })),\n"
686 x.kind_name
687 (List.length x.fields)
688 x.kind_name
689 x.kind_name
690 fields
692 let full_fidelity_syntax_template =
693 make_header CStyle ""
695 use crate::lexable_token::LexableToken;
696 use crate::syntax::*;
697 use crate::syntax_kind::SyntaxKind;
699 impl<T, V, C> SyntaxType<C> for Syntax<T, V>
700 where
701 T: LexableToken,
702 V: SyntaxValueType<T>,
704 SYNTAX_CONSTRUCTORS }
706 impl<T, V> Syntax<T, V>
707 where
708 T: LexableToken,
710 pub fn fold_over_children_owned<U>(
711 f: &dyn Fn(Self, U) -> U,
712 acc: U,
713 syntax: SyntaxVariant<T, V>,
714 ) -> U {
715 match syntax {
716 SyntaxVariant::Missing => acc,
717 SyntaxVariant::Token (_) => acc,
718 SyntaxVariant::SyntaxList(elems) => {
719 let mut acc = acc;
720 for item in elems {
721 acc = f(item, acc);
725 FOLD_OVER_CHILDREN_OWNED
729 pub fn kind(&self) -> SyntaxKind {
730 match &self.syntax {
731 SyntaxVariant::Missing => SyntaxKind::Missing,
732 SyntaxVariant::Token (t) => SyntaxKind::Token(t.kind()),
733 SyntaxVariant::SyntaxList (_) => SyntaxKind::SyntaxList,
734 TO_KIND }
737 pub fn from_children(kind : SyntaxKind, mut ts : Vec<Self>) -> SyntaxVariant<T, V> {
738 match (kind, ts.len()) {
739 (SyntaxKind::Missing, 0) => SyntaxVariant::Missing,
740 (SyntaxKind::SyntaxList, _) => SyntaxVariant::SyntaxList(ts),
741 SYNTAX_FROM_CHILDREN _ => panic!(\"from_children called with wrong number of children\"),
745 pub fn children(&self) -> &[Self] {
746 match &self.syntax {
747 SyntaxVariant::Missing => &[],
748 SyntaxVariant::Token(..) => &[],
749 SyntaxVariant::SyntaxList(l) => l.as_slice(),
750 SYNTAX_AS_SLICE }
753 pub fn children_mut(&mut self) -> &mut [Self] {
754 match &mut self.syntax {
755 SyntaxVariant::Missing => &mut [],
756 SyntaxVariant::Token(..) => &mut [],
757 SyntaxVariant::SyntaxList(l) => l.as_mut_slice(),
758 SYNTAX_AS_SLICE_MUT }
762 SYNTAX_CHILDREN
763 #[derive(Debug, Clone)]
764 pub enum SyntaxVariant<T, V> {
765 Token(Box<T>),
766 Missing,
767 SyntaxList(Vec<Syntax<T, V>>),
768 SYNTAX_VARIANT}
770 impl<'a, T, V> SyntaxChildrenIterator<'a, T, V> {
771 pub fn next_impl(&mut self, direction : bool) -> Option<&'a Syntax<T, V>> {
772 use SyntaxVariant::*;
773 let get_index = |len| {
774 let back_index_plus_1 = len - self.index_back;
775 if back_index_plus_1 <= self.index {
776 return None
778 if direction {
779 Some (self.index)
780 } else {
781 Some (back_index_plus_1 - 1)
784 let res = match &self.syntax {
785 Missing => None,
786 Token (_) => None,
787 SyntaxList(elems) => {
788 get_index(elems.len()).and_then(|x| elems.get(x))
790 ITER_CHILDREN
792 if res.is_some() {
793 if direction {
794 self.index = self.index + 1
795 } else {
796 self.index_back = self.index_back + 1
804 let full_fidelity_syntax =
805 Full_fidelity_schema.make_template_file
806 ~transformations:
808 { pattern = "SYNTAX_VARIANT"; func = to_syntax_variant };
809 { pattern = "SYNTAX_CHILDREN"; func = to_syntax_variant_children };
810 { pattern = "SYNTAX_CONSTRUCTORS"; func = to_syntax_constructors };
811 { pattern = "ITER_CHILDREN"; func = to_iter_children };
812 { pattern = "FOLD_OVER_CHILDREN_OWNED"; func = fold_over_owned };
813 { pattern = "TO_KIND"; func = to_kind };
814 { pattern = "SYNTAX_FROM_CHILDREN"; func = to_syntax_from_children };
815 { pattern = "SYNTAX_AS_SLICE"; func = syntax_as_slice };
816 { pattern = "SYNTAX_AS_SLICE_MUT"; func = syntax_as_slice_mut };
818 ~filename:(full_fidelity_path_prefix ^ "syntax_generated.rs")
819 ~template:full_fidelity_syntax_template
823 (* GenerateFFRustSyntax *)
825 module GenerateFFRustSyntaxType = struct
826 let to_kind x =
827 sprintf
828 " SyntaxVariant::%s {..} => SyntaxKind::%s,\n"
829 x.kind_name
830 x.kind_name
832 let to_children x =
833 let mapper prefix (f, _) = sprintf "&*%s_%s" prefix f in
834 let fields2 =
835 map_and_concat_separated ",\n " (mapper x.prefix) x.fields
837 let mapper prefix (f, _) = sprintf "ref %s_%s" prefix f in
838 let fields =
839 map_and_concat_separated ",\n " (mapper x.prefix) x.fields
841 sprintf
842 "SyntaxVariant::%s {
844 } => vec![%s],"
845 x.kind_name
846 fields
847 fields2
849 let into_children x =
850 let mapper prefix (f, _) = sprintf "x.%s_%s" prefix f in
851 let fields =
852 map_and_concat_separated ",\n " (mapper x.prefix) x.fields
854 sprintf
855 " SyntaxVariant::%s (x) => { vec!(
857 )},\n"
858 x.kind_name
859 fields
861 let fold_over x =
862 let mapper prefix (f, _) = sprintf "let acc = f(&x.%s_%s, acc)" prefix f in
863 let fields =
864 map_and_concat_separated ";\n " (mapper x.prefix) x.fields
866 sprintf
867 " SyntaxVariant::%s(x) => {
870 },\n"
871 x.kind_name
872 fields
874 let to_syntax_constructors x =
875 let mapper prefix (f, _) = sprintf "%s_%s: Self" prefix f in
876 let args = map_and_concat_separated ", " (mapper x.prefix) x.fields in
877 sprintf " fn make_%s(ctx: &C, %s) -> Self;\n" x.type_name args
879 let full_fidelity_syntax_template =
880 make_header CStyle ""
882 use crate::syntax::*;
884 pub trait SyntaxType<C>: SyntaxTypeBase<C>
886 SYNTAX_CONSTRUCTORS
890 let full_fidelity_syntax =
891 Full_fidelity_schema.make_template_file
892 ~transformations:
893 [{ pattern = "SYNTAX_CONSTRUCTORS"; func = to_syntax_constructors }]
894 ~filename:(full_fidelity_path_prefix ^ "syntax_type.rs")
895 ~template:full_fidelity_syntax_template
899 (* GenerateFFRustSyntaxType *)
901 module GenerateFFSyntaxSig = struct
902 let to_constructor_methods x =
903 let mapper1 (_f, _) = " t ->" in
904 let fields1 = map_and_concat mapper1 x.fields in
905 sprintf " val make_%s :%s t\n" x.type_name fields1
907 let to_type_tests x = sprintf " val is_%s : t -> bool\n" x.type_name
909 let to_syntax x =
910 let field_width = 50 - String.length x.prefix in
911 let fmt = sprintf "%s_%%-%ds: t\n" x.prefix field_width in
912 let mapper (f, _) = sprintf (Scanf.format_from_string fmt "%-1s") f in
913 let fields = map_and_concat_separated " ; " mapper x.fields in
914 sprintf
915 (" | " ^^ kind_name_fmt ^^ " of\n { %s }\n")
916 x.kind_name
917 fields
919 let full_fidelity_syntax_template : string =
920 make_header
921 MLStyle
923 * This module contains a signature which can be used to describe the public
924 * surface area of a constructable syntax tree.
928 module TriviaKind = Full_fidelity_trivia_kind
929 module TokenKind = Full_fidelity_token_kind
931 module type Syntax_S = sig
932 module Token : Lexable_token_sig.LexableToken_S
933 type value [@@deriving show, eq, sexp_of]
934 type t = { syntax : syntax ; value : value } [@@deriving show, eq, sexp_of]
935 and syntax =
936 | Token of Token.t
937 | Missing
938 | SyntaxList of t list
939 SYNTAX
940 [@@deriving sexp_of]
942 val rust_parse :
943 Full_fidelity_source_text.t ->
944 Full_fidelity_parser_env.t ->
945 unit * t * Full_fidelity_syntax_error.t list * Rust_pointer.t option
946 val rust_parser_errors :
947 Full_fidelity_source_text.t ->
948 Rust_pointer.t ->
949 ParserOptions.ffi_t ->
950 Full_fidelity_syntax_error.t list
951 val has_leading_trivia : TriviaKind.t -> Token.t -> bool
952 val to_json : ?with_value:bool -> ?ignore_missing:bool -> t -> Hh_json.json
953 val extract_text : t -> string option
954 val is_in_body : t -> int -> bool
955 val syntax_node_to_list : t -> t list
956 val width : t -> int
957 val full_width : t -> int
958 val trailing_width : t -> int
959 val leading_width : t -> int
960 val leading_token : t -> Token.t option
961 val children : t -> t list
962 val syntax : t -> syntax
963 val kind : t -> Full_fidelity_syntax_kind.t
964 val value : t -> value
965 val make_token : Token.t -> t
966 val get_token : t -> Token.t option
967 val all_tokens : t -> Token.t list
968 val make_missing : Full_fidelity_source_text.t -> int -> t
969 val make_list : Full_fidelity_source_text.t -> int -> t list -> t
970 val is_namespace_prefix : t -> bool
971 val syntax_list_fold : init:'a -> f:('a -> t -> 'a) -> t -> 'a
972 CONSTRUCTOR_METHODS
974 val position : Relative_path.t -> t -> Pos.t option
975 val offset : t -> int option
976 val is_missing : t -> bool
977 val is_list : t -> bool
978 TYPE_TESTS
980 val is_specific_token : TokenKind.t -> t -> bool
981 val is_loop_statement : t -> bool
982 val is_external : t -> bool
983 val is_name : t -> bool
984 val is_construct : t -> bool
985 val is_static : t -> bool
986 val is_private : t -> bool
987 val is_public : t -> bool
988 val is_protected : t -> bool
989 val is_abstract : t -> bool
990 val is_final : t -> bool
991 val is_async : t -> bool
992 val is_void : t -> bool
993 val is_left_brace : t -> bool
994 val is_ellipsis : t -> bool
995 val is_comma : t -> bool
996 val is_ampersand : t -> bool
997 val is_inout : t -> bool
1003 let full_fidelity_syntax_sig =
1004 Full_fidelity_schema.make_template_file
1005 ~transformations:
1007 { pattern = "SYNTAX"; func = to_syntax };
1008 { pattern = "CONSTRUCTOR_METHODS"; func = to_constructor_methods };
1009 { pattern = "TYPE_TESTS"; func = to_type_tests };
1011 ~filename:(full_fidelity_path_prefix ^ "syntax_sig.ml")
1012 ~template:full_fidelity_syntax_template
1016 (* GenerateFFSyntaxSig *)
1018 module GenerateFFSmartConstructors = struct
1019 let full_fidelity_smart_constructors_template : string =
1020 make_header
1021 MLStyle
1023 * This module contains a signature which can be used to describe smart
1024 * constructors.
1028 module ParserEnv = Full_fidelity_parser_env
1030 module type SmartConstructors_S = sig
1031 module Token : Lexable_token_sig.LexableToken_S
1033 type t (* state *) [@@deriving show, sexp_of]
1035 type r (* smart constructor return type *) [@@deriving show]
1037 val rust_parse :
1038 Full_fidelity_source_text.t ->
1039 ParserEnv.t ->
1040 t * r * Full_fidelity_syntax_error.t list * Rust_pointer.t option
1042 val initial_state : ParserEnv.t -> t
1046 let full_fidelity_smart_constructors =
1047 Full_fidelity_schema.make_template_file
1048 ~transformations:[]
1049 ~filename:
1050 (full_fidelity_path_prefix ^ "smart_constructors/smartConstructors.ml")
1051 ~template:full_fidelity_smart_constructors_template
1055 (* GenerateFFSmartConstructors *)
1057 module GenerateFFRustSmartConstructors = struct
1058 let to_make_methods x =
1059 let fields =
1060 List.mapi x.fields ~f:(fun i _ ->
1061 "arg" ^ string_of_int i ^ ": Self::Output")
1063 let stack = String.concat ~sep:", " fields in
1064 sprintf " fn make_%s(&mut self, %s) -> Self::Output;\n" x.type_name stack
1066 let full_fidelity_smart_constructors_template : string =
1067 make_header CStyle ""
1069 use parser_core_types::token_factory::TokenFactory;
1070 use parser_core_types::lexable_token::LexableToken;
1072 pub type Token<S> = <<S as SmartConstructors>::Factory as TokenFactory>::Token;
1073 pub type Trivia<S> = <Token<S> as LexableToken>::Trivia;
1075 pub trait SmartConstructors: Clone {
1076 type Factory: TokenFactory;
1077 type State;
1078 type Output;
1080 fn state_mut(&mut self) -> &mut Self::State;
1081 fn into_state(self) -> Self::State;
1082 fn token_factory_mut(&mut self) -> &mut Self::Factory;
1084 fn make_missing(&mut self, offset : usize) -> Self::Output;
1085 fn make_token(&mut self, arg0: Token<Self>) -> Self::Output;
1086 fn make_list(&mut self, arg0: Vec<Self::Output>, offset: usize) -> Self::Output;
1088 fn begin_enumerator(&mut self) {}
1089 fn begin_enum_class_enumerator(&mut self) {}
1090 fn begin_constant_declarator(&mut self) {}
1092 MAKE_METHODS
1096 let full_fidelity_smart_constructors =
1097 Full_fidelity_schema.make_template_file
1098 ~transformations:[{ pattern = "MAKE_METHODS"; func = to_make_methods }]
1099 ~filename:(full_fidelity_path_prefix ^ "smart_constructors_generated.rs")
1100 ~template:full_fidelity_smart_constructors_template
1104 (* GenerateFFRustSmartConstructors *)
1106 module GenerateFFRustPositionedSmartConstructors = struct
1107 let to_constructor_methods x =
1108 let args =
1109 List.mapi x.fields ~f:(fun i _ -> sprintf "arg%d: Self::Output" i)
1111 let args = String.concat ~sep:", " args in
1112 let fwd_args = List.mapi x.fields ~f:(fun i _ -> sprintf "arg%d" i) in
1113 let fwd_args = String.concat ~sep:", " fwd_args in
1114 sprintf
1115 " fn make_%s(&mut self, %s) -> Self::Output {
1116 <Self as SyntaxSmartConstructors<S, TF, St>>::make_%s(self, %s)
1117 }\n\n"
1118 x.type_name
1119 args
1120 x.type_name
1121 fwd_args
1123 let positioned_smart_constructors_template : string =
1124 make_header CStyle ""
1128 use parser_core_types::{
1129 syntax::*,
1130 lexable_token::LexableToken,
1131 token_factory::TokenFactory,
1133 use smart_constructors::SmartConstructors;
1134 use syntax_smart_constructors::{SyntaxSmartConstructors, StateType};
1136 #[derive(Clone)]
1137 pub struct PositionedSmartConstructors<S, TF, St: StateType<S>> {
1138 pub state: St,
1139 token_factory: TF,
1140 phantom_s: std::marker::PhantomData<S>,
1143 impl<S, TF, St: StateType<S>> PositionedSmartConstructors<S, TF, St> {
1144 pub fn new(state: St, token_factory: TF) -> Self {
1145 Self { state, token_factory, phantom_s: std::marker::PhantomData }
1149 impl<S, TF, St> SyntaxSmartConstructors<S, TF, St> for PositionedSmartConstructors<S, TF, St>
1150 where
1151 TF: TokenFactory<Token = S::Token>,
1152 St: StateType<S>,
1153 S: SyntaxType<St> + Clone,
1154 S::Token: LexableToken,
1157 impl<S, TF, St> SmartConstructors for PositionedSmartConstructors<S, TF, St>
1158 where
1159 TF: TokenFactory<Token = S::Token>,
1160 S::Token: LexableToken,
1161 S: SyntaxType<St> + Clone,
1162 St: StateType<S>,
1164 type Factory = TF;
1165 type State = St;
1166 type Output = S;
1168 fn state_mut(&mut self) -> &mut St {
1169 &mut self.state
1172 fn into_state(self) -> St {
1173 self.state
1176 fn token_factory_mut(&mut self) -> &mut Self::Factory {
1177 &mut self.token_factory
1180 fn make_missing(&mut self, offset: usize) -> Self::Output {
1181 <Self as SyntaxSmartConstructors<S, TF, St>>::make_missing(self, offset)
1184 fn make_token(&mut self, offset: <Self::Factory as TokenFactory>::Token) -> Self::Output {
1185 <Self as SyntaxSmartConstructors<S, TF, St>>::make_token(self, offset)
1188 fn make_list(&mut self, lst: Vec<Self::Output>, offset: usize) -> Self::Output {
1189 <Self as SyntaxSmartConstructors<S, TF, St>>::make_list(self, lst, offset)
1191 CONSTRUCTOR_METHODS}
1194 let positioned_smart_constructors =
1195 Full_fidelity_schema.make_template_file
1196 ~transformations:
1197 [{ pattern = "CONSTRUCTOR_METHODS"; func = to_constructor_methods }]
1198 ~filename:(full_fidelity_path_prefix ^ "positioned_smart_constructors.rs")
1199 ~template:positioned_smart_constructors_template
1203 module GenerateFFSyntaxSmartConstructors = struct
1204 let full_fidelity_syntax_smart_constructors_template : string =
1205 make_header
1206 MLStyle
1208 * This module contains smart constructors implementation that can be used to
1209 * build AST.
1212 open Sexplib.Std
1214 module type SC_S = SmartConstructors.SmartConstructors_S
1216 module ParserEnv = Full_fidelity_parser_env
1218 module type State_S = sig
1219 type r [@@deriving show]
1221 type t [@@deriving show, sexp_of]
1223 val initial : ParserEnv.t -> t
1225 val next : t -> r list -> t
1228 module type RustParser_S = sig
1229 type t
1231 type r
1233 val rust_parse :
1234 Full_fidelity_source_text.t ->
1235 ParserEnv.t ->
1236 t * r * Full_fidelity_syntax_error.t list * Rust_pointer.t option
1239 module WithSyntax (Syntax : Syntax_sig.Syntax_S) = struct
1240 module WithState (State : State_S with type r = Syntax.t) = struct
1241 module WithRustParser
1242 (RustParser : RustParser_S with type t = State.t with type r = Syntax.t) =
1243 struct
1244 module Token = Syntax.Token
1246 type t = State.t [@@deriving show, sexp_of]
1248 type r = Syntax.t [@@deriving show]
1250 let rust_parse = RustParser.rust_parse
1252 let initial_state = State.initial
1256 include WithState (struct
1257 type r = Syntax.t [@@deriving show]
1259 type t = unit [@@deriving show, sexp_of]
1261 let initial _ = ()
1263 let next () _ = ()
1264 end)
1266 include WithRustParser (struct
1267 type r = Syntax.t
1269 type t = unit
1271 let rust_parse = Syntax.rust_parse
1272 end)
1276 let full_fidelity_syntax_smart_constructors =
1277 Full_fidelity_schema.make_template_file
1278 ~transformations:[]
1279 ~filename:
1280 (full_fidelity_path_prefix
1281 ^ "smart_constructors/syntaxSmartConstructors.ml")
1282 ~template:full_fidelity_syntax_smart_constructors_template
1286 (* GenerateFFSyntaxSmartConstructors *)
1288 module GenerateFFRustSyntaxSmartConstructors = struct
1289 let to_constructor_methods x =
1290 let params =
1291 List.mapi x.fields ~f:(fun i _ -> sprintf "arg%d : Self::Output" i)
1293 let params = String.concat ~sep:", " params in
1294 let args = List.mapi x.fields ~f:(fun i _ -> sprintf "arg%d" i) in
1295 let args = String.concat ~sep:", " args in
1296 let next_args = List.mapi x.fields ~f:(fun i _ -> sprintf "&arg%d" i) in
1297 let next_args = String.concat ~sep:", " next_args in
1298 sprintf
1299 " fn make_%s(&mut self, %s) -> Self::Output {
1300 self.state_mut().next(&[%s]);
1301 Self::Output::make_%s(self.state_mut(), %s)
1302 }\n\n"
1303 x.type_name
1304 params
1305 next_args
1306 x.type_name
1307 args
1309 let full_fidelity_syntax_smart_constructors_template : string =
1310 make_header CStyle ""
1312 use parser_core_types::{
1313 syntax::*,
1314 token_factory::TokenFactory,
1316 use smart_constructors::{NoState, SmartConstructors};
1317 use crate::StateType;
1319 pub trait SyntaxSmartConstructors<S: SyntaxType<St>, TF: TokenFactory<Token = S::Token>, St = NoState>:
1320 SmartConstructors<State = St, Output=S, Factory = TF>
1321 where
1322 St: StateType<S>,
1324 fn make_missing(&mut self, offset: usize) -> Self::Output {
1325 let r = Self::Output::make_missing(self.state_mut(), offset);
1326 self.state_mut().next(&[]);
1330 fn make_token(&mut self, arg: <Self::Factory as TokenFactory>::Token) -> Self::Output {
1331 let r = Self::Output::make_token(self.state_mut(), arg);
1332 self.state_mut().next(&[]);
1336 fn make_list(&mut self, items: Vec<Self::Output>, offset: usize) -> Self::Output {
1337 if items.is_empty() {
1338 <Self as SyntaxSmartConstructors<S, TF, St>>::make_missing(self, offset)
1339 } else {
1340 let item_refs: Vec<_> = items.iter().collect();
1341 self.state_mut().next(&item_refs);
1342 Self::Output::make_list(self.state_mut(), items, offset)
1346 CONSTRUCTOR_METHODS}
1349 let full_fidelity_syntax_smart_constructors =
1350 Full_fidelity_schema.make_template_file
1351 ~transformations:
1352 [{ pattern = "CONSTRUCTOR_METHODS"; func = to_constructor_methods }]
1353 ~filename:
1354 (full_fidelity_path_prefix ^ "syntax_smart_constructors_generated.rs")
1355 ~template:full_fidelity_syntax_smart_constructors_template
1359 (* GenerateFFRustSyntaxSmartConstructors *)
1361 module GenerateFFRustDeclModeSmartConstructors = struct
1362 let to_constructor_methods x =
1363 let args =
1364 List.mapi x.fields ~f:(fun i _ -> sprintf "arg%d: Self::Output" i)
1366 let args = String.concat ~sep:", " args in
1367 let fwd_args = List.mapi x.fields ~f:(fun i _ -> sprintf "arg%d" i) in
1368 let fwd_args = String.concat ~sep:", " fwd_args in
1369 sprintf
1370 " fn make_%s(&mut self, %s) -> Self::Output {
1371 <Self as SyntaxSmartConstructors<Self::Output, Self::Factory, State<'_, '_, Self::Output>>>::make_%s(self, %s)
1372 }\n\n"
1373 x.type_name
1374 args
1375 x.type_name
1376 fwd_args
1378 let decl_mode_smart_constructors_template : string =
1379 make_header CStyle ""
1381 use parser_core_types::{
1382 lexable_token::LexableToken, syntax::SyntaxValueType, syntax_by_ref::syntax::Syntax,
1383 token_factory::TokenFactory,
1385 use smart_constructors::SmartConstructors;
1386 use syntax_smart_constructors::SyntaxSmartConstructors;
1387 use crate::*;
1389 impl<'s, 'a, Token, Value, TF> SmartConstructors
1390 for DeclModeSmartConstructors<'s, 'a, Syntax<'a, Token, Value>, Token, Value, TF>
1391 where
1392 TF: TokenFactory<Token = SyntaxToken<'s, 'a, Token, Value>>,
1393 Token: LexableToken + Copy,
1394 Value: SyntaxValueType<Token> + Clone,
1396 type State = State<'s, 'a, Syntax<'a, Token, Value>>;
1397 type Factory = TF;
1398 type Output = Syntax<'a, Token, Value>;
1400 fn state_mut(&mut self) -> &mut State<'s, 'a, Syntax<'a, Token, Value>> {
1401 &mut self.state
1404 fn into_state(self) -> State<'s, 'a, Syntax<'a, Token, Value>> {
1405 self.state
1408 fn token_factory_mut(&mut self) -> &mut Self::Factory {
1409 &mut self.token_factory
1412 fn make_missing(&mut self, o: usize) -> Self::Output {
1413 <Self as SyntaxSmartConstructors<Self::Output, Self::Factory, State<'_, '_, Self::Output>>>::make_missing(self, o)
1416 fn make_token(&mut self, token: <Self::Factory as TokenFactory>::Token) -> Self::Output {
1417 <Self as SyntaxSmartConstructors<Self::Output, Self::Factory, State<'_, '_, Self::Output>>>::make_token(self, token)
1420 fn make_list(&mut self, items: Vec<Self::Output>, offset: usize) -> Self::Output {
1421 <Self as SyntaxSmartConstructors<Self::Output, Self::Factory, State<'_, '_, Self::Output>>>::make_list(self, items, offset)
1424 CONSTRUCTOR_METHODS}
1427 let decl_mode_smart_constructors =
1428 Full_fidelity_schema.make_template_file
1429 ~transformations:
1430 [{ pattern = "CONSTRUCTOR_METHODS"; func = to_constructor_methods }]
1431 ~filename:
1432 (full_fidelity_path_prefix ^ "decl_mode_smart_constructors_generated.rs")
1433 ~template:decl_mode_smart_constructors_template
1437 (* GenerateFFRustDeclModeSmartConstructors *)
1439 module GenerateRustFlattenSmartConstructors = struct
1440 let to_constructor_methods x =
1441 let args =
1442 List.mapi x.fields ~f:(fun i _ -> sprintf "arg%d: Self::Output" i)
1444 let args = String.concat ~sep:", " args in
1445 let if_cond =
1446 List.mapi x.fields ~f:(fun i _ -> sprintf "Self::is_zero(&arg%d)" i)
1448 let if_cond = String.concat ~sep:" && " if_cond in
1449 let flatten_args = List.mapi x.fields ~f:(fun i _ -> sprintf "arg%d" i) in
1450 let flatten_args = String.concat ~sep:", " flatten_args in
1451 sprintf
1452 " fn make_%s(&mut self, %s) -> Self::Output {
1453 if %s {
1454 Self::zero(SyntaxKind::%s)
1455 } else {
1456 self.flatten(SyntaxKind::%s, vec!(%s))
1458 }\n\n"
1459 x.type_name
1460 args
1461 if_cond
1462 x.kind_name
1463 x.kind_name
1464 flatten_args
1466 let flatten_smart_constructors_template : string =
1467 make_header CStyle ""
1469 use smart_constructors::SmartConstructors;
1470 use parser_core_types::{
1471 lexable_token::LexableToken,
1472 syntax_kind::SyntaxKind,
1473 token_factory::TokenFactory,
1476 pub trait FlattenSmartConstructors: SmartConstructors
1478 fn is_zero(s: &Self::Output) -> bool;
1479 fn zero(kind: SyntaxKind) -> Self::Output;
1480 fn flatten(&self, kind: SyntaxKind, lst: Vec<Self::Output>) -> Self::Output;
1482 fn make_missing(&mut self, _: usize) -> Self::Output {
1483 Self::zero(SyntaxKind::Missing)
1486 fn make_token(&mut self, token: <Self::Factory as TokenFactory>::Token) -> Self::Output {
1487 Self::zero(SyntaxKind::Token(token.kind()))
1490 fn make_list(&mut self, _: Vec<Self::Output>, _: usize) -> Self::Output {
1491 Self::zero(SyntaxKind::SyntaxList)
1494 fn begin_enumerator(&mut self) {}
1496 fn begin_enum_class_enumerator(&mut self) {}
1498 fn begin_constant_declarator(&mut self) {}
1500 CONSTRUCTOR_METHODS}
1503 let flatten_smart_constructors =
1504 Full_fidelity_schema.make_template_file
1505 ~transformations:
1506 [{ pattern = "CONSTRUCTOR_METHODS"; func = to_constructor_methods }]
1507 ~filename:(full_fidelity_path_prefix ^ "flatten_smart_constructors.rs")
1508 ~template:flatten_smart_constructors_template
1512 (* GenerateRustFlattenSmartConstructors *)
1514 module GenerateRustDirectDeclSmartConstructors = struct
1515 let to_constructor_methods x =
1516 let args =
1517 List.map x.fields ~f:(fun (name, _) ->
1518 sprintf "%s: Self::Output" (escape_rust_keyword name))
1520 let args = String.concat ~sep:", " args in
1521 let fwd_args =
1522 List.map x.fields ~f:(fun (name, _) -> escape_rust_keyword name)
1524 let fwd_args = String.concat ~sep:", " fwd_args in
1525 sprintf
1526 " fn make_%s(&mut self, %s) -> Self::Output {
1527 <Self as FlattenSmartConstructors>::make_%s(self, %s)
1528 }\n\n"
1529 x.type_name
1530 args
1531 x.type_name
1532 fwd_args
1534 let direct_decl_smart_constructors_template : string =
1535 make_header CStyle ""
1537 use flatten_smart_constructors::*;
1538 use parser_core_types::compact_token::CompactToken;
1539 use parser_core_types::token_factory::SimpleTokenFactoryImpl;
1540 use smart_constructors::SmartConstructors;
1542 use crate::{DirectDeclSmartConstructors, Node, SourceTextAllocator};
1544 impl<'a, 'o, 't, S: SourceTextAllocator<'t, 'a>> SmartConstructors for DirectDeclSmartConstructors<'a, 'o, 't, S> {
1545 type State = Self;
1546 type Factory = SimpleTokenFactoryImpl<CompactToken>;
1547 type Output = Node<'a>;
1549 fn state_mut(&mut self) -> &mut Self {
1550 self
1553 fn into_state(self) -> Self {
1554 self
1557 fn token_factory_mut(&mut self) -> &mut Self::Factory {
1558 &mut self.token_factory
1561 fn make_missing(&mut self, offset: usize) -> Self::Output {
1562 <Self as FlattenSmartConstructors>::make_missing(self, offset)
1565 fn make_token(&mut self, token: CompactToken) -> Self::Output {
1566 <Self as FlattenSmartConstructors>::make_token(self, token)
1569 fn make_list(&mut self, items: Vec<Self::Output>, offset: usize) -> Self::Output {
1570 <Self as FlattenSmartConstructors>::make_list(self, items, offset)
1573 fn begin_enumerator(&mut self) {
1574 <Self as FlattenSmartConstructors>::begin_enumerator(self)
1577 fn begin_enum_class_enumerator(&mut self) {
1578 <Self as FlattenSmartConstructors>::begin_enum_class_enumerator(self)
1581 fn begin_constant_declarator(&mut self) {
1582 <Self as FlattenSmartConstructors>::begin_constant_declarator(self)
1587 CONSTRUCTOR_METHODS}
1590 let direct_decl_smart_constructors =
1591 Full_fidelity_schema.make_template_file
1592 ~transformations:
1593 [{ pattern = "CONSTRUCTOR_METHODS"; func = to_constructor_methods }]
1594 ~filename:
1595 (full_fidelity_path_prefix
1596 ^ "../decl/direct_decl_smart_constructors_generated.rs")
1597 ~template:direct_decl_smart_constructors_template
1601 (* GenerateRustDirectDeclSmartConstructors *)
1603 module GenerateRustPairSmartConstructors = struct
1604 let to_constructor_methods x =
1605 let args =
1606 List.map x.fields ~f:(fun (name, _) ->
1607 sprintf "%s: Self::Output" (escape_rust_keyword name))
1609 let args = String.concat ~sep:", " args in
1610 let fwd_args =
1611 List.map x.fields ~f:(fun (name, _) -> escape_rust_keyword name)
1613 let fwd_args idx =
1614 List.map fwd_args ~f:(fun name -> name ^ "." ^ idx)
1615 |> String.concat ~sep:", "
1617 sprintf
1618 " fn make_%s(&mut self, %s) -> Self::Output {
1619 Node(self.0.make_%s(%s), self.1.make_%s(%s))
1620 }\n\n"
1621 x.type_name
1622 args
1623 x.type_name
1624 (fwd_args "0")
1625 x.type_name
1626 (fwd_args "1")
1628 let pair_smart_constructors_template : string =
1629 make_header CStyle ""
1632 use parser_core_types::token_factory::TokenFactory;
1633 use smart_constructors::{NodeType, SmartConstructors};
1635 use crate::{PairTokenFactory, Node};
1637 #[derive(Clone)]
1638 pub struct PairSmartConstructors<SC0, SC1>(pub SC0, pub SC1, PairTokenFactory<SC0::Factory, SC1::Factory>)
1639 where
1640 SC0: SmartConstructors,
1641 SC0::Output: NodeType,
1642 SC1: SmartConstructors,
1643 SC1::Output: NodeType;
1645 impl<SC0, SC1> PairSmartConstructors<SC0, SC1>
1646 where
1647 SC0: SmartConstructors,
1648 SC0::Output: NodeType,
1649 SC1: SmartConstructors,
1650 SC1::Output: NodeType,
1652 pub fn new(mut sc0: SC0, mut sc1: SC1) -> Self {
1653 let tf0 = sc0.token_factory_mut().clone();
1654 let tf1 = sc1.token_factory_mut().clone();
1655 let tf = PairTokenFactory::new(tf0, tf1);
1656 Self(sc0, sc1, tf)
1660 impl<SC0, SC1> SmartConstructors for PairSmartConstructors<SC0, SC1>
1661 where
1662 SC0: SmartConstructors,
1663 SC0::Output: NodeType,
1664 SC1: SmartConstructors,
1665 SC1::Output: NodeType,
1667 type State = Self;
1668 type Factory = PairTokenFactory<SC0::Factory, SC1::Factory>;
1669 type Output = Node<SC0::Output, SC1::Output>;
1671 fn state_mut(&mut self) -> &mut Self {
1672 self
1675 fn into_state(self) -> Self {
1676 self
1679 fn token_factory_mut(&mut self) -> &mut Self::Factory {
1680 &mut self.2
1683 fn make_missing(&mut self, offset: usize) -> Self::Output {
1684 Node(self.0.make_missing(offset), self.1.make_missing(offset))
1687 fn make_token(&mut self, token: <Self::Factory as TokenFactory>::Token) -> Self::Output {
1688 Node(self.0.make_token(token.0), self.1.make_token(token.1))
1691 fn make_list(&mut self, items: Vec<Self::Output>, offset: usize) -> Self::Output {
1692 let (items0, items1) = items.into_iter().map(|n| (n.0, n.1)).unzip();
1693 Node(self.0.make_list(items0, offset), self.1.make_list(items1, offset))
1696 CONSTRUCTOR_METHODS}
1699 let pair_smart_constructors =
1700 Full_fidelity_schema.make_template_file
1701 ~transformations:
1702 [{ pattern = "CONSTRUCTOR_METHODS"; func = to_constructor_methods }]
1703 ~filename:
1704 (full_fidelity_path_prefix ^ "pair_smart_constructors_generated.rs")
1705 ~template:pair_smart_constructors_template
1709 (* GenerateRustPairSmartConstructors *)
1711 module GenerateFFSmartConstructorsWrappers = struct
1712 let full_fidelity_smart_constructors_wrappers_template : string =
1713 make_header
1714 MLStyle
1716 * This module contains smart constructors implementation that can be used to
1717 * build AST.
1721 module type SC_S = SmartConstructors.SmartConstructors_S
1723 module SK = Full_fidelity_syntax_kind
1725 module type SyntaxKind_S = sig
1726 include SC_S
1728 type original_sc_r [@@deriving show]
1731 module SyntaxKind (SC : SC_S) :
1732 SyntaxKind_S
1733 with module Token = SC.Token
1734 and type original_sc_r = SC.r
1735 and type t = SC.t = struct
1736 module Token = SC.Token
1738 type original_sc_r = SC.r [@@deriving show]
1740 type t = SC.t [@@deriving show, sexp_of]
1742 type r = SK.t * SC.r [@@deriving show]
1744 let compose : SK.t -> t * SC.r -> t * r =
1745 (fun kind (state, res) -> (state, (kind, res)))
1747 let rust_parse text env =
1748 let (state, res, errors, pointer) = SC.rust_parse text env in
1749 let (state, res) = compose SK.Script (state, res) in
1750 (state, res, errors, pointer)
1752 let initial_state = SC.initial_state
1756 let full_fidelity_smart_constructors_wrappers =
1757 Full_fidelity_schema.make_template_file
1758 ~transformations:[]
1759 ~filename:
1760 (full_fidelity_path_prefix
1761 ^ "smart_constructors/smartConstructorsWrappers.ml")
1762 ~template:full_fidelity_smart_constructors_wrappers_template
1766 (* GenerateFFSmartConstructorsWrappers *)
1768 module GenerateFFRustSmartConstructorsWrappers = struct
1769 let to_constructor_methods x =
1770 let params =
1771 List.mapi x.fields ~f:(fun i _ ->
1772 "arg" ^ string_of_int i ^ " : Self::Output")
1774 let params = String.concat ~sep:", " params in
1775 let args = List.mapi x.fields ~f:(fun i _ -> sprintf "arg%d" i) in
1776 let raw_args = map_and_concat_separated ", " (fun x -> x ^ ".1") args in
1777 sprintf
1778 " fn make_%s(&mut self, %s) -> Self::Output {
1779 compose(SyntaxKind::%s, self.s.make_%s(%s))
1780 }\n"
1781 x.type_name
1782 params
1783 x.kind_name
1784 x.type_name
1785 raw_args
1787 let full_fidelity_smart_constructors_wrappers_template : string =
1788 make_header CStyle ""
1790 // This module contains smart constructors implementation that can be used to
1791 // build AST.
1794 use parser_core_types::{
1795 lexable_token::LexableToken,
1796 syntax_kind::SyntaxKind,
1797 token_factory::TokenFactory,
1799 use crate::SmartConstructors;
1801 #[derive(Clone)]
1802 pub struct WithKind<S> {
1803 s: S,
1806 impl<S> WithKind<S> {
1807 pub fn new(s: S) -> Self {
1808 Self { s }
1812 impl<S, St> SmartConstructors for WithKind<S>
1813 where S: SmartConstructors<State = St>,
1815 type Factory = S::Factory;
1816 type State = St;
1817 type Output = (SyntaxKind, S::Output);
1819 fn state_mut(&mut self) -> &mut St {
1820 self.s.state_mut()
1823 fn into_state(self) -> St {
1824 self.s.into_state()
1827 fn token_factory_mut(&mut self) -> &mut Self::Factory {
1828 self.s.token_factory_mut()
1832 fn make_token(&mut self, token: <Self::Factory as TokenFactory>::Token) -> Self::Output {
1833 compose(SyntaxKind::Token(token.kind()), self.s.make_token(token))
1836 fn make_missing(&mut self, p: usize) -> Self::Output {
1837 compose(SyntaxKind::Missing, self.s.make_missing(p))
1840 fn make_list(&mut self, items: Vec<Self::Output>, p: usize) -> Self::Output {
1841 let kind = if items.is_empty() {
1842 SyntaxKind::Missing
1843 } else {
1844 SyntaxKind::SyntaxList
1846 compose(kind, self.s.make_list(items.into_iter().map(|x| x.1).collect(), p))
1849 CONSTRUCTOR_METHODS
1852 #[inline(always)]
1853 fn compose<R>(kind: SyntaxKind, r: R) -> (SyntaxKind, R) {
1854 (kind, r)
1858 let full_fidelity_smart_constructors_wrappers =
1859 Full_fidelity_schema.make_template_file
1860 ~transformations:
1861 [{ pattern = "CONSTRUCTOR_METHODS"; func = to_constructor_methods }]
1862 ~filename:(full_fidelity_path_prefix ^ "smart_constructors_wrappers.rs")
1863 ~template:full_fidelity_smart_constructors_wrappers_template
1867 (* GenerateFFRustSmartConstructorsWrappers *)
1869 module GenerateFFSyntax = struct
1870 let to_to_kind x =
1871 sprintf
1872 (" | " ^^ kind_name_fmt ^^ " _ -> SyntaxKind.%s\n")
1873 x.kind_name
1874 x.kind_name
1876 let to_type_tests x =
1877 sprintf
1878 (" let is_" ^^ type_name_fmt ^^ " = has_kind SyntaxKind.%s\n")
1879 x.type_name
1880 x.kind_name
1882 let to_children x =
1883 let mapper (f, _) = sprintf " %s_%s;\n" x.prefix f in
1884 let fields = map_and_concat mapper x.fields in
1885 sprintf
1886 " | %s {\n%s } -> [\n%s ]\n"
1887 x.kind_name
1888 fields
1889 fields
1891 let to_fold_from_syntax x =
1892 let mapper (f, _) = sprintf " %s_%s;\n" x.prefix f in
1893 let fields = map_and_concat mapper x.fields in
1894 let mapper2 (f, _) =
1895 sprintf " let acc = f acc %s_%s in\n" x.prefix f
1897 let fields2 = map_and_concat mapper2 x.fields in
1898 sprintf
1899 " | %s {\n%s } ->\n%s acc\n"
1900 x.kind_name
1901 fields
1902 fields2
1904 let to_children_names x =
1905 let mapper1 (f, _) = sprintf " %s_%s;\n" x.prefix f in
1906 let mapper2 (f, _) = sprintf " \"%s_%s\";\n" x.prefix f in
1907 let fields1 = map_and_concat mapper1 x.fields in
1908 let fields2 = map_and_concat mapper2 x.fields in
1909 sprintf
1910 " | %s {\n%s } -> [\n%s ]\n"
1911 x.kind_name
1912 fields1
1913 fields2
1915 let to_syntax_from_children x =
1916 let mapper (f, _) = sprintf " %s_%s;\n" x.prefix f in
1917 let fields = map_and_concat mapper x.fields in
1918 sprintf
1919 " | (SyntaxKind.%s, [
1920 %s ]) ->
1921 %s {
1922 %s }
1924 x.kind_name
1925 fields
1926 x.kind_name
1927 fields
1929 let to_constructor_methods x =
1930 let mapper1 (f, _) = sprintf " %s_%s\n" x.prefix f in
1931 let fields1 = map_and_concat mapper1 x.fields in
1932 let mapper2 (f, _) = sprintf " %s_%s;\n" x.prefix f in
1933 let fields2 = map_and_concat mapper2 x.fields in
1934 sprintf
1935 " let make_%s
1936 %s =
1937 let syntax = %s {
1938 %s } in
1939 let value = ValueBuilder.value_from_syntax syntax in
1940 make syntax value
1943 x.type_name
1944 fields1
1945 x.kind_name
1946 fields2
1948 let to_from_methods x =
1949 if omit_syntax_record x then
1951 else
1952 let mapper (f, _) = sprintf " %s_%s;\n" x.prefix f in
1953 let fields = map_and_concat mapper x.fields in
1954 sprintf
1955 " let from_%s {
1956 %s } = %s {
1957 %s }
1959 x.type_name
1960 fields
1961 x.kind_name
1962 fields
1964 let to_get_methods x =
1965 if omit_syntax_record x then
1967 else
1968 let mapper (f, _) = sprintf " %s_%s;\n" x.prefix f in
1969 let fields = map_and_concat mapper x.fields in
1970 sprintf
1971 " let get_%s x =
1972 match x with
1973 | %s {\n%s } -> {\n%s }
1974 | _ -> failwith \"get_%s: not a %s\"
1976 x.type_name
1977 x.kind_name
1978 fields
1979 fields
1980 x.type_name
1981 x.kind_name
1983 let full_fidelity_syntax_template =
1984 make_header
1985 MLStyle
1987 * With these factory methods, nodes can be built up from their child nodes. A
1988 * factory method must not just know all the children and the kind of node it is
1989 * constructing; it also must know how to construct the value that this node is
1990 * going to be tagged with. For that reason, an optional functor is provided.
1991 * This functor requires that methods be provided to construct the values
1992 * associated with a token or with any arbitrary node, given its children. If
1993 * this functor is used then the resulting module contains factory methods.
1995 * This module also provides some useful helper functions, like an iterator,
1996 * a rewriting visitor, and so on."
1999 open Hh_prelude
2000 open Full_fidelity_syntax_type
2002 module SyntaxKind = Full_fidelity_syntax_kind
2003 module TokenKind = Full_fidelity_token_kind
2004 module Operator = Full_fidelity_operator
2005 [@@@warning \"-27\"] (* unused variable *)
2007 module WithToken(Token: TokenType) = struct
2008 module WithSyntaxValue(SyntaxValue: SyntaxValueType) = struct
2010 include MakeSyntaxType(Token)(SyntaxValue)
2012 let make syntax value =
2013 { syntax; value }
2015 let syntax node =
2016 node.syntax
2018 let value node =
2019 node.value
2021 let syntax_node_to_list node =
2022 match syntax node with
2023 | SyntaxList x -> x
2024 | Missing -> []
2025 | _ -> [node]
2027 let to_kind syntax =
2028 match syntax with
2029 | Missing -> SyntaxKind.Missing
2030 | Token t -> SyntaxKind.Token (Token.kind t)
2031 | SyntaxList _ -> SyntaxKind.SyntaxList
2032 TO_KIND
2034 let kind node =
2035 to_kind (syntax node)
2037 let has_kind syntax_kind node =
2038 SyntaxKind.equal (kind node) syntax_kind
2040 let is_missing node =
2041 match kind node with
2042 | SyntaxKind.Missing -> true
2043 | _ -> false
2045 let is_list node =
2046 match kind node with
2047 | SyntaxKind.SyntaxList -> true
2048 | _ -> false
2050 TYPE_TESTS
2052 let is_loop_statement node =
2053 is_for_statement node ||
2054 is_foreach_statement node ||
2055 is_while_statement node ||
2056 is_do_statement node
2058 let is_separable_prefix node =
2059 match syntax node with
2060 | Token t -> begin
2061 TokenKind.(match Token.kind t with
2062 | PlusPlus | MinusMinus -> false
2063 | _ -> true) end
2064 | _ -> true
2066 let is_specific_token kind node =
2067 match syntax node with
2068 | Token t -> TokenKind.equal (Token.kind t) kind
2069 | _ -> false
2071 let is_namespace_prefix node =
2072 match syntax node with
2073 | QualifiedName e ->
2074 begin match List.last (syntax_node_to_list e.qualified_name_parts) with
2075 | None -> false
2076 | Some p ->
2077 begin match syntax p with
2078 | ListItem p -> not (is_missing p.list_separator)
2079 | _ -> false
2082 | _ -> false
2084 let has_leading_trivia kind token =
2085 List.exists (Token.leading token)
2086 ~f:(fun trivia ->
2087 Full_fidelity_trivia_kind.equal (Token.Trivia.kind trivia) kind)
2089 let is_external e =
2090 is_specific_token TokenKind.Semicolon e || is_missing e
2092 let is_name = is_specific_token TokenKind.Name
2093 let is_construct = is_specific_token TokenKind.Construct
2094 let is_static = is_specific_token TokenKind.Static
2095 let is_private = is_specific_token TokenKind.Private
2096 let is_public = is_specific_token TokenKind.Public
2097 let is_protected = is_specific_token TokenKind.Protected
2098 let is_abstract = is_specific_token TokenKind.Abstract
2099 let is_final = is_specific_token TokenKind.Final
2100 let is_async = is_specific_token TokenKind.Async
2101 let is_void = is_specific_token TokenKind.Void
2102 let is_left_brace = is_specific_token TokenKind.LeftBrace
2103 let is_ellipsis = is_specific_token TokenKind.DotDotDot
2104 let is_comma = is_specific_token TokenKind.Comma
2105 let is_ampersand = is_specific_token TokenKind.Ampersand
2106 let is_inout = is_specific_token TokenKind.Inout
2108 let syntax_list_fold ~init ~f node =
2109 match syntax node with
2110 | SyntaxList sl ->
2111 List.fold_left
2112 ~init
2113 ~f:(fun init li -> match syntax li with
2114 | ListItem { list_item; _; }-> f init list_item
2115 | Missing -> init
2116 | _ -> f init li)
2118 | Missing -> init
2119 | _ -> f init node
2121 let fold_over_children f acc syntax =
2122 match syntax with
2123 | Missing -> acc
2124 | Token _ -> acc
2125 | SyntaxList items ->
2126 List.fold_left ~f ~init:acc items
2127 FOLD_FROM_SYNTAX
2129 (* The order that the children are returned in should match the order
2130 that they appear in the source text *)
2131 let children_from_syntax s =
2132 match s with
2133 | Missing -> []
2134 | Token _ -> []
2135 | SyntaxList x -> x
2136 CHILDREN
2138 let children node =
2139 children_from_syntax node.syntax
2141 let children_names node =
2142 match node.syntax with
2143 | Missing -> []
2144 | Token _ -> []
2145 | SyntaxList _ -> []
2146 CHILDREN_NAMES
2148 let rec to_json_ ?(with_value = false) ?(ignore_missing = false) node =
2149 let open Hh_json in
2150 let ch = match node.syntax with
2151 | Token t -> [ \"token\", Token.to_json t ]
2152 | SyntaxList x -> [ (\"elements\",
2153 JSON_Array (List.filter_map ~f:(to_json_ ~with_value ~ignore_missing) x)) ]
2154 | _ ->
2155 let rec aux acc c n =
2156 match c, n with
2157 | ([], []) -> acc
2158 | ((hc :: tc), (hn :: tn)) ->
2159 let result = (to_json_ ~with_value ~ignore_missing) hc in
2160 (match result with
2161 | Some r -> aux ((hn, r):: acc) tc tn
2162 | None -> aux acc tc tn)
2163 | _ -> failwith \"mismatch between children and names\" in
2164 List.rev (aux [] (children node) (children_names node)) in
2165 let k = (\"kind\", JSON_String (SyntaxKind.to_string (kind node))) in
2166 let v = if with_value then
2167 (\"value\", SyntaxValue.to_json node.value) :: ch
2168 else ch in
2169 if ignore_missing && (List.is_empty ch) then None else Some(JSON_Object (k :: v))
2171 let to_json ?(with_value = false) ?(ignore_missing = false) node =
2172 match to_json_ ~with_value ~ignore_missing node with
2173 | Some x -> x
2174 | None -> Hh_json.JSON_Object([])
2176 let binary_operator_kind b =
2177 match syntax b with
2178 | Token token ->
2179 let kind = Token.kind token in
2180 if Operator.is_trailing_operator_token kind then
2181 Some (Operator.trailing_from_token kind)
2182 else
2183 None
2184 | _ -> None
2186 let get_token node =
2187 match (syntax node) with
2188 | Token token -> Some token
2189 | _ -> None
2191 let leading_token node =
2192 let rec aux nodes =
2193 match nodes with
2194 | [] -> None
2195 | h :: t ->
2196 let token = get_token h in
2197 if Option.is_none token then
2198 let result = aux (children h) in
2199 if Option.is_none result then aux t else result
2200 else
2201 token in
2202 aux [node]
2204 let trailing_token node =
2205 let rec aux nodes =
2206 match nodes with
2207 | [] -> None
2208 | h :: t ->
2209 let token = get_token h in
2210 if Option.is_none token then
2211 let result = aux (List.rev (children h)) in
2212 if Option.is_none result then aux t else result
2213 else
2214 token in
2215 aux [node]
2217 let syntax_from_children kind ts =
2218 match kind, ts with
2219 SYNTAX_FROM_CHILDREN | (SyntaxKind.Missing, []) -> Missing
2220 | (SyntaxKind.SyntaxList, items) -> SyntaxList items
2221 | _ -> failwith
2222 \"syntax_from_children called with wrong number of children\"
2224 let all_tokens node =
2225 let rec aux acc nodes =
2226 match nodes with
2227 | [] -> acc
2228 | h :: t ->
2229 begin
2230 match syntax h with
2231 | Token token -> aux (token :: acc) t
2232 | _ -> aux (aux acc (children h)) t
2233 end in
2234 List.rev (aux [] [node])
2236 module type ValueBuilderType = sig
2237 val value_from_children:
2238 Full_fidelity_source_text.t ->
2239 int -> (* offset *)
2240 Full_fidelity_syntax_kind.t ->
2241 t list ->
2242 SyntaxValue.t
2243 val value_from_token: Token.t -> SyntaxValue.t
2244 val value_from_syntax: syntax -> SyntaxValue.t
2247 module WithValueBuilder(ValueBuilder: ValueBuilderType) = struct
2248 let from_children text offset kind ts =
2249 let syntax = syntax_from_children kind ts in
2250 let value = ValueBuilder.value_from_children text offset kind ts in
2251 make syntax value
2253 let make_token token =
2254 let syntax = Token token in
2255 let value = ValueBuilder.value_from_token token in
2256 make syntax value
2258 let make_missing text offset =
2259 from_children text offset SyntaxKind.Missing []
2261 (* An empty list is represented by Missing; everything else is a
2262 SyntaxList, even if the list has only one item. *)
2263 let make_list text offset items =
2264 match items with
2265 | [] -> make_missing text offset
2266 | _ -> from_children text offset SyntaxKind.SyntaxList items
2268 CONSTRUCTOR_METHODS
2270 FROM_METHODS
2272 GET_METHODS
2279 let full_fidelity_syntax =
2280 Full_fidelity_schema.make_template_file
2281 ~transformations:
2283 { pattern = "TO_KIND"; func = to_to_kind };
2284 { pattern = "TYPE_TESTS"; func = to_type_tests };
2285 { pattern = "CHILDREN"; func = to_children };
2286 { pattern = "FOLD_FROM_SYNTAX"; func = to_fold_from_syntax };
2287 { pattern = "CHILDREN_NAMES"; func = to_children_names };
2288 { pattern = "SYNTAX_FROM_CHILDREN"; func = to_syntax_from_children };
2289 { pattern = "CONSTRUCTOR_METHODS"; func = to_constructor_methods };
2290 { pattern = "FROM_METHODS"; func = to_from_methods };
2291 { pattern = "GET_METHODS"; func = to_get_methods };
2293 ~filename:(full_fidelity_path_prefix ^ "full_fidelity_syntax.ml")
2294 ~template:full_fidelity_syntax_template
2298 module GenerateFFTriviaKind = struct
2299 let to_trivia { trivia_kind; trivia_text = _ } =
2300 sprintf " | %s\n" trivia_kind
2302 let to_to_string { trivia_kind; trivia_text } =
2303 sprintf
2304 (" | " ^^ trivia_kind_fmt ^^ " -> \"%s\"\n")
2305 trivia_kind
2306 trivia_text
2308 let full_fidelity_trivia_kind_template =
2309 make_header MLStyle ""
2312 type t =
2313 TRIVIA
2314 [@@deriving show, enum, eq, sexp_of]
2316 let to_string kind =
2317 match kind with
2318 TO_STRING"
2320 let full_fidelity_trivia_kind =
2321 Full_fidelity_schema.make_template_file
2322 ~trivia_transformations:
2324 { trivia_pattern = "TRIVIA"; trivia_func = map_and_concat to_trivia };
2326 trivia_pattern = "TO_STRING";
2327 trivia_func = map_and_concat to_to_string;
2330 ~filename:(full_fidelity_path_prefix ^ "/full_fidelity_trivia_kind.ml")
2331 ~template:full_fidelity_trivia_kind_template
2335 (* GenerateFFSyntaxKind *)
2337 module GenerateFFRustTriviaKind = struct
2338 let ocaml_tag = ref (-1)
2340 let to_trivia { trivia_kind; trivia_text = _ } =
2341 incr ocaml_tag;
2342 sprintf " %s = %d,\n" trivia_kind !ocaml_tag
2344 let to_to_string { trivia_kind; trivia_text } =
2345 sprintf " TriviaKind::%s => \"%s\",\n" trivia_kind trivia_text
2347 let full_fidelity_trivia_kind_template =
2348 make_header CStyle ""
2351 use ocamlrep::{FromOcamlRep, ToOcamlRep};
2353 #[derive(Debug, Copy, Clone, FromOcamlRep, ToOcamlRep, PartialEq)]
2354 #[repr(u8)]
2355 pub enum TriviaKind {
2356 TRIVIA}
2358 impl TriviaKind {
2359 pub fn to_string(&self) -> &str {
2360 match self {
2361 TO_STRING }
2364 pub const fn ocaml_tag(self) -> u8 {
2365 self as u8
2370 let full_fidelity_trivia_kind =
2371 Full_fidelity_schema.make_template_file
2372 ~trivia_transformations:
2374 { trivia_pattern = "TRIVIA"; trivia_func = map_and_concat to_trivia };
2376 trivia_pattern = "TO_STRING";
2377 trivia_func = map_and_concat to_to_string;
2380 ~filename:(full_fidelity_path_prefix ^ "trivia_kind.rs")
2381 ~template:full_fidelity_trivia_kind_template
2385 (* GenerateFFRustTriviaKind *)
2387 module GenerateFFSyntaxKind = struct
2388 let to_tokens x = sprintf " | %s\n" x.kind_name
2390 let to_to_string x =
2391 sprintf
2392 (" | " ^^ kind_name_fmt ^^ " -> \"%s\"\n")
2393 x.kind_name
2394 x.description
2396 let full_fidelity_syntax_kind_template =
2397 make_header MLStyle ""
2400 type t =
2401 | Token of Full_fidelity_token_kind.t
2402 | Missing
2403 | SyntaxList
2404 TOKENS
2405 [@@deriving show, eq]
2407 let to_string kind =
2408 match kind with
2409 | Token _ -> \"token\"
2410 | Missing -> \"missing\"
2411 | SyntaxList -> \"list\"
2412 TO_STRING"
2414 let full_fidelity_syntax_kind =
2415 Full_fidelity_schema.make_template_file
2416 ~transformations:
2418 { pattern = "TOKENS"; func = to_tokens };
2419 { pattern = "TO_STRING"; func = to_to_string };
2421 ~filename:(full_fidelity_path_prefix ^ "full_fidelity_syntax_kind.ml")
2422 ~template:full_fidelity_syntax_kind_template
2426 (* GenerateFFTriviaKind *)
2428 module GenerateFFRustSyntaxKind = struct
2429 let to_tokens x = sprintf " %s,\n" x.kind_name
2431 let to_to_string x =
2432 sprintf
2433 (" SyntaxKind::" ^^ kind_name_fmt ^^ " => \"%s\",\n")
2434 x.kind_name
2435 x.description
2437 let tag = ref 1
2439 let to_ocaml_tag x =
2440 incr tag;
2441 sprintf " SyntaxKind::%s => %d,\n" x.kind_name !tag
2443 let full_fidelity_syntax_kind_template =
2444 make_header CStyle ""
2447 use ocamlrep::{FromOcamlRep, ToOcamlRep};
2449 use crate::token_kind::TokenKind;
2451 #[derive(Debug, Copy, Clone, FromOcamlRep, ToOcamlRep, PartialEq)]
2452 pub enum SyntaxKind {
2453 Missing,
2454 Token(TokenKind),
2455 SyntaxList,
2456 TOKENS
2459 impl SyntaxKind {
2460 pub fn to_string(&self) -> &str {
2461 match self {
2462 SyntaxKind::SyntaxList => \"list\",
2463 SyntaxKind::Missing => \"missing\",
2464 SyntaxKind::Token(_) => \"token\",
2465 TO_STRING }
2468 pub fn ocaml_tag(self) -> u8 {
2469 match self {
2470 SyntaxKind::Missing => 0,
2471 SyntaxKind::Token(_) => 0,
2472 SyntaxKind::SyntaxList => 1,
2473 OCAML_TAG }
2478 let full_fidelity_syntax_kind =
2479 Full_fidelity_schema.make_template_file
2480 ~transformations:
2482 { pattern = "TOKENS"; func = to_tokens };
2483 { pattern = "TO_STRING"; func = to_to_string };
2484 { pattern = "OCAML_TAG"; func = to_ocaml_tag };
2486 ~filename:(full_fidelity_path_prefix ^ "syntax_kind.rs")
2487 ~template:full_fidelity_syntax_kind_template
2491 (* GenerateFFRustSyntaxKind *)
2493 module GenerateFFTokenKind = struct
2494 let given_text_width =
2495 let folder acc x = max acc (String.length x.token_text) in
2496 List.fold_left ~f:folder ~init:0 given_text_tokens
2498 let to_kind_declaration x = sprintf " | %s\n" x.token_kind
2500 let add_guard_or_pad :
2501 cond:bool * string -> ?else_cond:bool * string -> string -> string =
2502 fun ~cond:(cond, guard) ?else_cond guards ->
2503 let pad str = String.make (String.length str) ' ' in
2504 let is_only_spaces str = String.equal str (pad str) in
2505 let make_same_length str1 str2 =
2506 let blanks n =
2507 try String.make n ' ' with
2508 | Invalid_argument _ -> ""
2510 let (len1, len2) = (String.length str1, String.length str2) in
2511 let str1 = str1 ^ blanks (len2 - len1) in
2512 let str2 = str2 ^ blanks (len1 - len2) in
2513 (str1, str2)
2515 let (else_cond, else_guard) =
2516 match else_cond with
2517 | Some (cond, guard) -> (cond, guard)
2518 | None -> (false, "")
2520 let prefix =
2521 if cond || else_cond then
2522 if is_only_spaces guards then
2523 "when "
2524 else
2525 "&& "
2526 else
2529 let (guard, else_guard) = make_same_length guard else_guard in
2530 let guard =
2531 if cond then
2532 guard
2533 else if else_cond then
2534 else_guard
2535 else
2536 pad guard
2538 guards ^ prefix ^ guard ^ " "
2540 let to_from_string x =
2541 let token_text = escape_token_text x.token_text in
2542 let spacer_width = given_text_width - String.length token_text in
2543 let spacer = String.make spacer_width ' ' in
2544 let guards =
2545 add_guard_or_pad "" ~cond:(x.allowed_as_identifier, "not only_reserved")
2547 sprintf " | \"%s\"%s %s-> Some %s\n" token_text spacer guards x.token_kind
2549 let to_to_string x =
2550 let token_text = escape_token_text x.token_text in
2551 sprintf (" | " ^^ token_kind_fmt ^^ " -> \"%s\"\n") x.token_kind token_text
2553 let to_is_variable_text x = sprintf " | %s -> true\n" x.token_kind
2555 let full_fidelity_token_kind_template =
2556 make_header MLStyle ""
2559 type t =
2560 (* No text tokens *)
2561 KIND_DECLARATIONS_NO_TEXT (* Given text tokens *)
2562 KIND_DECLARATIONS_GIVEN_TEXT (* Variable text tokens *)
2563 KIND_DECLARATIONS_VARIABLE_TEXT
2564 [@@deriving show, eq, sexp_of]
2566 let from_string keyword ~only_reserved =
2567 match keyword with
2568 | \"true\" when not only_reserved -> Some BooleanLiteral
2569 | \"false\" when not only_reserved -> Some BooleanLiteral
2570 FROM_STRING_GIVEN_TEXT | _ -> None
2572 let to_string kind =
2573 match kind with
2574 (* No text tokens *)
2575 TO_STRING_NO_TEXT (* Given text tokens *)
2576 TO_STRING_GIVEN_TEXT (* Variable text tokens *)
2577 TO_STRING_VARIABLE_TEXT
2579 let is_variable_text kind =
2580 match kind with
2581 IS_VARIABLE_TEXT_VARIABLE_TEXT | _ -> false
2584 let full_fidelity_token_kind =
2585 Full_fidelity_schema.make_template_file
2586 ~token_no_text_transformations:
2589 token_pattern = "KIND_DECLARATIONS_NO_TEXT";
2590 token_func = map_and_concat to_kind_declaration;
2593 token_pattern = "TO_STRING_NO_TEXT";
2594 token_func = map_and_concat to_to_string;
2597 ~token_given_text_transformations:
2600 token_pattern = "KIND_DECLARATIONS_GIVEN_TEXT";
2601 token_func = map_and_concat to_kind_declaration;
2604 token_pattern = "FROM_STRING_GIVEN_TEXT";
2605 token_func = map_and_concat to_from_string;
2608 token_pattern = "TO_STRING_GIVEN_TEXT";
2609 token_func = map_and_concat to_to_string;
2612 ~token_variable_text_transformations:
2615 token_pattern = "KIND_DECLARATIONS_VARIABLE_TEXT";
2616 token_func = map_and_concat to_kind_declaration;
2619 token_pattern = "TO_STRING_VARIABLE_TEXT";
2620 token_func = map_and_concat to_to_string;
2623 token_pattern = "IS_VARIABLE_TEXT_VARIABLE_TEXT";
2624 token_func = map_and_concat to_is_variable_text;
2627 ~filename:(full_fidelity_path_prefix ^ "full_fidelity_token_kind.ml")
2628 ~template:full_fidelity_token_kind_template
2632 (* GenerateFFTokenKind *)
2634 module GenerateFFRustTokenKind = struct
2635 let token_kind x =
2636 match x.token_kind with
2637 | "Self" -> "SelfToken"
2638 | x -> x
2640 let to_from_string x =
2641 let token_text = escape_token_text x.token_text in
2642 let guard =
2643 if x.allowed_as_identifier then
2644 "!only_reserved"
2645 else
2648 let guard =
2649 if String.equal guard "" then
2651 else
2652 " if " ^ guard
2654 sprintf
2655 " b\"%s\"%s => Some(TokenKind::%s),\n"
2656 token_text
2657 guard
2658 (token_kind x)
2660 let rust_tag = ref (-1)
2662 let to_kind_declaration x =
2663 incr rust_tag;
2664 sprintf " %s = %d,\n" (token_kind x) !rust_tag
2666 let token_text x = escape_token_text x.token_text
2668 let to_to_string x =
2669 sprintf
2670 " TokenKind::%s => \"%s\",\n"
2671 (token_kind x)
2672 (token_text x)
2674 let ocaml_tag = ref (-1)
2676 let to_ocaml_tag x =
2677 incr ocaml_tag;
2678 sprintf " TokenKind::%s => %d,\n" (token_kind x) !ocaml_tag
2680 let from_u8_tag = ref (-1)
2682 let to_try_from_u8 x =
2683 incr from_u8_tag;
2684 sprintf
2685 " %d => Some(TokenKind::%s),\n"
2686 !from_u8_tag
2687 (token_kind x)
2689 let to_width x =
2690 let len =
2691 if String.equal (token_kind x) "Backslash" then
2693 else
2694 String.length (token_text x)
2696 assert (len > 0);
2697 sprintf
2698 " TokenKind::%s => Some(unsafe { NonZeroUsize::new_unchecked(%d) }),\n"
2699 (token_kind x)
2702 let full_fidelity_rust_token_kind_template =
2703 make_header CStyle ""
2706 use std::num::NonZeroUsize;
2708 use ocamlrep::{FromOcamlRep, ToOcamlRep};
2710 #[allow(non_camel_case_types)] // allow Include_once and Require_once
2711 #[derive(Debug, Copy, Clone, PartialEq, Ord, Eq, PartialOrd, FromOcamlRep, ToOcamlRep)]
2712 #[repr(u8)]
2713 pub enum TokenKind {
2714 // No text tokens
2715 KIND_DECLARATIONS_NO_TEXT // Given text tokens
2716 KIND_DECLARATIONS_GIVEN_TEXT // Variable text tokens
2717 KIND_DECLARATIONS_VARIABLE_TEXT}
2719 impl TokenKind {
2720 pub fn to_string(self) -> &'static str {
2721 match self {
2722 // No text tokens
2723 TO_STRING_NO_TEXT // Given text tokens
2724 TO_STRING_GIVEN_TEXT // Variable text tokes
2725 TO_STRING_VARIABLE_TEXT }
2728 pub fn from_string(
2729 keyword: &[u8],
2730 only_reserved: bool,
2731 ) -> Option<Self> {
2732 match keyword {
2733 b\"true\" if !only_reserved => Some(TokenKind::BooleanLiteral),
2734 b\"false\" if !only_reserved => Some(TokenKind::BooleanLiteral),
2735 FROM_STRING_GIVEN_TEXT _ => None,
2739 pub fn ocaml_tag(self) -> u8 {
2740 match self {
2741 OCAML_TAG_NO_TEXTOCAML_TAG_GIVEN_TEXTOCAML_TAG_VARIABLE_TEXT }
2744 pub fn try_from_u8(tag: u8) -> Option<Self> {
2745 match tag {
2746 FROM_U8_NO_TEXTFROM_U8_GIVEN_TEXTFROM_U8_VARIABLE_TEXT _ => None,
2750 pub fn fixed_width(self) -> Option<NonZeroUsize> {
2751 match self {
2752 WIDTH_GIVEN_TEXT _ => None,
2758 let full_fidelity_token_kind =
2759 Full_fidelity_schema.make_template_file
2760 ~token_no_text_transformations:
2763 token_pattern = "KIND_DECLARATIONS_NO_TEXT";
2764 token_func = map_and_concat to_kind_declaration;
2767 token_pattern = "TO_STRING_NO_TEXT";
2768 token_func = map_and_concat to_to_string;
2771 token_pattern = "OCAML_TAG_NO_TEXT";
2772 token_func = map_and_concat to_ocaml_tag;
2775 token_pattern = "FROM_U8_NO_TEXT";
2776 token_func = map_and_concat to_try_from_u8;
2779 ~token_given_text_transformations:
2782 token_pattern = "KIND_DECLARATIONS_GIVEN_TEXT";
2783 token_func = map_and_concat to_kind_declaration;
2786 token_pattern = "FROM_STRING_GIVEN_TEXT";
2787 token_func = map_and_concat to_from_string;
2790 token_pattern = "TO_STRING_GIVEN_TEXT";
2791 token_func = map_and_concat to_to_string;
2794 token_pattern = "OCAML_TAG_GIVEN_TEXT";
2795 token_func = map_and_concat to_ocaml_tag;
2798 token_pattern = "FROM_U8_GIVEN_TEXT";
2799 token_func = map_and_concat to_try_from_u8;
2802 token_pattern = "WIDTH_GIVEN_TEXT";
2803 token_func = map_and_concat to_width;
2806 ~token_variable_text_transformations:
2809 token_pattern = "KIND_DECLARATIONS_VARIABLE_TEXT";
2810 token_func = map_and_concat to_kind_declaration;
2813 token_pattern = "TO_STRING_VARIABLE_TEXT";
2814 token_func = map_and_concat to_to_string;
2817 token_pattern = "OCAML_TAG_VARIABLE_TEXT";
2818 token_func = map_and_concat to_ocaml_tag;
2821 token_pattern = "FROM_U8_VARIABLE_TEXT";
2822 token_func = map_and_concat to_try_from_u8;
2825 ~filename:(full_fidelity_path_prefix ^ "token_kind.rs")
2826 ~template:full_fidelity_rust_token_kind_template
2830 (* GenerateFFTRustTokenKind *)
2832 module GenerateFFOperatorRust = struct
2833 let template =
2834 make_header CStyle ""
2837 use ocamlrep::{FromOcamlRep, ToOcamlRep};
2839 #[derive(FromOcamlRep, ToOcamlRep)]
2840 pub enum Operator {
2841 OPERATORS}
2844 let full_fidelity_operators =
2845 Full_fidelity_schema.make_template_file
2846 ~operator_transformations:
2849 operator_pattern = "OPERATORS";
2850 operator_func =
2851 map_and_concat (fun op -> sprintf " %sOperator,\n" op.name);
2854 ~filename:(full_fidelity_path_prefix ^ "operator_generated.rs")
2855 ~template
2859 (* GenerateFFOperatorRust *)
2861 module GenerateFFOperator = struct
2862 let template =
2863 make_header MLStyle ""
2865 module type Sig = sig
2866 type t =
2867 OPERATOR_DECL_SIGend
2869 module Impl : Sig = struct
2870 type t =
2871 OPERATOR_DECL_IMPLend
2874 let op_pattern prefix op = sprintf "%s| %sOperator\n" prefix op.name
2876 let transform pattern =
2878 operator_pattern = pattern;
2879 operator_func = map_and_concat (op_pattern " ");
2882 let full_fidelity_operator =
2883 Full_fidelity_schema.make_template_file
2884 ~operator_transformations:
2885 [transform "OPERATOR_DECL_SIG"; transform "OPERATOR_DECL_IMPL"]
2886 ~filename:
2887 (full_fidelity_path_prefix ^ "full_fidelity_operator_generated.ml")
2888 ~template
2892 module GenerateSchemaVersion = struct
2893 let template =
2894 make_header CStyle ""
2895 ^ sprintf
2897 pub const VERSION: &str = \"%s\";
2899 Full_fidelity_schema.full_fidelity_schema_version_number
2901 let gen =
2902 Full_fidelity_schema.make_template_file
2903 ~filename:
2904 "hphp/hack/src/parser/schema/full_fidelity_schema_version_number.rs"
2905 ~template
2909 let templates =
2911 GenerateFFOperatorRust.full_fidelity_operators;
2912 GenerateFFOperator.full_fidelity_operator;
2913 GenerateFFSyntaxType.full_fidelity_syntax_type;
2914 GenerateFFSyntaxSig.full_fidelity_syntax_sig;
2915 GenerateFFTriviaKind.full_fidelity_trivia_kind;
2916 GenerateFFRustTriviaKind.full_fidelity_trivia_kind;
2917 GenerateFFSyntax.full_fidelity_syntax;
2918 GenerateFFRustSyntax.full_fidelity_syntax;
2919 GenerateFFRustSyntaxType.full_fidelity_syntax;
2920 GenerateFFSyntaxKind.full_fidelity_syntax_kind;
2921 GenerateFFRustSyntaxKind.full_fidelity_syntax_kind;
2922 GenerateFFTokenKind.full_fidelity_token_kind;
2923 GenerateFFRustTokenKind.full_fidelity_token_kind;
2924 GenerateFFJSONSchema.full_fidelity_json_schema;
2925 GenerateFFSmartConstructors.full_fidelity_smart_constructors;
2926 GenerateFFRustSmartConstructors.full_fidelity_smart_constructors;
2927 GenerateFFRustPositionedSmartConstructors.positioned_smart_constructors;
2928 GenerateFFSyntaxSmartConstructors.full_fidelity_syntax_smart_constructors;
2929 GenerateFFRustSyntaxSmartConstructors
2930 .full_fidelity_syntax_smart_constructors;
2931 GenerateFFRustDeclModeSmartConstructors.decl_mode_smart_constructors;
2932 GenerateRustFlattenSmartConstructors.flatten_smart_constructors;
2933 GenerateRustDirectDeclSmartConstructors.direct_decl_smart_constructors;
2934 GenerateRustPairSmartConstructors.pair_smart_constructors;
2935 GenerateFFSmartConstructorsWrappers
2936 .full_fidelity_smart_constructors_wrappers;
2937 GenerateFFRustSmartConstructorsWrappers
2938 .full_fidelity_smart_constructors_wrappers;
2939 GenerateFFRustSyntaxVariantByRef.full_fidelity_syntax;
2940 GenerateSyntaxTypeImpl.full_fidelity_syntax;
2941 GenerateSyntaxChildrenIterator.full_fidelity_syntax;
2942 GenerateFFRustSyntaxImplByRef.full_fidelity_syntax;
2943 GenerateSyntaxSerialize.gen;
2944 GenerateSchemaVersion.gen;