util.ml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. open Printf
  2. open Lexing
  3. open Types
  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, ann) ->
  37. FunDef (export, ret_type, name, flatten params, Block (flatten body), ann)
  38. | If (cond, Block body, ann) ->
  39. If (cond, Block (flatten body), ann)
  40. | IfElse (cond, Block tbody, Block fbody, ann) ->
  41. IfElse (cond, Block (flatten tbody), Block (flatten fbody), ann)
  42. | While (cond, Block body, ann) ->
  43. While (cond, Block (flatten body), ann)
  44. | DoWhile (cond, Block body, ann) ->
  45. DoWhile (cond, Block (flatten body), ann)
  46. | For (counter, start, stop, step, Block body, ann) ->
  47. For (counter, start, stop, step, Block (flatten body), ann)
  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, ann) ->
  61. Program (flatten_blocks (trav_all decls), ann)
  62. | FunDec (ret_type, name, params, ann) ->
  63. FunDec (ret_type, name, trav_all params, ann)
  64. | FunDef (export, ret_type, name, params, body, ann) ->
  65. FunDef (export, ret_type, name, trav_all params, trav body, ann)
  66. | GlobalDec (ctype, name, ann) ->
  67. GlobalDec (ctype, name, ann)
  68. | GlobalDef (export, ctype, name, Some init, ann) ->
  69. GlobalDef (export, ctype, name, Some (trav init), ann)
  70. | VarDec (ctype, name, Some init, ann) ->
  71. VarDec (ctype, name, Some (trav init), ann)
  72. | Assign (name, None, value, ann) ->
  73. Assign (name, None, trav value, ann)
  74. | Assign (name, Some dims, value, ann) ->
  75. Assign (name, Some (trav_all dims), trav value, ann)
  76. | VarLet (dec, None, value, ann) ->
  77. VarLet (dec, None, trav value, ann)
  78. | VarLet (dec, Some dims, value, ann) ->
  79. VarLet (dec, Some (trav_all dims), trav value, ann)
  80. | Return (value, ann) ->
  81. Return (trav value, ann)
  82. | If (cond, body, ann) ->
  83. If (trav cond, trav body, ann)
  84. | IfElse (cond, true_body, false_body, ann) ->
  85. IfElse (trav cond, trav true_body, trav false_body, ann)
  86. | While (cond, body, ann) ->
  87. While (trav cond, trav body, ann)
  88. | DoWhile (cond, body, ann) ->
  89. DoWhile (trav cond, trav body, ann)
  90. | For (counter, start, stop, step, body, ann) ->
  91. For (counter, trav start, trav stop, trav step, trav body, ann)
  92. | Allocate (name, dims, dec, ann) ->
  93. Allocate (name, trav_all dims, dec, ann)
  94. | Expr value ->
  95. Expr (trav value)
  96. | Block (body) ->
  97. Block (trav_all body)
  98. | Monop (op, value, ann) ->
  99. Monop (op, trav value, ann)
  100. | Binop (op, left, right, ann) ->
  101. Binop (op, trav left, trav right, ann)
  102. | Cond (cond, true_expr, false_expr, ann) ->
  103. Cond (trav cond, trav true_expr, trav false_expr, ann)
  104. | TypeCast (ctype, value, ann) ->
  105. TypeCast (ctype, trav value, ann)
  106. | FunCall (name, args, ann) ->
  107. FunCall (name, trav_all args, ann)
  108. | Arg value ->
  109. Arg (trav value)
  110. | ArrayInit (value, dims) ->
  111. ArrayInit (trav value, dims)
  112. | ArrayScalar value ->
  113. ArrayScalar (trav value)
  114. | Var (dec, Some dims, ann) ->
  115. Var (dec, Some (trav_all dims), ann)
  116. | VarUse (dec, Some dims, ann) ->
  117. VarUse (dec, Some (trav_all dims), ann)
  118. | FunUse (dec, params, ann) ->
  119. FunUse (dec, trav_all params, ann)
  120. | VarDecs decs ->
  121. VarDecs (trav_all decs)
  122. | LocalFuns funs ->
  123. LocalFuns (trav_all funs)
  124. | _ -> node
  125. let annotate a = function
  126. | Program (decls, ann) ->
  127. Program (decls, a :: ann)
  128. | FunDec (ret_type, name, params, ann) ->
  129. FunDec (ret_type, name, params, a :: ann)
  130. | FunDef (export, ret_type, name, params, body, ann) ->
  131. FunDef (export, ret_type, name, params, body, a :: ann)
  132. | GlobalDec (ctype, name, ann) ->
  133. GlobalDec (ctype, name, a :: ann)
  134. | GlobalDef (export, ctype, name, init, ann) ->
  135. GlobalDef (export, ctype, name, init, a :: ann)
  136. | VarDec (ctype, name, init, ann) ->
  137. VarDec (ctype, name, init, a :: ann)
  138. | Assign (name, dims, value, ann) ->
  139. Assign (name, dims, value, a :: ann)
  140. | VarLet (dec, dims, value, ann) ->
  141. VarLet (dec, dims, value, a :: ann)
  142. | Return (value, ann) ->
  143. Return (value, a :: ann)
  144. | If (cond, body, ann) ->
  145. If (cond, body, a :: ann)
  146. | IfElse (cond, true_body, false_body, ann) ->
  147. IfElse (cond, true_body, false_body, a :: ann)
  148. | While (cond, body, ann) ->
  149. While (cond, body, a :: ann)
  150. | DoWhile (cond, body, ann) ->
  151. DoWhile (cond, body, a :: ann)
  152. | For (counter, start, stop, step, body, ann) ->
  153. For (counter, start, stop, step, body, a :: ann)
  154. | Allocate (name, dims, dec, ann) ->
  155. Allocate (name, dims, dec, a :: ann)
  156. | Monop (op, value, ann) ->
  157. Monop (op, value, a :: ann)
  158. | Binop (op, left, right, ann) ->
  159. Binop (op, left, right, a :: ann)
  160. | Cond (cond, true_expr, false_expr, ann) ->
  161. Cond (cond, true_expr, false_expr, a :: ann)
  162. | TypeCast (ctype, value, ann) ->
  163. TypeCast (ctype, value, a :: ann)
  164. | FunCall (name, args, ann) ->
  165. FunCall (name, args, a :: ann)
  166. | Arg value ->
  167. Arg (value)
  168. | Var (dec, dims, ann) ->
  169. Var (dec, dims, a :: ann)
  170. | VarUse (dec, dims, ann) ->
  171. VarUse (dec, dims, a :: ann)
  172. | FunUse (dec, params, ann) ->
  173. FunUse (dec, params, a :: ann)
  174. | Const (BoolVal value, ann) ->
  175. Const (BoolVal value, a :: ann)
  176. | Const (IntVal value, ann) ->
  177. Const (IntVal value, a :: ann)
  178. | Const (FloatVal value, ann) ->
  179. Const (FloatVal value, a :: ann)
  180. | ArrayConst (value, ann) ->
  181. ArrayConst (value, a :: ann)
  182. | Param (ctype, name, ann) ->
  183. Param (ctype, name, a :: ann)
  184. | Dim (name, ann) ->
  185. Dim (name, a :: ann)
  186. | _ -> raise InvalidNode
  187. let rec annof = function
  188. | Program (_, ann)
  189. | Param (_, _, ann)
  190. | Dim (_, ann)
  191. | FunDec (_, _, _, ann)
  192. | FunDef (_, _, _, _, _, ann)
  193. | GlobalDec (_, _, ann)
  194. | GlobalDef (_, _, _, _, ann)
  195. | VarDec (_, _, _, ann)
  196. | Assign (_, _, _, ann)
  197. | VarLet (_, _, _, ann)
  198. | Return (_, ann)
  199. | If (_, _, ann)
  200. | IfElse (_, _, _, ann)
  201. | While (_, _, ann)
  202. | DoWhile (_, _, ann)
  203. | For (_, _, _, _, _, ann)
  204. | Allocate (_, _, _, ann)
  205. | Const (BoolVal _, ann)
  206. | Const (IntVal _, ann)
  207. | Const (FloatVal _, ann)
  208. | ArrayConst (_, ann)
  209. | Var (_, _, ann)
  210. | Monop (_, _, ann)
  211. | Binop (_, _, _, ann)
  212. | Cond (_, _, _, ann)
  213. | TypeCast (_, _, ann)
  214. | VarUse (_, _, ann)
  215. | FunUse (_, _, ann)
  216. | FunCall (_, _, ann) -> ann
  217. | ArrayInit (value, _)
  218. | ArrayScalar value
  219. | Expr value
  220. | Arg value -> annof value
  221. | _ -> raise InvalidNode
  222. let locof node =
  223. let rec trav = function
  224. | [] -> noloc
  225. | Loc loc :: tl -> loc
  226. | _ :: tl -> trav tl
  227. in trav (annof node)
  228. let rec depthof node =
  229. let rec trav = function
  230. | [] ->
  231. prerr_string "cannot get depth for: ";
  232. prt_node node;
  233. raise InvalidNode
  234. | Depth depth :: tl -> depth
  235. | _ :: tl -> trav tl
  236. in trav (annof node)
  237. let rec indexof node =
  238. let rec trav = function
  239. | [] ->
  240. prerr_string "cannot get index for: ";
  241. prt_node node;
  242. raise InvalidNode
  243. | Index index :: tl -> index
  244. | _ :: tl -> trav tl
  245. in trav (annof node)
  246. let typeof = function
  247. (* Some nodes have their type as property *)
  248. | VarDec (ctype, _, _, _)
  249. | Param (ctype, _, _)
  250. | FunDec (ctype, _, _, _)
  251. | FunDef (_, ctype, _, _, _, _)
  252. | GlobalDec (ctype, _, _)
  253. | GlobalDef (_, ctype, _, _, _)
  254. | TypeCast (ctype, _, _)
  255. -> ctype
  256. (* Other nodes must be annotated during typechecking *)
  257. | node ->
  258. let rec trav = function
  259. | [] ->
  260. prerr_string "cannot get type for: ";
  261. prt_node node;
  262. raise InvalidNode
  263. | Type t :: tl -> t
  264. | _ :: tl -> trav tl
  265. in trav (annof node)
  266. let prerr_loc (fname, ystart, yend, xstart, xend) =
  267. let file = open_in fname in
  268. (* skip lines until the first matched line *)
  269. for i = 1 to ystart - 1 do let _ = input_line file in () done;
  270. (* for each line in `loc`, print the source line with an underline *)
  271. for l = ystart to yend do
  272. let line = input_line file in
  273. let linewidth = String.length line in
  274. let left = if l = ystart then xstart else 1 in
  275. let right = if l = yend then xend else linewidth in
  276. if linewidth > 0 then (
  277. prerr_endline line;
  278. for i = 1 to left - 1 do prerr_char ' ' done;
  279. for i = left to right do prerr_char '^' done;
  280. prerr_endline "";
  281. )
  282. done;
  283. ()
  284. let prerr_loc_msg loc msg verbose =
  285. let (fname, ystart, yend, xstart, xend) = loc in
  286. let line_s = if yend != ystart
  287. then sprintf "lines %d-%d" ystart yend
  288. else sprintf "line %d" ystart
  289. in
  290. let char_s = if xend != xstart || yend != ystart
  291. then sprintf "characters %d-%d" xstart xend
  292. else sprintf "character %d" xstart
  293. in
  294. eprintf "File \"%s\", %s, %s:\n" fname line_s char_s;
  295. eprintf "%s\n" msg;
  296. if verbose >= 2 then prerr_loc loc;
  297. ()
  298. let block_body = function
  299. | Block nodes -> nodes
  300. | _ -> raise InvalidNode
  301. let rec list_size = function
  302. | [] -> 0
  303. | hd :: tl -> 1 + (list_size tl)
  304. let basetypeof node = match typeof node with
  305. | Array (ctype, _)
  306. | ctype -> ctype
  307. let array_depth = function
  308. | Array (_, dims) -> list_size dims
  309. | _ -> raise InvalidNode
  310. let nameof = function
  311. | GlobalDec (_, name, _)
  312. | GlobalDef (_, _, name, _, _)
  313. | FunDec (_, name, _, _)
  314. | FunDef (_, _, name, _, _, _)
  315. | VarDec (_, name, _, _)
  316. | Param (_, name, _)
  317. | Dim (name, _) -> name
  318. | _ -> raise InvalidNode
  319. let optmap f = function
  320. | None -> None
  321. | Some lst -> Some (List.map f lst)
  322. let optmapl f = function
  323. | None -> []
  324. | Some lst -> List.map f lst
  325. let mapi f lst =
  326. let rec trav i = function
  327. | [] -> []
  328. | hd :: tl -> f i hd :: (trav (i + 1) tl)
  329. in trav 0 lst