util.ml 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. open Printf
  2. open Lexing
  3. open Ast
  4. (* Logging functions *)
  5. let prt_line = prerr_endline
  6. let prt_node node = prt_line (Stringify.node2str node)
  7. let log_line verbosity line =
  8. if args.verbose >= verbosity then prt_line line
  9. let log_node verbosity node =
  10. if args.verbose >= verbosity then prt_node node
  11. let dbg_line = log_line verbosity_debug
  12. let dbg_node = log_node verbosity_debug
  13. (* Variable generation *)
  14. let var_counter = ref 0
  15. let fresh_var prefix =
  16. var_counter := !var_counter + 1;
  17. prefix ^ "$" ^ string_of_int !var_counter
  18. (* Constants are marked by a double $$ for recognition during constant
  19. * propagation *)
  20. let fresh_const prefix = fresh_var (prefix ^ "$")
  21. let loc_from_lexpos pstart pend =
  22. let (fname, ystart, yend, xstart, xend) = (
  23. pstart.pos_fname,
  24. pstart.pos_lnum,
  25. pend.pos_lnum,
  26. (pstart.pos_cnum - pstart.pos_bol + 1),
  27. (pend.pos_cnum - pend.pos_bol)
  28. ) in
  29. if ystart = yend && xend < xstart then
  30. (fname, ystart, yend, xstart, xstart)
  31. else
  32. (fname, ystart, yend, xstart, xend)
  33. let rec flatten_blocks lst =
  34. let flatten = flatten_blocks in
  35. let trav = function
  36. | FunDef (export, ret_type, name, params, Block body, loc) ->
  37. FunDef (export, ret_type, name, flatten params, Block (flatten body), loc)
  38. | If (cond, Block body, loc) ->
  39. If (cond, Block (flatten body), loc)
  40. | IfElse (cond, Block tbody, Block fbody, loc) ->
  41. IfElse (cond, Block (flatten tbody), Block (flatten fbody), loc)
  42. | While (cond, Block body, loc) ->
  43. While (cond, Block (flatten body), loc)
  44. | DoWhile (cond, Block body, loc) ->
  45. DoWhile (cond, Block (flatten body), loc)
  46. | For (counter, start, stop, step, Block body, loc) ->
  47. For (counter, start, stop, step, Block (flatten body), loc)
  48. | node -> node
  49. in
  50. match lst with
  51. | [] -> []
  52. | Block nodes :: tl -> flatten nodes @ (flatten tl)
  53. | DummyNode :: tl -> flatten tl
  54. | hd :: tl -> trav hd :: (flatten tl)
  55. (* Default tree transformation
  56. * (node -> node) -> node -> node *)
  57. let transform_children trav node =
  58. let trav_all nodes = List.map trav nodes in
  59. match node with
  60. | Program (decls, loc) ->
  61. Program (flatten_blocks (trav_all decls), loc)
  62. | FunDec (ret_type, name, params, loc) ->
  63. FunDec (ret_type, name, trav_all params, loc)
  64. | FunDef (export, ret_type, name, params, body, loc) ->
  65. FunDef (export, ret_type, name, trav_all params, trav body, loc)
  66. | GlobalDec (ctype, name, loc) ->
  67. GlobalDec (ctype, name, loc)
  68. | GlobalDef (export, ctype, name, Some init, loc) ->
  69. GlobalDef (export, ctype, name, Some (trav init), loc)
  70. | VarDec (ctype, name, Some init, loc) ->
  71. VarDec (ctype, name, Some (trav init), loc)
  72. | Assign (name, None, value, loc) ->
  73. Assign (name, None, trav value, loc)
  74. | Assign (name, Some dims, value, loc) ->
  75. Assign (name, Some (trav_all dims), trav value, loc)
  76. | Return (value, loc) ->
  77. Return (trav value, loc)
  78. | If (cond, body, loc) ->
  79. If (trav cond, trav body, loc)
  80. | IfElse (cond, true_body, false_body, loc) ->
  81. IfElse (trav cond, trav true_body, trav false_body, loc)
  82. | While (cond, body, loc) ->
  83. While (trav cond, trav body, loc)
  84. | DoWhile (cond, body, loc) ->
  85. DoWhile (trav cond, trav body, loc)
  86. | For (counter, start, stop, step, body, loc) ->
  87. For (counter, trav start, trav stop, trav step, trav body, loc)
  88. | Allocate (name, dims, dec, loc) ->
  89. Allocate (name, trav_all dims, dec, loc)
  90. | Expr value ->
  91. Expr (trav value)
  92. | Block (body) ->
  93. Block (trav_all body)
  94. | Monop (op, value, loc) ->
  95. Monop (op, trav value, loc)
  96. | Binop (op, left, right, loc) ->
  97. Binop (op, trav left, trav right, loc)
  98. | Cond (cond, true_expr, false_expr, loc) ->
  99. Cond (trav cond, trav true_expr, trav false_expr, loc)
  100. | TypeCast (ctype, value, loc) ->
  101. TypeCast (ctype, trav value, loc)
  102. | FunCall (name, args, loc) ->
  103. FunCall (name, trav_all args, loc)
  104. | Arg value ->
  105. Arg (trav value)
  106. | Deref (name, dims, loc) ->
  107. Deref (name, trav_all dims, loc)
  108. | ArrayInit (value, dims) ->
  109. ArrayInit (trav value, dims)
  110. | ArrayScalar value ->
  111. ArrayScalar (trav value)
  112. | Type (value, ctype) ->
  113. Type (trav value, ctype)
  114. | VarLet (assign, def, depth) ->
  115. VarLet (trav assign, def, depth)
  116. | VarUse (var, def, depth) ->
  117. VarUse (trav var, def, depth)
  118. | FunUse (funcall, def, depth) ->
  119. FunUse (trav funcall, def, depth)
  120. | DimDec node ->
  121. DimDec (trav node)
  122. | _ -> node
  123. (* Default tree transformation
  124. * (node -> node) -> node -> node *)
  125. let rec transform_all trav = function
  126. | [] -> []
  127. | node :: tail -> trav node :: (transform_all trav tail)
  128. let rec locof = function
  129. | Program (_, loc)
  130. | Param (_, _, loc)
  131. | Dim (_, loc)
  132. | FunDec (_, _, _, loc)
  133. | FunDef (_, _, _, _, _, loc)
  134. | GlobalDec (_, _, loc)
  135. | GlobalDef (_, _, _, _, loc)
  136. | VarDec (_, _, _, loc)
  137. | Assign (_, _, _, loc)
  138. | Return (_, loc)
  139. | If (_, _, loc)
  140. | IfElse (_, _, _, loc)
  141. | While (_, _, loc)
  142. | DoWhile (_, _, loc)
  143. | For (_, _, _, _, _, loc)
  144. | Allocate (_, _, _, loc)
  145. | BoolConst (_, loc)
  146. | IntConst (_, loc)
  147. | FloatConst (_, loc)
  148. | ArrayConst (_, loc)
  149. | Var (_, loc)
  150. | Deref (_, _, loc)
  151. | Monop (_, _, loc)
  152. | Binop (_, _, _, loc)
  153. | Cond (_, _, _, loc)
  154. | TypeCast (_, _, loc)
  155. | FunCall (_, _, loc) -> loc
  156. | ArrayInit (value, _)
  157. | ArrayScalar value
  158. | Expr value
  159. | VarLet (value, _, _)
  160. | VarUse (value, _, _)
  161. | FunUse (value, _, _)
  162. | Arg value
  163. | Type (value, _)
  164. | DimDec value -> locof value
  165. | _ -> noloc
  166. let prerr_loc (fname, ystart, yend, xstart, xend) =
  167. let file = open_in fname in
  168. (* skip lines until the first matched line *)
  169. for i = 1 to ystart - 1 do input_line file done;
  170. (* for each line in `loc`, print the source line with an underline *)
  171. for l = ystart to yend do
  172. let line = input_line file in
  173. let linewidth = String.length line in
  174. let left = if l = ystart then xstart else 1 in
  175. let right = if l = yend then xend else linewidth in
  176. if linewidth > 0 then (
  177. prerr_endline line;
  178. for i = 1 to left - 1 do prerr_char ' ' done;
  179. for i = left to right do prerr_char '^' done;
  180. prerr_endline "";
  181. )
  182. done;
  183. ()
  184. let prerr_loc_msg loc msg verbose =
  185. let (fname, ystart, yend, xstart, xend) = loc in
  186. let line_s = if yend != ystart
  187. then sprintf "lines %d-%d" ystart yend
  188. else sprintf "line %d" ystart
  189. in
  190. let char_s = if xend != xstart || yend != ystart
  191. then sprintf "characters %d-%d" xstart xend
  192. else sprintf "character %d" xstart
  193. in
  194. eprintf "File \"%s\", %s, %s:\n" fname line_s char_s;
  195. eprintf "%s\n" msg;
  196. if verbose >= 2 then prerr_loc loc;
  197. ()
  198. let ctypeof = function
  199. | VarDec (ctype, _, _, _)
  200. | Param (ctype, _, _)
  201. | FunDec (ctype, _, _, _)
  202. | FunDef (_, ctype, _, _, _, _)
  203. | GlobalDec (ctype, _, _)
  204. | GlobalDef (_, ctype, _, _, _)
  205. | TypeCast (ctype, _, _)
  206. | Type (_, ctype)
  207. -> ctype
  208. | Dim _ | DimDec _ -> Int
  209. | _ -> raise InvalidNode
  210. let block_body = function
  211. | Block nodes -> nodes
  212. | _ -> raise InvalidNode
  213. let rec list_size = function
  214. | [] -> 0
  215. | hd :: tl -> 1 + (list_size tl)
  216. let base_type = function
  217. | Array (ctype, _)
  218. | ctype -> ctype
  219. let array_depth = function
  220. | Array (_, dims) -> list_size dims
  221. | _ -> raise InvalidNode