fn gen_pu_accessor(
    fun_name: String,
    pos: ast_defs::Pos,
    is_final: bool,
    extends: bool,
    infos: Vec<(String, Tast::Expr)>,
    error: String,
) -> Tast::Method_ {
    let var_name = "$atom".to_string();
    let var_atom = lvar(pos.clone(), var_name.clone());
    let do_case = |entry, init| {
        let entry = str_(pos.clone(), entry);
        let ret = return_(pos.clone(), init);
        Tast::Case::Case(entry, vec![ret])
    };
    let mut cases = vec![];
    for info in infos.into_iter() {
        let (atom_name, value) = info;
        cases.push(do_case(atom_name.to_string(), value.clone()));
    }
    let default = if extends {
        let parent_call = class_const(pos.clone(), "parent".to_string(), fun_name.clone());
        let call = call(pos.clone(), parent_call, vec![var_atom.clone()]);
        let ret = return_(pos.clone(), call);
        Tast::Case::Default(pos.clone(), vec![ret])
    } else {
        let msg_ = Tast::Expr_::Binop(Box::new((
            ast_defs::Bop::Dot,
            str_(pos.clone(), error),
            var_atom.clone(),
        )));
        let msg = Tast::Expr(pos.clone(), msg_);
        let new_exn = new_(pos.clone(), "\\Exception".to_string(), vec![msg]);
        let throw = Tast::Stmt_::Throw(Box::new(new_exn));
        Tast::Case::Default(pos.clone(), vec![Tast::Stmt(pos.clone(), throw)])
    };
    cases.push(default);
    let body = {
        let switch = Tast::Stmt_::Switch(Box::new((var_atom, cases)));
        Tast::FuncBody {
            ast: vec![Tast::Stmt(pos.clone(), switch)],
            annotation: (),
        }
    };
    Tast::Method_ {
        span: pos.clone(),
        annotation: (),
        final_: is_final,
        abstract_: false,
        static_: true,
        visibility: aast_defs::Visibility::Public,
        name: ast_defs::Id(pos.clone(), fun_name),
        tparams: vec![],
        where_constraints: vec![],
        variadic: Tast::FunVariadicity::FVnonVariadic,
        params: vec![Tast::FunParam {
            annotation: pos.clone(),
            type_hint: create_string_type_hint(pos.clone()),
            is_variadic: false,
            pos: pos.clone(),
            name: var_name,
            expr: None,
            callconv: None,
            user_attributes: vec![],
            visibility: None,
        }],
        body,
        fun_kind: ast_defs::FunKind::FSync,
        user_attributes: vec![memoize(pos.clone())],
        ret: create_mixed_type_hint(pos),
        external: false,
        doc_comment: None,
    }
}
/* Generate a static accessor function from the pumapping information, eg:

   <<__Memoize>>
   static function pu$Field_name$Expr_name(string $atom) : mixed {
     switch ($atom) {
       case "A":
        return valA;
       case "B":
        return valB;
       ...
       default:
           raise \Exception "illegal..."
     }
    }

   If the class extends a superclass, the raise statement is replaced with
   a call to parent::pu$Field_name$Expr_name.

   Remark: at compile time we cannot reliably detect if, whenever a class D
   extends a class C, a PU defined in the subclass D extends a PU defined in C
   or is self-contained.  In this case the accessor functions include the
   default call to parent.  Type checking ensures that the default case is
   not reachable if the PU was not inherited from the super-class.
*/


If the class extends a superclass, the raise statement is replaced with
a call to parent::pu$Field_name$Expr_name.

