util.ml 6.6 KB

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