util.ml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. open Printf
  2. open Lexing
  3. open Types
  4. let rec repeat s n = if n < 1 then "" else s ^ (repeat s (n - 1))
  5. let expand n text = text ^ repeat " " (n - String.length text)
  6. (* Logging functions *)
  7. let hline = "-----------------------------------------------------------------"
  8. let prt_line = prerr_endline
  9. let prt_node node = prt_line (Stringify.node2str node)
  10. let log_plain_line verbosity line =
  11. if args.verbose >= verbosity then prt_line line
  12. let log_line verbosity line =
  13. log_plain_line verbosity (repeat " " 13 ^ line)
  14. let log_node verbosity node =
  15. if args.verbose >= verbosity then prt_node node
  16. (* Variable generation *)
  17. let var_counter = ref 0
  18. let fresh_var prefix =
  19. var_counter := !var_counter + 1;
  20. prefix ^ "$" ^ string_of_int !var_counter
  21. (* Constants are marked by a double $$ for recognition during constant
  22. * propagation *)
  23. let fresh_const prefix = fresh_var (prefix ^ "$")
  24. let loc_from_lexpos pstart pend =
  25. let (fname, ystart, yend, xstart, xend) = (
  26. pstart.pos_fname,
  27. pstart.pos_lnum,
  28. pend.pos_lnum,
  29. (pstart.pos_cnum - pstart.pos_bol + 1),
  30. (pend.pos_cnum - pend.pos_bol)
  31. ) in
  32. if ystart = yend && xend < xstart then
  33. (fname, ystart, yend, xstart, xstart)
  34. else
  35. (fname, ystart, yend, xstart, xend)
  36. let rec flatten_blocks lst =
  37. let flatten = flatten_blocks in
  38. let rec trav = function
  39. | Block body ->
  40. Block (flatten body)
  41. | FunDef (export, ret_type, name, params, body, ann) ->
  42. FunDef (export, ret_type, name, flatten params, trav body, ann)
  43. | If (cond, body, ann) ->
  44. If (cond, trav body, ann)
  45. | IfElse (cond, tbody, fbody, ann) ->
  46. IfElse (cond, trav tbody, trav fbody, ann)
  47. | While (cond, body, ann) ->
  48. While (cond, trav body, ann)
  49. | DoWhile (cond, body, ann) ->
  50. DoWhile (cond, trav body, ann)
  51. | For (counter, start, stop, step, body, ann) ->
  52. For (counter, start, stop, step, trav body, ann)
  53. | VarDecs decs ->
  54. VarDecs (flatten decs)
  55. | LocalFuns decs ->
  56. LocalFuns (flatten decs)
  57. | node -> node
  58. in
  59. match lst with
  60. | [] -> []
  61. | Block nodes :: tl -> flatten nodes @ (flatten tl)
  62. | DummyNode :: tl -> flatten tl
  63. | hd :: tl -> trav hd :: (flatten tl)
  64. (* Default tree transformation
  65. * (node -> node) -> node -> node *)
  66. let transform_children trav node =
  67. let trav_all nodes = List.map trav nodes in
  68. match node with
  69. | Program (decls, ann) ->
  70. Program (flatten_blocks (trav_all decls), ann)
  71. | FunDec (ret_type, name, params, ann) ->
  72. FunDec (ret_type, name, trav_all params, ann)
  73. | FunDef (export, ret_type, name, params, body, ann) ->
  74. FunDef (export, ret_type, name, trav_all params, trav body, ann)
  75. | GlobalDec (ctype, name, ann) ->
  76. GlobalDec (ctype, name, ann)
  77. | GlobalDef (export, ctype, name, Some init, ann) ->
  78. GlobalDef (export, ctype, name, Some (trav init), ann)
  79. | VarDecs decs ->
  80. VarDecs (trav_all decs)
  81. | LocalFuns funs ->
  82. LocalFuns (trav_all funs)
  83. | VarDec (ctype, name, Some init, ann) ->
  84. VarDec (ctype, name, Some (trav init), ann)
  85. | Assign (name, None, value, ann) ->
  86. Assign (name, None, trav value, ann)
  87. | Assign (name, Some dims, value, ann) ->
  88. Assign (name, Some (trav_all dims), trav value, ann)
  89. | VarLet (dec, None, value, ann) ->
  90. VarLet (dec, None, trav value, ann)
  91. | VarLet (dec, Some dims, value, ann) ->
  92. VarLet (dec, Some (trav_all dims), trav value, ann)
  93. | Return (value, ann) ->
  94. Return (trav value, ann)
  95. | If (cond, body, ann) ->
  96. If (trav cond, trav body, ann)
  97. | IfElse (cond, true_body, false_body, ann) ->
  98. IfElse (trav cond, trav true_body, trav false_body, ann)
  99. | While (cond, body, ann) ->
  100. While (trav cond, trav body, ann)
  101. | DoWhile (cond, body, ann) ->
  102. DoWhile (trav cond, trav body, ann)
  103. | For (counter, start, stop, step, body, ann) ->
  104. For (counter, trav start, trav stop, trav step, trav body, ann)
  105. | Allocate (dec, dims, ann) ->
  106. Allocate (dec, trav_all dims, ann)
  107. | Expr value ->
  108. Expr (trav value)
  109. | Block (body) ->
  110. Block (trav_all body)
  111. | Monop (op, value, ann) ->
  112. Monop (op, trav value, ann)
  113. | Binop (op, left, right, ann) ->
  114. Binop (op, trav left, trav right, ann)
  115. | Cond (cond, true_expr, false_expr, ann) ->
  116. Cond (trav cond, trav true_expr, trav false_expr, ann)
  117. | TypeCast (ctype, value, ann) ->
  118. TypeCast (ctype, trav value, ann)
  119. | FunCall (name, args, ann) ->
  120. FunCall (name, trav_all args, ann)
  121. | Arg value ->
  122. Arg (trav value)
  123. | ArrayInit (value, dims) ->
  124. ArrayInit (trav value, dims)
  125. | ArrayScalar value ->
  126. ArrayScalar (trav value)
  127. | Var (dec, Some dims, ann) ->
  128. Var (dec, Some (trav_all dims), ann)
  129. | VarUse (dec, Some dims, ann) ->
  130. VarUse (dec, Some (trav_all dims), ann)
  131. | FunUse (dec, params, ann) ->
  132. FunUse (dec, trav_all params, ann)
  133. | DimDec (name, Some init, ann) ->
  134. DimDec (name, Some (trav init), ann)
  135. | _ -> node
  136. let annotate a = function
  137. | Program (decls, ann) ->
  138. Program (decls, a :: ann)
  139. | FunDec (ret_type, name, params, ann) ->
  140. FunDec (ret_type, name, params, a :: ann)
  141. | FunDef (export, ret_type, name, params, body, ann) ->
  142. FunDef (export, ret_type, name, params, body, a :: ann)
  143. | GlobalDec (ctype, name, ann) ->
  144. GlobalDec (ctype, name, a :: ann)
  145. | GlobalDef (export, ctype, name, init, ann) ->
  146. GlobalDef (export, ctype, name, init, a :: ann)
  147. | VarDec (ctype, name, init, ann) ->
  148. VarDec (ctype, name, init, a :: ann)
  149. | Assign (name, dims, value, ann) ->
  150. Assign (name, dims, value, a :: ann)
  151. | VarLet (dec, dims, value, ann) ->
  152. VarLet (dec, dims, value, a :: ann)
  153. | Return (value, ann) ->
  154. Return (value, a :: ann)
  155. | If (cond, body, ann) ->
  156. If (cond, body, a :: ann)
  157. | IfElse (cond, true_body, false_body, ann) ->
  158. IfElse (cond, true_body, false_body, a :: ann)
  159. | While (cond, body, ann) ->
  160. While (cond, body, a :: ann)
  161. | DoWhile (cond, body, ann) ->
  162. DoWhile (cond, body, a :: ann)
  163. | For (counter, start, stop, step, body, ann) ->
  164. For (counter, start, stop, step, body, a :: ann)
  165. | Allocate (dec, dims, ann) ->
  166. Allocate (dec, dims, a :: ann)
  167. | Monop (op, value, ann) ->
  168. Monop (op, value, a :: ann)
  169. | Binop (op, left, right, ann) ->
  170. Binop (op, left, right, a :: ann)
  171. | Cond (cond, true_expr, false_expr, ann) ->
  172. Cond (cond, true_expr, false_expr, a :: ann)
  173. | TypeCast (ctype, value, ann) ->
  174. TypeCast (ctype, value, a :: ann)
  175. | FunCall (name, args, ann) ->
  176. FunCall (name, args, a :: ann)
  177. | Arg value ->
  178. Arg (value)
  179. | Var (dec, dims, ann) ->
  180. Var (dec, dims, a :: ann)
  181. | VarUse (dec, dims, ann) ->
  182. VarUse (dec, dims, a :: ann)
  183. | FunUse (dec, params, ann) ->
  184. FunUse (dec, params, a :: ann)
  185. | Const (BoolVal value, ann) ->
  186. Const (BoolVal value, a :: ann)
  187. | Const (IntVal value, ann) ->
  188. Const (IntVal value, a :: ann)
  189. | Const (FloatVal value, ann) ->
  190. Const (FloatVal value, a :: ann)
  191. | ArrayConst (value, ann) ->
  192. ArrayConst (value, a :: ann)
  193. | Param (ctype, name, ann) ->
  194. Param (ctype, name, a :: ann)
  195. | Dim (name, ann) ->
  196. Dim (name, a :: ann)
  197. | DimDec (name, init, ann) ->
  198. DimDec (name, init, a :: ann)
  199. | _ -> raise InvalidNode
  200. let rec annof = function
  201. | Program (_, ann)
  202. | Param (_, _, ann)
  203. | Dim (_, ann)
  204. | FunDec (_, _, _, ann)
  205. | FunDef (_, _, _, _, _, ann)
  206. | GlobalDec (_, _, ann)
  207. | GlobalDef (_, _, _, _, ann)
  208. | VarDec (_, _, _, ann)
  209. | Assign (_, _, _, ann)
  210. | VarLet (_, _, _, ann)
  211. | Return (_, ann)
  212. | If (_, _, ann)
  213. | IfElse (_, _, _, ann)
  214. | While (_, _, ann)
  215. | DoWhile (_, _, ann)
  216. | For (_, _, _, _, _, ann)
  217. | Allocate (_, _, ann)
  218. | Const (BoolVal _, ann)
  219. | Const (IntVal _, ann)
  220. | Const (FloatVal _, ann)
  221. | ArrayConst (_, ann)
  222. | Var (_, _, ann)
  223. | Monop (_, _, ann)
  224. | Binop (_, _, _, ann)
  225. | Cond (_, _, _, ann)
  226. | TypeCast (_, _, ann)
  227. | VarUse (_, _, ann)
  228. | FunUse (_, _, ann)
  229. | FunCall (_, _, ann)
  230. | DimDec (_, _, ann) -> ann
  231. | ArrayInit (value, _)
  232. | ArrayScalar value
  233. | Expr value
  234. | Arg value -> annof value
  235. | _ -> raise InvalidNode
  236. let locof node =
  237. let rec trav = function
  238. | [] -> noloc
  239. | Loc loc :: _ -> loc
  240. | _ :: tl -> trav tl
  241. in trav (annof node)
  242. let depthof node =
  243. let rec trav = function
  244. | [] ->
  245. prerr_string "cannot get depth for: ";
  246. prt_node node;
  247. raise InvalidNode
  248. | Depth depth :: _ -> depth
  249. | _ :: tl -> trav tl
  250. in trav (annof node)
  251. let indexof node =
  252. let rec trav = function
  253. | [] ->
  254. prerr_string "cannot get index for: ";
  255. prt_node node;
  256. raise InvalidNode
  257. | Index index :: _ -> index
  258. | _ :: tl -> trav tl
  259. in trav (annof node)
  260. let typeof = function
  261. (* Some nodes have their type as property *)
  262. | VarDec (ctype, _, _, _)
  263. | Param (ctype, _, _)
  264. | FunDec (ctype, _, _, _)
  265. | FunDef (_, ctype, _, _, _, _)
  266. | GlobalDec (ctype, _, _)
  267. | GlobalDef (_, ctype, _, _, _)
  268. | TypeCast (ctype, _, _)
  269. -> ctype
  270. (* Dim nodes are always type Int, and are copied by context analysis before
  271. * they are annotated with Type Int, so this match is necessary *)
  272. | DimDec _ | Dim _ -> Int
  273. (* Other nodes must be annotated during typechecking *)
  274. | node ->
  275. let rec trav = function
  276. | [] ->
  277. prerr_string "cannot get type for: ";
  278. prt_node node;
  279. raise InvalidNode
  280. | Type t :: _ -> t
  281. | _ :: tl -> trav tl
  282. in trav (annof node)
  283. let labelof node =
  284. let rec trav = function
  285. | [] ->
  286. prerr_string "cannot get label for: ";
  287. prt_node node;
  288. raise InvalidNode
  289. | LabelName label :: _ -> label
  290. | _ :: tl -> trav tl
  291. in trav (annof node)
  292. let const_type = function
  293. | BoolVal _ -> Bool
  294. | IntVal _ -> Int
  295. | FloatVal _ -> Float
  296. (*
  297. let get_line str n =
  298. let rec find_start from = function
  299. | n when n < 1 -> raise (Invalid_argument "n")
  300. | 1 -> from
  301. | n -> find_start ((String.index_from str from '\n') + 1) (n - 1)
  302. in
  303. let linestart = find_start 0 n in
  304. let len = String.length str in
  305. let lineend =
  306. try String.index_from str linestart '\n'
  307. with Not_found -> len
  308. in
  309. String.sub str linestart (lineend - linestart)
  310. *)
  311. let prerr_loc (fname, ystart, yend, xstart, xend) =
  312. let file = open_in fname in
  313. (* skip lines until the first matched line *)
  314. for i = 1 to ystart - 1 do let _ = input_line file in () done;
  315. (* for each line in `loc`, print the source line with an underline *)
  316. for l = ystart to yend do
  317. let line = input_line file in
  318. let linewidth = String.length line in
  319. let left = if l = ystart then xstart else 1 in
  320. let right = if l = yend then xend else linewidth in
  321. if linewidth > 0 then (
  322. prerr_endline line;
  323. for i = 1 to left - 1 do prerr_char ' ' done;
  324. for i = left to right do prerr_char '^' done;
  325. prerr_endline "";
  326. )
  327. done;
  328. ()
  329. let prerr_loc_msg loc msg =
  330. if args.verbose >= 1 then (
  331. let (fname, ystart, yend, xstart, xend) = loc in
  332. if loc != noloc then (
  333. let line_s = if yend != ystart
  334. then sprintf "lines %d-%d" ystart yend
  335. else sprintf "line %d" ystart
  336. in
  337. let char_s = if xend != xstart || yend != ystart
  338. then sprintf "characters %d-%d" xstart xend
  339. else sprintf "character %d" xstart
  340. in
  341. eprintf "File \"%s\", %s, %s:\n" fname line_s char_s;
  342. );
  343. eprintf "%s\n" msg;
  344. if args.verbose >= 1 && loc != noloc then
  345. try prerr_loc loc
  346. with Sys_error _ -> ()
  347. );
  348. ()
  349. let block_body = function
  350. | Block nodes -> nodes
  351. | _ -> raise InvalidNode
  352. let rec list_size = function
  353. | [] -> 0
  354. | hd :: tl -> 1 + (list_size tl)
  355. let basetypeof node = match typeof node with
  356. | Array (ctype, _)
  357. | FlatArray ctype
  358. | ctype -> ctype
  359. let array_depth = function
  360. | Array (_, dims) -> list_size dims
  361. | _ -> raise InvalidNode
  362. let nameof = function
  363. | GlobalDec (_, name, _)
  364. | GlobalDef (_, _, name, _, _)
  365. | FunDec (_, name, _, _)
  366. | FunDef (_, _, name, _, _, _)
  367. | VarDec (_, name, _, _)
  368. | Param (_, name, _)
  369. | Dim (name, _)
  370. | DimDec (name, _, _) -> name
  371. | _ -> raise InvalidNode
  372. let optmap f = function
  373. | None -> None
  374. | Some lst -> Some (List.map f lst)
  375. let optmapl f = function
  376. | None -> []
  377. | Some lst -> List.map f lst
  378. let mapi f lst =
  379. let rec trav i = function
  380. | [] -> []
  381. | hd :: tl -> f i hd :: (trav (i + 1) tl)
  382. in trav 0 lst
  383. let is_immediate_const const =
  384. if args.optimize then List.mem const immediate_consts else false
  385. let is_array node = match typeof node with Array _ -> true | _ -> false