at compile time we cannot reliably detect if, whenever a class D
extends a class C, a PU defined in the subclass D extends a PU defined in C
or is self-contained.  In this case the accessor functions include the
default call to parent.  Type checking ensures that the default case is
not reachable if the PU was not inherited from the super-class.
If the class extends a superclass the raise statement is replaced with a call to parent :: pu$Field_name$Expr_name . at compile time we cannot reliably detect if whenever a class D extends a class C a PU defined in the subclass D extends a PU defined in C or is self - contained . In this case the accessor functions include the default call to parent . Type checking ensures that the default case is not reachable if the PU was not inherited from the super - class .
fn gen_pu_accessor(
    fun_name: String,
    pos: ast_defs::Pos,
    is_final: bool,
    extends: bool,
    infos: Vec<(String, Tast::Expr)>,
    error: String,
) -> Tast::Method_ {
    let var_name = "$atom".to_string();
    let var_atom = lvar(pos.clone(), var_name.clone());
    let do_case = |entry, init| {
        let entry = str_(pos.clone(), entry);
        let ret = return_(pos.clone(), init);
        Tast::Case::Case(entry, vec![ret])
    };
    let mut cases = vec![];
    for info in infos.into_iter() {
        let (atom_name, value) = info;
        cases.push(do_case(atom_name.to_string(), value.clone()));
    }
    let default = if extends {
        let parent_call = class_const(pos.clone(), "parent".to_string(), fun_name.clone());
        let call = call(pos.clone(), parent_call, vec![var_atom.clone()]);
        let ret = return_(pos.clone(), call);
        Tast::Case::Default(pos.clone(), vec![ret])
    } else {
        let msg_ = Tast::Expr_::Binop(Box::new((
            ast_defs::Bop::Dot,
            str_(pos.clone(), error),
            var_atom.clone(),
        )));
        let msg = Tast::Expr(pos.clone(), msg_);
        let new_exn = new_(pos.clone(), "\\Exception".to_string(), vec![msg]);
        let throw = Tast::Stmt_::Throw(Box::new(new_exn));
        Tast::Case::Default(pos.clone(), vec![Tast::Stmt(pos.clone(), throw)])
    };
    cases.push(default);
    let body = {
        let switch = Tast::Stmt_::Switch(Box::new((var_atom, cases)));
        Tast::FuncBody {
            ast: vec![Tast::Stmt(pos.clone(), switch)],
            annotation: (),
        }
    };
    Tast::Method_ {
        span: pos.clone(),
        annotation: (),
        final_: is_final,
        abstract_: false,
        static_: true,
        visibility: aast_defs::Visibility::Public,
        name: ast_defs::Id(pos.clone(), fun_name),
        tparams: vec![],
        where_constraints: vec![],
        variadic: Tast::FunVariadicity::FVnonVariadic,
        params: vec![Tast::FunParam {
            annotation: pos.clone(),
            type_hint: create_string_type_hint(pos.clone()),
            is_variadic: false,
            pos: pos.clone(),
            name: var_name,
            expr: None,
            callconv: None,
            user_attributes: vec![],
            visibility: None,
        }],
        body,
        fun_kind: ast_defs::FunKind::FSync,
        user_attributes: vec![memoize(pos.clone())],
        ret: create_mixed_type_hint(pos),
        external: false,
        doc_comment: None,
    }
}
fn gen_pu_accessor ( fun_name : String , pos : ast_defs :: Pos , is_final : bool , extends : bool , infos : Vec < ( String , Tast :: Expr ) > , error : String , ) -> Tast :: Method_ { let var_name = " " . to_string ( ) ; let var_atom = lvar ( pos . clone ( ) , var_name . clone ( ) ) ; let do_case = | entry , init | { let entry = str_ ( pos . clone ( ) , entry ) ; let ret = return_ ( pos . clone ( ) , init ) ; Tast :: Case :: Case ( entry , vec ! [ ret ] ) } ; let mut cases = vec ! [ ] ; for info in infos . into_iter ( ) { let ( atom_name , value ) = info ; cases . push ( do_case ( atom_name . to_string ( ) , value . clone ( ) ) ) ; } let default = if extends { let parent_call = class_const ( pos . clone ( ) , " " . to_string ( ) , fun_name . clone ( ) ) ; let call = call ( pos . clone ( ) , parent_call , vec ! [ var_atom clone ( ) ] ) ; let ret = return_ ( pos . clone ( ) , call ) ; Tast :: Case :: Default ( pos . clone ( ) , vec ! [ ret ] ) } else { let msg_ = Tast :: Expr_ :: Binop ( Box :: new ( ( ast_defs :: Bop :: Dot , str_ ( pos . clone ( ) , error ) , var_atom . clone ( ) , ) ) ) ; let msg = Tast :: Expr ( pos . clone ( ) , msg_ ) ; let new_exn = new_ ( pos . clone ( ) , " \\ " . to_string ( ) , vec ! [ msg ] ) ; let throw = Tast :: Stmt_ :: Throw ( Box :: new ( new_exn ) ) ; Tast :: Case :: Default ( pos . clone ( ) , vec ! [ Tast Stmt ( pos clone ( ) throw ) ] ) } ; cases . push ( default ) ; let body = { let switch = Tast :: Stmt_ :: Switch ( Box :: new ( ( var_atom , cases ) ) ) ; Tast :: FuncBody { ast : vec ! [ Tast Stmt ( pos clone ( ) switch ) ] , annotation : ( ) , } } ; Tast :: Method_ { span : pos . clone ( ) , annotation : ( ) , final_ : is_final , abstract_ : false , static_ : true , visibility : aast_defs :: Visibility :: Public , name : ast_defs :: Id ( pos . clone ( ) , fun_name ) , tparams : vec ! [ ] , where_constraints : vec ! [ ] , variadic : Tast :: FunVariadicity :: FVnonVariadic , params : vec ! [ Tast FunParam { annotation pos clone ( ) type_hint create_string_type_hint ( pos clone ( ) ) is_variadic false pos pos clone ( ) name var_name expr None callconv None user_attributes vec [ ] visibility None } ] , body , fun_kind : ast_defs :: FunKind :: FSync , user_attributes : vec ! [ memoize ( pos clone ( ) ) ] , ret : create_mixed_type_hint ( pos ) , external : false , doc_comment : None , } }
Generate a static accessor function from the pumapping information, eg:
<<__Memoize>>
static function pu$Field_name$Expr_name(string $atom) : mixed {
switch ($atom) {
case "A":
return valA;
case "B":
return valB;
...
default:
raise \Exception "illegal..."
}
}
Generate a static accessor function from the pumapping information eg : <<__Memoize >> static function pu$Field_name$Expr_name ( string $atom ) : mixed { switch ( $atom ) { case " A " : return valA ; case " B " : return valB ; ... default : raise \ Exception " illegal ... " } }
fun_name
String
pos
ast_defs::Pos
is_final
bool
extends
bool
infos
Vec<(String, Tast::Expr)>
error
String