using visitor to check reified hint
[hiphop-php.git] / hphp / hack / src / parser / lowerer.rs
blob5bb64d5bb724ff1e8f88d7e5d23f8becc1e5dd7d
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 escaper::*;
8 use hh_autoimport_rust as hh_autoimport;
9 use itertools::{Either, Either::Left, Either::Right};
10 use naming_special_names_rust::{classes as special_classes, special_functions, special_idents};
11 use ocamlrep::rc::RcOc;
12 use oxidized::{
13     aast,
14     aast::Expr_ as E_,
15     aast_defs,
16     aast_visitor::{Node, Visitor},
17     ast_defs,
18     doc_comment::DocComment,
19     file_info,
20     global_options::GlobalOptions,
21     namespace_env::Env as NamespaceEnv,
22     pos::Pos,
23     s_map,
25 use parser_core_types::{
26     indexed_source_text::IndexedSourceText, lexable_token::LexablePositionedToken,
27     positioned_syntax::PositionedSyntaxTrait, source_text::SourceText, syntax::*, syntax_error,
28     syntax_kind, syntax_trait::SyntaxTrait, token_kind::TokenKind as TK,
30 use regex::bytes::Regex;
31 use std::{
32     cell::{Ref, RefCell, RefMut},
33     collections::HashSet,
34     mem,
35     rc::Rc,
36     result::Result::{Err, Ok},
37     slice::Iter,
40 use crate::lowerer_modifier as modifier;
42 macro_rules! aast {
43     ($ty:ident) =>  {oxidized::aast::$ty};
44     // NOTE: In <,> pattern, comma prevents rustfmt eating <>
45     ($ty:ident<,>) =>  {oxidized::aast::$ty<Pos, (), (), ()>}
48 macro_rules! ret {
49     ($ty:ty) => { std::result::Result<$ty, Error> }
52 macro_rules! ret_aast {
53     ($ty:ident) => { std::result::Result<aast!($ty), Error> };
54     ($ty:ident<,>) => { std::result::Result<aast!($ty<,>), Error> }
57 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
58 pub enum LiftedAwaitKind {
59     LiftedFromStatement,
60     LiftedFromConcurrent,
63 type LiftedAwaitExprs = Vec<(Option<aast!(Lid)>, aast!(Expr<,>))>;
65 #[derive(Debug, Clone)]
66 pub struct LiftedAwaits {
67     pub awaits: LiftedAwaitExprs,
68     lift_kind: LiftedAwaitKind,
71 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
72 pub enum ExprLocation {
73     TopLevel,
74     MemberSelect,
75     InDoubleQuotedString,
76     InBacktickedString,
77     AsStatement,
78     RightOfAssignment,
79     RightOfAssignmentInUsingStatement,
80     RightOfReturn,
81     UsingStatement,
84 impl ExprLocation {
85     fn in_string(self) -> bool {
86         self == ExprLocation::InDoubleQuotedString || self == ExprLocation::InBacktickedString
87     }
90 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
91 pub enum SuspensionKind {
92     SKSync,
93     SKAsync,
94     SKCoroutine,
97 #[derive(Copy, Clone, Eq, PartialEq)]
98 pub enum TokenOp {
99     Skip,
100     Noop,
101     LeftTrim(usize),
102     RightTrim(usize),
105 #[derive(Debug)]
106 pub struct FunHdr {
107     suspension_kind: SuspensionKind,
108     name: aast!(Sid),
109     constrs: Vec<aast_defs::WhereConstraint>,
110     type_parameters: Vec<aast!(Tparam<,>)>,
111     parameters: Vec<aast!(FunParam<,>)>,
112     return_type: Option<aast!(Hint)>,
115 impl FunHdr {
116     fn make_empty(env: &Env) -> Self {
117         Self {
118             suspension_kind: SuspensionKind::SKSync,
119             name: ast_defs::Id(env.mk_none_pos(), String::from("<ANONYMOUS>")),
120             constrs: vec![],
121             type_parameters: vec![],
122             parameters: vec![],
123             return_type: None,
124         }
125     }
128 #[derive(Debug)]
129 pub struct State {
130     /* Whether we've seen COMPILER_HALT_OFFSET. The value of COMPILER_HALT_OFFSET
131       defaults to 0 if HALT_COMPILER isn't called.
132       None -> COMPILER_HALT_OFFSET isn't in the source file
133       Some 0 -> COMPILER_HALT_OFFSET is in the source file, but HALT_COMPILER isn't
134       Some x -> COMPILER_HALT_OFFSET is in the source file,
135                 HALT_COMPILER is at x bytes offset in the file.
136     */
137     pub saw_compiler_halt_offset: Option<usize>,
138     pub cls_reified_generics: HashSet<String>,
139     pub in_static_method: bool,
140     pub parent_maybe_reified: bool,
141     /* This provides a generic mechanism to delay raising parsing errors;
142      * since we're moving FFP errors away from CST to a stage after lowering
143      * _and_ want to prioritize errors before lowering, the lowering errors
144      * must be merely stored when the lowerer runs (until check for FFP runs (on AST)
145      * and raised _after_ FFP error checking (unless we run the lowerer twice,
146      * which would be expensive). */
147     pub lowpri_errors: Vec<(Pos, String)>,
148     pub doc_comments: Vec<Option<DocComment>>,
150     pub local_id_counter: isize,
153 #[derive(Debug, Clone)]
154 pub struct Env<'a> {
155     codegen: bool,
156     pub keep_errors: bool,
157     quick_mode: bool,
158     /* Show errors even in quick mode. Does not override keep_errors. Hotfix
159      * until we can properly set up saved states to surface parse errors during
160      * typechecking properly. */
161     pub show_all_errors: bool,
162     fail_open: bool,
163     file_mode: file_info::Mode,
164     pub top_level_statements: bool, /* Whether we are (still) considering TLSs*/
166     // Cache none pos, lazy_static doesn't allow Rc.
167     pos_none: Pos,
168     empty_ns_env: RcOc<NamespaceEnv>,
170     pub saw_yield: bool, /* Information flowing back up */
171     pub lifted_awaits: Option<LiftedAwaits>,
172     pub tmp_var_counter: isize,
174     pub indexed_source_text: &'a IndexedSourceText<'a>,
175     pub parser_options: &'a GlobalOptions,
177     state: Rc<RefCell<State>>,
180 impl<'a> Env<'a> {
181     pub fn make(
182         codegen: bool,
183         quick_mode: bool,
184         keep_errors: bool,
185         show_all_errors: bool,
186         mode: file_info::Mode,
187         indexed_source_text: &'a IndexedSourceText<'a>,
188         parser_options: &'a GlobalOptions,
189     ) -> Self {
190         // Ported from namespace_env.ml
191         let mut ns_uses = hh_autoimport::NAMESPACES_MAP.clone();
192         parser_options
193             .po_auto_namespace_map
194             .iter()
195             .for_each(|(k, v)| {
196                 &ns_uses.insert(k.into(), v.into());
197             });
198         let empty_ns_env = NamespaceEnv {
199             ns_uses,
200             class_uses: s_map::SMap::new(),
201             fun_uses: hh_autoimport::FUNCS_MAP.clone(),
202             const_uses: hh_autoimport::CONSTS_MAP.clone(),
203             record_def_uses: s_map::SMap::new(),
204             name: None,
205             auto_ns_map: parser_options.po_auto_namespace_map.clone(),
206             is_codegen: codegen,
207         };
209         Env {
210             codegen,
211             keep_errors,
212             quick_mode,
213             show_all_errors,
214             fail_open: true,
215             file_mode: mode,
216             top_level_statements: true,
217             saw_yield: false,
218             lifted_awaits: None,
219             tmp_var_counter: 1,
220             indexed_source_text,
221             parser_options,
222             pos_none: Pos::make_none(),
223             empty_ns_env: RcOc::new(empty_ns_env),
225             state: Rc::new(RefCell::new(State {
226                 saw_compiler_halt_offset: None,
227                 cls_reified_generics: HashSet::new(),
228                 in_static_method: false,
229                 parent_maybe_reified: false,
230                 lowpri_errors: vec![],
231                 doc_comments: vec![],
232                 local_id_counter: 1,
233             })),
234         }
235     }
237     fn file_mode(&self) -> file_info::Mode {
238         self.file_mode
239     }
241     fn should_surface_error(&self) -> bool {
242         (!self.quick_mode || self.show_all_errors) && self.keep_errors
243     }
245     fn is_typechecker(&self) -> bool {
246         !self.codegen
247     }
249     fn codegen(&self) -> bool {
250         self.codegen
251     }
253     fn source_text(&self) -> &SourceText<'a> {
254         self.indexed_source_text.source_text()
255     }
257     fn fail_open(&self) -> bool {
258         self.fail_open
259     }
261     fn saw_compiler_halt_offset(&mut self) -> RefMut<Option<usize>> {
262         RefMut::map(self.state.borrow_mut(), |s| &mut s.saw_compiler_halt_offset)
263     }
265     fn cls_reified_generics(&mut self) -> RefMut<HashSet<String>> {
266         RefMut::map(self.state.borrow_mut(), |s| &mut s.cls_reified_generics)
267     }
269     fn in_static_method(&mut self) -> RefMut<bool> {
270         RefMut::map(self.state.borrow_mut(), |s| &mut s.in_static_method)
271     }
273     fn parent_maybe_reified(&mut self) -> RefMut<bool> {
274         RefMut::map(self.state.borrow_mut(), |s| &mut s.parent_maybe_reified)
275     }
277     pub fn lowpri_errors(&mut self) -> RefMut<Vec<(Pos, String)>> {
278         RefMut::map(self.state.borrow_mut(), |s| &mut s.lowpri_errors)
279     }
281     fn top_docblock(&self) -> Ref<Option<DocComment>> {
282         Ref::map(self.state.borrow(), |s| {
283             s.doc_comments.last().unwrap_or(&None)
284         })
285     }
287     fn next_local_id(&self) -> isize {
288         let mut id = RefMut::map(self.state.borrow_mut(), |s| &mut s.local_id_counter);
289         *id = *id + 1;
290         *id
291     }
293     fn push_docblock(&mut self, doc_comment: Option<DocComment>) {
294         RefMut::map(self.state.borrow_mut(), |s| &mut s.doc_comments).push(doc_comment)
295     }
297     fn pop_docblock(&mut self) {
298         RefMut::map(self.state.borrow_mut(), |s| &mut s.doc_comments).pop();
299     }
301     fn make_tmp_var_name(&mut self) -> String {
302         let name = String::from(special_idents::TMP_VAR_PREFIX) + &self.tmp_var_counter.to_string();
303         self.tmp_var_counter += 1;
304         name
305     }
307     fn mk_none_pos(&self) -> Pos {
308         self.pos_none.clone()
309     }
311     fn clone_and_unset_toplevel_if_toplevel<'b, 'c>(
312         e: &'b mut Env<'c>,
313     ) -> impl AsMut<Env<'c>> + 'b {
314         if e.top_level_statements {
315             let mut cloned = e.clone();
316             cloned.top_level_statements = false;
317             Either::Left(cloned)
318         } else {
319             Either::Right(e)
320         }
321     }
324 impl<'a> AsMut<Env<'a>> for Env<'a> {
325     fn as_mut(&mut self) -> &mut Env<'a> {
326         self
327     }
330 #[derive(Debug)]
331 pub enum Error {
332     APIMissingSyntax {
333         expecting: String,
334         pos: Pos,
335         node_name: String,
336         kind: syntax_kind::SyntaxKind,
337     },
338     Failwith(String),
341 pub struct Result {
342     pub aast: aast!(Program<,>),
345 use parser_core_types::syntax::SyntaxVariant::*;
347 pub trait Lowerer<'a, T, V>
348 where
349     T: LexablePositionedToken<'a>,
350     Syntax<T, V>: PositionedSyntaxTrait,
351     V: SyntaxValueWithKind + SyntaxValueType<T> + std::fmt::Debug,
353     fn mode_annotation(mode: file_info::Mode) -> file_info::Mode {
354         match mode {
355             file_info::Mode::Mphp => file_info::Mode::Mdecl,
356             m => m,
357         }
358     }
360     // Turns a syntax node into a list of nodes; if it is a separated syntax
361     // list then the separators are filtered from the resulting list.
362     fn syntax_to_list(include_separators: bool, node: &Syntax<T, V>) -> Vec<&Syntax<T, V>> {
363         fn on_list_item<T1, V1>(sep: bool, x: &ListItemChildren<T1, V1>) -> Vec<&Syntax<T1, V1>> {
364             if sep {
365                 vec![&x.list_item, &x.list_separator]
366             } else {
367                 vec![&x.list_item]
368             }
369         }
370         match &node.syntax {
371             Missing => vec![],
372             SyntaxList(s) => s
373                 .iter()
374                 .map(|x| match &x.syntax {
375                     ListItem(x) => on_list_item(include_separators, x),
376                     _ => vec![node],
377                 })
378                 .flatten()
379                 .collect(),
380             ListItem(x) => on_list_item(include_separators, x),
381             _ => vec![node],
382         }
383     }
385     fn p_pos(node: &Syntax<T, V>, env: &Env) -> Pos {
386         node.position_exclusive(env.indexed_source_text)
387             .unwrap_or_else(|| env.mk_none_pos())
388     }
390     fn raise_parsing_error(node: &Syntax<T, V>, env: &mut Env, msg: &str) {
391         Self::raise_parsing_error_(Either::Left(node), env, msg)
392     }
394     fn raise_parsing_error_pos(pos: &Pos, env: &mut Env, msg: &str) {
395         Self::raise_parsing_error_(Either::Right(pos), env, msg)
396     }
398     fn raise_parsing_error_(node_or_pos: Either<&Syntax<T, V>, &Pos>, env: &mut Env, msg: &str) {
399         if env.should_surface_error() {
400             let pos = node_or_pos.either(|node| Self::p_pos(node, env), |pos| pos.clone());
401             env.lowpri_errors().push((pos, String::from(msg)))
402         } else if env.codegen() {
403             let pos = node_or_pos.either(
404                 |node| {
405                     node.position_exclusive(env.indexed_source_text)
406                         .unwrap_or_else(|| env.mk_none_pos())
407                 },
408                 |pos| pos.clone(),
409             );
410             env.lowpri_errors().push((pos, String::from(msg)))
411         }
412     }
414     fn raise_nast_error(msg: &str) {
415         // A placehold for error raised in ast_to_aast.ml
416     }
418     #[inline]
419     fn failwith<N>(msg: impl Into<String>) -> ret!(N) {
420         Err(Error::Failwith(msg.into()))
421     }
423     #[inline]
424     fn text(node: &Syntax<T, V>, env: &Env) -> String {
425         String::from(node.text(env.source_text()))
426     }
428     #[inline]
429     fn text_str<'b>(node: &'b Syntax<T, V>, env: &'b Env) -> &'b str {
430         node.text(env.source_text())
431     }
433     fn lowering_error(env: &mut Env, pos: &Pos, text: &str, syntax_kind: &str) {
434         if env.is_typechecker() && env.lowpri_errors().is_empty() {
435             // TODO: Ocaml also checks Errors.currently_has_errors
436             Self::raise_parsing_error_pos(
437                 pos,
438                 env,
439                 &syntax_error::lowering_parsing_error(text, syntax_kind),
440             )
441         }
442     }
444     fn missing_syntax<N>(
445         fallback: Option<N>,
446         expecting: &str,
447         node: &Syntax<T, V>,
448         env: &mut Env,
449     ) -> ret!(N) {
450         let pos = Self::p_pos(node, env);
451         let text = Self::text(node, env);
452         Self::lowering_error(env, &pos, &text, expecting);
453         if let Some(x) = fallback {
454             if env.fail_open {
455                 return Ok(x);
456             }
457         }
458         Err(Error::APIMissingSyntax {
459             expecting: String::from(expecting),
460             pos: Self::p_pos(node, env),
461             node_name: text,
462             kind: node.kind(),
463         })
464     }
466     fn is_num_octal_lit(s: &str) -> bool {
467         !s.chars().any(|c| c == '8' || c == '9')
468     }
470     fn mp_optional<F, R>(p: F, node: &Syntax<T, V>, env: &mut Env) -> ret!(Option<R>)
471     where
472         F: FnOnce(&Syntax<T, V>, &mut Env) -> ret!(R),
473     {
474         match &node.syntax {
475             Missing => Ok(None),
476             _ => p(node, env).map(Some),
477         }
478     }
480     fn pos_qualified_name(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Sid) {
481         if let QualifiedName(c) = &node.syntax {
482             if let SyntaxList(l) = &c.qualified_name_parts.syntax {
483                 let p = Self::p_pos(node, env);
484                 let mut s = String::with_capacity(node.width());
485                 for i in l.iter() {
486                     match &i.syntax {
487                         ListItem(li) => {
488                             s += li.list_item.text(env.source_text());
489                             s += li.list_separator.text(env.source_text());
490                         }
491                         _ => s += i.text(env.source_text()),
492                     }
493                 }
494                 return Ok(ast_defs::Id(p, s));
495             }
496         }
497         Self::missing_syntax(None, "qualified name", node, env)
498     }
500     #[inline]
501     fn pos_name(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Sid) {
502         Self::pos_name_(node, env, None)
503     }
505     fn lid_from_pos_name(pos: Pos, name: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Lid) {
506         let name = Self::pos_name(name, env)?;
507         Ok(aast::Lid::new(pos, name.1))
508     }
510     fn lid_from_name(name: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Lid) {
511         let name = Self::pos_name(name, env)?;
512         Ok(aast::Lid::new(name.0, name.1))
513     }
515     // TODO: after porting unify Sid and Pstring
516     #[inline]
517     fn p_pstring(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Pstring) {
518         Self::p_pstring_(node, env, None)
519     }
521     #[inline]
522     fn p_pstring_(
523         node: &Syntax<T, V>,
524         env: &mut Env,
525         drop_prefix: Option<char>,
526     ) -> ret_aast!(Pstring) {
527         let ast_defs::Id(p, id) = Self::pos_name_(node, env, drop_prefix)?;
528         Ok((p, id))
529     }
531     #[inline]
532     fn drop_prefix(s: &str, prefix: char) -> &str {
533         if s.len() > 0 && s.chars().nth(0) == Some(prefix) {
534             &s[1..]
535         } else {
536             s
537         }
538     }
540     fn pos_name_(node: &Syntax<T, V>, env: &mut Env, drop_prefix: Option<char>) -> ret_aast!(Sid) {
541         match &node.syntax {
542             QualifiedName(_) => Self::pos_qualified_name(node, env),
543             SimpleTypeSpecifier(c) => Self::pos_name_(&c.simple_type_specifier, env, drop_prefix),
544             _ => {
545                 let mut name = node.text(env.indexed_source_text.source_text());
546                 if name == "__COMPILER_HALT_OFFSET__" {
547                     *env.saw_compiler_halt_offset() = Some(0);
548                 }
549                 if let Some(prefix) = drop_prefix {
550                     name = Self::drop_prefix(name, prefix);
551                 }
552                 let p = Self::p_pos(node, env);
553                 Ok(ast_defs::Id(p, String::from(name)))
554             }
555         }
556     }
558     fn mk_str<F>(node: &Syntax<T, V>, env: &mut Env, unescaper: F, mut content: &str) -> String
559     where
560         F: Fn(&str) -> std::result::Result<String, InvalidString>,
561     {
562         if let Some('b') = content.chars().nth(0) {
563             content = content.get(1..).unwrap();
564         }
566         let len = content.len();
567         let no_quotes_result = extract_unquoted_string(content, 0, len);
568         match no_quotes_result {
569             Ok(no_quotes) => {
570                 let result = unescaper(&no_quotes);
571                 match result {
572                     Ok(s) => s,
573                     Err(_) => {
574                         Self::raise_parsing_error(
575                             node,
576                             env,
577                             &format!("Malformed string literal <<{}>>", &no_quotes),
578                         );
579                         String::from("")
580                     }
581                 }
582             }
583             Err(_) => {
584                 Self::raise_parsing_error(
585                     node,
586                     env,
587                     &format!("Malformed string literal <<{}>>", &content),
588                 );
589                 String::from("")
590             }
591         }
592     }
594     fn unesc_dbl(s: &str) -> std::result::Result<String, InvalidString> {
595         let unesc_s = unescape_double(s)?;
596         match unesc_s.as_str() {
597             "''" | "\"\"" => Ok(String::from("")),
598             _ => Ok(unesc_s),
599         }
600     }
602     // TODO: return Cow<[u8]>
603     fn unesc_xhp(s: &[u8]) -> Vec<u8> {
604         lazy_static! {
605             static ref WHITESPACE: Regex = Regex::new("[\x20\t\n\r\x0c]+").unwrap();
606         }
607         WHITESPACE.replace_all(s, &b" "[..]).into_owned()
608     }
610     fn unesc_xhp_attr(s: &[u8]) -> Vec<u8> {
611         // TODO: change unesc_dbl to &[u8] -> Vec<u8>
612         let r = Self::get_quoted_content(s);
613         let r = unsafe { std::str::from_utf8_unchecked(r) };
614         Self::unesc_dbl(r).unwrap().into_bytes()
615     }
617     fn get_quoted_content(s: &[u8]) -> &[u8] {
618         lazy_static! {
619             static ref QUOTED: Regex = Regex::new(r#"^[\x20\t\n\r\x0c]*"((?:.|\n)*)""#).unwrap();
620         }
621         QUOTED
622             .captures(s)
623             .map_or(None, |c| c.get(1))
624             .map_or(s, |m| m.as_bytes())
625     }
627     fn as_list(node: &Syntax<T, V>) -> Vec<&Syntax<T, V>> {
628         fn strip_list_item<T1, V1>(node: &Syntax<T1, V1>) -> &Syntax<T1, V1> {
629             match &node.syntax {
630                 ListItem(i) => &i.list_item,
631                 _ => node,
632             }
633         }
634         match &node.syntax {
635             SyntaxList(l) => l.iter().map(strip_list_item).collect(),
636             Missing => vec![],
637             _ => vec![node],
638         }
639     }
641     fn token_kind(node: &Syntax<T, V>) -> Option<TK> {
642         match &node.syntax {
643             Token(t) => Some(t.kind()),
644             _ => None,
645         }
646     }
648     fn check_valid_reified_hint(env: &mut Env, node: &Syntax<T, V>, hint: &aast!(Hint)) {
649         struct Checker<F: FnMut(&String)>(F);
650         impl<F: FnMut(&String)> Visitor for Checker<F> {
651             type Context = ();
652             type Ex = Pos;
653             type Fb = ();
654             type En = ();
655             type Hi = ();
657             fn object(
658                 &mut self,
659             ) -> &mut dyn Visitor<Context = Self::Context, Ex = Pos, Fb = (), En = (), Hi = ()>
660             {
661                 self
662             }
664             fn visit_hint(&mut self, c: &mut (), h: &aast!(Hint)) {
665                 match h.1.as_ref() {
666                     aast::Hint_::Happly(id, _) => {
667                         self.0(&id.1);
668                     }
669                     aast::Hint_::Haccess(_, ids) => {
670                         ids.iter().for_each(|id| self.0(&id.1));
671                     }
672                     _ => {}
673                 }
674                 h.recurse(c, self);
675             }
676         }
678         if *env.in_static_method() {
679             let f = |id: &String| {
680                 Self::fail_if_invalid_reified_generic(node, env, id);
681             };
682             let mut visitor = Checker(f);
683             visitor.visit_hint(&mut (), hint);
684         }
685     }
687     fn p_closure_parameter(
688         node: &Syntax<T, V>,
689         env: &mut Env,
690     ) -> ret!((aast!(Hint), Option<ast_defs::ParamKind>)) {
691         match &node.syntax {
692             ClosureParameterTypeSpecifier(c) => {
693                 let kind = Self::mp_optional(
694                     Self::p_param_kind,
695                     &c.closure_parameter_call_convention,
696                     env,
697                 )?;
698                 let hint = Self::p_hint(&c.closure_parameter_type, env)?;
699                 Ok((hint, kind))
700             }
701             _ => Self::missing_syntax(None, "closure parameter", node, env),
702         }
703     }
705     fn mp_shape_expression_field<F, R>(
706         f: F,
707         node: &Syntax<T, V>,
708         env: &mut Env,
709     ) -> ret!((ast_defs::ShapeFieldName, R))
710     where
711         F: Fn(&Syntax<T, V>, &mut Env) -> ret!(R),
712     {
713         match &node.syntax {
714             FieldInitializer(c) => {
715                 let name = Self::p_shape_field_name(&c.field_initializer_name, env)?;
716                 let value = f(&c.field_initializer_value, env)?;
717                 Ok((name, value))
718             }
719             _ => Self::missing_syntax(None, "shape field", node, env),
720         }
721     }
723     fn p_shape_field_name(node: &Syntax<T, V>, env: &mut Env) -> ret!(ast_defs::ShapeFieldName) {
724         use ast_defs::ShapeFieldName::*;
725         let is_valid_shape_literal = |t: &T| {
726             let is_str = t.kind() == TK::SingleQuotedStringLiteral
727                 || t.kind() == TK::DoubleQuotedStringLiteral;
728             let text = t.text(env.source_text());
729             let is_empty = text == "\'\'" || text == "\"\"";
730             is_str && !is_empty
731         };
732         if let LiteralExpression(c) = &node.syntax {
733             if let Token(t) = &c.literal_expression.syntax {
734                 if is_valid_shape_literal(t) {
735                     let ast_defs::Id(p, n) = Self::pos_name(node, env)?;
736                     let str_ = Self::mk_str(node, env, Self::unesc_dbl, &n);
737                     match ocaml_helper::int_of_string_opt(&str_.as_bytes()) {
738                         Some(_) => Self::raise_parsing_error(
739                             node,
740                             env,
741                             &syntax_error::shape_field_int_like_string,
742                         ),
743                         _ => {}
744                     }
745                     return Ok(SFlitStr((p, str_)));
746                 }
747             }
748         }
749         match &node.syntax {
750             ScopeResolutionExpression(c) => Ok(SFclassConst(
751                 Self::pos_name(&c.scope_resolution_qualifier, env)?,
752                 Self::p_pstring(&c.scope_resolution_name, env)?,
753             )),
754             _ => {
755                 Self::raise_parsing_error(node, env, &syntax_error::invalid_shape_field_name);
756                 let ast_defs::Id(p, n) = Self::pos_name(node, env)?;
757                 Ok(SFlitStr((p, Self::mk_str(node, env, Self::unesc_dbl, &n))))
758             }
759         }
760     }
762     fn p_shape_field(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(ShapeFieldInfo) {
763         match &node.syntax {
764             FieldSpecifier(c) => {
765                 let optional = !c.field_question.is_missing();
766                 let name = Self::p_shape_field_name(&c.field_name, env)?;
767                 let hint = Self::p_hint(&c.field_type, env)?;
768                 Ok(aast::ShapeFieldInfo {
769                     optional,
770                     hint,
771                     name,
772                 })
773             }
774             _ => {
775                 let (name, hint) = Self::mp_shape_expression_field(Self::p_hint, node, env)?;
776                 Ok(aast::ShapeFieldInfo {
777                     optional: false,
778                     name,
779                     hint,
780                 })
781             }
782         }
783     }
785     fn p_targ(node: &Syntax<T, V>, env: &mut Env) -> ret!(aast::Targ<()>) {
786         Ok(aast::Targ((), Self::p_hint(node, env)?))
787     }
789     fn p_hint_(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Hint_) {
790         use aast_defs::Hint_::*;
791         let unary = |kw, ty, env: &mut Env| {
792             Ok(Happly(
793                 Self::pos_name(kw, env)?,
794                 Self::could_map(Self::p_hint, ty, env)?,
795             ))
796         };
797         let binary = |kw, key, ty, env: &mut Env| {
798             let kw = Self::pos_name(kw, env)?;
799             let key = Self::p_hint(key, env)?;
800             Ok(Happly(
801                 kw,
802                 Self::map_flatten_(&Self::p_hint, ty, env, vec![key])?,
803             ))
804         };
805         match &node.syntax {
806             /* Dirty hack; CastExpression can have type represented by token */
807             Token(_) | SimpleTypeSpecifier(_) | QualifiedName(_) => {
808                 Ok(Happly(Self::pos_name(node, env)?, vec![]))
809             }
810             ShapeTypeSpecifier(c) => {
811                 let allows_unknown_fields = !c.shape_type_ellipsis.is_missing();
812                 /* if last element lacks a separator and ellipsis is present, error */
813                 if let Some(l) = Self::syntax_to_list(true, &c.shape_type_fields).last() {
814                     if l.is_missing() && allows_unknown_fields {
815                         Self::raise_parsing_error(
816                             node,
817                             env,
818                             &syntax_error::shape_type_ellipsis_without_trailing_comma,
819                         )
820                     }
821                 }
823                 let field_map = Self::could_map(Self::p_shape_field, &c.shape_type_fields, env)?;
825                 Ok(Hshape(aast::NastShapeInfo {
826                     allows_unknown_fields,
827                     field_map,
828                 }))
829             }
830             TupleTypeSpecifier(c) => {
831                 Ok(Htuple(Self::could_map(Self::p_hint, &c.tuple_types, env)?))
832             }
833             UnionTypeSpecifier(c) => {
834                 Ok(Hunion(Self::could_map(&Self::p_hint, &c.union_types, env)?))
835             }
836             IntersectionTypeSpecifier(c) => Ok(Hintersection(Self::could_map(
837                 &Self::p_hint,
838                 &c.intersection_types,
839                 env,
840             )?)),
841             KeysetTypeSpecifier(c) => Ok(Happly(
842                 Self::pos_name(&c.keyset_type_keyword, env)?,
843                 Self::could_map(Self::p_hint, &c.keyset_type_type, env)?,
844             )),
845             VectorTypeSpecifier(c) => unary(&c.vector_type_keyword, &c.vector_type_type, env),
846             ClassnameTypeSpecifier(c) => unary(&c.classname_keyword, &c.classname_type, env),
847             TupleTypeExplicitSpecifier(c) => unary(&c.tuple_type_keyword, &c.tuple_type_types, env),
848             VarrayTypeSpecifier(c) => unary(&c.varray_keyword, &c.varray_type, env),
849             VectorArrayTypeSpecifier(c) => {
850                 unary(&c.vector_array_keyword, &c.vector_array_type, env)
851             }
852             DarrayTypeSpecifier(c) => {
853                 binary(&c.darray_keyword, &c.darray_key, &c.darray_value, env)
854             }
855             MapArrayTypeSpecifier(c) => binary(
856                 &c.map_array_keyword,
857                 &c.map_array_key,
858                 &c.map_array_value,
859                 env,
860             ),
861             DictionaryTypeSpecifier(c) => {
862                 unary(&c.dictionary_type_keyword, &c.dictionary_type_members, env)
863             }
864             GenericTypeSpecifier(c) => {
865                 let name = Self::pos_name(&c.generic_class_type, env)?;
866                 let args = &c.generic_argument_list;
867                 let type_args = match &args.syntax {
868                     TypeArguments(c) => {
869                         Self::could_map(Self::p_hint, &c.type_arguments_types, env)?
870                     }
871                     _ => Self::missing_syntax(None, "generic type arguments", args, env)?,
872                 };
873                 if env.codegen() {
874                     // aorenste: Not sure why the original code had this as
875                     // unimplemented!(), but returning the type is better than
876                     // nothing...
877                     Ok(Happly(name, type_args))
878                 } else {
879                     Ok(Happly(name, type_args))
880                 }
881             }
882             NullableTypeSpecifier(c) => Ok(Hoption(Self::p_hint(&c.nullable_type, env)?)),
883             LikeTypeSpecifier(c) => Ok(Hlike(Self::p_hint(&c.like_type, env)?)),
884             SoftTypeSpecifier(c) => Ok(Hsoft(Self::p_hint(&c.soft_type, env)?)),
885             ClosureTypeSpecifier(c) => {
886                 let (param_list, variadic_hints): (Vec<&Syntax<T, V>>, Vec<&Syntax<T, V>>) =
887                     Self::as_list(&c.closure_parameter_list)
888                         .iter()
889                         .partition(|n| match &n.syntax {
890                             VariadicParameter(_) => false,
891                             _ => true,
892                         });
893                 let (type_hints, kinds) = param_list
894                     .iter()
895                     .map(|p| Self::p_closure_parameter(p, env))
896                     .collect::<std::result::Result<Vec<_>, _>>()?
897                     .into_iter()
898                     .unzip();
899                 let variadic_hints = variadic_hints
900                     .iter()
901                     .map(|v| match &v.syntax {
902                         VariadicParameter(c) => {
903                             let vtype = &c.variadic_parameter_type;
904                             if vtype.is_missing() {
905                                 Self::raise_parsing_error(
906                                     v,
907                                     env,
908                                     "Cannot use ... without a typehint",
909                                 );
910                             }
911                             Ok(Some(Self::p_hint(vtype, env)?))
912                         }
913                         _ => panic!("expect variadic parameter"),
914                     })
915                     .collect::<std::result::Result<Vec<_>, _>>()?;
916                 if variadic_hints.len() > 1 {
917                     return Self::failwith(format!(
918                         "{} variadic parameters found. There should be no more than one.",
919                         variadic_hints.len().to_string()
920                     ));
921                 }
922                 Ok(Hfun(aast::HintFun {
923                     reactive_kind: aast::FuncReactive::FNonreactive,
924                     is_coroutine: !c.closure_coroutine.is_missing(),
925                     param_tys: type_hints,
926                     param_kinds: kinds,
927                     param_mutability: vec![],
928                     variadic_ty: variadic_hints.into_iter().next().unwrap_or(None),
929                     return_ty: Self::p_hint(&c.closure_return_type, env)?,
930                     is_mutable_return: true,
931                 }))
932             }
933             AttributizedSpecifier(c) => {
934                 let attrs = Self::p_user_attribute(&c.attributized_specifier_attribute_spec, env)?;
935                 let hint = Self::p_hint(&c.attributized_specifier_type, env)?;
936                 if attrs.iter().any(|attr| attr.name.1 != "__Soft") {
937                     Self::raise_parsing_error(node, env, &syntax_error::only_soft_allowed);
938                 }
939                 Ok(*Self::soften_hint(&attrs, hint).1)
940             }
941             TypeConstant(c) => {
942                 let child = Self::pos_name(&c.type_constant_right_type, env)?;
943                 match Self::p_hint_(&c.type_constant_left_type, env)? {
944                     Haccess(root, mut cs) => {
945                         cs.push(child);
946                         Ok(Haccess(root, cs))
947                     }
948                     Happly(ty, param) => {
949                         if param.is_empty() {
950                             let root = aast::Hint::new(ty.0.clone(), Happly(ty, param));
951                             Ok(Haccess(root, vec![child]))
952                         } else {
953                             Self::missing_syntax(None, "type constant base", node, env)
954                         }
955                     }
956                     _ => Self::missing_syntax(None, "type constant base", node, env),
957                 }
958             }
959             PUAccess(c) => {
960                 let pos = Self::p_pos(&c.pu_access_left_type, env);
961                 let child = Self::pos_name(&c.pu_access_right_type, env)?;
962                 match Self::p_hint_(&c.pu_access_left_type, env)? {
963                     h @ HpuAccess(_, _) => Ok(HpuAccess(aast::Hint::new(pos, h), child)),
964                     Happly(id, hints) => {
965                         if hints.is_empty() {
966                             Ok(HpuAccess(aast::Hint::new(pos, Happly(id, hints)), child))
967                         } else {
968                             Self::missing_syntax(None, "pocket universe access base", node, env)
969                         }
970                     }
971                     _ => Self::missing_syntax(None, "pocket universe access base", node, env),
972                 }
973             }
974             ReifiedTypeArgument(_) => {
975                 Self::raise_parsing_error(node, env, &syntax_error::invalid_reified);
976                 Self::missing_syntax(None, "refied type", node, env)
977             }
978             _ => Self::missing_syntax(None, "type hint", node, env),
979         }
980     }
982     fn p_hint(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Hint) {
983         let hint_ = Self::p_hint_(node, env)?;
984         let pos = Self::p_pos(node, env);
985         let hint = aast::Hint::new(pos, hint_);
986         Self::check_valid_reified_hint(env, node, &hint);
987         Ok(hint)
988     }
990     fn p_simple_initializer(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Expr<,>) {
991         match &node.syntax {
992             SimpleInitializer(c) => Self::p_expr(&c.simple_initializer_value, env),
993             _ => Self::missing_syntax(None, "simple initializer", node, env),
994         }
995     }
997     fn p_member(node: &Syntax<T, V>, env: &mut Env) -> ret!((aast!(Expr<,>), aast!(Expr<,>))) {
998         match &node.syntax {
999             ElementInitializer(c) => Ok((
1000                 Self::p_expr(&c.element_key, env)?,
1001                 Self::p_expr(&c.element_value, env)?,
1002             )),
1003             _ => Self::missing_syntax(None, "darray intrinsic expression element", node, env),
1004         }
1005     }
1007     fn expand_type_args(ty: &Syntax<T, V>, env: &mut Env) -> ret!(Vec<aast!(Hint)>) {
1008         match &ty.syntax {
1009             TypeArguments(c) => Self::could_map(Self::p_hint, &c.type_arguments_types, env),
1010             _ => Ok(vec![]),
1011         }
1012     }
1014     fn p_afield(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Afield<,>) {
1015         match &node.syntax {
1016             ElementInitializer(c) => Ok(aast::Afield::AFkvalue(
1017                 Self::p_expr(&c.element_key, env)?,
1018                 Self::p_expr(&c.element_value, env)?,
1019             )),
1020             _ => Ok(aast::Afield::AFvalue(Self::p_expr(node, env)?)),
1021         }
1022     }
1024     fn check_intrinsic_type_arg_varity(
1025         node: &Syntax<T, V>,
1026         env: &mut Env,
1027         tys: Vec<aast!(Hint)>,
1028     ) -> Option<aast::CollectionTarg<()>> {
1029         let count = tys.len();
1030         let mut tys = tys.into_iter();
1031         match count {
1032             2 => Some(aast::CollectionTarg::CollectionTKV(
1033                 aast::Targ((), tys.next().unwrap()),
1034                 aast::Targ((), tys.next().unwrap()),
1035             )),
1036             1 => Some(aast::CollectionTarg::CollectionTV(aast::Targ(
1037                 (),
1038                 tys.next().unwrap(),
1039             ))),
1040             0 => None,
1041             _ => {
1042                 Self::raise_parsing_error(
1043                     node,
1044                     env,
1045                     &syntax_error::collection_intrinsic_many_typeargs,
1046                 );
1047                 None
1048             }
1049         }
1050     }
1052     fn p_import_flavor(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(ImportFlavor) {
1053         use aast::ImportFlavor::*;
1054         match Self::token_kind(node) {
1055             Some(TK::Include) => Ok(Include),
1056             Some(TK::Require) => Ok(Require),
1057             Some(TK::Include_once) => Ok(IncludeOnce),
1058             Some(TK::Require_once) => Ok(RequireOnce),
1059             _ => Self::missing_syntax(None, "import flavor", node, env),
1060         }
1061     }
1063     fn p_null_flavor(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(OgNullFlavor) {
1064         use aast::OgNullFlavor::*;
1065         match Self::token_kind(node) {
1066             Some(TK::QuestionMinusGreaterThan) => Ok(OGNullsafe),
1067             Some(TK::MinusGreaterThan) => Ok(OGNullthrows),
1068             _ => Self::missing_syntax(None, "null flavor", node, env),
1069         }
1070     }
1072     #[inline]
1073     fn wrap_unescaper<F>(unescaper: F, s: &str) -> ret!(String)
1074     where
1075         F: FnOnce(&str) -> std::result::Result<String, InvalidString>,
1076     {
1077         unescaper(s).map_err(|e| Error::Failwith(e.msg))
1078     }
1080     fn fail_if_invalid_class_creation(node: &Syntax<T, V>, env: &mut Env, id: impl AsRef<str>) {
1081         let id = id.as_ref();
1082         let is_in_static_method = *env.in_static_method();
1083         if is_in_static_method
1084             && ((id == special_classes::SELF && !env.cls_reified_generics().is_empty())
1085                 || (id == special_classes::PARENT && *env.parent_maybe_reified()))
1086         {
1087             Self::raise_parsing_error(node, env, &syntax_error::static_method_reified_obj_creation);
1088         }
1089     }
1091     fn fail_if_invalid_reified_generic(node: &Syntax<T, V>, env: &mut Env, id: impl AsRef<str>) {
1092         let is_in_static_method = *env.in_static_method();
1093         if is_in_static_method && env.cls_reified_generics().contains(id.as_ref()) {
1094             Self::raise_parsing_error(
1095                 node,
1096                 env,
1097                 &syntax_error::cls_reified_generic_in_static_method,
1098             );
1099         }
1100     }
1102     // (hrust) `i` is initial index
1103     fn rfind(s: &[u8], mut i: usize, c: u8) -> ret!(usize) {
1104         if i >= s.len() {
1105             return Self::failwith("index out of range");
1106         }
1107         i += 1;
1108         while i > 0 {
1109             i -= 1;
1110             if s[i] == c {
1111                 return Ok(i);
1112             }
1113         }
1114         Self::failwith("char not found")
1115     }
1117     fn prep_string2(nodes: &[Syntax<T, V>], env: &mut Env) -> ret!((TokenOp, TokenOp)) {
1118         use TokenOp::*;
1119         let is_qoute = |c| c == b'\"' || c == b'`';
1120         let start_is_qoute = |s: &[u8]| {
1121             (s.len() > 0 && is_qoute(s[0])) || (s.len() > 1 && (s[0] == b'b' && s[1] == b'\"'))
1122         };
1123         let last_is_qoute = |s: &[u8]| s.len() > 0 && is_qoute(s[s.len() - 1]);
1124         let is_heredoc = |s: &[u8]| (s.len() > 3 && &s[0..3] == b"<<<");
1125         let mut nodes = nodes.iter();
1126         let first = nodes.next();
1127         match first.map(|n| &n.syntax) {
1128             Some(Token(t)) => {
1129                 let raise = |env| {
1130                     Self::raise_parsing_error(first.unwrap(), env, "Malformed String2 SyntaxList");
1131                 };
1132                 let text = t.text_raw(env.source_text());
1133                 if start_is_qoute(text) {
1134                     let first_token_op = match text[0] {
1135                         b'b' if text.len() > 2 => LeftTrim(2),
1136                         _ if is_qoute(text[0]) && text.len() > 1 => LeftTrim(1),
1137                         _ => Skip,
1138                     };
1139                     if let Some(Token(t)) = nodes.last().map(|n| &n.syntax) {
1140                         let last_text = t.text_raw(env.source_text());
1141                         if last_is_qoute(last_text) {
1142                             let last_taken_op = match last_text.len() {
1143                                 n if n > 1 => RightTrim(1),
1144                                 _ => Skip,
1145                             };
1146                             return Ok((first_token_op, last_taken_op));
1147                         }
1148                     }
1149                     raise(env);
1150                     Ok((first_token_op, Noop))
1151                 } else if is_heredoc(text) {
1152                     let trim_size = text
1153                         .iter()
1154                         .position(|c| *c == b'\n')
1155                         .ok_or_else(|| Error::Failwith(String::from("newline not found")))?
1156                         + 1;
1157                     let first_token_op = match trim_size {
1158                         _ if trim_size == text.len() => Skip,
1159                         _ => LeftTrim(trim_size),
1160                     };
1161                     if let Some(Token(t)) = nodes.last().map(|n| &n.syntax) {
1162                         let text = t.text_raw(env.source_text());
1163                         let len = text.len();
1164                         if len != 0 {
1165                             let n = Self::rfind(text, len - 2, b'\n')?;
1166                             let last_token_op = match n {
1167                                 0 => Skip,
1168                                 _ => RightTrim(len - n),
1169                             };
1170                             return Ok((first_token_op, last_token_op));
1171                         }
1172                     }
1173                     raise(env);
1174                     Ok((first_token_op, Noop))
1175                 } else {
1176                     Ok((Noop, Noop))
1177                 }
1178             }
1179             _ => Ok((Noop, Noop)),
1180         }
1181     }
1183     fn process_token_op(op: TokenOp, node: &Syntax<T, V>) -> ret!(Option<Syntax<T, V>>) {
1184         use TokenOp::*;
1185         match op {
1186             LeftTrim(n) => match &node.syntax {
1187                 Token(t) => {
1188                     let mut token = t.clone_value();
1189                     token.trim_left(n).map_err(Error::Failwith)?;
1190                     let node = <Syntax<T, V>>::make_token(token);
1191                     Ok(Some(node))
1192                 }
1193                 _ => Self::failwith("Token expected"),
1194             },
1195             RightTrim(n) => match &node.syntax {
1196                 Token(t) => {
1197                     let mut token = t.clone_value();
1198                     token.trim_right(n).map_err(Error::Failwith)?;
1199                     let node = <Syntax<T, V>>::make_token(token);
1200                     Ok(Some(node))
1201                 }
1202                 _ => Self::failwith("Token expected"),
1203             },
1204             _ => Ok(None),
1205         }
1206     }
1208     fn p_string2(nodes: &[Syntax<T, V>], env: &mut Env) -> ret!(Vec<aast!(Expr<,>)>) {
1209         use TokenOp::*;
1210         let (head_op, tail_op) = Self::prep_string2(nodes, env)?;
1211         let mut result = Vec::with_capacity(nodes.len());
1212         let mut i = 0;
1213         let last = nodes.len() - 1;
1214         while i <= last {
1215             let op = match i {
1216                 0 => head_op,
1217                 _ if i == last => tail_op,
1218                 _ => Noop,
1219             };
1221             if op == Skip {
1222                 i += 1;
1223                 continue;
1224             }
1226             let node = Self::process_token_op(op, &nodes[i])?;
1227             let node = node.as_ref().unwrap_or(&nodes[i]);
1229             if Self::token_kind(node) == Some(TK::Dollar) && i < last {
1230                 if let EmbeddedBracedExpression(c) = &nodes[i + 1].syntax {
1231                     Self::raise_parsing_error(
1232                         &nodes[i + 1],
1233                         env,
1234                         &syntax_error::outside_dollar_str_interp,
1235                     );
1237                     result.push(Self::p_expr_with_loc(
1238                         ExprLocation::InDoubleQuotedString,
1239                         &nodes[i + 1],
1240                         env,
1241                     )?);
1242                     i += 2;
1243                     continue;
1244                 }
1245             }
1247             result.push(Self::p_expr_with_loc(
1248                 ExprLocation::InDoubleQuotedString,
1249                 node,
1250                 env,
1251             )?);
1252             i += 1;
1253         }
1254         Ok(result)
1255     }
1257     fn p_expr_l(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Expr<,>) {
1258         Self::p_expr_l_with_loc(ExprLocation::TopLevel, node, env)
1259     }
1261     fn p_expr_l_with_loc(
1262         loc: ExprLocation,
1263         node: &Syntax<T, V>,
1264         env: &mut Env,
1265     ) -> ret_aast!(Expr<,>) {
1266         let p_expr = |n: &Syntax<T, V>, e: &mut Env| -> ret_aast!(Expr<,>) {
1267             Self::p_expr_with_loc(loc, n, e)
1268         };
1269         Ok(aast::Expr::new(
1270             Self::p_pos(node, env),
1271             E_::ExprList(Self::could_map(p_expr, node, env)?),
1272         ))
1273     }
1275     #[inline]
1276     fn p_expr(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Expr<,>) {
1277         Self::p_expr_with_loc(ExprLocation::TopLevel, node, env)
1278     }
1280     #[inline]
1281     fn p_expr_with_loc(
1282         location: ExprLocation,
1283         node: &Syntax<T, V>,
1284         env: &mut Env,
1285     ) -> ret_aast!(Expr<,>) {
1286         Self::p_expr_impl(location, node, env, None)
1287     }
1289     fn p_expr_impl(
1290         location: ExprLocation,
1291         node: &Syntax<T, V>,
1292         env: &mut Env,
1293         parent_pos: Option<Pos>,
1294     ) -> ret_aast!(Expr<,>) {
1295         match &node.syntax {
1296             BracedExpression(c) => {
1297                 let expr = &c.braced_expression_expression;
1298                 let inner = Self::p_expr_impl(location, expr, env, parent_pos)?;
1299                 let inner_pos = &inner.0;
1300                 let inner_expr_ = &inner.1;
1301                 use E_::*;
1302                 match inner_expr_ {
1303                     Lvar(_) | String(_) | Int(_) | Float(_) => Ok(inner),
1304                     _ => Ok(aast::Expr::new(
1305                         inner_pos.clone(),
1306                         E_::mk_braced_expr(inner),
1307                     )),
1308                 }
1309             }
1310             ParenthesizedExpression(c) => Self::p_expr_impl(
1311                 location,
1312                 &c.parenthesized_expression_expression,
1313                 env,
1314                 parent_pos,
1315             ),
1316             _ => {
1317                 let pos = Self::p_pos(node, env);
1318                 let expr_ = Self::p_expr_impl_(location, node, env, parent_pos)?;
1319                 Ok(aast::Expr::new(pos, expr_))
1320             }
1321         }
1322     }
1324     fn p_expr_lit(
1325         location: ExprLocation,
1326         parent: &Syntax<T, V>,
1327         expr: &Syntax<T, V>,
1328         env: &mut Env,
1329     ) -> ret_aast!(Expr_<,>) {
1330         match &expr.syntax {
1331             Token(_) => {
1332                 let s = expr.text(env.indexed_source_text.source_text());
1333                 match (location, Self::token_kind(expr)) {
1334                     (ExprLocation::InDoubleQuotedString, _) if env.codegen() => {
1335                         Ok(E_::String(Self::mk_str(expr, env, Self::unesc_dbl, s)))
1336                     }
1337                     (ExprLocation::InBacktickedString, _) if env.codegen() => {
1338                         Ok(E_::String(Self::mk_str(expr, env, unescape_backtick, s)))
1339                     }
1340                     (_, Some(TK::OctalLiteral))
1341                         if env.is_typechecker() && !Self::is_num_octal_lit(s) =>
1342                     {
1343                         Self::raise_parsing_error(
1344                             parent,
1345                             env,
1346                             &syntax_error::invalid_octal_integer,
1347                         );
1348                         Self::missing_syntax(None, "octal", expr, env)
1349                     }
1350                     (_, Some(TK::DecimalLiteral))
1351                     | (_, Some(TK::OctalLiteral))
1352                     | (_, Some(TK::HexadecimalLiteral))
1353                     | (_, Some(TK::BinaryLiteral)) => Ok(E_::Int(s.replace("_", ""))),
1354                     (_, Some(TK::FloatingLiteral)) => Ok(E_::Float(String::from(s))),
1355                     (_, Some(TK::SingleQuotedStringLiteral)) => {
1356                         Ok(E_::String(Self::mk_str(expr, env, unescape_single, s)))
1357                     }
1358                     (_, Some(TK::DoubleQuotedStringLiteral)) => {
1359                         Ok(E_::String(Self::mk_str(expr, env, unescape_double, s)))
1360                     }
1361                     (_, Some(TK::HeredocStringLiteral)) => {
1362                         Ok(E_::String(Self::mk_str(expr, env, unescape_heredoc, s)))
1363                     }
1364                     (_, Some(TK::NowdocStringLiteral)) => {
1365                         Ok(E_::String(Self::mk_str(expr, env, unescape_nowdoc, s)))
1366                     }
1367                     (_, Some(TK::NullLiteral)) => {
1368                         // TODO: Handle Lint
1369                         Ok(E_::Null)
1370                     }
1371                     (_, Some(TK::BooleanLiteral)) => {
1372                         // TODO: Handle Lint
1373                         if s.eq_ignore_ascii_case("false") {
1374                             Ok(E_::False)
1375                         } else if s.eq_ignore_ascii_case("true") {
1376                             Ok(E_::True)
1377                         } else {
1378                             Self::missing_syntax(None, &format!("boolean (not: {})", s), expr, env)
1379                         }
1380                     }
1381                     _ => Self::missing_syntax(None, "literal", expr, env),
1382                 }
1383             }
1384             SyntaxList(ts) => Ok(E_::String2(Self::p_string2(ts.as_slice(), env)?)),
1385             _ => Self::missing_syntax(None, "literal expressoin", expr, env),
1386         }
1387     }
1389     fn p_expr_with_loc_(
1390         location: ExprLocation,
1391         node: &Syntax<T, V>,
1392         env: &mut Env,
1393     ) -> ret_aast!(Expr_<,>) {
1394         Self::p_expr_impl_(location, node, env, None)
1395     }
1397     fn p_expr_impl_(
1398         location: ExprLocation,
1399         node: &Syntax<T, V>,
1400         env: &mut Env,
1401         parent_pos: Option<Pos>,
1402     ) -> ret_aast!(Expr_<,>) {
1403         use aast::Expr as E;
1404         let split_args_varargs = |arg_list_node: &Syntax<T, V>,
1405                                   e: &mut Env|
1406          -> ret!((Vec<aast!(Expr<,>)>, Vec<aast!(Expr<,>)>)) {
1407             let mut arg_list = Self::as_list(arg_list_node);
1408             if let Some(last_arg) = arg_list.last() {
1409                 if let DecoratedExpression(c) = &last_arg.syntax {
1410                     if Self::token_kind(&c.decorated_expression_decorator) == Some(TK::DotDotDot) {
1411                         let _ = arg_list.pop();
1412                         let args: std::result::Result<Vec<_>, _> =
1413                             arg_list.iter().map(|a| Self::p_expr(a, e)).collect();
1414                         let args = args?;
1415                         let vararg = Self::p_expr(&c.decorated_expression_expression, e)?;
1416                         return Ok((args, vec![vararg]));
1417                     }
1418                 }
1419             }
1420             Ok((Self::could_map(Self::p_expr, arg_list_node, e)?, vec![]))
1421         };
1422         let mk_lid = |p: Pos, s: String| aast::Lid(p, (0, s));
1423         let mk_name_lid = |name: &Syntax<T, V>, env: &mut Env| {
1424             let name = Self::pos_name(name, env)?;
1425             Ok(mk_lid(name.0, name.1))
1426         };
1427         let mk_lvar = |name: &Syntax<T, V>, env: &mut Env| Ok(E_::mk_lvar(mk_name_lid(name, env)?));
1428         let mk_id_expr = |name: aast!(Sid)| E::new(name.0.clone(), E_::mk_id(name));
1429         let p_intri_expr = |kw, ty, v, e: &mut Env| {
1430             let hints = Self::expand_type_args(ty, e)?;
1431             let hints = Self::check_intrinsic_type_arg_varity(node, e, hints);
1432             Ok(E_::mk_collection(
1433                 Self::pos_name(kw, e)?,
1434                 hints,
1435                 Self::could_map(Self::p_afield, v, e)?,
1436             ))
1437         };
1438         let p_special_call =
1439             |recv: &Syntax<T, V>, args: &Syntax<T, V>, e: &mut Env| -> ret_aast!(Expr_<,>) {
1440                 let pos_if_has_parens = match &recv.syntax {
1441                     ParenthesizedExpression(_) => Some(Self::p_pos(recv, e)),
1442                     _ => None,
1443                 };
1444                 let recv = Self::p_expr(recv, e)?;
1445                 let recv = match (&recv.1, pos_if_has_parens) {
1446                     (E_::ObjGet(_), Some(p)) => E::new(p, E_::mk_parenthesized_expr(recv)),
1447                     (E_::ClassGet(_), Some(p)) => E::new(p, E_::mk_parenthesized_expr(recv)),
1448                     _ => recv,
1449                 };
1450                 let (args, varargs) = split_args_varargs(args, e)?;
1451                 Ok(E_::mk_call(
1452                     aast::CallType::Cnormal,
1453                     recv,
1454                     vec![],
1455                     args,
1456                     varargs,
1457                 ))
1458             };
1459         let p_obj_get = |recv: &Syntax<T, V>,
1460                          op: &Syntax<T, V>,
1461                          name: &Syntax<T, V>,
1462                          e: &mut Env|
1463          -> ret_aast!(Expr_<,>) {
1464             if recv.is_object_creation_expression() && !e.codegen() {
1465                 Self::raise_parsing_error(recv, e, &syntax_error::invalid_constructor_method_call);
1466             }
1467             let recv = Self::p_expr(recv, e)?;
1468             let name = Self::p_expr_with_loc(ExprLocation::MemberSelect, name, e)?;
1469             let op = Self::p_null_flavor(op, e)?;
1470             Ok(E_::mk_obj_get(recv, name, op))
1471         };
1472         let pos = match parent_pos {
1473             None => Self::p_pos(node, env),
1474             Some(p) => p,
1475         };
1476         match &node.syntax {
1477             LambdaExpression(c) => {
1478                 let suspension_kind =
1479                     Self::mk_suspension_kind(node, env, &c.lambda_async, &c.lambda_coroutine);
1480                 let (params, ret) = match &c.lambda_signature.syntax {
1481                     LambdaSignature(c) => (
1482                         Self::could_map(Self::p_fun_param, &c.lambda_parameters, env)?,
1483                         Self::mp_optional(Self::p_hint, &c.lambda_type, env)?,
1484                     ),
1485                     Token(_) => {
1486                         let ast_defs::Id(p, n) = Self::pos_name(&c.lambda_signature, env)?;
1487                         (
1488                             vec![aast::FunParam {
1489                                 annotation: p.clone(),
1490                                 type_hint: aast::TypeHint((), None),
1491                                 is_reference: false,
1492                                 is_variadic: false,
1493                                 pos: p,
1494                                 name: n,
1495                                 expr: None,
1496                                 callconv: None,
1497                                 user_attributes: vec![],
1498                                 visibility: None,
1499                             }],
1500                             None,
1501                         )
1502                     }
1503                     _ => Self::missing_syntax(None, "lambda signature", &c.lambda_signature, env)?,
1504                 };
1505                 let (body, yield_) = if !c.lambda_body.is_compound_statement() {
1506                     Self::mp_yielding(Self::p_function_body, &c.lambda_body, env)?
1507                 } else {
1508                     let mut env1 = Env::clone_and_unset_toplevel_if_toplevel(env);
1509                     Self::mp_yielding(&Self::p_function_body, &c.lambda_body, env1.as_mut())?
1510                 };
1511                 let external = c.lambda_body.is_external();
1512                 let fun = aast::Fun_ {
1513                     span: pos.clone(),
1514                     annotation: (),
1515                     mode: Self::mode_annotation(env.file_mode()),
1516                     ret: aast::TypeHint((), ret),
1517                     name: ast_defs::Id(pos, String::from(";anonymous")),
1518                     tparams: vec![],
1519                     where_constraints: vec![],
1520                     body: aast::FuncBody {
1521                         ast: body,
1522                         annotation: (),
1523                     },
1524                     fun_kind: Self::mk_fun_kind(suspension_kind, yield_),
1525                     variadic: Self::determine_variadicity(&params),
1526                     params,
1527                     user_attributes: Self::p_user_attributes(&c.lambda_attribute_spec, env)?,
1528                     file_attributes: vec![],
1529                     external,
1530                     namespace: Self::mk_empty_ns_env(env),
1531                     doc_comment: None,
1532                     static_: false,
1533                 };
1534                 Ok(E_::mk_lfun(fun, vec![]))
1535             }
1536             BracedExpression(c) => {
1537                 Self::p_expr_with_loc_(location, &c.braced_expression_expression, env)
1538             }
1539             EmbeddedBracedExpression(c) => Self::p_expr_impl_(
1540                 location,
1541                 &c.embedded_braced_expression_expression,
1542                 env,
1543                 Some(pos),
1544             ),
1545             ParenthesizedExpression(c) => {
1546                 Self::p_expr_with_loc_(location, &c.parenthesized_expression_expression, env)
1547             }
1548             DictionaryIntrinsicExpression(c) => p_intri_expr(
1549                 &c.dictionary_intrinsic_keyword,
1550                 &c.dictionary_intrinsic_explicit_type,
1551                 &c.dictionary_intrinsic_members,
1552                 env,
1553             ),
1554             KeysetIntrinsicExpression(c) => p_intri_expr(
1555                 &c.keyset_intrinsic_keyword,
1556                 &c.keyset_intrinsic_explicit_type,
1557                 &c.keyset_intrinsic_members,
1558                 env,
1559             ),
1560             VectorIntrinsicExpression(c) => p_intri_expr(
1561                 &c.vector_intrinsic_keyword,
1562                 &c.vector_intrinsic_explicit_type,
1563                 &c.vector_intrinsic_members,
1564                 env,
1565             ),
1566             CollectionLiteralExpression(c) => {
1567                 let collection_name = &c.collection_literal_name;
1568                 let (collection_name, hints) = match &collection_name.syntax {
1569                     SimpleTypeSpecifier(c) => {
1570                         (Self::pos_name(&c.simple_type_specifier, env)?, None)
1571                     }
1572                     GenericTypeSpecifier(c) => {
1573                         let hints = Self::expand_type_args(&c.generic_argument_list, env)?;
1574                         let hints = Self::check_intrinsic_type_arg_varity(node, env, hints);
1575                         (Self::pos_name(&c.generic_class_type, env)?, hints)
1576                     }
1577                     _ => (Self::pos_name(collection_name, env)?, None),
1578                 };
1579                 Ok(E_::mk_collection(
1580                     collection_name,
1581                     hints,
1582                     Self::could_map(Self::p_afield, &c.collection_literal_initializers, env)?,
1583                 ))
1584             }
1585             VarrayIntrinsicExpression(c) => {
1586                 let hints = Self::expand_type_args(&c.varray_intrinsic_explicit_type, env)?;
1587                 let hints = Self::check_intrinsic_type_arg_varity(node, env, hints);
1588                 let targ = match hints {
1589                     Some(aast::CollectionTarg::CollectionTV(ty)) => Some(ty),
1590                     None => None,
1591                     _ => Self::missing_syntax(
1592                         None,
1593                         "VarrayIntrinsicExpression type args",
1594                         node,
1595                         env,
1596                     )?,
1597                 };
1598                 Ok(E_::mk_varray(
1599                     targ,
1600                     Self::could_map(Self::p_expr, &c.varray_intrinsic_members, env)?,
1601                 ))
1602             }
1603             DarrayIntrinsicExpression(c) => {
1604                 let hints = Self::expand_type_args(&c.darray_intrinsic_explicit_type, env)?;
1605                 let hints = Self::check_intrinsic_type_arg_varity(node, env, hints);
1606                 match hints {
1607                     Some(aast::CollectionTarg::CollectionTKV(tk, tv)) => Ok(E_::mk_darray(
1608                         Some((tk, tv)),
1609                         Self::could_map(Self::p_member, &c.darray_intrinsic_members, env)?,
1610                     )),
1611                     None => Ok(E_::mk_darray(
1612                         None,
1613                         Self::could_map(Self::p_member, &c.darray_intrinsic_members, env)?,
1614                     )),
1615                     _ => {
1616                         Self::missing_syntax(None, "DarrayIntrinsicExpression type args", node, env)
1617                     }
1618                 }
1619             }
1620             ArrayIntrinsicExpression(c) => {
1621                 /* TODO: Or tie in with other intrinsics and post-process to Array */
1622                 Ok(E_::Array(Self::could_map(
1623                     Self::p_afield,
1624                     &c.array_intrinsic_members,
1625                     env,
1626                 )?))
1627             }
1628             ArrayCreationExpression(c) => {
1629                 /* TODO: Or tie in with other intrinsics and post-process to Array */
1630                 Ok(E_::Array(Self::could_map(
1631                     Self::p_afield,
1632                     &c.array_creation_members,
1633                     env,
1634                 )?))
1635             }
1636             ListExpression(c) => {
1637                 /* TODO: Or tie in with other intrinsics and post-process to List */
1638                 let p_binder_or_ignore = |n: &Syntax<T, V>, e: &mut Env| -> ret_aast!(Expr<,>) {
1639                     match &n.syntax {
1640                         Missing => Ok(E::new(e.mk_none_pos(), E_::Omitted)),
1641                         _ => Self::p_expr(n, e),
1642                     }
1643                 };
1644                 Ok(E_::List(Self::could_map(
1645                     &p_binder_or_ignore,
1646                     &c.list_members,
1647                     env,
1648                 )?))
1649             }
1650             EvalExpression(c) => p_special_call(&c.eval_keyword, &c.eval_argument, env),
1651             IssetExpression(c) => p_special_call(&c.isset_keyword, &c.isset_argument_list, env),
1652             TupleExpression(c) => {
1653                 p_special_call(&c.tuple_expression_keyword, &c.tuple_expression_items, env)
1654             }
1655             FunctionCallExpression(c) => {
1656                 let recv = &c.function_call_receiver;
1657                 let args = &c.function_call_argument_list;
1658                 let get_hhas_adata = || {
1659                     if Self::text_str(recv, env) == "__hhas_adata" {
1660                         if let SyntaxList(l) = &args.syntax {
1661                             if let Some(li) = l.first() {
1662                                 if let ListItem(i) = &li.syntax {
1663                                     if let LiteralExpression(le) = &i.list_item.syntax {
1664                                         let expr = &le.literal_expression;
1665                                         if Self::token_kind(expr) == Some(TK::NowdocStringLiteral) {
1666                                             return Some(expr);
1667                                         }
1668                                     }
1669                                 }
1670                             }
1671                         }
1672                     }
1673                     None
1674                 };
1675                 match get_hhas_adata() {
1676                     Some(expr) => {
1677                         let literal_expression_pos = Self::p_pos(expr, env);
1678                         let s = extract_unquoted_string(Self::text_str(expr, env), 0, expr.width())
1679                             .map_err(|e| Error::Failwith(e.msg))?;
1680                         Ok(E_::mk_call(
1681                             aast::CallType::Cnormal,
1682                             Self::p_expr(recv, env)?,
1683                             vec![],
1684                             vec![E::new(literal_expression_pos, E_::String(s))],
1685                             vec![],
1686                         ))
1687                     }
1688                     None => {
1689                         let targs = match (&recv.syntax, &c.function_call_type_args.syntax) {
1690                             (_, TypeArguments(c)) => {
1691                                 Self::could_map(Self::p_targ, &c.type_arguments_types, env)?
1692                             }
1693                             /* TODO might not be needed */
1694                             (GenericTypeSpecifier(c), _) => match &c.generic_argument_list.syntax {
1695                                 TypeArguments(c) => {
1696                                     Self::could_map(Self::p_targ, &c.type_arguments_types, env)?
1697                                 }
1698                                 _ => vec![],
1699                             },
1700                             _ => vec![],
1701                         };
1703                         /* preserve parens on receiver of call expression
1704                         to allow distinguishing between
1705                         ($a->b)() // invoke on callable property
1706                         $a->b()   // method call */
1707                         let pos_if_has_parens = match &recv.syntax {
1708                             ParenthesizedExpression(_) => Some(Self::p_pos(recv, env)),
1709                             _ => None,
1710                         };
1711                         let recv = Self::p_expr(recv, env)?;
1712                         let recv = match (&recv.1, pos_if_has_parens) {
1713                             (E_::ObjGet(_), Some(p)) => E::new(p, E_::mk_parenthesized_expr(recv)),
1714                             (E_::ClassGet(_), Some(p)) => {
1715                                 E::new(p, E_::mk_parenthesized_expr(recv))
1716                             }
1717                             _ => recv,
1718                         };
1719                         let (args, varargs) = split_args_varargs(args, env)?;
1720                         Ok(E_::mk_call(
1721                             aast::CallType::Cnormal,
1722                             recv,
1723                             targs,
1724                             args,
1725                             varargs,
1726                         ))
1727                     }
1728                 }
1729             }
1730             QualifiedName(_) => {
1731                 if location.in_string() {
1732                     let ast_defs::Id(_, n) = Self::pos_qualified_name(node, env)?;
1733                     Ok(E_::String(n))
1734                 } else {
1735                     Ok(E_::mk_id(Self::pos_qualified_name(node, env)?))
1736                 }
1737             }
1738             VariableExpression(c) => Ok(E_::mk_lvar(Self::lid_from_pos_name(
1739                 pos,
1740                 &c.variable_expression,
1741                 env,
1742             )?)),
1743             PipeVariableExpression(_) => Ok(E_::mk_lvar(mk_lid(pos, String::from("$$")))),
1744             InclusionExpression(c) => Ok(E_::mk_import(
1745                 Self::p_import_flavor(&c.inclusion_require, env)?,
1746                 Self::p_expr(&c.inclusion_filename, env)?,
1747             )),
1748             MemberSelectionExpression(c) => {
1749                 p_obj_get(&c.member_object, &c.member_operator, &c.member_name, env)
1750             }
1751             SafeMemberSelectionExpression(c) => p_obj_get(
1752                 &c.safe_member_object,
1753                 &c.safe_member_operator,
1754                 &c.safe_member_name,
1755                 env,
1756             ),
1757             EmbeddedMemberSelectionExpression(c) => p_obj_get(
1758                 &c.embedded_member_object,
1759                 &c.embedded_member_operator,
1760                 &c.embedded_member_name,
1761                 env,
1762             ),
1763             PrefixUnaryExpression(_) | PostfixUnaryExpression(_) | DecoratedExpression(_) => {
1764                 let (operand, op, postfix) = match &node.syntax {
1765                     PrefixUnaryExpression(c) => {
1766                         (&c.prefix_unary_operand, &c.prefix_unary_operator, false)
1767                     }
1768                     PostfixUnaryExpression(c) => {
1769                         (&c.postfix_unary_operand, &c.postfix_unary_operator, true)
1770                     }
1771                     DecoratedExpression(c) => (
1772                         &c.decorated_expression_expression,
1773                         &c.decorated_expression_decorator,
1774                         false,
1775                     ),
1776                     _ => Self::missing_syntax(None, "unary exppr", node, env)?,
1777                 };
1779                 let expr = Self::p_expr(operand, env)?;
1780                 /**
1781                  * FFP does not destinguish between ++$i and $i++ on the level of token
1782                  * kind annotation. Prevent duplication by switching on `postfix` for
1783                  * the two operatores for which AST /does/ differentiate between
1784                  * fixities.
1785                  */
1786                 use ast_defs::Uop::*;
1787                 let mk_unop = |op, e| Ok(E_::mk_unop(op, e));
1788                 match Self::token_kind(op) {
1789                     Some(TK::PlusPlus) if postfix => mk_unop(Upincr, expr),
1790                     Some(TK::MinusMinus) if postfix => mk_unop(Updecr, expr),
1791                     Some(TK::PlusPlus) => mk_unop(Uincr, expr),
1792                     Some(TK::MinusMinus) => mk_unop(Udecr, expr),
1793                     Some(TK::Exclamation) => mk_unop(Unot, expr),
1794                     Some(TK::Tilde) => mk_unop(Utild, expr),
1795                     Some(TK::Plus) => mk_unop(Uplus, expr),
1796                     Some(TK::Minus) => mk_unop(Uminus, expr),
1797                     Some(TK::At) => {
1798                         if env.parser_options.po_disallow_silence {
1799                             Self::raise_parsing_error(op, env, &syntax_error::no_silence);
1800                         }
1801                         if env.codegen() {
1802                             mk_unop(Usilence, expr)
1803                         } else {
1804                             let expr =
1805                                 Self::p_expr_impl(ExprLocation::TopLevel, operand, env, Some(pos))?;
1806                             Ok(expr.1)
1807                         }
1808                     }
1809                     Some(TK::Inout) => Ok(E_::mk_callconv(ast_defs::ParamKind::Pinout, expr)),
1810                     Some(TK::Await) => Self::lift_await(pos, expr, env, location),
1811                     Some(TK::Suspend) => Ok(E_::mk_suspend(expr)),
1812                     Some(TK::Clone) => Ok(E_::mk_clone(expr)),
1813                     Some(TK::Print) => Ok(E_::mk_call(
1814                         aast::CallType::Cnormal,
1815                         E::new(
1816                             pos.clone(),
1817                             E_::mk_id(ast_defs::Id(pos, String::from("echo"))),
1818                         ),
1819                         vec![],
1820                         vec![expr],
1821                         vec![],
1822                     )),
1823                     Some(TK::Dollar) => {
1824                         let E(p, expr_) = expr;
1825                         match expr_ {
1826                             E_::String(s) | E_::Int(s) | E_::Float(s) => {
1827                                 if !env.codegen() {
1828                                     Self::raise_parsing_error(
1829                                         op,
1830                                         env,
1831                                         &syntax_error::invalid_variable_name,
1832                                     )
1833                                 }
1834                                 let id = String::with_capacity(1 + s.len()) + "$" + &s;
1835                                 let lid = aast::Lid(pos, (0, id));
1836                                 Ok(E_::mk_lvar(lid))
1837                             }
1838                             _ => {
1839                                 Self::raise_parsing_error(
1840                                     op,
1841                                     env,
1842                                     &syntax_error::invalid_variable_variable,
1843                                 );
1844                                 Ok(E_::Omitted)
1845                             }
1846                         }
1847                     }
1848                     _ => Self::missing_syntax(None, "unary operator", node, env),
1849                 }
1850             }
1851             BinaryExpression(c) => {
1852                 use ExprLocation::*;
1853                 let rlocation = if Self::token_kind(&c.binary_operator) == Some(TK::Equal) {
1854                     match location {
1855                         AsStatement => RightOfAssignment,
1856                         UsingStatement => RightOfAssignmentInUsingStatement,
1857                         _ => TopLevel,
1858                     }
1859                 } else {
1860                     TopLevel
1861                 };
1862                 // Ocaml evaluates right first then left, ordering will affect
1863                 // tmp var count in lifted await statement.
1864                 let right = Self::p_expr_with_loc(rlocation, &c.binary_right_operand, env)?;
1865                 let left = Self::p_expr(&c.binary_left_operand, env)?;
1866                 let bop_ast_node = Self::p_bop(pos, &c.binary_operator, left, right, env)?;
1867                 if let E_::Binop(bop) = &bop_ast_node {
1868                     if let (ast_defs::Bop::Eq(_), lhs, _) = bop.as_ref() {
1869                         Self::check_lvalue(lhs, env);
1870                     }
1871                 }
1872                 Ok(bop_ast_node)
1873             }
1874             Token(t) => {
1875                 use ExprLocation::*;
1876                 match (location, t.kind()) {
1877                     (MemberSelect, TK::Variable) => mk_lvar(node, env),
1878                     (InDoubleQuotedString, _) => Ok(E_::String(Self::wrap_unescaper(
1879                         Self::unesc_dbl,
1880                         Self::text_str(node, env),
1881                     )?)),
1882                     (InBacktickedString, _) => Ok(E_::String(Self::wrap_unescaper(
1883                         unescape_backtick,
1884                         Self::text_str(node, env),
1885                     )?)),
1886                     (MemberSelect, _)
1887                     | (TopLevel, _)
1888                     | (AsStatement, _)
1889                     | (UsingStatement, _)
1890                     | (RightOfAssignment, _)
1891                     | (RightOfAssignmentInUsingStatement, _)
1892                     | (RightOfReturn, _) => Ok(E_::mk_id(Self::pos_name(node, env)?)),
1893                 }
1894             }
1895             YieldExpression(c) => {
1896                 use ExprLocation::*;
1897                 env.saw_yield = true;
1898                 if location != AsStatement
1899                     && location != RightOfAssignment
1900                     && location != RightOfAssignmentInUsingStatement
1901                 {
1902                     Self::raise_parsing_error(node, env, &syntax_error::invalid_yield);
1903                 }
1904                 if c.yield_operand.text(env.source_text()) == "break" {
1905                     Ok(E_::YieldBreak)
1906                 } else if c.yield_operand.is_missing() {
1907                     Ok(E_::mk_yield(aast::Afield::AFvalue(E::new(pos, E_::Null))))
1908                 } else {
1909                     Ok(E_::mk_yield(Self::p_afield(&c.yield_operand, env)?))
1910                 }
1911             }
1912             YieldFromExpression(c) => {
1913                 use ExprLocation::*;
1914                 env.saw_yield = true;
1915                 if location != AsStatement
1916                     && location != RightOfAssignment
1917                     && location != RightOfAssignmentInUsingStatement
1918                     && location != RightOfReturn
1919                 {
1920                     Self::raise_parsing_error(node, env, &syntax_error::invalid_yield_from);
1921                 }
1922                 Ok(E_::mk_yield_from(Self::p_expr(&c.yield_from_operand, env)?))
1923             }
1924             DefineExpression(c) => {
1925                 let name = Self::pos_name(&c.define_keyword, env)?;
1926                 Ok(E_::mk_call(
1927                     aast_defs::CallType::Cnormal,
1928                     mk_id_expr(name),
1929                     vec![],
1930                     Self::as_list(&c.define_argument_list)
1931                         .iter()
1932                         .map(|x| Self::p_expr(x, env))
1933                         .collect::<std::result::Result<Vec<_>, _>>()?,
1934                     vec![],
1935                 ))
1936             }
1937             ScopeResolutionExpression(c) => {
1938                 let qual = Self::p_expr(&c.scope_resolution_qualifier, env)?;
1939                 let qual = if env.codegen() {
1940                     qual
1941                 } else if let E_::Lvar(a) = qual.1 {
1942                     let pos = qual.0;
1943                     E::new(pos.clone(), E_::mk_id(ast_defs::Id(pos, (a.1).1)))
1944                 } else {
1945                     qual
1946                 };
1947                 if let E_::Id(id) = &qual.1 {
1948                     Self::fail_if_invalid_reified_generic(node, env, &id.1);
1949                 }
1950                 match &c.scope_resolution_name.syntax {
1951                     Token(token) if token.kind() == TK::Variable => {
1952                         let ast_defs::Id(p, name) = Self::pos_name(&c.scope_resolution_name, env)?;
1953                         Ok(E_::mk_class_get(
1954                             aast::ClassId(pos, aast::ClassId_::CIexpr(qual)),
1955                             aast::ClassGetExpr::CGstring((p, name)),
1956                         ))
1957                     }
1958                     _ => {
1959                         let E(p, expr_) = Self::p_expr(&c.scope_resolution_name, env)?;
1960                         match expr_ {
1961                             E_::String(id) => Ok(E_::mk_class_const(
1962                                 aast::ClassId(pos, aast::ClassId_::CIexpr(qual)),
1963                                 (p, id),
1964                             )),
1965                             E_::Id(id) => {
1966                                 let ast_defs::Id(p, n) = *id;
1967                                 Ok(E_::mk_class_const(
1968                                     aast::ClassId(pos, aast::ClassId_::CIexpr(qual)),
1969                                     (p, n),
1970                                 ))
1971                             }
1972                             E_::Lvar(id) => {
1973                                 let aast::Lid(p, (_, n)) = *id;
1974                                 Ok(E_::mk_class_get(
1975                                     aast::ClassId(pos, aast::ClassId_::CIexpr(qual)),
1976                                     aast::ClassGetExpr::CGstring((p, n)),
1977                                 ))
1978                             }
1979                             _ => Ok(E_::mk_class_get(
1980                                 aast::ClassId(pos, aast::ClassId_::CIexpr(qual)),
1981                                 aast::ClassGetExpr::CGexpr(E(p, expr_)),
1982                             )),
1983                         }
1984                     }
1985                 }
1986             }
1987             CastExpression(c) => Ok(E_::mk_cast(
1988                 Self::p_hint(&c.cast_type, env)?,
1989                 Self::p_expr(&c.cast_operand, env)?,
1990             )),
1991             ConditionalExpression(c) => {
1992                 let alter = Self::p_expr(&c.conditional_alternative, env)?;
1993                 let consequence = Self::mp_optional(Self::p_expr, &c.conditional_consequence, env)?;
1994                 let condition = Self::p_expr(&c.conditional_test, env)?;
1995                 Ok(E_::mk_eif(condition, consequence, alter))
1996             }
1997             SubscriptExpression(c) => Ok(E_::mk_array_get(
1998                 Self::p_expr(&c.subscript_receiver, env)?,
1999                 Self::mp_optional(Self::p_expr, &c.subscript_index, env)?,
2000             )),
2001             EmbeddedSubscriptExpression(c) => Ok(E_::mk_array_get(
2002                 Self::p_expr(&c.embedded_subscript_receiver, env)?,
2003                 Self::mp_optional(
2004                     |n, e| Self::p_expr_with_loc(location, n, e),
2005                     &c.embedded_subscript_index,
2006                     env,
2007                 )?,
2008             )),
2009             ShapeExpression(c) => Ok(E_::Shape(Self::could_map(
2010                 |n: &Syntax<T, V>, e: &mut Env| {
2011                     Self::mp_shape_expression_field(&Self::p_expr, n, e)
2012                 },
2013                 &c.shape_expression_fields,
2014                 env,
2015             )?)),
2016             ObjectCreationExpression(c) => {
2017                 Self::p_expr_impl_(location, &c.object_creation_object, env, Some(pos))
2018             }
2019             ConstructorCall(c) => {
2020                 let (args, varargs) = split_args_varargs(&c.constructor_call_argument_list, env)?;
2021                 let (e, hl) = match &c.constructor_call_type.syntax {
2022                     GenericTypeSpecifier(c) => {
2023                         let name = Self::pos_name(&c.generic_class_type, env)?;
2024                         let hints = match &c.generic_argument_list.syntax {
2025                             TypeArguments(c) => {
2026                                 Self::could_map(Self::p_targ, &c.type_arguments_types, env)?
2027                             }
2028                             _ => Self::missing_syntax(
2029                                 None,
2030                                 "generic type arguments",
2031                                 &c.generic_argument_list,
2032                                 env,
2033                             )?,
2034                         };
2035                         (mk_id_expr(name), hints)
2036                     }
2037                     SimpleTypeSpecifier(_) => {
2038                         let name = Self::pos_name(&c.constructor_call_type, env)?;
2039                         (mk_id_expr(name), vec![])
2040                     }
2041                     _ => (Self::p_expr(&c.constructor_call_type, env)?, vec![]),
2042                 };
2043                 if let E_::Id(name) = &e.1 {
2044                     Self::fail_if_invalid_reified_generic(node, env, &name.1);
2045                     Self::fail_if_invalid_class_creation(node, env, &name.1);
2046                 }
2047                 Ok(E_::mk_new(
2048                     aast::ClassId(pos.clone(), aast::ClassId_::CIexpr(e)),
2049                     hl,
2050                     args,
2051                     varargs,
2052                     pos,
2053                 ))
2054             }
2055             GenericTypeSpecifier(c) => {
2056                 if !c.generic_argument_list.is_missing() {
2057                     Self::raise_parsing_error(
2058                         &c.generic_argument_list,
2059                         env,
2060                         &syntax_error::targs_not_allowed,
2061                     )
2062                 }
2063                 let name = Self::pos_name(&c.generic_class_type, env)?;
2064                 Ok(E_::mk_id(name))
2065             }
2066             RecordCreationExpression(c) => {
2067                 let id = Self::pos_name(&c.record_creation_type, env)?;
2068                 let is_record_array =
2069                     Self::token_kind(&c.record_creation_array_token) == Some(TK::At);
2070                 Ok(E_::mk_record(
2071                     id,
2072                     is_record_array,
2073                     Self::could_map(Self::p_member, &c.record_creation_members, env)?,
2074                 ))
2075             }
2076             LiteralExpression(c) => Self::p_expr_lit(location, node, &c.literal_expression, env),
2077             PrefixedStringExpression(c) => {
2078                 /* Temporarily allow only`re`- prefixed strings */
2079                 let name_text = Self::text(&c.prefixed_string_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.prefixed_string_str, env)?,
2086                 ))
2087             }
2088             IsExpression(c) => Ok(E_::mk_is(
2089                 Self::p_expr(&c.is_left_operand, env)?,
2090                 Self::p_hint(&c.is_right_operand, env)?,
2091             )),
2092             AsExpression(c) => Ok(E_::mk_as(
2093                 Self::p_expr(&c.as_left_operand, env)?,
2094                 Self::p_hint(&c.as_right_operand, env)?,
2095                 false,
2096             )),
2097             NullableAsExpression(c) => Ok(E_::mk_as(
2098                 Self::p_expr(&c.nullable_as_left_operand, env)?,
2099                 Self::p_hint(&c.nullable_as_right_operand, env)?,
2100                 true,
2101             )),
2102             AnonymousFunction(c) => {
2103                 if env.parser_options.po_disable_static_closures
2104                     && Self::token_kind(&c.anonymous_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: &Syntax<T, V>, e: &mut Env| match &n.syntax {
2113                     Token(_) => mk_name_lid(n, e),
2114                     _ => Self::missing_syntax(None, "use variable", n, e),
2115                 };
2116                 let p_use = |n: &Syntax<T, V>, e: &mut Env| match &n.syntax {
2117                     AnonymousFunctionUseClause(c) => {
2118                         Self::could_map(p_arg, &c.anonymous_use_variables, e)
2119                     }
2120                     _ => Ok(vec![]),
2121                 };
2122                 let suspension_kind = Self::mk_suspension_kind(
2123                     node,
2124                     env,
2125                     &c.anonymous_async_keyword,
2126                     &c.anonymous_coroutine_keyword,
2127                 );
2128                 let (body, yield_) = {
2129                     let mut env1 = Env::clone_and_unset_toplevel_if_toplevel(env);
2130                     Self::mp_yielding(&Self::p_function_body, &c.anonymous_body, env1.as_mut())?
2131                 };
2132                 let doc_comment =
2133                     Self::extract_docblock(node, env).or_else(|| env.top_docblock().clone());
2134                 let user_attributes = Self::p_user_attributes(&c.anonymous_attribute_spec, env)?;
2135                 let external = c.anonymous_body.is_external();
2136                 let params = Self::could_map(Self::p_fun_param, &c.anonymous_parameters, env)?;
2137                 let name_pos = Self::p_function(node, env);
2138                 let fun = aast::Fun_ {
2139                     span: Self::p_pos(node, env),
2140                     annotation: (),
2141                     mode: Self::mode_annotation(env.file_mode()),
2142                     ret: aast::TypeHint(
2143                         (),
2144                         Self::mp_optional(Self::p_hint, &c.anonymous_type, env)?,
2145                     ),
2146                     name: ast_defs::Id(name_pos, String::from(";anonymous")),
2147                     tparams: vec![],
2148                     where_constraints: vec![],
2149                     body: aast::FuncBody {
2150                         ast: body,
2151                         annotation: (),
2152                     },
2153                     fun_kind: Self::mk_fun_kind(suspension_kind, yield_),
2154                     variadic: Self::determine_variadicity(&params),
2155                     params,
2156                     user_attributes,
2157                     file_attributes: vec![],
2158                     external,
2159                     namespace: Self::mk_empty_ns_env(env),
2160                     doc_comment,
2161                     static_: !c.anonymous_static_keyword.is_missing(),
2162                 };
2163                 let uses = p_use(&c.anonymous_use, env).unwrap_or_else(|_| vec![]);
2164                 Ok(E_::mk_efun(fun, uses))
2165             }
2166             AwaitableCreationExpression(c) => {
2167                 let suspension_kind =
2168                     Self::mk_suspension_kind(node, env, &c.awaitable_async, &c.awaitable_coroutine);
2169                 let (blk, yld) = Self::mp_yielding(
2170                     &Self::p_function_body,
2171                     &c.awaitable_compound_statement,
2172                     env,
2173                 )?;
2174                 let user_attributes = Self::p_user_attributes(&c.awaitable_attribute_spec, env)?;
2175                 let external = c.awaitable_compound_statement.is_external();
2176                 let name_pos = Self::p_function(node, env);
2177                 let body = aast::Fun_ {
2178                     span: pos.clone(),
2179                     annotation: (),
2180                     mode: Self::mode_annotation(env.file_mode()),
2181                     ret: aast::TypeHint((), None),
2182                     name: ast_defs::Id(name_pos, String::from(";anonymous")),
2183                     tparams: vec![],
2184                     where_constraints: vec![],
2185                     body: aast::FuncBody {
2186                         ast: if blk.len() == 0 {
2187                             let pos = Self::p_pos(&c.awaitable_compound_statement, env);
2188                             vec![aast::Stmt::noop(pos)]
2189                         } else {
2190                             blk
2191                         },
2192                         annotation: (),
2193                     },
2194                     fun_kind: Self::mk_fun_kind(suspension_kind, yld),
2195                     variadic: Self::determine_variadicity(&[]),
2196                     params: vec![],
2197                     user_attributes,
2198                     file_attributes: vec![],
2199                     external,
2200                     namespace: Self::mk_empty_ns_env(env),
2201                     doc_comment: None,
2202                     static_: false,
2203                 };
2204                 Ok(E_::mk_call(
2205                     aast::CallType::Cnormal,
2206                     E::new(pos, E_::mk_lfun(body, vec![])),
2207                     vec![],
2208                     vec![],
2209                     vec![],
2210                 ))
2211             }
2212             XHPExpression(c) if c.xhp_open.is_xhp_open() => {
2213                 if let XHPOpen(c1) = &c.xhp_open.syntax {
2214                     let name = Self::pos_name(&c1.xhp_open_name, env)?;
2215                     let attrs = Self::could_map(Self::p_xhp_attr, &c1.xhp_open_attributes, env)?;
2216                     let exprs = Self::aggregate_xhp_tokens(&c.xhp_body)?
2217                         .iter()
2218                         .map(|n| match n {
2219                             Either::Left(n) => Self::p_xhp_embedded(Self::unesc_xhp, &n, env),
2220                             Either::Right(n) => Self::p_xhp_embedded(Self::unesc_xhp, n, env),
2221                         })
2222                         .collect::<std::result::Result<Vec<_>, _>>()?;
2224                     Ok(E_::mk_xml(
2225                         // TODO: update pos_name to support prefix
2226                         ast_defs::Id(name.0, String::from(":") + &name.1),
2227                         attrs,
2228                         exprs,
2229                     ))
2230                 } else {
2231                     Self::failwith("expect xhp open")
2232                 }
2233             }
2234             PocketAtomExpression(c) => Ok(E_::PUAtom(
2235                 Self::pos_name(&c.pocket_atom_expression, env)?.1,
2236             )),
2237             PocketIdentifierExpression(c) => {
2238                 let mk_class_id = |e: aast!(Expr<,>)| aast::ClassId(pos, aast::ClassId_::CIexpr(e));
2239                 let qual = Self::p_expr(&c.pocket_identifier_qualifier, env)?;
2240                 let qual = if env.codegen() {
2241                     mk_class_id(qual)
2242                 } else if let E_::Lvar(a) = qual.1 {
2243                     let p = qual.0;
2244                     let expr = E::new(p.clone(), E_::mk_id(ast_defs::Id(p, (a.1).1)));
2245                     mk_class_id(expr)
2246                 } else {
2247                     mk_class_id(qual)
2248                 };
2249                 let E(p, expr_) = Self::p_expr(&c.pocket_identifier_field, env)?;
2250                 let field = match expr_ {
2251                     E_::String(id) => (p, id),
2252                     E_::Id(id) => {
2253                         let ast_defs::Id(p, n) = *id;
2254                         (p, n)
2255                     }
2256                     _ => Self::missing_syntax(None, "PocketIdentifierExpression field", node, env)?,
2257                 };
2258                 let E(p, expr_) = Self::p_expr(&c.pocket_identifier_name, env)?;
2259                 let name = match expr_ {
2260                     E_::String(id) => (p, id),
2261                     E_::Id(id) => {
2262                         let ast_defs::Id(p, n) = *id;
2263                         (p, n)
2264                     }
2265                     _ => Self::missing_syntax(None, "PocketIdentifierExpression name", node, env)?,
2266                 };
2267                 Ok(E_::mk_puidentifier(qual, field, name))
2268             }
2269             _ => Self::missing_syntax(Some(E_::Null), "expression", node, env),
2270         }
2271     }
2273     fn check_lvalue(aast::Expr(p, expr_): &aast!(Expr<,>), env: &mut Env) {
2274         use E_::*;
2275         let mut raise = |s| Self::raise_parsing_error_pos(p, env, s);
2276         match expr_ {
2277             ObjGet(og) => match og.as_ref() {
2278                 (_, aast::Expr(_, Id(_)), ast_defs::OgNullFlavor::OGNullsafe) => {
2279                     raise("?-> syntax is not supported for lvalues")
2280                 }
2281                 (_, aast::Expr(_, Id(sid)), _) if sid.1.as_bytes()[0] == b':' => {
2282                     raise("->: syntax is not supported for lvalues")
2283                 }
2284                 _ => {}
2285             },
2286             ArrayGet(ag) => {
2287                 if let ClassConst(_) = (ag.0).1 {
2288                     raise("Array-like class consts are not valid lvalues");
2289                 }
2290             }
2291             Call(c) => match &(c.1).1 {
2292                 Id(sid) if sid.1 == "tuple" => {
2293                     raise("Tuple cannot be used as an lvalue. Maybe you meant list?")
2294                 }
2295                 _ => raise("Invalid lvalue"),
2296             },
2297             List(l) => {
2298                 for i in l.iter() {
2299                     Self::check_lvalue(i, env);
2300                 }
2301             }
2302             Array(_) | Darray(_) | Varray(_) | Shape(_) | Collection(_) | Record(_) | Null
2303             | True | False | Id(_) | Clone(_) | ClassConst(_) | Int(_) | Float(_)
2304             | PrefixedString(_) | String(_) | String2(_) | Yield(_) | YieldBreak | YieldFrom(_)
2305             | Await(_) | Suspend(_) | ExprList(_) | Cast(_) | Unop(_) | Binop(_) | Eif(_)
2306             | New(_) | Efun(_) | Lfun(_) | Xml(_) | Import(_) | Pipe(_) | Callconv(_) | Is(_)
2307             | As(_) | ParenthesizedExpr(_) | PUIdentifier(_) => raise("Invalid lvalue"),
2308             _ => {}
2309         }
2310     }
2312     fn p_xhp_embedded<F>(escaper: F, node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Expr<,>)
2313     where
2314         F: FnOnce(&[u8]) -> Vec<u8>,
2315     {
2316         if let Some(kind) = Self::token_kind(node) {
2317             if env.codegen() && TK::XHPStringLiteral == kind {
2318                 let p = Self::p_pos(node, env);
2319                 /* for XHP string literals (attribute values) just extract
2320                 value from quotes and decode HTML entities  */
2321                 let text = html_entities::decode(&Self::get_quoted_content(
2322                     node.full_text(env.source_text()),
2323                 ));
2324                 Ok(aast::Expr::new(p, E_::make_string(text)))
2325             } else if env.codegen() && TK::XHPBody == kind {
2326                 let p = Self::p_pos(node, env);
2327                 /* for XHP body - only decode HTML entities */
2328                 let text =
2329                     html_entities::decode(&Self::unesc_xhp(node.full_text(env.source_text())));
2330                 Ok(aast::Expr::new(p, E_::make_string(text)))
2331             } else {
2332                 let p = Self::p_pos(node, env);
2333                 let s = escaper(node.full_text(env.source_text()));
2334                 Ok(aast::Expr::new(p, E_::make_string(s)))
2335             }
2336         } else {
2337             let expr = Self::p_expr(node, env)?;
2338             match expr.1 {
2339                 E_::BracedExpr(e) => Ok(*e),
2340                 _ => Ok(expr),
2341             }
2342         }
2343     }
2345     fn p_xhp_attr(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(XhpAttribute<,>) {
2346         match &node.syntax {
2347             XHPSimpleAttribute(c) => {
2348                 let attr_expr = &c.xhp_simple_attribute_expression;
2349                 let name = Self::p_pstring(&c.xhp_simple_attribute_name, env)?;
2350                 let expr = if attr_expr.is_braced_expression()
2351                     && env.file_mode() == file_info::Mode::Mdecl
2352                     && !env.codegen()
2353                 {
2354                     aast::Expr::new(env.mk_none_pos(), E_::Null)
2355                 } else {
2356                     Self::p_xhp_embedded(Self::unesc_xhp_attr, attr_expr, env)?
2357                 };
2358                 Ok(aast::XhpAttribute::XhpSimple(name, expr))
2359             }
2360             XHPSpreadAttribute(c) => {
2361                 let expr =
2362                     Self::p_xhp_embedded(Self::unesc_xhp, &c.xhp_spread_attribute_expression, env)?;
2363                 Ok(aast::XhpAttribute::XhpSpread(expr))
2364             }
2365             _ => Self::missing_syntax(None, "XHP attribute", node, env),
2366         }
2367     }
2369     fn aggregate_xhp_tokens<'b>(
2370         nodes: &'b Syntax<T, V>,
2371     ) -> ret!(Vec<Either<Syntax<T, V>, &'b Syntax<T, V>>>) {
2372         let nodes = Self::as_list(nodes);
2373         let mut state = (None, None, vec![]); // (start, end, result)
2374         let combine = |state: &mut (
2375             Option<&'b Syntax<T, V>>,
2376             Option<&'b Syntax<T, V>>,
2377             Vec<Either<Syntax<T, V>, &'b Syntax<T, V>>>,
2378         )| {
2379             match (state.0, state.1) {
2380                 (Some(s), None) => state.2.push(Right(s)),
2381                 (Some(s), Some(e)) => {
2382                     let token = T::concatenate(s.get_token().unwrap(), e.get_token().unwrap())
2383                         .map_err(Error::Failwith)?;
2384                     let node = <Syntax<T, V>>::make_token(token);
2385                     state.2.push(Left(node))
2386                 }
2387                 _ => {}
2388             }
2389             state.0 = None;
2390             state.1 = None;
2391             Ok(())
2392         };
2393         for n in nodes {
2394             match &n.syntax {
2395                 Token(t) if t.kind() == TK::XHPComment => {
2396                     if state.0.is_some() {
2397                         combine(&mut state)?;
2398                     }
2399                 }
2400                 Token(t) => {
2401                     if state.0.is_none() {
2402                         state.0 = Some(n)
2403                     } else {
2404                         state.1 = Some(n)
2405                     }
2406                 }
2407                 _ => {
2408                     combine(&mut state)?;
2409                     state.2.push(Right(n));
2410                 }
2411             }
2412         }
2413         combine(&mut state)?;
2414         Ok(state.2)
2415     }
2417     fn p_bop(
2418         pos: Pos,
2419         node: &Syntax<T, V>,
2420         lhs: aast!(Expr<,>),
2421         rhs: aast!(Expr<,>),
2422         env: &mut Env,
2423     ) -> ret_aast!(Expr_<,>) {
2424         use ast_defs::Bop::*;
2425         let mk = |op, l, r| Ok(E_::mk_binop(op, l, r));
2426         let mk_eq = |op, l, r| Ok(E_::mk_binop(Eq(Some(Box::new(op))), l, r));
2427         match Self::token_kind(node) {
2428             Some(TK::Equal) => mk(Eq(None), lhs, rhs),
2429             Some(TK::Bar) => mk(Bar, lhs, rhs),
2430             Some(TK::Ampersand) => mk(Amp, lhs, rhs),
2431             Some(TK::Plus) => mk(Plus, lhs, rhs),
2432             Some(TK::Minus) => mk(Minus, lhs, rhs),
2433             Some(TK::Star) => mk(Star, lhs, rhs),
2434             Some(TK::Carat) => mk(Xor, lhs, rhs),
2435             Some(TK::Slash) => mk(Slash, lhs, rhs),
2436             Some(TK::Dot) => mk(Dot, lhs, rhs),
2437             Some(TK::Percent) => mk(Percent, lhs, rhs),
2438             Some(TK::LessThan) => mk(Lt, lhs, rhs),
2439             Some(TK::GreaterThan) => mk(Gt, lhs, rhs),
2440             Some(TK::EqualEqual) => mk(Eqeq, lhs, rhs),
2441             Some(TK::LessThanEqual) => mk(Lte, lhs, rhs),
2442             Some(TK::GreaterThanEqual) => mk(Gte, lhs, rhs),
2443             Some(TK::StarStar) => mk(Starstar, lhs, rhs),
2444             Some(TK::ExclamationEqual) => mk(Diff, lhs, rhs),
2445             Some(TK::BarEqual) => mk_eq(Bar, lhs, rhs),
2446             Some(TK::PlusEqual) => mk_eq(Plus, lhs, rhs),
2447             Some(TK::MinusEqual) => mk_eq(Minus, lhs, rhs),
2448             Some(TK::StarEqual) => mk_eq(Star, lhs, rhs),
2449             Some(TK::StarStarEqual) => mk_eq(Starstar, lhs, rhs),
2450             Some(TK::SlashEqual) => mk_eq(Slash, lhs, rhs),
2451             Some(TK::DotEqual) => mk_eq(Dot, lhs, rhs),
2452             Some(TK::PercentEqual) => mk_eq(Percent, lhs, rhs),
2453             Some(TK::CaratEqual) => mk_eq(Xor, lhs, rhs),
2454             Some(TK::AmpersandEqual) => mk_eq(Amp, lhs, rhs),
2455             Some(TK::BarBar) => mk(Barbar, lhs, rhs),
2456             Some(TK::AmpersandAmpersand) => mk(Ampamp, lhs, rhs),
2457             Some(TK::LessThanLessThan) => mk(Ltlt, lhs, rhs),
2458             Some(TK::GreaterThanGreaterThan) => mk(Gtgt, lhs, rhs),
2459             Some(TK::EqualEqualEqual) => mk(Eqeqeq, lhs, rhs),
2460             Some(TK::LessThanLessThanEqual) => mk_eq(Ltlt, lhs, rhs),
2461             Some(TK::GreaterThanGreaterThanEqual) => mk_eq(Gtgt, lhs, rhs),
2462             Some(TK::ExclamationEqualEqual) => mk(Diff2, lhs, rhs),
2463             Some(TK::LessThanEqualGreaterThan) => mk(Cmp, lhs, rhs),
2464             Some(TK::QuestionQuestion) => mk(QuestionQuestion, lhs, rhs),
2465             Some(TK::QuestionQuestionEqual) => mk_eq(QuestionQuestion, lhs, rhs),
2466             /* The ugly duckling; In the FFP, `|>` is parsed as a
2467              * `BinaryOperator`, whereas the typed AST has separate constructors for
2468              * Pipe and Binop. This is why we don't just project onto a
2469              * `bop`, but a `expr -> expr -> expr_`.
2470              */
2471             Some(TK::BarGreaterThan) => {
2472                 let lid = aast::Lid::from_counter(
2473                     pos,
2474                     env.next_local_id(),
2475                     special_idents::DOLLAR_DOLLAR,
2476                 );
2477                 Ok(E_::mk_pipe(lid, lhs, rhs))
2478             }
2479             Some(TK::QuestionColon) => Ok(E_::mk_eif(lhs, None, rhs)),
2480             _ => Self::missing_syntax(None, "binary operator", node, env),
2481         }
2482     }
2484     fn is_noop(stmt: &aast!(Stmt<,>)) -> bool {
2485         if let aast::Stmt_::Noop = stmt.1 {
2486             true
2487         } else {
2488             false
2489         }
2490     }
2492     fn p_stmt_list_(
2493         pos: &Pos,
2494         mut nodes: Iter<&Syntax<T, V>>,
2495         env: &mut Env,
2496     ) -> ret!(Vec<aast!(Stmt<,>)>) {
2497         let mut r = vec![];
2498         loop {
2499             match nodes.next() {
2500                 Some(n) => match &n.syntax {
2501                     UsingStatementFunctionScoped(c) => {
2502                         let body = Self::p_stmt_list_(pos, nodes, env)?;
2503                         let f = |e: &mut Env| {
2504                             Ok(aast::Stmt::new(
2505                                 pos.clone(),
2506                                 aast::Stmt_::mk_using(aast::UsingStmt {
2507                                     is_block_scoped: false,
2508                                     has_await: !c.using_function_await_keyword.is_missing(),
2509                                     expr: Self::p_expr_l_with_loc(
2510                                         ExprLocation::UsingStatement,
2511                                         &c.using_function_expression,
2512                                         e,
2513                                     )?,
2514                                     block: body,
2515                                 }),
2516                             ))
2517                         };
2518                         let using = Self::lift_awaits_in_statement_(f, Either::Right(pos), env)?;
2519                         r.push(using);
2520                         break Ok(r);
2521                     }
2522                     _ => {
2523                         r.push(Self::p_stmt(n, env)?);
2524                     }
2525                 },
2526                 _ => break Ok(r),
2527             }
2528         }
2529     }
2531     // TODO: rename to p_stmt_list
2532     fn handle_loop_body(pos: Pos, node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Stmt<,>) {
2533         let list = Self::as_list(node);
2534         let blk: Vec<_> = Self::p_stmt_list_(&pos, list.iter(), env)?
2535             .into_iter()
2536             .filter(|stmt| !Self::is_noop(stmt))
2537             .collect();
2538         let body = if blk.len() == 0 {
2539             vec![Self::mk_noop(env)]
2540         } else {
2541             blk
2542         };
2543         Ok(aast::Stmt::new(pos, aast::Stmt_::mk_block(body)))
2544     }
2546     fn is_simple_assignment_await_expression(node: &Syntax<T, V>) -> bool {
2547         match &node.syntax {
2548             BinaryExpression(c) => {
2549                 Self::token_kind(&c.binary_operator) == Some(TK::Equal)
2550                     && Self::is_simple_await_expression(&c.binary_right_operand)
2551             }
2552             _ => false,
2553         }
2554     }
2556     fn is_simple_await_expression(node: &Syntax<T, V>) -> bool {
2557         match &node.syntax {
2558             PrefixUnaryExpression(c) => {
2559                 Self::token_kind(&c.prefix_unary_operator) == Some(TK::Await)
2560             }
2561             _ => false,
2562         }
2563     }
2565     fn with_new_nonconcurrent_scrope<F, R>(f: F, env: &mut Env) -> R
2566     where
2567         F: FnOnce(&mut Env) -> R,
2568     {
2569         let saved_lifted_awaits = env.lifted_awaits.take();
2570         let result = f(env);
2571         env.lifted_awaits = saved_lifted_awaits;
2572         result
2573     }
2575     fn with_new_concurrent_scrope<F, R>(f: F, env: &mut Env) -> ret!((LiftedAwaitExprs, R))
2576     where
2577         F: FnOnce(&mut Env) -> ret!(R),
2578     {
2579         let saved_lifted_awaits = env.lifted_awaits.replace(LiftedAwaits {
2580             awaits: vec![],
2581             lift_kind: LiftedAwaitKind::LiftedFromConcurrent,
2582         });
2583         let result = f(env);
2584         let lifted_awaits = mem::replace(&mut env.lifted_awaits, saved_lifted_awaits);
2585         let result = result?;
2586         let awaits = match lifted_awaits {
2587             Some(la) => Self::process_lifted_awaits(la, env)?,
2588             None => Self::failwith("lifted awaits should not be None")?,
2589         };
2590         Ok((awaits, result))
2591     }
2593     fn process_lifted_awaits(mut awaits: LiftedAwaits, env: &Env) -> ret!(LiftedAwaitExprs) {
2594         for await_ in awaits.awaits.iter() {
2595             if (await_.1).0.is_none() {
2596                 return Self::failwith("none pos in lifted awaits");
2597             }
2598         }
2599         awaits
2600             .awaits
2601             .sort_unstable_by(|a1, a2| Pos::compare(&(a1.1).0, &(a2.1).0));
2602         Ok(awaits.awaits)
2603     }
2605     fn clear_statement_scope<F, R>(f: F, env: &mut Env) -> R
2606     where
2607         F: FnOnce(&mut Env) -> R,
2608     {
2609         use LiftedAwaitKind::*;
2610         match &env.lifted_awaits {
2611             Some(LiftedAwaits { lift_kind, .. }) if *lift_kind == LiftedFromStatement => {
2612                 let saved_lifted_awaits = env.lifted_awaits.take();
2613                 let result = f(env);
2614                 env.lifted_awaits = saved_lifted_awaits;
2615                 result
2616             }
2617             _ => f(env),
2618         }
2619     }
2621     fn lift_awaits_in_statement<F>(f: F, node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Stmt<,>)
2622     where
2623         F: FnOnce(&mut Env) -> ret_aast!(Stmt<,>),
2624     {
2625         Self::lift_awaits_in_statement_(f, Either::Left(node), env)
2626     }
2628     fn lift_awaits_in_statement_<F>(
2629         f: F,
2630         pos: Either<&Syntax<T, V>, &Pos>,
2631         env: &mut Env,
2632     ) -> ret_aast!(Stmt<,>)
2633     where
2634         F: FnOnce(&mut Env) -> ret_aast!(Stmt<,>),
2635     {
2636         use LiftedAwaitKind::*;
2637         let (lifted_awaits, result) = match env.lifted_awaits {
2638             Some(LiftedAwaits { lift_kind, .. }) if lift_kind == LiftedFromConcurrent => {
2639                 (None, f(env)?)
2640             }
2641             _ => {
2642                 let saved = env.lifted_awaits.replace(LiftedAwaits {
2643                     awaits: vec![],
2644                     lift_kind: LiftedFromStatement,
2645                 });
2646                 let result = f(env);
2647                 let lifted_awaits = mem::replace(&mut env.lifted_awaits, saved);
2648                 let result = result?;
2649                 (lifted_awaits, result)
2650             }
2651         };
2652         if let Some(lifted_awaits) = lifted_awaits {
2653             if !lifted_awaits.awaits.is_empty() {
2654                 let awaits = Self::process_lifted_awaits(lifted_awaits, env)?;
2655                 let pos = match pos {
2656                     Either::Left(n) => Self::p_pos(n, env),
2657                     Either::Right(p) => p.clone(),
2658                 };
2659                 return Ok(aast::Stmt::new(
2660                     pos,
2661                     aast::Stmt_::mk_awaitall(awaits, vec![result]),
2662                 ));
2663             }
2664         }
2665         Ok(result)
2666     }
2668     fn lift_await(
2669         parent_pos: Pos,
2670         expr: aast!(Expr<,>),
2671         env: &mut Env,
2672         location: ExprLocation,
2673     ) -> ret_aast!(Expr_<,>) {
2674         use ExprLocation::*;
2675         match (&env.lifted_awaits, location) {
2676             (_, UsingStatement) | (_, RightOfAssignmentInUsingStatement) | (None, _) => {
2677                 Ok(E_::mk_await(expr))
2678             }
2679             (Some(_), _) => {
2680                 if location != AsStatement {
2681                     let name = env.make_tmp_var_name();
2682                     let lid = aast::Lid::new(parent_pos, name.clone());
2683                     let await_lid = aast::Lid::new(expr.0.clone(), name);
2684                     let await_ = (Some(await_lid), expr);
2685                     env.lifted_awaits.as_mut().map(|aw| aw.awaits.push(await_));
2686                     Ok(E_::mk_lvar(lid))
2687                 } else {
2688                     env.lifted_awaits
2689                         .as_mut()
2690                         .map(|aw| aw.awaits.push((None, expr)));
2691                     Ok(E_::Null)
2692                 }
2693             }
2694         }
2695     }
2697     fn p_stmt(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Stmt<,>) {
2698         Self::clear_statement_scope(
2699             |e: &mut Env| {
2700                 let docblock = Self::extract_docblock(node, e);
2701                 e.push_docblock(docblock);
2702                 let result = Self::p_stmt_(node, e);
2703                 e.pop_docblock();
2704                 result
2705             },
2706             env,
2707         )
2708     }
2710     fn p_stmt_(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Stmt<,>) {
2711         let pos = Self::p_pos(node, env);
2712         use aast::{Stmt as S, Stmt_ as S_};
2713         match &node.syntax {
2714             SwitchStatement(c) => {
2715                 let p_label = |n: &Syntax<T, V>, e: &mut Env| -> ret_aast!(Case<,>) {
2716                     match &n.syntax {
2717                         CaseLabel(c) => Ok(aast::Case::Case(
2718                             Self::p_expr(&c.case_expression, e)?,
2719                             vec![],
2720                         )),
2721                         DefaultLabel(_) => Ok(aast::Case::Default(Self::p_pos(n, e), vec![])),
2722                         _ => Self::missing_syntax(None, "switch label", n, e),
2723                     }
2724                 };
2725                 let p_section = |n: &Syntax<T, V>, e: &mut Env| -> ret!(Vec<aast!(Case<,>)>) {
2726                     match &n.syntax {
2727                         SwitchSection(c) => {
2728                             let mut blk =
2729                                 Self::could_map(Self::p_stmt, &c.switch_section_statements, e)?;
2730                             if !c.switch_section_fallthrough.is_missing() {
2731                                 blk.push(S::new(e.mk_none_pos(), S_::Fallthrough));
2732                             }
2733                             let mut labels = Self::could_map(p_label, &c.switch_section_labels, e)?;
2734                             match labels.last_mut() {
2735                                 Some(aast::Case::Default(_, b)) => *b = blk,
2736                                 Some(aast::Case::Case(_, b)) => *b = blk,
2737                                 _ => Self::raise_parsing_error(n, e, "Malformed block result"),
2738                             }
2739                             Ok(labels)
2740                         }
2741                         _ => Self::missing_syntax(None, "switch section", n, e),
2742                     }
2743                 };
2744                 let f = |env: &mut Env| -> ret_aast!(Stmt<,>) {
2745                     Ok(S::new(
2746                         pos,
2747                         S_::mk_switch(
2748                             Self::p_expr(&c.switch_expression, env)?,
2749                             itertools::concat(Self::could_map(p_section, &c.switch_sections, env)?),
2750                         ),
2751                     ))
2752                 };
2753                 Self::lift_awaits_in_statement(f, node, env)
2754             }
2755             IfStatement(c) => {
2756                 let p_else_if =
2757                     |n: &Syntax<T, V>, e: &mut Env| -> ret!((aast!(Expr<,>), aast!(Block<,>))) {
2758                         match &n.syntax {
2759                             ElseifClause(c) => Ok((
2760                                 Self::p_expr(&c.elseif_condition, e)?,
2761                                 Self::p_block(true, &c.elseif_statement, e)?,
2762                             )),
2763                             _ => Self::missing_syntax(None, "elseif clause", n, e),
2764                         }
2765                     };
2766                 let f = |env: &mut Env| -> ret_aast!(Stmt<,>) {
2767                     let condition = Self::p_expr(&c.if_condition, env)?;
2768                     let statement =
2769                         Self::p_block(true /* remove noop */, &c.if_statement, env)?;
2770                     let else_ = match &c.if_else_clause.syntax {
2771                         ElseClause(c) => Self::p_block(true, &c.else_statement, env)?,
2772                         Missing => vec![Self::mk_noop(env)],
2773                         _ => Self::missing_syntax(None, "else clause", &c.if_else_clause, env)?,
2774                     };
2775                     let else_ifs = Self::could_map(p_else_if, &c.if_elseif_clauses, env)?;
2776                     let else_if = else_ifs
2777                         .into_iter()
2778                         .rev()
2779                         .fold(else_, |child, (cond, stmts)| {
2780                             vec![S::new(pos.clone(), S_::mk_if(cond, stmts, child))]
2781                         });
2782                     Ok(S::new(pos, S_::mk_if(condition, statement, else_if)))
2783                 };
2784                 Self::lift_awaits_in_statement(f, node, env)
2785             }
2786             ExpressionStatement(c) => {
2787                 let expr = &c.expression_statement_expression;
2788                 let f = |e: &mut Env| -> ret_aast!(Stmt<,>) {
2789                     if expr.is_missing() {
2790                         Ok(S::new(pos, S_::Noop))
2791                     } else {
2792                         Ok(S::new(
2793                             pos,
2794                             S_::mk_expr(Self::p_expr_with_loc(ExprLocation::AsStatement, expr, e)?),
2795                         ))
2796                     }
2797                 };
2798                 if Self::is_simple_assignment_await_expression(expr)
2799                     || Self::is_simple_await_expression(expr)
2800                 {
2801                     f(env)
2802                 } else {
2803                     Self::lift_awaits_in_statement(f, node, env)
2804                 }
2805             }
2806             CompoundStatement(c) => Self::handle_loop_body(pos, &c.compound_statements, env),
2807             SyntaxList(_) => Self::handle_loop_body(pos, node, env),
2808             ThrowStatement(c) => Self::lift_awaits_in_statement(
2809                 |e: &mut Env| -> ret_aast!(Stmt<,>) {
2810                     Ok(S::new(
2811                         pos,
2812                         S_::mk_throw(Self::p_expr(&c.throw_expression, e)?),
2813                     ))
2814                 },
2815                 node,
2816                 env,
2817             ),
2818             DoStatement(c) => Ok(S::new(
2819                 pos,
2820                 S_::mk_do(
2821                     Self::p_block(false /* remove noop */, &c.do_body, env)?,
2822                     Self::p_expr(&c.do_condition, env)?,
2823                 ),
2824             )),
2825             WhileStatement(c) => Ok(S::new(
2826                 pos,
2827                 S_::mk_while(
2828                     Self::p_expr(&c.while_condition, env)?,
2829                     Self::p_block(true, &c.while_body, env)?,
2830                 ),
2831             )),
2832             UsingStatementBlockScoped(c) => {
2833                 let f = |e: &mut Env| -> ret_aast!(Stmt<,>) {
2834                     Ok(S::new(
2835                         pos,
2836                         S_::mk_using(aast::UsingStmt {
2837                             is_block_scoped: true,
2838                             has_await: !&c.using_block_await_keyword.is_missing(),
2839                             expr: Self::p_expr_l_with_loc(
2840                                 ExprLocation::UsingStatement,
2841                                 &c.using_block_expressions,
2842                                 e,
2843                             )?,
2844                             block: Self::p_block(false, &c.using_block_body, e)?,
2845                         }),
2846                     ))
2847                 };
2848                 Self::lift_awaits_in_statement(f, node, env)
2849             }
2850             UsingStatementFunctionScoped(c) => {
2851                 let f = |e: &mut Env| -> ret_aast!(Stmt<,>) {
2852                     Ok(S::new(
2853                         pos,
2854                         S_::mk_using(aast::UsingStmt {
2855                             is_block_scoped: false,
2856                             has_await: !&c.using_function_await_keyword.is_missing(),
2857                             expr: Self::p_expr_l_with_loc(
2858                                 ExprLocation::UsingStatement,
2859                                 &c.using_function_expression,
2860                                 e,
2861                             )?,
2862                             block: vec![Self::mk_noop(e)],
2863                         }),
2864                     ))
2865                 };
2866                 Self::lift_awaits_in_statement(f, node, env)
2867             }
2868             LetStatement(c) => {
2869                 let f = |e: &mut Env| -> ret_aast!(Stmt<,>) {
2870                     let id = Self::lid_from_pos_name(pos.clone(), &c.let_statement_name, e)?;
2871                     let ty = Self::mp_optional(Self::p_hint, &c.let_statement_type, e)?;
2872                     let expr = Self::p_simple_initializer(&c.let_statement_initializer, e)?;
2873                     Ok(S::new(pos, S_::mk_let(id, ty, expr)))
2874                 };
2875                 Self::lift_awaits_in_statement(f, node, env)
2876             }
2877             ForStatement(c) => {
2878                 let f = |e: &mut Env| -> ret_aast!(Stmt<,>) {
2879                     let ini = Self::p_expr_l(&c.for_initializer, e)?;
2880                     let ctr = Self::p_expr_l(&c.for_control, e)?;
2881                     let eol = Self::p_expr_l(&c.for_end_of_loop, e)?;
2882                     let blk = Self::p_block(true, &c.for_body, e)?;
2883                     Ok(S::new(pos, S_::mk_for(ini, ctr, eol, blk)))
2884                 };
2885                 Self::lift_awaits_in_statement(f, node, env)
2886             }
2887             ForeachStatement(c) => {
2888                 let f = |e: &mut Env| -> ret_aast!(Stmt<,>) {
2889                     let col = Self::p_expr(&c.foreach_collection, e)?;
2890                     let akw = match Self::token_kind(&c.foreach_await_keyword) {
2891                         Some(TK::Await) => Some(Self::p_pos(&c.foreach_await_keyword, e)),
2892                         _ => None,
2893                     };
2894                     let value = Self::p_expr(&c.foreach_value, e)?;
2895                     let akv = match (akw, &c.foreach_key.syntax) {
2896                         (Some(p), Missing) => aast::AsExpr::AwaitAsV(p, value),
2897                         (None, Missing) => aast::AsExpr::AsV(value),
2898                         (Some(p), _) => {
2899                             aast::AsExpr::AwaitAsKv(p, Self::p_expr(&c.foreach_key, e)?, value)
2900                         }
2901                         (None, _) => aast::AsExpr::AsKv(Self::p_expr(&c.foreach_key, e)?, value),
2902                     };
2903                     let blk = Self::p_block(true, &c.foreach_body, e)?;
2904                     Ok(S::new(pos, S_::mk_foreach(col, akv, blk)))
2905                 };
2906                 Self::lift_awaits_in_statement(f, node, env)
2907             }
2908             TryStatement(c) => Ok(S::new(
2909                 pos,
2910                 S_::mk_try(
2911                     Self::p_block(false, &c.try_compound_statement, env)?,
2912                     Self::could_map(
2913                         |n: &Syntax<T, V>, e| match &n.syntax {
2914                             CatchClause(c) => Ok(aast::Catch(
2915                                 Self::pos_name(&c.catch_type, e)?,
2916                                 Self::lid_from_name(&c.catch_variable, e)?,
2917                                 Self::p_block(true, &c.catch_body, e)?,
2918                             )),
2919                             _ => Self::missing_syntax(None, "catch clause", n, e),
2920                         },
2921                         &c.try_catch_clauses,
2922                         env,
2923                     )?,
2924                     match &c.try_finally_clause.syntax {
2925                         FinallyClause(c) => Self::p_block(false, &c.finally_body, env)?,
2926                         _ => vec![],
2927                     },
2928                 ),
2929             )),
2930             ReturnStatement(c) => {
2931                 let f = |e: &mut Env| -> ret_aast!(Stmt<,>) {
2932                     let expr = match &c.return_expression.syntax {
2933                         Missing => None,
2934                         _ => Some(Self::p_expr_with_loc(
2935                             ExprLocation::RightOfReturn,
2936                             &c.return_expression,
2937                             e,
2938                         )?),
2939                     };
2940                     Ok(aast::Stmt::new(pos, aast::Stmt_::mk_return(expr)))
2941                 };
2942                 if Self::is_simple_await_expression(&c.return_expression) {
2943                     f(env)
2944                 } else {
2945                     Self::lift_awaits_in_statement(f, node, env)
2946                 }
2947             }
2948             GotoLabel(c) => {
2949                 if env.is_typechecker() && !env.parser_options.po_allow_goto {
2950                     Self::raise_parsing_error(node, env, &syntax_error::goto_label);
2951                 }
2952                 Ok(S::new(
2953                     pos,
2954                     S_::mk_goto_label((
2955                         Self::p_pos(&c.goto_label_name, env),
2956                         Self::text(&c.goto_label_name, env),
2957                     )),
2958                 ))
2959             }
2960             GotoStatement(c) => {
2961                 if env.is_typechecker() && !env.parser_options.po_allow_goto {
2962                     Self::raise_parsing_error(node, env, &syntax_error::goto_label);
2963                 }
2964                 Ok(S::new(
2965                     pos,
2966                     S_::mk_goto(Self::p_pstring(&c.goto_statement_label_name, env)?),
2967                 ))
2968             }
2969             EchoStatement(c) => {
2970                 let f = |e: &mut Env| -> ret_aast!(Stmt<,>) {
2971                     let echo = match &c.echo_keyword.syntax {
2972                         QualifiedName(_) | SimpleTypeSpecifier(_) | Token(_) => {
2973                             let name = Self::pos_name(&c.echo_keyword, e)?;
2974                             aast::Expr::new(name.0.clone(), E_::mk_id(name))
2975                         }
2976                         _ => Self::missing_syntax(None, "id", &c.echo_keyword, e)?,
2977                     };
2978                     let args = Self::could_map(Self::p_expr, &c.echo_expressions, e)?;
2979                     Ok(S::new(
2980                         pos.clone(),
2981                         S_::mk_expr(aast::Expr::new(
2982                             pos,
2983                             E_::mk_call(aast::CallType::Cnormal, echo, vec![], args, vec![]),
2984                         )),
2985                     ))
2986                 };
2987                 Self::lift_awaits_in_statement(f, node, env)
2988             }
2989             UnsetStatement(c) => {
2990                 let f = |e: &mut Env| -> ret_aast!(Stmt<,>) {
2991                     let args = Self::could_map(Self::p_expr, &c.unset_variables, e)?;
2992                     if e.parser_options.po_disable_unset_class_const {
2993                         args.iter()
2994                             .for_each(|arg| Self::check_mutate_class_const(arg, node, e))
2995                     }
2996                     let unset = match &c.unset_keyword.syntax {
2997                         QualifiedName(_) | SimpleTypeSpecifier(_) | Token(_) => {
2998                             let name = Self::pos_name(&c.unset_keyword, e)?;
2999                             aast::Expr::new(name.0.clone(), E_::mk_id(name))
3000                         }
3001                         _ => Self::missing_syntax(None, "id", &c.unset_keyword, e)?,
3002                     };
3003                     Ok(S::new(
3004                         pos.clone(),
3005                         S_::mk_expr(aast::Expr::new(
3006                             pos,
3007                             E_::mk_call(aast::CallType::Cnormal, unset, vec![], args, vec![]),
3008                         )),
3009                     ))
3010                 };
3011                 Self::lift_awaits_in_statement(f, node, env)
3012             }
3013             BreakStatement(_) => Ok(S::new(pos, S_::Break)),
3014             ContinueStatement(_) => Ok(S::new(pos, S_::Continue)),
3015             ConcurrentStatement(c) => {
3016                 let (lifted_awaits, S(stmt_pos, stmt)) = Self::with_new_concurrent_scrope(
3017                     |e: &mut Env| Self::p_stmt(&c.concurrent_statement, e),
3018                     env,
3019                 )?;
3020                 let stmt = match stmt {
3021                     S_::Block(stmts) => {
3022                         use aast::Expr as E;
3023                         use ast_defs::Bop::Eq;
3024                         /* Reuse tmp vars from lifted_awaits, this is safe because there will
3025                          * always be more awaits with tmp vars than statements with assignments */
3026                         let mut tmp_vars = lifted_awaits
3027                             .iter()
3028                             .filter_map(|lifted_await| lifted_await.0.as_ref().map(|x| &x.1));
3029                         let mut body_stmts = vec![];
3030                         let mut assign_stmts = vec![];
3031                         for n in stmts.into_iter() {
3032                             if !n.is_assign_expr() {
3033                                 body_stmts.push(n);
3034                                 continue;
3035                             }
3037                             if let Some(tv) = tmp_vars.next() {
3038                                 if let S(p1, S_::Expr(expr)) = n {
3039                                     if let E(p2, E_::Binop(bop)) = *expr {
3040                                         if let (Eq(op), e1, e2) = *bop {
3041                                             let tmp_n = E::mk_lvar(&e2.0, &(tv.1));
3042                                             if tmp_n.lvar_name() != e2.lvar_name() {
3043                                                 let new_n = S::new(
3044                                                     p1.clone(),
3045                                                     S_::mk_expr(E::new(
3046                                                         p2.clone(),
3047                                                         E_::mk_binop(
3048                                                             Eq(None),
3049                                                             tmp_n.clone(),
3050                                                             e2.clone(),
3051                                                         ),
3052                                                     )),
3053                                                 );
3054                                                 body_stmts.push(new_n);
3055                                             }
3056                                             let assign_stmt = S::new(
3057                                                 p1,
3058                                                 S_::mk_expr(E::new(
3059                                                     p2,
3060                                                     E_::mk_binop(Eq(op), e1, tmp_n),
3061                                                 )),
3062                                             );
3063                                             assign_stmts.push(assign_stmt);
3064                                             continue;
3065                                         }
3066                                     }
3067                                 }
3069                                 Self::failwith("Expect assignment stmt")?;
3070                             } else {
3071                                 Self::raise_parsing_error_pos(
3072                                     &stmt_pos,
3073                                     env,
3074                                     &syntax_error::statement_without_await_in_concurrent_block,
3075                                 );
3076                                 body_stmts.push(n)
3077                             }
3078                         }
3079                         body_stmts.append(&mut assign_stmts);
3080                         S::new(stmt_pos, S_::mk_block(body_stmts))
3081                     }
3082                     _ => Self::failwith("Unexpected concurrent stmt structure")?,
3083                 };
3084                 Ok(S::new(pos, S_::mk_awaitall(lifted_awaits, vec![stmt])))
3085             }
3086             MarkupSection(_) => Self::p_markup(node, env),
3087             _ => Self::missing_syntax(
3088                 Some(S::new(env.mk_none_pos(), S_::Noop)),
3089                 "statement",
3090                 node,
3091                 env,
3092             ),
3093         }
3094     }
3096     fn check_mutate_class_const(e: &aast!(Expr<,>), node: &Syntax<T, V>, env: &mut Env) {
3097         match &e.1 {
3098             E_::ArrayGet(c) if c.1.is_some() => Self::check_mutate_class_const(&c.0, node, env),
3099             E_::ClassConst(_) => {
3100                 Self::raise_parsing_error(node, env, &syntax_error::const_mutation)
3101             }
3102             _ => {}
3103         }
3104     }
3106     fn is_hashbang(node: &Syntax<T, V>, env: &Env) -> bool {
3107         let text = Self::text_str(node, env);
3108         lazy_static! {
3109             static ref RE: regex::Regex = regex::Regex::new("^#!.*\n").unwrap();
3110         }
3111         text.lines().nth(1).is_none() && // only one line
3112         RE.is_match(text)
3113     }
3115     fn p_markup(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Stmt<,>) {
3116         match &node.syntax {
3117             MarkupSection(c) => {
3118                 let markup_prefix = &c.markup_prefix;
3119                 let markup_text = &c.markup_text;
3120                 let markup_expression = &c.markup_expression;
3121                 let pos = Self::p_pos(node, env);
3122                 let has_dot_hack_extension = pos.filename().has_extension("hack");
3123                 if has_dot_hack_extension {
3124                     Self::raise_parsing_error(node, env, &syntax_error::error1060);
3125                 } else if markup_prefix.value.is_missing()
3126                     && markup_text.width() > 0
3127                     && !Self::is_hashbang(&markup_text, env)
3128                 {
3129                     Self::raise_parsing_error(node, env, &syntax_error::error1001);
3130                 }
3131                 let expr = match &markup_expression.syntax {
3132                     Missing => None,
3133                     ExpressionStatement(e) => {
3134                         Some(Self::p_expr(&e.expression_statement_expression, env)?)
3135                     }
3136                     _ => Self::failwith("expression expected")?,
3137                 };
3138                 let stmt_ =
3139                     aast::Stmt_::mk_markup((pos.clone(), Self::text(&markup_text, env)), expr);
3140                 Ok(aast::Stmt::new(pos, stmt_))
3141             }
3142             _ => Self::failwith("invalid node"),
3143         }
3144     }
3146     fn p_modifiers<F: Fn(R, modifier::Kind) -> R, R>(
3147         on_kind: F,
3148         mut init: R,
3149         node: &Syntax<T, V>,
3150         env: &mut Env,
3151     ) -> ret!((modifier::KindSet, R)) {
3152         let nodes = Self::as_list(node);
3153         let mut kind_set = modifier::KindSet::new();
3154         for n in nodes.iter() {
3155             let token_kind = Self::token_kind(n).map_or(None, modifier::from_token_kind);
3156             match token_kind {
3157                 Some(kind) => {
3158                     kind_set.add(kind);
3159                     init = on_kind(init, kind);
3160                 }
3161                 _ => Self::missing_syntax(None, "kind", n, env)?,
3162             }
3163         }
3164         Ok((kind_set, init))
3165     }
3167     fn p_kinds(node: &Syntax<T, V>, env: &mut Env) -> ret!(modifier::KindSet) {
3168         Self::p_modifiers(|_, _| {}, (), node, env).map(|r| r.0)
3169     }
3171     // TODO: change name to map_flatten after porting
3172     #[inline]
3173     fn could_map<R, F>(f: F, node: &Syntax<T, V>, env: &mut Env) -> ret!(Vec<R>)
3174     where
3175         F: Fn(&Syntax<T, V>, &mut Env) -> ret!(R),
3176     {
3177         Self::map_flatten_(f, node, env, vec![])
3178     }
3180     #[inline]
3181     fn map_flatten_<R, F>(f: F, node: &Syntax<T, V>, env: &mut Env, acc: Vec<R>) -> ret!(Vec<R>)
3182     where
3183         F: Fn(&Syntax<T, V>, &mut Env) -> ret!(R),
3184     {
3185         let op = |mut v: Vec<R>, a| {
3186             v.push(a);
3187             v
3188         };
3189         Self::map_fold(&f, &op, node, env, acc)
3190     }
3192     fn map_fold<A, R, F, O>(f: &F, op: &O, node: &Syntax<T, V>, env: &mut Env, acc: A) -> ret!(A)
3193     where
3194         F: Fn(&Syntax<T, V>, &mut Env) -> ret!(R),
3195         O: Fn(A, R) -> A,
3196     {
3197         match &node.syntax {
3198             Missing => Ok(acc),
3199             SyntaxList(xs) => {
3200                 let mut a = acc;
3201                 for x in xs.iter() {
3202                     a = Self::map_fold(f, op, &x, env, a)?;
3203                 }
3204                 Ok(a)
3205             }
3206             ListItem(x) => Ok(op(acc, f(&x.list_item, env)?)),
3207             _ => Ok(op(acc, f(node, env)?)),
3208         }
3209     }
3211     fn p_visibility(node: &Syntax<T, V>, env: &mut Env) -> ret!(Option<aast!(Visibility)>) {
3212         let first_vis =
3213             |r: Option<aast!(Visibility)>, kind| r.or_else(|| modifier::to_visibility(kind));
3214         Self::p_modifiers(first_vis, None, node, env).map(|r| r.1)
3215     }
3217     fn p_visibility_or(
3218         node: &Syntax<T, V>,
3219         env: &mut Env,
3220         default: aast!(Visibility),
3221     ) -> ret_aast!(Visibility) {
3222         Self::p_visibility(node, env).map(|v| v.unwrap_or(default))
3223     }
3225     fn p_visibility_last_win(
3226         node: &Syntax<T, V>,
3227         env: &mut Env,
3228     ) -> ret!(Option<aast!(Visibility)>) {
3229         let last_vis = |r, kind| modifier::to_visibility(kind).or(r);
3230         Self::p_modifiers(last_vis, None, node, env).map(|r| r.1)
3231     }
3233     fn p_visibility_last_win_or(
3234         node: &Syntax<T, V>,
3235         env: &mut Env,
3236         default: aast!(Visibility),
3237     ) -> ret_aast!(Visibility) {
3238         Self::p_visibility_last_win(node, env).map(|v| v.unwrap_or(default))
3239     }
3241     fn has_soft(attrs: &[aast!(UserAttribute<,>)]) -> bool {
3242         attrs.iter().any(|attr| attr.name.1 == "__Soft")
3243     }
3245     fn soften_hint(attrs: &[aast!(UserAttribute<,>)], hint: aast!(Hint)) -> aast!(Hint) {
3246         if Self::has_soft(attrs) {
3247             aast::Hint::new(hint.0.clone(), aast::Hint_::Hsoft(hint))
3248         } else {
3249             hint
3250         }
3251     }
3253     fn p_fun_param_default_value(
3254         node: &Syntax<T, V>,
3255         env: &mut Env,
3256     ) -> ret!(Option<aast!(Expr<,>)>) {
3257         match &node.syntax {
3258             SimpleInitializer(c) => {
3259                 Self::mp_optional(Self::p_expr, &c.simple_initializer_value, env)
3260             }
3261             _ => Ok(None),
3262         }
3263     }
3265     fn p_param_kind(node: &Syntax<T, V>, env: &mut Env) -> ret!(ast_defs::ParamKind) {
3266         match Self::token_kind(node) {
3267             Some(TK::Inout) => Ok(ast_defs::ParamKind::Pinout),
3268             _ => Self::missing_syntax(None, "param kind", node, env),
3269         }
3270     }
3272     fn param_template(node: &Syntax<T, V>, env: &Env) -> aast!(FunParam<,>) {
3273         let pos = Self::p_pos(node, env);
3274         aast::FunParam {
3275             annotation: pos.clone(),
3276             type_hint: aast::TypeHint((), None),
3277             is_reference: false,
3278             is_variadic: false,
3279             pos,
3280             name: Self::text(node, env),
3281             expr: None,
3282             callconv: None,
3283             user_attributes: vec![],
3284             visibility: None,
3285         }
3286     }
3288     fn p_fun_param(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(FunParam<,>) {
3289         match &node.syntax {
3290             ParameterDeclaration(c) => {
3291                 let parameter_attribute = &c.parameter_attribute;
3292                 let parameter_visibility = &c.parameter_visibility;
3293                 let parameter_call_convention = &c.parameter_call_convention;
3294                 let parameter_type = &c.parameter_type;
3295                 let parameter_name = &c.parameter_name;
3296                 let parameter_default_value = &c.parameter_default_value;
3297                 let (is_reference, is_variadic, name) = match &parameter_name.syntax {
3298                     DecoratedExpression(c) => {
3299                         let decorated_expression_decorator = &c.decorated_expression_decorator;
3300                         let decorated_expression_expression = &c.decorated_expression_expression;
3301                         let decorator = Self::text_str(decorated_expression_decorator, env);
3302                         match &decorated_expression_expression.syntax {
3303                             DecoratedExpression(c) => {
3304                                 let nested_expression = &c.decorated_expression_expression;
3305                                 let nested_decorator =
3306                                     Self::text_str(&c.decorated_expression_decorator, env);
3307                                 (
3308                                     decorator == "&" || nested_decorator == "&",
3309                                     decorator == "..." || nested_decorator == "...",
3310                                     nested_expression,
3311                                 )
3312                             }
3313                             _ => (
3314                                 decorator == "&",
3315                                 decorator == "...",
3316                                 decorated_expression_expression,
3317                             ),
3318                         }
3319                     }
3320                     _ => (false, false, parameter_name),
3321                 };
3322                 let user_attributes = Self::p_user_attributes(&parameter_attribute, env)?;
3323                 let hint = Self::mp_optional(Self::p_hint, parameter_type, env)?
3324                     .map(|h| Self::soften_hint(&user_attributes, h));
3325                 if is_variadic && !user_attributes.is_empty() {
3326                     Self::raise_parsing_error(
3327                         node,
3328                         env,
3329                         &syntax_error::no_attributes_on_variadic_parameter,
3330                     );
3331                 }
3332                 let pos = Self::p_pos(name, env);
3333                 Ok(aast::FunParam {
3334                     annotation: pos.clone(),
3335                     type_hint: aast::TypeHint((), hint),
3336                     user_attributes,
3337                     is_reference,
3338                     is_variadic,
3339                     pos,
3340                     name: Self::text(name, env),
3341                     expr: Self::p_fun_param_default_value(parameter_default_value, env)?,
3342                     callconv: Self::mp_optional(
3343                         Self::p_param_kind,
3344                         parameter_call_convention,
3345                         env,
3346                     )?,
3347                     /* implicit field via constructor parameter.
3348                      * This is always None except for constructors and the modifier
3349                      * can be only Public or Protected or Private.
3350                      */
3351                     visibility: Self::p_visibility(parameter_visibility, env)?,
3352                 })
3353             }
3354             VariadicParameter(_) => {
3355                 let mut param = Self::param_template(node, env);
3356                 param.is_variadic = true;
3357                 Ok(param)
3358             }
3359             Token(_) if Self::text_str(node, env) == "..." => {
3360                 let mut param = Self::param_template(node, env);
3361                 param.is_variadic = true;
3362                 Ok(param)
3363             }
3364             _ => Self::missing_syntax(None, "function parameter", node, env),
3365         }
3366     }
3368     fn p_tconstraint_ty(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Hint) {
3369         match &node.syntax {
3370             TypeConstraint(c) => Self::p_hint(&c.constraint_type, env),
3371             _ => Self::missing_syntax(None, "type constraint", node, env),
3372         }
3373     }
3375     fn p_tconstraint(
3376         node: &Syntax<T, V>,
3377         env: &mut Env,
3378     ) -> ret!((ast_defs::ConstraintKind, aast!(Hint))) {
3379         match &node.syntax {
3380             TypeConstraint(c) => Ok((
3381                 match Self::token_kind(&c.constraint_keyword) {
3382                     Some(TK::As) => ast_defs::ConstraintKind::ConstraintAs,
3383                     Some(TK::Super) => ast_defs::ConstraintKind::ConstraintSuper,
3384                     Some(TK::Equal) => ast_defs::ConstraintKind::ConstraintEq,
3385                     _ => Self::missing_syntax(
3386                         None,
3387                         "constraint operator",
3388                         &c.constraint_keyword,
3389                         env,
3390                     )?,
3391                 },
3392                 Self::p_hint(&c.constraint_type, env)?,
3393             )),
3394             _ => Self::missing_syntax(None, "type constraint", node, env),
3395         }
3396     }
3398     fn p_tparam(is_class: bool, node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Tparam<,>) {
3399         match &node.syntax {
3400             TypeParameter(c) => {
3401                 let user_attributes = Self::p_user_attributes(&c.type_attribute_spec, env)?;
3402                 let is_reified = !&c.type_reified.is_missing();
3403                 if is_class && is_reified {
3404                     let type_name = Self::text(&c.type_name, env);
3405                     env.cls_reified_generics().insert(type_name);
3406                 }
3407                 let variance = match Self::token_kind(&c.type_variance) {
3408                     Some(TK::Plus) => ast_defs::Variance::Covariant,
3409                     Some(TK::Minus) => ast_defs::Variance::Contravariant,
3410                     _ => ast_defs::Variance::Invariant,
3411                 };
3412                 if is_reified && variance != ast_defs::Variance::Invariant {
3413                     Self::raise_parsing_error(
3414                         node,
3415                         env,
3416                         &syntax_error::non_invariant_reified_generic,
3417                     );
3418                 }
3419                 let reified = match (is_reified, Self::has_soft(&user_attributes)) {
3420                     (true, true) => aast::ReifyKind::SoftReified,
3421                     (true, false) => aast::ReifyKind::Reified,
3422                     _ => aast::ReifyKind::Erased,
3423                 };
3424                 Ok(aast::Tparam {
3425                     variance,
3426                     name: Self::pos_name(&c.type_name, env)?,
3427                     constraints: Self::could_map(Self::p_tconstraint, &c.type_constraints, env)?,
3428                     reified,
3429                     user_attributes,
3430                 })
3431             }
3432             _ => Self::missing_syntax(None, "type parameter", node, env),
3433         }
3434     }
3436     fn p_tparam_l(
3437         is_class: bool,
3438         node: &Syntax<T, V>,
3439         env: &mut Env,
3440     ) -> ret!(Vec<aast!(Tparam<,>)>) {
3441         match &node.syntax {
3442             Missing => Ok(vec![]),
3443             TypeParameters(c) => Self::could_map(
3444                 |n, e| Self::p_tparam(is_class, n, e),
3445                 &c.type_parameters_parameters,
3446                 env,
3447             ),
3448             _ => Self::missing_syntax(None, "type parameter", node, env),
3449         }
3450     }
3452     fn p_fun_hdr(node: &Syntax<T, V>, env: &mut Env) -> ret!(FunHdr) {
3453         match &node.syntax {
3454             FunctionDeclarationHeader(c) => {
3455                 let function_modifiers = &c.function_modifiers;
3456                 let function_name = &c.function_name;
3457                 let function_where_clause = &c.function_where_clause;
3458                 let function_type_parameter_list = &c.function_type_parameter_list;
3459                 let function_parameter_list = &c.function_parameter_list;
3460                 let function_type = &c.function_type;
3461                 let is_autoload = Self::text_str(function_name, env)
3462                     .eq_ignore_ascii_case(special_functions::AUTOLOAD);
3463                 if function_name.value.is_missing() {
3464                     Self::raise_parsing_error(function_name, env, &syntax_error::empty_method_name);
3465                 }
3466                 let num_params = Self::syntax_to_list(false, function_parameter_list).len();
3467                 if is_autoload && num_params > 1 {
3468                     Self::raise_parsing_error(
3469                         node,
3470                         env,
3471                         &syntax_error::autoload_takes_one_argument,
3472                     );
3473                 }
3474                 let kinds = Self::p_kinds(function_modifiers, env)?;
3475                 let has_async = kinds.has(modifier::ASYNC);
3476                 let has_coroutine = kinds.has(modifier::COROUTINE);
3477                 let parameters = Self::could_map(Self::p_fun_param, function_parameter_list, env)?;
3478                 let return_type = Self::mp_optional(Self::p_hint, function_type, env)?;
3479                 let suspension_kind =
3480                     Self::mk_suspension_kind_(node, env, has_async, has_coroutine);
3481                 let name = Self::pos_name(function_name, env)?;
3482                 let constrs = Self::p_where_constraint(false, node, function_where_clause, env)?;
3483                 let type_parameters = Self::p_tparam_l(false, function_type_parameter_list, env)?;
3484                 Ok(FunHdr {
3485                     suspension_kind,
3486                     name,
3487                     constrs,
3488                     type_parameters,
3489                     parameters,
3490                     return_type,
3491                 })
3492             }
3493             LambdaSignature(c) => {
3494                 let mut header = FunHdr::make_empty(env);
3495                 header.parameters = Self::could_map(Self::p_fun_param, &c.lambda_parameters, env)?;
3496                 header.return_type = Self::mp_optional(Self::p_hint, &c.lambda_type, env)?;
3497                 Ok(header)
3498             }
3499             Token(_) => Ok(FunHdr::make_empty(env)),
3500             _ => Self::missing_syntax(None, "function header", node, env),
3501         }
3502     }
3504     fn determine_variadicity(params: &[aast!(FunParam<,>)]) -> aast!(FunVariadicity<,>) {
3505         use aast::FunVariadicity::*;
3506         if let Some(x) = params.last() {
3507             match (x.is_variadic, &x.name) {
3508                 (false, _) => FVnonVariadic,
3509                 (true, name) if name == "..." => FVellipsis(x.pos.clone()),
3510                 (true, _) => FVvariadicArg(x.clone()),
3511             }
3512         } else {
3513             FVnonVariadic
3514         }
3515     }
3517     // TODO: change name to p_fun_pos after porting.
3518     fn p_function(node: &Syntax<T, V>, env: &Env) -> Pos {
3519         let get_pos = |n: &Syntax<T, V>, p: Pos| -> Pos {
3520             if let FunctionDeclarationHeader(c1) = &n.syntax {
3521                 if !c1.function_keyword.value.is_missing() {
3522                     return Pos::btw_nocheck(Self::p_pos(n, env), p);
3523                 }
3524             }
3525             p
3526         };
3527         let p = Self::p_pos(node, env);
3528         match &node.syntax {
3529             FunctionDeclaration(c) if env.codegen() => get_pos(&c.function_declaration_header, p),
3530             MethodishDeclaration(c) if env.codegen() => {
3531                 get_pos(&c.methodish_function_decl_header, p)
3532             }
3533             _ => p,
3534         }
3535     }
3537     fn p_block(remove_noop: bool, node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Block<,>) {
3538         let aast::Stmt(p, stmt_) = Self::p_stmt(node, env)?;
3539         if let aast::Stmt_::Block(blk) = stmt_ {
3540             if remove_noop && blk.len() == 1 {
3541                 if let aast::Stmt_::Noop = blk[0].1 {
3542                     return Ok(vec![]);
3543                 }
3544             }
3545             return Ok(blk);
3546         } else {
3547             Ok(vec![aast::Stmt(p, stmt_)])
3548         }
3549     }
3551     fn mk_noop(env: &Env) -> aast!(Stmt<,>) {
3552         aast::Stmt::noop(env.mk_none_pos())
3553     }
3555     fn p_function_body(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Block<,>) {
3556         let mk_noop_result = |e: &Env| Ok(vec![Self::mk_noop(e)]);
3557         let f = |e: &mut Env| -> ret_aast!(Block<,>) {
3558             match &node.syntax {
3559                 Missing => Ok(vec![]),
3560                 CompoundStatement(c) => {
3561                     let compound_statements = &c.compound_statements.syntax;
3562                     let compound_right_brace = &c.compound_right_brace.syntax;
3563                     match (compound_statements, compound_right_brace) {
3564                         (Missing, Token(_)) => mk_noop_result(e),
3565                         (SyntaxList(t), _) if t.len() == 1 && t[0].is_yield() => {
3566                             e.saw_yield = true;
3567                             mk_noop_result(e)
3568                         }
3569                         _ => {
3570                             if !e.top_level_statements
3571                                 && ((e.file_mode() == file_info::Mode::Mdecl && !e.codegen())
3572                                     || e.quick_mode)
3573                             {
3574                                 mk_noop_result(e)
3575                             } else {
3576                                 Self::p_block(false /*remove noop*/, node, e)
3577                             }
3578                         }
3579                     }
3580                 }
3581                 _ => {
3582                     let f = |e: &mut Env| {
3583                         let expr = Self::p_expr(node, e)?;
3584                         Ok(aast::Stmt::new(
3585                             expr.0.clone(),
3586                             aast::Stmt_::mk_return(Some(expr)),
3587                         ))
3588                     };
3589                     Ok(vec![Self::lift_awaits_in_statement(f, node, e)?])
3590                 }
3591             }
3592         };
3593         Self::with_new_nonconcurrent_scrope(f, env)
3594     }
3596     fn mk_suspension_kind(
3597         node: &Syntax<T, V>,
3598         env: &mut Env,
3599         async_keyword: &Syntax<T, V>,
3600         coroutine_keyword: &Syntax<T, V>,
3601     ) -> SuspensionKind {
3602         Self::mk_suspension_kind_(
3603             node,
3604             env,
3605             !async_keyword.is_missing(),
3606             !coroutine_keyword.is_missing(),
3607         )
3608     }
3610     fn mk_suspension_kind_(
3611         node: &Syntax<T, V>,
3612         env: &mut Env,
3613         has_async: bool,
3614         has_coroutine: bool,
3615     ) -> SuspensionKind {
3616         use SuspensionKind::*;
3617         match (has_async, has_coroutine) {
3618             (false, false) => SKSync,
3619             (true, false) => SKAsync,
3620             (false, true) => SKCoroutine,
3621             (true, true) => {
3622                 Self::raise_parsing_error(node, env, "Coroutine functions may not be async");
3623                 SKCoroutine
3624             }
3625         }
3626     }
3628     fn mk_fun_kind(suspension_kind: SuspensionKind, yield_: bool) -> ast_defs::FunKind {
3629         use ast_defs::FunKind::*;
3630         use SuspensionKind::*;
3631         match (suspension_kind, yield_) {
3632             (SKSync, true) => FGenerator,
3633             (SKAsync, true) => FAsyncGenerator,
3634             (SKSync, false) => FSync,
3635             (SKAsync, false) => FAsync,
3636             (SKCoroutine, _) => FCoroutine,
3637         }
3638     }
3640     fn process_attribute_constructor_call(
3641         node: &Syntax<T, V>,
3642         constructor_call_argument_list: &Syntax<T, V>,
3643         constructor_call_type: &Syntax<T, V>,
3644         env: &mut Env,
3645     ) -> ret_aast!(UserAttribute<,>) {
3646         let name = Self::pos_name(constructor_call_type, env)?;
3647         if name.1.eq_ignore_ascii_case("__reified")
3648             || name.1.eq_ignore_ascii_case("__hasreifiedparent")
3649         {
3650             Self::raise_parsing_error(node, env, &syntax_error::reified_attribute);
3651         } else if name.1.eq_ignore_ascii_case("__soft")
3652             && Self::as_list(constructor_call_argument_list).len() > 0
3653         {
3654             Self::raise_parsing_error(node, env, &syntax_error::soft_no_arguments);
3655         }
3656         let params = Self::could_map(
3657             |n: &Syntax<T, V>, e: &mut Env| -> ret_aast!(Expr<,>) {
3658                 if let ScopeResolutionExpression(c) = &n.syntax {
3659                     if let Some(TK::Name) = Self::token_kind(&c.scope_resolution_name) {
3660                         Self::raise_parsing_error(
3661                             n,
3662                             e,
3663                             &syntax_error::constants_as_attribute_arguments,
3664                         );
3665                     }
3666                 } else if let Some(TK::Name) = Self::token_kind(n) {
3667                     Self::raise_parsing_error(
3668                         n,
3669                         e,
3670                         &syntax_error::constants_as_attribute_arguments,
3671                     );
3672                 }
3673                 Self::p_expr(n, e)
3674             },
3675             constructor_call_argument_list,
3676             env,
3677         )?;
3678         Ok(aast::UserAttribute { name, params })
3679     }
3681     fn p_user_attribute(node: &Syntax<T, V>, env: &mut Env) -> ret!(Vec<aast!(UserAttribute<,>)>) {
3682         let p_attr = |n: &Syntax<T, V>, e: &mut Env| -> ret_aast!(UserAttribute<,>) {
3683             match &n.syntax {
3684                 ConstructorCall(c) => Self::process_attribute_constructor_call(
3685                     node,
3686                     &c.constructor_call_argument_list,
3687                     &c.constructor_call_type,
3688                     e,
3689                 ),
3690                 _ => Self::missing_syntax(None, "attribute", node, e),
3691             }
3692         };
3693         match &node.syntax {
3694             FileAttributeSpecification(c) => {
3695                 Self::could_map(p_attr, &c.file_attribute_specification_attributes, env)
3696             }
3697             OldAttributeSpecification(c) => {
3698                 Self::could_map(p_attr, &c.old_attribute_specification_attributes, env)
3699             }
3700             AttributeSpecification(c) => Self::could_map(
3701                 |n: &Syntax<T, V>, e: &mut Env| -> ret_aast!(UserAttribute<,>) {
3702                     match &n.syntax {
3703                         Attribute(c) => p_attr(&c.attribute_attribute_name, e),
3704                         _ => Self::missing_syntax(None, "attribute", node, e),
3705                     }
3706                 },
3707                 &c.attribute_specification_attributes,
3708                 env,
3709             ),
3710             _ => Self::missing_syntax(None, "attribute specification", node, env),
3711         }
3712     }
3714     fn p_user_attributes(node: &Syntax<T, V>, env: &mut Env) -> ret!(Vec<aast!(UserAttribute<,>)>) {
3715         Self::map_fold(
3716             &Self::p_user_attribute,
3717             &|mut acc: Vec<aast!(UserAttribute<,>)>, mut x: Vec<aast!(UserAttribute<,>)>| {
3718                 acc.append(&mut x);
3719                 acc
3720             },
3721             node,
3722             env,
3723             vec![],
3724         )
3725     }
3727     fn mp_yielding<F, R>(p: F, node: &Syntax<T, V>, env: &mut Env) -> ret!((R, bool))
3728     where
3729         F: FnOnce(&Syntax<T, V>, &mut Env) -> ret!(R),
3730     {
3731         let outer_saw_yield = env.saw_yield;
3732         env.saw_yield = false;
3733         let r = p(node, env);
3734         let saw_yield = env.saw_yield;
3735         env.saw_yield = outer_saw_yield;
3736         Ok((r?, saw_yield))
3737     }
3739     fn mk_empty_ns_env(env: &Env) -> RcOc<NamespaceEnv> {
3740         RcOc::clone(&env.empty_ns_env)
3741     }
3743     fn extract_docblock(node: &Syntax<T, V>, env: &Env) -> Option<DocComment> {
3744         #[derive(Copy, Clone, Eq, PartialEq)]
3745         enum ScanState {
3746             DocComment,
3747             EmbeddedCmt,
3748             EndDoc,
3749             EndEmbedded,
3750             Free,
3751             LineCmt,
3752             MaybeDoc,
3753             MaybeDoc2,
3754             SawSlash,
3755         }
3756         use ScanState::*;
3757         // `parse` mixes loop and recursion to use less stack space.
3758         fn parse(str: &str, start: usize, state: ScanState, idx: usize) -> Option<String> {
3759             let is_whitespace = |c| c == ' ' || c == '\t' || c == '\n' || c == '\r';
3760             let mut s = (start, state, idx);
3761             let chars = str.as_bytes();
3762             loop {
3763                 if s.2 == str.len() {
3764                     break None;
3765                 }
3767                 let next = s.2 + 1;
3768                 match (s.1, chars[s.2] as char) {
3769                     (LineCmt, '\n') => s = (next, Free, next),
3770                     (EndEmbedded, '/') => s = (next, Free, next),
3771                     (EndDoc, '/') => {
3772                         let r = parse(str, next, Free, next);
3773                         match r {
3774                             d @ Some(_) => break d,
3775                             None => break Some(String::from(&str[s.0..s.2 + 1])),
3776                         }
3777                     }
3778                     /* PHP has line comments delimited by a # */
3779                     (Free, '#') => s = (next, LineCmt, next),
3780                     /* All other comment delimiters start with a / */
3781                     (Free, '/') => s = (s.2, SawSlash, next),
3782                     /* After a / in trivia, we must see either another / or a * */
3783                     (SawSlash, '/') => s = (next, LineCmt, next),
3784                     (SawSlash, '*') => s = (s.0, MaybeDoc, next),
3785                     (MaybeDoc, '*') => s = (s.0, MaybeDoc2, next),
3786                     (MaybeDoc, _) => s = (s.0, EmbeddedCmt, next),
3787                     (MaybeDoc2, '/') => s = (next, Free, next),
3788                     /* Doc comments have a space after the second star */
3789                     (MaybeDoc2, c) if is_whitespace(c) => s = (s.0, DocComment, s.2),
3790                     (MaybeDoc2, _) => s = (s.0, EmbeddedCmt, next),
3791                     (DocComment, '*') => s = (s.0, EndDoc, next),
3792                     (DocComment, _) => s = (s.0, DocComment, next),
3793                     (EndDoc, _) => s = (s.0, DocComment, next),
3794                     /* A * without a / does not end an embedded comment */
3795                     (EmbeddedCmt, '*') => s = (s.0, EndEmbedded, next),
3796                     (EndEmbedded, '*') => s = (s.0, EndEmbedded, next),
3797                     (EndEmbedded, _) => s = (s.0, EmbeddedCmt, next),
3798                     /* Whitespace skips everywhere else */
3799                     (_, c) if is_whitespace(c) => s = (s.0, s.1, next),
3800                     /* When scanning comments, anything else is accepted */
3801                     (LineCmt, _) => s = (s.0, s.1, next),
3802                     (EmbeddedCmt, _) => s = (s.0, s.1, next),
3803                     _ => break None,
3804                 }
3805             }
3806         }
3807         let str = node.leading_text(env.indexed_source_text.source_text());
3808         parse(str, 0, Free, 0).map(Rc::new)
3809     }
3811     fn p_xhp_child(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(XhpChild) {
3812         use aast::XhpChild::*;
3813         use aast::XhpChildOp::*;
3814         match &node.syntax {
3815             Token(_) => Self::pos_name(node, env).map(ChildName),
3816             PostfixUnaryExpression(c) => {
3817                 let operand = Self::p_xhp_child(&c.postfix_unary_operand, env)?;
3818                 let operator = match Self::token_kind(&c.postfix_unary_operator) {
3819                     Some(TK::Question) => ChildQuestion,
3820                     Some(TK::Plus) => ChildPlus,
3821                     Some(TK::Star) => ChildStar,
3822                     _ => Self::missing_syntax(None, "xhp children operator", node, env)?,
3823                 };
3824                 Ok(ChildUnary(Box::new(operand), operator))
3825             }
3826             BinaryExpression(c) => {
3827                 let left = Self::p_xhp_child(&c.binary_left_operand, env)?;
3828                 let right = Self::p_xhp_child(&c.binary_right_operand, env)?;
3829                 Ok(ChildBinary(Box::new(left), Box::new(right)))
3830             }
3831             XHPChildrenParenthesizedList(c) => {
3832                 let children = Self::as_list(&c.xhp_children_list_xhp_children);
3833                 let children: std::result::Result<Vec<_>, _> =
3834                     children.iter().map(|c| Self::p_xhp_child(c, env)).collect();
3835                 Ok(ChildList(children?))
3836             }
3837             _ => Self::missing_syntax(None, "xhp children", node, env),
3838         }
3839     }
3841     fn p_class_elt_(class: &mut aast!(Class_<,>), node: &Syntax<T, V>, env: &mut Env) -> ret!(()) {
3842         let doc_comment_opt = Self::extract_docblock(node, env);
3843         let has_fun_header = |m: &MethodishDeclarationChildren<T, V>| {
3844             if let FunctionDeclarationHeader(_) = m.methodish_function_decl_header.syntax {
3845                 return true;
3846             }
3847             false
3848         };
3849         let has_fun_header_mtr = |m: &MethodishTraitResolutionChildren<T, V>| {
3850             if let FunctionDeclarationHeader(_) = m.methodish_trait_function_decl_header.syntax {
3851                 return true;
3852             }
3853             false
3854         };
3855         let p_method_vis = |node: &Syntax<T, V>, env: &mut Env| -> ret_aast!(Visibility) {
3856             match Self::p_visibility_last_win(node, env)? {
3857                 None => {
3858                     Self::raise_nast_error("method_needs_visiblity");
3859                     Ok(aast::Visibility::Public)
3860                 }
3861                 Some(v) => Ok(v),
3862             }
3863         };
3864         match &node.syntax {
3865             ConstDeclaration(c) => {
3866                 // TODO: make wrap `type_` `doc_comment` by `Rc` in ClassConst to avoid clone
3867                 let type_ = Self::mp_optional(Self::p_hint, &c.const_type_specifier, env)?;
3868                 // using map_fold can save one Vec allocation, but ocaml's behavior is that
3869                 // if anything throw, it will discard all lowered elements. So adding to class
3870                 // must be at the last.
3871                 let mut class_consts = Self::could_map(
3872                     |n: &Syntax<T, V>, e: &mut Env| -> ret_aast!(ClassConst<,>) {
3873                         match &n.syntax {
3874                             ConstantDeclarator(c) => {
3875                                 let id = Self::pos_name(&c.constant_declarator_name, e)?;
3876                                 let expr = if n.is_abstract() {
3877                                     None
3878                                 } else {
3879                                     Self::mp_optional(
3880                                         Self::p_simple_initializer,
3881                                         &c.constant_declarator_initializer,
3882                                         e,
3883                                     )?
3884                                 };
3885                                 Ok(aast::ClassConst {
3886                                     type_: type_.clone(),
3887                                     id,
3888                                     expr,
3889                                     doc_comment: doc_comment_opt.clone(),
3890                                 })
3891                             }
3892                             _ => Self::missing_syntax(None, "constant declarator", n, e),
3893                         }
3894                     },
3895                     &c.const_declarators,
3896                     env,
3897                 )?;
3898                 Ok(class.consts.append(&mut class_consts))
3899             }
3900             TypeConstDeclaration(c) => {
3901                 if !c.type_const_type_parameters.is_missing() {
3902                     Self::raise_parsing_error(node, env, &syntax_error::tparams_in_tconst);
3903                 }
3904                 let user_attributes = Self::p_user_attributes(&c.type_const_attribute_spec, env)?;
3905                 let type__ = Self::mp_optional(Self::p_hint, &c.type_const_type_specifier, env)?
3906                     .map(|hint| Self::soften_hint(&user_attributes, hint));
3907                 let kinds = Self::p_kinds(&c.type_const_modifiers, env)?;
3908                 let name = Self::pos_name(&c.type_const_name, env)?;
3909                 let constraint =
3910                     Self::mp_optional(Self::p_tconstraint_ty, &c.type_const_type_constraint, env)?;
3911                 let span = Self::p_pos(node, env);
3912                 let has_abstract = kinds.has(modifier::ABSTRACT);
3913                 let (type_, abstract_kind) = match (has_abstract, &constraint, &type__) {
3914                     (false, _, None) => {
3915                         Self::raise_nast_error("not_abstract_without_typeconst");
3916                         (constraint.clone(), aast::TypeconstAbstractKind::TCConcrete)
3917                     }
3918                     (false, None, Some(_)) => (type__, aast::TypeconstAbstractKind::TCConcrete),
3919                     (false, Some(_), Some(_)) => {
3920                         (type__, aast::TypeconstAbstractKind::TCPartiallyAbstract)
3921                     }
3922                     (true, _, None) => (
3923                         type__.clone(),
3924                         aast::TypeconstAbstractKind::TCAbstract(type__),
3925                     ),
3926                     (true, _, Some(_)) => (None, aast::TypeconstAbstractKind::TCAbstract(type__)),
3927                 };
3928                 Ok(class.typeconsts.push(aast::ClassTypeconst {
3929                     abstract_: abstract_kind,
3930                     name,
3931                     constraint,
3932                     type_,
3933                     user_attributes,
3934                     span,
3935                     doc_comment: doc_comment_opt,
3936                 }))
3937             }
3938             PropertyDeclaration(c) => {
3939                 let user_attributes = Self::p_user_attributes(&c.property_attribute_spec, env)?;
3940                 let type_ = Self::mp_optional(Self::p_hint, &c.property_type, env)?
3941                     .map(|t| Self::soften_hint(&user_attributes, t));
3942                 let kinds = Self::p_kinds(&c.property_modifiers, env)?;
3943                 let vis = Self::p_visibility_last_win_or(
3944                     &c.property_modifiers,
3945                     env,
3946                     aast::Visibility::Public,
3947                 )?;
3948                 let doc_comment = if env.quick_mode {
3949                     None
3950                 } else {
3951                     doc_comment_opt
3952                 };
3953                 let name_exprs = Self::could_map(
3954                     |n, e| -> ret!((Pos, aast!(Sid), Option<aast!(Expr<,>)>)) {
3955                         match &n.syntax {
3956                             PropertyDeclarator(c) => {
3957                                 let name = Self::pos_name_(&c.property_name, e, Some('$'))?;
3958                                 let pos = Self::p_pos(n, e);
3959                                 let expr = Self::mp_optional(
3960                                     Self::p_simple_initializer,
3961                                     &c.property_initializer,
3962                                     e,
3963                                 )?;
3964                                 Ok((pos, name, expr))
3965                             }
3966                             _ => Self::missing_syntax(None, "property declarator", n, e),
3967                         }
3968                     },
3969                     &c.property_declarators,
3970                     env,
3971                 )?;
3973                 let mut i = 0;
3974                 for name_expr in name_exprs.into_iter() {
3975                     class.vars.push(aast::ClassVar {
3976                         final_: kinds.has(modifier::FINAL),
3977                         xhp_attr: None,
3978                         abstract_: kinds.has(modifier::ABSTRACT),
3979                         visibility: vis,
3980                         type_: type_.clone(),
3981                         id: name_expr.1,
3982                         expr: name_expr.2,
3983                         user_attributes: user_attributes.clone(),
3984                         doc_comment: if i == 0 { doc_comment.clone() } else { None },
3985                         is_promoted_variadic: false,
3986                         is_static: kinds.has(modifier::STATIC),
3987                         span: name_expr.0,
3988                     });
3989                     i += 1;
3990                 }
3991                 Ok(())
3992             }
3993             MethodishDeclaration(c) if has_fun_header(c) => {
3994                 let classvar_init =
3995                     |param: &aast!(FunParam<,>)| -> (aast!(Stmt<,>), aast!(ClassVar<,>)) {
3996                         let cvname = Self::drop_prefix(&param.name, '$');
3997                         let p = &param.pos;
3998                         let span = match &param.expr {
3999                             Some(aast::Expr(pos_end, _)) => {
4000                                 Pos::btw(p, pos_end).unwrap_or_else(|_| p.clone())
4001                             }
4002                             _ => p.clone(),
4003                         };
4004                         let e = |expr_: aast!(Expr_<,>)| -> aast!(Expr<,>) {
4005                             aast::Expr::new(p.clone(), expr_)
4006                         };
4007                         let lid =
4008                             |s: &str| -> aast!(Lid) { aast::Lid(p.clone(), (0, s.to_string())) };
4009                         (
4010                             aast::Stmt::new(
4011                                 p.clone(),
4012                                 aast::Stmt_::mk_expr(e(E_::mk_binop(
4013                                     ast_defs::Bop::Eq(None),
4014                                     e(E_::mk_obj_get(
4015                                         e(E_::mk_lvar(lid("$this"))),
4016                                         e(E_::mk_id(ast_defs::Id(p.clone(), cvname.to_string()))),
4017                                         aast::OgNullFlavor::OGNullthrows,
4018                                     )),
4019                                     e(E_::mk_lvar(lid(&param.name))),
4020                                 ))),
4021                             ),
4022                             aast::ClassVar {
4023                                 final_: false,
4024                                 xhp_attr: None,
4025                                 abstract_: false,
4026                                 visibility: param.visibility.unwrap(),
4027                                 type_: param.type_hint.1.clone(),
4028                                 id: ast_defs::Id(p.clone(), cvname.to_string()),
4029                                 expr: None,
4030                                 user_attributes: param.user_attributes.clone(),
4031                                 doc_comment: None,
4032                                 is_promoted_variadic: param.is_variadic,
4033                                 is_static: false,
4034                                 span,
4035                             },
4036                         )
4037                     };
4038                 let header = &c.methodish_function_decl_header;
4039                 let h = match &header.syntax {
4040                     FunctionDeclarationHeader(h) => h,
4041                     _ => panic!(),
4042                 };
4043                 let hdr = Self::p_fun_hdr(header, env)?;
4044                 if hdr.name.1 == "__construct" && !hdr.type_parameters.is_empty() {
4045                     Self::raise_parsing_error(
4046                         header,
4047                         env,
4048                         &syntax_error::no_generics_on_constructors,
4049                     );
4050                 }
4051                 let (mut member_init, mut member_def): (
4052                     Vec<aast!(Stmt<,>)>,
4053                     Vec<aast!(ClassVar<,>)>,
4054                 ) = hdr
4055                     .parameters
4056                     .iter()
4057                     .filter_map(|p| p.visibility.map(|_| classvar_init(p)))
4058                     .unzip();
4060                 let kinds = Self::p_kinds(&h.function_modifiers, env)?;
4061                 let visibility = p_method_vis(&h.function_modifiers, env)?;
4062                 let is_static = kinds.has(modifier::STATIC);
4063                 *env.in_static_method() = is_static;
4064                 let (mut body, body_has_yield) =
4065                     Self::mp_yielding(Self::p_function_body, &c.methodish_function_body, env)?;
4066                 if env.codegen() {
4067                     member_init.reverse();
4068                 }
4069                 member_init.append(&mut body);
4070                 let body = member_init;
4071                 *env.in_static_method() = false;
4072                 let is_abstract = kinds.has(modifier::ABSTRACT);
4073                 let is_external = !is_abstract && c.methodish_function_body.is_external();
4074                 let user_attributes = Self::p_user_attributes(&c.methodish_attribute, env)?;
4075                 let method = aast::Method_ {
4076                     span: Self::p_function(node, env),
4077                     annotation: (),
4078                     final_: kinds.has(modifier::FINAL),
4079                     abstract_: is_abstract,
4080                     static_: is_static,
4081                     name: hdr.name,
4082                     visibility,
4083                     tparams: hdr.type_parameters,
4084                     where_constraints: hdr.constrs,
4085                     variadic: Self::determine_variadicity(&hdr.parameters),
4086                     params: hdr.parameters,
4087                     body: aast::FuncBody {
4088                         annotation: (),
4089                         ast: body,
4090                     },
4091                     fun_kind: Self::mk_fun_kind(hdr.suspension_kind, body_has_yield),
4092                     user_attributes,
4093                     ret: aast::TypeHint((), hdr.return_type),
4094                     external: is_external,
4095                     doc_comment: doc_comment_opt,
4096                 };
4097                 class.vars.append(&mut member_def);
4098                 Ok(class.methods.push(method))
4099             }
4100             MethodishTraitResolution(c) if has_fun_header_mtr(c) => {
4101                 let header = &c.methodish_trait_function_decl_header;
4102                 let h = match &header.syntax {
4103                     FunctionDeclarationHeader(h) => h,
4104                     _ => panic!(),
4105                 };
4106                 let hdr = Self::p_fun_hdr(header, env)?;
4107                 let kind = Self::p_kinds(&h.function_modifiers, env)?;
4108                 let (qualifier, name) = match &c.methodish_trait_name.syntax {
4109                     ScopeResolutionExpression(c) => (
4110                         Self::p_hint(&c.scope_resolution_qualifier, env)?,
4111                         Self::p_pstring(&c.scope_resolution_name, env)?,
4112                     ),
4113                     _ => Self::missing_syntax(None, "trait method redeclaration", node, env)?,
4114                 };
4115                 let user_attributes = Self::p_user_attributes(&c.methodish_trait_attribute, env)?;
4116                 let visibility = p_method_vis(&h.function_modifiers, env)?;
4117                 let mtr = aast::MethodRedeclaration {
4118                     final_: kind.has(modifier::FINAL),
4119                     abstract_: kind.has(modifier::ABSTRACT),
4120                     static_: kind.has(modifier::STATIC),
4121                     visibility,
4122                     name: hdr.name,
4123                     tparams: hdr.type_parameters,
4124                     where_constraints: hdr.constrs,
4125                     variadic: Self::determine_variadicity(&hdr.parameters),
4126                     params: hdr.parameters,
4127                     fun_kind: Self::mk_fun_kind(hdr.suspension_kind, false),
4128                     ret: aast::TypeHint((), hdr.return_type),
4129                     trait_: qualifier,
4130                     method: name,
4131                     user_attributes,
4132                 };
4133                 class.method_redeclarations.push(mtr);
4134                 Ok(())
4135             }
4136             TraitUseConflictResolution(c) => {
4137                 type Ret = ret!(Either<aast!(InsteadofAlias), aast!(UseAsAlias)>);
4138                 let p_item = |n: &Syntax<T, V>, e: &mut Env| -> Ret {
4139                     match &n.syntax {
4140                         TraitUsePrecedenceItem(c) => {
4141                             let removed_names = &c.trait_use_precedence_item_removed_names;
4142                             let (qualifier, name) = match &c.trait_use_precedence_item_name.syntax {
4143                                 ScopeResolutionExpression(c) => (
4144                                     Self::pos_name(&c.scope_resolution_qualifier, e)?,
4145                                     Self::p_pstring(&c.scope_resolution_name, e)?,
4146                                 ),
4147                                 _ => Self::missing_syntax(None, "trait use precedence item", n, e)?,
4148                             };
4149                             let removed_names = Self::could_map(Self::pos_name, removed_names, e)?;
4150                             Self::raise_nast_error("unsupported_instead_of");
4151                             Ok(Either::Left(aast::InsteadofAlias(
4152                                 qualifier,
4153                                 name,
4154                                 removed_names,
4155                             )))
4156                         }
4157                         TraitUseAliasItem(c) => {
4158                             let aliasing_name = &c.trait_use_alias_item_aliasing_name;
4159                             let modifiers = &c.trait_use_alias_item_modifiers;
4160                             let aliased_name = &c.trait_use_alias_item_aliased_name;
4161                             let (qualifier, name) = match &aliasing_name.syntax {
4162                                 ScopeResolutionExpression(c) => (
4163                                     Some(Self::pos_name(&c.scope_resolution_qualifier, e)?),
4164                                     Self::p_pstring(&c.scope_resolution_name, e)?,
4165                                 ),
4166                                 _ => (None, Self::p_pstring(aliasing_name, e)?),
4167                             };
4168                             let (kinds, mut vis_raw) = Self::p_modifiers(
4169                                 |mut acc, kind| -> Vec<aast_defs::UseAsVisibility> {
4170                                     if let Some(v) = modifier::to_use_as_visibility(kind) {
4171                                         acc.push(v);
4172                                     }
4173                                     acc
4174                                 },
4175                                 vec![],
4176                                 modifiers,
4177                                 e,
4178                             )?;
4179                             let vis = if kinds.is_empty() || kinds.has_any(modifier::VISIBILITIES) {
4180                                 vis_raw
4181                             } else {
4182                                 let mut v = vec![aast::UseAsVisibility::UseAsPublic];
4183                                 v.append(&mut vis_raw);
4184                                 v
4185                             };
4186                             let aliased_name = if !aliased_name.is_missing() {
4187                                 Some(Self::pos_name(aliased_name, e)?)
4188                             } else {
4189                                 None
4190                             };
4191                             Self::raise_nast_error("unsupported_trait_use_as");
4192                             Ok(Either::Right(aast::UseAsAlias(
4193                                 qualifier,
4194                                 name,
4195                                 aliased_name,
4196                                 vis,
4197                             )))
4198                         }
4199                         _ => Self::missing_syntax(None, "trait use conflict resolution item", n, e),
4200                     }
4201                 };
4202                 let mut uses =
4203                     Self::could_map(Self::p_hint, &c.trait_use_conflict_resolution_names, env)?;
4204                 let elts = Self::could_map(p_item, &c.trait_use_conflict_resolution_clauses, env)?;
4205                 class.uses.append(&mut uses);
4206                 for elt in elts.into_iter() {
4207                     match elt {
4208                         Either::Left(l) => class.insteadof_alias.push(l),
4209                         Either::Right(r) => class.use_as_alias.push(r),
4210                     }
4211                 }
4212                 Ok(())
4213             }
4214             TraitUse(c) => {
4215                 let mut uses = Self::could_map(Self::p_hint, &c.trait_use_names, env)?;
4216                 Ok(class.uses.append(&mut uses))
4217             }
4218             RequireClause(c) => {
4219                 let hint = Self::p_hint(&c.require_name, env)?;
4220                 let is_extends = match Self::token_kind(&c.require_kind) {
4221                     Some(TK::Implements) => false,
4222                     Some(TK::Extends) => true,
4223                     _ => Self::missing_syntax(None, "trait require kind", &c.require_kind, env)?,
4224                 };
4225                 Ok(class.reqs.push((hint, is_extends)))
4226             }
4227             XHPClassAttributeDeclaration(c) => {
4228                 type Ret = ret!(Either<aast!(XhpAttr<,>), aast!(Hint)>);
4229                 let p_attr = |node: &Syntax<T, V>, env: &mut Env| -> Ret {
4230                     let mut mk_attr_use = |n: &Syntax<T, V>| {
4231                         Ok(Either::Right(aast::Hint(
4232                             Self::p_pos(n, env),
4233                             Box::new(aast::Hint_::Happly(Self::pos_name(n, env)?, vec![])),
4234                         )))
4235                     };
4236                     match &node.syntax {
4237                         XHPClassAttribute(c) => {
4238                             let ty = &c.xhp_attribute_decl_type;
4239                             let init = &c.xhp_attribute_decl_initializer;
4240                             let ast_defs::Id(p, name) =
4241                                 Self::pos_name(&c.xhp_attribute_decl_name, env)?;
4242                             match &ty.syntax {
4243                                 TypeConstant(_) if env.is_typechecker() => {
4244                                     Self::raise_parsing_error(
4245                                         ty,
4246                                         env,
4247                                         &syntax_error::xhp_class_attribute_type_constant,
4248                                     )
4249                                 }
4250                                 _ => {}
4251                             }
4252                             let req = match &c.xhp_attribute_decl_required.syntax {
4253                                 XHPRequired(_) => Some(aast::XhpAttrTag::Required),
4254                                 XHPLateinit(_) => Some(aast::XhpAttrTag::LateInit),
4255                                 _ => None,
4256                             };
4257                             let pos = if init.is_missing() {
4258                                 p.clone()
4259                             } else {
4260                                 Pos::btw(&p, &Self::p_pos(init, env)).map_err(Error::Failwith)?
4261                             };
4262                             let (hint, enum_) = match &ty.syntax {
4263                                 XHPEnumType(c) => {
4264                                     let p = Self::p_pos(ty, env);
4265                                     let opt = !(&c.xhp_enum_optional.is_missing());
4266                                     let vals =
4267                                         Self::could_map(Self::p_expr, &c.xhp_enum_values, env)?;
4268                                     (None, Some((p, opt, vals)))
4269                                 }
4270                                 _ => (Some(Self::p_hint(ty, env)?), None),
4271                             };
4272                             let init_expr =
4273                                 Self::mp_optional(Self::p_simple_initializer, init, env)?;
4274                             let xhp_attr = aast::XhpAttr(
4275                                 hint.clone(),
4276                                 aast::ClassVar {
4277                                     final_: false,
4278                                     xhp_attr: Some(aast::XhpAttrInfo { xai_tag: req }),
4279                                     abstract_: false,
4280                                     visibility: aast::Visibility::Public,
4281                                     type_: hint,
4282                                     id: ast_defs::Id(p, String::from(":") + &name),
4283                                     expr: init_expr,
4284                                     user_attributes: vec![],
4285                                     doc_comment: None,
4286                                     is_promoted_variadic: false,
4287                                     is_static: false,
4288                                     span: pos,
4289                                 },
4290                                 req,
4291                                 enum_,
4292                             );
4293                             Ok(Either::Left(xhp_attr))
4294                         }
4295                         XHPSimpleClassAttribute(c) => {
4296                             mk_attr_use(&c.xhp_simple_class_attribute_type)
4297                         }
4298                         Token(_) => mk_attr_use(node),
4299                         _ => Self::missing_syntax(None, "XHP attribute", node, env),
4300                     }
4301                 };
4302                 let attrs = Self::could_map(p_attr, &c.xhp_attribute_attributes, env)?;
4303                 for attr in attrs.into_iter() {
4304                     match attr {
4305                         Either::Left(attr) => class.xhp_attrs.push(attr),
4306                         Either::Right(xhp_attr_use) => class.xhp_attr_uses.push(xhp_attr_use),
4307                     }
4308                 }
4309                 Ok(())
4310             }
4311             XHPChildrenDeclaration(c) => {
4312                 let p = Self::p_pos(node, env);
4313                 Ok(class
4314                     .xhp_children
4315                     .push((p, Self::p_xhp_child(&c.xhp_children_expression, env)?)))
4316             }
4317             XHPCategoryDeclaration(c) => {
4318                 let p = Self::p_pos(node, env);
4319                 let categories = Self::could_map(
4320                     |n, e| Self::p_pstring_(n, e, Some('%')),
4321                     &c.xhp_category_categories,
4322                     env,
4323                 )?;
4324                 if let Some((_, cs)) = &class.xhp_category {
4325                     if cs.len() > 0 {
4326                         Self::raise_nast_error("multiple_xhp_category")
4327                     }
4328                 }
4329                 Ok(class.xhp_category = Some((p, categories)))
4330             }
4331             PocketEnumDeclaration(c) => {
4332                 let is_final = Self::p_kinds(&c.pocket_enum_modifiers, env)?.has(modifier::FINAL);
4333                 let id = Self::pos_name(&c.pocket_enum_name, env)?;
4334                 let flds = Self::as_list(&c.pocket_enum_fields);
4335                 let mut case_types = vec![];
4336                 let mut case_values = vec![];
4337                 let mut members = vec![];
4338                 for fld in flds.iter() {
4339                     match &fld.syntax {
4340                         PocketAtomMappingDeclaration(c) => {
4341                             let id = Self::pos_name(&c.pocket_atom_mapping_name, env)?;
4342                             let maps = Self::as_list(&c.pocket_atom_mapping_mappings);
4343                             let mut types = vec![];
4344                             let mut exprs = vec![];
4345                             for map in maps.iter() {
4346                                 match &map.syntax {
4347                                     PocketMappingIdDeclaration(c) => {
4348                                         let id = Self::pos_name(&c.pocket_mapping_id_name, env)?;
4349                                         let expr = Self::p_simple_initializer(
4350                                             &c.pocket_mapping_id_initializer,
4351                                             env,
4352                                         )?;
4353                                         exprs.push((id, expr));
4354                                     }
4355                                     PocketMappingTypeDeclaration(c) => {
4356                                         let id = Self::pos_name(&c.pocket_mapping_type_name, env)?;
4357                                         let hint = Self::p_hint(&c.pocket_mapping_type_type, env)?;
4358                                         types.push((id, hint));
4359                                     }
4360                                     _ => {
4361                                         Self::missing_syntax(None, "pumapping", map, env)?;
4362                                     }
4363                                 }
4364                             }
4365                             members.push(aast::PuMember {
4366                                 atom: id,
4367                                 types,
4368                                 exprs,
4369                             })
4370                         }
4371                         PocketFieldTypeExprDeclaration(c) => {
4372                             let typ = Self::p_hint(&c.pocket_field_type_expr_type, env)?;
4373                             let id = Self::pos_name(&c.pocket_field_type_expr_name, env)?;
4374                             case_values.push((id, typ));
4375                         }
4376                         PocketFieldTypeDeclaration(c) => {
4377                             let id = Self::pos_name(&c.pocket_field_type_name, env)?;
4378                             case_types.push(id);
4379                         }
4380                         _ => {
4381                             Self::missing_syntax(None, "pufield", fld, env)?;
4382                         }
4383                     }
4384                 }
4385                 Ok(class.pu_enums.push(aast::PuEnum {
4386                     name: id,
4387                     is_final,
4388                     case_types,
4389                     case_values,
4390                     members,
4391                 }))
4392             }
4393             _ => Self::missing_syntax(None, "class element", node, env),
4394         }
4395     }
4397     fn p_class_elt(class: &mut aast!(Class_<,>), node: &Syntax<T, V>, env: &mut Env) -> ret!(()) {
4398         let r = Self::p_class_elt_(class, node, env);
4399         match r {
4400             // match ocaml behavior, don't throw if missing syntax when fail_open is true
4401             Err(Error::APIMissingSyntax { .. }) if env.fail_open => Ok(()),
4402             _ => r,
4403         }
4404     }
4406     fn contains_class_body(c: &ClassishDeclarationChildren<T, V>) -> bool {
4407         match &c.classish_body.syntax {
4408             ClassishBody(_) => true,
4409             _ => false,
4410         }
4411     }
4413     fn p_where_constraint(
4414         is_class: bool,
4415         parent: &Syntax<T, V>,
4416         node: &Syntax<T, V>,
4417         env: &mut Env,
4418     ) -> ret!(Vec<aast!(WhereConstraint)>) {
4419         match &node.syntax {
4420             Missing => Ok(vec![]),
4421             WhereClause(c) => {
4422                 if is_class && !env.parser_options.po_enable_class_level_where_clauses {
4423                     Self::raise_parsing_error(
4424                         parent,
4425                         env,
4426                         "Class-level where clauses are disabled",
4427                     );
4428                 }
4429                 let f = |n: &Syntax<T, V>, e: &mut Env| -> ret_aast!(WhereConstraint) {
4430                     match &n.syntax {
4431                         WhereConstraint(c) => {
4432                             use ast_defs::ConstraintKind::*;
4433                             let l = Self::p_hint(&c.where_constraint_left_type, e)?;
4434                             let o = &c.where_constraint_operator;
4435                             let o = match Self::token_kind(o) {
4436                                 Some(TK::Equal) => ConstraintEq,
4437                                 Some(TK::As) => ConstraintAs,
4438                                 Some(TK::Super) => ConstraintSuper,
4439                                 _ => Self::missing_syntax(None, "constraint operator", o, e)?,
4440                             };
4441                             let r = Self::p_hint(&c.where_constraint_right_type, e)?;
4442                             Ok(aast::WhereConstraint(l, o, r))
4443                         }
4444                         _ => Self::missing_syntax(None, "where constraint", n, e),
4445                     }
4446                 };
4447                 Self::as_list(&c.where_clause_constraints)
4448                     .iter()
4449                     .map(|n| f(n, env))
4450                     .collect()
4451             }
4452             _ => {
4453                 if is_class {
4454                     Self::missing_syntax(None, "classish declaration constraints", parent, env)
4455                 } else {
4456                     Self::missing_syntax(None, "function header constraints", parent, env)
4457                 }
4458             }
4459         }
4460     }
4462     fn p_namespace_use_kind(kind: &Syntax<T, V>, env: &mut Env) -> ret_aast!(NsKind) {
4463         use aast::NsKind::*;
4464         match &kind.syntax {
4465             Missing => Ok(NSClassAndNamespace),
4466             _ => match Self::token_kind(kind) {
4467                 Some(TK::Namespace) => Ok(NSNamespace),
4468                 Some(TK::Type) => Ok(NSClass),
4469                 Some(TK::Function) => Ok(NSFun),
4470                 Some(TK::Const) => Ok(NSConst),
4471                 _ => Self::missing_syntax(None, "namespace use kind", kind, env),
4472             },
4473         }
4474     }
4476     fn p_namespace_use_clause(
4477         prefix: Option<&Syntax<T, V>>,
4478         kind: ret_aast!(NsKind),
4479         node: &Syntax<T, V>,
4480         env: &mut Env,
4481     ) -> ret!((aast!(NsKind), aast!(Sid), aast!(Sid))) {
4482         lazy_static! {
4483             static ref NAMESPACE_USE: regex::Regex = regex::Regex::new("[^\\\\]*$").unwrap();
4484         }
4486         match &node.syntax {
4487             NamespaceUseClause(c) => {
4488                 let clause_kind = &c.namespace_use_clause_kind;
4489                 let alias = &c.namespace_use_alias;
4490                 let name = &c.namespace_use_name;
4491                 let ast_defs::Id(p, n) = match (prefix, Self::pos_name(name, env)?) {
4492                     (None, id) => id,
4493                     (Some(prefix), ast_defs::Id(p, n)) => {
4494                         ast_defs::Id(p, Self::pos_name(prefix, env)?.1 + &n)
4495                     }
4496                 };
4497                 let alias = if alias.is_missing() {
4498                     let x = NAMESPACE_USE.find(&n).unwrap().as_str();
4499                     ast_defs::Id(p.clone(), x.to_string())
4500                 } else {
4501                     Self::pos_name(alias, env)?
4502                 };
4503                 let kind = if clause_kind.is_missing() {
4504                     kind
4505                 } else {
4506                     Self::p_namespace_use_kind(clause_kind, env)
4507                 }?;
4508                 Ok((
4509                     kind,
4510                     ast_defs::Id(
4511                         p,
4512                         if n.len() > 0 && n.chars().nth(0) == Some('\\') {
4513                             n
4514                         } else {
4515                             String::from("\\") + &n
4516                         },
4517                     ),
4518                     alias,
4519                 ))
4520             }
4521             _ => Self::missing_syntax(None, "namespace use clause", node, env),
4522         }
4523     }
4525     fn p_def(node: &Syntax<T, V>, env: &mut Env) -> ret!(Vec<aast!(Def<,>)>) {
4526         let doc_comment_opt = Self::extract_docblock(node, env);
4527         match &node.syntax {
4528             FunctionDeclaration(c) => {
4529                 let function_attribute_spec = &c.function_attribute_spec;
4530                 let function_declaration_header = &c.function_declaration_header;
4531                 let function_body = &c.function_body;
4532                 let mut env = Env::clone_and_unset_toplevel_if_toplevel(env);
4533                 let env = env.as_mut();
4534                 let hdr = Self::p_fun_hdr(function_declaration_header, env)?;
4535                 let is_external = function_body.is_external();
4536                 let (block, yield_) = if is_external {
4537                     (vec![], false)
4538                 } else {
4539                     Self::mp_yielding(&Self::p_function_body, function_body, env)?
4540                 };
4541                 let user_attributes = Self::p_user_attributes(function_attribute_spec, env)?;
4542                 let variadic = Self::determine_variadicity(&hdr.parameters);
4543                 let ret = aast::TypeHint((), hdr.return_type);
4544                 Ok(vec![aast::Def::mk_fun(aast::Fun_ {
4545                     span: Self::p_function(node, env),
4546                     annotation: (),
4547                     mode: Self::mode_annotation(env.file_mode()),
4548                     ret,
4549                     name: hdr.name,
4550                     tparams: hdr.type_parameters,
4551                     where_constraints: hdr.constrs,
4552                     params: hdr.parameters,
4553                     body: aast::FuncBody {
4554                         ast: block,
4555                         annotation: (),
4556                     },
4557                     fun_kind: Self::mk_fun_kind(hdr.suspension_kind, yield_),
4558                     variadic,
4559                     user_attributes,
4560                     file_attributes: vec![],
4561                     external: is_external,
4562                     namespace: Self::mk_empty_ns_env(env),
4563                     doc_comment: doc_comment_opt,
4564                     static_: false,
4565                 })])
4566             }
4567             ClassishDeclaration(c) if Self::contains_class_body(c) => {
4568                 let mut env = Env::clone_and_unset_toplevel_if_toplevel(env);
4569                 let env = env.as_mut();
4570                 let mode = Self::mode_annotation(env.file_mode());
4571                 let user_attributes = Self::p_user_attributes(&c.classish_attribute, env)?;
4572                 let kinds = Self::p_kinds(&c.classish_modifiers, env)?;
4573                 let final_ = kinds.has(modifier::FINAL);
4574                 let is_xhp = match Self::token_kind(&c.classish_name) {
4575                     Some(TK::XHPElementName) => true,
4576                     Some(TK::XHPClassName) => true,
4577                     _ => false,
4578                 };
4579                 let name = Self::pos_name(&c.classish_name, env)?;
4580                 *env.cls_reified_generics() = HashSet::new();
4581                 let tparams = aast::ClassTparams {
4582                     list: Self::p_tparam_l(true, &c.classish_type_parameters, env)?,
4583                     constraints: s_map::SMap::new(),
4584                 };
4585                 let extends = Self::could_map(Self::p_hint, &c.classish_extends_list, env)?;
4586                 *env.parent_maybe_reified() = match extends.first().map(|h| h.1.as_ref()) {
4587                     Some(aast::Hint_::Happly(_, hl)) => !hl.is_empty(),
4588                     _ => false,
4589                 };
4590                 let implements = Self::could_map(Self::p_hint, &c.classish_implements_list, env)?;
4591                 let where_constraints =
4592                     Self::p_where_constraint(true, node, &c.classish_where_clause, env)?;
4593                 let namespace = Self::mk_empty_ns_env(env);
4594                 let span = Self::p_pos(node, env);
4595                 let class_kind = match Self::token_kind(&c.classish_keyword) {
4596                     Some(TK::Class) if kinds.has(modifier::ABSTRACT) => {
4597                         ast_defs::ClassKind::Cabstract
4598                     }
4599                     Some(TK::Class) => ast_defs::ClassKind::Cnormal,
4600                     Some(TK::Interface) => ast_defs::ClassKind::Cinterface,
4601                     Some(TK::Trait) => ast_defs::ClassKind::Ctrait,
4602                     Some(TK::Enum) => ast_defs::ClassKind::Cenum,
4603                     _ => Self::missing_syntax(None, "class kind", &c.classish_keyword, env)?,
4604                 };
4605                 let mut class_ = aast::Class_ {
4606                     span,
4607                     annotation: (),
4608                     mode,
4609                     final_,
4610                     is_xhp,
4611                     kind: class_kind,
4612                     name,
4613                     tparams,
4614                     extends,
4615                     uses: vec![],
4616                     use_as_alias: vec![],
4617                     insteadof_alias: vec![],
4618                     method_redeclarations: vec![],
4619                     xhp_attr_uses: vec![],
4620                     xhp_category: None,
4621                     reqs: vec![],
4622                     implements,
4623                     where_constraints,
4624                     consts: vec![],
4625                     typeconsts: vec![],
4626                     vars: vec![],
4627                     methods: vec![],
4628                     // TODO: what is this attbiute? check ast_to_aast
4629                     attributes: vec![],
4630                     xhp_children: vec![],
4631                     xhp_attrs: vec![],
4632                     namespace,
4633                     user_attributes,
4634                     file_attributes: vec![],
4635                     enum_: None,
4636                     pu_enums: vec![],
4637                     doc_comment: doc_comment_opt,
4638                 };
4639                 match &c.classish_body.syntax {
4640                     ClassishBody(c1) => {
4641                         for elt in Self::as_list(&c1.classish_body_elements).iter() {
4642                             Self::p_class_elt(&mut class_, elt, env)?;
4643                         }
4644                     }
4645                     _ => Self::missing_syntax(None, "classish body", &c.classish_body, env)?,
4646                 }
4647                 Ok(vec![aast::Def::mk_class(class_)])
4648             }
4649             ConstDeclaration(c) => {
4650                 let ty = &c.const_type_specifier;
4651                 let decls = Self::as_list(&c.const_declarators);
4652                 let mut defs = vec![];
4653                 for decl in decls.iter() {
4654                     let def = match &decl.syntax {
4655                         ConstantDeclarator(c) => {
4656                             let name = &c.constant_declarator_name;
4657                             let init = &c.constant_declarator_initializer;
4658                             let gconst = aast::Gconst {
4659                                 annotation: (),
4660                                 mode: Self::mode_annotation(env.file_mode()),
4661                                 name: Self::pos_name(name, env)?,
4662                                 type_: Self::mp_optional(Self::p_hint, ty, env)?,
4663                                 value: Self::p_simple_initializer(init, env)?,
4664                                 namespace: Self::mk_empty_ns_env(env),
4665                                 span: Self::p_pos(node, env),
4666                             };
4667                             aast::Def::mk_constant(gconst)
4668                         }
4669                         _ => Self::missing_syntax(None, "constant declaration", decl, env)?,
4670                     };
4671                     defs.push(def);
4672                 }
4673                 Ok(defs)
4674             }
4675             AliasDeclaration(c) => {
4676                 let tparams = Self::p_tparam_l(false, &c.alias_generic_parameter, env)?;
4677                 for tparam in tparams.iter() {
4678                     if tparam.reified != aast::ReifyKind::Erased {
4679                         Self::raise_parsing_error(node, env, &syntax_error::invalid_reified)
4680                     }
4681                 }
4682                 Ok(vec![aast::Def::mk_typedef(aast::Typedef {
4683                     annotation: (),
4684                     name: Self::pos_name(&c.alias_name, env)?,
4685                     tparams,
4686                     constraint: Self::mp_optional(Self::p_tconstraint, &c.alias_constraint, env)?
4687                         .map(|x| x.1),
4688                     user_attributes: itertools::concat(
4689                         Self::as_list(&c.alias_attribute_spec)
4690                             .iter()
4691                             .map(|attr| Self::p_user_attribute(attr, env))
4692                             .collect::<std::result::Result<Vec<Vec<_>>, _>>()?,
4693                     ),
4694                     namespace: Self::mk_empty_ns_env(env),
4695                     mode: Self::mode_annotation(env.file_mode()),
4696                     vis: match Self::token_kind(&c.alias_keyword) {
4697                         Some(TK::Type) => aast::TypedefVisibility::Transparent,
4698                         Some(TK::Newtype) => aast::TypedefVisibility::Opaque,
4699                         _ => Self::missing_syntax(None, "kind", &c.alias_keyword, env)?,
4700                     },
4701                     kind: Self::p_hint(&c.alias_type, env)?,
4702                 })])
4703             }
4704             EnumDeclaration(c) => {
4705                 let p_enumerator = |n: &Syntax<T, V>, e: &mut Env| -> ret_aast!(ClassConst<,>) {
4706                     match &n.syntax {
4707                         Enumerator(c) => Ok(aast::ClassConst {
4708                             type_: None,
4709                             id: Self::pos_name(&c.enumerator_name, e)?,
4710                             expr: Some(Self::p_expr(&c.enumerator_value, e)?),
4711                             doc_comment: None,
4712                         }),
4713                         _ => Self::missing_syntax(None, "enumerator", n, e),
4714                     }
4715                 };
4716                 Ok(vec![aast::Def::mk_class(aast::Class_ {
4717                     annotation: (),
4718                     mode: Self::mode_annotation(env.file_mode()),
4719                     user_attributes: Self::p_user_attributes(&c.enum_attribute_spec, env)?,
4720                     file_attributes: vec![],
4721                     final_: false,
4722                     kind: ast_defs::ClassKind::Cenum,
4723                     is_xhp: false,
4724                     name: Self::pos_name(&c.enum_name, env)?,
4725                     tparams: aast::ClassTparams {
4726                         list: vec![],
4727                         constraints: s_map::SMap::new(),
4728                     },
4729                     extends: vec![],
4730                     implements: vec![],
4731                     where_constraints: vec![],
4732                     consts: Self::could_map(p_enumerator, &c.enum_enumerators, env)?,
4733                     namespace: Self::mk_empty_ns_env(env),
4734                     span: Self::p_pos(node, env),
4735                     enum_: Some(aast::Enum_ {
4736                         base: Self::p_hint(&c.enum_base, env)?,
4737                         constraint: Self::mp_optional(Self::p_tconstraint_ty, &c.enum_type, env)?,
4738                     }),
4740                     doc_comment: doc_comment_opt,
4741                     uses: vec![],
4742                     use_as_alias: vec![],
4743                     insteadof_alias: vec![],
4744                     method_redeclarations: vec![],
4745                     xhp_attr_uses: vec![],
4746                     xhp_category: None,
4747                     reqs: vec![],
4748                     vars: vec![],
4749                     typeconsts: vec![],
4750                     methods: vec![],
4751                     attributes: vec![],
4752                     xhp_children: vec![],
4753                     xhp_attrs: vec![],
4754                     pu_enums: vec![],
4755                 })])
4756             }
4757             RecordDeclaration(c) => {
4758                 let p_field = |n: &Syntax<T, V>, e: &mut Env| match &n.syntax {
4759                     RecordField(c) => Ok((
4760                         Self::pos_name(&c.record_field_name, e)?,
4761                         Self::p_hint(&c.record_field_type, e)?,
4762                         Self::mp_optional(Self::p_simple_initializer, &c.record_field_init, e)?,
4763                     )),
4764                     _ => Self::missing_syntax(None, "record_field", n, e),
4765                 };
4766                 Ok(vec![aast::Def::mk_record_def(aast::RecordDef {
4767                     annotation: (),
4768                     name: Self::pos_name(&c.record_name, env)?,
4769                     extends: Self::could_map(Self::p_hint, &c.record_extends_list, env)?
4770                         .into_iter()
4771                         .next(),
4772                     abstract_: Self::token_kind(&c.record_modifier) == Some(TK::Abstract),
4773                     user_attributes: Self::p_user_attributes(&c.record_attribute_spec, env)?,
4774                     fields: Self::could_map(p_field, &c.record_fields, env)?,
4775                     namespace: Self::mk_empty_ns_env(env),
4776                     span: Self::p_pos(node, env),
4777                     doc_comment: doc_comment_opt,
4778                 })])
4779             }
4780             InclusionDirective(c)
4781                 if env.file_mode() != file_info::Mode::Mdecl
4782                     && env.file_mode() != file_info::Mode::Mphp
4783                     || env.codegen() =>
4784             {
4785                 let expr = Self::p_expr(&c.inclusion_expression, env)?;
4786                 Ok(vec![aast::Def::mk_stmt(aast::Stmt::new(
4787                     Self::p_pos(node, env),
4788                     aast::Stmt_::mk_expr(expr),
4789                 ))])
4790             }
4791             NamespaceDeclaration(c) => {
4792                 let name = &c.namespace_name;
4793                 let defs = match &c.namespace_body.syntax {
4794                     NamespaceBody(c) => {
4795                         let mut env1 = Env::clone_and_unset_toplevel_if_toplevel(env);
4796                         let env1 = env1.as_mut();
4797                         itertools::concat(
4798                             Self::as_list(&c.namespace_declarations)
4799                                 .iter()
4800                                 .map(|n| Self::p_def(n, env1))
4801                                 .collect::<std::result::Result<Vec<Vec<_>>, _>>()?,
4802                         )
4803                     }
4804                     _ => vec![],
4805                 };
4806                 Ok(vec![aast::Def::mk_namespace(
4807                     Self::pos_name(name, env)?,
4808                     defs,
4809                 )])
4810             }
4811             NamespaceGroupUseDeclaration(c) => {
4812                 let uses: std::result::Result<Vec<_>, _> =
4813                     Self::as_list(&c.namespace_group_use_clauses)
4814                         .iter()
4815                         .map(|n| {
4816                             Self::p_namespace_use_clause(
4817                                 Some(&c.namespace_group_use_prefix),
4818                                 Self::p_namespace_use_kind(&c.namespace_group_use_kind, env),
4819                                 n,
4820                                 env,
4821                             )
4822                         })
4823                         .collect();
4824                 Ok(vec![aast::Def::mk_namespace_use(uses?)])
4825             }
4826             NamespaceUseDeclaration(c) => {
4827                 let uses: std::result::Result<Vec<_>, _> = Self::as_list(&c.namespace_use_clauses)
4828                     .iter()
4829                     .map(|n| {
4830                         Self::p_namespace_use_clause(
4831                             None,
4832                             Self::p_namespace_use_kind(&c.namespace_use_kind, env),
4833                             n,
4834                             env,
4835                         )
4836                     })
4837                     .collect();
4838                 Ok(vec![aast::Def::mk_namespace_use(uses?)])
4839             }
4840             FileAttributeSpecification(_) => {
4841                 Ok(vec![aast::Def::mk_file_attributes(aast::FileAttribute {
4842                     user_attributes: Self::p_user_attribute(node, env)?,
4843                     namespace: Self::mk_empty_ns_env(env),
4844                 })])
4845             }
4846             _ if env.file_mode() == file_info::Mode::Mdecl
4847                 || env.file_mode() == file_info::Mode::Mphp && !env.codegen =>
4848             {
4849                 Ok(vec![])
4850             }
4851             _ => Ok(vec![aast::Def::mk_stmt(Self::p_stmt(node, env)?)]),
4852         }
4853     }
4855     fn partial_should_check_error(mode: file_info::Mode, code: usize) -> bool {
4856         use file_info::Mode::*;
4857         match mode {
4858             Mexperimental | Mstrict => true,
4859             Mdecl | Mphp => false,
4860             Mpartial => false, // TODO: Error.is_strict_code code
4861         }
4862     }
4864     fn post_process(env: &mut Env, program: aast!(Program<,>), acc: &mut aast!(Program<,>)) {
4865         use aast::{Def, Def::*, Stmt_::*};
4866         let mut saw_ns: Option<(aast!(Sid), aast!(Program<,>))> = None;
4867         for def in program.into_iter() {
4868             if let Namespace(_) = &def {
4869                 if let Some((n, ns_acc)) = saw_ns {
4870                     acc.push(Def::mk_namespace(n, ns_acc));
4871                     saw_ns = None;
4872                 }
4873             }
4875             if let Namespace(ns) = def {
4876                 let (n, defs) = *ns;
4877                 if defs.is_empty() {
4878                     saw_ns = Some((n, vec![]));
4879                 } else {
4880                     let mut acc_ = vec![];
4881                     Self::post_process(env, defs, &mut acc_);
4882                     acc.push(Def::mk_namespace(n, acc_));
4883                 }
4885                 continue;
4886             }
4888             if let Stmt(s) = &def {
4889                 if Self::is_noop(&s) {
4890                     continue;
4891                 }
4892                 let raise_error = match &s.1 {
4893                     Markup(_) => false,
4894                     Expr(expr)
4895                         if expr.as_ref().is_import()
4896                             && !env.parser_options.po_disallow_toplevel_requires =>
4897                     {
4898                         false
4899                     }
4900                     _ => {
4901                         env.keep_errors
4902                             && env.is_typechecker()
4903                             && Self::partial_should_check_error(env.file_mode(), 1002)
4904                     }
4905                 };
4906                 if raise_error {
4907                     Self::raise_parsing_error_pos(&s.0, env, &syntax_error::toplevel_statements);
4908                 }
4909             }
4911             if let Some((_, ns_acc)) = &mut saw_ns {
4912                 ns_acc.push(def);
4913             } else {
4914                 acc.push(def);
4915             };
4916         }
4917         if let Some((n, defs)) = saw_ns {
4918             acc.push(Def::mk_namespace(n, defs));
4919         }
4920     }
4922     fn p_program(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Program<,>) {
4923         let is_halt = |syntax: &SyntaxVariant<T, V>| -> bool {
4924             match syntax {
4925                 ExpressionStatement(c) => match &c.expression_statement_expression.syntax {
4926                     HaltCompilerExpression(_) => true,
4927                     _ => false,
4928                 },
4929                 _ => false,
4930             }
4931         };
4932         let nodes = Self::as_list(node);
4933         let mut acc = vec![];
4934         for i in 0..nodes.len() {
4935             match &nodes[i].syntax {
4936                 EndOfFile(_) => break,
4937                 n if is_halt(n) => {
4938                     let pos = Self::p_pos(nodes[i], env);
4939                     *env.saw_compiler_halt_offset() = Some(pos.end_cnum());
4940                 }
4941                 _ => match Self::p_def(nodes[i], env) {
4942                     Err(Error::APIMissingSyntax { .. }) if env.fail_open => {}
4943                     e @ Err(_) => return e,
4944                     Ok(mut def) => acc.append(&mut def),
4945                 },
4946             }
4947         }
4948         let mut program = vec![];
4949         Self::post_process(env, acc, &mut program);
4950         Ok(program)
4951     }
4953     fn p_script(node: &Syntax<T, V>, env: &mut Env) -> ret_aast!(Program<,>) {
4954         match &node.syntax {
4955             Script(children) => Self::p_program(&children.script_declarations, env),
4956             _ => Self::missing_syntax(None, "script", node, env),
4957         }
4958     }
4960     fn elaborate_halt_compiler(ast: aast!(Program<,>), env: &mut Env) -> aast!(Program<,>) {
4961         match *env.saw_compiler_halt_offset() {
4962             Some(_) => unimplemented!(),
4963             _ => ast,
4964         }
4965     }
4967     fn lower(env: &mut Env<'a>, script: &Syntax<T, V>) -> std::result::Result<Result, String> {
4968         let aast_result = Self::p_script(script, env);
4969         let aast = match aast_result {
4970             Ok(ast) => ast,
4971             Err(err) => match err {
4972                 Error::APIMissingSyntax {
4973                     expecting,
4974                     pos,
4975                     node_name,
4976                     kind,
4977                 } => Err(format!(
4978                     "missing case in {:?}.\n - pos: {:?}\n - unexpected: '{:?}'\n - kind: {:?}\n",
4979                     expecting.to_string(),
4980                     pos,
4981                     node_name.to_string(),
4982                     kind,
4983                 ))?,
4984                 _ => Err(format!("Lowerer Error: {:?}", err))?,
4985             },
4986         };
4988         let aast = Self::elaborate_halt_compiler(aast, env);
4989         Ok(Result { aast })
4990     }