Moving from class wrapper to class-less wrapper
[hiphop-php.git] / hphp / hack / src / parser / lowerer / lowerer.rs
blobd86950e3b3cadfa9f2ef3a852d6c3d635f2ce8a1
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 crate::{desugar_expression_tree::desugar, modifier};
8 use bstr::{BStr, BString, ByteSlice, B};
9 use bumpalo::Bump;
10 use escaper::*;
11 use hh_autoimport_rust as hh_autoimport;
12 use itertools::Either;
13 use lint_rust::LintError;
14 use naming_special_names_rust::{
15     classes as special_classes, literal, rx, special_functions, special_idents,
16     typehints as special_typehints, user_attributes as special_attrs,
18 use ocamlrep::rc::RcOc;
19 use oxidized::{
20     aast,
21     aast_visitor::{AstParams, Node, Visitor},
22     ast,
23     ast::Expr_ as E_,
24     doc_comment::DocComment,
25     errors::{Error as HHError, Naming, NastCheck},
26     file_info,
27     global_options::GlobalOptions,
28     namespace_env::Env as NamespaceEnv,
29     pos::Pos,
30     s_map,
32 use parser_core_types::{
33     indexed_source_text::IndexedSourceText,
34     lexable_token::LexablePositionedToken,
35     source_text::SourceText,
36     syntax::{SyntaxValueType, SyntaxValueWithKind},
37     syntax_by_ref::{
38         positioned_token::{PositionedToken, TokenFactory as PositionedTokenFactory},
39         positioned_value::PositionedValue,
40         syntax::Syntax,
41         syntax_variant_generated::{SyntaxVariant::*, *},
42     },
43     syntax_error, syntax_kind,
44     syntax_trait::SyntaxTrait,
45     token_factory::TokenMutator,
46     token_kind::TokenKind as TK,
48 use regex::bytes::Regex;
49 use stack_limit::StackLimit;
50 use std::{
51     cell::{Ref, RefCell, RefMut},
52     collections::HashSet,
53     matches, mem,
54     rc::Rc,
55     slice::Iter,
58 fn unescape_single(s: &str) -> std::result::Result<BString, escaper::InvalidString> {
59     Ok(escaper::unescape_single(s)?.into())
62 fn unescape_nowdoc(s: &str) -> std::result::Result<BString, escaper::InvalidString> {
63     Ok(escaper::unescape_nowdoc(s)?.into())
66 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
67 pub enum LiftedAwaitKind {
68     LiftedFromStatement,
69     LiftedFromConcurrent,
72 type LiftedAwaitExprs = Vec<(Option<ast::Lid>, ast::Expr)>;
74 #[derive(Debug, Clone)]
75 pub struct LiftedAwaits {
76     pub awaits: LiftedAwaitExprs,
77     lift_kind: LiftedAwaitKind,
80 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
81 pub enum ExprLocation {
82     TopLevel,
83     MemberSelect,
84     InDoubleQuotedString,
85     AsStatement,
86     RightOfAssignment,
87     RightOfAssignmentInUsingStatement,
88     RightOfReturn,
89     UsingStatement,
92 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
93 pub enum SuspensionKind {
94     SKSync,
95     SKAsync,
98 #[derive(Copy, Clone, Eq, PartialEq)]
99 pub enum TokenOp {
100     Skip,
101     Noop,
102     LeftTrim(usize),
103     RightTrim(usize),
106 #[derive(Debug)]
107 pub struct FunHdr {
108     suspension_kind: SuspensionKind,
109     name: ast::Sid,
110     constrs: Vec<ast::WhereConstraintHint>,
111     type_parameters: Vec<ast::Tparam>,
112     parameters: Vec<ast::FunParam>,
113     contexts: Option<ast::Contexts>,
114     unsafe_contexts: Option<ast::Contexts>,
115     return_type: Option<ast::Hint>,
118 impl FunHdr {
119     fn make_empty<TF: Clone>(env: &Env<TF>) -> Self {
120         Self {
121             suspension_kind: SuspensionKind::SKSync,
122             name: ast::Id(env.mk_none_pos(), String::from("<ANONYMOUS>")),
123             constrs: vec![],
124             type_parameters: vec![],
125             parameters: vec![],
126             contexts: None,
127             unsafe_contexts: None,
128             return_type: None,
129         }
130     }
133 #[derive(Debug)]
134 pub struct State {
135     pub cls_reified_generics: HashSet<String>,
136     pub in_static_method: bool,
137     pub parent_maybe_reified: bool,
138     /// This provides a generic mechanism to delay raising parsing errors;
139     /// since we're moving FFP errors away from CST to a stage after lowering
140     /// _and_ want to prioritize errors before lowering, the lowering errors
141     /// must be merely stored when the lowerer runs (until check for FFP runs (on AST)
142     /// and raised _after_ FFP error checking (unless we run the lowerer twice,
143     /// which would be expensive).
144     pub lowpri_errors: Vec<(Pos, String)>,
145     /// hh_errors captures errors after parsing, naming, nast, etc.
146     pub hh_errors: Vec<HHError>,
147     pub lint_errors: Vec<LintError>,
148     pub doc_comments: Vec<Option<DocComment>>,
150     pub local_id_counter: isize,
152     // TODO(hrust): this check is to avoid crash in Ocaml.
153     // Remove it after all Ocaml callers are eliminated.
154     pub exp_recursion_depth: usize,
157 const EXP_RECUSION_LIMIT: usize = 30_000;
159 #[derive(Debug, Clone)]
160 pub struct Env<'a, TF> {
161     pub codegen: bool,
162     pub keep_errors: bool,
163     quick_mode: bool,
164     /// Show errors even in quick mode. Does not override keep_errors. Hotfix
165     /// until we can properly set up saved states to surface parse errors during
166     /// typechecking properly.
167     pub show_all_errors: bool,
168     fail_open: bool,
169     file_mode: file_info::Mode,
170     disable_lowering_parsing_error: bool,
171     pub top_level_statements: bool, /* Whether we are (still) considering TLSs*/
173     // Cache none pos, lazy_static doesn't allow Rc.
174     pos_none: Pos,
175     pub empty_ns_env: RcOc<NamespaceEnv>,
177     pub saw_yield: bool, /* Information flowing back up */
178     pub lifted_awaits: Option<LiftedAwaits>,
179     pub tmp_var_counter: isize,
181     pub indexed_source_text: &'a IndexedSourceText<'a>,
182     pub parser_options: &'a GlobalOptions,
183     pub stack_limit: Option<&'a StackLimit>,
185     pub token_factory: TF,
186     pub arena: &'a Bump,
188     state: Rc<RefCell<State>>,
191 impl<'a, TF: Clone> Env<'a, TF> {
192     pub fn make(
193         codegen: bool,
194         quick_mode: bool,
195         keep_errors: bool,
196         show_all_errors: bool,
197         fail_open: bool,
198         disable_lowering_parsing_error: bool,
199         mode: file_info::Mode,
200         indexed_source_text: &'a IndexedSourceText<'a>,
201         parser_options: &'a GlobalOptions,
202         use_default_namespace: bool,
203         stack_limit: Option<&'a StackLimit>,
204         token_factory: TF,
205         arena: &'a Bump,
206     ) -> Self {
207         // (hrust) Ported from namespace_env.ml
208         let empty_ns_env = if use_default_namespace {
209             let mut nsenv = NamespaceEnv::empty(vec![], false, false);
210             nsenv.is_codegen = codegen;
211             nsenv.disable_xhp_element_mangling = parser_options.po_disable_xhp_element_mangling;
212             nsenv
213         } else {
214             let mut ns_uses = hh_autoimport::NAMESPACES_MAP.clone();
215             parser_options
216                 .po_auto_namespace_map
217                 .iter()
218                 .for_each(|(k, v)| {
219                     &ns_uses.insert(k.into(), v.into());
220                 });
221             NamespaceEnv {
222                 ns_uses,
223                 class_uses: hh_autoimport::TYPES_MAP.clone(),
224                 fun_uses: hh_autoimport::FUNCS_MAP.clone(),
225                 const_uses: hh_autoimport::CONSTS_MAP.clone(),
226                 record_def_uses: s_map::SMap::new(),
227                 name: None,
228                 auto_ns_map: parser_options.po_auto_namespace_map.clone(),
229                 is_codegen: codegen,
230                 disable_xhp_element_mangling: parser_options.po_disable_xhp_element_mangling,
231             }
232         };
234         Env {
235             codegen,
236             keep_errors,
237             quick_mode,
238             show_all_errors,
239             fail_open,
240             disable_lowering_parsing_error,
241             file_mode: mode,
242             top_level_statements: true,
243             saw_yield: false,
244             lifted_awaits: None,
245             tmp_var_counter: 1,
246             indexed_source_text,
247             parser_options,
248             pos_none: Pos::make_none(),
249             empty_ns_env: RcOc::new(empty_ns_env),
250             stack_limit,
251             token_factory,
252             arena,
254             state: Rc::new(RefCell::new(State {
255                 cls_reified_generics: HashSet::new(),
256                 in_static_method: false,
257                 parent_maybe_reified: false,
258                 lowpri_errors: vec![],
259                 doc_comments: vec![],
260                 local_id_counter: 1,
261                 hh_errors: vec![],
262                 lint_errors: vec![],
263                 exp_recursion_depth: 0,
264             })),
265         }
266     }
268     fn file_mode(&self) -> file_info::Mode {
269         self.file_mode
270     }
272     fn should_surface_error(&self) -> bool {
273         (!self.quick_mode || self.show_all_errors) && self.keep_errors
274     }
276     fn is_typechecker(&self) -> bool {
277         !self.codegen
278     }
280     fn codegen(&self) -> bool {
281         self.codegen
282     }
284     fn source_text(&self) -> &SourceText<'a> {
285         self.indexed_source_text.source_text()
286     }
288     fn fail_open(&self) -> bool {
289         self.fail_open
290     }
292     fn cls_reified_generics(&mut self) -> RefMut<HashSet<String>> {
293         RefMut::map(self.state.borrow_mut(), |s| &mut s.cls_reified_generics)
294     }
296     fn in_static_method(&mut self) -> RefMut<bool> {
297         RefMut::map(self.state.borrow_mut(), |s| &mut s.in_static_method)
298     }
300     fn parent_maybe_reified(&mut self) -> RefMut<bool> {
301         RefMut::map(self.state.borrow_mut(), |s| &mut s.parent_maybe_reified)
302     }
304     pub fn lowpri_errors(&mut self) -> RefMut<Vec<(Pos, String)>> {
305         RefMut::map(self.state.borrow_mut(), |s| &mut s.lowpri_errors)
306     }
308     pub fn hh_errors(&mut self) -> RefMut<Vec<HHError>> {
309         RefMut::map(self.state.borrow_mut(), |s| &mut s.hh_errors)
310     }
312     pub fn lint_errors(&mut self) -> RefMut<Vec<LintError>> {
313         RefMut::map(self.state.borrow_mut(), |s| &mut s.lint_errors)
314     }
316     fn top_docblock(&self) -> Ref<Option<DocComment>> {
317         Ref::map(self.state.borrow(), |s| {
318             s.doc_comments.last().unwrap_or(&None)
319         })
320     }
322     fn exp_recursion_depth(&self) -> RefMut<usize> {
323         RefMut::map(self.state.borrow_mut(), |s| &mut s.exp_recursion_depth)
324     }
326     fn next_local_id(&self) -> isize {
327         let mut id = RefMut::map(self.state.borrow_mut(), |s| &mut s.local_id_counter);
328         *id = *id + 1;
329         *id
330     }
332     fn push_docblock(&mut self, doc_comment: Option<DocComment>) {
333         RefMut::map(self.state.borrow_mut(), |s| &mut s.doc_comments).push(doc_comment)
334     }
336     fn pop_docblock(&mut self) {
337         RefMut::map(self.state.borrow_mut(), |s| &mut s.doc_comments).pop();
338     }
340     fn make_tmp_var_name(&mut self) -> String {
341         let name = String::from(special_idents::TMP_VAR_PREFIX) + &self.tmp_var_counter.to_string();
342         self.tmp_var_counter += 1;
343         name
344     }
346     fn mk_none_pos(&self) -> Pos {
347         self.pos_none.clone()
348     }
350     fn clone_and_unset_toplevel_if_toplevel<'b, 'c>(
351         e: &'b mut Env<'c, TF>,
352     ) -> impl AsMut<Env<'c, TF>> + 'b {
353         if e.top_level_statements {
354             let mut cloned = e.clone();
355             cloned.top_level_statements = false;
356             Either::Left(cloned)
357         } else {
358             Either::Right(e)
359         }
360     }
362     fn check_stack_limit(&self) {
363         self.stack_limit
364             .as_ref()
365             .map(|limit| limit.panic_if_exceeded());
366     }
369 impl<'a, TF> AsMut<Env<'a, TF>> for Env<'a, TF> {
370     fn as_mut(&mut self) -> &mut Env<'a, TF> {
371         self
372     }
375 #[derive(Debug)]
376 pub enum Error {
377     MissingSyntax {
378         expecting: String,
379         pos: Pos,
380         node_name: String,
381         kind: syntax_kind::SyntaxKind,
382     },
383     Failwith(String),
386 type Result<T> = std::result::Result<T, Error>;
387 type S<'arena, T, V> = &'arena Syntax<'arena, T, V>;
389 trait Lowerer<'a, T, V, TF>
390 where
391     TF: TokenMutator<Token = T> + Clone + 'a,
392     T: 'a + LexablePositionedToken + Copy,
393     V: 'a + SyntaxValueWithKind + SyntaxValueType<T>,
394     Syntax<'a, T, V>: SyntaxTrait,
396     fn p_pos(node: S<'a, T, V>, env: &Env<TF>) -> Pos {
397         node.position_exclusive(env.indexed_source_text)
398             .unwrap_or_else(|| env.mk_none_pos())
399     }
401     fn raise_parsing_error(node: S<'a, T, V>, env: &mut Env<'a, TF>, msg: &str) {
402         Self::raise_parsing_error_(Either::Left(node), env, msg)
403     }
405     fn raise_parsing_error_pos(pos: &Pos, env: &mut Env<'a, TF>, msg: &str) {
406         Self::raise_parsing_error_(Either::Right(pos), env, msg)
407     }
409     fn raise_parsing_error_(
410         node_or_pos: Either<S<'a, T, V>, &Pos>,
411         env: &mut Env<'a, TF>,
412         msg: &str,
413     ) {
414         if env.should_surface_error() {
415             let pos = node_or_pos.either(|node| Self::p_pos(node, env), |pos| pos.clone());
416             env.lowpri_errors().push((pos, String::from(msg)))
417         } else if env.codegen() {
418             let pos = node_or_pos.either(
419                 |node| {
420                     node.position_exclusive(env.indexed_source_text)
421                         .unwrap_or_else(|| env.mk_none_pos())
422                 },
423                 |pos| pos.clone(),
424             );
425             env.lowpri_errors().push((pos, String::from(msg)))
426         }
427     }
429     fn raise_hh_error(env: &mut Env<'a, TF>, err: HHError) {
430         env.hh_errors().push(err);
431     }
433     fn raise_lint_error(env: &mut Env<'a, TF>, err: LintError) {
434         env.lint_errors().push(err);
435     }
437     fn failwith<N>(msg: impl Into<String>) -> Result<N> {
438         Err(Error::Failwith(msg.into()))
439     }
441     fn text(node: S<'a, T, V>, env: &Env<TF>) -> String {
442         String::from(node.text(env.source_text()))
443     }
445     fn text_str<'b>(node: S<'a, T, V>, env: &'b Env<TF>) -> &'b str {
446         node.text(env.source_text())
447     }
449     fn lowering_error(env: &mut Env<'a, TF>, pos: &Pos, text: &str, syntax_kind: &str) {
450         if env.is_typechecker()
451             && !env.disable_lowering_parsing_error
452             && env.lowpri_errors().is_empty()
453         {
454             Self::raise_parsing_error_pos(
455                 pos,
456                 env,
457                 &syntax_error::lowering_parsing_error(text, syntax_kind),
458             )
459         }
460     }
462     fn missing_syntax_<N>(
463         fallback: Option<N>,
464         expecting: &str,
465         node: S<'a, T, V>,
466         env: &mut Env<'a, TF>,
467     ) -> Result<N> {
468         let pos = Self::p_pos(node, env);
469         let text = Self::text(node, env);
470         Self::lowering_error(env, &pos, &text, expecting);
471         if let Some(x) = fallback {
472             if env.fail_open() {
473                 return Ok(x);
474             }
475         }
476         Err(Error::MissingSyntax {
477             expecting: String::from(expecting),
478             pos: Self::p_pos(node, env),
479             node_name: text,
480             kind: node.kind(),
481         })
482     }
484     fn missing_syntax<N>(expecting: &str, node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<N> {
485         Self::missing_syntax_(None, expecting, node, env)
486     }
488     fn is_num_octal_lit(s: &str) -> bool {
489         !s.chars().any(|c| c == '8' || c == '9')
490     }
492     fn mp_optional<F, R>(p: F, node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<Option<R>>
493     where
494         F: FnOnce(S<'a, T, V>, &mut Env<'a, TF>) -> Result<R>,
495     {
496         match &node.children {
497             Missing => Ok(None),
498             _ => p(node, env).map(Some),
499         }
500     }
502     fn pos_qualified_name(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Sid> {
503         if let QualifiedName(c) = &node.children {
504             if let SyntaxList(l) = &c.parts.children {
505                 let p = Self::p_pos(node, env);
506                 let mut s = String::with_capacity(node.width());
507                 for i in l.iter() {
508                     match &i.children {
509                         ListItem(li) => {
510                             s += Self::text_str(&li.item, env);
511                             s += Self::text_str(&li.separator, env);
512                         }
513                         _ => s += Self::text_str(&i, env),
514                     }
515                 }
516                 return Ok(ast::Id(p, s));
517             }
518         }
519         Self::missing_syntax("qualified name", node, env)
520     }
522     fn pos_name(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Sid> {
523         Self::pos_name_(node, env, None)
524     }
526     fn lid_from_pos_name(pos: Pos, name: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Lid> {
527         let name = Self::pos_name(name, env)?;
528         Ok(ast::Lid::new(pos, name.1))
529     }
531     fn lid_from_name(name: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Lid> {
532         let name = Self::pos_name(name, env)?;
533         Ok(ast::Lid::new(name.0, name.1))
534     }
536     fn p_pstring(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Pstring> {
537         Self::p_pstring_(node, env, None)
538     }
540     fn p_pstring_(
541         node: S<'a, T, V>,
542         env: &mut Env<'a, TF>,
543         drop_prefix: Option<char>,
544     ) -> Result<ast::Pstring> {
545         let ast::Id(p, id) = Self::pos_name_(node, env, drop_prefix)?;
546         Ok((p, id))
547     }
549     fn drop_prefix(s: &str, prefix: char) -> &str {
550         if s.len() > 0 && s.chars().nth(0) == Some(prefix) {
551             &s[1..]
552         } else {
553             s
554         }
555     }
557     fn pos_name_(
558         node: S<'a, T, V>,
559         env: &mut Env<'a, TF>,
560         drop_prefix: Option<char>,
561     ) -> Result<ast::Sid> {
562         match &node.children {
563             QualifiedName(_) => Self::pos_qualified_name(node, env),
564             SimpleTypeSpecifier(c) => Self::pos_name_(&c.specifier, env, drop_prefix),
565             _ => {
566                 let mut name = node.text(env.indexed_source_text.source_text());
567                 if let Some(prefix) = drop_prefix {
568                     name = Self::drop_prefix(name, prefix);
569                 }
570                 let p = Self::p_pos(node, env);
571                 Ok(ast::Id(p, String::from(name)))
572             }
573         }
574     }
576     fn mk_str<F>(
577         node: S<'a, T, V>,
578         env: &mut Env<'a, TF>,
579         unescaper: F,
580         mut content: &str,
581     ) -> BString
582     where
583         F: Fn(&str) -> std::result::Result<BString, InvalidString>,
584     {
585         if let Some('b') = content.chars().nth(0) {
586             content = content.get(1..).unwrap();
587         }
589         let len = content.len();
590         let no_quotes_result = extract_unquoted_string(content, 0, len);
591         match no_quotes_result {
592             Ok(no_quotes) => {
593                 let result = unescaper(&no_quotes);
594                 match result {
595                     Ok(s) => s,
596                     Err(_) => {
597                         Self::raise_parsing_error(
598                             node,
599                             env,
600                             &format!("Malformed string literal <<{}>>", &no_quotes),
601                         );
602                         BString::from("")
603                     }
604                 }
605             }
606             Err(_) => {
607                 Self::raise_parsing_error(
608                     node,
609                     env,
610                     &format!("Malformed string literal <<{}>>", &content),
611                 );
612                 BString::from("")
613             }
614         }
615     }
617     fn unesc_dbl(s: &str) -> std::result::Result<BString, InvalidString> {
618         let unesc_s = unescape_double(s)?;
619         if unesc_s == B("''") || unesc_s == B("\"\"") {
620             Ok(BString::from(""))
621         } else {
622             Ok(unesc_s)
623         }
624     }
626     // TODO: return Cow<[u8]>
627     fn unesc_xhp(s: &[u8]) -> Vec<u8> {
628         lazy_static! {
629             static ref WHITESPACE: Regex = Regex::new("[\x20\t\n\r\x0c]+").unwrap();
630         }
631         WHITESPACE.replace_all(s, &b" "[..]).into_owned()
632     }
634     fn unesc_xhp_attr(s: &[u8]) -> Vec<u8> {
635         // TODO: change unesc_dbl to &[u8] -> BString
636         let r = Self::get_quoted_content(s);
637         let r = unsafe { std::str::from_utf8_unchecked(r) };
638         Self::unesc_dbl(r).unwrap().into()
639     }
641     fn get_quoted_content(s: &[u8]) -> &[u8] {
642         lazy_static! {
643             static ref QUOTED: Regex = Regex::new(r#"^[\x20\t\n\r\x0c]*"((?:.|\n)*)""#).unwrap();
644         }
645         QUOTED
646             .captures(s)
647             .map_or(None, |c| c.get(1))
648             .map_or(s, |m| m.as_bytes())
649     }
651     fn token_kind(node: S<'a, T, V>) -> Option<TK> {
652         match &node.children {
653             Token(t) => Some(t.kind()),
654             _ => None,
655         }
656     }
658     fn check_valid_reified_hint(env: &mut Env<'a, TF>, node: S<'a, T, V>, hint: &ast::Hint) {
659         struct Checker<F: FnMut(&String)>(F);
660         impl<'ast, F: FnMut(&String)> Visitor<'ast> for Checker<F> {
661             type P = AstParams<(), ()>;
663             fn object(&mut self) -> &mut dyn Visitor<'ast, P = Self::P> {
664                 self
665             }
667             fn visit_hint(&mut self, c: &mut (), h: &ast::Hint) -> std::result::Result<(), ()> {
668                 match h.1.as_ref() {
669                     ast::Hint_::Happly(id, _) => {
670                         self.0(&id.1);
671                     }
672                     ast::Hint_::Haccess(_, ids) => {
673                         ids.iter().for_each(|id| self.0(&id.1));
674                     }
675                     _ => {}
676                 }
677                 h.recurse(c, self)
678             }
679         }
681         if *env.in_static_method() {
682             let f = |id: &String| {
683                 Self::fail_if_invalid_reified_generic(node, env, id);
684             };
685             let mut visitor = Checker(f);
686             visitor.visit_hint(&mut (), hint).unwrap();
687         }
688     }
690     fn p_closure_parameter(
691         node: S<'a, T, V>,
692         env: &mut Env<'a, TF>,
693     ) -> Result<(ast::Hint, Option<ast::ParamKind>)> {
694         match &node.children {
695             ClosureParameterTypeSpecifier(c) => {
696                 let kind = Self::mp_optional(Self::p_param_kind, &c.call_convention, env)?;
697                 let hint = Self::p_hint(&c.type_, env)?;
698                 Ok((hint, kind))
699             }
700             _ => Self::missing_syntax("closure parameter", node, env),
701         }
702     }
704     fn mp_shape_expression_field<F, R>(
705         f: F,
706         node: S<'a, T, V>,
707         env: &mut Env<'a, TF>,
708     ) -> Result<(ast::ShapeFieldName, R)>
709     where
710         F: Fn(S<'a, T, V>, &mut Env<'a, TF>) -> Result<R>,
711     {
712         match &node.children {
713             FieldInitializer(c) => {
714                 let name = Self::p_shape_field_name(&c.name, env)?;
715                 let value = f(&c.value, env)?;
716                 Ok((name, value))
717             }
718             _ => Self::missing_syntax("shape field", node, env),
719         }
720     }
722     fn p_shape_field_name(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::ShapeFieldName> {
723         use ast::ShapeFieldName::*;
724         let is_valid_shape_literal = |t: &T| {
725             let is_str = t.kind() == TK::SingleQuotedStringLiteral
726                 || t.kind() == TK::DoubleQuotedStringLiteral;
727             let text = t.text(env.source_text());
728             let is_empty = text == "\'\'" || text == "\"\"";
729             is_str && !is_empty
730         };
731         if let LiteralExpression(c) = &node.children {
732             if let Token(t) = &c.expression.children {
733                 if is_valid_shape_literal(t) {
734                     let ast::Id(p, n) = Self::pos_name(node, env)?;
735                     let unescp = if t.kind() == TK::SingleQuotedStringLiteral {
736                         unescape_single
737                     } else {
738                         Self::unesc_dbl
739                     };
740                     let str_ = Self::mk_str(node, env, unescp, &n);
741                     if let Some(_) = ocaml_helper::int_of_string_opt(&str_.as_bytes()) {
742                         Self::raise_parsing_error(
743                             node,
744                             env,
745                             &syntax_error::shape_field_int_like_string,
746                         )
747                     }
748                     return Ok(SFlitStr((p, str_)));
749                 }
750             }
751         }
752         match &node.children {
753             ScopeResolutionExpression(c) => Ok(SFclassConst(
754                 Self::pos_name(&c.qualifier, env)?,
755                 Self::p_pstring(&c.name, env)?,
756             )),
757             _ => {
758                 Self::raise_parsing_error(node, env, &syntax_error::invalid_shape_field_name);
759                 let ast::Id(p, n) = Self::pos_name(node, env)?;
760                 Ok(SFlitStr((p, Self::mk_str(node, env, Self::unesc_dbl, &n))))
761             }
762         }
763     }
765     fn p_shape_field(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::ShapeFieldInfo> {
766         match &node.children {
767             FieldSpecifier(c) => {
768                 let optional = !c.question.is_missing();
769                 let name = Self::p_shape_field_name(&c.name, env)?;
770                 let hint = Self::p_hint(&c.type_, env)?;
771                 Ok(ast::ShapeFieldInfo {
772                     optional,
773                     hint,
774                     name,
775                 })
776             }
777             _ => {
778                 let (name, hint) = Self::mp_shape_expression_field(Self::p_hint, node, env)?;
779                 Ok(ast::ShapeFieldInfo {
780                     optional: false,
781                     name,
782                     hint,
783                 })
784             }
785         }
786     }
788     fn p_targ(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Targ> {
789         Ok(ast::Targ((), Self::p_hint(node, env)?))
790     }
792     fn p_hint_(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Hint_> {
793         use ast::Hint_::*;
794         let unary = |kw, ty, env: &mut Env<'a, TF>| {
795             Ok(Happly(
796                 Self::pos_name(kw, env)?,
797                 Self::could_map(Self::p_hint, ty, env)?,
798             ))
799         };
800         let binary = |kw, key, ty, env: &mut Env<'a, TF>| {
801             let kw = Self::pos_name(kw, env)?;
802             let key = Self::p_hint(key, env)?;
803             Ok(Happly(
804                 kw,
805                 Self::map_flatten_(&Self::p_hint, ty, env, vec![key])?,
806             ))
807         };
809         match &node.children {
810             Token(token) if token.kind() == TK::Variable => {
811                 let ast::Id(_pos, name) = Self::pos_name(node, env)?;
812                 Ok(Hvar(name))
813             }
814             /* Dirty hack; CastExpression can have type represented by token */
815             Token(_) | SimpleTypeSpecifier(_) | QualifiedName(_) => {
816                 let ast::Id(pos, name) = Self::pos_name(node, env)?;
817                 let mut suggest = |name: &str, canonical: &str| {
818                     Self::raise_parsing_error(
819                         node,
820                         env,
821                         &syntax_error::invalid_typehint_alias(name, canonical),
822                     );
823                 };
824                 if "integer".eq_ignore_ascii_case(&name) {
825                     suggest(&name, special_typehints::INT);
826                 } else if "boolean".eq_ignore_ascii_case(&name) {
827                     suggest(&name, special_typehints::BOOL);
828                 } else if "double".eq_ignore_ascii_case(&name) {
829                     suggest(&name, special_typehints::FLOAT);
830                 } else if "real".eq_ignore_ascii_case(&name) {
831                     suggest(&name, special_typehints::FLOAT);
832                 }
833                 Ok(Happly(ast::Id(pos, name), vec![]))
834             }
835             ShapeTypeSpecifier(c) => {
836                 let allows_unknown_fields = !c.ellipsis.is_missing();
837                 /* if last element lacks a separator and ellipsis is present, error */
838                 if allows_unknown_fields {
839                     if let SyntaxList(items) = &c.fields.children {
840                         if let Some(ListItem(item)) = items.last().map(|i| &i.children) {
841                             if item.separator.is_missing() {
842                                 Self::raise_parsing_error(
843                                     node,
844                                     env,
845                                     &syntax_error::shape_type_ellipsis_without_trailing_comma,
846                                 )
847                             }
848                         }
849                     }
850                 }
852                 let field_map = Self::could_map(Self::p_shape_field, &c.fields, env)?;
853                 // TODO:(shiqicao) improve perf
854                 // 1. replace HashSet by fnv hash map or something faster,
855                 // 2. move `set` to Env to avoid allocation,
856                 let mut set: HashSet<&BStr> = HashSet::with_capacity(field_map.len());
857                 for f in field_map.iter() {
858                     if !set.insert(f.name.get_name()) {
859                         Self::raise_hh_error(
860                             env,
861                             Naming::fd_name_already_bound(f.name.get_pos().clone()),
862                         );
863                     }
864                 }
866                 Ok(Hshape(ast::NastShapeInfo {
867                     allows_unknown_fields,
868                     field_map,
869                 }))
870             }
871             TupleTypeSpecifier(c) => Ok(Htuple(Self::could_map(Self::p_hint, &c.types, env)?)),
872             UnionTypeSpecifier(c) => Ok(Hunion(Self::could_map(&Self::p_hint, &c.types, env)?)),
873             IntersectionTypeSpecifier(c) => Ok(Hintersection(Self::could_map(
874                 &Self::p_hint,
875                 &c.types,
876                 env,
877             )?)),
878             KeysetTypeSpecifier(c) => Ok(Happly(
879                 Self::pos_name(&c.keyword, env)?,
880                 Self::could_map(Self::p_hint, &c.type_, env)?,
881             )),
882             VectorTypeSpecifier(c) => unary(&c.keyword, &c.type_, env),
883             ClassnameTypeSpecifier(c) => unary(&c.keyword, &c.type_, env),
884             TupleTypeExplicitSpecifier(c) => unary(&c.keyword, &c.types, env),
885             VarrayTypeSpecifier(c) => unary(&c.keyword, &c.type_, env),
886             DarrayTypeSpecifier(c) => binary(&c.keyword, &c.key, &c.value, env),
887             DictionaryTypeSpecifier(c) => unary(&c.keyword, &c.members, env),
888             GenericTypeSpecifier(c) => {
889                 let name = Self::pos_name(&c.class_type, env)?;
890                 let args = &c.argument_list;
891                 let type_args = match &args.children {
892                     TypeArguments(c) => Self::could_map(Self::p_hint, &c.types, env)?,
893                     _ => Self::missing_syntax("generic type arguments", args, env)?,
894                 };
895                 if env.codegen() {
896                     let process = |name: ast::Sid, mut args: Vec<ast::Hint>| -> ast::Hint_ {
897                         if args.len() == 1 {
898                             let eq = |s| name.1.eq_ignore_ascii_case(s);
899                             if (args[0].1.is_hfun()
900                                 && (eq(rx::RX)
901                                     || eq(rx::RX_LOCAL)
902                                     || eq(rx::RX_SHALLOW)
903                                     || eq(rx::PURE)))
904                                 || (args[0].1.is_happly()
905                                     && (eq(rx::MUTABLE)
906                                         || eq(rx::MAYBE_MUTABLE)
907                                         || eq(rx::OWNED_MUTABLE)))
908                             {
909                                 return *args.pop().unwrap().1;
910                             }
911                         }
912                         Happly(name, args)
913                     };
914                     Ok(process(name, type_args))
915                 } else {
916                     Ok(Happly(name, type_args))
917                 }
918             }
919             NullableTypeSpecifier(c) => Ok(Hoption(Self::p_hint(&c.type_, env)?)),
920             LikeTypeSpecifier(c) => Ok(Hlike(Self::p_hint(&c.type_, env)?)),
921             SoftTypeSpecifier(c) => Ok(Hsoft(Self::p_hint(&c.type_, env)?)),
922             ClosureTypeSpecifier(c) => {
923                 let (param_list, variadic_hints): (Vec<S<'a, T, V>>, Vec<S<'a, T, V>>) = c
924                     .parameter_list
925                     .syntax_node_to_list_skip_separator()
926                     .partition(|n| match &n.children {
927                         VariadicParameter(_) => false,
928                         _ => true,
929                     });
930                 let (type_hints, kinds) = param_list
931                     .iter()
932                     .map(|p| Self::p_closure_parameter(p, env))
933                     .collect::<std::result::Result<Vec<_>, _>>()?
934                     .into_iter()
935                     .unzip();
936                 let variadic_hints = variadic_hints
937                     .iter()
938                     .map(|v| match &v.children {
939                         VariadicParameter(c) => {
940                             if c.type_.is_missing() {
941                                 Self::raise_parsing_error(
942                                     v,
943                                     env,
944                                     "Cannot use ... without a typehint",
945                                 );
946                             }
947                             Ok(Some(Self::p_hint(&c.type_, env)?))
948                         }
949                         _ => panic!("expect variadic parameter"),
950                     })
951                     .collect::<std::result::Result<Vec<_>, _>>()?;
952                 if variadic_hints.len() > 1 {
953                     return Self::failwith(format!(
954                         "{} variadic parameters found. There should be no more than one.",
955                         variadic_hints.len().to_string()
956                     ));
957                 }
958                 let (ctxs, _) = Self::p_contexts(&c.contexts, env)?;
959                 Ok(Hfun(ast::HintFun {
960                     reactive_kind: ast::FuncReactive::FNonreactive,
961                     param_tys: type_hints,
962                     param_kinds: kinds,
963                     param_mutability: vec![],
964                     variadic_ty: variadic_hints.into_iter().next().unwrap_or(None),
965                     ctxs,
966                     return_ty: Self::p_hint(&c.return_type, env)?,
967                     is_mutable_return: true,
968                 }))
969             }
970             AttributizedSpecifier(c) => {
971                 let attrs = Self::p_user_attribute(&c.attribute_spec, env)?;
972                 let hint = Self::p_hint(&c.type_, env)?;
973                 if attrs.iter().any(|attr| attr.name.1 != special_attrs::SOFT) {
974                     Self::raise_parsing_error(node, env, &syntax_error::only_soft_allowed);
975                 }
976                 Ok(*Self::soften_hint(&attrs, hint).1)
977             }
978             FunctionCtxTypeSpecifier(c) => {
979                 let ast::Id(_p, n) = Self::pos_name(&c.variable, env)?;
980                 Ok(HfunContext(n))
981             }
982             TypeConstant(c) => {
983                 let child = Self::pos_name(&c.right_type, env)?;
984                 match Self::p_hint_(&c.left_type, env)? {
985                     Haccess(root, mut cs) => {
986                         cs.push(child);
987                         Ok(Haccess(root, cs))
988                     }
989                     Hvar(n) => {
990                         let pos = Self::p_pos(&c.left_type, env);
991                         let root = ast::Hint::new(pos, Hvar(n));
992                         Ok(Haccess(root, vec![child]))
993                     }
994                     Happly(ty, param) => {
995                         if param.is_empty() {
996                             let root = ast::Hint::new(ty.0.clone(), Happly(ty, param));
997                             Ok(Haccess(root, vec![child]))
998                         } else {
999                             Self::missing_syntax("type constant base", node, env)
1000                         }
1001                     }
1002                     _ => Self::missing_syntax("type constant base", node, env),
1003                 }
1004             }
1005             ReifiedTypeArgument(_) => {
1006                 Self::raise_parsing_error(node, env, &syntax_error::invalid_reified);
1007                 Self::missing_syntax("refied type", node, env)
1008             }
1009             _ => Self::missing_syntax("type hint", node, env),
1010         }
1011     }
1013     fn p_hint(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Hint> {
1014         let hint_ = Self::p_hint_(node, env)?;
1015         let pos = Self::p_pos(node, env);
1016         let hint = ast::Hint::new(pos, hint_);
1017         Self::check_valid_reified_hint(env, node, &hint);
1018         Ok(hint)
1019     }
1021     fn p_simple_initializer(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Expr> {
1022         match &node.children {
1023             SimpleInitializer(c) => Self::p_expr(&c.value, env),
1024             _ => Self::missing_syntax("simple initializer", node, env),
1025         }
1026     }
1028     fn p_member(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<(ast::Expr, ast::Expr)> {
1029         match &node.children {
1030             ElementInitializer(c) => Ok((Self::p_expr(&c.key, env)?, Self::p_expr(&c.value, env)?)),
1031             _ => Self::missing_syntax("darray intrinsic expression element", node, env),
1032         }
1033     }
1035     fn expand_type_args(ty: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<Vec<ast::Hint>> {
1036         match &ty.children {
1037             TypeArguments(c) => Self::could_map(Self::p_hint, &c.types, env),
1038             _ => Ok(vec![]),
1039         }
1040     }
1042     fn p_afield(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Afield> {
1043         match &node.children {
1044             ElementInitializer(c) => Ok(ast::Afield::AFkvalue(
1045                 Self::p_expr(&c.key, env)?,
1046                 Self::p_expr(&c.value, env)?,
1047             )),
1048             _ => Ok(ast::Afield::AFvalue(Self::p_expr(node, env)?)),
1049         }
1050     }
1052     fn check_intrinsic_type_arg_varity(
1053         node: S<'a, T, V>,
1054         env: &mut Env<'a, TF>,
1055         tys: Vec<ast::Hint>,
1056     ) -> Option<ast::CollectionTarg> {
1057         let count = tys.len();
1058         let mut tys = tys.into_iter();
1059         match count {
1060             2 => Some(ast::CollectionTarg::CollectionTKV(
1061                 ast::Targ((), tys.next().unwrap()),
1062                 ast::Targ((), tys.next().unwrap()),
1063             )),
1064             1 => Some(ast::CollectionTarg::CollectionTV(ast::Targ(
1065                 (),
1066                 tys.next().unwrap(),
1067             ))),
1068             0 => None,
1069             _ => {
1070                 Self::raise_parsing_error(
1071                     node,
1072                     env,
1073                     &syntax_error::collection_intrinsic_many_typeargs,
1074                 );
1075                 None
1076             }
1077         }
1078     }
1080     fn p_import_flavor(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::ImportFlavor> {
1081         use ast::ImportFlavor::*;
1082         match Self::token_kind(node) {
1083             Some(TK::Include) => Ok(Include),
1084             Some(TK::Require) => Ok(Require),
1085             Some(TK::Include_once) => Ok(IncludeOnce),
1086             Some(TK::Require_once) => Ok(RequireOnce),
1087             _ => Self::missing_syntax("import flavor", node, env),
1088         }
1089     }
1091     fn p_null_flavor(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::OgNullFlavor> {
1092         use ast::OgNullFlavor::*;
1093         match Self::token_kind(node) {
1094             Some(TK::QuestionMinusGreaterThan) => Ok(OGNullsafe),
1095             Some(TK::MinusGreaterThan) => Ok(OGNullthrows),
1096             _ => Self::missing_syntax("null flavor", node, env),
1097         }
1098     }
1100     fn wrap_unescaper<F>(unescaper: F, s: &str) -> Result<BString>
1101     where
1102         F: FnOnce(&str) -> std::result::Result<BString, InvalidString>,
1103     {
1104         unescaper(s).map_err(|e| Error::Failwith(e.msg))
1105     }
1107     fn fail_if_invalid_class_creation(
1108         node: S<'a, T, V>,
1109         env: &mut Env<'a, TF>,
1110         id: impl AsRef<str>,
1111     ) {
1112         let id = id.as_ref();
1113         let is_in_static_method = *env.in_static_method();
1114         if is_in_static_method
1115             && ((id == special_classes::SELF && !env.cls_reified_generics().is_empty())
1116                 || (id == special_classes::PARENT && *env.parent_maybe_reified()))
1117         {
1118             Self::raise_parsing_error(node, env, &syntax_error::static_method_reified_obj_creation);
1119         }
1120     }
1122     fn fail_if_invalid_reified_generic(
1123         node: S<'a, T, V>,
1124         env: &mut Env<'a, TF>,
1125         id: impl AsRef<str>,
1126     ) {
1127         let is_in_static_method = *env.in_static_method();
1128         if is_in_static_method && env.cls_reified_generics().contains(id.as_ref()) {
1129             Self::raise_parsing_error(
1130                 node,
1131                 env,
1132                 &syntax_error::cls_reified_generic_in_static_method,
1133             );
1134         }
1135     }
1137     fn rfind(s: &[u8], mut i: usize, c: u8) -> Result<usize> {
1138         if i >= s.len() {
1139             return Self::failwith("index out of range");
1140         }
1141         i += 1;
1142         while i > 0 {
1143             i -= 1;
1144             if s[i] == c {
1145                 return Ok(i);
1146             }
1147         }
1148         Self::failwith("char not found")
1149     }
1151     fn prep_string2(
1152         nodes: &'a [Syntax<'a, T, V>],
1153         env: &mut Env<'a, TF>,
1154     ) -> Result<(TokenOp, TokenOp)> {
1155         use TokenOp::*;
1156         let is_qoute = |c| c == b'\"' || c == b'`';
1157         let start_is_qoute = |s: &[u8]| {
1158             (s.len() > 0 && is_qoute(s[0])) || (s.len() > 1 && (s[0] == b'b' && s[1] == b'\"'))
1159         };
1160         let last_is_qoute = |s: &[u8]| s.len() > 0 && is_qoute(s[s.len() - 1]);
1161         let is_heredoc = |s: &[u8]| (s.len() > 3 && &s[0..3] == b"<<<");
1162         let mut nodes = nodes.iter();
1163         let first = nodes.next();
1164         match first.map(|n| &n.children) {
1165             Some(Token(t)) => {
1166                 let raise = |env| {
1167                     Self::raise_parsing_error(first.unwrap(), env, "Malformed String2 SyntaxList");
1168                 };
1169                 let text = t.text_raw(env.source_text());
1170                 if start_is_qoute(text) {
1171                     let first_token_op = match text[0] {
1172                         b'b' if text.len() > 2 => LeftTrim(2),
1173                         _ if is_qoute(text[0]) && text.len() > 1 => LeftTrim(1),
1174                         _ => Skip,
1175                     };
1176                     if let Some(Token(t)) = nodes.last().map(|n| &n.children) {
1177                         let last_text = t.text_raw(env.source_text());
1178                         if last_is_qoute(last_text) {
1179                             let last_taken_op = match last_text.len() {
1180                                 n if n > 1 => RightTrim(1),
1181                                 _ => Skip,
1182                             };
1183                             return Ok((first_token_op, last_taken_op));
1184                         }
1185                     }
1186                     raise(env);
1187                     Ok((first_token_op, Noop))
1188                 } else if is_heredoc(text) {
1189                     let trim_size = text
1190                         .iter()
1191                         .position(|c| *c == b'\n')
1192                         .ok_or_else(|| Error::Failwith(String::from("newline not found")))?
1193                         + 1;
1194                     let first_token_op = match trim_size {
1195                         _ if trim_size == text.len() => Skip,
1196                         _ => LeftTrim(trim_size),
1197                     };
1198                     if let Some(Token(t)) = nodes.last().map(|n| &n.children) {
1199                         let text = t.text_raw(env.source_text());
1200                         let len = text.len();
1201                         if len != 0 {
1202                             let n = Self::rfind(text, len - 2, b'\n')?;
1203                             let last_token_op = match n {
1204                                 0 => Skip,
1205                                 _ => RightTrim(len - n),
1206                             };
1207                             return Ok((first_token_op, last_token_op));
1208                         }
1209                     }
1210                     raise(env);
1211                     Ok((first_token_op, Noop))
1212                 } else {
1213                     Ok((Noop, Noop))
1214                 }
1215             }
1216             _ => Ok((Noop, Noop)),
1217         }
1218     }
1220     fn process_token_op(
1221         env: &mut Env<'a, TF>,
1222         op: TokenOp,
1223         node: S<'a, T, V>,
1224     ) -> Result<Option<S<'a, T, V>>> {
1225         use TokenOp::*;
1226         match op {
1227             LeftTrim(n) => match &node.children {
1228                 Token(t) => {
1229                     let token = env.token_factory.trim_left(t, n);
1230                     let node = env.arena.alloc(<Syntax<'a, T, V>>::make_token(token));
1231                     Ok(Some(node))
1232                 }
1233                 _ => Self::failwith("Token expected"),
1234             },
1235             RightTrim(n) => match &node.children {
1236                 Token(t) => {
1237                     let token = env.token_factory.trim_right(t, n);
1238                     let node = env.arena.alloc(<Syntax<'a, T, V>>::make_token(token));
1239                     Ok(Some(node))
1240                 }
1241                 _ => Self::failwith("Token expected"),
1242             },
1243             _ => Ok(None),
1244         }
1245     }
1247     fn p_string2(nodes: &'a [Syntax<'a, T, V>], env: &mut Env<'a, TF>) -> Result<Vec<ast::Expr>> {
1248         use TokenOp::*;
1249         let (head_op, tail_op) = Self::prep_string2(nodes, env)?;
1250         let mut result = Vec::with_capacity(nodes.len());
1251         let mut i = 0;
1252         let last = nodes.len() - 1;
1253         while i <= last {
1254             let op = match i {
1255                 0 => head_op,
1256                 _ if i == last => tail_op,
1257                 _ => Noop,
1258             };
1260             if op == Skip {
1261                 i += 1;
1262                 continue;
1263             }
1265             let node = Self::process_token_op(env, op, &nodes[i])?;
1266             let node = node.unwrap_or(&nodes[i]);
1268             if Self::token_kind(node) == Some(TK::Dollar) && i < last {
1269                 if let EmbeddedBracedExpression(_) = &nodes[i + 1].children {
1270                     Self::raise_parsing_error(
1271                         &nodes[i + 1],
1272                         env,
1273                         &syntax_error::outside_dollar_str_interp,
1274                     );
1276                     result.push(Self::p_expr_with_loc(
1277                         ExprLocation::InDoubleQuotedString,
1278                         &nodes[i + 1],
1279                         env,
1280                     )?);
1281                     i += 2;
1282                     continue;
1283                 }
1284             }
1286             result.push(Self::p_expr_with_loc(
1287                 ExprLocation::InDoubleQuotedString,
1288                 node,
1289                 env,
1290             )?);
1291             i += 1;
1292         }
1293         Ok(result)
1294     }
1296     fn p_expr_l(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<Vec<ast::Expr>> {
1297         let p_expr = |n: S<'a, T, V>, e: &mut Env<'a, TF>| -> Result<ast::Expr> {
1298             Self::p_expr_with_loc(ExprLocation::TopLevel, n, e)
1299         };
1300         Self::could_map(p_expr, node, env)
1301     }
1303     fn p_expr(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Expr> {
1304         Self::p_expr_with_loc(ExprLocation::TopLevel, node, env)
1305     }
1307     fn p_expr_with_loc(
1308         location: ExprLocation,
1309         node: S<'a, T, V>,
1310         env: &mut Env<'a, TF>,
1311     ) -> Result<ast::Expr> {
1312         Self::p_expr_impl(location, node, env, None)
1313     }
1315     fn p_expr_impl(
1316         location: ExprLocation,
1317         node: S<'a, T, V>,
1318         env: &mut Env<'a, TF>,
1319         parent_pos: Option<Pos>,
1320     ) -> Result<ast::Expr> {
1321         match &node.children {
1322             BracedExpression(c) => {
1323                 // Either a dynamic method lookup on a dynamic value:
1324                 //   $foo->{$meth_name}();
1325                 // or an XHP splice.
1326                 //   <p id={$id}>hello</p>;
1327                 // In both cases, unwrap, consistent with parentheses.
1328                 Self::p_expr_impl(location, &c.expression, env, parent_pos)
1329             }
1330             ParenthesizedExpression(c) => {
1331                 Self::p_expr_impl(location, &c.expression, env, parent_pos)
1332             }
1333             ETSpliceExpression(c) => {
1334                 let pos = Self::p_pos(node, env);
1336                 let inner_pos = Self::p_pos(&c.expression, env);
1337                 let inner_expr_ = Self::p_expr_impl_(location, &c.expression, env, parent_pos)?;
1338                 let inner_expr = ast::Expr::new(inner_pos, inner_expr_);
1339                 Ok(ast::Expr::new(
1340                     pos,
1341                     ast::Expr_::ETSplice(Box::new(inner_expr)),
1342                 ))
1343             }
1344             _ => {
1345                 let pos = Self::p_pos(node, env);
1346                 let expr_ = Self::p_expr_impl_(location, node, env, parent_pos)?;
1347                 Ok(ast::Expr::new(pos, expr_))
1348             }
1349         }
1350     }
1352     fn p_expr_lit(
1353         location: ExprLocation,
1354         parent: S<'a, T, V>,
1355         expr: S<'a, T, V>,
1356         env: &mut Env<'a, TF>,
1357     ) -> Result<ast::Expr_> {
1358         match &expr.children {
1359             Token(_) => {
1360                 let s = expr.text(env.indexed_source_text.source_text());
1361                 let check_lint_err = |e: &mut Env<'a, TF>, s: &str, expected: &str| {
1362                     if !e.codegen() && s != expected {
1363                         Self::raise_lint_error(
1364                             e,
1365                             LintError::lowercase_constant(Self::p_pos(expr, e), s),
1366                         );
1367                     }
1368                 };
1369                 match (location, Self::token_kind(expr)) {
1370                     (ExprLocation::InDoubleQuotedString, _) if env.codegen() => {
1371                         Ok(E_::String(Self::mk_str(expr, env, Self::unesc_dbl, s)))
1372                     }
1373                     (_, Some(TK::OctalLiteral))
1374                         if env.is_typechecker() && !Self::is_num_octal_lit(s) =>
1375                     {
1376                         Self::raise_parsing_error(
1377                             parent,
1378                             env,
1379                             &syntax_error::invalid_octal_integer,
1380                         );
1381                         Self::missing_syntax("octal", expr, env)
1382                     }
1383                     (_, Some(TK::DecimalLiteral))
1384                     | (_, Some(TK::OctalLiteral))
1385                     | (_, Some(TK::HexadecimalLiteral))
1386                     | (_, Some(TK::BinaryLiteral)) => Ok(E_::Int(s.replace("_", ""))),
1387                     (_, Some(TK::FloatingLiteral)) => Ok(E_::Float(String::from(s))),
1388                     (_, Some(TK::SingleQuotedStringLiteral)) => {
1389                         Ok(E_::String(Self::mk_str(expr, env, unescape_single, s)))
1390                     }
1391                     (_, Some(TK::DoubleQuotedStringLiteral)) => {
1392                         Ok(E_::String(Self::mk_str(expr, env, unescape_double, s)))
1393                     }
1394                     (_, Some(TK::HeredocStringLiteral)) => {
1395                         Ok(E_::String(Self::mk_str(expr, env, unescape_heredoc, s)))
1396                     }
1397                     (_, Some(TK::NowdocStringLiteral)) => {
1398                         Ok(E_::String(Self::mk_str(expr, env, unescape_nowdoc, s)))
1399                     }
1400                     (_, Some(TK::NullLiteral)) => {
1401                         check_lint_err(env, s, literal::NULL);
1402                         Ok(E_::Null)
1403                     }
1404                     (_, Some(TK::BooleanLiteral)) => {
1405                         if s.eq_ignore_ascii_case(literal::FALSE) {
1406                             check_lint_err(env, s, literal::FALSE);
1407                             Ok(E_::False)
1408                         } else if s.eq_ignore_ascii_case(literal::TRUE) {
1409                             check_lint_err(env, s, literal::TRUE);
1410                             Ok(E_::True)
1411                         } else {
1412                             Self::missing_syntax(&format!("boolean (not: {})", s), expr, env)
1413                         }
1414                     }
1415                     _ => Self::missing_syntax("literal", expr, env),
1416                 }
1417             }
1418             SyntaxList(ts) => Ok(E_::String2(Self::p_string2(ts, env)?)),
1419             _ => Self::missing_syntax("literal expressoin", expr, env),
1420         }
1421     }
1423     fn p_expr_with_loc_(
1424         location: ExprLocation,
1425         node: S<'a, T, V>,
1426         env: &mut Env<'a, TF>,
1427     ) -> Result<ast::Expr_> {
1428         Self::p_expr_impl_(location, node, env, None)
1429     }
1431     fn p_expr_impl_(
1432         location: ExprLocation,
1433         node: S<'a, T, V>,
1434         env: &mut Env<'a, TF>,
1435         parent_pos: Option<Pos>,
1436     ) -> Result<ast::Expr_> {
1437         if *env.exp_recursion_depth() >= EXP_RECUSION_LIMIT {
1438             Err(Error::Failwith("Expression recursion limit reached".into()))
1439         } else {
1440             *env.exp_recursion_depth() += 1;
1441             let r = Self::p_expr_impl__(location, node, env, parent_pos);
1442             *env.exp_recursion_depth() -= 1;
1443             r
1444         }
1445     }
1447     fn p_expr_impl__(
1448         location: ExprLocation,
1449         node: S<'a, T, V>,
1450         env: &mut Env<'a, TF>,
1451         parent_pos: Option<Pos>,
1452     ) -> Result<ast::Expr_> {
1453         env.check_stack_limit();
1454         use ast::Expr as E;
1455         let split_args_vararg = |
1456             arg_list_node: S<'a, T, V>,
1457             e: &mut Env<'a, TF>,
1458         | -> Result<(Vec<ast::Expr>, Option<ast::Expr>)> {
1459             let mut arg_list: Vec<_> = arg_list_node.syntax_node_to_list_skip_separator().collect();
1460             if let Some(last_arg) = arg_list.last() {
1461                 if let DecoratedExpression(c) = &last_arg.children {
1462                     if Self::token_kind(&c.decorator) == Some(TK::DotDotDot) {
1463                         let _ = arg_list.pop();
1464                         let args: std::result::Result<Vec<_>, _> =
1465                             arg_list.iter().map(|a| Self::p_expr(a, e)).collect();
1466                         let args = args?;
1467                         let vararg = Self::p_expr(&c.expression, e)?;
1468                         return Ok((args, Some(vararg)));
1469                     }
1470                 }
1471             }
1472             Ok((Self::could_map(Self::p_expr, arg_list_node, e)?, None))
1473         };
1474         let mk_lid = |p: Pos, s: String| ast::Lid(p, (0, s));
1475         let mk_name_lid = |name: S<'a, T, V>, env: &mut Env<'a, TF>| {
1476             let name = Self::pos_name(name, env)?;
1477             Ok(mk_lid(name.0, name.1))
1478         };
1479         let mk_lvar =
1480             |name: S<'a, T, V>, env: &mut Env<'a, TF>| Ok(E_::mk_lvar(mk_name_lid(name, env)?));
1481         let mk_id_expr = |name: ast::Sid| E::new(name.0.clone(), E_::mk_id(name));
1482         let p_intri_expr = |kw, ty, v, e: &mut Env<'a, TF>| {
1483             let hints = Self::expand_type_args(ty, e)?;
1484             let hints = Self::check_intrinsic_type_arg_varity(node, e, hints);
1485             Ok(E_::mk_collection(
1486                 Self::pos_name(kw, e)?,
1487                 hints,
1488                 Self::could_map(Self::p_afield, v, e)?,
1489             ))
1490         };
1491         let p_special_call =
1492             |recv: S<'a, T, V>, args: S<'a, T, V>, e: &mut Env<'a, TF>| -> Result<ast::Expr_> {
1493                 let pos_if_has_parens = match &recv.children {
1494                     ParenthesizedExpression(_) => Some(Self::p_pos(recv, e)),
1495                     _ => None,
1496                 };
1497                 let recv = Self::p_expr(recv, e)?;
1498                 let recv = match (&recv.1, pos_if_has_parens) {
1499                     (E_::ObjGet(t), Some(ref _p)) => {
1500                         let (a, b, c, _false) = &**t;
1501                         E::new(
1502                             recv.0.clone(),
1503                             E_::mk_obj_get(a.clone(), b.clone(), c.clone(), true),
1504                         )
1505                     }
1506                     (E_::ClassGet(c), Some(ref _p)) => {
1507                         let (a, b, _false) = &**c;
1508                         E::new(recv.0.clone(), E_::mk_class_get(a.clone(), b.clone(), true))
1509                     }
1510                     _ => recv,
1511                 };
1512                 let (args, varargs) = split_args_vararg(args, e)?;
1513                 Ok(E_::mk_call(recv, vec![], args, varargs))
1514             };
1515         let p_obj_get = |
1516             recv: S<'a, T, V>,
1517             op: S<'a, T, V>,
1518             name: S<'a, T, V>,
1519             e: &mut Env<'a, TF>,
1520         | -> Result<ast::Expr_> {
1521             if recv.is_object_creation_expression() && !e.codegen() {
1522                 Self::raise_parsing_error(recv, e, &syntax_error::invalid_constructor_method_call);
1523             }
1524             let recv = Self::p_expr(recv, e)?;
1525             let name = Self::p_expr_with_loc(ExprLocation::MemberSelect, name, e)?;
1526             let op = Self::p_null_flavor(op, e)?;
1527             Ok(E_::mk_obj_get(recv, name, op, false))
1528         };
1529         let pos = match parent_pos {
1530             None => Self::p_pos(node, env),
1531             Some(p) => p,
1532         };
1533         match &node.children {
1534             LambdaExpression(c) => {
1535                 let suspension_kind = Self::mk_suspension_kind(&c.async_);
1536                 let (params, (ctxs, unsafe_ctxs), ret) = match &c.signature.children {
1537                     LambdaSignature(c) => (
1538                         Self::could_map(Self::p_fun_param, &c.parameters, env)?,
1539                         Self::p_contexts(&c.contexts, env)?,
1540                         Self::mp_optional(Self::p_hint, &c.type_, env)?,
1541                     ),
1542                     Token(_) => {
1543                         let ast::Id(p, n) = Self::pos_name(&c.signature, env)?;
1544                         (
1545                             vec![ast::FunParam {
1546                                 annotation: p.clone(),
1547                                 type_hint: ast::TypeHint((), None),
1548                                 is_variadic: false,
1549                                 pos: p,
1550                                 name: n,
1551                                 expr: None,
1552                                 callconv: None,
1553                                 user_attributes: vec![],
1554                                 visibility: None,
1555                             }],
1556                             (None, None),
1557                             None,
1558                         )
1559                     }
1560                     _ => Self::missing_syntax("lambda signature", &c.signature, env)?,
1561                 };
1562                 let (body, yield_) = if !c.body.is_compound_statement() {
1563                     Self::mp_yielding(Self::p_function_body, &c.body, env)?
1564                 } else {
1565                     let mut env1 = Env::clone_and_unset_toplevel_if_toplevel(env);
1566                     Self::mp_yielding(&Self::p_function_body, &c.body, env1.as_mut())?
1567                 };
1568                 let external = c.body.is_external();
1569                 let fun = ast::Fun_ {
1570                     span: pos.clone(),
1571                     annotation: (),
1572                     mode: env.file_mode(),
1573                     ret: ast::TypeHint((), ret),
1574                     name: ast::Id(pos, String::from(";anonymous")),
1575                     tparams: vec![],
1576                     where_constraints: vec![],
1577                     body: ast::FuncBody {
1578                         ast: body,
1579                         annotation: (),
1580                     },
1581                     fun_kind: Self::mk_fun_kind(suspension_kind, yield_),
1582                     variadic: Self::determine_variadicity(&params),
1583                     params,
1584                     ctxs,
1585                     unsafe_ctxs,
1586                     user_attributes: Self::p_user_attributes(&c.attribute_spec, env)?,
1587                     file_attributes: vec![],
1588                     external,
1589                     namespace: Self::mk_empty_ns_env(env),
1590                     doc_comment: None,
1591                     static_: false,
1592                 };
1593                 Ok(E_::mk_lfun(fun, vec![]))
1594             }
1595             BracedExpression(c) => Self::p_expr_with_loc_(location, &c.expression, env),
1596             EmbeddedBracedExpression(c) => {
1597                 Self::p_expr_impl_(location, &c.expression, env, Some(pos))
1598             }
1599             ParenthesizedExpression(c) => Self::p_expr_with_loc_(location, &c.expression, env),
1600             DictionaryIntrinsicExpression(c) => {
1601                 p_intri_expr(&c.keyword, &c.explicit_type, &c.members, env)
1602             }
1603             KeysetIntrinsicExpression(c) => {
1604                 p_intri_expr(&c.keyword, &c.explicit_type, &c.members, env)
1605             }
1606             VectorIntrinsicExpression(c) => {
1607                 p_intri_expr(&c.keyword, &c.explicit_type, &c.members, env)
1608             }
1609             CollectionLiteralExpression(c) => {
1610                 let (collection_name, hints) = match &c.name.children {
1611                     SimpleTypeSpecifier(c) => (Self::pos_name(&c.specifier, env)?, None),
1612                     GenericTypeSpecifier(c) => {
1613                         let hints = Self::expand_type_args(&c.argument_list, env)?;
1614                         let hints = Self::check_intrinsic_type_arg_varity(node, env, hints);
1615                         (Self::pos_name(&c.class_type, env)?, hints)
1616                     }
1617                     _ => (Self::pos_name(&c.name, env)?, None),
1618                 };
1619                 Ok(E_::mk_collection(
1620                     collection_name,
1621                     hints,
1622                     Self::could_map(Self::p_afield, &c.initializers, env)?,
1623                 ))
1624             }
1625             VarrayIntrinsicExpression(c) => {
1626                 let hints = Self::expand_type_args(&c.explicit_type, env)?;
1627                 let hints = Self::check_intrinsic_type_arg_varity(node, env, hints);
1628                 let targ = match hints {
1629                     Some(ast::CollectionTarg::CollectionTV(ty)) => Some(ty),
1630                     None => None,
1631                     _ => Self::missing_syntax("VarrayIntrinsicExpression type args", node, env)?,
1632                 };
1633                 Ok(E_::mk_varray(
1634                     targ,
1635                     Self::could_map(Self::p_expr, &c.members, env)?,
1636                 ))
1637             }
1638             DarrayIntrinsicExpression(c) => {
1639                 let hints = Self::expand_type_args(&c.explicit_type, env)?;
1640                 let hints = Self::check_intrinsic_type_arg_varity(node, env, hints);
1641                 match hints {
1642                     Some(ast::CollectionTarg::CollectionTKV(tk, tv)) => Ok(E_::mk_darray(
1643                         Some((tk, tv)),
1644                         Self::could_map(Self::p_member, &c.members, env)?,
1645                     )),
1646                     None => Ok(E_::mk_darray(
1647                         None,
1648                         Self::could_map(Self::p_member, &c.members, env)?,
1649                     )),
1650                     _ => Self::missing_syntax("DarrayIntrinsicExpression type args", node, env),
1651                 }
1652             }
1653             ListExpression(c) => {
1654                 /* TODO: Or tie in with other intrinsics and post-process to List */
1655                 let p_binder_or_ignore =
1656                     |n: S<'a, T, V>, e: &mut Env<'a, TF>| -> Result<ast::Expr> {
1657                         match &n.children {
1658                             Missing => Ok(E::new(e.mk_none_pos(), E_::Omitted)),
1659                             _ => Self::p_expr(n, e),
1660                         }
1661                     };
1662                 Ok(E_::List(Self::could_map(
1663                     &p_binder_or_ignore,
1664                     &c.members,
1665                     env,
1666                 )?))
1667             }
1668             EvalExpression(c) => p_special_call(&c.keyword, &c.argument, env),
1669             IssetExpression(c) => p_special_call(&c.keyword, &c.argument_list, env),
1670             TupleExpression(c) => p_special_call(&c.keyword, &c.items, env),
1671             FunctionCallExpression(c) => {
1672                 let recv = &c.receiver;
1673                 let args = &c.argument_list;
1674                 let get_hhas_adata = || {
1675                     if Self::text_str(recv, env) == "__hhas_adata" {
1676                         if let SyntaxList(l) = &args.children {
1677                             if let Some(li) = l.first() {
1678                                 if let ListItem(i) = &li.children {
1679                                     if let LiteralExpression(le) = &i.item.children {
1680                                         let expr = &le.expression;
1681                                         if Self::token_kind(expr) == Some(TK::NowdocStringLiteral) {
1682                                             return Some(expr);
1683                                         }
1684                                     }
1685                                 }
1686                             }
1687                         }
1688                     }
1689                     None
1690                 };
1691                 match get_hhas_adata() {
1692                     Some(expr) => {
1693                         let literal_expression_pos = Self::p_pos(expr, env);
1694                         let s = extract_unquoted_string(Self::text_str(expr, env), 0, expr.width())
1695                             .map_err(|e| Error::Failwith(e.msg))?;
1696                         Ok(E_::mk_call(
1697                             Self::p_expr(recv, env)?,
1698                             vec![],
1699                             vec![E::new(literal_expression_pos, E_::String(s.into()))],
1700                             None,
1701                         ))
1702                     }
1703                     None => {
1704                         let targs = match (&recv.children, &c.type_args.children) {
1705                             (_, TypeArguments(c)) => Self::could_map(Self::p_targ, &c.types, env)?,
1706                             /* TODO might not be needed */
1707                             (GenericTypeSpecifier(c), _) => match &c.argument_list.children {
1708                                 TypeArguments(c) => Self::could_map(Self::p_targ, &c.types, env)?,
1709                                 _ => vec![],
1710                             },
1711                             _ => vec![],
1712                         };
1714                         /* preserve parens on receiver of call expression
1715                         to allow distinguishing between
1716                         ($a->b)() // invoke on callable property
1717                         $a->b()   // method call */
1718                         let pos_if_has_parens = match &recv.children {
1719                             ParenthesizedExpression(_) => Some(Self::p_pos(recv, env)),
1720                             _ => None,
1721                         };
1722                         let recv = Self::p_expr(recv, env)?;
1723                         let recv = match (&recv.1, pos_if_has_parens) {
1724                             (E_::ObjGet(t), Some(ref _p)) => {
1725                                 let (a, b, c, _false) = &**t;
1726                                 E::new(
1727                                     recv.0.clone(),
1728                                     E_::mk_obj_get(a.clone(), b.clone(), c.clone(), true),
1729                                 )
1730                             }
1731                             (E_::ClassGet(c), Some(ref _p)) => {
1732                                 let (a, b, _false) = &**c;
1733                                 E::new(recv.0.clone(), E_::mk_class_get(a.clone(), b.clone(), true))
1734                             }
1735                             _ => recv,
1736                         };
1737                         let (args, varargs) = split_args_vararg(args, env)?;
1738                         Ok(E_::mk_call(recv, targs, args, varargs))
1739                     }
1740                 }
1741             }
1742             FunctionPointerExpression(c) => {
1743                 let targs = match &c.type_args.children {
1744                     TypeArguments(c) => Self::could_map(Self::p_targ, &c.types, env)?,
1745                     _ => vec![],
1746                 };
1748                 let recv = Self::p_expr(&c.receiver, env)?;
1750                 match &recv.1 {
1751                     aast::Expr_::Id(id) => Ok(E_::mk_function_pointer(
1752                         aast::FunctionPtrId::FPId(*(id.to_owned())),
1753                         targs,
1754                     )),
1755                     aast::Expr_::ClassConst(c) => {
1756                         if let aast::ClassId_::CIexpr(aast::Expr(_, aast::Expr_::Id(_))) = (c.0).1 {
1757                             Ok(E_::mk_function_pointer(
1758                                 aast::FunctionPtrId::FPClassConst(c.0.to_owned(), c.1.to_owned()),
1759                                 targs,
1760                             ))
1761                         } else {
1762                             Self::raise_parsing_error(
1763                                 node,
1764                                 env,
1765                                 &syntax_error::function_pointer_bad_recv,
1766                             );
1767                             Self::missing_syntax("function or static method", node, env)
1768                         }
1769                     }
1770                     _ => {
1771                         Self::raise_parsing_error(
1772                             node,
1773                             env,
1774                             &syntax_error::function_pointer_bad_recv,
1775                         );
1776                         Self::missing_syntax("function or static method", node, env)
1777                     }
1778                 }
1779             }
1780             QualifiedName(_) => match location {
1781                 ExprLocation::InDoubleQuotedString => {
1782                     let ast::Id(_, n) = Self::pos_qualified_name(node, env)?;
1783                     Ok(E_::String(n.into()))
1784                 }
1785                 _ => Ok(E_::mk_id(Self::pos_qualified_name(node, env)?)),
1786             },
1787             VariableExpression(c) => Ok(E_::mk_lvar(Self::lid_from_pos_name(
1788                 pos,
1789                 &c.expression,
1790                 env,
1791             )?)),
1792             PipeVariableExpression(_) => Ok(E_::mk_lvar(mk_lid(
1793                 pos,
1794                 special_idents::DOLLAR_DOLLAR.into(),
1795             ))),
1796             InclusionExpression(c) => Ok(E_::mk_import(
1797                 Self::p_import_flavor(&c.require, env)?,
1798                 Self::p_expr(&c.filename, env)?,
1799             )),
1800             MemberSelectionExpression(c) => p_obj_get(&c.object, &c.operator, &c.name, env),
1801             SafeMemberSelectionExpression(c) => p_obj_get(&c.object, &c.operator, &c.name, env),
1802             EmbeddedMemberSelectionExpression(c) => p_obj_get(&c.object, &c.operator, &c.name, env),
1803             PrefixUnaryExpression(_) | PostfixUnaryExpression(_) | DecoratedExpression(_) => {
1804                 let (operand, op, postfix) = match &node.children {
1805                     PrefixUnaryExpression(c) => (&c.operand, &c.operator, false),
1806                     PostfixUnaryExpression(c) => (&c.operand, &c.operator, true),
1807                     DecoratedExpression(c) => (&c.expression, &c.decorator, false),
1808                     _ => Self::missing_syntax("unary exppr", node, env)?,
1809                 };
1811                 /**
1812                  * FFP does not destinguish between ++$i and $i++ on the level of token
1813                  * kind annotation. Prevent duplication by switching on `postfix` for
1814                  * the two operatores for which AST /does/ differentiate between
1815                  * fixities.
1816                  */
1817                 use ast::Uop::*;
1818                 let mk_unop = |op, e| Ok(E_::mk_unop(op, e));
1819                 let op_kind = Self::token_kind(op);
1820                 if let Some(TK::At) = op_kind {
1821                     if env.parser_options.po_disallow_silence {
1822                         Self::raise_parsing_error(op, env, &syntax_error::no_silence);
1823                     }
1824                     if env.codegen() {
1825                         let expr = Self::p_expr(operand, env)?;
1826                         mk_unop(Usilence, expr)
1827                     } else {
1828                         let expr =
1829                             Self::p_expr_impl(ExprLocation::TopLevel, operand, env, Some(pos))?;
1830                         Ok(expr.1)
1831                     }
1832                 } else {
1833                     let expr = Self::p_expr(operand, env)?;
1834                     match op_kind {
1835                         Some(TK::PlusPlus) if postfix => mk_unop(Upincr, expr),
1836                         Some(TK::MinusMinus) if postfix => mk_unop(Updecr, expr),
1837                         Some(TK::PlusPlus) => mk_unop(Uincr, expr),
1838                         Some(TK::MinusMinus) => mk_unop(Udecr, expr),
1839                         Some(TK::Exclamation) => mk_unop(Unot, expr),
1840                         Some(TK::Tilde) => mk_unop(Utild, expr),
1841                         Some(TK::Plus) => mk_unop(Uplus, expr),
1842                         Some(TK::Minus) => mk_unop(Uminus, expr),
1843                         Some(TK::Inout) => Ok(E_::mk_callconv(ast::ParamKind::Pinout, expr)),
1844                         Some(TK::Await) => Self::lift_await(pos, expr, env, location),
1845                         Some(TK::Clone) => Ok(E_::mk_clone(expr)),
1846                         Some(TK::Print) => Ok(E_::mk_call(
1847                             E::new(
1848                                 pos.clone(),
1849                                 E_::mk_id(ast::Id(pos, special_functions::ECHO.into())),
1850                             ),
1851                             vec![],
1852                             vec![expr],
1853                             None,
1854                         )),
1855                         Some(TK::Dollar) => {
1856                             Self::raise_parsing_error(
1857                                 op,
1858                                 env,
1859                                 &syntax_error::invalid_variable_name,
1860                             );
1861                             Ok(E_::Omitted)
1862                         }
1863                         _ => Self::missing_syntax("unary operator", node, env),
1864                     }
1865                 }
1866             }
1867             BinaryExpression(c) => {
1868                 use ExprLocation::*;
1869                 let rlocation = if Self::token_kind(&c.operator) == Some(TK::Equal) {
1870                     match location {
1871                         AsStatement => RightOfAssignment,
1872                         UsingStatement => RightOfAssignmentInUsingStatement,
1873                         _ => TopLevel,
1874                     }
1875                 } else {
1876                     TopLevel
1877                 };
1878                 let bop_ast_node = Self::p_bop(
1879                     pos,
1880                     &c.operator,
1881                     Self::p_expr(&c.left_operand, env)?,
1882                     Self::p_expr_with_loc(rlocation, &c.right_operand, env)?,
1883                     env,
1884                 )?;
1885                 if let Some((ast::Bop::Eq(_), lhs, _)) = bop_ast_node.as_binop() {
1886                     Self::check_lvalue(lhs, env);
1887                 }
1888                 Ok(bop_ast_node)
1889             }
1890             Token(t) => {
1891                 use ExprLocation::*;
1892                 match (location, t.kind()) {
1893                     (MemberSelect, TK::Variable) => mk_lvar(node, env),
1894                     (InDoubleQuotedString, TK::HeredocStringLiteral)
1895                     | (InDoubleQuotedString, TK::HeredocStringLiteralHead)
1896                     | (InDoubleQuotedString, TK::HeredocStringLiteralTail) => Ok(E_::String(
1897                         Self::wrap_unescaper(unescape_heredoc, Self::text_str(node, env))?,
1898                     )),
1899                     (InDoubleQuotedString, _) => Ok(E_::String(Self::wrap_unescaper(
1900                         Self::unesc_dbl,
1901                         Self::text_str(node, env),
1902                     )?)),
1903                     (MemberSelect, _)
1904                     | (TopLevel, _)
1905                     | (AsStatement, _)
1906                     | (UsingStatement, _)
1907                     | (RightOfAssignment, _)
1908                     | (RightOfAssignmentInUsingStatement, _)
1909                     | (RightOfReturn, _) => Ok(E_::mk_id(Self::pos_name(node, env)?)),
1910                 }
1911             }
1912             YieldExpression(c) => {
1913                 use ExprLocation::*;
1914                 env.saw_yield = true;
1915                 if location != AsStatement
1916                     && location != RightOfAssignment
1917                     && location != RightOfAssignmentInUsingStatement
1918                 {
1919                     Self::raise_parsing_error(node, env, &syntax_error::invalid_yield);
1920                 }
1921                 if Self::text_str(&c.operand, env) == "break" {
1922                     Ok(E_::YieldBreak)
1923                 } else if c.operand.is_missing() {
1924                     Ok(E_::mk_yield(ast::Afield::AFvalue(E::new(pos, E_::Null))))
1925                 } else {
1926                     Ok(E_::mk_yield(Self::p_afield(&c.operand, env)?))
1927                 }
1928             }
1929             DefineExpression(c) => {
1930                 let name = Self::pos_name(&c.keyword, env)?;
1931                 Ok(E_::mk_call(
1932                     mk_id_expr(name),
1933                     vec![],
1934                     c.argument_list
1935                         .syntax_node_to_list_skip_separator()
1936                         .map(|x| Self::p_expr(x, env))
1937                         .collect::<std::result::Result<Vec<_>, _>>()?,
1938                     None,
1939                 ))
1940             }
1941             ScopeResolutionExpression(c) => {
1942                 let qual = Self::p_expr(&c.qualifier, env)?;
1943                 if let E_::Id(id) = &qual.1 {
1944                     Self::fail_if_invalid_reified_generic(node, env, &id.1);
1945                 }
1946                 match &c.name.children {
1947                     Token(token) if token.kind() == TK::Variable => {
1948                         let ast::Id(p, name) = Self::pos_name(&c.name, env)?;
1949                         Ok(E_::mk_class_get(
1950                             ast::ClassId(pos, ast::ClassId_::CIexpr(qual)),
1951                             ast::ClassGetExpr::CGstring((p, name)),
1952                             false,
1953                         ))
1954                     }
1955                     _ => {
1956                         let E(p, expr_) = Self::p_expr(&c.name, env)?;
1957                         match expr_ {
1958                             E_::String(id) => Ok(E_::mk_class_const(
1959                                 ast::ClassId(pos, ast::ClassId_::CIexpr(qual)),
1960                                 (
1961                                     p,
1962                                     String::from_utf8(id.into())
1963                                         .map_err(|e| Error::Failwith(e.to_string()))?,
1964                                 ),
1965                             )),
1966                             E_::Id(id) => {
1967                                 let ast::Id(p, n) = *id;
1968                                 Ok(E_::mk_class_const(
1969                                     ast::ClassId(pos, ast::ClassId_::CIexpr(qual)),
1970                                     (p, n),
1971                                 ))
1972                             }
1973                             E_::Lvar(id) => {
1974                                 let ast::Lid(p, (_, n)) = *id;
1975                                 Ok(E_::mk_class_get(
1976                                     ast::ClassId(pos, ast::ClassId_::CIexpr(qual)),
1977                                     ast::ClassGetExpr::CGstring((p, n)),
1978                                     false,
1979                                 ))
1980                             }
1981                             _ => Ok(E_::mk_class_get(
1982                                 ast::ClassId(pos, ast::ClassId_::CIexpr(qual)),
1983                                 ast::ClassGetExpr::CGexpr(E(p, expr_)),
1984                                 false,
1985                             )),
1986                         }
1987                     }
1988                 }
1989             }
1990             CastExpression(c) => Ok(E_::mk_cast(
1991                 Self::p_hint(&c.type_, env)?,
1992                 Self::p_expr(&c.operand, env)?,
1993             )),
1994             PrefixedCodeExpression(c) => {
1995                 let src_expr = Self::p_expr(&c.expression, env)?;
1996                 let hint = Self::p_hint(&c.prefix, env)?;
1997                 let desugared_expr = desugar(&hint, &src_expr, env);
1998                 Ok(E_::mk_expression_tree(ast::ExpressionTree {
1999                     hint,
2000                     src_expr,
2001                     desugared_expr,
2002                 }))
2003             }
2004             ConditionalExpression(c) => {
2005                 let alter = Self::p_expr(&c.alternative, env)?;
2006                 let consequence = Self::mp_optional(Self::p_expr, &c.consequence, env)?;
2007                 let condition = Self::p_expr(&c.test, env)?;
2008                 Ok(E_::mk_eif(condition, consequence, alter))
2009             }
2010             SubscriptExpression(c) => Ok(E_::mk_array_get(
2011                 Self::p_expr(&c.receiver, env)?,
2012                 Self::mp_optional(Self::p_expr, &c.index, env)?,
2013             )),
2014             EmbeddedSubscriptExpression(c) => Ok(E_::mk_array_get(
2015                 Self::p_expr(&c.receiver, env)?,
2016                 Self::mp_optional(|n, e| Self::p_expr_with_loc(location, n, e), &c.index, env)?,
2017             )),
2018             ShapeExpression(c) => Ok(E_::Shape(Self::could_map(
2019                 |n: S<'a, T, V>, e: &mut Env<'a, TF>| {
2020                     Self::mp_shape_expression_field(&Self::p_expr, n, e)
2021                 },
2022                 &c.fields,
2023                 env,
2024             )?)),
2025             ObjectCreationExpression(c) => Self::p_expr_impl_(location, &c.object, env, Some(pos)),
2026             ConstructorCall(c) => {
2027                 let (args, varargs) = split_args_vararg(&c.argument_list, env)?;
2028                 let (e, hl) = match &c.type_.children {
2029                     GenericTypeSpecifier(c) => {
2030                         let name = Self::pos_name(&c.class_type, env)?;
2031                         let hints = match &c.argument_list.children {
2032                             TypeArguments(c) => Self::could_map(Self::p_targ, &c.types, env)?,
2033                             _ => Self::missing_syntax(
2034                                 "generic type arguments",
2035                                 &c.argument_list,
2036                                 env,
2037                             )?,
2038                         };
2039                         (mk_id_expr(name), hints)
2040                     }
2041                     SimpleTypeSpecifier(_) => {
2042                         let name = Self::pos_name(&c.type_, env)?;
2043                         (mk_id_expr(name), vec![])
2044                     }
2045                     _ => (Self::p_expr(&c.type_, env)?, vec![]),
2046                 };
2047                 if let E_::Id(name) = &e.1 {
2048                     Self::fail_if_invalid_reified_generic(node, env, &name.1);
2049                     Self::fail_if_invalid_class_creation(node, env, &name.1);
2050                 }
2051                 Ok(E_::mk_new(
2052                     ast::ClassId(pos.clone(), ast::ClassId_::CIexpr(e)),
2053                     hl,
2054                     args,
2055                     varargs,
2056                     pos,
2057                 ))
2058             }
2059             GenericTypeSpecifier(c) => {
2060                 if !c.argument_list.is_missing() {
2061                     Self::raise_parsing_error(
2062                         &c.argument_list,
2063                         env,
2064                         &syntax_error::targs_not_allowed,
2065                     )
2066                 }
2067                 Ok(E_::mk_id(Self::pos_name(&c.class_type, env)?))
2068             }
2069             RecordCreationExpression(c) => {
2070                 let id = Self::pos_name(&c.type_, env)?;
2071                 Ok(E_::mk_record(
2072                     id,
2073                     Self::could_map(Self::p_member, &c.members, env)?,
2074                 ))
2075             }
2076             LiteralExpression(c) => Self::p_expr_lit(location, node, &c.expression, env),
2077             PrefixedStringExpression(c) => {
2078                 /* Temporarily allow only`re`- prefixed strings */
2079                 let name_text = Self::text(&c.name, env);
2080                 if name_text != "re" {
2081                     Self::raise_parsing_error(node, env, &syntax_error::non_re_prefix);
2082                 }
2083                 Ok(E_::mk_prefixed_string(
2084                     name_text,
2085                     Self::p_expr(&c.str, env)?,
2086                 ))
2087             }
2088             IsExpression(c) => Ok(E_::mk_is(
2089                 Self::p_expr(&c.left_operand, env)?,
2090                 Self::p_hint(&c.right_operand, env)?,
2091             )),
2092             AsExpression(c) => Ok(E_::mk_as(
2093                 Self::p_expr(&c.left_operand, env)?,
2094                 Self::p_hint(&c.right_operand, env)?,
2095                 false,
2096             )),
2097             NullableAsExpression(c) => Ok(E_::mk_as(
2098                 Self::p_expr(&c.left_operand, env)?,
2099                 Self::p_hint(&c.right_operand, env)?,
2100                 true,
2101             )),
2102             AnonymousFunction(c) => {
2103                 if env.parser_options.po_disable_static_closures
2104                     && Self::token_kind(&c.static_keyword) == Some(TK::Static)
2105                 {
2106                     Self::raise_parsing_error(
2107                         node,
2108                         env,
2109                         &syntax_error::static_closures_are_disabled,
2110                     );
2111                 }
2112                 let p_arg = |n: S<'a, T, V>, e: &mut Env<'a, TF>| match &n.children {
2113                     Token(_) => mk_name_lid(n, e),
2114                     _ => Self::missing_syntax("use variable", n, e),
2115                 };
2116                 let (ctxs, unsafe_ctxs) = Self::p_contexts(&c.ctx_list, env)?;
2117                 let p_use = |n: S<'a, T, V>, e: &mut Env<'a, TF>| match &n.children {
2118                     AnonymousFunctionUseClause(c) => Self::could_map(p_arg, &c.variables, e),
2119                     _ => Ok(vec![]),
2120                 };
2121                 let suspension_kind = Self::mk_suspension_kind(&c.async_keyword);
2122                 let (body, yield_) = {
2123                     let mut env1 = Env::clone_and_unset_toplevel_if_toplevel(env);
2124                     Self::mp_yielding(&Self::p_function_body, &c.body, env1.as_mut())?
2125                 };
2126                 let doc_comment =
2127                     Self::extract_docblock(node, env).or_else(|| env.top_docblock().clone());
2128                 let user_attributes = Self::p_user_attributes(&c.attribute_spec, env)?;
2129                 let external = c.body.is_external();
2130                 let params = Self::could_map(Self::p_fun_param, &c.parameters, env)?;
2131                 let name_pos = Self::p_fun_pos(node, env);
2132                 let fun = ast::Fun_ {
2133                     span: Self::p_pos(node, env),
2134                     annotation: (),
2135                     mode: env.file_mode(),
2136                     ret: ast::TypeHint((), Self::mp_optional(Self::p_hint, &c.type_, env)?),
2137                     name: ast::Id(name_pos, String::from(";anonymous")),
2138                     tparams: vec![],
2139                     where_constraints: vec![],
2140                     body: ast::FuncBody {
2141                         ast: body,
2142                         annotation: (),
2143                     },
2144                     fun_kind: Self::mk_fun_kind(suspension_kind, yield_),
2145                     variadic: Self::determine_variadicity(&params),
2146                     params,
2147                     ctxs,
2148                     unsafe_ctxs,
2149                     user_attributes,
2150                     file_attributes: vec![],
2151                     external,
2152                     namespace: Self::mk_empty_ns_env(env),
2153                     doc_comment,
2154                     static_: !c.static_keyword.is_missing(),
2155                 };
2156                 let uses = p_use(&c.use_, env).unwrap_or_else(|_| vec![]);
2157                 Ok(E_::mk_efun(fun, uses))
2158             }
2159             AwaitableCreationExpression(c) => {
2160                 let suspension_kind = Self::mk_suspension_kind(&c.async_);
2161                 let (blk, yld) =
2162                     Self::mp_yielding(&Self::p_function_body, &c.compound_statement, env)?;
2163                 let user_attributes = Self::p_user_attributes(&c.attribute_spec, env)?;
2164                 let external = c.compound_statement.is_external();
2165                 let name_pos = Self::p_fun_pos(node, env);
2166                 let body = ast::Fun_ {
2167                     span: pos.clone(),
2168                     annotation: (),
2169                     mode: env.file_mode(),
2170                     ret: ast::TypeHint((), None),
2171                     name: ast::Id(name_pos, String::from(";anonymous")),
2172                     tparams: vec![],
2173                     where_constraints: vec![],
2174                     body: ast::FuncBody {
2175                         ast: if blk.len() == 0 {
2176                             let pos = Self::p_pos(&c.compound_statement, env);
2177                             vec![ast::Stmt::noop(pos)]
2178                         } else {
2179                             blk
2180                         },
2181                         annotation: (),
2182                     },
2183                     fun_kind: Self::mk_fun_kind(suspension_kind, yld),
2184                     variadic: Self::determine_variadicity(&[]),
2185                     params: vec![],
2186                     ctxs: None,        // TODO(T70095684)
2187                     unsafe_ctxs: None, // TODO(T70095684)
2188                     user_attributes,
2189                     file_attributes: vec![],
2190                     external,
2191                     namespace: Self::mk_empty_ns_env(env),
2192                     doc_comment: None,
2193                     static_: false,
2194                 };
2195                 Ok(E_::mk_call(
2196                     E::new(pos, E_::mk_lfun(body, vec![])),
2197                     vec![],
2198                     vec![],
2199                     None,
2200                 ))
2201             }
2202             XHPExpression(c) if c.open.is_xhp_open() => {
2203                 if let XHPOpen(c1) = &c.open.children {
2204                     let name = Self::pos_name(&c1.name, env)?;
2205                     let attrs = Self::could_map(Self::p_xhp_attr, &c1.attributes, env)?;
2206                     let exprs = Self::aggregate_xhp_tokens(env, &c.body)?
2207                         .iter()
2208                         .map(|n| Self::p_xhp_embedded(Self::unesc_xhp, n, env))
2209                         .collect::<std::result::Result<Vec<_>, _>>()?;
2211                     let id = if env.empty_ns_env.disable_xhp_element_mangling {
2212                         ast::Id(name.0, name.1)
2213                     } else {
2214                         ast::Id(name.0, String::from(":") + &name.1)
2215                     };
2217                     Ok(E_::mk_xml(
2218                         // TODO: update pos_name to support prefix
2219                         id, attrs, exprs,
2220                     ))
2221                 } else {
2222                     Self::failwith("expect xhp open")
2223                 }
2224             }
2225             EnumAtomExpression(c) => Ok(E_::EnumAtom(Self::pos_name(&c.expression, env)?.1)),
2226             _ => Self::missing_syntax_(Some(E_::Null), "expression", node, env),
2227         }
2228     }
2230     fn check_lvalue(ast::Expr(p, expr_): &ast::Expr, env: &mut Env<'a, TF>) {
2231         use aast::Expr_::*;
2232         let mut raise = |s| Self::raise_parsing_error_pos(p, env, s);
2233         match expr_ {
2234             ObjGet(og) => {
2235                 if og.as_ref().3 {
2236                     raise("Invalid lvalue")
2237                 } else {
2238                     match og.as_ref() {
2239                         (_, ast::Expr(_, Id(_)), ast::OgNullFlavor::OGNullsafe, _) => {
2240                             raise("?-> syntax is not supported for lvalues")
2241                         }
2242                         (_, ast::Expr(_, Id(sid)), _, _) if sid.1.as_bytes()[0] == b':' => {
2243                             raise("->: syntax is not supported for lvalues")
2244                         }
2245                         _ => {}
2246                     }
2247                 }
2248             }
2249             ArrayGet(ag) => {
2250                 if let ClassConst(_) = (ag.0).1 {
2251                     raise("Array-like class consts are not valid lvalues");
2252                 }
2253             }
2254             Call(c) => match &(c.0).1 {
2255                 Id(sid) if sid.1 == "tuple" => {
2256                     raise("Tuple cannot be used as an lvalue. Maybe you meant list?")
2257                 }
2258                 _ => raise("Invalid lvalue"),
2259             },
2260             List(l) => {
2261                 for i in l.iter() {
2262                     Self::check_lvalue(i, env);
2263                 }
2264             }
2265             Darray(_) | Varray(_) | Shape(_) | Collection(_) | Record(_) | Null | True | False
2266             | Id(_) | Clone(_) | ClassConst(_) | Int(_) | Float(_) | PrefixedString(_)
2267             | String(_) | String2(_) | Yield(_) | YieldBreak | Await(_) | Cast(_) | Unop(_)
2268             | Binop(_) | Eif(_) | New(_) | Efun(_) | Lfun(_) | Xml(_) | Import(_) | Pipe(_)
2269             | Callconv(_) | Is(_) | As(_) => raise("Invalid lvalue"),
2270             _ => {}
2271         }
2272     }
2274     fn p_xhp_embedded<F>(escaper: F, node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Expr>
2275     where
2276         F: FnOnce(&[u8]) -> Vec<u8>,
2277     {
2278         if let Some(kind) = Self::token_kind(node) {
2279             if env.codegen() && TK::XHPStringLiteral == kind {
2280                 let p = Self::p_pos(node, env);
2281                 /* for XHP string literals (attribute values) just extract
2282                 value from quotes and decode HTML entities  */
2283                 let text = html_entities::decode(&Self::get_quoted_content(
2284                     node.full_text(env.source_text()),
2285                 ));
2286                 Ok(ast::Expr::new(p, E_::make_string(text)))
2287             } else if env.codegen() && TK::XHPBody == kind {
2288                 let p = Self::p_pos(node, env);
2289                 /* for XHP body - only decode HTML entities */
2290                 let text =
2291                     html_entities::decode(&Self::unesc_xhp(node.full_text(env.source_text())));
2292                 Ok(ast::Expr::new(p, E_::make_string(text)))
2293             } else {
2294                 let p = Self::p_pos(node, env);
2295                 let s = escaper(node.full_text(env.source_text()));
2296                 Ok(ast::Expr::new(p, E_::make_string(s)))
2297             }
2298         } else {
2299             Self::p_expr(node, env)
2300         }
2301     }
2304     fn p_xhp_attr(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::XhpAttribute> {
2305         match &node.children {
2306             XHPSimpleAttribute(c) => {
2307                 let attr_expr = &c.expression;
2308                 let name = Self::p_pstring(&c.name, env)?;
2309                 let expr = if attr_expr.is_braced_expression()
2310                     && env.file_mode() == file_info::Mode::Mdecl
2311                     && !env.codegen()
2312                 {
2313                     ast::Expr::new(env.mk_none_pos(), E_::Null)
2314                 } else {
2315                     Self::p_xhp_embedded(Self::unesc_xhp_attr, attr_expr, env)?
2316                 };
2317                 Ok(ast::XhpAttribute::XhpSimple(name, expr))
2318             }
2319             XHPSpreadAttribute(c) => {
2320                 let expr = Self::p_xhp_embedded(Self::unesc_xhp, &c.expression, env)?;
2321                 Ok(ast::XhpAttribute::XhpSpread(expr))
2322             }
2323             _ => Self::missing_syntax("XHP attribute", node, env),
2324         }
2325     }
2327     fn aggregate_xhp_tokens(env: &mut Env<'a, TF>, nodes: S<'a, T, V>) -> Result<Vec<S<'a, T, V>>> {
2328         let nodes = nodes.syntax_node_to_list_skip_separator();
2329         let mut state = (None, None, vec![]); // (start, end, result)
2330         let mut combine =
2331             |state: &mut (Option<S<'a, T, V>>, Option<S<'a, T, V>>, Vec<S<'a, T, V>>)| {
2332                 match (state.0, state.1) {
2333                     (Some(s), None) => state.2.push(s),
2334                     (Some(s), Some(e)) => {
2335                         let token = env
2336                             .token_factory
2337                             .concatenate(s.get_token().unwrap(), e.get_token().unwrap());
2338                         let node = env.arena.alloc(<Syntax<T, V>>::make_token(token));
2339                         state.2.push(node)
2340                     }
2341                     _ => {}
2342                 }
2343                 state.0 = None;
2344                 state.1 = None;
2345                 Ok(())
2346             };
2347         for n in nodes {
2348             match &n.children {
2349                 Token(t) if t.kind() == TK::XHPComment => {
2350                     if state.0.is_some() {
2351                         combine(&mut state)?;
2352                     }
2353                 }
2354                 Token(_) => {
2355                     if state.0.is_none() {
2356                         state.0 = Some(n)
2357                     } else {
2358                         state.1 = Some(n)
2359                     }
2360                 }
2361                 _ => {
2362                     combine(&mut state)?;
2363                     state.2.push(n);
2364                 }
2365             }
2366         }
2367         combine(&mut state)?;
2368         Ok(state.2)
2369     }
2371     fn p_bop(
2372         pos: Pos,
2373         node: S<'a, T, V>,
2374         lhs: ast::Expr,
2375         rhs: ast::Expr,
2376         env: &mut Env<'a, TF>,
2377     ) -> Result<ast::Expr_> {
2378         use ast::Bop::*;
2379         let mk = |op, l, r| Ok(E_::mk_binop(op, l, r));
2380         let mk_eq = |op, l, r| Ok(E_::mk_binop(Eq(Some(Box::new(op))), l, r));
2381         match Self::token_kind(node) {
2382             Some(TK::Equal) => mk(Eq(None), lhs, rhs),
2383             Some(TK::Bar) => mk(Bar, lhs, rhs),
2384             Some(TK::Ampersand) => mk(Amp, lhs, rhs),
2385             Some(TK::Plus) => mk(Plus, lhs, rhs),
2386             Some(TK::Minus) => mk(Minus, lhs, rhs),
2387             Some(TK::Star) => mk(Star, lhs, rhs),
2388             Some(TK::Carat) => mk(Xor, lhs, rhs),
2389             Some(TK::Slash) => mk(Slash, lhs, rhs),
2390             Some(TK::Dot) => mk(Dot, lhs, rhs),
2391             Some(TK::Percent) => mk(Percent, lhs, rhs),
2392             Some(TK::LessThan) => mk(Lt, lhs, rhs),
2393             Some(TK::GreaterThan) => mk(Gt, lhs, rhs),
2394             Some(TK::EqualEqual) => mk(Eqeq, lhs, rhs),
2395             Some(TK::LessThanEqual) => mk(Lte, lhs, rhs),
2396             Some(TK::GreaterThanEqual) => mk(Gte, lhs, rhs),
2397             Some(TK::StarStar) => mk(Starstar, lhs, rhs),
2398             Some(TK::ExclamationEqual) => mk(Diff, lhs, rhs),
2399             Some(TK::BarEqual) => mk_eq(Bar, lhs, rhs),
2400             Some(TK::PlusEqual) => mk_eq(Plus, lhs, rhs),
2401             Some(TK::MinusEqual) => mk_eq(Minus, lhs, rhs),
2402             Some(TK::StarEqual) => mk_eq(Star, lhs, rhs),
2403             Some(TK::StarStarEqual) => mk_eq(Starstar, lhs, rhs),
2404             Some(TK::SlashEqual) => mk_eq(Slash, lhs, rhs),
2405             Some(TK::DotEqual) => mk_eq(Dot, lhs, rhs),
2406             Some(TK::PercentEqual) => mk_eq(Percent, lhs, rhs),
2407             Some(TK::CaratEqual) => mk_eq(Xor, lhs, rhs),
2408             Some(TK::AmpersandEqual) => mk_eq(Amp, lhs, rhs),
2409             Some(TK::BarBar) => mk(Barbar, lhs, rhs),
2410             Some(TK::AmpersandAmpersand) => mk(Ampamp, lhs, rhs),
2411             Some(TK::LessThanLessThan) => mk(Ltlt, lhs, rhs),
2412             Some(TK::GreaterThanGreaterThan) => mk(Gtgt, lhs, rhs),
2413             Some(TK::EqualEqualEqual) => mk(Eqeqeq, lhs, rhs),
2414             Some(TK::LessThanLessThanEqual) => mk_eq(Ltlt, lhs, rhs),
2415             Some(TK::GreaterThanGreaterThanEqual) => mk_eq(Gtgt, lhs, rhs),
2416             Some(TK::ExclamationEqualEqual) => mk(Diff2, lhs, rhs),
2417             Some(TK::LessThanEqualGreaterThan) => mk(Cmp, lhs, rhs),
2418             Some(TK::QuestionQuestion) => mk(QuestionQuestion, lhs, rhs),
2419             Some(TK::QuestionQuestionEqual) => mk_eq(QuestionQuestion, lhs, rhs),
2420             /* The ugly duckling; In the FFP, `|>` is parsed as a
2421              * `BinaryOperator`, whereas the typed AST has separate constructors for
2422              * Pipe and Binop. This is why we don't just project onto a
2423              * `bop`, but a `expr -> expr -> expr_`.
2424              */
2425             Some(TK::BarGreaterThan) => {
2426                 let lid =
2427                     ast::Lid::from_counter(pos, env.next_local_id(), special_idents::DOLLAR_DOLLAR);
2428                 Ok(E_::mk_pipe(lid, lhs, rhs))
2429             }
2430             Some(TK::QuestionColon) => Ok(E_::mk_eif(lhs, None, rhs)),
2431             _ => Self::missing_syntax("binary operator", node, env),
2432         }
2433     }
2435     fn p_exprs_with_loc(n: S<'a, T, V>, e: &mut Env<'a, TF>) -> Result<(Pos, Vec<ast::Expr>)> {
2436         let loc = Self::p_pos(&n, e);
2437         let p_expr = |n: S<'a, T, V>, e: &mut Env<'a, TF>| -> Result<ast::Expr> {
2438             Self::p_expr_with_loc(ExprLocation::UsingStatement, n, e)
2439         };
2440         Ok((loc, Self::could_map(p_expr, n, e)?))
2441     }
2443     fn p_stmt_list_(
2444         pos: &Pos,
2445         mut nodes: Iter<S<'a, T, V>>,
2446         env: &mut Env<'a, TF>,
2447     ) -> Result<Vec<ast::Stmt>> {
2448         let mut r = vec![];
2449         loop {
2450             match nodes.next() {
2451                 Some(n) => match &n.children {
2452                     UsingStatementFunctionScoped(c) => {
2453                         let body = Self::p_stmt_list_(pos, nodes, env)?;
2454                         let f = |e: &mut Env<'a, TF>| {
2455                             Ok(ast::Stmt::new(
2456                                 pos.clone(),
2457                                 ast::Stmt_::mk_using(ast::UsingStmt {
2458                                     is_block_scoped: false,
2459                                     has_await: !c.await_keyword.is_missing(),
2460                                     exprs: Self::p_exprs_with_loc(&c.expression, e)?,
2461                                     block: body,
2462                                 }),
2463                             ))
2464                         };
2465                         let using = Self::lift_awaits_in_statement_(f, Either::Right(pos), env)?;
2466                         r.push(using);
2467                         break Ok(r);
2468                     }
2469                     _ => {
2470                         r.push(Self::p_stmt(n, env)?);
2471                     }
2472                 },
2473                 _ => break Ok(r),
2474             }
2475         }
2476     }
2478     fn handle_loop_body(pos: Pos, node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Stmt> {
2479         let list: Vec<_> = node.syntax_node_to_list_skip_separator().collect();
2480         let blk: Vec<_> = Self::p_stmt_list_(&pos, list.iter(), env)?
2481             .into_iter()
2482             .filter(|stmt| !stmt.1.is_noop())
2483             .collect();
2484         let body = if blk.len() == 0 {
2485             vec![Self::mk_noop(env)]
2486         } else {
2487             blk
2488         };
2489         Ok(ast::Stmt::new(pos, ast::Stmt_::mk_block(body)))
2490     }
2492     fn is_simple_assignment_await_expression(node: S<'a, T, V>) -> bool {
2493         match &node.children {
2494             BinaryExpression(c) => {
2495                 Self::token_kind(&c.operator) == Some(TK::Equal)
2496                     && Self::is_simple_await_expression(&c.right_operand)
2497             }
2498             _ => false,
2499         }
2500     }
2502     fn is_simple_await_expression(node: S<'a, T, V>) -> bool {
2503         match &node.children {
2504             PrefixUnaryExpression(c) => Self::token_kind(&c.operator) == Some(TK::Await),
2505             _ => false,
2506         }
2507     }
2509     fn with_new_nonconcurrent_scope<F, R>(f: F, env: &mut Env<'a, TF>) -> R
2510     where
2511         F: FnOnce(&mut Env<'a, TF>) -> R,
2512     {
2513         let saved_lifted_awaits = env.lifted_awaits.take();
2514         let result = f(env);
2515         env.lifted_awaits = saved_lifted_awaits;
2516         result
2517     }
2519     fn with_new_concurrent_scope<F, R>(f: F, env: &mut Env<'a, TF>) -> Result<(LiftedAwaitExprs, R)>
2520     where
2521         F: FnOnce(&mut Env<'a, TF>) -> Result<R>,
2522     {
2523         let saved_lifted_awaits = env.lifted_awaits.replace(LiftedAwaits {
2524             awaits: vec![],
2525             lift_kind: LiftedAwaitKind::LiftedFromConcurrent,
2526         });
2527         let result = f(env);
2528         let lifted_awaits = mem::replace(&mut env.lifted_awaits, saved_lifted_awaits);
2529         let result = result?;
2530         let awaits = match lifted_awaits {
2531             Some(la) => Self::process_lifted_awaits(la)?,
2532             None => Self::failwith("lifted awaits should not be None")?,
2533         };
2534         Ok((awaits, result))
2535     }
2537     fn process_lifted_awaits(mut awaits: LiftedAwaits) -> Result<LiftedAwaitExprs> {
2538         for await_ in awaits.awaits.iter() {
2539             if (await_.1).0.is_none() {
2540                 return Self::failwith("none pos in lifted awaits");
2541             }
2542         }
2543         awaits
2544             .awaits
2545             .sort_unstable_by(|a1, a2| Pos::cmp(&(a1.1).0, &(a2.1).0));
2546         Ok(awaits.awaits)
2547     }
2549     fn clear_statement_scope<F, R>(f: F, env: &mut Env<'a, TF>) -> R
2550     where
2551         F: FnOnce(&mut Env<'a, TF>) -> R,
2552     {
2553         use LiftedAwaitKind::*;
2554         match &env.lifted_awaits {
2555             Some(LiftedAwaits { lift_kind, .. }) if *lift_kind == LiftedFromStatement => {
2556                 let saved_lifted_awaits = env.lifted_awaits.take();
2557                 let result = f(env);
2558                 env.lifted_awaits = saved_lifted_awaits;
2559                 result
2560             }
2561             _ => f(env),
2562         }
2563     }
2565     fn lift_awaits_in_statement<F>(
2566         f: F,
2567         node: S<'a, T, V>,
2568         env: &mut Env<'a, TF>,
2569     ) -> Result<ast::Stmt>
2570     where
2571         F: FnOnce(&mut Env<'a, TF>) -> Result<ast::Stmt>,
2572     {
2573         Self::lift_awaits_in_statement_(f, Either::Left(node), env)
2574     }
2576     fn lift_awaits_in_statement_<F>(
2577         f: F,
2578         pos: Either<S<'a, T, V>, &Pos>,
2579         env: &mut Env<'a, TF>,
2580     ) -> Result<ast::Stmt>
2581     where
2582         F: FnOnce(&mut Env<'a, TF>) -> Result<ast::Stmt>,
2583     {
2584         use LiftedAwaitKind::*;
2585         let (lifted_awaits, result) = match env.lifted_awaits {
2586             Some(LiftedAwaits { lift_kind, .. }) if lift_kind == LiftedFromConcurrent => {
2587                 (None, f(env)?)
2588             }
2589             _ => {
2590                 let saved = env.lifted_awaits.replace(LiftedAwaits {
2591                     awaits: vec![],
2592                     lift_kind: LiftedFromStatement,
2593                 });
2594                 let result = f(env);
2595                 let lifted_awaits = mem::replace(&mut env.lifted_awaits, saved);
2596                 let result = result?;
2597                 (lifted_awaits, result)
2598             }
2599         };
2600         if let Some(lifted_awaits) = lifted_awaits {
2601             if !lifted_awaits.awaits.is_empty() {
2602                 let awaits = Self::process_lifted_awaits(lifted_awaits)?;
2603                 let pos = match pos {
2604                     Either::Left(n) => Self::p_pos(n, env),
2605                     Either::Right(p) => p.clone(),
2606                 };
2607                 return Ok(ast::Stmt::new(
2608                     pos,
2609                     ast::Stmt_::mk_awaitall(awaits, vec![result]),
2610                 ));
2611             }
2612         }
2613         Ok(result)
2614     }
2616     fn lift_await(
2617         parent_pos: Pos,
2618         expr: ast::Expr,
2619         env: &mut Env<'a, TF>,
2620         location: ExprLocation,
2621     ) -> Result<ast::Expr_> {
2622         use ExprLocation::*;
2623         match (&env.lifted_awaits, location) {
2624             (_, UsingStatement) | (_, RightOfAssignmentInUsingStatement) | (None, _) => {
2625                 Ok(E_::mk_await(expr))
2626             }
2627             (Some(_), _) => {
2628                 if location != AsStatement {
2629                     let name = env.make_tmp_var_name();
2630                     let lid = ast::Lid::new(parent_pos, name.clone());
2631                     let await_lid = ast::Lid::new(expr.0.clone(), name);
2632                     let await_ = (Some(await_lid), expr);
2633                     env.lifted_awaits.as_mut().map(|aw| aw.awaits.push(await_));
2634                     Ok(E_::mk_lvar(lid))
2635                 } else {
2636                     env.lifted_awaits
2637                         .as_mut()
2638                         .map(|aw| aw.awaits.push((None, expr)));
2639                     Ok(E_::Null)
2640                 }
2641             }
2642         }
2643     }
2645     fn p_stmt(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Stmt> {
2646         Self::clear_statement_scope(
2647             |e: &mut Env<'a, TF>| {
2648                 let docblock = Self::extract_docblock(node, e);
2649                 e.push_docblock(docblock);
2650                 let result = Self::p_stmt_(node, e);
2651                 e.pop_docblock();
2652                 result
2653             },
2654             env,
2655         )
2656     }
2658     fn p_stmt_(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Stmt> {
2659         let pos = Self::p_pos(node, env);
2660         use ast::{Stmt, Stmt_ as S_};
2661         let new = Stmt::new;
2662         match &node.children {
2663             SwitchStatement(c) => {
2664                 let p_label = |n: S<'a, T, V>, e: &mut Env<'a, TF>| -> Result<ast::Case> {
2665                     match &n.children {
2666                         CaseLabel(c) => {
2667                             Ok(ast::Case::Case(Self::p_expr(&c.expression, e)?, vec![]))
2668                         }
2669                         DefaultLabel(_) => Ok(ast::Case::Default(Self::p_pos(n, e), vec![])),
2670                         _ => Self::missing_syntax("switch label", n, e),
2671                     }
2672                 };
2673                 let p_section = |n: S<'a, T, V>, e: &mut Env<'a, TF>| -> Result<Vec<ast::Case>> {
2674                     match &n.children {
2675                         SwitchSection(c) => {
2676                             let mut blk = Self::could_map(Self::p_stmt, &c.statements, e)?;
2677                             if !c.fallthrough.is_missing() {
2678                                 blk.push(new(e.mk_none_pos(), S_::Fallthrough));
2679                             }
2680                             let mut labels = Self::could_map(p_label, &c.labels, e)?;
2681                             match labels.last_mut() {
2682                                 Some(ast::Case::Default(_, b)) => *b = blk,
2683                                 Some(ast::Case::Case(_, b)) => *b = blk,
2684                                 _ => Self::raise_parsing_error(n, e, "Malformed block result"),
2685                             }
2686                             Ok(labels)
2687                         }
2688                         _ => Self::missing_syntax("switch section", n, e),
2689                     }
2690                 };
2691                 let f = |env: &mut Env<'a, TF>| -> Result<ast::Stmt> {
2692                     Ok(new(
2693                         pos,
2694                         S_::mk_switch(
2695                             Self::p_expr(&c.expression, env)?,
2696                             itertools::concat(Self::could_map(p_section, &c.sections, env)?),
2697                         ),
2698                     ))
2699                 };
2700                 Self::lift_awaits_in_statement(f, node, env)
2701             }
2702             IfStatement(c) => {
2703                 let p_else_if =
2704                     |n: S<'a, T, V>, e: &mut Env<'a, TF>| -> Result<(ast::Expr, ast::Block)> {
2705                         match &n.children {
2706                             ElseifClause(c) => Ok((
2707                                 Self::p_expr(&c.condition, e)?,
2708                                 Self::p_block(true, &c.statement, e)?,
2709                             )),
2710                             _ => Self::missing_syntax("elseif clause", n, e),
2711                         }
2712                     };
2713                 let f = |env: &mut Env<'a, TF>| -> Result<ast::Stmt> {
2714                     let condition = Self::p_expr(&c.condition, env)?;
2715                     let statement = Self::p_block(true /* remove noop */, &c.statement, env)?;
2716                     let else_ = match &c.else_clause.children {
2717                         ElseClause(c) => Self::p_block(true, &c.statement, env)?,
2718                         Missing => vec![Self::mk_noop(env)],
2719                         _ => Self::missing_syntax("else clause", &c.else_clause, env)?,
2720                     };
2721                     let else_ifs = Self::could_map(p_else_if, &c.elseif_clauses, env)?;
2722                     let else_if = else_ifs
2723                         .into_iter()
2724                         .rev()
2725                         .fold(else_, |child, (cond, stmts)| {
2726                             vec![new(pos.clone(), S_::mk_if(cond, stmts, child))]
2727                         });
2728                     Ok(new(pos, S_::mk_if(condition, statement, else_if)))
2729                 };
2730                 Self::lift_awaits_in_statement(f, node, env)
2731             }
2732             ExpressionStatement(c) => {
2733                 let expr = &c.expression;
2734                 let f = |e: &mut Env<'a, TF>| -> Result<ast::Stmt> {
2735                     if expr.is_missing() {
2736                         Ok(new(pos, S_::Noop))
2737                     } else {
2738                         Ok(new(
2739                             pos,
2740                             S_::mk_expr(Self::p_expr_with_loc(ExprLocation::AsStatement, expr, e)?),
2741                         ))
2742                     }
2743                 };
2744                 if Self::is_simple_assignment_await_expression(expr)
2745                     || Self::is_simple_await_expression(expr)
2746                 {
2747                     f(env)
2748                 } else {
2749                     Self::lift_awaits_in_statement(f, node, env)
2750                 }
2751             }
2752             CompoundStatement(c) => Self::handle_loop_body(pos, &c.statements, env),
2753             SyntaxList(_) => Self::handle_loop_body(pos, node, env),
2754             ThrowStatement(c) => Self::lift_awaits_in_statement(
2755                 |e: &mut Env<'a, TF>| -> Result<ast::Stmt> {
2756                     Ok(new(pos, S_::mk_throw(Self::p_expr(&c.expression, e)?)))
2757                 },
2758                 node,
2759                 env,
2760             ),
2761             DoStatement(c) => Ok(new(
2762                 pos,
2763                 S_::mk_do(
2764                     Self::p_block(false /* remove noop */, &c.body, env)?,
2765                     Self::p_expr(&c.condition, env)?,
2766                 ),
2767             )),
2768             WhileStatement(c) => Ok(new(
2769                 pos,
2770                 S_::mk_while(
2771                     Self::p_expr(&c.condition, env)?,
2772                     Self::p_block(true, &c.body, env)?,
2773                 ),
2774             )),
2775             UsingStatementBlockScoped(c) => {
2776                 let f = |e: &mut Env<'a, TF>| -> Result<ast::Stmt> {
2777                     Ok(new(
2778                         pos,
2779                         S_::mk_using(ast::UsingStmt {
2780                             is_block_scoped: true,
2781                             has_await: !&c.await_keyword.is_missing(),
2782                             exprs: Self::p_exprs_with_loc(&c.expressions, e)?,
2783                             block: Self::p_block(false, &c.body, e)?,
2784                         }),
2785                     ))
2786                 };
2787                 Self::lift_awaits_in_statement(f, node, env)
2788             }
2789             UsingStatementFunctionScoped(c) => {
2790                 let f = |e: &mut Env<'a, TF>| -> Result<ast::Stmt> {
2791                     Ok(new(
2792                         pos,
2793                         S_::mk_using(ast::UsingStmt {
2794                             is_block_scoped: false,
2795                             has_await: !&c.await_keyword.is_missing(),
2796                             exprs: Self::p_exprs_with_loc(&c.expression, e)?,
2797                             block: vec![Self::mk_noop(e)],
2798                         }),
2799                     ))
2800                 };
2801                 Self::lift_awaits_in_statement(f, node, env)
2802             }
2803             ForStatement(c) => {
2804                 let f = |e: &mut Env<'a, TF>| -> Result<ast::Stmt> {
2805                     let ini = Self::p_expr_l(&c.initializer, e)?;
2806                     let ctr = Self::mp_optional(Self::p_expr, &c.control, e)?;
2807                     let eol = Self::p_expr_l(&c.end_of_loop, e)?;
2808                     let blk = Self::p_block(true, &c.body, e)?;
2809                     Ok(Stmt::new(pos, S_::mk_for(ini, ctr, eol, blk)))
2810                 };
2811                 Self::lift_awaits_in_statement(f, node, env)
2812             }
2813             ForeachStatement(c) => {
2814                 let f = |e: &mut Env<'a, TF>| -> Result<ast::Stmt> {
2815                     let col = Self::p_expr(&c.collection, e)?;
2816                     let akw = match Self::token_kind(&c.await_keyword) {
2817                         Some(TK::Await) => Some(Self::p_pos(&c.await_keyword, e)),
2818                         _ => None,
2819                     };
2820                     let value = Self::p_expr(&c.value, e)?;
2821                     let akv = match (akw, &c.key.children) {
2822                         (Some(p), Missing) => ast::AsExpr::AwaitAsV(p, value),
2823                         (None, Missing) => ast::AsExpr::AsV(value),
2824                         (Some(p), _) => ast::AsExpr::AwaitAsKv(p, Self::p_expr(&c.key, e)?, value),
2825                         (None, _) => ast::AsExpr::AsKv(Self::p_expr(&c.key, e)?, value),
2826                     };
2827                     let blk = Self::p_block(true, &c.body, e)?;
2828                     Ok(new(pos, S_::mk_foreach(col, akv, blk)))
2829                 };
2830                 Self::lift_awaits_in_statement(f, node, env)
2831             }
2832             TryStatement(c) => Ok(new(
2833                 pos,
2834                 S_::mk_try(
2835                     Self::p_block(false, &c.compound_statement, env)?,
2836                     Self::could_map(
2837                         |n: S<'a, T, V>, e| match &n.children {
2838                             CatchClause(c) => Ok(ast::Catch(
2839                                 Self::pos_name(&c.type_, e)?,
2840                                 Self::lid_from_name(&c.variable, e)?,
2841                                 Self::p_block(true, &c.body, e)?,
2842                             )),
2843                             _ => Self::missing_syntax("catch clause", n, e),
2844                         },
2845                         &c.catch_clauses,
2846                         env,
2847                     )?,
2848                     match &c.finally_clause.children {
2849                         FinallyClause(c) => Self::p_block(false, &c.body, env)?,
2850                         _ => vec![],
2851                     },
2852                 ),
2853             )),
2854             ReturnStatement(c) => {
2855                 let f = |e: &mut Env<'a, TF>| -> Result<ast::Stmt> {
2856                     let expr = match &c.expression.children {
2857                         Missing => None,
2858                         _ => Some(Self::p_expr_with_loc(
2859                             ExprLocation::RightOfReturn,
2860                             &c.expression,
2861                             e,
2862                         )?),
2863                     };
2864                     Ok(ast::Stmt::new(pos, ast::Stmt_::mk_return(expr)))
2865                 };
2866                 if Self::is_simple_await_expression(&c.expression) {
2867                     f(env)
2868                 } else {
2869                     Self::lift_awaits_in_statement(f, node, env)
2870                 }
2871             }
2872             EchoStatement(c) => {
2873                 let f = |e: &mut Env<'a, TF>| -> Result<ast::Stmt> {
2874                     let echo = match &c.keyword.children {
2875                         QualifiedName(_) | SimpleTypeSpecifier(_) | Token(_) => {
2876                             let name = Self::pos_name(&c.keyword, e)?;
2877                             ast::Expr::new(name.0.clone(), E_::mk_id(name))
2878                         }
2879                         _ => Self::missing_syntax("id", &c.keyword, e)?,
2880                     };
2881                     let args = Self::could_map(Self::p_expr, &c.expressions, e)?;
2882                     Ok(new(
2883                         pos.clone(),
2884                         S_::mk_expr(ast::Expr::new(pos, E_::mk_call(echo, vec![], args, None))),
2885                     ))
2886                 };
2887                 Self::lift_awaits_in_statement(f, node, env)
2888             }
2889             UnsetStatement(c) => {
2890                 let f = |e: &mut Env<'a, TF>| -> Result<ast::Stmt> {
2891                     let args = Self::could_map(Self::p_expr, &c.variables, e)?;
2892                     if e.parser_options.po_disable_unset_class_const {
2893                         args.iter()
2894                             .for_each(|arg| Self::check_mutate_class_const(arg, node, e))
2895                     }
2896                     let unset = match &c.keyword.children {
2897                         QualifiedName(_) | SimpleTypeSpecifier(_) | Token(_) => {
2898                             let name = Self::pos_name(&c.keyword, e)?;
2899                             ast::Expr::new(name.0.clone(), E_::mk_id(name))
2900                         }
2901                         _ => Self::missing_syntax("id", &c.keyword, e)?,
2902                     };
2903                     Ok(new(
2904                         pos.clone(),
2905                         S_::mk_expr(ast::Expr::new(pos, E_::mk_call(unset, vec![], args, None))),
2906                     ))
2907                 };
2908                 Self::lift_awaits_in_statement(f, node, env)
2909             }
2910             BreakStatement(_) => Ok(new(pos, S_::Break)),
2911             ContinueStatement(_) => Ok(new(pos, S_::Continue)),
2912             ConcurrentStatement(c) => {
2913                 let keyword_pos = Self::p_pos(&c.keyword, env);
2914                 let (lifted_awaits, Stmt(stmt_pos, stmt)) = Self::with_new_concurrent_scope(
2915                     |e: &mut Env<'a, TF>| Self::p_stmt(&c.statement, e),
2916                     env,
2917                 )?;
2918                 let stmt = match stmt {
2919                     S_::Block(stmts) => {
2920                         use ast::Bop::Eq;
2921                         use ast::Expr as E;
2922                         /* Reuse tmp vars from lifted_awaits, this is safe because there will
2923                          * always be more awaits with tmp vars than statements with assignments */
2924                         let mut tmp_vars = lifted_awaits
2925                             .iter()
2926                             .filter_map(|lifted_await| lifted_await.0.as_ref().map(|x| &x.1));
2927                         let mut body_stmts = vec![];
2928                         let mut assign_stmts = vec![];
2929                         for n in stmts.into_iter() {
2930                             if !n.is_assign_expr() {
2931                                 body_stmts.push(n);
2932                                 continue;
2933                             }
2935                             if let Some(tv) = tmp_vars.next() {
2936                                 if let Stmt(p1, S_::Expr(expr)) = n {
2937                                     if let E(p2, E_::Binop(bop)) = *expr {
2938                                         if let (Eq(op), e1, e2) = *bop {
2939                                             let tmp_n = E::mk_lvar(&e2.0, &(tv.1));
2940                                             if tmp_n.lvar_name() != e2.lvar_name() {
2941                                                 let new_n = new(
2942                                                     p1.clone(),
2943                                                     S_::mk_expr(E::new(
2944                                                         p2.clone(),
2945                                                         E_::mk_binop(
2946                                                             Eq(None),
2947                                                             tmp_n.clone(),
2948                                                             e2.clone(),
2949                                                         ),
2950                                                     )),
2951                                                 );
2952                                                 body_stmts.push(new_n);
2953                                             }
2954                                             let assign_stmt = new(
2955                                                 p1,
2956                                                 S_::mk_expr(E::new(
2957                                                     p2,
2958                                                     E_::mk_binop(Eq(op), e1, tmp_n),
2959                                                 )),
2960                                             );
2961                                             assign_stmts.push(assign_stmt);
2962                                             continue;
2963                                         }
2964                                     }
2965                                 }
2967                                 Self::failwith("Expect assignment stmt")?;
2968                             } else {
2969                                 Self::raise_parsing_error_pos(
2970                                     &stmt_pos,
2971                                     env,
2972                                     &syntax_error::statement_without_await_in_concurrent_block,
2973                                 );
2974                                 body_stmts.push(n)
2975                             }
2976                         }
2977                         body_stmts.append(&mut assign_stmts);
2978                         new(stmt_pos, S_::mk_block(body_stmts))
2979                     }
2980                     _ => Self::failwith("Unexpected concurrent stmt structure")?,
2981                 };
2982                 Ok(new(keyword_pos, S_::mk_awaitall(lifted_awaits, vec![stmt])))
2983             }
2984             MarkupSection(_) => Self::p_markup(node, env),
2985             _ => Self::missing_syntax_(
2986                 Some(new(env.mk_none_pos(), S_::Noop)),
2987                 "statement",
2988                 node,
2989                 env,
2990             ),
2991         }
2992     }
2993     fn check_mutate_class_const(e: &ast::Expr, node: S<'a, T, V>, env: &mut Env<'a, TF>) {
2994         match &e.1 {
2995             E_::ArrayGet(c) if c.1.is_some() => Self::check_mutate_class_const(&c.0, node, env),
2996             E_::ClassConst(_) => {
2997                 Self::raise_parsing_error(node, env, &syntax_error::const_mutation)
2998             }
2999             _ => {}
3000         }
3001     }
3003     fn is_hashbang(node: S<'a, T, V>, env: &Env<TF>) -> bool {
3004         let text = Self::text_str(node, env);
3005         lazy_static! {
3006             static ref RE: regex::Regex = regex::Regex::new("^#!.*\n").unwrap();
3007         }
3008         text.lines().nth(1).is_none() && // only one line
3009         RE.is_match(text)
3010     }
3012     fn p_markup(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Stmt> {
3013         match &node.children {
3014             MarkupSection(c) => {
3015                 let markup_hashbang = &c.hashbang;
3016                 let pos = Self::p_pos(node, env);
3017                 let f = pos.filename();
3018                 if (f.has_extension("hack") || f.has_extension("hackpartial"))
3019                     && !(&c.suffix.is_missing())
3020                 {
3021                     let ext = f.path().extension().unwrap(); // has_extension ensures this is a Some
3022                     Self::raise_parsing_error(
3023                         node,
3024                         env,
3025                         &syntax_error::error1060(&ext.to_str().unwrap()),
3026                     );
3027                 } else if markup_hashbang.width() > 0 && !Self::is_hashbang(markup_hashbang, env) {
3028                     Self::raise_parsing_error(node, env, &syntax_error::error1001);
3029                 }
3030                 let stmt_ = ast::Stmt_::mk_markup((pos.clone(), Self::text(markup_hashbang, env)));
3031                 Ok(ast::Stmt::new(pos, stmt_))
3032             }
3033             _ => Self::failwith("invalid node"),
3034         }
3035     }
3037     fn p_modifiers<F: Fn(R, modifier::Kind) -> R, R>(
3038         on_kind: F,
3039         mut init: R,
3040         node: S<'a, T, V>,
3041         env: &mut Env<'a, TF>,
3042     ) -> Result<(modifier::KindSet, R)> {
3043         let mut kind_set = modifier::KindSet::new();
3044         for n in node.syntax_node_to_list_skip_separator() {
3045             let token_kind = Self::token_kind(n).map_or(None, modifier::from_token_kind);
3046             match token_kind {
3047                 Some(kind) => {
3048                     kind_set.add(kind);
3049                     init = on_kind(init, kind);
3050                 }
3051                 _ => Self::missing_syntax("kind", n, env)?,
3052             }
3053         }
3054         Ok((kind_set, init))
3055     }
3057     fn p_kinds(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<modifier::KindSet> {
3058         Self::p_modifiers(|_, _| {}, (), node, env).map(|r| r.0)
3059     }
3061     fn could_map<R, F>(f: F, node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<Vec<R>>
3062     where
3063         F: Fn(S<'a, T, V>, &mut Env<'a, TF>) -> Result<R>,
3064     {
3065         Self::map_flatten_(f, node, env, vec![])
3066     }
3068     fn map_flatten_<R, F>(
3069         f: F,
3070         node: S<'a, T, V>,
3071         env: &mut Env<'a, TF>,
3072         acc: Vec<R>,
3073     ) -> Result<Vec<R>>
3074     where
3075         F: Fn(S<'a, T, V>, &mut Env<'a, TF>) -> Result<R>,
3076     {
3077         let op = |mut v: Vec<R>, a| {
3078             v.push(a);
3079             v
3080         };
3081         Self::map_fold(&f, &op, node, env, acc)
3082     }
3084     fn could_map_filter<R, F>(
3085         f: F,
3086         node: S<'a, T, V>,
3087         env: &mut Env<'a, TF>,
3088     ) -> Result<(Vec<R>, bool)>
3089     where
3090         F: Fn(S<'a, T, V>, &mut Env<'a, TF>) -> Result<Option<R>>,
3091     {
3092         Self::map_flatten_filter_(f, node, env, (vec![], false))
3093     }
3095     #[inline]
3096     fn map_flatten_filter_<R, F>(
3097         f: F,
3098         node: S<'a, T, V>,
3099         env: &mut Env<'a, TF>,
3100         acc: (Vec<R>, bool),
3101     ) -> Result<(Vec<R>, bool)>
3102     where
3103         F: Fn(S<'a, T, V>, &mut Env<'a, TF>) -> Result<Option<R>>,
3104     {
3105         let op = |mut v: (Vec<R>, bool), a| -> (Vec<R>, bool) {
3106             match a {
3107                 Option::None => (v.0, true),
3108                 Option::Some(a) => {
3109                     v.0.push(a);
3110                     v
3111                 }
3112             }
3113         };
3114         Self::map_fold(&f, &op, node, env, acc)
3115     }
3117     fn map_fold<A, R, F, O>(
3118         f: &F,
3119         op: &O,
3120         node: S<'a, T, V>,
3121         env: &mut Env<'a, TF>,
3122         mut acc: A,
3123     ) -> Result<A>
3124     where
3125         F: Fn(S<'a, T, V>, &mut Env<'a, TF>) -> Result<R>,
3126         O: Fn(A, R) -> A,
3127     {
3128         for n in node.syntax_node_to_list_skip_separator() {
3129             acc = op(acc, f(n, env)?);
3130         }
3131         Ok(acc)
3132     }
3134     fn p_visibility(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<Option<ast::Visibility>> {
3135         let first_vis =
3136             |r: Option<ast::Visibility>, kind| r.or_else(|| modifier::to_visibility(kind));
3137         Self::p_modifiers(first_vis, None, node, env).map(|r| r.1)
3138     }
3140     fn p_visibility_or(
3141         node: S<'a, T, V>,
3142         env: &mut Env<'a, TF>,
3143         default: ast::Visibility,
3144     ) -> Result<ast::Visibility> {
3145         Self::p_visibility(node, env).map(|v| v.unwrap_or(default))
3146     }
3148     fn p_visibility_last_win(
3149         node: S<'a, T, V>,
3150         env: &mut Env<'a, TF>,
3151     ) -> Result<Option<ast::Visibility>> {
3152         let last_vis = |r, kind| modifier::to_visibility(kind).or(r);
3153         Self::p_modifiers(last_vis, None, node, env).map(|r| r.1)
3154     }
3156     fn p_visibility_last_win_or(
3157         node: S<'a, T, V>,
3158         env: &mut Env<'a, TF>,
3159         default: ast::Visibility,
3160     ) -> Result<ast::Visibility> {
3161         Self::p_visibility_last_win(node, env).map(|v| v.unwrap_or(default))
3162     }
3164     fn has_soft(attrs: &[ast::UserAttribute]) -> bool {
3165         attrs.iter().any(|attr| attr.name.1 == special_attrs::SOFT)
3166     }
3168     fn soften_hint(attrs: &[ast::UserAttribute], hint: ast::Hint) -> ast::Hint {
3169         if Self::has_soft(attrs) {
3170             ast::Hint::new(hint.0.clone(), ast::Hint_::Hsoft(hint))
3171         } else {
3172             hint
3173         }
3174     }
3176     fn has_polymorphic_context(contexts: &Option<ast::Contexts>) -> bool {
3177         use ast::Hint_::{Haccess, HfunContext, Hvar};
3178         if let Some(ast::Contexts(_, ref context_hints)) = contexts {
3179             return context_hints.iter().any(|c| match *c.1 {
3180                 HfunContext(_) => true,
3181                 Haccess(ref root, _) => {
3182                     if let Hvar(_) = *root.1 {
3183                         true
3184                     } else {
3185                         false
3186                     }
3187                 }
3188                 _ => false,
3189             });
3190         } else {
3191             false
3192         }
3193     }
3195     fn rewrite_effect_polymorphism(
3196         env: &mut Env<'a, TF>,
3197         params: &mut Vec<ast::FunParam>,
3198         tparams: &mut Vec<ast::Tparam>,
3199         contexts: &Option<ast::Contexts>,
3200         where_constraints: &mut Vec<ast::WhereConstraintHint>,
3201     ) {
3202         use ast::{Hint, Hint_, ReifyKind, Variance};
3203         use Hint_::{Haccess, Happly, HfunContext, Hvar};
3205         if !Self::has_polymorphic_context(contexts) {
3206             return;
3207         }
3208         let ast::Contexts(ref _p, ref context_hints) = contexts.as_ref().unwrap();
3209         let tp = |name, v| ast::Tparam {
3210             variance: Variance::Invariant,
3211             name,
3212             parameters: vec![],
3213             constraints: v,
3214             reified: ReifyKind::Erased,
3215             user_attributes: vec![],
3216         };
3218         // For polymorphic context with form `ctx $f`
3219         // require that `(function (ts)[_]: t) $f` exists
3220         // rewrite as `(function (ts)[ctx $f]: t) $f`
3221         // add a type parameter named "Tctx$f"
3222         let rewrite_fun_ctx =
3223             |env: &mut Env<'a, TF>, tparams: &mut Vec<ast::Tparam>, hint: &mut Hint, name: &str| {
3224                 let mut invalid = |p| {
3225                     Self::raise_parsing_error_pos(
3226                         p,
3227                         env,
3228                         &syntax_error::ctx_fun_invalid_type_hint(name),
3229                     )
3230                 };
3231                 match *hint.1 {
3232                     Hint_::Hfun(ref mut hf) => {
3233                         if let Some(ast::Contexts(ref p, ref mut hl)) = &mut hf.ctxs {
3234                             if let [ref mut h] = *hl.as_mut_slice() {
3235                                 if let Hint_::Happly(ast::Id(ref pos, s), _) = &*h.1 {
3236                                     if s == "_" {
3237                                         *h.1 = Hint_::HfunContext(name.to_string());
3238                                         tparams.push(tp(
3239                                             ast::Id(h.0.clone(), "Tctx".to_string() + name),
3240                                             vec![],
3241                                         ));
3242                                     } else {
3243                                         invalid(pos);
3244                                     }
3245                                 } else {
3246                                     invalid(p);
3247                                 }
3248                             } else {
3249                                 invalid(p);
3250                             }
3251                         } else {
3252                             invalid(&hint.0);
3253                         }
3254                     }
3255                     _ => invalid(&hint.0),
3256                 }
3257             };
3259         // For polymorphic context with form `$g::C`
3260         // if $g's type is not a type parameter
3261         //   add one named "T$g" constrained by $g's type
3262         //   replace $g's type hint
3263         // let Tg denote $g's final type (must be a type parameter).
3264         // add a type parameter "T$g@C"
3265         // add a where constraint T$g@C = Tg :: C
3266         let rewrite_arg_ctx = |
3267             env: &mut Env<'a, TF>,
3268             tparams: &mut Vec<ast::Tparam>,
3269             where_constraints: &mut Vec<ast::WhereConstraintHint>,
3270             hint: &mut Hint,
3271             param_pos: &Pos,
3272             name: &str,
3273             context_pos: &Pos,
3274             cst: &ast::Id,
3275         | match *hint.1 {
3276             Happly(ast::Id(_, ref type_name), _) => {
3277                 if !tparams.iter().any(|h| h.name.1 == *type_name) {
3278                     // If the parameter is X $g, create tparam `T$g as X` and replace $g's type hint
3279                     let id = ast::Id(param_pos.clone(), "T".to_string() + name);
3280                     tparams.push(tp(
3281                         id.clone(),
3282                         vec![(ast::ConstraintKind::ConstraintAs, hint.clone())],
3283                     ));
3284                     *hint = ast::Hint::new(param_pos.clone(), Happly(id, vec![]));
3285                 };
3286                 let right = ast::Hint::new(
3287                     context_pos.clone(),
3288                     Haccess(hint.clone(), vec![cst.clone()]),
3289                 );
3290                 let left_id = ast::Id(
3291                     context_pos.clone(),
3292                     // IMPORTANT: using `::` here will not work, because
3293                     // Typing_taccess constructs its own fake type parameter
3294                     // for the Taccess with `::`. So, if the two type parameters
3295                     // are named `Tprefix` and `Tprefix::Const`, the latter
3296                     // will collide with the one generated for `Tprefix`::Const
3297                     "T".to_string() + name + "@" + &cst.1,
3298                 );
3299                 tparams.push(tp(left_id.clone(), vec![]));
3300                 let left = ast::Hint::new(context_pos.clone(), Happly(left_id, vec![]));
3301                 where_constraints.push(ast::WhereConstraintHint(
3302                     left,
3303                     ast::ConstraintKind::ConstraintEq,
3304                     right,
3305                 ))
3306             }
3307             _ => Self::raise_parsing_error_pos(
3308                 &hint.0,
3309                 env,
3310                 &syntax_error::ctx_var_invalid_type_hint(name),
3311             ),
3312         };
3314         let mut hint_by_param: std::collections::HashMap<
3315             &str,
3316             (&mut Option<ast::Hint>, &Pos, aast::IsVariadic),
3317             std::hash::BuildHasherDefault<fnv::FnvHasher>,
3318         > = fnv::FnvHashMap::default();
3319         for param in params.iter_mut() {
3320             hint_by_param.insert(
3321                 param.name.as_ref(),
3322                 (&mut param.type_hint.1, &param.pos, param.is_variadic),
3323             );
3324         }
3327         for context_hint in context_hints {
3328             match *context_hint.1 {
3329                 HfunContext(ref name) => match hint_by_param.get_mut::<str>(name) {
3330                     Some((hint_opt, param_pos, _is_variadic)) => match hint_opt {
3331                         Some(ref mut param_hint) => match *param_hint.1 {
3332                             Hint_::Hoption(ref mut h) => rewrite_fun_ctx(env, tparams, h, name),
3333                             _ => rewrite_fun_ctx(env, tparams, param_hint, name),
3334                         },
3335                         None => Self::raise_parsing_error_pos(
3336                             param_pos,
3337                             env,
3338                             &syntax_error::ctx_var_missing_type_hint(name),
3339                         ),
3340                     },
3342                     None => Self::raise_parsing_error_pos(
3343                         &context_hint.0,
3344                         env,
3345                         &syntax_error::ctx_var_invalid_parameter(name),
3346                     ),
3347                 },
3348                 Haccess(ref root, ref csts) => {
3349                     if let Hvar(ref name) = *root.1 {
3350                         match hint_by_param.get_mut::<str>(name) {
3351                             Some((hint_opt, param_pos, is_variadic)) => {
3352                                 if *is_variadic {
3353                                     Self::raise_parsing_error_pos(
3354                                         param_pos,
3355                                         env,
3356                                         &syntax_error::ctx_var_variadic(name),
3357                                     )
3358                                 } else {
3359                                     match hint_opt {
3360                                         Some(ref mut param_hint) => match *param_hint.1 {
3361                                             Hint_::Hoption(ref mut h) => rewrite_arg_ctx(
3362                                                 env,
3363                                                 tparams,
3364                                                 where_constraints,
3365                                                 h,
3366                                                 param_pos,
3367                                                 name,
3368                                                 &context_hint.0,
3369                                                 &csts[0],
3370                                             ),
3371                                             _ => rewrite_arg_ctx(
3372                                                 env,
3373                                                 tparams,
3374                                                 where_constraints,
3375                                                 param_hint,
3376                                                 param_pos,
3377                                                 name,
3378                                                 &context_hint.0,
3379                                                 &csts[0],
3380                                             ),
3381                                         },
3382                                         None => Self::raise_parsing_error_pos(
3383                                             param_pos,
3384                                             env,
3385                                             &syntax_error::ctx_var_missing_type_hint(name),
3386                                         ),
3387                                     }
3388                                 }
3389                             }
3390                             None => Self::raise_parsing_error_pos(
3391                                 &root.0,
3392                                 env,
3393                                 &syntax_error::ctx_var_invalid_parameter(name),
3394                             ),
3395                         }
3396                     }
3397                 }
3398                 _ => {}
3399             }
3400         }
3401     }
3403     fn p_fun_param_default_value(
3404         node: S<'a, T, V>,
3405         env: &mut Env<'a, TF>,
3406     ) -> Result<Option<ast::Expr>> {
3407         match &node.children {
3408             SimpleInitializer(c) => Self::mp_optional(Self::p_expr, &c.value, env),
3409             _ => Ok(None),
3410         }
3411     }
3413     fn p_param_kind(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::ParamKind> {
3414         match Self::token_kind(node) {
3415             Some(TK::Inout) => Ok(ast::ParamKind::Pinout),
3416             _ => Self::missing_syntax("param kind", node, env),
3417         }
3418     }
3420     fn param_template(node: S<'a, T, V>, env: &Env<TF>) -> ast::FunParam {
3421         let pos = Self::p_pos(node, env);
3422         ast::FunParam {
3423             annotation: pos.clone(),
3424             type_hint: ast::TypeHint((), None),
3425             is_variadic: false,
3426             pos,
3427             name: Self::text(node, env),
3428             expr: None,
3429             callconv: None,
3430             user_attributes: vec![],
3431             visibility: None,
3432         }
3433     }
3435     fn p_fun_param(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::FunParam> {
3436         match &node.children {
3437             ParameterDeclaration(ParameterDeclarationChildren {
3438                 attribute,
3439                 visibility,
3440                 call_convention,
3441                 type_,
3442                 name,
3443                 default_value,
3444             }) => {
3445                 let (is_variadic, name) = match &name.children {
3446                     DecoratedExpression(DecoratedExpressionChildren {
3447                         decorator,
3448                         expression,
3449                     }) => {
3450                         let decorator = Self::text_str(decorator, env);
3451                         match &expression.children {
3452                             DecoratedExpression(c) => {
3453                                 let nested_expression = &c.expression;
3454                                 let nested_decorator = Self::text_str(&c.decorator, env);
3455                                 (
3456                                     decorator == "..." || nested_decorator == "...",
3457                                     nested_expression,
3458                                 )
3459                             }
3460                             _ => (decorator == "...", expression),
3461                         }
3462                     }
3463                     _ => (false, name),
3464                 };
3465                 let user_attributes = Self::p_user_attributes(attribute, env)?;
3466                 let pos = Self::p_pos(name, env);
3467                 let name = Self::text(name, env);
3468                 let hint = Self::mp_optional(Self::p_hint, type_, env)?;
3469                 let hint = hint.map(|h| Self::soften_hint(&user_attributes, h));
3471                 if is_variadic && !user_attributes.is_empty() {
3472                     Self::raise_parsing_error(
3473                         node,
3474                         env,
3475                         &syntax_error::no_attributes_on_variadic_parameter,
3476                     );
3477                 }
3478                 Ok(ast::FunParam {
3479                     annotation: pos.clone(),
3480                     type_hint: ast::TypeHint((), hint),
3481                     user_attributes,
3482                     is_variadic,
3483                     pos,
3484                     name,
3485                     expr: Self::p_fun_param_default_value(default_value, env)?,
3486                     callconv: Self::mp_optional(Self::p_param_kind, call_convention, env)?,
3487                     /* implicit field via constructor parameter.
3488                      * This is always None except for constructors and the modifier
3489                      * can be only Public or Protected or Private.
3490                      */
3491                     visibility: Self::p_visibility(visibility, env)?,
3492                 })
3493             }
3494             VariadicParameter(_) => {
3495                 let mut param = Self::param_template(node, env);
3496                 param.is_variadic = true;
3497                 Ok(param)
3498             }
3499             Token(_) if Self::text_str(node, env) == "..." => {
3500                 let mut param = Self::param_template(node, env);
3501                 param.is_variadic = true;
3502                 Ok(param)
3503             }
3504             _ => Self::missing_syntax("function parameter", node, env),
3505         }
3506     }
3508     fn p_tconstraint_ty(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Hint> {
3509         match &node.children {
3510             TypeConstraint(c) => Self::p_hint(&c.type_, env),
3511             _ => Self::missing_syntax("type constraint", node, env),
3512         }
3513     }
3515     fn p_tconstraint(
3516         node: S<'a, T, V>,
3517         env: &mut Env<'a, TF>,
3518     ) -> Result<(ast::ConstraintKind, ast::Hint)> {
3519         match &node.children {
3520             TypeConstraint(c) => Ok((
3521                 match Self::token_kind(&c.keyword) {
3522                     Some(TK::As) => ast::ConstraintKind::ConstraintAs,
3523                     Some(TK::Super) => ast::ConstraintKind::ConstraintSuper,
3524                     Some(TK::Equal) => ast::ConstraintKind::ConstraintEq,
3525                     _ => Self::missing_syntax("constraint operator", &c.keyword, env)?,
3526                 },
3527                 Self::p_hint(&c.type_, env)?,
3528             )),
3529             _ => Self::missing_syntax("type constraint", node, env),
3530         }
3531     }
3533     fn p_tparam(is_class: bool, node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Tparam> {
3534         match &node.children {
3535             TypeParameter(TypeParameterChildren {
3536                 attribute_spec,
3537                 reified,
3538                 variance,
3539                 name,
3540                 param_params,
3541                 constraints,
3542             }) => {
3543                 let user_attributes = Self::p_user_attributes(attribute_spec, env)?;
3544                 let is_reified = !reified.is_missing();
3545                 if is_class && is_reified {
3546                     let type_name = Self::text(name, env);
3547                     env.cls_reified_generics().insert(type_name);
3548                 }
3549                 let variance = match Self::token_kind(variance) {
3550                     Some(TK::Plus) => ast::Variance::Covariant,
3551                     Some(TK::Minus) => ast::Variance::Contravariant,
3552                     _ => ast::Variance::Invariant,
3553                 };
3554                 if is_reified && variance != ast::Variance::Invariant {
3555                     Self::raise_parsing_error(
3556                         node,
3557                         env,
3558                         &syntax_error::non_invariant_reified_generic,
3559                     );
3560                 }
3561                 let reified = match (is_reified, Self::has_soft(&user_attributes)) {
3562                     (true, true) => ast::ReifyKind::SoftReified,
3563                     (true, false) => ast::ReifyKind::Reified,
3564                     _ => ast::ReifyKind::Erased,
3565                 };
3566                 let parameters = Self::p_tparam_l(is_class, param_params, env)?;
3567                 Ok(ast::Tparam {
3568                     variance,
3569                     name: Self::pos_name(name, env)?,
3570                     parameters,
3571                     constraints: Self::could_map(Self::p_tconstraint, constraints, env)?,
3572                     reified,
3573                     user_attributes,
3574                 })
3575             }
3576             _ => Self::missing_syntax("type parameter", node, env),
3577         }
3578     }
3580     fn p_tparam_l(
3581         is_class: bool,
3582         node: S<'a, T, V>,
3583         env: &mut Env<'a, TF>,
3584     ) -> Result<Vec<ast::Tparam>> {
3585         match &node.children {
3586             Missing => Ok(vec![]),
3587             TypeParameters(c) => {
3588                 Self::could_map(|n, e| Self::p_tparam(is_class, n, e), &c.parameters, env)
3589             }
3590             _ => Self::missing_syntax("type parameter", node, env),
3591         }
3592     }
3594     fn p_contexts(
3595         node: S<'a, T, V>,
3596         env: &mut Env<'a, TF>,
3597     ) -> Result<(Option<ast::Contexts>, Option<ast::Contexts>)> {
3598         match &node.children {
3599             Missing => Ok((None, None)),
3600             Contexts(c) => {
3601                 let hints = Self::could_map(&Self::p_hint, &c.types, env)?;
3602                 let pos = Self::p_pos(node, env);
3603                 let ctxs = ast::Contexts(pos, hints);
3604                 let unsafe_ctxs = ctxs.clone();
3605                 Ok((Some(ctxs), Some(unsafe_ctxs)))
3606             }
3607             _ => Self::missing_syntax("contexts", node, env),
3608         }
3609     }
3611     fn p_context_list_to_intersection(
3612         ctx_list: S<'a, T, V>,
3613         env: &mut Env<'a, TF>,
3614     ) -> Result<Option<ast::Hint>> {
3615         Ok(Self::mp_optional(Self::p_contexts, &ctx_list, env)?
3616             .and_then(|t| t.0)
3617             .map(|t| ast::Hint::new(t.0, ast::Hint_::Hintersection(t.1))))
3618     }
3620     fn p_fun_hdr(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<FunHdr> {
3621         match &node.children {
3622             FunctionDeclarationHeader(FunctionDeclarationHeaderChildren {
3623                 modifiers,
3624                 name,
3625                 where_clause,
3626                 type_parameter_list,
3627                 parameter_list,
3628                 type_,
3629                 contexts,
3630                 ..
3631             }) => {
3632                 if name.value.is_missing() {
3633                     Self::raise_parsing_error(name, env, &syntax_error::empty_method_name);
3634                 }
3635                 let kinds = Self::p_kinds(modifiers, env)?;
3636                 let has_async = kinds.has(modifier::ASYNC);
3637                 let mut type_parameters = Self::p_tparam_l(false, type_parameter_list, env)?;
3638                 let mut parameters = Self::could_map(Self::p_fun_param, parameter_list, env)?;
3639                 let (contexts, unsafe_contexts) = Self::p_contexts(contexts, env)?;
3640                 let mut constrs = Self::p_where_constraint(false, node, where_clause, env)?;
3641                 Self::rewrite_effect_polymorphism(
3642                     env,
3643                     &mut parameters,
3644                     &mut type_parameters,
3645                     &contexts,
3646                     &mut constrs,
3647                 );
3648                 let return_type = Self::mp_optional(Self::p_hint, type_, env)?;
3649                 let suspension_kind = Self::mk_suspension_kind_(has_async);
3650                 let name = Self::pos_name(name, env)?;
3651                 Ok(FunHdr {
3652                     suspension_kind,
3653                     name,
3654                     constrs,
3655                     type_parameters,
3656                     parameters,
3657                     contexts,
3658                     unsafe_contexts,
3659                     return_type,
3660                 })
3661             }
3662             LambdaSignature(LambdaSignatureChildren {
3663                 parameters,
3664                 contexts,
3665                 type_,
3666                 ..
3667             }) => {
3668                 let mut header = FunHdr::make_empty(env);
3669                 header.parameters = Self::could_map(Self::p_fun_param, parameters, env)?;
3670                 let (contexts, unsafe_contexts) = Self::p_contexts(contexts, env)?;
3671                 header.contexts = contexts;
3672                 header.unsafe_contexts = unsafe_contexts;
3673                 header.return_type = Self::mp_optional(Self::p_hint, type_, env)?;
3674                 Ok(header)
3675             }
3676             Token(_) => Ok(FunHdr::make_empty(env)),
3677             _ => Self::missing_syntax("function header", node, env),
3678         }
3679     }
3681     fn determine_variadicity(params: &[ast::FunParam]) -> ast::FunVariadicity {
3682         use aast::FunVariadicity::*;
3683         if let Some(x) = params.last() {
3684             match (x.is_variadic, &x.name) {
3685                 (false, _) => FVnonVariadic,
3686                 (true, name) if name == "..." => FVellipsis(x.pos.clone()),
3687                 (true, _) => FVvariadicArg(x.clone()),
3688             }
3689         } else {
3690             FVnonVariadic
3691         }
3692     }
3694     fn p_fun_pos(node: S<'a, T, V>, env: &Env<TF>) -> Pos {
3695         let get_pos = |n: S<'a, T, V>, p: Pos| -> Pos {
3696             if let FunctionDeclarationHeader(c1) = &n.children {
3697                 if !c1.keyword.is_missing() {
3698                     return Pos::btw_nocheck(Self::p_pos(&c1.keyword, env), p);
3699                 }
3700             }
3701             p
3702         };
3703         let p = Self::p_pos(node, env);
3704         match &node.children {
3705             FunctionDeclaration(c) if env.codegen() => get_pos(&c.declaration_header, p),
3706             MethodishDeclaration(c) if env.codegen() => get_pos(&c.function_decl_header, p),
3707             _ => p,
3708         }
3709     }
3711     fn p_block(remove_noop: bool, node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Block> {
3712         let ast::Stmt(p, stmt_) = Self::p_stmt(node, env)?;
3713         if let ast::Stmt_::Block(blk) = stmt_ {
3714             if remove_noop && blk.len() == 1 && blk[0].1.is_noop() {
3715                 return Ok(vec![]);
3716             }
3717             return Ok(blk);
3718         } else {
3719             Ok(vec![ast::Stmt(p, stmt_)])
3720         }
3721     }
3723     fn mk_noop(env: &Env<TF>) -> ast::Stmt {
3724         ast::Stmt::noop(env.mk_none_pos())
3725     }
3727     fn p_function_body(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Block> {
3728         let mk_noop_result = |e: &Env<TF>| Ok(vec![Self::mk_noop(e)]);
3729         let f = |e: &mut Env<'a, TF>| -> Result<ast::Block> {
3730             match &node.children {
3731                 Missing => Ok(vec![]),
3732                 CompoundStatement(c) => {
3733                     let compound_statements = &c.statements.children;
3734                     let compound_right_brace = &c.right_brace.children;
3735                     match (compound_statements, compound_right_brace) {
3736                         (Missing, Token(_)) => mk_noop_result(e),
3737                         (SyntaxList(t), _) if t.len() == 1 && t[0].is_yield() => {
3738                             e.saw_yield = true;
3739                             mk_noop_result(e)
3740                         }
3741                         _ => {
3742                             if !e.top_level_statements
3743                                 && ((e.file_mode() == file_info::Mode::Mdecl && !e.codegen())
3744                                     || e.quick_mode)
3745                             {
3746                                 mk_noop_result(e)
3747                             } else {
3748                                 Self::p_block(false /*remove noop*/, node, e)
3749                             }
3750                         }
3751                     }
3752                 }
3753                 _ => {
3754                     let f = |e: &mut Env<'a, TF>| {
3755                         let expr = Self::p_expr(node, e)?;
3756                         Ok(ast::Stmt::new(
3757                             expr.0.clone(),
3758                             ast::Stmt_::mk_return(Some(expr)),
3759                         ))
3760                     };
3761                     if Self::is_simple_await_expression(node) {
3762                         Ok(vec![f(e)?])
3763                     } else {
3764                         Ok(vec![Self::lift_awaits_in_statement(f, node, e)?])
3765                     }
3766                 }
3767             }
3768         };
3769         Self::with_new_nonconcurrent_scope(f, env)
3770     }
3772     fn mk_suspension_kind(async_keyword: S<'a, T, V>) -> SuspensionKind {
3773         Self::mk_suspension_kind_(!async_keyword.is_missing())
3774     }
3776     fn mk_suspension_kind_(has_async: bool) -> SuspensionKind {
3777         if has_async {
3778             SuspensionKind::SKAsync
3779         } else {
3780             SuspensionKind::SKSync
3781         }
3782     }
3784     fn mk_fun_kind(suspension_kind: SuspensionKind, yield_: bool) -> ast::FunKind {
3785         use ast::FunKind::*;
3786         use SuspensionKind::*;
3787         match (suspension_kind, yield_) {
3788             (SKSync, true) => FGenerator,
3789             (SKAsync, true) => FAsyncGenerator,
3790             (SKSync, false) => FSync,
3791             (SKAsync, false) => FAsync,
3792         }
3793     }
3795     fn process_attribute_constructor_call(
3796         node: S<'a, T, V>,
3797         constructor_call_argument_list: S<'a, T, V>,
3798         constructor_call_type: S<'a, T, V>,
3799         env: &mut Env<'a, TF>,
3800     ) -> Result<ast::UserAttribute> {
3801         let name = Self::pos_name(constructor_call_type, env)?;
3802         if name.1.eq_ignore_ascii_case("__reified")
3803             || name.1.eq_ignore_ascii_case("__hasreifiedparent")
3804         {
3805             Self::raise_parsing_error(node, env, &syntax_error::reified_attribute);
3806         } else if name.1.eq_ignore_ascii_case(special_attrs::SOFT)
3807             && constructor_call_argument_list
3808                 .syntax_node_to_list_skip_separator()
3809                 .count()
3810                 > 0
3811         {
3812             Self::raise_parsing_error(node, env, &syntax_error::soft_no_arguments);
3813         }
3814         let params = Self::could_map(
3815             |n: S<'a, T, V>, e: &mut Env<'a, TF>| -> Result<ast::Expr> {
3816                 Self::is_valid_attribute_arg(n, e);
3817                 Self::p_expr(n, e)
3818             },
3819             constructor_call_argument_list,
3820             env,
3821         )?;
3822         Ok(ast::UserAttribute { name, params })
3823     }
3825     // Arguments to attributes must be literals (int, string, etc), collections
3826     // (eg vec, dict, keyset, etc), Foo::class strings, shapes, string
3827     // concatenations, or tuples.
3828     fn is_valid_attribute_arg(node: S<'a, T, V>, env: &mut Env<'a, TF>) {
3829         let mut is_valid_list = |nodes: S<'a, T, V>| {
3830             let _ = Self::could_map(
3831                 |n, e| {
3832                     Self::is_valid_attribute_arg(n, e);
3833                     Ok(())
3834                 },
3835                 nodes,
3836                 env,
3837             );
3838             ()
3839         };
3840         match &node.children {
3841             ParenthesizedExpression(c) => Self::is_valid_attribute_arg(&c.expression, env),
3842             // Normal literals (string, int, etc)
3843             LiteralExpression(_) => {}
3844             // ::class strings
3845             ScopeResolutionExpression(c) => {
3846                 if let Some(TK::Class) = Self::token_kind(&c.name) {
3847                 } else {
3848                     Self::raise_parsing_error(
3849                         node,
3850                         env,
3851                         &syntax_error::expression_as_attribute_arguments,
3852                     );
3853                 }
3854             }
3855             // Negations
3856             PrefixUnaryExpression(c) => {
3857                 Self::is_valid_attribute_arg(&c.operand, env);
3858                 match Self::token_kind(&c.operator) {
3859                     Some(TK::Minus) => {}
3860                     Some(TK::Plus) => {}
3861                     _ => Self::raise_parsing_error(
3862                         node,
3863                         env,
3864                         &syntax_error::expression_as_attribute_arguments,
3865                     ),
3866                 }
3867             }
3868             // String concatenation
3869             BinaryExpression(c) => {
3870                 if let Some(TK::Dot) = Self::token_kind(&c.operator) {
3871                     Self::is_valid_attribute_arg(&c.left_operand, env);
3872                     Self::is_valid_attribute_arg(&c.right_operand, env);
3873                 } else {
3874                     Self::raise_parsing_error(
3875                         node,
3876                         env,
3877                         &syntax_error::expression_as_attribute_arguments,
3878                     );
3879                 }
3880             }
3881             // Top-level Collections
3882             DarrayIntrinsicExpression(c) => is_valid_list(&c.members),
3883             DictionaryIntrinsicExpression(c) => is_valid_list(&c.members),
3884             KeysetIntrinsicExpression(c) => is_valid_list(&c.members),
3885             VarrayIntrinsicExpression(c) => is_valid_list(&c.members),
3886             VectorIntrinsicExpression(c) => is_valid_list(&c.members),
3887             ShapeExpression(c) => is_valid_list(&c.fields),
3888             TupleExpression(c) => is_valid_list(&c.items),
3889             // Collection Internals
3890             FieldInitializer(c) => {
3891                 Self::is_valid_attribute_arg(&c.name, env);
3892                 Self::is_valid_attribute_arg(&c.value, env);
3893             }
3894             ElementInitializer(c) => {
3895                 Self::is_valid_attribute_arg(&c.key, env);
3896                 Self::is_valid_attribute_arg(&c.value, env);
3897             }
3898             // Everything else is not allowed
3899             _ => Self::raise_parsing_error(
3900                 node,
3901                 env,
3902                 &syntax_error::expression_as_attribute_arguments,
3903             ),
3904         }
3905     }
3907     fn p_user_attribute(
3908         node: S<'a, T, V>,
3909         env: &mut Env<'a, TF>,
3910     ) -> Result<Vec<ast::UserAttribute>> {
3911         let p_attr = |n: S<'a, T, V>, e: &mut Env<'a, TF>| -> Result<ast::UserAttribute> {
3912             match &n.children {
3913                 ConstructorCall(c) => {
3914                     Self::process_attribute_constructor_call(node, &c.argument_list, &c.type_, e)
3915                 }
3916                 _ => Self::missing_syntax("attribute", node, e),
3917             }
3918         };
3919         match &node.children {
3920             FileAttributeSpecification(c) => Self::could_map(p_attr, &c.attributes, env),
3921             OldAttributeSpecification(c) => Self::could_map(p_attr, &c.attributes, env),
3922             AttributeSpecification(c) => Self::could_map(
3923                 |n: S<'a, T, V>, e: &mut Env<'a, TF>| -> Result<ast::UserAttribute> {
3924                     match &n.children {
3925                         Attribute(c) => p_attr(&c.attribute_name, e),
3926                         _ => Self::missing_syntax("attribute", node, e),
3927                     }
3928                 },
3929                 &c.attributes,
3930                 env,
3931             ),
3932             _ => Self::missing_syntax("attribute specification", node, env),
3933         }
3934     }
3936     fn p_user_attributes(
3937         node: S<'a, T, V>,
3938         env: &mut Env<'a, TF>,
3939     ) -> Result<Vec<ast::UserAttribute>> {
3940         Self::map_fold(
3941             &Self::p_user_attribute,
3942             &|mut acc: Vec<ast::UserAttribute>, mut x: Vec<ast::UserAttribute>| {
3943                 acc.append(&mut x);
3944                 acc
3945             },
3946             node,
3947             env,
3948             vec![],
3949         )
3950     }
3952     fn mp_yielding<F, R>(p: F, node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<(R, bool)>
3953     where
3954         F: FnOnce(S<'a, T, V>, &mut Env<'a, TF>) -> Result<R>,
3955     {
3956         let outer_saw_yield = env.saw_yield;
3957         env.saw_yield = false;
3958         let r = p(node, env);
3959         let saw_yield = env.saw_yield;
3960         env.saw_yield = outer_saw_yield;
3961         Ok((r?, saw_yield))
3962     }
3964     fn mk_empty_ns_env(env: &Env<TF>) -> RcOc<NamespaceEnv> {
3965         RcOc::clone(&env.empty_ns_env)
3966     }
3968     fn extract_docblock(node: S<'a, T, V>, env: &Env<TF>) -> Option<DocComment> {
3969         #[derive(Copy, Clone, Eq, PartialEq)]
3970         enum ScanState {
3971             DocComment,
3972             EmbeddedCmt,
3973             EndDoc,
3974             EndEmbedded,
3975             Free,
3976             LineCmt,
3977             MaybeDoc,
3978             MaybeDoc2,
3979             SawSlash,
3980         }
3981         use ScanState::*;
3982         // `parse` mixes loop and recursion to use less stack space.
3983         fn parse(
3984             str: &str,
3985             start: usize,
3986             state: ScanState,
3987             idx: usize,
3988         ) -> Option<(usize, usize, String)> {
3989             let is_whitespace = |c| c == ' ' || c == '\t' || c == '\n' || c == '\r';
3990             let mut s = (start, state, idx);
3991             let chars = str.as_bytes();
3992             loop {
3993                 if s.2 == str.len() {
3994                     break None;
3995                 }
3997                 let next = s.2 + 1;
3998                 match (s.1, chars[s.2] as char) {
3999                     (LineCmt, '\n') => s = (next, Free, next),
4000                     (EndEmbedded, '/') => s = (next, Free, next),
4001                     (EndDoc, '/') => {
4002                         let r = parse(str, next, Free, next);
4003                         match r {
4004                             d @ Some(_) => break d,
4005                             None => break Some((s.0, s.2 + 1, String::from(&str[s.0..s.2 + 1]))),
4006                         }
4007                     }
4008                     /* PHP has line comments delimited by a # */
4009                     (Free, '#') => s = (next, LineCmt, next),
4010                     /* All other comment delimiters start with a / */
4011                     (Free, '/') => s = (s.2, SawSlash, next),
4012                     /* After a / in trivia, we must see either another / or a * */
4013                     (SawSlash, '/') => s = (next, LineCmt, next),
4014                     (SawSlash, '*') => s = (s.0, MaybeDoc, next),
4015                     (MaybeDoc, '*') => s = (s.0, MaybeDoc2, next),
4016                     (MaybeDoc, _) => s = (s.0, EmbeddedCmt, next),
4017                     (MaybeDoc2, '/') => s = (next, Free, next),
4018                     /* Doc comments have a space after the second star */
4019                     (MaybeDoc2, c) if is_whitespace(c) => s = (s.0, DocComment, s.2),
4020                     (MaybeDoc2, _) => s = (s.0, EmbeddedCmt, next),
4021                     (DocComment, '*') => s = (s.0, EndDoc, next),
4022                     (DocComment, _) => s = (s.0, DocComment, next),
4023                     (EndDoc, _) => s = (s.0, DocComment, next),
4024                     /* A * without a / does not end an embedded comment */
4025                     (EmbeddedCmt, '*') => s = (s.0, EndEmbedded, next),
4026                     (EndEmbedded, '*') => s = (s.0, EndEmbedded, next),
4027                     (EndEmbedded, _) => s = (s.0, EmbeddedCmt, next),
4028                     /* Whitespace skips everywhere else */
4029                     (_, c) if is_whitespace(c) => s = (s.0, s.1, next),
4030                     /* When scanning comments, anything else is accepted */
4031                     (LineCmt, _) => s = (s.0, s.1, next),
4032                     (EmbeddedCmt, _) => s = (s.0, s.1, next),
4033                     _ => break None,
4034                 }
4035             }
4036         }
4037         let str = node.leading_text(env.indexed_source_text.source_text());
4038         parse(str, 0, Free, 0).map(|(start, end, txt)| {
4039             let anchor = node.leading_start_offset();
4040             let pos = env
4041                 .indexed_source_text
4042                 .relative_pos(anchor + start, anchor + end);
4043             let ps = (pos, txt);
4044             oxidized::doc_comment::DocComment::new(ps)
4045         })
4046     }
4048     fn p_xhp_child(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::XhpChild> {
4049         use ast::XhpChild::*;
4050         use ast::XhpChildOp::*;
4051         match &node.children {
4052             Token(_) => Self::pos_name(node, env).map(ChildName),
4053             PostfixUnaryExpression(c) => {
4054                 let operand = Self::p_xhp_child(&c.operand, env)?;
4055                 let operator = match Self::token_kind(&c.operator) {
4056                     Some(TK::Question) => ChildQuestion,
4057                     Some(TK::Plus) => ChildPlus,
4058                     Some(TK::Star) => ChildStar,
4059                     _ => Self::missing_syntax("xhp children operator", node, env)?,
4060                 };
4061                 Ok(ChildUnary(Box::new(operand), operator))
4062             }
4063             BinaryExpression(c) => {
4064                 let left = Self::p_xhp_child(&c.left_operand, env)?;
4065                 let right = Self::p_xhp_child(&c.right_operand, env)?;
4066                 Ok(ChildBinary(Box::new(left), Box::new(right)))
4067             }
4068             XHPChildrenParenthesizedList(c) => {
4069                 let children: std::result::Result<Vec<_>, _> = c
4070                     .xhp_children
4071                     .syntax_node_to_list_skip_separator()
4072                     .map(|c| Self::p_xhp_child(c, env))
4073                     .collect();
4074                 Ok(ChildList(children?))
4075             }
4076             _ => Self::missing_syntax("xhp children", node, env),
4077         }
4078     }
4080     fn p_class_elt_(
4081         class: &mut ast::Class_,
4082         node: S<'a, T, V>,
4083         env: &mut Env<'a, TF>,
4084     ) -> Result<()> {
4085         use ast::Visibility;
4086         let doc_comment_opt = Self::extract_docblock(node, env);
4087         let has_fun_header = |m: &MethodishDeclarationChildren<T, V>| {
4088             matches!(
4089                 m.function_decl_header.children,
4090                 FunctionDeclarationHeader(_)
4091             )
4092         };
4093         let p_method_vis = |
4094             node: S<'a, T, V>,
4095             name_pos: &Pos,
4096             env: &mut Env<'a, TF>,
4097         | -> Result<Visibility> {
4098             match Self::p_visibility_last_win(node, env)? {
4099                 None => {
4100                     Self::raise_hh_error(env, Naming::method_needs_visibility(name_pos.clone()));
4101                     Ok(Visibility::Public)
4102                 }
4103                 Some(v) => Ok(v),
4104             }
4105         };
4106         match &node.children {
4107             ConstDeclaration(c) => {
4108                 // TODO: make wrap `type_` `doc_comment` by `Rc` in ClassConst to avoid clone
4109                 let type_ = Self::mp_optional(Self::p_hint, &c.type_specifier, env)?;
4110                 // using map_fold can save one Vec allocation, but ocaml's behavior is that
4111                 // if anything throw, it will discard all lowered elements. So adding to class
4112                 // must be at the last.
4113                 let mut class_consts = Self::could_map(
4114                     |n: S<'a, T, V>, e: &mut Env<'a, TF>| -> Result<ast::ClassConst> {
4115                         match &n.children {
4116                             ConstantDeclarator(c) => {
4117                                 let id = Self::pos_name(&c.name, e)?;
4118                                 let expr = if n.is_abstract() {
4119                                     None
4120                                 } else {
4121                                     Self::mp_optional(
4122                                         Self::p_simple_initializer,
4123                                         &c.initializer,
4124                                         e,
4125                                     )?
4126                                 };
4127                                 Ok(ast::ClassConst {
4128                                     type_: type_.clone(),
4129                                     id,
4130                                     expr,
4131                                     doc_comment: doc_comment_opt.clone(),
4132                                 })
4133                             }
4134                             _ => Self::missing_syntax("constant declarator", n, e),
4135                         }
4136                     },
4137                     &c.declarators,
4138                     env,
4139                 )?;
4140                 Ok(class.consts.append(&mut class_consts))
4141             }
4142             TypeConstDeclaration(c) => {
4143                 if !c.type_parameters.is_missing() {
4144                     Self::raise_parsing_error(node, env, &syntax_error::tparams_in_tconst);
4145                 }
4146                 let user_attributes = Self::p_user_attributes(&c.attribute_spec, env)?;
4147                 let type__ = Self::mp_optional(Self::p_hint, &c.type_specifier, env)?
4148                     .map(|hint| Self::soften_hint(&user_attributes, hint));
4149                 let kinds = Self::p_kinds(&c.modifiers, env)?;
4150                 let name = Self::pos_name(&c.name, env)?;
4151                 let constraint =
4152                     Self::mp_optional(Self::p_tconstraint_ty, &c.type_constraint, env)?;
4153                 let span = Self::p_pos(node, env);
4154                 let has_abstract = kinds.has(modifier::ABSTRACT);
4155                 let (type_, abstract_kind) = match (has_abstract, &constraint, &type__) {
4156                     (false, _, None) => {
4157                         Self::raise_hh_error(
4158                             env,
4159                             NastCheck::not_abstract_without_typeconst(name.0.clone()),
4160                         );
4161                         (constraint.clone(), ast::TypeconstAbstractKind::TCConcrete)
4162                     }
4163                     (false, None, Some(_)) => (type__, ast::TypeconstAbstractKind::TCConcrete),
4164                     (false, Some(_), Some(_)) => {
4165                         (type__, ast::TypeconstAbstractKind::TCPartiallyAbstract)
4166                     }
4167                     (true, _, None) => (
4168                         type__.clone(),
4169                         ast::TypeconstAbstractKind::TCAbstract(type__),
4170                     ),
4171                     (true, _, Some(_)) => (None, ast::TypeconstAbstractKind::TCAbstract(type__)),
4172                 };
4173                 Ok(class.typeconsts.push(ast::ClassTypeconst {
4174                     abstract_: abstract_kind,
4175                     name,
4176                     constraint,
4177                     type_,
4178                     user_attributes,
4179                     span,
4180                     doc_comment: doc_comment_opt,
4181                     is_ctx: false,
4182                 }))
4183             }
4184             ContextConstDeclaration(c) => {
4185                 if !c.type_parameters.is_missing() {
4186                     Self::raise_parsing_error(node, env, &syntax_error::tparams_in_tconst);
4187                 }
4188                 let name = Self::pos_name(&c.name, env)?;
4189                 let context = Self::p_context_list_to_intersection(&c.ctx_list, env)?;
4190                 let constraints = Self::could_map(
4191                     |cstrnt, e: &mut Env<'a, TF>| match &cstrnt.children {
4192                         Missing => Ok(None),
4193                         TypeConstraint(c) => Self::p_context_list_to_intersection(&c.type_, e),
4194                         _ => Self::missing_syntax("const ctx constraint", node, e),
4195                     },
4196                     &c.constraint,
4197                     env,
4198                 )?;
4200                 // TODO(coeffects)
4201                 // so it turns out that type constant and context constant
4202                 // constraints super don't jive.
4203                 // 1. type constants allow only 1 constraint
4204                 // 2. type constants don't record the *type* of the constraint
4205                 // these both need to be fixed or we need to lower to something
4206                 // else in the meantime, just grab the first one if it exists
4207                 let constraint = constraints.into_iter().next().flatten();
4209                 let span = Self::p_pos(node, env);
4210                 let kinds = Self::p_kinds(&c.modifiers, env)?;
4211                 let has_abstract = kinds.has(modifier::ABSTRACT);
4212                 let (context, abstract_kind) = match (has_abstract, &constraint, &context) {
4213                     (false, _, None) => {
4214                         Self::raise_hh_error(
4215                             env,
4216                             NastCheck::not_abstract_without_typeconst(name.0.clone()),
4217                         );
4218                         (constraint.clone(), ast::TypeconstAbstractKind::TCConcrete)
4219                     }
4220                     (false, None, Some(_)) => (context, ast::TypeconstAbstractKind::TCConcrete),
4221                     (false, Some(_), Some(_)) => {
4222                         let errstr = "No partially abstract context constants";
4223                         Self::raise_parsing_error(node, env, errstr);
4224                         return Err(Error::Failwith(errstr.to_string()));
4225                     }
4226                     (true, _, None) => (
4227                         context.clone(),
4228                         ast::TypeconstAbstractKind::TCAbstract(context),
4229                     ),
4230                     (true, _, Some(_)) => (None, ast::TypeconstAbstractKind::TCAbstract(context)),
4231                 };
4232                 Ok(class.typeconsts.push(ast::ClassTypeconst {
4233                     abstract_: abstract_kind,
4234                     name,
4235                     constraint,
4236                     type_: context,
4237                     user_attributes: vec![],
4238                     span,
4239                     doc_comment: doc_comment_opt,
4240                     is_ctx: true,
4241                 }))
4242             }
4243             PropertyDeclaration(c) => {
4244                 let user_attributes = Self::p_user_attributes(&c.attribute_spec, env)?;
4245                 let type_ = Self::mp_optional(Self::p_hint, &c.type_, env)?
4246                     .map(|t| Self::soften_hint(&user_attributes, t));
4247                 let kinds = Self::p_kinds(&c.modifiers, env)?;
4248                 let vis = Self::p_visibility_last_win_or(&c.modifiers, env, Visibility::Public)?;
4249                 let doc_comment = if env.quick_mode {
4250                     None
4251                 } else {
4252                     doc_comment_opt
4253                 };
4254                 let name_exprs = Self::could_map(
4255                     |n, e| -> Result<(Pos, ast::Sid, Option<ast::Expr>)> {
4256                         match &n.children {
4257                             PropertyDeclarator(c) => {
4258                                 let name = Self::pos_name_(&c.name, e, Some('$'))?;
4259                                 let pos = Self::p_pos(n, e);
4260                                 let expr = Self::mp_optional(
4261                                     Self::p_simple_initializer,
4262                                     &c.initializer,
4263                                     e,
4264                                 )?;
4265                                 Ok((pos, name, expr))
4266                             }
4267                             _ => Self::missing_syntax("property declarator", n, e),
4268                         }
4269                     },
4270                     &c.declarators,
4271                     env,
4272                 )?;
4274                 let mut i = 0;
4275                 for name_expr in name_exprs.into_iter() {
4276                     class.vars.push(ast::ClassVar {
4277                         final_: kinds.has(modifier::FINAL),
4278                         xhp_attr: None,
4279                         abstract_: kinds.has(modifier::ABSTRACT),
4280                         visibility: vis,
4281                         type_: ast::TypeHint((), type_.clone()),
4282                         id: name_expr.1,
4283                         expr: name_expr.2,
4284                         user_attributes: user_attributes.clone(),
4285                         doc_comment: if i == 0 { doc_comment.clone() } else { None },
4286                         is_promoted_variadic: false,
4287                         is_static: kinds.has(modifier::STATIC),
4288                         span: name_expr.0,
4289                     });
4290                     i += 1;
4291                 }
4292                 Ok(())
4293             }
4294             MethodishDeclaration(c) if has_fun_header(c) => {
4295                 let classvar_init = |param: &ast::FunParam| -> (ast::Stmt, ast::ClassVar) {
4296                     let cvname = Self::drop_prefix(&param.name, '$');
4297                     let p = &param.pos;
4298                     let span = match &param.expr {
4299                         Some(ast::Expr(pos_end, _)) => {
4300                             Pos::btw(p, pos_end).unwrap_or_else(|_| p.clone())
4301                         }
4302                         _ => p.clone(),
4303                     };
4304                     let e = |expr_: ast::Expr_| -> ast::Expr { ast::Expr::new(p.clone(), expr_) };
4305                     let lid = |s: &str| -> ast::Lid { ast::Lid(p.clone(), (0, s.to_string())) };
4306                     (
4307                         ast::Stmt::new(
4308                             p.clone(),
4309                             ast::Stmt_::mk_expr(e(E_::mk_binop(
4310                                 ast::Bop::Eq(None),
4311                                 e(E_::mk_obj_get(
4312                                     e(E_::mk_lvar(lid(special_idents::THIS))),
4313                                     e(E_::mk_id(ast::Id(p.clone(), cvname.to_string()))),
4314                                     ast::OgNullFlavor::OGNullthrows,
4315                                     false,
4316                                 )),
4317                                 e(E_::mk_lvar(lid(&param.name))),
4318                             ))),
4319                         ),
4320                         ast::ClassVar {
4321                             final_: false,
4322                             xhp_attr: None,
4323                             abstract_: false,
4324                             visibility: param.visibility.unwrap(),
4325                             type_: param.type_hint.clone(),
4326                             id: ast::Id(p.clone(), cvname.to_string()),
4327                             expr: None,
4328                             user_attributes: param.user_attributes.clone(),
4329                             doc_comment: None,
4330                             is_promoted_variadic: param.is_variadic,
4331                             is_static: false,
4332                             span,
4333                         },
4334                     )
4335                 };
4336                 let header = &c.function_decl_header;
4337                 let h = match &header.children {
4338                     FunctionDeclarationHeader(h) => h,
4339                     _ => panic!(),
4340                 };
4341                 let hdr = Self::p_fun_hdr(header, env)?;
4342                 let (mut member_init, mut member_def): (Vec<ast::Stmt>, Vec<ast::ClassVar>) = hdr
4343                     .parameters
4344                     .iter()
4345                     .filter_map(|p| p.visibility.map(|_| classvar_init(p)))
4346                     .unzip();
4348                 let kinds = Self::p_kinds(&h.modifiers, env)?;
4349                 let visibility = p_method_vis(&h.modifiers, &hdr.name.0, env)?;
4350                 let is_static = kinds.has(modifier::STATIC);
4351                 *env.in_static_method() = is_static;
4352                 let (mut body, body_has_yield) =
4353                     Self::mp_yielding(Self::p_function_body, &c.function_body, env)?;
4354                 if env.codegen() {
4355                     member_init.reverse();
4356                 }
4357                 member_init.append(&mut body);
4358                 let body = member_init;
4359                 *env.in_static_method() = false;
4360                 let is_abstract = kinds.has(modifier::ABSTRACT);
4361                 let is_external = !is_abstract && c.function_body.is_external();
4362                 let user_attributes = Self::p_user_attributes(&c.attribute, env)?;
4363                 Self::check_effect_polymorphic_memoized(
4364                     &hdr.contexts,
4365                     &user_attributes,
4366                     "method",
4367                     env,
4368                 );
4369                 let method = ast::Method_ {
4370                     span: Self::p_fun_pos(node, env),
4371                     annotation: (),
4372                     final_: kinds.has(modifier::FINAL),
4373                     abstract_: is_abstract,
4374                     static_: is_static,
4375                     name: hdr.name,
4376                     visibility,
4377                     tparams: hdr.type_parameters,
4378                     where_constraints: hdr.constrs,
4379                     variadic: Self::determine_variadicity(&hdr.parameters),
4380                     params: hdr.parameters,
4381                     ctxs: hdr.contexts,
4382                     unsafe_ctxs: hdr.unsafe_contexts,
4383                     body: ast::FuncBody {
4384                         annotation: (),
4385                         ast: body,
4386                     },
4387                     fun_kind: Self::mk_fun_kind(hdr.suspension_kind, body_has_yield),
4388                     user_attributes,
4389                     ret: ast::TypeHint((), hdr.return_type),
4390                     external: is_external,
4391                     doc_comment: doc_comment_opt,
4392                 };
4393                 class.vars.append(&mut member_def);
4394                 Ok(class.methods.push(method))
4395             }
4396             TraitUseConflictResolution(c) => {
4397                 type Ret = Result<Either<ast::InsteadofAlias, ast::UseAsAlias>>;
4398                 let p_item = |n: S<'a, T, V>, e: &mut Env<'a, TF>| -> Ret {
4399                     match &n.children {
4400                         TraitUsePrecedenceItem(c) => {
4401                             let (qualifier, name) = match &c.name.children {
4402                                 ScopeResolutionExpression(c) => (
4403                                     Self::pos_name(&c.qualifier, e)?,
4404                                     Self::p_pstring(&c.name, e)?,
4405                                 ),
4406                                 _ => Self::missing_syntax("trait use precedence item", n, e)?,
4407                             };
4408                             let removed_names =
4409                                 Self::could_map(Self::pos_name, &c.removed_names, e)?;
4410                             Self::raise_hh_error(e, Naming::unsupported_instead_of(name.0.clone()));
4411                             Ok(Either::Left(ast::InsteadofAlias(
4412                                 qualifier,
4413                                 name,
4414                                 removed_names,
4415                             )))
4416                         }
4417                         TraitUseAliasItem(c) => {
4418                             let (qualifier, name) = match &c.aliasing_name.children {
4419                                 ScopeResolutionExpression(c) => (
4420                                     Some(Self::pos_name(&c.qualifier, e)?),
4421                                     Self::p_pstring(&c.name, e)?,
4422                                 ),
4423                                 _ => (None, Self::p_pstring(&c.aliasing_name, e)?),
4424                             };
4425                             let (kinds, mut vis_raw) = Self::p_modifiers(
4426                                 |mut acc, kind| -> Vec<ast::UseAsVisibility> {
4427                                     if let Some(v) = modifier::to_use_as_visibility(kind) {
4428                                         acc.push(v);
4429                                     }
4430                                     acc
4431                                 },
4432                                 vec![],
4433                                 &c.modifiers,
4434                                 e,
4435                             )?;
4436                             let vis = if kinds.is_empty() || kinds.has_any(modifier::VISIBILITIES) {
4437                                 vis_raw
4438                             } else {
4439                                 let mut v = vec![ast::UseAsVisibility::UseAsPublic];
4440                                 v.append(&mut vis_raw);
4441                                 v
4442                             };
4443                             let aliased_name = if !c.aliased_name.is_missing() {
4444                                 Some(Self::pos_name(&c.aliased_name, e)?)
4445                             } else {
4446                                 None
4447                             };
4448                             Self::raise_hh_error(
4449                                 e,
4450                                 Naming::unsupported_trait_use_as(name.0.clone()),
4451                             );
4452                             Ok(Either::Right(ast::UseAsAlias(
4453                                 qualifier,
4454                                 name,
4455                                 aliased_name,
4456                                 vis,
4457                             )))
4458                         }
4459                         _ => Self::missing_syntax("trait use conflict resolution item", n, e),
4460                     }
4461                 };
4462                 let mut uses = Self::could_map(Self::p_hint, &c.names, env)?;
4463                 let elts = Self::could_map(p_item, &c.clauses, env)?;
4464                 class.uses.append(&mut uses);
4465                 for elt in elts.into_iter() {
4466                     match elt {
4467                         Either::Left(l) => class.insteadof_alias.push(l),
4468                         Either::Right(r) => class.use_as_alias.push(r),
4469                     }
4470                 }
4471                 Ok(())
4472             }
4473             TraitUse(c) => {
4474                 let mut uses = Self::could_map(Self::p_hint, &c.names, env)?;
4475                 Ok(class.uses.append(&mut uses))
4476             }
4477             RequireClause(c) => {
4478                 let hint = Self::p_hint(&c.name, env)?;
4479                 let is_extends = match Self::token_kind(&c.kind) {
4480                     Some(TK::Implements) => false,
4481                     Some(TK::Extends) => true,
4482                     _ => Self::missing_syntax("trait require kind", &c.kind, env)?,
4483                 };
4484                 Ok(class.reqs.push((hint, is_extends)))
4485             }
4486             XHPClassAttributeDeclaration(c) => {
4487                 type Ret = Result<Either<ast::XhpAttr, ast::Hint>>;
4488                 let p_attr = |node: S<'a, T, V>, env: &mut Env<'a, TF>| -> Ret {
4489                     let mk_attr_use = |n: S<'a, T, V>, env: &mut Env<'a, TF>| {
4490                         Ok(Either::Right(ast::Hint(
4491                             Self::p_pos(n, env),
4492                             Box::new(ast::Hint_::Happly(Self::pos_name(n, env)?, vec![])),
4493                         )))
4494                     };
4495                     match &node.children {
4496                         XHPClassAttribute(c) => {
4497                             let ast::Id(p, name) = Self::pos_name(&c.name, env)?;
4498                             if let TypeConstant(_) = &c.type_.children {
4499                                 if env.is_typechecker() {
4500                                     Self::raise_parsing_error(
4501                                         &c.type_,
4502                                         env,
4503                                         &syntax_error::xhp_class_attribute_type_constant,
4504                                     )
4505                                 }
4506                             }
4507                             let req = match &c.required.children {
4508                                 XHPRequired(_) => Some(ast::XhpAttrTag::Required),
4509                                 XHPLateinit(_) => Some(ast::XhpAttrTag::LateInit),
4510                                 _ => None,
4511                             };
4512                             let pos = if c.initializer.is_missing() {
4513                                 p.clone()
4514                             } else {
4515                                 Pos::btw(&p, &Self::p_pos(&c.initializer, env))
4516                                     .map_err(Error::Failwith)?
4517                             };
4518                             let (hint, enum_) = match &c.type_.children {
4519                                 XHPEnumType(c1) => {
4520                                     let p = Self::p_pos(&c.type_, env);
4521                                     let vals = Self::could_map(Self::p_expr, &c1.values, env)?;
4522                                     (None, Some((p, vals)))
4523                                 }
4524                                 _ => (Some(Self::p_hint(&c.type_, env)?), None),
4525                             };
4526                             let init_expr =
4527                                 Self::mp_optional(Self::p_simple_initializer, &c.initializer, env)?;
4528                             let xhp_attr = ast::XhpAttr(
4529                                 ast::TypeHint((), hint.clone()),
4530                                 ast::ClassVar {
4531                                     final_: false,
4532                                     xhp_attr: Some(ast::XhpAttrInfo { xai_tag: req }),
4533                                     abstract_: false,
4534                                     visibility: ast::Visibility::Public,
4535                                     type_: ast::TypeHint((), hint),
4536                                     id: ast::Id(p, String::from(":") + &name),
4537                                     expr: init_expr,
4538                                     user_attributes: vec![],
4539                                     doc_comment: None,
4540                                     is_promoted_variadic: false,
4541                                     is_static: false,
4542                                     span: pos,
4543                                 },
4544                                 req,
4545                                 enum_,
4546                             );
4547                             Ok(Either::Left(xhp_attr))
4548                         }
4549                         XHPSimpleClassAttribute(c) => mk_attr_use(&c.type_, env),
4550                         Token(_) => mk_attr_use(node, env),
4551                         _ => Self::missing_syntax("XHP attribute", node, env),
4552                     }
4553                 };
4554                 let attrs = Self::could_map(p_attr, &c.attributes, env)?;
4555                 for attr in attrs.into_iter() {
4556                     match attr {
4557                         Either::Left(attr) => class.xhp_attrs.push(attr),
4558                         Either::Right(xhp_attr_use) => class.xhp_attr_uses.push(xhp_attr_use),
4559                     }
4560                 }
4561                 Ok(())
4562             }
4563             XHPChildrenDeclaration(c) => {
4564                 let p = Self::p_pos(node, env);
4565                 Ok(class
4566                     .xhp_children
4567                     .push((p, Self::p_xhp_child(&c.expression, env)?)))
4568             }
4569             XHPCategoryDeclaration(c) => {
4570                 let p = Self::p_pos(node, env);
4571                 let categories =
4572                     Self::could_map(|n, e| Self::p_pstring_(n, e, Some('%')), &c.categories, env)?;
4573                 if let Some((_, cs)) = &class.xhp_category {
4574                     if let Some(category) = cs.first() {
4575                         Self::raise_hh_error(
4576                             env,
4577                             NastCheck::multiple_xhp_category(category.0.clone()),
4578                         )
4579                     }
4580                 }
4581                 Ok(class.xhp_category = Some((p, categories)))
4582             }
4583             _ => Self::missing_syntax("class element", node, env),
4584         }
4585     }
4587     fn p_class_elt(
4588         class: &mut ast::Class_,
4589         node: S<'a, T, V>,
4590         env: &mut Env<'a, TF>,
4591     ) -> Result<()> {
4592         let r = Self::p_class_elt_(class, node, env);
4593         match r {
4594             // match ocaml behavior, don't throw if missing syntax when fail_open is true
4595             Err(Error::MissingSyntax { .. }) if env.fail_open() => Ok(()),
4596             _ => r,
4597         }
4598     }
4600     fn contains_class_body(c: &ClassishDeclarationChildren<T, V>) -> bool {
4601         matches!(&c.body.children, ClassishBody(_))
4602     }
4604     fn p_where_constraint(
4605         is_class: bool,
4606         parent: S<'a, T, V>,
4607         node: S<'a, T, V>,
4608         env: &mut Env<'a, TF>,
4609     ) -> Result<Vec<ast::WhereConstraintHint>> {
4610         match &node.children {
4611             Missing => Ok(vec![]),
4612             WhereClause(c) => {
4613                 let f = |n: S<'a, T, V>, e: &mut Env<'a, TF>| -> Result<ast::WhereConstraintHint> {
4614                     match &n.children {
4615                         WhereConstraint(c) => {
4616                             use ast::ConstraintKind::*;
4617                             let l = Self::p_hint(&c.left_type, e)?;
4618                             let o = &c.operator;
4619                             let o = match Self::token_kind(o) {
4620                                 Some(TK::Equal) => ConstraintEq,
4621                                 Some(TK::As) => ConstraintAs,
4622                                 Some(TK::Super) => ConstraintSuper,
4623                                 _ => Self::missing_syntax("constraint operator", o, e)?,
4624                             };
4625                             Ok(ast::WhereConstraintHint(
4626                                 l,
4627                                 o,
4628                                 Self::p_hint(&c.right_type, e)?,
4629                             ))
4630                         }
4631                         _ => Self::missing_syntax("where constraint", n, e),
4632                     }
4633                 };
4634                 c.constraints
4635                     .syntax_node_to_list_skip_separator()
4636                     .map(|n| f(n, env))
4637                     .collect()
4638             }
4639             _ => {
4640                 if is_class {
4641                     Self::missing_syntax("classish declaration constraints", parent, env)
4642                 } else {
4643                     Self::missing_syntax("function header constraints", parent, env)
4644                 }
4645             }
4646         }
4647     }
4649     fn p_namespace_use_kind(kind: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::NsKind> {
4650         use ast::NsKind::*;
4651         match &kind.children {
4652             Missing => Ok(NSClassAndNamespace),
4653             _ => match Self::token_kind(kind) {
4654                 Some(TK::Namespace) => Ok(NSNamespace),
4655                 Some(TK::Type) => Ok(NSClass),
4656                 Some(TK::Function) => Ok(NSFun),
4657                 Some(TK::Const) => Ok(NSConst),
4658                 _ => Self::missing_syntax("namespace use kind", kind, env),
4659             },
4660         }
4661     }
4663     fn p_namespace_use_clause(
4664         prefix: Option<S<'a, T, V>>,
4665         kind: Result<ast::NsKind>,
4666         node: S<'a, T, V>,
4667         env: &mut Env<'a, TF>,
4668     ) -> Result<(ast::NsKind, ast::Sid, ast::Sid)> {
4669         lazy_static! {
4670             static ref NAMESPACE_USE: regex::Regex = regex::Regex::new("[^\\\\]*$").unwrap();
4671         }
4673         match &node.children {
4674             NamespaceUseClause(NamespaceUseClauseChildren {
4675                 clause_kind,
4676                 alias,
4677                 name,
4678                 ..
4679             }) => {
4680                 let ast::Id(p, n) = match (prefix, Self::pos_name(name, env)?) {
4681                     (None, id) => id,
4682                     (Some(prefix), ast::Id(p, n)) => {
4683                         ast::Id(p, Self::pos_name(prefix, env)?.1 + &n)
4684                     }
4685                 };
4686                 let alias = if alias.is_missing() {
4687                     let x = NAMESPACE_USE.find(&n).unwrap().as_str();
4688                     ast::Id(p.clone(), x.to_string())
4689                 } else {
4690                     Self::pos_name(alias, env)?
4691                 };
4692                 let kind = if clause_kind.is_missing() {
4693                     kind
4694                 } else {
4695                     Self::p_namespace_use_kind(clause_kind, env)
4696                 }?;
4697                 Ok((
4698                     kind,
4699                     ast::Id(
4700                         p,
4701                         if n.len() > 0 && n.chars().nth(0) == Some('\\') {
4702                             n
4703                         } else {
4704                             String::from("\\") + &n
4705                         },
4706                     ),
4707                     alias,
4708                 ))
4709             }
4710             _ => Self::missing_syntax("namespace use clause", node, env),
4711         }
4712     }
4714     fn check_effect_polymorphic_memoized(
4715         contexts: &Option<ast::Contexts>,
4716         user_attributes: &[aast::UserAttribute<Pos, (), (), ()>],
4717         kind: &str,
4718         env: &mut Env<'a, TF>,
4719     ) {
4720         if Self::has_polymorphic_context(contexts) {
4721             if let Some(u) = user_attributes
4722                 .iter()
4723                 .find(|u| u.name.1 == naming_special_names_rust::user_attributes::MEMOIZE)
4724             {
4725                 Self::raise_parsing_error_pos(
4726                     &u.name.0,
4727                     env,
4728                     &syntax_error::effect_polymorphic_memoized(kind),
4729                 )
4730             }
4731         }
4732     }
4734     fn p_def(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<Vec<ast::Def>> {
4735         let doc_comment_opt = Self::extract_docblock(node, env);
4736         match &node.children {
4737             FunctionDeclaration(FunctionDeclarationChildren {
4738                 attribute_spec,
4739                 declaration_header,
4740                 body,
4741             }) => {
4742                 let mut env = Env::clone_and_unset_toplevel_if_toplevel(env);
4743                 let env = env.as_mut();
4744                 let hdr = Self::p_fun_hdr(declaration_header, env)?;
4745                 let is_external = body.is_external();
4746                 let (block, yield_) = if is_external {
4747                     (vec![], false)
4748                 } else {
4749                     Self::mp_yielding(&Self::p_function_body, body, env)?
4750                 };
4751                 let user_attributes = Self::p_user_attributes(attribute_spec, env)?;
4752                 Self::check_effect_polymorphic_memoized(
4753                     &hdr.contexts,
4754                     &user_attributes,
4755                     "function",
4756                     env,
4757                 );
4758                 let variadic = Self::determine_variadicity(&hdr.parameters);
4759                 let ret = ast::TypeHint((), hdr.return_type);
4760                 Ok(vec![ast::Def::mk_fun(ast::Fun_ {
4761                     span: Self::p_fun_pos(node, env),
4762                     annotation: (),
4763                     mode: env.file_mode(),
4764                     ret,
4765                     name: hdr.name,
4766                     tparams: hdr.type_parameters,
4767                     where_constraints: hdr.constrs,
4768                     params: hdr.parameters,
4769                     ctxs: hdr.contexts,
4770                     unsafe_ctxs: hdr.unsafe_contexts,
4771                     body: ast::FuncBody {
4772                         ast: block,
4773                         annotation: (),
4774                     },
4775                     fun_kind: Self::mk_fun_kind(hdr.suspension_kind, yield_),
4776                     variadic,
4777                     user_attributes,
4778                     file_attributes: vec![],
4779                     external: is_external,
4780                     namespace: Self::mk_empty_ns_env(env),
4781                     doc_comment: doc_comment_opt,
4782                     static_: false,
4783                 })])
4784             }
4785             ClassishDeclaration(c) if Self::contains_class_body(c) => {
4786                 let mut env = Env::clone_and_unset_toplevel_if_toplevel(env);
4787                 let env = env.as_mut();
4788                 let mode = env.file_mode();
4789                 let user_attributes = Self::p_user_attributes(&c.attribute, env)?;
4790                 let kinds = Self::p_kinds(&c.modifiers, env)?;
4791                 let final_ = kinds.has(modifier::FINAL);
4792                 let is_xhp = matches!(
4793                     Self::token_kind(&c.name),
4794                     Some(TK::XHPElementName) | Some(TK::XHPClassName)
4795                 );
4796                 let has_xhp_keyword = matches!(Self::token_kind(&c.xhp), Some(TK::XHP));
4797                 let name = Self::pos_name(&c.name, env)?;
4798                 *env.cls_reified_generics() = HashSet::new();
4799                 let tparams = Self::p_tparam_l(true, &c.type_parameters, env)?;
4800                 let class_kind = match Self::token_kind(&c.keyword) {
4801                     Some(TK::Class) if kinds.has(modifier::ABSTRACT) => ast::ClassKind::Cabstract,
4802                     Some(TK::Class) => ast::ClassKind::Cnormal,
4803                     Some(TK::Interface) => ast::ClassKind::Cinterface,
4804                     Some(TK::Trait) => ast::ClassKind::Ctrait,
4805                     Some(TK::Enum) => ast::ClassKind::Cenum,
4806                     _ => Self::missing_syntax("class kind", &c.keyword, env)?,
4807                 };
4808                 let filter_dynamic =
4809                     |node: S<'a, T, V>, env: &mut Env<'a, TF>| -> Result<Option<ast::Hint>> {
4810                         match Self::p_hint(node, env) {
4811                             Err(e) => Err(e),
4812                             Ok(h) => match &*h.1 {
4813                                 oxidized::aast_defs::Hint_::Happly(oxidized::ast::Id(_, id), _) => {
4814                                     if id == "dynamic" {
4815                                         Ok(None)
4816                                     } else {
4817                                         Ok(Some(h))
4818                                     }
4819                                 }
4820                                 _ => Ok(Some(h)),
4821                             },
4822                         }
4823                     };
4824                 let (extends, extends_dynamic) = match class_kind {
4825                     ast::ClassKind::Cinterface if env.parser_options.tco_enable_sound_dynamic => {
4826                         Self::could_map_filter(filter_dynamic, &c.extends_list, env)?
4827                     }
4828                     _ => (Self::could_map(Self::p_hint, &c.extends_list, env)?, false),
4829                 };
4830                 *env.parent_maybe_reified() = match extends.first().map(|h| h.1.as_ref()) {
4831                     Some(ast::Hint_::Happly(_, hl)) => !hl.is_empty(),
4832                     _ => false,
4833                 };
4834                 let (implements, implements_dynamic) =
4835                     if env.parser_options.tco_enable_sound_dynamic {
4836                         Self::could_map_filter(filter_dynamic, &c.implements_list, env)?
4837                     } else {
4838                         (
4839                             Self::could_map(Self::p_hint, &c.implements_list, env)?,
4840                             false,
4841                         )
4842                     };
4844                 let where_constraints = Self::p_where_constraint(true, node, &c.where_clause, env)?;
4845                 let namespace = Self::mk_empty_ns_env(env);
4846                 let span = Self::p_pos(node, env);
4847                 let mut class_ = ast::Class_ {
4848                     span,
4849                     annotation: (),
4850                     mode,
4851                     final_,
4852                     is_xhp,
4853                     has_xhp_keyword,
4854                     kind: class_kind,
4855                     name,
4856                     tparams,
4857                     extends,
4858                     uses: vec![],
4859                     use_as_alias: vec![],
4860                     insteadof_alias: vec![],
4861                     xhp_attr_uses: vec![],
4862                     xhp_category: None,
4863                     reqs: vec![],
4864                     implements,
4865                     implements_dynamic: implements_dynamic || extends_dynamic,
4866                     where_constraints,
4867                     consts: vec![],
4868                     typeconsts: vec![],
4869                     vars: vec![],
4870                     methods: vec![],
4871                     // TODO: what is this attbiute? check ast_to_aast
4872                     attributes: vec![],
4873                     xhp_children: vec![],
4874                     xhp_attrs: vec![],
4875                     namespace,
4876                     user_attributes,
4877                     file_attributes: vec![],
4878                     enum_: None,
4879                     doc_comment: doc_comment_opt,
4880                     emit_id: None,
4881                 };
4882                 match &c.body.children {
4883                     ClassishBody(c1) => {
4884                         for elt in c1.elements.syntax_node_to_list_skip_separator() {
4885                             Self::p_class_elt(&mut class_, elt, env)?;
4886                         }
4887                     }
4888                     _ => Self::missing_syntax("classish body", &c.body, env)?,
4889                 }
4890                 Ok(vec![ast::Def::mk_class(class_)])
4891             }
4892             ConstDeclaration(c) => {
4893                 let ty = &c.type_specifier;
4894                 let decls = c.declarators.syntax_node_to_list_skip_separator();
4895                 let mut defs = vec![];
4896                 for decl in decls {
4897                     let def = match &decl.children {
4898                         ConstantDeclarator(c) => {
4899                             let name = &c.name;
4900                             let init = &c.initializer;
4901                             let gconst = ast::Gconst {
4902                                 annotation: (),
4903                                 mode: env.file_mode(),
4904                                 name: Self::pos_name(name, env)?,
4905                                 type_: Self::mp_optional(Self::p_hint, ty, env)?,
4906                                 value: Self::p_simple_initializer(init, env)?,
4907                                 namespace: Self::mk_empty_ns_env(env),
4908                                 span: Self::p_pos(node, env),
4909                                 emit_id: None,
4910                             };
4911                             ast::Def::mk_constant(gconst)
4912                         }
4913                         _ => Self::missing_syntax("constant declaration", decl, env)?,
4914                     };
4915                     defs.push(def);
4916                 }
4917                 Ok(defs)
4918             }
4919             AliasDeclaration(c) => {
4920                 let tparams = Self::p_tparam_l(false, &c.generic_parameter, env)?;
4921                 for tparam in tparams.iter() {
4922                     if tparam.reified != ast::ReifyKind::Erased {
4923                         Self::raise_parsing_error(node, env, &syntax_error::invalid_reified)
4924                     }
4925                 }
4926                 Ok(vec![ast::Def::mk_typedef(ast::Typedef {
4927                     annotation: (),
4928                     name: Self::pos_name(&c.name, env)?,
4929                     tparams,
4930                     constraint: Self::mp_optional(Self::p_tconstraint, &c.constraint, env)?
4931                         .map(|x| x.1),
4932                     user_attributes: itertools::concat(
4933                         c.attribute_spec
4934                             .syntax_node_to_list_skip_separator()
4935                             .map(|attr| Self::p_user_attribute(attr, env))
4936                             .collect::<std::result::Result<Vec<Vec<_>>, _>>()?,
4937                     ),
4938                     namespace: Self::mk_empty_ns_env(env),
4939                     mode: env.file_mode(),
4940                     vis: match Self::token_kind(&c.keyword) {
4941                         Some(TK::Type) => ast::TypedefVisibility::Transparent,
4942                         Some(TK::Newtype) => ast::TypedefVisibility::Opaque,
4943                         _ => Self::missing_syntax("kind", &c.keyword, env)?,
4944                     },
4945                     kind: Self::p_hint(&c.type_, env)?,
4946                     span: Self::p_pos(node, env),
4947                     emit_id: None,
4948                 })])
4949             }
4950             EnumDeclaration(c) => {
4951                 let p_enumerator =
4952                     |n: S<'a, T, V>, e: &mut Env<'a, TF>| -> Result<ast::ClassConst> {
4953                         match &n.children {
4954                             Enumerator(c) => Ok(ast::ClassConst {
4955                                 type_: None,
4956                                 id: Self::pos_name(&c.name, e)?,
4957                                 expr: Some(Self::p_expr(&c.value, e)?),
4958                                 doc_comment: None,
4959                             }),
4960                             _ => Self::missing_syntax("enumerator", n, e),
4961                         }
4962                     };
4963                 Ok(vec![ast::Def::mk_class(ast::Class_ {
4964                     annotation: (),
4965                     mode: env.file_mode(),
4966                     user_attributes: Self::p_user_attributes(&c.attribute_spec, env)?,
4967                     file_attributes: vec![],
4968                     final_: false,
4969                     kind: ast::ClassKind::Cenum,
4970                     is_xhp: false,
4971                     has_xhp_keyword: false,
4972                     name: Self::pos_name(&c.name, env)?,
4973                     tparams: vec![],
4974                     extends: vec![],
4975                     implements: vec![],
4976                     implements_dynamic: false,
4977                     where_constraints: vec![],
4978                     consts: Self::could_map(p_enumerator, &c.enumerators, env)?,
4979                     namespace: Self::mk_empty_ns_env(env),
4980                     span: Self::p_pos(node, env),
4981                     enum_: Some(ast::Enum_ {
4982                         base: Self::p_hint(&c.base, env)?,
4983                         constraint: Self::mp_optional(Self::p_tconstraint_ty, &c.type_, env)?,
4984                         includes: Self::could_map(Self::p_hint, &c.includes_list, env)?,
4985                         enum_class: false,
4986                     }),
4988                     doc_comment: doc_comment_opt,
4989                     uses: vec![],
4990                     use_as_alias: vec![],
4991                     insteadof_alias: vec![],
4992                     xhp_attr_uses: vec![],
4993                     xhp_category: None,
4994                     reqs: vec![],
4995                     vars: vec![],
4996                     typeconsts: vec![],
4997                     methods: vec![],
4998                     attributes: vec![],
4999                     xhp_children: vec![],
5000                     xhp_attrs: vec![],
5001                     emit_id: None,
5002                 })])
5003             }
5004             EnumClassDeclaration(c) => {
5005                 let name = Self::pos_name(&c.name, env)?;
5006                 // Adding __EnumClass
5007                 let mut user_attributes = Self::p_user_attributes(&c.attribute_spec, env)?;
5008                 let enum_class_attribute = ast::UserAttribute {
5009                     name: ast::Id(name.0.clone(), special_attrs::ENUM_CLASS.to_string()),
5010                     params: vec![],
5011                 };
5012                 user_attributes.push(enum_class_attribute);
5013                 // During lowering we store the base type as is. It will be updated during
5014                 // the naming phase
5015                 let base_type = Self::p_hint(&c.base, env)?;
5017                 let name_s = name.1.clone(); // TODO: can I avoid this clone ?
5019                 // Helper to build X -> HH\MemberOf<enum_name, X>
5020                 let build_elt = |p: Pos, ty: ast::Hint| -> ast::Hint {
5021                     let enum_name = ast::Id(p.clone(), name_s.clone());
5022                     let enum_class = ast::Hint_::mk_happly(enum_name, vec![]);
5023                     let enum_class = ast::Hint::new(p.clone(), enum_class);
5024                     let elt_id = ast::Id(p.clone(), special_classes::MEMBER_OF.to_string());
5025                     let full_type = ast::Hint_::mk_happly(elt_id, vec![enum_class, ty]);
5026                     ast::Hint::new(p, full_type)
5027                 };
5029                 let extends = Self::could_map(Self::p_hint, &c.extends_list, env)?;
5031                 let mut enum_class = ast::Class_ {
5032                     annotation: (),
5033                     mode: env.file_mode(),
5034                     user_attributes,
5035                     file_attributes: vec![],
5036                     final_: false, // TODO(T77095784): support final EDTs
5037                     kind: ast::ClassKind::Cenum,
5038                     is_xhp: false,
5039                     has_xhp_keyword: false,
5040                     name,
5041                     tparams: vec![],
5042                     extends: extends.clone(),
5043                     implements: vec![],
5044                     implements_dynamic: false,
5045                     where_constraints: vec![],
5046                     consts: vec![],
5047                     namespace: Self::mk_empty_ns_env(env),
5048                     span: Self::p_pos(node, env),
5049                     enum_: Some(ast::Enum_ {
5050                         base: base_type,
5051                         constraint: None,
5052                         includes: extends,
5053                         enum_class: true,
5054                     }),
5055                     doc_comment: doc_comment_opt,
5056                     uses: vec![],
5057                     use_as_alias: vec![],
5058                     insteadof_alias: vec![],
5059                     xhp_attr_uses: vec![],
5060                     xhp_category: None,
5061                     reqs: vec![],
5062                     vars: vec![],
5063                     typeconsts: vec![],
5064                     methods: vec![],
5065                     attributes: vec![],
5066                     xhp_children: vec![],
5067                     xhp_attrs: vec![],
5068                     emit_id: None,
5069                 };
5071                 for n in c.elements.syntax_node_to_list_skip_separator() {
5072                     match &n.children {
5073                         // TODO(T77095784): check pos and span usage
5074                         EnumClassEnumerator(c) => {
5075                             // we turn:
5076                             // - type name = expression;
5077                             // into
5078                             // - const MemberOf<enum_name, type> name = expression
5079                             let name = Self::pos_name(&c.name, env)?;
5080                             let pos = &name.0;
5081                             let elt_type = Self::p_hint(&c.type_, env)?;
5082                             let full_type = build_elt(pos.clone(), elt_type);
5083                             let initial_value = Self::p_expr(&c.initial_value, env)?;
5084                             let class_const = ast::ClassConst {
5085                                 type_: Some(full_type),
5086                                 id: name,
5087                                 expr: Some(initial_value),
5088                                 doc_comment: None,
5089                             };
5090                             enum_class.consts.push(class_const)
5091                         }
5092                         _ => {
5093                             let pos = Self::p_pos(n, env);
5094                             Self::raise_parsing_error_pos(
5095                                 &pos,
5096                                 env,
5097                                 &syntax_error::invalid_enum_class_enumerator,
5098                             )
5099                         }
5100                     }
5101                 }
5102                 Ok(vec![ast::Def::mk_class(enum_class)])
5103             }
5104             RecordDeclaration(c) => {
5105                 let p_field = |n: S<'a, T, V>, e: &mut Env<'a, TF>| match &n.children {
5106                     RecordField(c) => Ok((
5107                         Self::pos_name(&c.name, e)?,
5108                         Self::p_hint(&c.type_, e)?,
5109                         Self::mp_optional(Self::p_simple_initializer, &c.init, e)?,
5110                     )),
5111                     _ => Self::missing_syntax("record_field", n, e),
5112                 };
5113                 Ok(vec![ast::Def::mk_record_def(ast::RecordDef {
5114                     annotation: (),
5115                     name: Self::pos_name(&c.name, env)?,
5116                     extends: Self::could_map(Self::p_hint, &c.extends_opt, env)?
5117                         .into_iter()
5118                         .next(),
5119                     abstract_: Self::token_kind(&c.modifier) == Some(TK::Abstract),
5120                     user_attributes: Self::p_user_attributes(&c.attribute_spec, env)?,
5121                     fields: Self::could_map(p_field, &c.fields, env)?,
5122                     namespace: Self::mk_empty_ns_env(env),
5123                     span: Self::p_pos(node, env),
5124                     doc_comment: doc_comment_opt,
5125                     emit_id: None,
5126                 })])
5127             }
5128             InclusionDirective(c) if env.file_mode() != file_info::Mode::Mdecl || env.codegen() => {
5129                 let expr = Self::p_expr(&c.expression, env)?;
5130                 Ok(vec![ast::Def::mk_stmt(ast::Stmt::new(
5131                     Self::p_pos(node, env),
5132                     ast::Stmt_::mk_expr(expr),
5133                 ))])
5134             }
5135             NamespaceDeclaration(c) => {
5136                 let name = if let NamespaceDeclarationHeader(h) = &c.header.children {
5137                     &h.name
5138                 } else {
5139                     return Self::missing_syntax("namespace_declaration_header", node, env);
5140                 };
5141                 let defs = match &c.body.children {
5142                     NamespaceBody(c) => {
5143                         let mut env1 = Env::clone_and_unset_toplevel_if_toplevel(env);
5144                         let env1 = env1.as_mut();
5145                         itertools::concat(
5146                             c.declarations
5147                                 .syntax_node_to_list_skip_separator()
5148                                 .map(|n| Self::p_def(n, env1))
5149                                 .collect::<std::result::Result<Vec<Vec<_>>, _>>()?,
5150                         )
5151                     }
5152                     _ => vec![],
5153                 };
5154                 Ok(vec![ast::Def::mk_namespace(
5155                     Self::pos_name(name, env)?,
5156                     defs,
5157                 )])
5158             }
5159             NamespaceGroupUseDeclaration(c) => {
5160                 let uses: std::result::Result<Vec<_>, _> = c
5161                     .clauses
5162                     .syntax_node_to_list_skip_separator()
5163                     .map(|n| {
5164                         Self::p_namespace_use_clause(
5165                             Some(&c.prefix),
5166                             Self::p_namespace_use_kind(&c.kind, env),
5167                             n,
5168                             env,
5169                         )
5170                     })
5171                     .collect();
5172                 Ok(vec![ast::Def::mk_namespace_use(uses?)])
5173             }
5174             NamespaceUseDeclaration(c) => {
5175                 let uses: std::result::Result<Vec<_>, _> = c
5176                     .clauses
5177                     .syntax_node_to_list_skip_separator()
5178                     .map(|n| {
5179                         Self::p_namespace_use_clause(
5180                             None,
5181                             Self::p_namespace_use_kind(&c.kind, env),
5182                             n,
5183                             env,
5184                         )
5185                     })
5186                     .collect();
5187                 Ok(vec![ast::Def::mk_namespace_use(uses?)])
5188             }
5189             FileAttributeSpecification(_) => {
5190                 Ok(vec![ast::Def::mk_file_attributes(ast::FileAttribute {
5191                     user_attributes: Self::p_user_attribute(node, env)?,
5192                     namespace: Self::mk_empty_ns_env(env),
5193                 })])
5194             }
5195             _ if env.file_mode() == file_info::Mode::Mdecl => Ok(vec![]),
5196             _ => Ok(vec![ast::Def::mk_stmt(Self::p_stmt(node, env)?)]),
5197         }
5198     }
5200     fn post_process(env: &mut Env<'a, TF>, program: ast::Program, acc: &mut ast::Program) {
5201         use aast::{Def, Def::*, Stmt_::*};
5202         let mut saw_ns: Option<(ast::Sid, ast::Program)> = None;
5203         for def in program.into_iter() {
5204             if let Namespace(_) = &def {
5205                 if let Some((n, ns_acc)) = saw_ns {
5206                     acc.push(Def::mk_namespace(n, ns_acc));
5207                     saw_ns = None;
5208                 }
5209             }
5211             if let Namespace(ns) = def {
5212                 let (n, defs) = *ns;
5213                 if defs.is_empty() {
5214                     saw_ns = Some((n, vec![]));
5215                 } else {
5216                     let mut acc_ = vec![];
5217                     Self::post_process(env, defs, &mut acc_);
5218                     acc.push(Def::mk_namespace(n, acc_));
5219                 }
5221                 continue;
5222             }
5224             if let Stmt(s) = &def {
5225                 if s.1.is_noop() {
5226                     continue;
5227                 }
5228                 let raise_error = match &s.1 {
5229                     Markup(_) => false,
5230                     Expr(expr)
5231                         if expr.as_ref().is_import()
5232                             && !env.parser_options.po_disallow_toplevel_requires =>
5233                     {
5234                         false
5235                     }
5236                     _ => {
5237                         use file_info::Mode::*;
5238                         let mode = env.file_mode();
5239                         env.keep_errors
5240                             && env.is_typechecker()
5241                             && (mode == Mstrict
5242                                 || (mode == Mpartial
5243                                     && env
5244                                         .parser_options
5245                                         .error_codes_treated_strictly
5246                                         .contains(&1002)))
5247                     }
5248                 };
5249                 if raise_error {
5250                     Self::raise_parsing_error_pos(&s.0, env, &syntax_error::toplevel_statements);
5251                 }
5252             }
5254             if let Some((_, ns_acc)) = &mut saw_ns {
5255                 ns_acc.push(def);
5256             } else {
5257                 acc.push(def);
5258             };
5259         }
5260         if let Some((n, defs)) = saw_ns {
5261             acc.push(Def::mk_namespace(n, defs));
5262         }
5263     }
5265     fn p_program(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Program> {
5266         let nodes = node.syntax_node_to_list_skip_separator();
5267         let mut acc = vec![];
5268         for n in nodes {
5269             match &n.children {
5270                 EndOfFile(_) => break,
5271                 _ => match Self::p_def(n, env) {
5272                     Err(Error::MissingSyntax { .. }) if env.fail_open => {}
5273                     e @ Err(_) => return e,
5274                     Ok(mut def) => acc.append(&mut def),
5275                 },
5276             }
5277         }
5278         let mut program = vec![];
5279         Self::post_process(env, acc, &mut program);
5280         Ok(program)
5281     }
5283     fn p_script(node: S<'a, T, V>, env: &mut Env<'a, TF>) -> Result<ast::Program> {
5284         match &node.children {
5285             Script(c) => Self::p_program(&c.declarations, env),
5286             _ => Self::missing_syntax("script", node, env),
5287         }
5288     }
5290     fn lower(
5291         env: &mut Env<'a, TF>,
5292         script: S<'a, T, V>,
5293     ) -> std::result::Result<ast::Program, String> {
5294         Self::p_script(script, env).map_err(|e| match e {
5295             Error::MissingSyntax {
5296                 expecting,
5297                 pos,
5298                 node_name,
5299                 kind,
5300             } => format!(
5301                 "missing case in {:?}.\n - pos: {:?}\n - unexpected: '{:?}'\n - kind: {:?}\n",
5302                 expecting.to_string(),
5303                 pos,
5304                 node_name.to_string(),
5305                 kind,
5306             ),
5307             Error::Failwith(msg) => msg,
5308         })
5309     }
5312 struct PositionedSyntaxLowerer;
5313 impl<'a> Lowerer<'a, PositionedToken<'a>, PositionedValue<'a>, PositionedTokenFactory<'a>>
5314     for PositionedSyntaxLowerer
5318 pub fn lower<'a>(
5319     env: &mut Env<'a, PositionedTokenFactory<'a>>,
5320     script: S<'a, PositionedToken<'a>, PositionedValue<'a>>,
5321 ) -> std::result::Result<ast::Program, String> {
5322     PositionedSyntaxLowerer::lower(env, script)