Przeglądaj źródła

Generated variable names now have leading underscores instead of dollar signs

Taddeus Kroes 12 lat temu
rodzic
commit
b530c36dde
12 zmienionych plików z 170 dodań i 138 usunięć
  1. 4 7
      phases/constprop.ml
  2. 30 29
      phases/constprop.mli
  3. 1 3
      phases/context.ml
  4. 6 6
      phases/desug.ml
  5. 21 21
      phases/desug.mli
  6. 20 15
      phases/extern.ml
  7. 35 32
      phases/extern.mli
  8. 3 2
      phases/index.ml
  9. 1 3
      phases/unroll.ml
  10. 10 10
      phases/unroll.mli
  11. 23 4
      util.ml
  12. 16 6
      util.mli

+ 4 - 7
phases/constprop.ml

@@ -1,6 +1,6 @@
 (**
- * The compiler sometimes generates variables of the form foo$$1, to make sure
- * that expressions are only executed once. In many cases, this leads to
+ * The compiler sometimes generates variables of the form __foo_1__, to make
+ * sure that expressions are only executed once. In many cases, this leads to
  * over-complex constructions, for example when converting for-loops to
  * while-loops. We use the knowledge of these variables being constant by
  * propagation the constant values to their occurrences, and then apply
@@ -18,9 +18,6 @@
 open Types
 open Util
 
-let is_const_name name =
-  Str.string_match (Str.regexp "^.+\\$\\$[0-9]+$") name 0
-
 let is_const = function
   | Const _
   | VarUse (_, None, _) -> true
@@ -128,7 +125,7 @@ let rec propagate consts node =
   match node with
 
   (* Constant assignments are added to constants table *)
-  | Assign (name, None, value, ann) when is_const_name name ->
+  | Assign (name, None, value, ann) when is_const_id name ->
     let value = propagate value in
     if is_const value then begin
       Hashtbl.add consts name value;
@@ -136,7 +133,7 @@ let rec propagate consts node =
     end else
       Assign (name, None, value, ann)
 
-  | VarLet (dec, None, value, ann) when is_const_name (nameof dec) ->
+  | VarLet (dec, None, value, ann) when is_const_id (nameof dec) ->
     let value = propagate value in
     if is_const value then begin
       Hashtbl.add consts (nameof dec) value;

+ 30 - 29
phases/constprop.mli

@@ -1,7 +1,7 @@
 (** Rudimentary constant propagation and constant folding on generated
     variables. *)
 
-(** The compiler sometimes generates variables of the form [foo$$1], to make
+(** The compiler sometimes generates variables of the form [__foo_1__], to make
     sure that expressions are only executed once. In many cases, this leads to
     over-complex constructions with more variable definitions den necessary, for
     example when converting for-loops to while-loops. We use the knowledge of
@@ -32,44 +32,45 @@
 After desugaring and array dimension reduction this becomes:
 
 {v void foo() \{
-    int i$4$5;
-    int stop$$6;
-    int step$$7;
-    int arr$dim$$1;
-    int arr$dim$$2;
-    int const$$1;
-    int const$$2;
-    int const$$3;
+    int ____i_6_7;
+    int __arr_1_2__;
+    int __arr_2_1__;
+    int __const_3__;
+    int __const_4__;
+    int __const_5__;
     int[] arr;
-    arr$dim$$1 = 2;
-    arr$dim$$2 = 2;
-    const$$1 = 1;
-    const$$2 = 2;
-    const$$3 = 3;
-    arr = __allocate((arr$dim$$1 * arr$dim$$2));
-    arr[((0 * arr$dim$$2) + 0)] = const$$1;
-    arr[((0 * arr$dim$$2) + 1)] = const$$2;
-    i$4$5 = 0;
-    stop$$6 = arr$dim$$2;
-    step$$7 = 1;
-    while (((step$$7 > 0) ? (i$4$5 < stop$$6) : (i$4$5 > stop$$6))) \{
-        arr[((1 * arr$dim$$2) + i$4$5)] = const$$3;
-        i$4$5 = (i$4$5 + step$$7);
+    int __stop_8__;
+    int __step_9__;
+    __arr_1_2__ = 2;
+    __arr_2_1__ = 2;
+    __const_3__ = 1;
+    __const_4__ = 2;
+    __const_5__ = 3;
+    arr := <allocate>((__arr_1_2__ * __arr_2_1__));
+    arr[((0 * __arr_2_1__) + 0)] = __const_3__;
+    arr[((0 * __arr_2_1__) + 1)] = __const_4__;
+    ____i_6_7 = 0;
+    __stop_8__ = __arr_2_1__;
+    __step_9__ = 1;
+    while (((__step_9__ > 0) ? (____i_6_7 < __stop_8__) : (____i_6_7 > __stop_8__))) \{
+        arr[((1 * __arr_2_1__) + ____i_6_7)] = __const_5__;
+        ____i_6_7 = (____i_6_7 + __step_9__);
     \}
+
 \} v}
 
 Constant propagation reduces this to:
 
 {v void foo() \{
-    int i$4$5;
+    int ____i_6_7;
     int[] arr;
-    arr = __allocate(4);
+    arr := <allocate>(4);
     arr[0] = 1;
     arr[1] = 2;
-    i$4$5 = 0;
-    while ((i$4$5 < 2)) \{
-        arr[(2 + i$4$5)] = 3;
-        i$4$5 = (i$4$5 + 1);
+    ____i_6_7 = 0;
+    while ((____i_6_7 < 2)) \{
+        arr[(2 + ____i_6_7)] = 3;
+        ____i_6_7 = (____i_6_7 + 1);
     \}
 \} v}
     *)

+ 1 - 3
phases/context.ml

@@ -9,8 +9,6 @@ let type2str = function Funcname _ -> "function" | Varname _ -> "variable"
 let mapfind name tbl =
   if Hashtbl.mem tbl name then Some (Hashtbl.find tbl name) else None
 
-let is_generated name = String.contains name '$'
-
 let check_in_scope name errnode scope =
   let (vars, funs) = scope in
   let (name, tbl, other_map, desired_type) = match name with
@@ -39,7 +37,7 @@ let add_to_scope name dec depth (vars, funs) =
     (* For generated variables, don't gove an error, since the error variable
      * is a derived array dimension of a redefined array, which will yield an
      * error later on *)
-    if is_generated name then
+    if is_generated_id name then
       Hashtbl.replace tbl name (dec, depth, name_type)
     else
       let msg = sprintf "Error: cannot redeclare %s \"%s\"" name_type name in

+ 6 - 6
phases/desug.ml

@@ -57,7 +57,7 @@ let rec array_dims node =
     (* Names for VarDec dimensions must be unique to avoid weid errors when
      * during context analysis, when an array variable is redeclared within the
      * same scope *)
-    let make_dimname i _ = fresh_const (name ^ "$" ^ string_of_int (i + 1)) in
+    let make_dimname i _ = fresh_const (name ^ "_" ^ string_of_int (i + 1)) in
 
     let make_dec value name = VarDec (Int, name, Some value, []) in
     let (decs, dims) = make_dims make_dimname values make_dec in
@@ -65,9 +65,9 @@ let rec array_dims node =
 
   | GlobalDef (export, ArrayDims (ctype, values), name, init, ann) ->
     (* For global decs, the name must be derived from the array base name, but
-     * not constant (no $$in the name) since the variable must exist for
-     * exporting (and not pruned during constant propagation) *)
-    let make_dimname i _ = name ^ "$" ^ string_of_int (i + 1) in
+     * not constant (no trailing __) since the variable must exist for exporting
+     * (and not pruned during constant propagation) *)
+    let make_dimname i _ = generate_id name (i + 1) in
 
     let make_dec value name = GlobalDef (export, Int, name, Some value, []) in
     let (decs, dims) = make_dims make_dimname values make_dec in
@@ -200,7 +200,7 @@ let for_to_while node =
 
     (* Transform for-loops to while-loops *)
     | For (counter, start, stop, step, body, ann) ->
-      let _i = fresh_var counter in
+      let _i = fresh_id counter in
       let _stop = fresh_const "stop" in
       let _step = fresh_const "step" in
       (*new_vars := !new_vars @ [_i; _stop; _step];*)
@@ -284,7 +284,7 @@ let rec array_init = function
       | [] ->
         array_init (Assign (name, Some indices, value, ann))
       | dim :: rest ->
-        let counter = fresh_var "i" in
+        let counter = fresh_id "i" in
         let start = Const (IntVal 0, []) in
         let step = Const (IntVal 1, []) in
         let body = Block [add_loop (indices @ [Var (counter, None, [])]) rest] in

+ 21 - 21
phases/desug.mli

@@ -96,19 +96,19 @@ void foo() \{
     and constant propagation):
 {v ...
 void foo() \{
-  int a$dim$$2;
-  int const$$1;
-  int const$$2;
-  int[2, a$dim$$2] a;
-  a$dim$$2 = two();
-  const$$1 = two();
-  const$$2 = two();
-  a = __allocate(2 * a$dim$$2);
-  a[0] = 1;
-  a[1] = const$$1;
-  a[a$dim$$2)] = 1;
-  a[a$dim$$2) + 1] = const$$2;
-  printInt(a[(1 * a$dim$$2) + 1]);
+    int _a_2_1_;
+    int _const_4_;
+    int _const_6_;
+    int[] a;
+    _a_2_1_ = two();
+    _const_4_ = two();
+    _const_6_ = two();
+    a := <allocate>((2 * _a_2_1_));
+    a[0] = 1;
+    a[1] = _const_4_;
+    a[_a_2_1_] = 1;
+    a[(_a_2_1_ + 1)] = _const_6_;
+    printInt(a[(_a_2_1_ + 1)]);
 \} v}
 
 
@@ -121,17 +121,17 @@ void foo() \{
 
     is transformed into:
 
-{v i$1 = <start>;
-step$2 = <step>;
-stop$3 = <stop>;
-while ((step$2 > 0) ? (i$1 < stop$3) : (i$1 > stop$3)) \{
+{v _i_1 = <start>;
+_step_2 = <step>;
+_stop_3 = <stop>;
+while ((_step_2 > 0) ? (_i_1 < _stop_3) : (_i_1 > _stop_3)) \{
     <body>
-    i$1 = i$1 + step$2;
+    _i_1 = _i_1 + _step_2;
 \} v}
 
-    Here, [i$1], [step$2] and [stop$3] are fresh variables. Definitions of these
-    new variables are added to the scope of the current function. Every
-    occurrence of [i] in [<body>] is replaced with the fresh variable [i$1],
+    Here, [_i_1], [_step_2] and [_stop_3] are fresh variables. Definitions of
+    these new variables are added to the scope of the current function. Every
+    occurrence of [i] in [<body>] is replaced with the fresh variable [_i_1],
     this prevents problems with nested for-loops that use the same induction
     variable.
     *)

+ 20 - 15
phases/extern.ml

@@ -12,22 +12,27 @@ let call node args depth =
     FunUse (dec, args, [Type ctype; Depth depth])
   | _ -> raise InvalidNode
 
+let generate_name name postfix = "_" ^ name ^ "_" ^ postfix
+let getname name = generate_name name "get"
+let setname name = generate_name name "set"
+
 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
      * desugaring phase *)
-    let (param, index) = create_param Int (fresh_var "index") in
+    let (param, index) = create_param Int (fresh_id "index") in
     let var = VarUse (dec, Some [index], [Type ctype; Depth 1]) in
     let body = Block [Return (var, [])] in
-    let getter = FunDef (true, ctype, name ^ "$get", [param], body, []) in
+    let getter = FunDef (true, ctype, getname name, [param], body, []) in
 
     (* Setters for array variable: create setter for given index *)
-    let (param1, index) = create_param Int (fresh_var "index") in
-    let (param2, value) = create_param ctype (fresh_var "value") in
+    let (param1, index) = create_param Int (fresh_id "index") in
+    let (param2, value) = create_param ctype (fresh_id "value") in
+    let params = [param1; param2] in
     let body = Block [VarLet (dec, Some [index], value, [])] in
-    let setter = FunDef (true, Void, name ^ "$set", [param1; param2], body, []) in
+    let setter = FunDef (true, Void, setname name, params, body, []) in
 
     [getter; setter]
 
@@ -35,12 +40,12 @@ let create_getset globals = function
     (* Getter for basic variable type: return the variable *)
     let var = VarUse (dec, None, [Type ctype; Depth 1]) in
     let body = [Return (var, [])] in
-    let getter = FunDef (true, ctype, name ^ "$get", [], Block body, []) in
+    let getter = FunDef (true, ctype, getname name, [], Block body, []) in
 
     (* Setter for basic variable type: assign the variable *)
-    let (param, value) = create_param ctype (fresh_var "value") in
+    let (param, value) = create_param ctype (fresh_id "value") in
     let body = [VarLet (dec, None, value, [])] in
-    let setter = FunDef (true, Void, name ^ "$set", [param], Block body, []) in
+    let setter = FunDef (true, Void, setname name, [param], Block body, []) in
 
     [getter; setter]
 
@@ -51,12 +56,12 @@ let create_getset globals = function
     let rec add_dims i = function
       | [] -> []
       | Dim (dimname, ann) :: tl ->
-        let newname = name ^ "$" ^ string_of_int i in
+        let newname = generate_id name i in
 
-        let getter = FunDec (ctype, newname ^ "$get", [], []) in
+        let getter = FunDec (ctype, getname newname, [], []) in
 
         let (param, _) = create_param ctype "value" in
-        let setter = FunDec (Void, newname ^ "$set", [param], []) in
+        let setter = FunDec (Void, setname newname, [param], []) in
 
         Hashtbl.add globals dimname (call getter, call setter);
         getter :: setter :: (add_dims (i + 1) tl)
@@ -65,21 +70,21 @@ let create_getset globals = function
     let dimfuncs = add_dims 1 dims in
 
     let (param, _) = create_param Int "index" in
-    let getter = FunDec (ctype, name ^ "$get", [param], []) in
+    let getter = FunDec (ctype, getname name, [param], []) in
 
     let (param1, index) = create_param Int "index" in
     let (param2, value) = create_param ctype "value" in
-    let setter = FunDec (Void, name ^ "$set", [param1; param2], []) in
+    let setter = FunDec (Void, setname name, [param1; param2], []) in
 
     Hashtbl.add globals name (call getter, call setter);
     getter :: setter :: dimfuncs
 
   (* Getter for basic variable type: return the variable *)
   | GlobalDec (ctype, name, ann) ->
-    let getter = FunDec (ctype, name ^ "$get", [], []) in
+    let getter = FunDec (ctype, getname name, [], []) in
 
     let (param, _) = create_param ctype "value" in
-    let setter = FunDec (Void, name ^ "$set", [param], []) in
+    let setter = FunDec (Void, setname name, [param], []) in
 
     Hashtbl.add globals name (call getter, call setter);
     [getter; setter]

+ 35 - 32
phases/extern.mli

@@ -16,43 +16,44 @@
 
 
 {v export int foo;
-export int [n] bar; v}
+export int[2] bar; v}
 
     becomes:
 
 {v int foo;
-int bar$1;
-int [bar$1] bar;
 
-export void foo$set(int new_value) \{
-    foo = new_value;
+export int _foo_get() \{
+    return foo;
 \}
 
-export int foo$get() \{
-    return foo;
+export void _foo_set(int _value_1) \{
+    foo = _value_1;
 \}
 
-export void bar$set(int index, int new_value) \{
-    bar[index] = new_value;
+int _bar_1 = 2;
+
+export int __bar_1_get() \{
+    return _bar_1;
 \}
 
-export int bar$get(int index) \{
-    return bar[index];
+export void __bar_1_set(int _value_2) \{
+    _bar_1 = _value_2;
 \}
 
-export void bar$1$set(int new_value) \{
-    bar$1 = new_value;
+int[_bar_1] bar;
+
+export int _bar_get(int _index_3) \{
+    return bar[_index_3];
 \}
 
-export int bar$1$get() \{
-    return bar$1;
+export void _bar_set(int _index_4, int _value_5) \{
+    bar[_index_4] = _value_5;
 \} v}
 
-
-Note that array dimensions are renamed during the desugaring phase, [n] is
-renamed to [bar$1] because it is the first dimension of bar. After that, it is
-handled as a regulary exported integer for which setter and getter functions are
-created.
+Note that array dimensions are renamed during the desugaring phase, [2] is
+moved to a variable [_bar_1] because it is the first dimension of [bar]. After
+that, it is handled as a regulary exported integer for which setter and getter
+functions are created implicitly.
 
 In the second step, external variable declarations are replaced by function
 declarations for the corresponding getter and setter functions. For example:
@@ -63,16 +64,17 @@ extern int[n] bar; v}
 
     becomes:
 
-{v extern void foo$set(int new_value);
-extern int foo$get();
-extern void bar$set(int index, int new_value);
-extern int bar$get(int index);
-extern int bar$1$get(int new_value);
-extern int bar$1$set(int index, int new_value); v}
+{v extern int _foo_get();
+extern void _foo_set(int value);
+extern int _bar_get(int index);
+extern void _bar_set(int index, int value);
+extern int __bar_1_get();
+extern void __bar_1_set(int value); v}
 
-Again, note that [n] is renamed to [bar$1]. This is, however, not done during
-the desugaring phase, since the dimensions are not prevented from being
-evaluated more than once (See {!Desug} for an explanation about this).
+Again, note that [n] is renamed to [_bar_1]. Also note that this is not already
+done during the desugaring phase for external arrays, since the dimensions are
+not prevented from being evaluated more than once (See {!Desug} for an
+explanation about this).
 
 In the third step, all occurrences of external variables are replaced by
 function call to a getter or setter function. For example:
@@ -85,10 +87,11 @@ export void main() \{
 
     becomes:
 
-{v export void main() \{
-    bar$set(foo$get(), bar$1$get());
+{v ...
+export void main() \{
+    _bar_set(_foo_get(), __bar_1_get());
 \} v}
 
     *)
-(** Main phase function, called by \{!Main\}. *)
+(** Main phase function, called by {!Main}. *)
 val phase : Main.phase_func

+ 3 - 2
phases/index.ml

@@ -19,9 +19,10 @@ let tag_index program =
       annotate (Index index) (transform_children trav node)
 
     | FunDef (export, rtype, name, params, body, ann) ->
-      (* label name for local function is "<parent_label>$<name>" *)
+      (* label name for local function is "__<parent_label>_<name>" *)
       let callstack = name :: callstack in
-      let label = String.concat "$" (List.rev callstack) in
+      let prefix = if List.length callstack > 1 then "__" else "" in
+      let label = prefix ^ String.concat "_" (List.rev callstack) in
 
       let stacklen = ref 0 in
       let trav = tag stacklen callstack in

+ 1 - 3
phases/unroll.ml

@@ -5,8 +5,6 @@ open Util
 let may_be_unrolled i_values body =
   List.length i_values * List.length body <= 25
 
-let is_generated s = Str.string_match (Str.regexp "^.+\\$[0-9]+$") s 0
-
 let rec range i j step =
   if i >= j then [] else i :: (range (i + step) j step)
 
@@ -56,7 +54,7 @@ let rec unroll_body counters = function
       _),
       Block body,
     _) as loop) :: tl
-    when is_generated i & comp = i ->
+    when is_generated_id i & comp = i ->
       begin
         match get_body_step i [] body with
         | Some (step, rest) ->

+ 10 - 10
phases/unroll.mli

@@ -20,23 +20,23 @@
     After desugaring and constant propagation, this has been transformed into:
 
 {v void foo() \{
-    int i$2$4;
-    int i$3$7;
+    int _i_6;
+    int _i_9;
     int[] arr;
     arr := <allocate>(6);
-    i$2$4 = 0;
-    while ((i$2$4 < 2)) \{
-        i$3$7 = 0;
-        while ((i$3$7 < 3)) \{
-            arr[((i$2$4 * 3) + i$3$7)] = 1;
-            i$3$7 = (i$3$7 + 1);
+    _i_6 = 0;
+    while ((_i_6 < 2)) \{
+        _i_9 = 0;
+        while ((_i_9 < 3)) \{
+            arr[((_i_6 * 3) + _i_9)] = 1;
+            _i_9 = (_i_9 + 1);
         \}
-        i$2$4 = (i$2$4 + 1);
+        _i_6 = (_i_6 + 1);
     \}
 \} v}
 
     Now, the loops are unrolled (first the inner loop, then the outer loop) and
-    constant folding is applied to [arr[((i$2$4 * 3) + i$3$7)]] in each
+    constant folding is applied to [arr[((_i_6 * 3) + _i_9)]] in each
     iteration:
 
 {v void foo() \{

+ 23 - 4
util.ml

@@ -25,14 +25,33 @@ let log_node verbosity node =
   if Globals.args.verbose >= verbosity then prt_node node
 
 (* Variable generation *)
+
+let generate_id id num =
+  "_" ^ id ^ "_" ^ string_of_int num
+
 let var_counter = ref 0
-let fresh_var prefix =
+
+let fresh_id base =
+  (* For generated variables, just replace the counter *)
+  let base =
+    if string_match (regexp "^_\\(.+\\)_[0-9]+_?$") base 0 then
+      matched_group 1 base
+    else
+      base
+  in
   var_counter := !var_counter + 1;
-  prefix ^ "$" ^ string_of_int !var_counter
+  generate_id base !var_counter
 
-(* Constants are marked by a double $$ for recognition during constant
+(* Constants are marked by a leading _ for recognition during constant
  * propagation *)
-let fresh_const prefix = fresh_var (prefix ^ "$")
+let fresh_const id = fresh_id id ^ "_"
+
+let is_generated_id id = String.length id >= 1 & id.[0] = '_'
+
+let is_const_id id =
+  String.length id >= 2
+  & id.[0] = '_'
+  & id.[String.length id - 1] = '_'
 
 let loc_from_lexpos pstart pend =
   let (fname, ystart, yend, xstart, xend) = begin

+ 16 - 6
util.mli

@@ -2,16 +2,26 @@
 
 (** {2 Generating variables} *)
 
-(** Generate a new variable from a given prefix, e.g. ["foo"] becomes ["foo$1"].
-    Uses an [int] reference defined in the implementation file as a counter to
-    assert uniqueness of the generated variable. *)
-val fresh_var : string -> string
+(** Generate a new identifier from a given base, e.g. ["foo"] becomes
+    ["_foo_1"]. Uses an [int] reference defined in the implementation file as a
+    counter to assert uniqueness of the generated variable. *)
+val fresh_id : string -> string
 
 (** Generate a new constant (a variable that is known to be assigned only once
-    in total) from a given prefix, e.g. ["foo"] becomes ["foo$$1"]. Uses the
-    same counter as {!fresh_var}. *)
+    in total) from a given id, e.g. ["foo"] becomes ["_foo_1_"]. Uses the same
+    counter as {!fresh_id}. *)
 val fresh_const : string -> string
 
+(** Check if an identifier is generated by the compiler. *)
+val is_generated_id : string -> bool
+
+(** Check if an identifier is a constant generated by the compiler. *)
+val is_const_id : string -> bool
+
+(** Generate an identifier from a base and a number. E.g., [generate_id "foo"
+    1] returns ["_foo_1"]*)
+val generate_id : string -> int -> string
+
 (** {2 AST traversal} *)
 
 (** Default transformation traversal for AST nodes of arbitrary constructor.