|
|
@@ -12,12 +12,12 @@ let call node args depth =
|
|
|
FunUse (dec, args, [Type ctype; Depth depth])
|
|
|
| _ -> raise InvalidNode
|
|
|
|
|
|
-let process globals = function
|
|
|
- | GlobalDef (true, Array ctype, name, None, ann) as dec ->
|
|
|
- (* Getters for array variable: crate getter for given index Note that
|
|
|
+let create_getset globals = function
|
|
|
+ | GlobalDef (true, ArrayDims (ctype, _), name, None, ann) as dec ->
|
|
|
+ (* Getters for array variable: create getter for given index Note that
|
|
|
* getters and setters for dimensions are automatically generated,
|
|
|
* because they have been put into new global variables during the
|
|
|
- * desugarin phase *)
|
|
|
+ * desugaring phase *)
|
|
|
let (param, index) = create_param Int (fresh_var "index") in
|
|
|
let var = VarUse (dec, Some [index], [Type ctype; Depth 1]) in
|
|
|
let body = Block [Return (var, [])] in
|
|
|
@@ -44,9 +44,26 @@ let process globals = function
|
|
|
|
|
|
[getter; setter]
|
|
|
|
|
|
- | GlobalDec (Array ctype, name, ann) ->
|
|
|
- (* Getters for external array variable: create getter and setter for a
|
|
|
- * given index *)
|
|
|
+ | GlobalDec (ArrayDims (ctype, dims), name, ann) ->
|
|
|
+ (* External array variable: create getter and setter for a given index. Now
|
|
|
+ * we also need to generate functions for dimensions since they are NOT
|
|
|
+ * added as new variables during desugaring. *)
|
|
|
+ let rec add_dims i = function
|
|
|
+ | [] -> []
|
|
|
+ | Dim (dimname, ann) :: tl ->
|
|
|
+ let newname = name ^ "$" ^ string_of_int i in
|
|
|
+
|
|
|
+ let getter = FunDec (ctype, newname ^ "$get", [], []) in
|
|
|
+
|
|
|
+ let (param, _) = create_param ctype "value" in
|
|
|
+ let setter = FunDec (Void, newname ^ "$set", [param], []) in
|
|
|
+
|
|
|
+ Hashtbl.add globals dimname (call getter, call setter);
|
|
|
+ getter :: setter :: (add_dims (i + 1) tl)
|
|
|
+ | _ -> raise InvalidNode
|
|
|
+ in
|
|
|
+ let dimfuncs = add_dims 1 dims in
|
|
|
+
|
|
|
let (param, _) = create_param Int "index" in
|
|
|
let getter = FunDec (ctype, name ^ "$get", [param], []) in
|
|
|
|
|
|
@@ -55,7 +72,7 @@ let process globals = function
|
|
|
let setter = FunDec (Void, name ^ "$set", [param1; param2], []) in
|
|
|
|
|
|
Hashtbl.add globals name (call getter, call setter);
|
|
|
- [getter; setter]
|
|
|
+ getter :: setter :: dimfuncs
|
|
|
|
|
|
(* Getter for basic variable type: return the variable *)
|
|
|
| GlobalDec (ctype, name, ann) ->
|
|
|
@@ -69,25 +86,30 @@ let process globals = function
|
|
|
|
|
|
| _ -> raise InvalidNode
|
|
|
|
|
|
+(* Create getter/setter functions for exported/imported variables *)
|
|
|
let rec create_funcs globals = function
|
|
|
| Program (decls, ann) ->
|
|
|
let decls = List.map (create_funcs globals) decls in
|
|
|
Program (flatten_blocks (List.map (create_funcs globals) decls), ann)
|
|
|
|
|
|
| GlobalDef (true, ctype, name, None, ann) as node ->
|
|
|
- Block (GlobalDef (false, ctype, name, None, ann) :: (process globals node))
|
|
|
+ Block (GlobalDef (false, ctype, name, None, ann) ::
|
|
|
+ (create_getset globals node))
|
|
|
|
|
|
| GlobalDec (ctype, name, ann) as node ->
|
|
|
- Block (process globals node)
|
|
|
+ Block (create_getset globals node)
|
|
|
|
|
|
| node -> transform_children (create_funcs globals) node
|
|
|
|
|
|
+(* Replace uses for imported/exported variabels with getter/setter functions *)
|
|
|
let rec replace_vars scope depth = function
|
|
|
+ (* Variable names may be redefined in function scopes *)
|
|
|
| (VarDec (_, name, _, _) as node)
|
|
|
| (Param (_, name, _) as node) when Hashtbl.mem scope name ->
|
|
|
Hashtbl.remove scope name;
|
|
|
node
|
|
|
|
|
|
+ (* Copy scope when traversing into function,, and restore afterwards *)
|
|
|
| FunDef (export, ret_type, name, params, body, ann) ->
|
|
|
let local_scope = Hashtbl.copy scope in
|
|
|
let trav = replace_vars local_scope (depth + 1) in
|