include Ast let var_counter = ref 0 let fresh_var prefix = var_counter := !var_counter + 1; prefix ^ "$" ^ string_of_int !var_counter (* Default tree transformation * (node -> node) -> node -> node *) let rec transform visitor node = let trav = visitor in let trav_all nodes = List.map trav nodes in match node with | Program (decls) -> Program (trav_all decls) | FunDec (ret_type, name, params) -> FunDec (ret_type, name, trav_all params) | FunDef (export, ret_type, name, params, body) -> FunDef (export, ret_type, name, trav_all params, trav_all body) | GlobalDec (ctype, name) -> GlobalDec (ctype, name) | GlobalDef (export, ctype, name, Some init) -> GlobalDef (export, ctype, name, Some (trav init)) | VarDec (ctype, name, Some init) -> VarDec (ctype, name, Some (trav init)) | Assign (name, value) -> Assign (name, trav value) | Return (value) -> Return (trav value) | If (cond, body) -> If (trav cond, trav_all body) | IfElse (cond, true_body, false_body) -> IfElse (trav cond, trav_all true_body, trav_all false_body) | While (cond, body) -> While (trav cond, trav_all body) | DoWhile (cond, body) -> DoWhile (trav cond, trav_all body) | For (counter, start, stop, step, body) -> For (counter, trav start, trav stop, trav step, trav_all body) | Expr (value) -> Expr (trav value) | Monop (op, value) -> Monop (op, trav value) | Binop (op, left, right) -> Binop (op, trav left, trav right) | Cond (cond, true_expr, false_expr) -> Cond (trav cond, trav true_expr, trav false_expr) | TypeCast (ctype, value) -> TypeCast (ctype, trav value) | FunCall (name, args) -> FunCall (name, trav_all args) | Statements (stats) -> Statements (trav_all stats) | Loc (node, loc) -> Loc (trav node, loc) | _ -> node