desug.ml 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. open Ast
  2. open Util
  3. let rec flatten_blocks = function
  4. | [] -> []
  5. | Block nodes :: t -> (flatten_blocks nodes) @ (flatten_blocks t)
  6. | h :: t -> h :: (flatten_blocks t)
  7. let rec var_init = function
  8. (* Split local variable initialisations in declaration and assignment *)
  9. | FunDef (export, ret_type, name, params, Block body, loc) ->
  10. let move_inits body =
  11. let rec trav inits node = match node with
  12. (* translate scalar array initialisation to ArrayScalar node,
  13. * for easy replacement later on *)
  14. | VarDec (ArrayDef (_, _) as vtype, name,
  15. Some ((BoolConst (_, l)) as v), loc) :: t
  16. | VarDec (ArrayDef (_, _) as vtype, name,
  17. Some ((FloatConst (_, l)) as v), loc) :: t
  18. | VarDec (ArrayDef (_, _) as vtype, name,
  19. Some ((IntConst (_, l)) as v), loc) :: t ->
  20. trav inits (VarDec (vtype, name, Some (ArrayScalar (v, l)), loc) :: t)
  21. | VarDec (ctype, name, init, loc) :: t ->
  22. (* array definition: create __allocate statement *)
  23. let alloc = match ctype with
  24. | ArrayDef (_, dims) -> [Allocate (name, dims, loc)]
  25. | _ -> []
  26. in
  27. (* initialisation: create assign statement *)
  28. let add = match init with
  29. | Some value -> alloc @ [Assign (name, value, loc)]
  30. | None -> alloc
  31. in
  32. VarDec (ctype, name, None, loc) :: (trav (inits @ add) t)
  33. (* initialisations need to be placed after local functions *)
  34. | (FunDef (_, _, _, _, _, _) as h) :: t ->
  35. (var_init h) :: (trav inits t)
  36. (* rest of function body: recurse *)
  37. | rest -> inits @ (List.map var_init rest)
  38. in trav [] body
  39. in
  40. FunDef (export, ret_type, name, params, Block (move_inits body), loc)
  41. (* Move global variable initialisations to exported __init function *)
  42. | GlobalDef (export, ctype, name, Some init, loc) ->
  43. Block [GlobalDef (export, ctype, name, None, loc);
  44. Assign (name, init, locof init)]
  45. (* Move global initialisations to __init function *)
  46. | Program (decls, loc) ->
  47. let decls = flatten_blocks (List.map var_init decls) in
  48. let rec trav assigns = function
  49. | [] -> (assigns, [])
  50. | (Assign (_, _, _) as h) :: t -> trav (assigns @ [h]) t
  51. | h :: t ->
  52. let (assigns, decls) = trav assigns t in
  53. (assigns, (h :: decls))
  54. in
  55. let (assigns, decls) = trav [] decls in
  56. (match assigns with
  57. | [] -> Program (decls, loc)
  58. | assigns ->
  59. let init_func = FunDef (true, Void, "__init", [], Block assigns, noloc) in
  60. Program (init_func :: decls, loc)
  61. )
  62. | node -> transform_children var_init node
  63. (*
  64. let rec array_init = function
  65. (* transform scalar assignment into nested for loops *)
  66. | Assign (name, ArrayScalar (value)) ->
  67. let rec add_loop indices = function
  68. | [] ->
  69. Assign (Deref (name, indices), value)
  70. | dim :: rest ->
  71. let counter = fresh_var "counter" in
  72. let ind = (indices @ [Var counter]) in
  73. For (counter, IntConst 0, dim, IntConst 1, add_loop ind rest)
  74. in
  75. add_loop [] dims
  76. | Assign (name, ArrayConst (dims)) -> Block []
  77. | node -> transform array_init node
  78. *)
  79. let rec phase repr =
  80. let _ = print_endline "- Desugaring" in
  81. match repr with
  82. | Node (node, verbose) ->
  83. Node (var_init node, verbose)
  84. | _ -> raise (CompileError "invalid input for this phase")