From f0a067e93124e05327ad8888b9d5bbd4ebe2b85e Mon Sep 17 00:00:00 2001
From: ploc <ploc@garoche.net>
Date: Fri, 15 Mar 2019 14:14:18 -0700
Subject: [PATCH] Better production of trace files. By default traces are not
 produced. Requires the option -t to produce them

---
 include/io_frontend.c              | 25 +++-------
 include/io_frontend.h              | 14 +++---
 include/io_frontend.hpp            | 25 +++-------
 src/backends/C/c_backend_common.ml | 77 +++++++++++++++++++++++-------
 src/backends/C/c_backend_main.ml   | 77 +++++++++++++++++++++++-------
 src/plugins/scopes/scopes.ml       | 34 ++++++++-----
 6 files changed, 163 insertions(+), 89 deletions(-)

diff --git a/include/io_frontend.c b/include/io_frontend.c
index 8984b3ce..1ea3db2c 100644
--- a/include/io_frontend.c
+++ b/include/io_frontend.c
@@ -6,7 +6,7 @@
 int ISATTY;
 
 /* Standard Input procedures **************/
-_Bool _get_bool(FILE* file, char* n){
+_Bool _get_bool(char* n){
    char b[512];
    int r = 0;
    int s = 1;
@@ -22,11 +22,10 @@ _Bool _get_bool(FILE* file, char* n){
       if((c == '0') || (c == 'f') || (c == 'F')) r = 0;
       if((c == '1') || (c == 't') || (c == 'T')) r = 1;
    } while((s != 1) || (r == -1));
-   fprintf(file, "%i\n",r);
    return (_Bool)r;
 }
 
-int _get_int(FILE* file, char* n){
+int _get_int(char* n){
    char b[512];
    int r;
    int s = 1;
@@ -38,11 +37,10 @@ int _get_int(FILE* file, char* n){
       if(scanf("%s", b)==EOF) exit(0);
       s = sscanf(b, "%d", &r);
    } while(s != 1);
-   fprintf(file, "%d\n", r);
    return r;
 }
 
-double _get_double(FILE* file, char* n){
+double _get_double(char* n){
    char b[512];
    double r;
    int s = 1;
@@ -54,11 +52,10 @@ double _get_double(FILE* file, char* n){
       if(scanf("%s", b)==EOF) exit(0);
       s = sscanf(b, "%lf", &r);
    } while(s != 1);
-   fprintf(file, "%f\n", r);
    return r;
 }
 /* Standard Output procedures **************/
-void _put_bool(FILE* file, char* n, _Bool _V){
+void _put_bool(char* n, _Bool _V){
   if(ISATTY) {
     printf("%s = ", n);
   } else {
@@ -66,10 +63,8 @@ void _put_bool(FILE* file, char* n, _Bool _V){
   };
   printf("'%i' ", (_V)? 1 : 0);
   printf("\n");
-  fprintf(file, "%i\n", _V);
-  fflush(file);
 }
-void _put_int(FILE* file, char* n, int _V){
+void _put_int(char* n, int _V){
   if(ISATTY) {
     printf("%s = ", n);
   } else {
@@ -77,11 +72,9 @@ void _put_int(FILE* file, char* n, int _V){
   };
   printf("'%d' ", _V);
   printf("\n");
-  fprintf(file, "%d\n", _V);
-  fflush(file);
 }
 
-void _put_float(FILE* file, char* n, float _V, int PREC){
+void _put_float(char* n, float _V, int PREC){
   if(ISATTY) {
     printf("%s = ", n);
   } else {
@@ -89,11 +82,9 @@ void _put_float(FILE* file, char* n, float _V, int PREC){
   };
   printf("'%.*f' ", PREC, _V);
   printf("\n");
-  fprintf(file, "%.*f\n", PREC, _V);
-  fflush(file);
 }
 
-void _put_double(FILE* file, char* n, double _V, int PREC){
+void _put_double(char* n, double _V, int PREC){
   if(ISATTY) {
     printf("%s = ", n);
   } else {
@@ -101,6 +92,4 @@ void _put_double(FILE* file, char* n, double _V, int PREC){
   };
   printf("'%.*f' ", PREC, _V);
   printf("\n");
-  fprintf(file, "%.*f\n", PREC, _V);
-  fflush(file);
 }
diff --git a/include/io_frontend.h b/include/io_frontend.h
index 09084965..a7b75519 100644
--- a/include/io_frontend.h
+++ b/include/io_frontend.h
@@ -7,25 +7,25 @@ extern int ISATTY;
 /* Standard Input procedures **************/
 
 /*@ assigns *n; */
-extern _Bool _get_bool(FILE* file, char* n);
+extern _Bool _get_bool(char* n);
 
 /*@ assigns *n; */
-extern int _get_int(FILE* file, char* n);
+extern int _get_int(char* n);
 
 /*@ assigns *n; */
-extern double _get_double(FILE* file, char* n);
+extern double _get_double(char* n);
 
 /* Standard Output procedures **************/
 /*@ assigns \nothing; */
-extern void _put_bool(FILE* file, char* n, _Bool _V);
+extern void _put_bool(char* n, _Bool _V);
 
 /*@ assigns \nothing; */
-extern void _put_int(FILE* file, char* n, int _V);
+extern void _put_int(char* n, int _V);
 
 /*@ assigns \nothing; */
-extern void _put_float(FILE* file, char* n, float _V, int PREC);
+extern void _put_float(char* n, float _V, int PREC);
 
 /*@ assigns \nothing; */
-extern void _put_double(FILE* file, char* n, double _V, int PREC);
+extern void _put_double(char* n, double _V, int PREC);
 
 #endif
diff --git a/include/io_frontend.hpp b/include/io_frontend.hpp
index b02385e2..3c15747e 100644
--- a/include/io_frontend.hpp
+++ b/include/io_frontend.hpp
@@ -8,7 +8,7 @@
 int ISATTY;
 
 /* Standard Input procedures **************/
-bool _get_bool(FILE* file, char* n){
+bool _get_bool(char* n){
    char b[512];
    bool r = 0;
    int s = 1;
@@ -24,11 +24,10 @@ bool _get_bool(FILE* file, char* n){
       if((c == '0') || (c == 'f') || (c == 'F')) r = 0;
       if((c == '1') || (c == 't') || (c == 'T')) r = 1;
    } while((s != 1) || (r == -1));
-   fprintf(file, "%i\n",r);
    return r;
 }
 
-int _get_int(FILE* file, char* n){
+int _get_int(char* n){
    char b[512];
    int r;
    int s = 1;
@@ -40,11 +39,10 @@ int _get_int(FILE* file, char* n){
       if(scanf("%s", b)==EOF) exit(0);
       s = sscanf(b, "%d", &r);
    } while(s != 1);
-   fprintf(file, "%d\n", r);
    return r;
 }
 
-double _get_double(FILE* file, char* n){
+double _get_double(char* n){
    char b[512];
    double r;
    int s = 1;
@@ -56,32 +54,27 @@ double _get_double(FILE* file, char* n){
       if(scanf("%s", b)==EOF) exit(0);
       s = sscanf(b, "%lf", &r);
    } while(s != 1);
-   fprintf(file, "%f\n", r);
    return r;
 }
 /* Standard Output procedures **************/
-void _put_bool(FILE* file, char* n, bool _V){
+void _put_bool(char* n, bool _V){
   if(ISATTY) {
     printf("%s = ", n);
   } else {
     printf("'%s': ", n);
   };
   printf("'%i' ", (_V)? 1 : 0);
-  printf("\n");
-  fprintf(file, "%i\n", _V);
 }
-void _put_int(FILE* file, char* n, int _V){
+void _put_int(char* n, int _V){
   if(ISATTY) {
     printf("%s = ", n);
   } else {
     printf("'%s': ", n);
   };
   printf("'%d' ", _V);
-  printf("\n");
-  fprintf(file, "%d\n", _V);
 }
 
-void _put_float(FILE* file, char* n, float _V, int PREC){
+void _put_float(char* n, float _V, int PREC){
   if(ISATTY) {
     printf("%s = ", n);
   } else {
@@ -89,11 +82,9 @@ void _put_float(FILE* file, char* n, float _V, int PREC){
   };
   printf("'%.*f' ", PREC, _V);
   printf("\n");
-  fprintf(file, "%.*f\n", PREC, _V);
-  fflush(file);
 }
 
-void _put_double(FILE* file, char* n, double _V, int PREC){
+void _put_double(char* n, double _V, int PREC){
   if(ISATTY) {
     printf("%s = ", n);
   } else {
@@ -101,8 +92,6 @@ void _put_double(FILE* file, char* n, double _V, int PREC){
   };
   printf("'%.*f' ", PREC, _V);
   printf("\n");
-  fprintf(file, "%.*f\n", PREC, _V);
-  fflush(file);
 }
 
 
diff --git a/src/backends/C/c_backend_common.ml b/src/backends/C/c_backend_common.ml
index 11e823e1..fbeade98 100644
--- a/src/backends/C/c_backend_common.ml
+++ b/src/backends/C/c_backend_common.ml
@@ -705,34 +705,57 @@ let pp_instance_call m self fmt i (inputs: Machine_code_types.value_t list) (out
 
   (*** Common functions for main ***)
 
+let pp_print_file file_suffix fmt typ arg =
+  fprintf fmt "@[<v 2>if (traces) {@ ";
+  fprintf fmt "fprintf(f_%s, \"%%%s\\n\", %s);@ " file_suffix typ arg;
+  fprintf fmt "fflush(f_%s);@ " file_suffix;
+  fprintf fmt "@]}@ "
+  
 let print_put_var fmt file_suffix name var_type var_id =
+  let pp_file = pp_print_file ("out" ^ file_suffix) in
   let unclocked_t = Types.unclock_type var_type in
-  if Types.is_int_type unclocked_t then
-    fprintf fmt "_put_int(f_out%s, \"%s\", %s)" file_suffix name var_id
-  else if Types.is_bool_type unclocked_t then
-    fprintf fmt "_put_bool(f_out%s, \"%s\", %s)" file_suffix name var_id
+  if Types.is_int_type unclocked_t then (
+    fprintf fmt "_put_int(\"%s\", %s);@ " name var_id;
+    pp_file fmt "d" var_id
+  )
+  else if Types.is_bool_type unclocked_t then (
+    fprintf fmt "_put_bool(\"%s\", %s);@ " name var_id;
+    pp_file fmt "i" var_id
+  )
   else if Types.is_real_type unclocked_t then
-    if !Options.mpfr then
-      fprintf fmt "_put_double(f_out%s, \"%s\", mpfr_get_d(%s, %s), %i)" file_suffix name var_id (Mpfr.mpfr_rnd ()) !Options.print_prec_double
-    else
-      fprintf fmt "_put_double(f_out%s, \"%s\", %s, %i)" file_suffix name var_id !Options.print_prec_double
+    let _ =
+      if !Options.mpfr then
+        fprintf fmt "_put_double(\"%s\", mpfr_get_d(%s, %s), %i);@ " name var_id (Mpfr.mpfr_rnd ()) !Options.print_prec_double
+      else
+        fprintf fmt "_put_double(\"%s\", %s, %i);@ " name var_id !Options.print_prec_double
+    in
+    pp_file fmt ".*f" ((string_of_int !Options.print_prec_double) ^ ", " ^ var_id)
   else
     (Format.eprintf "Impossible to print the _put_xx for type %a@.@?" Types.print_ty var_type; assert false)
 
       
 let print_get_inputs fmt m =
   let pi fmt (id, v', v) =
-
+    let pp_file = pp_print_file ("in" ^ (string_of_int id)) in
     let unclocked_t = Types.unclock_type v.var_type in
-    if Types.is_int_type unclocked_t then
-      fprintf fmt "%s = _get_int(f_in%i, \"%s\")" v.var_id id v'.var_id
-    else if Types.is_bool_type unclocked_t then
-      fprintf fmt "%s = _get_bool(f_in%i, \"%s\")" v.var_id id v'.var_id
+    if Types.is_int_type unclocked_t then (
+      fprintf fmt "%s = _get_int(\"%s\");@ " v.var_id v'.var_id;
+      pp_file fmt "d" v.var_id
+    )
+    else if Types.is_bool_type unclocked_t then (
+      fprintf fmt "%s = _get_bool(\"%s\");@ " v.var_id v'.var_id;
+      pp_file fmt "i" v.var_id
+    )
     else if Types.is_real_type unclocked_t then
-      if !Options.mpfr then
-	fprintf fmt "mpfr_set_d(%s, _get_double(f_in%i, \"%s\"), %i)" v.var_id id v'.var_id (Mpfr.mpfr_prec ())
-      else
-	fprintf fmt "%s = _get_double(f_in%i, \"%s\")" v.var_id id v'.var_id
+        if !Options.mpfr then (
+	  fprintf fmt "double %s_tmp = _get_double(\"%s\");@ " v.var_id v'.var_id;
+          pp_file fmt "f" (v.var_id ^ "_tmp");
+          fprintf fmt "mpfr_set_d(%s, %s_tmp, %i);" v.var_id v.var_id (Mpfr.mpfr_prec ())
+        )
+        else (
+	  fprintf fmt "%s = _get_double(\"%s\");@ " v.var_id v'.var_id;
+          pp_file fmt "f" v.var_id
+        )
     else
       begin
 	Global.main_node := !Options.main_node;
@@ -743,10 +766,28 @@ let print_get_inputs fmt m =
       end
   in
   Utils.List.iteri2 (fun idx v' v ->
-    fprintf fmt "@ %a;" pi ((idx+1), v', v);
+    fprintf fmt "@ %a" pi ((idx+1), v', v);
   ) m.mname.node_inputs m.mstep.step_inputs
 
 
+let pp_file_decl fmt inout idx =
+  let idx = idx + 1 in (* we start from 1: in1, in2, ... *)
+  fprintf fmt "FILE *f_%s%i;@ " inout idx 
+
+let pp_file_open fmt inout idx =
+  let idx = idx + 1 in (* we start from 1: in1, in2, ... *)
+  fprintf fmt "const char* cst_char_suffix_%s%i = \"_simu.%s%i\";@ " inout idx inout idx;
+  fprintf fmt "size_t l%s%i = strlen(dir) + strlen(prefix) + strlen(cst_char_suffix_%s%i);@ " inout idx inout idx;
+  fprintf fmt "char* f_%s%i_name = malloc((l%s%i+2) * sizeof(char));@ " inout idx inout idx;
+  fprintf fmt "strcpy (f_%s%i_name, dir);@ " inout idx;
+  fprintf fmt "strcat(f_%s%i_name, \"/\");@ " inout idx;
+  fprintf fmt "strcat(f_%s%i_name, prefix);@ " inout idx;
+  fprintf fmt "strcat(f_%s%i_name, cst_char_suffix_%s%i);@ " inout idx inout idx;
+  fprintf fmt "f_%s%i = fopen(f_%s%i_name, \"w\");@ " inout idx inout idx;
+  fprintf fmt "free(f_%s%i_name);@ " inout idx;
+  "f_" ^ inout ^ (string_of_int idx)
+
+
 (* Local Variables: *)
 (* compile-command:"make -C ../../.." *)
 (* End: *)
diff --git a/src/backends/C/c_backend_main.ml b/src/backends/C/c_backend_main.ml
index 90f3862e..6d8bf847 100644
--- a/src/backends/C/c_backend_main.ml
+++ b/src/backends/C/c_backend_main.ml
@@ -40,24 +40,25 @@ let print_put_outputs fmt m =
   in
   List.iteri2 (fun idx v' v -> fprintf fmt "@ %a;" po ((idx+1), v', v)) m.mname.node_outputs m.mstep.step_outputs
 
-let print_main_inout_declaration basename fmt m =
-  let mname = m.mname.node_id in
-  (* TODO: find a proper way to shorthen long names. This causes segfault in the binary when trying to fprintf in them *)
-  let mname = if String.length mname > 50 then string_of_int (Hashtbl.hash mname) else mname in
+  
+let print_main_inout_declaration m fmt =
   fprintf fmt "/* Declaration of inputs/outputs variables */@ ";
-  List.iteri 
-    (fun idx v ->
+  List.iteri (fun idx v ->
       fprintf fmt "%a;@ " (pp_c_type v.var_id) v.var_type;
-      fprintf fmt "FILE *f_in%i;@ " (idx+1); (* we start from 1: in1, in2, ... *)
-      fprintf fmt "f_in%i = fopen(\"%s_%s_simu.in%i\", \"w\");@ " (idx+1) basename mname (idx+1);
+      ignore (pp_file_decl fmt "in" idx) 
     ) m.mstep.step_inputs;
-  List.iteri 
-    (fun idx v ->
+  List.iteri (fun idx v ->
       fprintf fmt "%a;@ " (pp_c_type v.var_id) v.var_type;
-      fprintf fmt "FILE *f_out%i;@ " (idx+1); (* we start from 1: in1, in2, ... *)
-      fprintf fmt "f_out%i = fopen(\"%s_%s_simu.out%i\", \"w\");@ " (idx+1) basename mname (idx+1);
-    ) m.mstep.step_outputs
-
+      ignore (pp_file_decl fmt "out" idx)
+    ) m.mstep.step_outputs;
+  fprintf fmt "@[<v 2>if (traces) {@ ";
+  List.iteri (fun idx _ ->
+      ignore (pp_file_open fmt "in" idx) 
+    ) m.mstep.step_inputs;
+  List.iteri (fun idx _ ->
+      ignore (pp_file_open fmt "out" idx)
+    ) m.mstep.step_outputs;
+  fprintf fmt "@]}@ "
 
   
 let print_main_memory_allocation mname main_mem fmt m =
@@ -122,22 +123,66 @@ let print_main_loop mname main_mem fmt m =
     fprintf fmt "@ /* Infinite loop */@ ";
     fprintf fmt "@[<v 2>while(1){@ ";
     fprintf fmt  "fflush(stdout);@ ";
+    fprintf fmt "@[<v 2>if (traces) {@ ";
     List.iteri (fun idx _ -> fprintf fmt "fflush(f_in%i);@ " (idx+1)) m.mstep.step_inputs;
     List.iteri (fun idx _ -> fprintf fmt "fflush(f_out%i);@ " (idx+1)) m.mstep.step_outputs;
+    fprintf fmt "@]}@ ";
     fprintf fmt "%a@ %t%a"
       print_get_inputs m
       (fun fmt -> pp_main_call mname main_mem fmt m input_values m.mstep.step_outputs)
       print_put_outputs m
   end
 
+let print_usage fmt =
+  fprintf fmt "@[<v 2>void usage(char *argv[]) {@ ";
+  fprintf fmt "printf(\"Usage: %%s\\n\", argv[0]);@ ";
+  fprintf fmt "printf(\" -t: produce trace files for input/output flows\\n\");@ ";
+  fprintf fmt "printf(\" -d<dir>: directory containing traces (default: _traces)\\n\");@ ";
+  fprintf fmt "printf(\" -p<prefix>: prefix_simu.scope<id> (default: file_node)\\n\");@ ";
+  fprintf fmt "exit (8);@ ";
+  fprintf fmt "@]}@ "
+
+let print_options fmt name =
+  fprintf fmt "int traces = 0;@ ";
+  fprintf fmt "char* prefix = \"%s\";@ " name;
+  fprintf fmt "char* dir = \".\";@ ";
+  fprintf fmt "@[<v 2>while ((argc > 1) && (argv[1][0] == '-')) {@ ";
+  fprintf fmt "@[<v 2>switch (argv[1][1]) {@ ";
+  fprintf fmt "@[<v 2>case 't':@ ";
+  fprintf fmt "traces = 1;@ ";
+  fprintf fmt "break;@ ";
+  fprintf fmt "@]@ ";
+  fprintf fmt "@[<v 2>case 'd':@ ";
+  fprintf fmt "dir = &argv[1][2];@ ";
+  fprintf fmt "break;@ ";
+  fprintf fmt "@]@ ";
+  fprintf fmt "@[<v 2>case 'p':@ ";
+  fprintf fmt "prefix = &argv[1][2];@ ";
+  fprintf fmt "break;@ ";
+  fprintf fmt "@]@ ";
+  fprintf fmt "@[<v 2>default:@ ";
+  fprintf fmt "printf(\"Wrong Argument: %%s\\n\", argv[1]);@ ";
+  fprintf fmt "usage(argv);@ ";
+  fprintf fmt "@]@ ";
+  fprintf fmt "@]}@ ";
+  fprintf fmt "++argv;@ ";
+  fprintf fmt "--argc;@ ";
+  fprintf fmt "@]}@ "
+  
 let print_main_code fmt basename m =
   let mname = m.mname.node_id in
+  (* TODO: find a proper way to shorthen long names. This causes segfault in the binary when trying to fprintf in them *)
+  let mname = if String.length mname > 50 then string_of_int (Hashtbl.hash mname) else mname in
+  
   let main_mem =
     if (!Options.static_mem && !Options.main_node <> "")
     then "&main_mem"
     else "main_mem" in
+  print_usage fmt;
+  
   fprintf fmt "@[<v 2>int main (int argc, char *argv[]) {@ ";
-  print_main_inout_declaration basename fmt m;
+  print_options fmt (basename ^ "_" ^ mname);
+  print_main_inout_declaration m fmt;
   Plugins.c_backend_main_loop_body_prefix basename mname fmt ();
   print_main_memory_allocation mname main_mem fmt m;
   if !Options.mpfr then
@@ -158,7 +203,7 @@ let print_main_code fmt basename m =
   fprintf fmt "@]@ }@."       
 
 let print_main_header fmt =
-  fprintf fmt (if !Options.cpp then "#include <stdio.h>@.#include <unistd.h>@.#include \"%s/io_frontend.hpp\"@." else "#include <stdio.h>@.#include <unistd.h>@.#include \"%s/io_frontend.h\"@.")
+  fprintf fmt (if !Options.cpp then "#include <stdio.h>@.#include <unistd.h>@.#include \"%s/io_frontend.hpp\"@." else "#include <stdio.h>@.#include <unistd.h>@.#include <string.h>@.#include \"%s/io_frontend.h\"@.")
     (Options_management.core_dependency "io_frontend")
 
 let print_main_c main_fmt main_machine basename prog machines _ (*dependencies*) =
diff --git a/src/plugins/scopes/scopes.ml b/src/plugins/scopes/scopes.ml
index a51196d9..2846911c 100644
--- a/src/plugins/scopes/scopes.ml
+++ b/src/plugins/scopes/scopes.ml
@@ -175,7 +175,7 @@ par ex main_mem->n8->n9->_reg.flow
 let extract_scopes_defs scopes =
   let rec scope_path_name (path, flow) accu = 
     match path with 
-    | [] -> accu ^ "_reg." ^ (scope_var_name flow.var_id), flow.var_type
+    | [] -> accu ^ "_reg." ^ (scope_var_name flow.var_id), flow
     | (_, _, Some instance_id)::tl -> scope_path_name (tl, flow) ( accu ^ instance_id ^ "->" ) 
     | _ -> assert false
   in
@@ -189,22 +189,32 @@ let extract_scopes_defs scopes =
   
 let pp_scopes_files basename mname fmt scopes =
   let scopes_vars = extract_scopes_defs scopes in
-  List.iteri (fun idx _ (* (id, (var, typ)) *) ->
-      Format.fprintf fmt "FILE *f_out_scopes_%i;@ " (idx+1);
-      (* we start from 1: in1, in2, ... *)
-    Format.fprintf fmt
-      "f_out_scopes_%i = fopen(\"%s_%s_simu.scope%i\", \"w\");@ "
-      (idx+1) basename mname (idx+1);
-  ) scopes_vars
-
+  List.iteri (fun idx  _(*(id, (var_path, var))*)  ->
+      C_backend_common.pp_file_decl fmt "out_scopes" idx)
+    scopes_vars;
+  Format.fprintf fmt "@[<v 2>if (traces) {@ ";
+  List.iteri (fun idx  (id, (var_path, var))  ->
+      let file = C_backend_common.pp_file_open fmt "out_scopes" idx in
+      Format.fprintf fmt
+        "fprintf(%s, \"# scope: %s\\n\");@ "
+        file id;
+      Format.fprintf fmt
+        "fprintf(%s, \"# node: %s\\n\");@ "
+        file (Utils.desome var.var_parent_nodeid);
+      Format.fprintf fmt
+        "fprintf(%s, \"# variable: %s\\n\");@ "
+        file var.var_id
+    ) scopes_vars;
+  Format.fprintf fmt "@]}@ "
+    
   
 let pp_scopes fmt scopes = 
   let scopes_vars = extract_scopes_defs scopes in
-  List.iteri (fun idx (id, (var, typ)) ->
+  List.iteri (fun idx (id, (var_path, var)) ->
     Format.fprintf fmt "@ %t;" 
       (fun fmt -> C_backend_common.print_put_var fmt
-                    ("_scopes_" ^ string_of_int (idx+1))
-                    id (*var*) typ var)
+                    ("_scopes" ^ string_of_int (idx+1))
+                    id (*var*) var.var_type var_path)
   ) scopes_vars
 
 (**********************************************************************)
-- 
GitLab