extern.ml 4.2 KB

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