From 6d0951a578bd7e8baab9e357b18039e5fb2e26eb Mon Sep 17 00:00:00 2001
From: Paul Iannetta <paul.iannetta@ens-lyon.fr>
Date: Wed, 15 Jul 2015 14:41:20 +0200
Subject: [PATCH] some pretty-printing fixes

---
 generator/js_of_ast.ml | 201 +++++++++++++++++++++++++++++------------
 1 file changed, 145 insertions(+), 56 deletions(-)

diff --git a/generator/js_of_ast.ml b/generator/js_of_ast.ml
index dc5aff1..cedf30a 100644
--- a/generator/js_of_ast.ml
+++ b/generator/js_of_ast.ml
@@ -29,9 +29,84 @@ let print_type_tbl () =
     | x :: xs -> (Printf.sprintf {|"%s", |} x) ^ print_str_list xs
   in Hashtbl.iter (fun cstr elems -> Printf.printf ({|%s -> [%s]|} ^^ "\n") cstr (print_str_list elems)) type_tbl; ()
 
+  
 let env_diff_names env1 env2 =
-  List.map Ident.name (Env.diff env1 env2)
-                                                                                                                     
+  List.map Ident.unique_name (Env.diff env1 env2)
+
+(**
+ *  Functions to work with environment
+ **)
+
+let rec list_of_ident_from_summary = function
+  | Env_empty -> []
+  | Env_value (sum, id, vd) -> id :: list_of_ident_from_summary sum
+  | Env_type (sum,_,_)
+  | Env_extension (sum,_,_)
+  | Env_module (sum,_,_)
+  | Env_modtype (sum,_,_)
+  | Env_class (sum,_,_)
+  | Env_cltype (sum,_,_)
+  | Env_open (sum,_)
+  | Env_functor_arg (sum,_) -> list_of_ident_from_summary sum
+           
+(** Those functions might be deleted 
+         
+type 'a diff =
+    'a list (* Removed from the reference *)
+    * 'a list (* Added to the reference *)
+
+let rec set_inter set1 set2 =
+  (** Set are supposed sorted **)
+  match set1, set2 with
+  | [], [] | _, [] | [], _ -> []
+  | x :: xs, y :: ys ->
+     if x = y then x :: set_inter xs ys
+     else if x < y then set_inter xs set2
+     else set_inter set1 ys
+
+let rec set_minus set_ref min =
+  (** Set are supposed sorted **)
+  match set_ref, min with
+  | [], _ -> []
+  | xs, [] -> xs
+  | x :: xs, y :: ys ->
+     if x = y then set_minus xs ys
+     else if x < y then x :: set_minus xs min
+     else set_minus set_ref ys
+                    
+let env_diff env_ref env : string diff =
+  let sum_ref = Env.summary env_ref in
+  let sum_new = Env.summary env in
+  let ident_ref = list_of_ident_from_summary sum_ref
+                  |> List.map Ident.unique_name
+                  |> List.sort compare in
+  let ident_new = list_of_ident_from_summary sum_new
+                  |> List.map Ident.unique_name
+                  |> List.sort compare in
+  let inter = set_inter ident_ref ident_new in
+  let del = set_minus ident_ref inter in
+  let ins = set_minus ident_new inter in
+  (del, ins)
+
+  let print_diff env1 env2 =
+    let (del, ins) = env_diff env1 env2 in
+    Printf.printf "del: %s ; ins: %s\n" (print_name_list del) (print_name_list ins)
+ *)
+
+let print_name_list l =
+  let rec aux = function
+    | [] -> ""
+    | x :: [] -> x
+    | x :: xs -> x ^ ", " ^ aux xs
+  in "[ " ^ aux l ^ " ]"
+
+let print_env env =
+  let idents = env
+               |> Env.summary
+               |> list_of_ident_from_summary
+               |> List.map Ident.name in
+  Printf.printf "env: %s\n" (print_name_list idents)
+                            
 (**
  * Useful functions (Warning: shadows `show_list' from Mytools)
  *)
@@ -63,21 +138,21 @@ let ppf_lambda_wrap s =
   
 let ppf_branch case binders expr =
   Printf.sprintf "@[<v 1>%s: @[<v 2>%s@,return %s;@,@]@,@,@]"
-    case binders expr
+                 case binders expr
 
 let ppf_let_in decl exp =
   let s =
-    Printf.sprintf "@[<v 2>%s@,@,return %s;@]"
-      decl exp
+    Printf.sprintf "@[<v 0>%s@,@,return %s;@]"
+                   decl exp
   in ppf_lambda_wrap s
 
 let ppf_function args body=
   Printf.sprintf "@[<v 0>function (%s) {@,@[<v 2>@,return %s;@,@]@,}@]"
-    args body
+                 args body
 
 let ppf_apply f args =
   Printf.sprintf "@[<v 0>%s(%s)@]"
-    f args
+                 f args
 
 let ppf_apply_infix f arg1 arg2 =
   Printf.sprintf "@[<v 0>%s %s %s@]"
@@ -85,44 +160,45 @@ let ppf_apply_infix f arg1 arg2 =
     
 let ppf_match value cases =
   let s =
-    Printf.sprintf "switch (%s.type) {@,@[<v 2>@,%s@,@]@,}"
-      value cases
+    Printf.sprintf "@[<v 0>switch (%s.type) {@,@[<v 2>@,%s@,@]@,}@]"
+                   value cases
   in ppf_lambda_wrap s
 
-(*  Format.sprintf "@[<v 0>(function () {@,@[<v 2>@,switch (%s.type) {@,@[<v 2>@,%s@,@]@,}@]@,})()@]"
-    value cases*)
-
 let ppf_array values =
-  Printf.sprintf "[%s]"
-    values
-
+  Printf.sprintf "@[<v 0>[%s]@]"
+                 values
+                 
 let ppf_tuple = ppf_array
     
 let ppf_ifthen cond iftrue =
   Printf.sprintf "@[<v 0>(function () {@,@[<v 2>@,if (%s) {@,@[<v 2>@,return  %s;@]@,}@]@,})()@]"
-    cond iftrue
+                 cond iftrue
 
 let ppf_ifthenelse cond iftrue iffalse =
-  Printf.sprintf "@[<v 0>(function () {@,@[<v 2>@,if (%s) {@,@[<v 2>@,return  %s;@]@,} else {@,@[<v 2>@,return  %s;@]@,}@]@]@,})()@]"
-    cond iftrue iffalse
+  Printf.sprintf "@[<v 0>(function () {@,@[<v 2>@,if (%s) {@,@[<v 2>@,return  %s;@]@,} else {@,@[<v 2>@,return  %s;@]@,}@]@,})()@]"
+                 cond iftrue iffalse
 
 let ppf_sequence exp1 exp2 =
   Printf.sprintf "@[<v 0>return %s,@,%s@]"
-    exp1 exp2
+                 exp1 exp2
 
 let ppf_while cd body =
-  Printf.sprintf "@[<v 0> function () {@,@[<v 1>@,while(%s) {@,@[<v 2>@,%s@]@]@,@]}@,)()@]"
-    cd body
-    
+  let s =
+    Printf.sprintf "@[<v 0>@,while(%s) {@,@[<v 2>@,%s@]@,}@]"
+                   cd body
+  in ppf_lambda_wrap s
+                     
 let ppf_for id start ed flag body =
   let fl_to_string = function
     | Upto   -> "++"
     | Downto -> "--" in
   let fl_to_symbl = function
     | Upto   -> "<="
-    | Downto -> ">="
-  in Printf.sprintf "@[<v 0>(function () {@,@[<v 3>@,for (%s = %s ; %s %s %s ; %s%s) {@,@[@,%s @]@,} @,@]})() @]"
-  id start id (fl_to_symbl flag) ed (fl_to_string flag)  id body
+    | Downto -> ">=" in
+  let s =
+    Printf.sprintf "[<v 0>@,for (%s = %s ; %s %s %s ; %s%s) {@,@[<v 2>@,%s @]@,}@]"
+                   id start id (fl_to_symbl flag) ed (fl_to_string flag) id body
+  in ppf_lambda_wrap s
 
 let ppf_single_cstr tag =
   Printf.sprintf "%s"
@@ -133,11 +209,11 @@ let ppf_cstr tag value =
     tag value
 
 let ppf_single_cstrs typ =
-   Printf.sprintf "{type: \"%s\"}"
+   Printf.sprintf "@[<v 0>{type: \"%s\"}@]"
      typ
       
 let ppf_multiple_cstrs typ rest =
-  Printf.sprintf "{type: \"%s\", %s}"
+  Printf.sprintf "@[<v 0>{type: \"%s\", @[<v 2>%s@]}@]"
     typ rest
 
 let ppf_record llde =
@@ -146,21 +222,30 @@ let ppf_record llde =
     | (lbl, exp) :: [] -> aux (acc ^ Printf.sprintf "%s: %s" lbl exp) []
     | (lbl, exp) :: xs -> aux (acc ^ Printf.sprintf "%s: %s,@," lbl exp) xs
   in aux "" llde
-    
+
+let ppf_decl id expr =
+  Printf.sprintf "@[<v 0>var %s = %s;@,@]" 
+                 id expr
+
+let ppf_pat_array id_list array_expr =
+  Printf.sprintf "@[<v 0>var __%s = %s;@,@]" "array" array_expr ^
+    List.fold_left2 (fun acc (name, exp_type) y -> acc ^ Printf.sprintf "@[<v 0>var %s = __%s[%d];@,@]" name "array" y)
+                    "" id_list @@ range 0 (List.length id_list - 1)
+                 
 (**
  * Main part
  *)
 
 let rec to_javascript typedtree =
   let pre_res = js_of_structure Env.empty typedtree in
-  L.logged_output pre_res, L.unlogged_output pre_res, pre_res
-                                           
+  L.logged_output pre_res, L.unlogged_output pre_res, pre_res                                           
   
 and show_value_binding old_env vb =
   js_of_let_pattern old_env vb.vb_pat vb.vb_expr
     
 and js_of_structure old_env s =
-  show_list_f (fun strct -> js_of_structure_item old_env strct) lin2 s.str_items
+  let new_env = s.str_final_env in
+  show_list_f (fun strct -> js_of_structure_item new_env strct) lin2 s.str_items
     
 and js_of_structure_item old_env s =
   let new_env = s.str_env in
@@ -194,9 +279,9 @@ and js_of_structure_item old_env s =
   | Tstr_attribute  attrs -> out_of_scope "attributes"
 
 and js_of_branch old_env b obj =
-  let spat, binders = js_of_pattern b.c_lhs obj in
+  let spat, binders = js_of_pattern old_env b.c_lhs obj in
   let se = js_of_expression old_env b.c_rhs in
-  ppf_branch spat binders se
+  L.log_line (ppf_branch spat binders se) (L.Add binders)
     
 and js_of_expression old_env e =
   let new_env = e.exp_env in
@@ -286,7 +371,8 @@ and ident_of_pat pat = match pat.pat_desc with
   | _ -> error "functions can't deconstruct values"
     
 and js_of_let_pattern old_env pat expr =
-  let expr_type pat expr = match expr.exp_desc with
+  let new_env = pat.pat_env in
+  (*let expr_type pat expr = match expr.exp_desc with
     | Texp_construct (loc, cd, el) ->
        let value = js_of_longident loc in
        if el = [] then
@@ -295,40 +381,43 @@ and js_of_let_pattern old_env pat expr =
          let rec expand_constructor_list fields exprs = match fields, exprs with
            | [], [] -> []
            | [], x :: xs | x :: xs , [] -> failwith "argument lists should have the same length."
-           | x :: xs, y :: ys ->  ppf_cstr  x y :: expand_constructor_list xs ys in
+           | x :: xs, y :: ys -> ppf_cstr  x y :: expand_constructor_list xs ys in
          let names = Hashtbl.find type_tbl value
-         in ppf_multiple_cstrs value (show_list ", " (expand_constructor_list names (List.map (fun exp -> js_of_expression old_env exp) el)))
-    | _ -> string_of_type_exp pat.pat_type in
-  let sexpr = js_of_expression old_env expr in
+         in ppf_multiple_cstrs value (show_list ", " (expand_constructor_list names (List.map (fun exp -> js_of_expression new_env exp) el)))
+    | _ -> string_of_type_exp pat.pat_type in*)
+  let sexpr = js_of_expression new_env expr in
   match pat.pat_desc with
-  | Tpat_var (id, _) ->
-     Printf.sprintf "@[<v 0>var %s = %s;@,@]" (Ident.name id) sexpr
+  | Tpat_var (id, _) -> ppf_decl (Ident.name id) sexpr
   | Tpat_tuple (pat_l)
   | Tpat_array (pat_l) ->
-     let l = List.map (function pat -> match pat.pat_desc with
-                                       | Tpat_var (id, _) -> (Ident.name id, string_of_type_exp pat.pat_type)
-                                       | _ -> out_of_scope "pattern-matching in arrays") pat_l in
-     Printf.sprintf "@[<v 0>var __%s = %s;@,@]" "array" sexpr ^
-       List.fold_left2 (fun acc (name, exp_type) y -> acc ^ Printf.sprintf "@[<v 0>var %s = __%s[%d];@,@]" name "array" y)
-                       "" l @@ range 0 (List.length l - 1)
+     let l = List.map
+               (function pat ->
+                         match pat.pat_desc with
+                         | Tpat_var (id, _) -> (Ident.name id, string_of_type_exp pat.pat_type)
+                         | _ -> out_of_scope "pattern-matching in arrays"
+               ) pat_l in
+     ppf_pat_array l sexpr
   | _ -> error "let can't deconstruct values"
 
-and js_of_pattern pat obj = match pat.pat_desc with
-  | Tpat_any -> "default", ""
-  | Tpat_constant c -> js_of_constant c, ""
-  | Tpat_var (id, _) -> Ident.name id, ""
-  | Tpat_alias (_,_,_) -> out_of_scope "alias-pattern"
-  | Tpat_tuple (_) -> out_of_scope "tuple matching"
+and js_of_pattern old_env pat obj =
+ let new_env = pat.pat_env in
+  match pat.pat_desc with
+  | Tpat_any                     -> "default", ""
+  | Tpat_constant   c            -> js_of_constant c, ""
+  | Tpat_var       (id, _)       -> Ident.name id, ""
   | Tpat_construct (loc, cd, el) ->
      let c = js_of_longident loc in
      let spat = Printf.sprintf "%s" ("case \"" ^ c ^ "\"") in
      let params = Hashtbl.find type_tbl c in
      let binders =
        if List.length el = 0 then ""
-       else Printf.sprintf "%s@," ("var " ^ show_list ", " (List.map2 (fun x y -> x ^ " = " ^ obj ^ "." ^ y) (List.map (fun x -> fst (js_of_pattern x obj)) el) params) ^ ";") in
+       else Printf.sprintf "@[<v 0>%s@,@]"
+          ("var " ^ show_list ", " (List.map2 (fun x y -> x ^ " = " ^ obj ^ "." ^ y) (List.map (fun x -> fst (js_of_pattern new_env x obj)) el) params) ^ ";") in
      spat, binders
-  | Tpat_variant (_,_,_) -> out_of_scope "polymorphic variants in pattern matching"
-  | Tpat_array (_) -> out_of_scope "array-match"
+  | Tpat_tuple el -> out_of_scope "tuple matching"
+  | Tpat_array el -> out_of_scope "array-match"
   | Tpat_record (_,_) -> out_of_scope "record"
   | Tpat_or (_,_,_) -> failwith "not implemented yet"
-  | Tpat_lazy (_) -> out_of_scope "lazy-pattern"
+  | Tpat_alias (_,_,_) -> out_of_scope "alias-pattern"
+  | Tpat_variant (_,_,_) -> out_of_scope "polymorphic variants in pattern matching"
+  | Tpat_lazy _ -> out_of_scope "lazy-pattern"
-- 
GitLab