@@ -306,10 +306,149 @@ and eq_primitive (p : Lambda.primitive) (p1 : Lambda.primitive) =
306306    try  p =  p1 with  _  ->  false 
307307
308308
309- let  is_closed_by  map  lam  =  
310-   Lambda.IdentSet. for_all Ident. global 
311-     (Lambda.IdentSet. diff (Lambda. free_variables lam) map )
309+ 
310+ type  stats  = 
311+   { 
312+     mutable  top  : bool  ;  
313+     (*  all appearances are in the top,  substitution is fine 
314+        whether it is pure or not 
315+        {[ 
316+          (fun x y           
317+            ->  x + y + (f x )) (32) (console.log('hi'), 33) 
318+        ]}        
319+        since in ocaml, the application order is intentionally undefined,  
320+        note if [times] is not one, this field does not make sense        
321+     *)      
322+     mutable  times  : int  ;  
323+   }
324+ type  env  = 
325+   { top   : bool  ;  
326+     loop  : bool  
327+   }
328+ 
329+ let  no_substitute =  { top =  false ; loop =  true  }
330+ let  fresh_env =  {top =  true ; loop =  false  }
331+ let  fresh_stats  ()  =  { top =  true ; times =  0  }
332+ 
333+ let  param_map_of_list  lst  =  
334+   List. fold_left  (fun  acc  l  -> Ident_map. add l (fresh_stats () ) acc) Ident_map. empty  lst 
335+ 
336+ (* * Sanity check, remove all varaibles in [local_set] in the last pass *)    
337+ 
338+ let  free_variables  (export_idents  : Ident_set.t  ) (params  : stats Ident_map.t  ) lam  =  
339+   let  fv =  ref  params in 
340+   let  local_set =  ref  export_idents in 
341+ 
342+   let  local_add  k  = 
343+     local_set :=  Ident_set. add k ! local_set in 
344+   let  local_add_list  ks  =  
345+     local_set :=   
346+       List. fold_left (fun  acc  k  -> Ident_set. add k acc) ! local_set ks 
347+   in     
348+   let  loop_use =  100  in 
349+   let  map_use  {top; loop}  v  =  
350+     (*  relies on [identifier] uniquely bound *)      
351+     let  times =  if  loop then  loop_use else  1  in 
352+     if  Ident_set. mem v ! local_set then  ()     
353+     else  begin  match  Ident_map. find v ! fv with   
354+       |  exception  Not_found 
355+         -> fv :=  Ident_map. add v { top ; times } ! fv
356+       |  v  ->
357+         v.times < -  v.times +  times ; 
358+         v.top < -  v.top &&  top          
359+     end 
360+   in 
361+   let  new_env  lam  (env  : env ) =  
362+     if  env.top then  
363+       if  no_side_effects lam 
364+       then  env 
365+       else  { env with  top =  false }
366+     else  env      
367+   in     
368+   let  rec  iter  (top  : env ) (lam  : Lambda.lambda ) = 
369+     match  lam with   
370+     |  Lvar  v  -> map_use top v 
371+     |  Lconst  _  -> () 
372+     |  Lapply (fn , args , _ ) ->
373+       iter top  fn; 
374+       let  top =  new_env fn top in 
375+       List. iter (iter top ) args  
376+     |  Lprim (_p , args ) -> 
377+       (*  Check: can top be propoaged for all primitives *) 
378+       List. iter (iter top) args
379+     |  Lfunction (_kind , params , body ) ->
380+       local_add_list params;
381+       iter no_substitute body 
382+     |  Llet (_let_kind , id , arg , body ) ->
383+       local_add id ;  
384+       iter top  arg; iter no_substitute body
385+     |  Lletrec (decl , body ) ->
386+       local_set :=  List. fold_left (fun  acc  (id , _ ) -> 
387+           Ident_set. add id acc) ! local_set decl;        
388+       List. iter (fun  (_ , exp ) -> iter no_substitute exp) decl;
389+       iter no_substitute body
390+     |  Lswitch (arg , sw ) ->
391+       iter top arg; 
392+       let  top =  new_env arg top  in        
393+       List. iter (fun  (key , case ) -> iter top case) sw.sw_consts;
394+       List. iter (fun  (key , case ) -> iter top  case) sw.sw_blocks;
395+   
396+       begin  match  sw.sw_failaction with   
397+         |  None  -> () 
398+         |  Some  x  ->
399+           let  nconsts =  List. length sw.sw_consts in 
400+           let  nblocks =  List. length sw.sw_blocks in 
401+ 
402+           if  nconsts <  sw.sw_numconsts  &&  nblocks <  sw.sw_numblocks then 
403+             iter no_substitute x
404+           else 
405+             iter top x
406+       end 
407+ 
408+     |  Lstringswitch  (arg ,cases ,default ) ->
409+       iter top arg ;
410+       let  top =  new_env arg top  in        
411+       List. iter (fun  (_ ,act ) -> iter top  act) cases ;
412+       begin  match  default with   
413+       |  None  -> () 
414+       |  Some  x  -> iter top x 
415+       end 
416+     |  Lstaticraise  (_ ,args ) ->
417+       List. iter (iter no_substitute ) args
418+     |  Lstaticcatch (e1 , (_ ,vars ), e2 ) ->
419+       iter no_substitute  e1; 
420+       local_add_list vars;       
421+       iter no_substitute e2
422+     |  Ltrywith (e1 , exn , e2 ) ->
423+       iter top  e1; iter no_substitute  e2
424+     |  Lifthenelse (e1 , e2 , e3 ) ->
425+       iter top e1; 
426+       let  top =  new_env e1 top  in 
427+       iter top e2; iter top e3
428+     |  Lsequence (e1 , e2 ) ->
429+       iter top e1; iter no_substitute e2
430+     |  Lwhile (e1 , e2 ) ->
431+       iter no_substitute e1; iter no_substitute e2 (*  in the loop, no substitution any way *) 
432+     |  Lfor (v , e1 , e2 , dir , e3 ) ->
433+       local_add v ; 
434+       iter no_substitute e1; iter no_substitute e2; iter no_substitute e3
435+     |  Lassign (id , e ) ->
436+       map_use top  id ; 
437+       iter top e
438+     |  Lsend  (_k , met , obj , args , _ ) ->
439+       iter no_substitute met ; 
440+       iter no_substitute obj;
441+       List. iter (iter no_substitute) args
442+     |  Levent  (lam , evt ) ->
443+       iter top  lam
444+     |  Lifused  (v , e ) ->
445+       iter no_substitute e in 
446+   iter fresh_env  lam ; ! fv 
447+ 
448+ 
449+ let  is_closed_by  set  lam  =  
450+   Ident_map. is_empty (free_variables set (Ident_map. empty ) lam   )
312451
313452
314453let  is_closed   lam  =  
315-   Lambda.IdentSet. for_all  Ident. global ( Lambda. free_variables  lam)  
454+   Ident_map. is_empty (free_variables  Ident_set. empty  Ident_map. empty  lam)  
0 commit comments