(* Yoann Padioleau * * Copyright (C) 2010, University of Copenhagen DIKU and INRIA. * Copyright (C) 2006, 2007, 2008, 2009 Ecole des Mines de Nantes * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License (GPL) * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * file license.txt for more details. *) open Common open Ast_c module F = Control_flow_c (*****************************************************************************) (* Prelude *) (*****************************************************************************) (* todo? dont go in Include. Have a visitor flag ? disable_go_include ? * disable_go_type_annotation ? *) (*****************************************************************************) (* Wrappers *) (*****************************************************************************) let pr2, pr2_once = Common.mk_pr2_wrappers Flag_parsing_c.verbose_visit (*****************************************************************************) (* Functions to visit the Ast, and now also the CFG nodes *) (*****************************************************************************) (* Why this module ? * * The problem is that we manipulate the AST of C programs * and some of our analysis need only to specify an action for * specific cases, such as the function call case, and recurse * for the other cases. * Here is a simplification of our AST: * * type ctype = * | Basetype of ... * | Pointer of ctype * | Array of expression option * ctype * | ... * and expression = * | Ident of string * | FunCall of expression * expression list * | Postfix of ... * | RecordAccess of .. * | ... * and statement = * ... * and declaration = * ... * and program = * ... * * What we want is really write code like * * let my_analysis program = * analyze_all_expressions program (fun expr -> * match expr with * | FunCall (e, es) -> do_something() * | _ -> * ) * * The problem is how to write analyze_all_expressions * and find_a_way_to_recurse_for_all_the_other_cases. * * Our solution is to mix the ideas of visitor, pattern matching, * and continuation. Here is how it looks like * using our hybrid-visitor API: * * let my_analysis program = * Visitor.visit_iter program { * Visitor.kexpr = (fun k e -> * match e with * | FunCall (e, es) -> do_something() * | _ -> k e * ); * } * * You can of course also give action "hooks" for * kstatement, ktype, or kdeclaration. But we don't overuse * visitors and so it would be stupid to provide * kfunction_call, kident, kpostfix hooks as one can just * use pattern matching with kexpr to achieve the same effect. * * Note: when want to apply recursively, always apply the continuator * on the toplevel expression, otherwise may miss some intermediate steps. * Do * match expr with * | FunCall (e, es) -> ... * k expr * Or * match expr with * | FunCall (e, es) -> ... * Visitor_c.vk_expr bigf e * Not * match expr with * | FunCall (e, es) -> ... * k e * * * * * * Alternatives: from the caml mailing list: * "You should have a look at the Camlp4 metaprogramming facilities : * http://brion.inria.fr/gallium/index.php/Camlp4MapGenerator * You would write something like" : * let my_analysis program = * let analysis = object (self) * inherit fold as super * method expr = function * | FunCall (e, es) -> do_something (); self * | other -> super#expr other * end in analysis#expr * * The problem is that you don't have control about what is generated * and in our case we sometimes dont want to visit too much. For instance * our visitor don't recurse on the type annotation of expressions * Ok, this could be worked around, but the pb remains, you * don't have control and at some point you may want. In the same * way we want to enforce a certain order in the visit (ok this is not good, * but it's convenient) of ast elements. For instance first * processing the left part 'e' of a Funcall(e,es), then the arguments 'es'. * *) (* Visitor based on continuation. Cleaner than the one based on mutable * pointer functions that I had before. * src: based on a (vague) idea from Remy Douence. * * * * Diff with Julia's visitor ? She does: * * let ident r k i = * ... * let expression r k e = * ... * ... (List.map r.V0.combiner_expression expr_list) ... * ... * let res = V0.combiner bind option_default * mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode * donothing donothing donothing donothing * ident expression typeC donothing parameter declaration statement * donothing in * ... * collect_unitary_nonunitary * (List.concat (List.map res.V0.combiner_top_level t)) * * * * So she has to remember at which position you must put the 'expression' * function. I use record which is easier. * * When she calls recursively, her res.V0.combiner_xxx does not take bigf * in param whereas I do * | F.Decl decl -> Visitor_c.vk_decl bigf decl * And with the record she gets, she does not have to do my * multiple defs of function such as 'let al_type = V0.vk_type_s bigf' * * The code of visitor.ml is cleaner with julia because mutual recursive calls * are clean such as ... 'expression e' ... and not 'f (k, bigf) e' * or 'vk_expr bigf e'. * * So it is very dual: * - I give a record but then I must handle bigf. * - She gets a record, and gives a list of function * *) (* old: first version (only visiting expr) let (iter_expr:((expression -> unit) -> expression -> unit) -> expression -> unit) = fun f expr -> let rec k e = match e with | Constant c -> () | FunCall (e, es) -> f k e; List.iter (f k) es | CondExpr (e1, e2, e3) -> f k e1; f k e2; f k e3 | Sequence (e1, e2) -> f k e1; f k e2; | Assignment (e1, op, e2) -> f k e1; f k e2; | Postfix (e, op) -> f k e | Infix (e, op) -> f k e | Unary (e, op) -> f k e | Binary (e1, op, e2) -> f k e1; f k e2; | ArrayAccess (e1, e2) -> f k e1; f k e2; | RecordAccess (e, s) -> f k e | RecordPtAccess (e, s) -> f k e | SizeOfExpr e -> f k e | SizeOfType t -> () | _ -> failwith "to complete" in f k expr let ex1 = Sequence (Sequence (Constant (Ident "1"), Constant (Ident "2")), Constant (Ident "4")) let test = iter_expr (fun k e -> match e with | Constant (Ident x) -> Common.pr2 x | rest -> k rest ) ex1 ==> 1 2 4 *) (*****************************************************************************) (* Side effect style visitor *) (*****************************************************************************) (* Visitors for all langage concept, not just for expression. * * Note that I don't visit necesserally in the order of the token * found in the original file. So don't assume such hypothesis! * * todo? parameter ? *) type visitor_c = { kexpr: (expression -> unit) * visitor_c -> expression -> unit; kstatement: (statement -> unit) * visitor_c -> statement -> unit; ktype: (fullType -> unit) * visitor_c -> fullType -> unit; kdecl: (declaration -> unit) * visitor_c -> declaration -> unit; konedecl: (onedecl -> unit) * visitor_c -> onedecl -> unit; kparam: (parameterType -> unit) * visitor_c -> parameterType -> unit; kdef: (definition -> unit) * visitor_c -> definition -> unit; kname : (name -> unit) * visitor_c -> name -> unit; kini: (initialiser -> unit) * visitor_c -> initialiser -> unit; kfield: (field -> unit) * visitor_c -> field -> unit; kcppdirective: (cpp_directive -> unit) * visitor_c -> cpp_directive -> unit; kdefineval : (define_val -> unit) * visitor_c -> define_val -> unit; kstatementseq: (statement_sequencable -> unit) * visitor_c -> statement_sequencable -> unit; (* CFG *) knode: (F.node -> unit) * visitor_c -> F.node -> unit; (* AST *) ktoplevel: (toplevel -> unit) * visitor_c -> toplevel -> unit; kinfo: (info -> unit) * visitor_c -> info -> unit; } let default_visitor_c = { kexpr = (fun (k,_) e -> k e); kstatement = (fun (k,_) st -> k st); ktype = (fun (k,_) t -> k t); kdecl = (fun (k,_) d -> k d); konedecl = (fun (k,_) d -> k d); kparam = (fun (k,_) d -> k d); kdef = (fun (k,_) d -> k d); kini = (fun (k,_) ie -> k ie); kname = (fun (k,_) x -> k x); kinfo = (fun (k,_) ii -> k ii); knode = (fun (k,_) n -> k n); ktoplevel = (fun (k,_) p -> k p); kcppdirective = (fun (k,_) p -> k p); kdefineval = (fun (k,_) p -> k p); kstatementseq = (fun (k,_) p -> k p); kfield = (fun (k,_) p -> k p); } (* ------------------------------------------------------------------------ *) let rec vk_expr = fun bigf expr -> let iif ii = vk_ii bigf ii in let rec exprf e = bigf.kexpr (k,bigf) e (* !!! dont go in _typ !!! *) and k ((e,_typ), ii) = iif ii; match e with | Ident (name) -> vk_name bigf name | Constant (c) -> () | FunCall (e, es) -> exprf e; vk_argument_list bigf es; | CondExpr (e1, e2, e3) -> exprf e1; do_option (exprf) e2; exprf e3 | Sequence (e1, e2) -> exprf e1; exprf e2; | Assignment (e1, op, e2) -> exprf e1; exprf e2; | Postfix (e, op) -> exprf e | Infix (e, op) -> exprf e | Unary (e, op) -> exprf e | Binary (e1, op, e2) -> exprf e1; exprf e2; | ArrayAccess (e1, e2) -> exprf e1; exprf e2; | RecordAccess (e, name) -> exprf e; vk_name bigf name | RecordPtAccess (e, name) -> exprf e; vk_name bigf name | SizeOfExpr (e) -> exprf e | SizeOfType (t) -> vk_type bigf t | Cast (t, e) -> vk_type bigf t; exprf e (* old: | StatementExpr (((declxs, statxs), is)), is2 -> * List.iter (vk_decl bigf) declxs; * List.iter (vk_statement bigf) statxs *) | StatementExpr ((statxs, is)) -> iif is; statxs +> List.iter (vk_statement_sequencable bigf); | Constructor (t, init) -> vk_type bigf t; vk_ini bigf init | ParenExpr (e) -> exprf e | New (None, t) -> vk_argument bigf t | New (Some ts, t) -> vk_argument_list bigf ts; vk_argument bigf t | Delete e -> vk_expr bigf e in exprf expr (* ------------------------------------------------------------------------ *) and vk_name = fun bigf ident -> let iif ii = vk_ii bigf ii in let rec namef x = bigf.kname (k,bigf) x and k id = match id with | RegularName (s, ii) -> iif ii | CppConcatenatedName xs -> xs +> List.iter (fun ((x,ii1), ii2) -> iif ii2; iif ii1; ); | CppVariadicName (s, ii) -> iif ii | CppIdentBuilder ((s,iis), xs) -> iif iis; xs +> List.iter (fun ((x,iix), iicomma) -> iif iicomma; iif iix; ) in namef ident (* ------------------------------------------------------------------------ *) and vk_statement = fun bigf (st: Ast_c.statement) -> let iif ii = vk_ii bigf ii in let rec statf x = bigf.kstatement (k,bigf) x and k st = let (unwrap_st, ii) = st in iif ii; match unwrap_st with | Labeled (Label (name, st)) -> vk_name bigf name; statf st; | Labeled (Case (e, st)) -> vk_expr bigf e; statf st; | Labeled (CaseRange (e, e2, st)) -> vk_expr bigf e; vk_expr bigf e2; statf st; | Labeled (Default st) -> statf st; | Compound statxs -> statxs +> List.iter (vk_statement_sequencable bigf) | ExprStatement (eopt) -> do_option (vk_expr bigf) eopt; | Selection (If (e, st1, st2)) -> vk_expr bigf e; statf st1; statf st2; | Selection (Switch (e, st)) -> vk_expr bigf e; statf st; | Iteration (While (e, st)) -> vk_expr bigf e; statf st; | Iteration (DoWhile (st, e)) -> statf st; vk_expr bigf e; | Iteration (For (first, (e2opt,i2), (e3opt,i3), st)) -> (match first with ForExp (e1opt,i1) -> statf (mk_st (ExprStatement (e1opt)) i1) | ForDecl decl -> vk_decl bigf decl); statf (mk_st (ExprStatement (e2opt)) i2); statf (mk_st (ExprStatement (e3opt)) i3); statf st; | Iteration (MacroIteration (s, es, st)) -> vk_argument_list bigf es; statf st; | Jump (Goto name) -> vk_name bigf name | Jump ((Continue|Break|Return)) -> () | Jump (ReturnExpr e) -> vk_expr bigf e; | Jump (GotoComputed e) -> vk_expr bigf e; | Decl decl -> vk_decl bigf decl | Asm asmbody -> vk_asmbody bigf asmbody | NestedFunc def -> vk_def bigf def | MacroStmt -> () in statf st and vk_statement_sequencable = fun bigf stseq -> let f = bigf.kstatementseq in let rec k stseq = match stseq with | StmtElem st -> vk_statement bigf st | CppDirectiveStmt directive -> vk_cpp_directive bigf directive | IfdefStmt ifdef -> vk_ifdef_directive bigf ifdef | IfdefStmt2 (ifdef, xxs) -> ifdef +> List.iter (vk_ifdef_directive bigf); xxs +> List.iter (fun xs -> xs +> List.iter (vk_statement_sequencable bigf) ) in f (k, bigf) stseq and vk_type = fun bigf t -> let iif ii = vk_ii bigf ii in let rec typef x = bigf.ktype (k, bigf) x and k t = let (q, t) = t in let (unwrap_q, iiq) = q in let (unwrap_t, iit) = t in iif iiq; iif iit; match unwrap_t with | NoType -> () | BaseType _ -> () | Pointer t -> typef t | Array (eopt, t) -> do_option (vk_expr bigf) eopt; typef t | FunctionType (returnt, paramst) -> typef returnt; (match paramst with | (ts, (b,iihas3dots)) -> iif iihas3dots; vk_param_list bigf ts ) | Enum (sopt, enumt) -> vk_enum_fields bigf enumt | StructUnion (sopt, _su, fields) -> vk_struct_fields bigf fields | StructUnionName (s, structunion) -> () | EnumName s -> () (* dont go in _typ *) | TypeName (name,_typ) -> vk_name bigf name | ParenType t -> typef t | TypeOfExpr e -> vk_expr bigf e | TypeOfType t -> typef t in typef t and vk_attribute = fun bigf attr -> let iif ii = vk_ii bigf ii in match attr with | Attribute s, ii -> iif ii (* ------------------------------------------------------------------------ *) and vk_decl = fun bigf d -> let iif ii = vk_ii bigf ii in let f = bigf.kdecl in let rec k decl = match decl with | DeclList (xs,ii) -> iif ii; xs +> List.iter (fun (x,ii) -> iif ii; vk_onedecl bigf x ); | MacroDecl ((s, args, ptvg),ii) -> iif ii; vk_argument_list bigf args | MacroDeclInit ((s, args, ini),ii) -> iif ii; vk_argument_list bigf args; vk_ini bigf ini in f (k, bigf) d and vk_decl_list = fun bigf ts -> ts +> List.iter (vk_decl bigf) and vk_onedecl = fun bigf onedecl -> let iif ii = vk_ii bigf ii in let f = bigf.konedecl in let rec k onedecl = match onedecl with | ({v_namei = var; v_type = t; v_type_bis = tbis; v_storage = _sto; v_attr = attrs}) -> vk_type bigf t; (* dont go in tbis *) attrs +> List.iter (vk_attribute bigf); var +> Common.do_option (fun (name, iniopt) -> vk_name bigf name; (match iniopt with Ast_c.NoInit -> () | Ast_c.ValInit(iini,init) -> iif [iini]; vk_ini bigf init | Ast_c.ConstrInit((init,ii)) -> iif ii; vk_argument_list bigf init) ) in f (k, bigf) onedecl and vk_ini = fun bigf ini -> let iif ii = vk_ii bigf ii in let rec inif x = bigf.kini (k, bigf) x and k (ini, iini) = iif iini; match ini with | InitExpr e -> vk_expr bigf e | InitList initxs -> initxs +> List.iter (fun (ini, ii) -> inif ini; iif ii; ) | InitDesignators (xs, e) -> xs +> List.iter (vk_designator bigf); inif e | InitFieldOld (s, e) -> inif e | InitIndexOld (e1, e) -> vk_expr bigf e1; inif e in inif ini and vk_ini_list = fun bigf ts -> let iif ii = vk_ii bigf ii in ts +> List.iter (fun (ini,iicomma) -> vk_ini bigf ini; iif iicomma; ) and vk_designator = fun bigf design -> let iif ii = vk_ii bigf ii in let (designator, ii) = design in iif ii; match designator with | DesignatorField s -> () | DesignatorIndex e -> vk_expr bigf e | DesignatorRange (e1, e2) -> vk_expr bigf e1; vk_expr bigf e2 (* ------------------------------------------------------------------------ *) and vk_struct_fields = fun bigf fields -> fields +> List.iter (vk_struct_field bigf); and vk_struct_field = fun bigf field -> let iif ii = vk_ii bigf ii in let f = bigf.kfield in let rec k field = match field with | DeclarationField (FieldDeclList (onefield_multivars, iiptvirg)) -> vk_struct_fieldkinds bigf onefield_multivars; iif iiptvirg; | EmptyField info -> iif [info] | MacroDeclField ((s, args),ii) -> iif ii; vk_argument_list bigf args; | CppDirectiveStruct directive -> vk_cpp_directive bigf directive | IfdefStruct ifdef -> vk_ifdef_directive bigf ifdef in f (k, bigf) field and vk_struct_fieldkinds = fun bigf onefield_multivars -> let iif ii = vk_ii bigf ii in onefield_multivars +> List.iter (fun (field, iicomma) -> iif iicomma; match field with | Simple (nameopt, t) -> Common.do_option (vk_name bigf) nameopt; vk_type bigf t; | BitField (nameopt, t, info, expr) -> Common.do_option (vk_name bigf) nameopt; vk_info bigf info; vk_expr bigf expr; vk_type bigf t ) and vk_enum_fields = fun bigf enumt -> let iif ii = vk_ii bigf ii in enumt +> List.iter (fun ((name, eopt), iicomma) -> vk_oneEnum bigf (name, eopt); iif iicomma) and vk_oneEnum = fun bigf (name, eopt) -> let iif ii = vk_ii bigf ii in vk_name bigf name; eopt +> Common.do_option (fun (info, e) -> iif [info]; vk_expr bigf e ) (* ------------------------------------------------------------------------ *) and vk_def = fun bigf d -> let iif ii = vk_ii bigf ii in let f = bigf.kdef in let rec k d = match d with | {f_name = name; f_type = (returnt, (paramst, (b, iib))); f_storage = sto; f_body = statxs; f_attr = attrs; f_old_c_style = oldstyle; }, ii -> iif ii; iif iib; attrs +> List.iter (vk_attribute bigf); vk_type bigf returnt; vk_name bigf name; paramst +> List.iter (fun (param,iicomma) -> vk_param bigf param; iif iicomma; ); oldstyle +> Common.do_option (fun decls -> decls +> List.iter (vk_decl bigf); ); statxs +> List.iter (vk_statement_sequencable bigf) in f (k, bigf) d and vk_toplevel = fun bigf p -> let f = bigf.ktoplevel in let iif ii = vk_ii bigf ii in let rec k p = match p with | Declaration decl -> (vk_decl bigf decl) | Definition def -> (vk_def bigf def) | EmptyDef ii -> iif ii | MacroTop (s, xs, ii) -> vk_argument_list bigf xs; iif ii | CppTop top -> vk_cpp_directive bigf top | IfdefTop ifdefdir -> vk_ifdef_directive bigf ifdefdir | NotParsedCorrectly ii -> iif ii | FinalDef info -> vk_info bigf info | Namespace (tls, ii) -> List.iter (vk_toplevel bigf) tls in f (k, bigf) p and vk_program = fun bigf xs -> xs +> List.iter (vk_toplevel bigf) and vk_ifdef_directive bigf directive = let iif ii = vk_ii bigf ii in match directive with | IfdefDirective (ifkind, ii) -> iif ii and vk_cpp_directive bigf directive = let iif ii = vk_ii bigf ii in let f = bigf.kcppdirective in let rec k directive = match directive with | Include {i_include = (s, ii); i_content = copt; } -> (* go inside ? yes, can be useful, for instance for type_annotater. * The only pb may be that when we want to unparse the code we * don't want to unparse the included file but the unparser * and pretty_print do not use visitor_c so no problem. *) iif ii; copt +> Common.do_option (fun (file, asts) -> vk_program bigf asts ); | Define ((s,ii), (defkind, defval)) -> iif ii; vk_define_kind bigf defkind; vk_define_val bigf defval | PragmaAndCo (ii) -> iif ii in f (k, bigf) directive and vk_define_kind bigf defkind = match defkind with | DefineVar -> () | DefineFunc (params, ii) -> vk_ii bigf ii; params +> List.iter (fun ((s,iis), iicomma) -> vk_ii bigf iis; vk_ii bigf iicomma; ) | Undef -> () and vk_define_val bigf defval = let f = bigf.kdefineval in let rec k defval = match defval with | DefineExpr e -> vk_expr bigf e | DefineStmt stmt -> vk_statement bigf stmt | DefineDoWhileZero ((stmt, e), ii) -> vk_statement bigf stmt; vk_expr bigf e; vk_ii bigf ii | DefineFunction def -> vk_def bigf def | DefineType ty -> vk_type bigf ty | DefineText (s, ii) -> vk_ii bigf ii | DefineEmpty -> () | DefineInit ini -> vk_ini bigf ini (* christia: added multi *) | DefineMulti stmts -> List.fold_left (fun () d -> vk_statement bigf d) () stmts | DefineTodo -> pr2_once "DefineTodo"; () in f (k, bigf) defval (* ------------------------------------------------------------------------ *) (* Now keep fullstatement inside the control flow node, * so that can then get in a MetaStmtVar the fullstatement to later * pp back when the S is in a +. But that means that * Exp will match an Ifnode even if there is no such exp * inside the condition of the Ifnode (because the exp may * be deeper, in the then branch). So have to not visit * all inside a node anymore. * * update: j'ai choisi d'accrocher au noeud du CFG a la * fois le fullstatement et le partialstatement et appeler le * visiteur que sur le partialstatement. *) and vk_node = fun bigf node -> let iif ii = vk_ii bigf ii in let infof info = vk_info bigf info in let f = bigf.knode in let rec k n = match F.unwrap n with | F.FunHeader (def) -> assert(null (fst def).f_body); vk_def bigf def; | F.Decl decl -> vk_decl bigf decl | F.ExprStatement (st, (eopt, ii)) -> iif ii; eopt +> do_option (vk_expr bigf) | F.IfHeader (_, (e,ii)) | F.SwitchHeader (_, (e,ii)) | F.WhileHeader (_, (e,ii)) | F.DoWhileTail (e,ii) -> iif ii; vk_expr bigf e | F.ForHeader (_st, ((ForExp (e1opt,i1), (e2opt,i2), (e3opt,i3)), ii)) -> iif i1; iif i2; iif i3; iif ii; e1opt +> do_option (vk_expr bigf); e2opt +> do_option (vk_expr bigf); e3opt +> do_option (vk_expr bigf); | F.ForHeader (_st, ((ForDecl decl, (e2opt,i2), (e3opt,i3)), ii)) -> iif i2; iif i3; iif ii; decl +> (vk_decl bigf); e2opt +> do_option (vk_expr bigf); e3opt +> do_option (vk_expr bigf); | F.MacroIterHeader (_s, ((s,es), ii)) -> iif ii; vk_argument_list bigf es; | F.ReturnExpr (_st, (e,ii)) -> iif ii; vk_expr bigf e | F.Case (_st, (e,ii)) -> iif ii; vk_expr bigf e | F.CaseRange (_st, ((e1, e2),ii)) -> iif ii; vk_expr bigf e1; vk_expr bigf e2 | F.CaseNode i -> () | F.DefineExpr e -> vk_expr bigf e | F.DefineType ft -> vk_type bigf ft | F.DefineHeader ((s,ii), (defkind)) -> iif ii; vk_define_kind bigf defkind; | F.DefineDoWhileZeroHeader (((),ii)) -> iif ii | F.DefineTodo -> pr2_once "DefineTodo"; () | F.Include {i_include = (s, ii);} -> iif ii; | F.MacroTop (s, args, ii) -> iif ii; vk_argument_list bigf args | F.IfdefHeader (info) -> vk_ifdef_directive bigf info | F.IfdefElse (info) -> vk_ifdef_directive bigf info | F.IfdefEndif (info) -> vk_ifdef_directive bigf info | F.Break (st,((),ii)) -> iif ii | F.Continue (st,((),ii)) -> iif ii | F.Default (st,((),ii)) -> iif ii | F.Return (st,((),ii)) -> iif ii | F.Goto (st, name, ((),ii)) -> vk_name bigf name; iif ii | F.Label (st, name, ((),ii)) -> vk_name bigf name; iif ii | F.DoHeader (st, info) -> infof info | F.Else info -> infof info | F.EndStatement iopt -> do_option infof iopt | F.SeqEnd (i, info) -> infof info | F.SeqStart (st, i, info) -> infof info | F.MacroStmt (st, ((),ii)) -> iif ii | F.Asm (st, (asmbody,ii)) -> iif ii; vk_asmbody bigf asmbody | ( F.TopNode|F.EndNode| F.ErrorExit|F.Exit|F.Enter|F.LoopFallThroughNode|F.FallThroughNode| F.AfterNode|F.FalseNode|F.TrueNode|F.InLoopNode| F.Fake ) -> () in f (k, bigf) node (* ------------------------------------------------------------------------ *) and vk_info = fun bigf info -> let rec infof ii = bigf.kinfo (k, bigf) ii and k i = () in infof info and vk_ii = fun bigf ii -> List.iter (vk_info bigf) ii (* ------------------------------------------------------------------------ *) and vk_argument = fun bigf arg -> let rec do_action = function | (ActMisc ii) -> vk_ii bigf ii in match arg with | Left e -> (vk_expr bigf) e | Right (ArgType param) -> vk_param bigf param | Right (ArgAction action) -> do_action action and vk_argument_list = fun bigf es -> let iif ii = vk_ii bigf ii in es +> List.iter (fun (e, ii) -> iif ii; vk_argument bigf e ) and vk_param = fun bigf param -> let iif ii = vk_ii bigf ii in let f = bigf.kparam in let rec k param = let {p_namei = swrapopt; p_register = (b, iib); p_type=ft} = param in swrapopt +> Common.do_option (vk_name bigf); iif iib; vk_type bigf ft in f (k, bigf) param and vk_param_list = fun bigf ts -> let iif ii = vk_ii bigf ii in ts +> List.iter (fun (param,iicomma) -> vk_param bigf param; iif iicomma; ) (* ------------------------------------------------------------------------ *) and vk_asmbody = fun bigf (string_list, colon_list) -> let iif ii = vk_ii bigf ii in iif string_list; colon_list +> List.iter (fun (Colon xs, ii) -> iif ii; xs +> List.iter (fun (x,iicomma) -> iif iicomma; (match x with | ColonMisc, ii -> iif ii | ColonExpr e, ii -> vk_expr bigf e; iif ii ) )) (* ------------------------------------------------------------------------ *) let vk_splitted element = fun bigf args_splitted -> let iif ii = vk_ii bigf ii in args_splitted +> List.iter (function | Left arg -> element bigf arg | Right ii -> iif ii ) let vk_args_splitted = vk_splitted vk_argument let vk_define_params_splitted = vk_splitted (fun bigf (_,ii) -> vk_ii bigf ii) let vk_params_splitted = vk_splitted vk_param let vk_enum_fields_splitted = vk_splitted vk_oneEnum let vk_inis_splitted = vk_splitted vk_ini (* ------------------------------------------------------------------------ *) let vk_cst = fun bigf (cst, ii) -> let iif ii = vk_ii bigf ii in iif ii; (match cst with | Left cst -> () | Right s -> () ) (*****************************************************************************) (* "syntetisized attributes" style *) (*****************************************************************************) (* TODO port the xxs_s to new cpp construct too *) type 'a inout = 'a -> 'a (* _s for synthetizized attributes * * Note that I don't visit necesserally in the order of the token * found in the original file. So don't assume such hypothesis! *) type visitor_c_s = { kexpr_s: (expression inout * visitor_c_s) -> expression inout; kstatement_s: (statement inout * visitor_c_s) -> statement inout; ktype_s: (fullType inout * visitor_c_s) -> fullType inout; kdecl_s: (declaration inout * visitor_c_s) -> declaration inout; kdef_s: (definition inout * visitor_c_s) -> definition inout; kname_s: (name inout * visitor_c_s) -> name inout; kini_s: (initialiser inout * visitor_c_s) -> initialiser inout; kcppdirective_s: (cpp_directive inout * visitor_c_s) -> cpp_directive inout; kdefineval_s: (define_val inout * visitor_c_s) -> define_val inout; kstatementseq_s: (statement_sequencable inout * visitor_c_s) -> statement_sequencable inout; kstatementseq_list_s: (statement_sequencable list inout * visitor_c_s) -> statement_sequencable list inout; knode_s: (F.node inout * visitor_c_s) -> F.node inout; ktoplevel_s: (toplevel inout * visitor_c_s) -> toplevel inout; kinfo_s: (info inout * visitor_c_s) -> info inout; } let default_visitor_c_s = { kexpr_s = (fun (k,_) e -> k e); kstatement_s = (fun (k,_) st -> k st); ktype_s = (fun (k,_) t -> k t); kdecl_s = (fun (k,_) d -> k d); kdef_s = (fun (k,_) d -> k d); kname_s = (fun (k,_) x -> k x); kini_s = (fun (k,_) d -> k d); ktoplevel_s = (fun (k,_) p -> k p); knode_s = (fun (k,_) n -> k n); kinfo_s = (fun (k,_) i -> k i); kdefineval_s = (fun (k,_) x -> k x); kstatementseq_s = (fun (k,_) x -> k x); kstatementseq_list_s = (fun (k,_) x -> k x); kcppdirective_s = (fun (k,_) x -> k x); } let rec vk_expr_s = fun bigf expr -> let iif ii = vk_ii_s bigf ii in let rec exprf e = bigf.kexpr_s (k, bigf) e and k e = let ((unwrap_e, typ), ii) = e in (* !!! don't analyse optional type !!! * old: typ +> map_option (vk_type_s bigf) in *) let typ' = typ in let e' = match unwrap_e with | Ident (name) -> Ident (vk_name_s bigf name) | Constant (c) -> Constant (c) | FunCall (e, es) -> FunCall (exprf e, es +> List.map (fun (e,ii) -> vk_argument_s bigf e, iif ii )) | CondExpr (e1, e2, e3) -> CondExpr (exprf e1, fmap exprf e2, exprf e3) | Sequence (e1, e2) -> Sequence (exprf e1, exprf e2) | Assignment (e1, op, e2) -> Assignment (exprf e1, op, exprf e2) | Postfix (e, op) -> Postfix (exprf e, op) | Infix (e, op) -> Infix (exprf e, op) | Unary (e, op) -> Unary (exprf e, op) | Binary (e1, op, e2) -> Binary (exprf e1, op, exprf e2) | ArrayAccess (e1, e2) -> ArrayAccess (exprf e1, exprf e2) | RecordAccess (e, name) -> RecordAccess (exprf e, vk_name_s bigf name) | RecordPtAccess (e, name) -> RecordPtAccess (exprf e, vk_name_s bigf name) | SizeOfExpr (e) -> SizeOfExpr (exprf e) | SizeOfType (t) -> SizeOfType (vk_type_s bigf t) | Cast (t, e) -> Cast (vk_type_s bigf t, exprf e) | StatementExpr (statxs, is) -> StatementExpr ( vk_statement_sequencable_list_s bigf statxs, iif is) | Constructor (t, init) -> Constructor (vk_type_s bigf t, vk_ini_s bigf init) | ParenExpr (e) -> ParenExpr (exprf e) | New (None, t) -> New (None, vk_argument_s bigf t) | New (Some ts, t) -> New (Some (ts +> List.map (fun (e,ii) -> vk_argument_s bigf e, iif ii)), vk_argument_s bigf t) | Delete e -> Delete (vk_expr_s bigf e) in (e', typ'), (iif ii) in exprf expr and vk_argument_s bigf argument = let iif ii = vk_ii_s bigf ii in let rec do_action = function | (ActMisc ii) -> ActMisc (iif ii) in (match argument with | Left e -> Left (vk_expr_s bigf e) | Right (ArgType param) -> Right (ArgType (vk_param_s bigf param)) | Right (ArgAction action) -> Right (ArgAction (do_action action)) ) (* ------------------------------------------------------------------------ *) and vk_name_s = fun bigf ident -> let iif ii = vk_ii_s bigf ii in let rec namef x = bigf.kname_s (k,bigf) x and k id = (match id with | RegularName (s,ii) -> RegularName (s, iif ii) | CppConcatenatedName xs -> CppConcatenatedName (xs +> List.map (fun ((x,ii1), ii2) -> (x, iif ii1), iif ii2 )) | CppVariadicName (s, ii) -> CppVariadicName (s, iif ii) | CppIdentBuilder ((s,iis), xs) -> CppIdentBuilder ((s, iif iis), xs +> List.map (fun ((x,iix), iicomma) -> ((x, iif iix), iif iicomma))) ) in namef ident (* ------------------------------------------------------------------------ *) and vk_statement_s = fun bigf st -> let rec statf st = bigf.kstatement_s (k, bigf) st and k st = let (unwrap_st, ii) = st in let st' = match unwrap_st with | Labeled (Label (name, st)) -> Labeled (Label (vk_name_s bigf name, statf st)) | Labeled (Case (e, st)) -> Labeled (Case ((vk_expr_s bigf) e , statf st)) | Labeled (CaseRange (e, e2, st)) -> Labeled (CaseRange ((vk_expr_s bigf) e, (vk_expr_s bigf) e2, statf st)) | Labeled (Default st) -> Labeled (Default (statf st)) | Compound statxs -> Compound (vk_statement_sequencable_list_s bigf statxs) | ExprStatement (None) -> ExprStatement (None) | ExprStatement (Some e) -> ExprStatement (Some ((vk_expr_s bigf) e)) | Selection (If (e, st1, st2)) -> Selection (If ((vk_expr_s bigf) e, statf st1, statf st2)) | Selection (Switch (e, st)) -> Selection (Switch ((vk_expr_s bigf) e, statf st)) | Iteration (While (e, st)) -> Iteration (While ((vk_expr_s bigf) e, statf st)) | Iteration (DoWhile (st, e)) -> Iteration (DoWhile (statf st, (vk_expr_s bigf) e)) | Iteration (For (first, (e2opt,i2), (e3opt,i3), st)) -> let first = match first with ForExp (e1opt,i1) -> let e1opt' = statf (mk_st (ExprStatement (e1opt)) i1) in let e1' = Ast_c.unwrap_st e1opt' in let i1' = Ast_c.get_ii_st_take_care e1opt' in (match e1' with ExprStatement x1 -> ForExp (x1,i1') | _ -> failwith "cant be here if iterator keep ExprStatement as is") | ForDecl decl -> ForDecl (vk_decl_s bigf decl) in let e2opt' = statf (mk_st (ExprStatement (e2opt)) i2) in let e3opt' = statf (mk_st (ExprStatement (e3opt)) i3) in let e2' = Ast_c.unwrap_st e2opt' in let e3' = Ast_c.unwrap_st e3opt' in let i2' = Ast_c.get_ii_st_take_care e2opt' in let i3' = Ast_c.get_ii_st_take_care e3opt' in (match (e2', e3') with | ((ExprStatement x2), ((ExprStatement x3))) -> Iteration (For (first, (x2,i2'), (x3,i3'), statf st)) | x -> failwith "cant be here if iterator keep ExprStatement as is" ) | Iteration (MacroIteration (s, es, st)) -> Iteration (MacroIteration (s, es +> List.map (fun (e, ii) -> vk_argument_s bigf e, vk_ii_s bigf ii ), statf st )) | Jump (Goto name) -> Jump (Goto (vk_name_s bigf name)) | Jump (((Continue|Break|Return) as x)) -> Jump (x) | Jump (ReturnExpr e) -> Jump (ReturnExpr ((vk_expr_s bigf) e)) | Jump (GotoComputed e) -> Jump (GotoComputed (vk_expr_s bigf e)); | Decl decl -> Decl (vk_decl_s bigf decl) | Asm asmbody -> Asm (vk_asmbody_s bigf asmbody) | NestedFunc def -> NestedFunc (vk_def_s bigf def) | MacroStmt -> MacroStmt in st', vk_ii_s bigf ii in statf st and vk_statement_sequencable_s = fun bigf stseq -> let f = bigf.kstatementseq_s in let k stseq = match stseq with | StmtElem st -> StmtElem (vk_statement_s bigf st) | CppDirectiveStmt directive -> CppDirectiveStmt (vk_cpp_directive_s bigf directive) | IfdefStmt ifdef -> IfdefStmt (vk_ifdef_directive_s bigf ifdef) | IfdefStmt2 (ifdef, xxs) -> let ifdef' = List.map (vk_ifdef_directive_s bigf) ifdef in let xxs' = xxs +> List.map (fun xs -> xs +> vk_statement_sequencable_list_s bigf ) in IfdefStmt2(ifdef', xxs') in f (k, bigf) stseq and vk_statement_sequencable_list_s = fun bigf statxs -> let f = bigf.kstatementseq_list_s in let k xs = xs +> List.map (vk_statement_sequencable_s bigf) in f (k, bigf) statxs and vk_asmbody_s = fun bigf (string_list, colon_list) -> let iif ii = vk_ii_s bigf ii in iif string_list, colon_list +> List.map (fun (Colon xs, ii) -> Colon (xs +> List.map (fun (x, iicomma) -> (match x with | ColonMisc, ii -> ColonMisc, iif ii | ColonExpr e, ii -> ColonExpr (vk_expr_s bigf e), iif ii ), iif iicomma )), iif ii ) (* todo? a visitor for qualifier *) and vk_type_s = fun bigf t -> let rec typef t = bigf.ktype_s (k,bigf) t and iif ii = vk_ii_s bigf ii and k t = let (q, t) = t in let (unwrap_q, iiq) = q in (* strip_info_visitor needs iiq to be processed before iit *) let iif_iiq = iif iiq in let q' = unwrap_q in let (unwrap_t, iit) = t in let t' = match unwrap_t with | NoType -> NoType | BaseType x -> BaseType x | Pointer t -> Pointer (typef t) | Array (eopt, t) -> Array (fmap (vk_expr_s bigf) eopt, typef t) | FunctionType (returnt, paramst) -> FunctionType (typef returnt, (match paramst with | (ts, (b, iihas3dots)) -> (ts +> List.map (fun (param,iicomma) -> (vk_param_s bigf param, iif iicomma)), (b, iif iihas3dots)) )) | Enum (sopt, enumt) -> Enum (sopt, vk_enum_fields_s bigf enumt) | StructUnion (sopt, su, fields) -> StructUnion (sopt, su, vk_struct_fields_s bigf fields) | StructUnionName (s, structunion) -> StructUnionName (s, structunion) | EnumName s -> EnumName s | TypeName (name, typ) -> TypeName (vk_name_s bigf name, typ) | ParenType t -> ParenType (typef t) | TypeOfExpr e -> TypeOfExpr (vk_expr_s bigf e) | TypeOfType t -> TypeOfType (typef t) in (q', iif_iiq), (t', iif iit) in typef t and vk_attribute_s = fun bigf attr -> let iif ii = vk_ii_s bigf ii in match attr with | Attribute s, ii -> Attribute s, iif ii and vk_decl_s = fun bigf d -> let f = bigf.kdecl_s in let iif ii = vk_ii_s bigf ii in let rec k decl = match decl with | DeclList (xs, ii) -> DeclList (List.map aux xs, iif ii) | MacroDecl ((s, args, ptvg),ii) -> MacroDecl ((s, args +> List.map (fun (e,ii) -> vk_argument_s bigf e, iif ii), ptvg), iif ii) | MacroDeclInit ((s, args, ini),ii) -> MacroDeclInit ((s, args +> List.map (fun (e,ii) -> vk_argument_s bigf e, iif ii), vk_ini_s bigf ini), iif ii) and aux ({v_namei = var; v_type = t; v_type_bis = tbis; v_storage = sto; v_local= local; v_attr = attrs}, iicomma) = {v_namei = (var +> map_option (fun (name, iniopt) -> vk_name_s bigf name, (match iniopt with Ast_c.NoInit -> iniopt | Ast_c.ValInit(iini,init) -> Ast_c.ValInit(vk_info_s bigf iini,vk_ini_s bigf init) | Ast_c.ConstrInit((init,ii)) -> let init = init +> List.map (fun (e,ii) -> vk_argument_s bigf e, iif ii) in Ast_c.ConstrInit((init, List.map (vk_info_s bigf) ii))) )); v_type = vk_type_s bigf t; (* !!! dont go in semantic related stuff !!! *) v_type_bis = tbis; v_storage = sto; v_local = local; v_attr = attrs +> List.map (vk_attribute_s bigf); }, iif iicomma in f (k, bigf) d and vk_decl_list_s = fun bigf decls -> decls +> List.map (vk_decl_s bigf) and vk_ini_s = fun bigf ini -> let rec inif ini = bigf.kini_s (k,bigf) ini and k ini = let (unwrap_ini, ii) = ini in let ini' = match unwrap_ini with | InitExpr e -> InitExpr (vk_expr_s bigf e) | InitList initxs -> InitList (initxs +> List.map (fun (ini, ii) -> inif ini, vk_ii_s bigf ii) ) | InitDesignators (xs, e) -> InitDesignators (xs +> List.map (vk_designator_s bigf), inif e ) | InitFieldOld (s, e) -> InitFieldOld (s, inif e) | InitIndexOld (e1, e) -> InitIndexOld (vk_expr_s bigf e1, inif e) in ini', vk_ii_s bigf ii in inif ini and vk_designator_s = fun bigf design -> let iif ii = vk_ii_s bigf ii in let (designator, ii) = design in (match designator with | DesignatorField s -> DesignatorField s | DesignatorIndex e -> DesignatorIndex (vk_expr_s bigf e) | DesignatorRange (e1, e2) -> DesignatorRange (vk_expr_s bigf e1, vk_expr_s bigf e2) ), iif ii and vk_struct_fieldkinds_s = fun bigf onefield_multivars -> let iif ii = vk_ii_s bigf ii in onefield_multivars +> List.map (fun (field, iicomma) -> (match field with | Simple (nameopt, t) -> Simple (Common.map_option (vk_name_s bigf) nameopt, vk_type_s bigf t) | BitField (nameopt, t, info, expr) -> BitField (Common.map_option (vk_name_s bigf) nameopt, vk_type_s bigf t, vk_info_s bigf info, vk_expr_s bigf expr) ), iif iicomma ) and vk_struct_field_s = fun bigf field -> let iif ii = vk_ii_s bigf ii in match field with (DeclarationField (FieldDeclList (onefield_multivars, iiptvirg))) -> DeclarationField (FieldDeclList (vk_struct_fieldkinds_s bigf onefield_multivars, iif iiptvirg)) | EmptyField info -> EmptyField (vk_info_s bigf info) | MacroDeclField ((s, args),ii) -> MacroDeclField ((s, args +> List.map (fun (e,ii) -> vk_argument_s bigf e, iif ii) ), iif ii) | CppDirectiveStruct directive -> CppDirectiveStruct (vk_cpp_directive_s bigf directive) | IfdefStruct ifdef -> IfdefStruct (vk_ifdef_directive_s bigf ifdef) and vk_struct_fields_s = fun bigf fields -> fields +> List.map (vk_struct_field_s bigf) and vk_enum_fields_s = fun bigf enumt -> let iif ii = vk_ii_s bigf ii in enumt +> List.map (fun ((name, eopt), iicomma) -> vk_oneEnum_s bigf (name, eopt), iif iicomma) and vk_oneEnum_s = fun bigf oneEnum -> let (name,eopt) = oneEnum in (vk_name_s bigf name, eopt +> Common.fmap (fun (info, e) -> vk_info_s bigf info, vk_expr_s bigf e )) and vk_def_s = fun bigf d -> let f = bigf.kdef_s in let iif ii = vk_ii_s bigf ii in let rec k d = match d with | {f_name = name; f_type = (returnt, (paramst, (b, iib))); f_storage = sto; f_body = statxs; f_attr = attrs; f_old_c_style = oldstyle; }, ii -> {f_name = vk_name_s bigf name; f_type = (vk_type_s bigf returnt, (paramst +> List.map (fun (param, iicomma) -> (vk_param_s bigf param, iif iicomma) ), (b, iif iib))); f_storage = sto; f_body = vk_statement_sequencable_list_s bigf statxs; f_attr = attrs +> List.map (vk_attribute_s bigf); f_old_c_style = oldstyle +> Common.map_option (fun decls -> decls +> List.map (vk_decl_s bigf) ); }, iif ii in f (k, bigf) d and vk_toplevel_s = fun bigf p -> let f = bigf.ktoplevel_s in let iif ii = vk_ii_s bigf ii in let rec k p = match p with | Declaration decl -> Declaration (vk_decl_s bigf decl) | Definition def -> Definition (vk_def_s bigf def) | EmptyDef ii -> EmptyDef (iif ii) | MacroTop (s, xs, ii) -> MacroTop (s, xs +> List.map (fun (elem, iicomma) -> vk_argument_s bigf elem, iif iicomma ), iif ii ) | CppTop top -> CppTop (vk_cpp_directive_s bigf top) | IfdefTop ifdefdir -> IfdefTop (vk_ifdef_directive_s bigf ifdefdir) | NotParsedCorrectly ii -> NotParsedCorrectly (iif ii) | FinalDef info -> FinalDef (vk_info_s bigf info) | Namespace (tls, ii) -> Namespace (List.map (vk_toplevel_s bigf) tls, ii) in f (k, bigf) p and vk_program_s = fun bigf xs -> xs +> List.map (vk_toplevel_s bigf) and vk_cpp_directive_s = fun bigf top -> let iif ii = vk_ii_s bigf ii in let f = bigf.kcppdirective_s in let rec k top = match top with (* go inside ? *) | Include {i_include = (s, ii); i_rel_pos = h_rel_pos; i_is_in_ifdef = b; i_content = copt; } -> Include {i_include = (s, iif ii); i_rel_pos = h_rel_pos; i_is_in_ifdef = b; i_content = copt +> Common.map_option (fun (file, asts) -> file, vk_program_s bigf asts ); } | Define ((s,ii), (defkind, defval)) -> Define ((s, iif ii), (vk_define_kind_s bigf defkind, vk_define_val_s bigf defval)) | PragmaAndCo (ii) -> PragmaAndCo (iif ii) in f (k, bigf) top and vk_ifdef_directive_s = fun bigf ifdef -> let iif ii = vk_ii_s bigf ii in match ifdef with | IfdefDirective (ifkind, ii) -> IfdefDirective (ifkind, iif ii) and vk_define_kind_s = fun bigf defkind -> match defkind with | DefineVar -> DefineVar | DefineFunc (params, ii) -> DefineFunc (params +> List.map (fun ((s,iis),iicomma) -> ((s, vk_ii_s bigf iis), vk_ii_s bigf iicomma) ), vk_ii_s bigf ii ) | Undef -> Undef and vk_define_val_s = fun bigf x -> let f = bigf.kdefineval_s in let iif ii = vk_ii_s bigf ii in let rec k x = match x with | DefineExpr e -> DefineExpr (vk_expr_s bigf e) | DefineStmt st -> DefineStmt (vk_statement_s bigf st) | DefineDoWhileZero ((st,e),ii) -> let st' = vk_statement_s bigf st in let e' = vk_expr_s bigf e in DefineDoWhileZero ((st',e'), iif ii) | DefineFunction def -> DefineFunction (vk_def_s bigf def) | DefineType ty -> DefineType (vk_type_s bigf ty) | DefineText (s, ii) -> DefineText (s, iif ii) | DefineEmpty -> DefineEmpty | DefineInit ini -> DefineInit (vk_ini_s bigf ini) (* christia: added multi *) | DefineMulti ds -> DefineMulti (List.map (vk_statement_s bigf) ds) | DefineTodo -> pr2_once "DefineTodo"; DefineTodo in f (k, bigf) x and vk_info_s = fun bigf info -> let rec infof ii = bigf.kinfo_s (k, bigf) ii and k i = i in infof info and vk_ii_s = fun bigf ii -> List.map (vk_info_s bigf) ii (* ------------------------------------------------------------------------ *) and vk_node_s = fun bigf node -> let iif ii = vk_ii_s bigf ii in let infof info = vk_info_s bigf info in let rec nodef n = bigf.knode_s (k, bigf) n and k node = F.rewrap node ( match F.unwrap node with | F.FunHeader (def) -> assert (null (fst def).f_body); F.FunHeader (vk_def_s bigf def) | F.Decl declb -> F.Decl (vk_decl_s bigf declb) | F.ExprStatement (st, (eopt, ii)) -> F.ExprStatement (st, (eopt +> map_option (vk_expr_s bigf), iif ii)) | F.IfHeader (st, (e,ii)) -> F.IfHeader (st, (vk_expr_s bigf e, iif ii)) | F.SwitchHeader (st, (e,ii)) -> F.SwitchHeader(st, (vk_expr_s bigf e, iif ii)) | F.WhileHeader (st, (e,ii)) -> F.WhileHeader (st, (vk_expr_s bigf e, iif ii)) | F.DoWhileTail (e,ii) -> F.DoWhileTail (vk_expr_s bigf e, iif ii) | F.ForHeader (st, ((first, (e2opt,i2), (e3opt,i3)), ii)) -> let first = match first with ForExp (e1opt,i1) -> ForExp (e1opt +> Common.map_option (vk_expr_s bigf), iif i1) | ForDecl decl -> ForDecl (vk_decl_s bigf decl) in F.ForHeader (st, ((first, (e2opt +> Common.map_option (vk_expr_s bigf), iif i2), (e3opt +> Common.map_option (vk_expr_s bigf), iif i3)), iif ii)) | F.MacroIterHeader (st, ((s,es), ii)) -> F.MacroIterHeader (st, ((s, es +> List.map (fun (e, ii) -> vk_argument_s bigf e, iif ii)), iif ii)) | F.ReturnExpr (st, (e,ii)) -> F.ReturnExpr (st, (vk_expr_s bigf e, iif ii)) | F.Case (st, (e,ii)) -> F.Case (st, (vk_expr_s bigf e, iif ii)) | F.CaseRange (st, ((e1, e2),ii)) -> F.CaseRange (st, ((vk_expr_s bigf e1, vk_expr_s bigf e2), iif ii)) | F.CaseNode i -> F.CaseNode i | F.DefineHeader((s,ii), (defkind)) -> F.DefineHeader ((s, iif ii), (vk_define_kind_s bigf defkind)) | F.DefineExpr e -> F.DefineExpr (vk_expr_s bigf e) | F.DefineType ft -> F.DefineType (vk_type_s bigf ft) | F.DefineDoWhileZeroHeader ((),ii) -> F.DefineDoWhileZeroHeader ((),iif ii) | F.DefineTodo -> F.DefineTodo | F.Include {i_include = (s, ii); i_rel_pos = h_rel_pos; i_is_in_ifdef = b; i_content = copt; } -> assert (copt =*= None); F.Include {i_include = (s, iif ii); i_rel_pos = h_rel_pos; i_is_in_ifdef = b; i_content = copt; } | F.MacroTop (s, args, ii) -> F.MacroTop (s, args +> List.map (fun (e, ii) -> vk_argument_s bigf e, iif ii), iif ii) | F.MacroStmt (st, ((),ii)) -> F.MacroStmt (st, ((),iif ii)) | F.Asm (st, (body,ii)) -> F.Asm (st, (vk_asmbody_s bigf body,iif ii)) | F.Break (st,((),ii)) -> F.Break (st,((),iif ii)) | F.Continue (st,((),ii)) -> F.Continue (st,((),iif ii)) | F.Default (st,((),ii)) -> F.Default (st,((),iif ii)) | F.Return (st,((),ii)) -> F.Return (st,((),iif ii)) | F.Goto (st, name, ((),ii)) -> F.Goto (st, vk_name_s bigf name, ((),iif ii)) | F.Label (st, name, ((),ii)) -> F.Label (st, vk_name_s bigf name, ((),iif ii)) | F.EndStatement iopt -> F.EndStatement (map_option infof iopt) | F.DoHeader (st, info) -> F.DoHeader (st, infof info) | F.Else info -> F.Else (infof info) | F.SeqEnd (i, info) -> F.SeqEnd (i, infof info) | F.SeqStart (st, i, info) -> F.SeqStart (st, i, infof info) | F.IfdefHeader (info) -> F.IfdefHeader (vk_ifdef_directive_s bigf info) | F.IfdefElse (info) -> F.IfdefElse (vk_ifdef_directive_s bigf info) | F.IfdefEndif (info) -> F.IfdefEndif (vk_ifdef_directive_s bigf info) | ( ( F.TopNode|F.EndNode| F.ErrorExit|F.Exit|F.Enter|F.LoopFallThroughNode|F.FallThroughNode| F.AfterNode|F.FalseNode|F.TrueNode|F.InLoopNode| F.Fake ) as x) -> x ) in nodef node (* ------------------------------------------------------------------------ *) and vk_param_s = fun bigf param -> let iif ii = vk_ii_s bigf ii in let {p_namei = swrapopt; p_register = (b, iib); p_type=ft} = param in { p_namei = swrapopt +> Common.map_option (vk_name_s bigf); p_register = (b, iif iib); p_type = vk_type_s bigf ft; } let vk_arguments_s = fun bigf args -> let iif ii = vk_ii_s bigf ii in args +> List.map (fun (e, ii) -> vk_argument_s bigf e, iif ii) let vk_inis_s = fun bigf inis -> let iif ii = vk_ii_s bigf ii in inis +> List.map (fun (e, ii) -> vk_ini_s bigf e, iif ii) let vk_params_s = fun bigf args -> let iif ii = vk_ii_s bigf ii in args +> List.map (fun (p,ii) -> vk_param_s bigf p, iif ii) let vk_cst_s = fun bigf (cst, ii) -> let iif ii = vk_ii_s bigf ii in (match cst with | Left cst -> Left cst | Right s -> Right s ), iif ii (* ------------------------------------------------------------------------ *) let vk_splitted_s element = fun bigf args_splitted -> let iif ii = vk_ii_s bigf ii in args_splitted +> List.map (function | Left arg -> Left (element bigf arg) | Right ii -> Right (iif ii) ) let vk_args_splitted_s = vk_splitted_s vk_argument_s let vk_params_splitted_s = vk_splitted_s vk_param_s let vk_define_params_splitted_s = vk_splitted_s (fun bigf (s,ii) -> (s,vk_ii_s bigf ii)) let vk_enum_fields_splitted_s = vk_splitted_s vk_oneEnum_s let vk_inis_splitted_s = vk_splitted_s vk_ini_s