extern_vars.ml 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. open Types
  2. open Util
  3. let create_param ctype name =
  4. let param = Param (ctype, name, [Depth 1]) in
  5. let value = VarUse (param, None, [Type ctype; Depth 1]) in
  6. (param, value)
  7. let call node args depth = match node with
  8. | FunDec (ctype, name, _, _) as dec ->
  9. FunUse (dec, args, [Type ctype; Depth depth])
  10. | _ -> raise InvalidNode
  11. let process globals = function
  12. | GlobalDef (true, Array (ctype, dims), name, None, ann) as dec ->
  13. (* Getters for array variable: crate getter for given index Note that
  14. * getters and setters for dimensions are automatically generated,
  15. * because they have been put into new global variables during the
  16. * desugarin phase *)
  17. let (param, index) = create_param Int (fresh_var "index") in
  18. let var = VarUse (dec, Some [index], [Type ctype; Depth 1]) in
  19. let body = Block [Return (var, [])] in
  20. let getter = FunDef (true, ctype, name ^ "$get", [param], body, []) in
  21. (* Setters for array variable: create setter for given index *)
  22. let (param1, index) = create_param Int (fresh_var "index") in
  23. let (param2, value) = create_param ctype (fresh_var "value") in
  24. let body = Block [VarLet (dec, Some [index], value, [])] in
  25. let setter = FunDef (true, Void, name ^ "$set", [param1; param2], body, []) in
  26. [getter; setter]
  27. | GlobalDef (true, ctype, name, None, ann) as dec ->
  28. (* Getter for basic variable type: return the variable *)
  29. let var = VarUse (dec, None, [Type ctype; Depth 1]) in
  30. let body = [Return (var, [])] in
  31. let getter = FunDef (true, ctype, name ^ "$get", [], Block body, []) in
  32. (* Setter for basic variable type: assign the variable *)
  33. let (param, value) = create_param ctype (fresh_var "value") in
  34. let body = [VarLet (dec, None, value, [])] in
  35. let setter = FunDef (true, Void, name ^ "$set", [param], Block body, []) in
  36. [getter; setter]
  37. | GlobalDec (Array (ctype, dims), name, ann) ->
  38. (* Getters for external array variable: create getter for a given index *)
  39. (* Setters for external array variable:
  40. * - define setter for a given index
  41. * - define setter for each dimension*)
  42. let (param, _) = create_param Int "index" in
  43. let rec process_dims i = function
  44. | [] -> []
  45. | Dim (oldname, _) :: tl ->
  46. let dimname = name ^ "$" ^ string_of_int i in
  47. let getter = FunDec (Void, dimname ^ "$get", [], []) in
  48. let (param, _) = create_param ctype "value" in
  49. let setter = FunDec (Void, dimname ^ "$set", [param], []) in
  50. Hashtbl.add globals oldname (call getter, call setter);
  51. getter :: setter :: (process_dims (i + 1) tl)
  52. | _ -> raise InvalidNode
  53. in
  54. let getter = FunDec (ctype, name ^ "$get", [param], []) in
  55. let (param1, index) = create_param Int "index" in
  56. let (param2, value) = create_param ctype "value" in
  57. let setter = FunDec (Void, name ^ "$set", [param1; param2], []) in
  58. Hashtbl.add globals name (call getter, call setter);
  59. getter :: setter :: (process_dims 1 dims)
  60. (* Getter for basic variable type: return the variable *)
  61. | GlobalDec (ctype, name, ann) ->
  62. let getter = FunDec (ctype, name ^ "$get", [], []) in
  63. let (param, _) = create_param ctype "value" in
  64. let setter = FunDec (Void, name ^ "$set", [param], []) in
  65. Hashtbl.add globals name (call getter, call setter);
  66. [getter; setter]
  67. | _ -> raise InvalidNode
  68. let rec create_funcs globals = function
  69. | Program (decls, ann) ->
  70. let decls = List.map (create_funcs globals) decls in
  71. Program (flatten_blocks (List.map (create_funcs globals) decls), ann)
  72. | GlobalDef (true, ctype, name, None, ann) as node ->
  73. Block (GlobalDef (false, ctype, name, None, ann) ::
  74. (process globals node))
  75. | GlobalDec (ctype, name, ann) as node ->
  76. Block (process globals node)
  77. | node -> transform_children (create_funcs globals) node
  78. let rec replace_vars scope depth = function
  79. | (VarDec (_, name, _, _) as node)
  80. | (Param (_, name, _) as node)
  81. when Hashtbl.mem scope name ->
  82. Hashtbl.remove scope name;
  83. node
  84. | FunDef (export, ret_type, name, params, body, ann) ->
  85. let local_scope = Hashtbl.copy scope in
  86. let trav = replace_vars local_scope (depth + 1) in
  87. let params = List.map trav params in
  88. FunDef (export, ret_type, name, params, trav body, ann)
  89. | VarUse (dec, None, _) when Hashtbl.mem scope (nameof dec) ->
  90. let (get, _) = Hashtbl.find scope (nameof dec) in
  91. get [] depth
  92. | VarLet (dec, dims, value, _) when Hashtbl.mem scope (nameof dec) ->
  93. let dims = optmapl (replace_vars scope depth) dims in
  94. let (_, set) = Hashtbl.find scope (nameof dec) in
  95. Expr (set (dims @ [replace_vars scope depth value]) depth)
  96. | node -> transform_children (replace_vars scope depth) node
  97. let rec phase input =
  98. log_line 2 "- Create getters and setters for extern variables";
  99. match input with
  100. | Types node ->
  101. let globals = Hashtbl.create 20 in
  102. let node = create_funcs globals node in
  103. Types (replace_vars globals 0 node)
  104. | _ -> raise (InvalidInput "extern vars")