Skip to content

Commit 1be8b7e

Browse files
committed
WIP
1 parent e022247 commit 1be8b7e

File tree

8 files changed

+38
-9
lines changed

8 files changed

+38
-9
lines changed

compiler/lib/driver.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ if (typeof module === 'object' && module.exports) {
650650

651651
let collects_shapes p =
652652
let _, info = Flow.f p in
653+
let pure = Pure_fun.f p in
653654
let l = ref StringMap.empty in
654655
Code.Addr.Map.iter
655656
(fun _ block ->
@@ -660,7 +661,7 @@ let collects_shapes p =
660661
, Prim
661662
( Extern "caml_register_global"
662663
, [ _code; Pv block; Pc (NativeString name) ] ) ) ->
663-
let shape = Flow.the_shape_of info block in
664+
let shape = Flow.the_shape_of ~pure info block in
664665
let name =
665666
match name with
666667
| Byte s -> s

compiler/lib/flow.ml

+20-4
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ let direct_approx (info : Info.t) x =
397397
y
398398
| _ -> None
399399

400-
let rec the_shape_of info x =
400+
let rec the_shape_of ~pure info x =
401401
let rec loop info x acc : Shape.t =
402402
get_approx
403403
info
@@ -407,9 +407,10 @@ let rec the_shape_of info x =
407407
| None -> (
408408
match info.info_defs.(Var.idx x) with
409409
| Expr (Block (_, a, _, Immutable)) ->
410-
Shape.Block (List.map ~f:(the_shape_of info) (Array.to_list a))
410+
Shape.Block (List.map ~f:(the_shape_of ~pure info) (Array.to_list a))
411411
| Expr (Closure (l, _)) ->
412-
Shape.Function { arity = List.length l; pure = false; res = Top "unk" }
412+
let pure = Code.Var.Set.mem x pure in
413+
Shape.Function { arity = List.length l; pure; res = Top "unk" }
413414
| Expr (Special (Alias_prim name)) -> (
414415
try
415416
let arity = Primitive.arity name in
@@ -429,7 +430,22 @@ let rec the_shape_of info x =
429430
| Shape.Block _ | Shape.Top _ -> Shape.Top "apply2")
430431
| _ -> Shape.Top "other"))
431432
(Top "init")
432-
(fun _u _v -> Shape.Top "merge")
433+
(fun u v ->
434+
let rec merge (u : Shape.t) (v : Shape.t) =
435+
match u, v with
436+
| ( Function { arity = a1; pure = p1; res = r1 }
437+
, Function { arity = a2; pure = p2; res = r2 } ) ->
438+
if a1 = a2
439+
then Shape.Function { arity = a1; pure = p1 && p2; res = merge r1 r2 }
440+
else Shape.Top "merge"
441+
| Block b1, Block b2 ->
442+
if List.length b1 = List.length b2
443+
then Block (List.map2 b1 b2 ~f:merge)
444+
else Top "merge block"
445+
| (Top _ as a), _ | _, (Top _ as a) -> a
446+
| Function _, Block _ | Block _, Function _ -> Shape.Top "merge block/fun"
447+
in
448+
merge u v)
433449
x
434450
in
435451
loop info x []

compiler/lib/flow.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,6 @@ val the_native_string_of : Info.t -> Code.prim_arg -> Code.Native_string.t optio
6060

6161
val the_int : Info.t -> Code.prim_arg -> int32 option
6262

63-
val the_shape_of : Info.t -> Code.Var.t -> Shape.t
63+
val the_shape_of : pure:Code.Var.Set.t -> Info.t -> Code.Var.t -> Shape.t
6464

6565
val f : ?skip_param:bool -> Code.program -> Code.program * Info.t

compiler/lib/pure_fun.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ let pure_expr pure_funs e =
2626
match e with
2727
| Block _ | Field _ | Closure _ | Constant _ -> true
2828
| Special (Alias_prim _ | Undefined) -> true
29-
| Apply { f; exact; _ } -> exact && Var.Set.mem f pure_funs
29+
| Apply { f; exact; _ } ->
30+
exact && (Var.Set.mem f pure_funs || Shape.State.is_pure_fun f)
3031
| Prim (p, _l) -> (
3132
match p with
3233
| Extern f -> Primitive.is_pure f

compiler/lib/shape.ml

+8-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ let rec to_string (shape : t) =
4646
match shape with
4747
| Top s -> if true then "N" else Printf.sprintf "N(%s)" s
4848
| Block l -> "[" ^ String.concat ~sep:"," (List.map ~f:to_string l) ^ "]"
49-
| Function { arity; _ } -> Printf.sprintf "F(%d)" arity
49+
| Function { arity; pure; _ } ->
50+
Printf.sprintf "F(%d)%s" arity (if pure then "" else "")
5051

5152
module Store = struct
5253
module T = Hashtbl.Make (struct
@@ -153,5 +154,11 @@ module State = struct
153154

154155
let get x = T.find_opt t x
155156

157+
let is_pure_fun x =
158+
match T.find_opt t x with
159+
| None -> false
160+
| Some (Top _ | Block _) -> false
161+
| Some (Function { pure; _ }) -> pure
162+
156163
let reset () = T.clear t
157164
end

compiler/lib/shape.mli

+2
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,7 @@ module State : sig
5353

5454
val get : Code.Var.t -> t option
5555

56+
val is_pure_fun : Code.Var.t -> bool
57+
5658
val reset : unit -> unit
5759
end

compiler/lib/specialize.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ open! Stdlib
2121
open Code
2222

2323
let function_arity info x =
24-
match Flow.the_shape_of info x with
24+
match Flow.the_shape_of ~pure:Code.Var.Set.empty info x with
2525
| Top _ | Block _ -> None
2626
| Function { arity; _ } -> Some arity
2727

toplevel/examples/lwt_toplevel/dune

+2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
(action
7070
(run
7171
%{bin:js_of_ocaml}
72+
--no-runtime
7273
--pretty
7374
--toplevel
7475
%{read-strings:effects_flags.txt}
@@ -79,6 +80,7 @@
7980
(action
8081
(run
8182
%{bin:js_of_ocaml}
83+
--no-runtime
8284
--pretty
8385
--toplevel
8486
--include-runtime

0 commit comments

Comments
 (0)