util.ml 6.3 KB

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