context.ml 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. open Printf
  2. open Types
  3. open Util
  4. let rec add_depth depth node =
  5. match node with
  6. | GlobalDec (ArrayDims (ctype, dims), name, ann) ->
  7. (* XXX: traversal should traverse into Dim nodes *)
  8. let dims = List.map (add_depth depth) dims in
  9. GlobalDec (ArrayDims (ctype, dims), name, Depth depth :: ann)
  10. | Param (ArrayDims (ctype, dims), name, ann) ->
  11. let dims = List.map (add_depth depth) dims in
  12. Param (ArrayDims (ctype, dims), name, Depth depth :: ann)
  13. | GlobalDec _
  14. | GlobalDef _
  15. | Param _
  16. | Dim _
  17. | VarDec _
  18. | Var _
  19. | FunCall _
  20. | Assign _
  21. | For _
  22. | VarUse _
  23. | FunUse _
  24. | VarLet _ ->
  25. annotate (Depth depth) node |> traverse_unit (add_depth depth)
  26. | FunDec _ ->
  27. annotate (Depth depth) node
  28. | FunDef (export, ret_type, name, params, body, ann) ->
  29. let params = List.map (add_depth (depth + 1)) params in
  30. let body = add_depth (depth + 1) body in
  31. FunDef (export, ret_type, name, params, body, Depth depth :: ann)
  32. | _ ->
  33. traverse_unit (add_depth depth) node
  34. type identifier_type = Funcname | Varname
  35. let typename = function Varname -> "variable" | Funcname -> "function"
  36. let tblfind tbl name = try Some (Hashtbl.find tbl name) with Not_found -> None
  37. let add_to_scope scope name dec namety err =
  38. match tblfind scope name with
  39. | Some orig when depthof orig >= depthof dec ->
  40. err := NodeMsg (orig, "\rPreviously declared here:") ::
  41. NodeMsg (dec, sprintf "Error: cannot redeclare %s \"%s\""
  42. (typename namety) name) :: !err
  43. | Some _ ->
  44. Hashtbl.replace scope name dec
  45. | None ->
  46. Hashtbl.add scope name dec
  47. let check_in_scope scope name errnode namety err =
  48. match tblfind scope name with
  49. | Some dec -> dec
  50. | None ->
  51. let msg = sprintf "undefined %s \"%s\"" (typename namety) name in
  52. err := NodeMsg (errnode, msg) :: !err;
  53. DummyNode
  54. let prt_vars vars =
  55. let prt name dec = prerr_string (name ^ ", ") in
  56. Hashtbl.iter prt vars;
  57. prerr_endline "(end)"
  58. let analyse do_rename program =
  59. let err = ref [] in
  60. (* Add functions at the current depth to the function scope, do not traverse
  61. * into nested functions *)
  62. let rec collect_funs funs node =
  63. match node with
  64. | FunDec (_, name, _, _)
  65. | FunDef (_, _, name, _, _, _) ->
  66. (* TODO: don't copy function body to save memory *)
  67. add_to_scope funs name node Funcname err;
  68. node
  69. | _ -> traverse_unit (collect_funs funs) node
  70. in
  71. (* Traverse through statements in the current scope, checking and replacing
  72. * variable occurrences. Add newly declared variables to the variable scope
  73. * on-the-fly. *)
  74. let rec traverse scope node =
  75. let trav = traverse scope in
  76. let trav_dims = function
  77. | ArrayDims (ctype, dims) ->
  78. ArrayDims (ctype, List.map trav dims)
  79. | ctype -> ctype
  80. in
  81. let vars, funs, repl = scope in
  82. let check_rename node rename =
  83. let name = nameof node in
  84. let shadows_higher_scope =
  85. do_rename && (Hashtbl.mem vars name || Hashtbl.mem repl name)
  86. in
  87. (* Trigger duplication error and make sure following duplication errors
  88. * will refer to a non-generated variable name *)
  89. add_to_scope vars name node Varname err;
  90. if shadows_higher_scope then begin
  91. let newname = fresh_id name in
  92. Hashtbl.replace repl name newname;
  93. let newnode = rename newname in
  94. add_to_scope vars newname newnode Varname err;
  95. newnode
  96. end else
  97. node
  98. in
  99. let add_dims = function
  100. | ArrayDims (ctype, dims) ->
  101. let rec add = function
  102. | [] -> []
  103. | (Dim (name, ann) as dim) :: tl ->
  104. check_rename dim (fun name -> Dim (name, ann)) :: add tl
  105. | _ -> raise InvalidNode
  106. in
  107. ArrayDims (ctype, add dims)
  108. | ctype -> ctype
  109. in
  110. match node with
  111. | Program (decls, ann) ->
  112. Program (Block decls |> trav |> trav_funs scope |> block_body, ann)
  113. (* Do not traverse into external function declarations, since their
  114. * parameters must not be added to the namespace *)
  115. | FunDec _ | FunDef _ -> node
  116. | GlobalDef (export, ctype, name, init, ann) ->
  117. let node = GlobalDef (export, trav_dims ctype, name, optdo trav init, ann) in
  118. add_to_scope vars name node Varname err;
  119. node
  120. | VarDec (ctype, name, init, ann) ->
  121. let ctype = trav_dims ctype in
  122. let init = optdo trav init in
  123. let node = VarDec (ctype, name, init, ann) in
  124. check_rename node (fun name -> VarDec (ctype, name, init, ann))
  125. | GlobalDec (ArrayDims (ctype, dims), name, ann) ->
  126. let rec replace_dims i = function
  127. | [] -> []
  128. | Dim (dimname, ann) :: tl ->
  129. let newname = generate_array_dim name i in
  130. Hashtbl.add repl dimname newname;
  131. Dim (newname, ann) :: replace_dims (i + 1) tl
  132. | _ -> raise InvalidNode
  133. in
  134. let ctype = ArrayDims (ctype, replace_dims 0 dims) in
  135. let node = GlobalDec (add_dims ctype, name, ann) in
  136. add_to_scope vars name node Varname err;
  137. node
  138. | GlobalDec (ctype, name, ann) ->
  139. add_to_scope vars name node Varname err;
  140. node
  141. | Param (ctype, name, ann) ->
  142. let ctype = add_dims ctype in
  143. let node = Param (ctype, name, ann) in
  144. check_rename node (fun name -> Param (ctype, name, ann))
  145. | For (name, start, stop, step, body, ann) ->
  146. let start, stop, step = trav start, trav stop, trav step in
  147. (* For-loops are a special case: the loop counter defines a new scope
  148. * which is allowed to shadow existing local variables, and allows for
  149. * nested loops with the same induction variables. Replace the loop
  150. * counter with a fresh variable to enforce this behaviour, and avoid
  151. * having to replace variables during desigaring. *)
  152. (* FIXME: only create new variable if necessary *)
  153. let newname = fresh_id name in
  154. let node = For (newname, start, stop, step, body, ann) in
  155. Hashtbl.add vars name node;
  156. Hashtbl.add vars newname node;
  157. Hashtbl.add repl name newname;
  158. let node = For (newname, start, stop, step, trav body, ann) in
  159. Hashtbl.remove repl name;
  160. Hashtbl.remove vars newname;
  161. Hashtbl.remove vars name;
  162. node
  163. (* Perform renaming *)
  164. | Var (name, dims, ann) when Hashtbl.mem repl name ->
  165. trav (Var (Hashtbl.find repl name, dims, ann))
  166. | Assign (name, dims, value, ann) when Hashtbl.mem repl name ->
  167. trav (Assign (Hashtbl.find repl name, dims, value, ann) )
  168. (* Replace variables or function calls with use-nodes which contain the
  169. * entire declaration *)
  170. | Var (name, dims, ann) ->
  171. let dec = check_in_scope vars name node Varname err in
  172. VarUse (dec, optmap trav dims, ann)
  173. | FunCall (name, args, ann) ->
  174. let dec = check_in_scope funs name node Funcname err in
  175. FunUse (dec, List.map trav args, ann)
  176. (* Assign statements are replaced with VarLet nodes, which stores the
  177. * declaration of the assigned variable *)
  178. | Assign (name, dims, value, ann) ->
  179. begin
  180. match check_in_scope vars name node Varname err with
  181. | For _ ->
  182. err := NodeMsg (node, "cannot assign to induction variable") :: !err;
  183. node
  184. | dec ->
  185. VarLet (dec, optmap trav dims, trav value, ann)
  186. end
  187. (* Also support intermediary nodes because context analysis is re-run later
  188. * on to propagate new declaration properties *)
  189. | VarUse (dec, dims, ann) ->
  190. VarUse (Hashtbl.find vars (nameof dec), optmap trav dims, ann)
  191. | FunUse (dec, args, ann) ->
  192. FunUse (Hashtbl.find funs (nameof dec), List.map trav args, ann)
  193. | VarLet (dec, dims, value, ann) ->
  194. VarLet (Hashtbl.find vars (nameof dec), optmap trav dims, trav value, ann)
  195. | Allocate (dec, dims, ann) ->
  196. Allocate (Hashtbl.find vars (nameof dec), List.map trav dims, ann)
  197. | _ -> traverse_unit trav node
  198. and trav_funs scope = function
  199. (* Copy scope when entering a function body *)
  200. | FunDef (export, ret_type, name, params, body, ann) ->
  201. let vars, funs, repl = scope in
  202. let locfuns = Hashtbl.copy funs in
  203. let locscope = (Hashtbl.copy vars, locfuns, Hashtbl.copy repl) in
  204. let params = List.map (traverse locscope) params in
  205. let body =
  206. collect_funs locfuns body |> traverse locscope |> trav_funs locscope
  207. in
  208. FunDef (export, ret_type, name, params, body, ann)
  209. | node -> traverse_unit (trav_funs scope) node
  210. in
  211. let vars = Hashtbl.create 32 in
  212. let funs = Hashtbl.create 16 in
  213. let repl = Hashtbl.create 16 in
  214. add_depth 0 program |>
  215. collect_funs funs |>
  216. traverse (vars, funs, repl) |>
  217. quit_on_error (List.rev !err)
  218. let phase = function
  219. | Ast node -> Ast (analyse true node)
  220. | _ -> raise InvalidInput