@@ -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 []
0 commit comments