Use ocamlrep rather than ocamlvalue in rust_to_ocaml
[hiphop-php.git] / hphp / hack / src / parser / smart_constructors.rs
blob08efdabc5bd763529b67b8810d72dceef12db73f
1 // Copyright (c) 2019, Facebook, Inc.
2 // All rights reserved.
3 //
4 // This source code is licensed under the MIT license found in the
5 // LICENSE file in the "hack" directory of this source tree.
7 use ocamlrep_derive::OcamlRep;
9 use parser_core_types::syntax_kind::SyntaxKind;
10 use parser_core_types::token_kind::TokenKind;
12 pub use crate::smart_constructors_generated::*;
13 pub use crate::smart_constructors_wrappers::*;
15 // Usage: S!(make_foo, parser, arg1, ...)  (in OCaml: Make.foo parser arg1 ...)
16 // Corresponds to a call to Make.foo followed by sc_call in OCaml (see *{precedence,simple}_parser)
17 // - Make.foo first calls SmartConstructorsWrapper, which calls parser's call method,
18 // - parser's call method forwards to SmartConstructors' make_foo(parser.sc_state, ...),
19 //   returning (sc_state, result)
20 // - parser's sc_state is updated with sc_state, and result is forwarded
21 // Instead of generating two 183-method SC wrappers in Rust, just use a simple macro.
22 macro_rules! S {
23     // special cases to avoid borrow checker error in common cases (150+) such as:
24     //    S!(make_missing, self, self.pos())
25     (make_list, $parser: expr, $r: expr, $pos: expr) => {{
26         let pos = $pos;
27         S_!(make_list, $parser, $r, pos)
28     }};
29     (make_missing, $parser: expr, $pos: expr) => {{
30         let pos = $pos;
31         S_!(make_missing, $parser, pos)
32     }};
33     // general case
34     ($f: ident, $parser: expr, $($rs:expr),* $(,)*) => {
35         S_!($f, $parser, $($rs),+)
36     }
38 macro_rules! S_ {
39     ($f: ident, $parser: expr, $($rs:expr),* $(,)*) => {{
40         let result = $parser.sc_mut().$f($($rs),+);
41         $parser.check_stack_limit();
42         result
43     }}
46 #[derive(Clone, OcamlRep)]
47 pub struct NoState; // zero-overhead placeholder when there is no state
49 pub trait NodeType {
50     type R;
51     fn extract(self) -> Self::R;
52     fn is_missing(&self) -> bool;
53     fn is_abstract(&self) -> bool;
54     fn is_variable_expression(&self) -> bool;
55     fn is_subscript_expression(&self) -> bool;
56     fn is_member_selection_expression(&self) -> bool;
57     fn is_scope_resolution_expression(&self) -> bool;
58     fn is_object_creation_expression(&self) -> bool;
59     fn is_qualified_name(&self) -> bool;
60     fn is_safe_member_selection_expression(&self) -> bool;
61     fn is_function_call_expression(&self) -> bool;
62     fn is_list_expression(&self) -> bool;
63     fn is_name(&self) -> bool;
64     fn is_halt_compiler_expression(&self) -> bool;
65     fn is_prefix_unary_expression(&self) -> bool;
68 impl<R> NodeType for (SyntaxKind, R) {
69     type R = R;
71     fn extract(self) -> Self::R {
72         self.1
73     }
75     fn is_missing(&self) -> bool {
76         match self.0 {
77             SyntaxKind::Missing => true,
78             _ => false,
79         }
80     }
82     fn is_abstract(&self) -> bool {
83         match &self.0 {
84             SyntaxKind::Token(TokenKind::Abstract) => true,
85             _ => false,
86         }
87     }
89     fn is_name(&self) -> bool {
90         match &self.0 {
91             SyntaxKind::Token(TokenKind::Name) => true,
92             _ => false,
93         }
94     }
96     // Note: we could generate ~150 methods like those below but most would be dead
98     fn is_variable_expression(&self) -> bool {
99         match &self.0 {
100             SyntaxKind::VariableExpression { .. } => true,
101             _ => false,
102         }
103     }
105     fn is_subscript_expression(&self) -> bool {
106         match &self.0 {
107             SyntaxKind::SubscriptExpression { .. } => true,
108             _ => false,
109         }
110     }
112     fn is_member_selection_expression(&self) -> bool {
113         match &self.0 {
114             SyntaxKind::MemberSelectionExpression { .. } => true,
115             _ => false,
116         }
117     }
119     fn is_scope_resolution_expression(&self) -> bool {
120         match &self.0 {
121             SyntaxKind::ScopeResolutionExpression { .. } => true,
122             _ => false,
123         }
124     }
126     fn is_object_creation_expression(&self) -> bool {
127         match &self.0 {
128             SyntaxKind::ObjectCreationExpression { .. } => true,
129             _ => false,
130         }
131     }
133     fn is_qualified_name(&self) -> bool {
134         match &self.0 {
135             SyntaxKind::QualifiedName { .. } => true,
136             _ => false,
137         }
138     }
140     fn is_safe_member_selection_expression(&self) -> bool {
141         match &self.0 {
142             SyntaxKind::SafeMemberSelectionExpression { .. } => true,
143             _ => false,
144         }
145     }
147     fn is_function_call_expression(&self) -> bool {
148         match &self.0 {
149             SyntaxKind::FunctionCallExpression { .. } => true,
150             _ => false,
151         }
152     }
154     fn is_list_expression(&self) -> bool {
155         match &self.0 {
156             SyntaxKind::ListExpression { .. } => true,
157             _ => false,
158         }
159     }
161     fn is_halt_compiler_expression(&self) -> bool {
162         match &self.0 {
163             SyntaxKind::HaltCompilerExpression { .. } => true,
164             _ => false,
165         }
166     }
168     fn is_prefix_unary_expression(&self) -> bool {
169         match &self.0 {
170             SyntaxKind::PrefixUnaryExpression { .. } => true,
171             _ => false,
172         }
173     }