[sledge] Eliminate recursive records

Summary:
The support for recursive references to globals from within their
initializers is enough to handle all the cases of recursive structs
that have been encountered so far. Therefore this diff removes the
complication of recursive records entirely.

Reviewed By: jvillard

Differential Revision: D24772955

fbshipit-source-id: f59f06257
master
Josh Berdine 4 years ago committed by Facebook GitHub Bot
parent 0c17ac4281
commit aa307294a5

@ -127,8 +127,7 @@ let rec apron_texpr_of_llair_exp exp q =
| Label _ | Label _
|Ap1 ((Splat | Select _), _, _) |Ap1 ((Splat | Select _), _, _)
|Ap3 (Conditional, _, _, _, _) |Ap3 (Conditional, _, _, _, _)
|ApN (Record, _, _) |ApN (Record, _, _) ->
|RecRecord _ ->
None None
let assign reg exp q = let assign reg exp q =

@ -416,7 +416,7 @@ let convert_to_siz =
let xlate_llvm_eh_typeid_for : x -> Typ.t -> Exp.t -> Exp.t = let xlate_llvm_eh_typeid_for : x -> Typ.t -> Exp.t -> Exp.t =
fun x typ arg -> Exp.convert typ ~to_:(i32 x) arg fun x typ arg -> Exp.convert typ ~to_:(i32 x) arg
let rec xlate_intrinsic_exp stk : let rec xlate_intrinsic_exp :
string -> (x -> Llvm.llvalue -> Inst.t list * Exp.t) option = string -> (x -> Llvm.llvalue -> Inst.t list * Exp.t) option =
fun name -> fun name ->
match name with match name with
@ -424,36 +424,36 @@ let rec xlate_intrinsic_exp stk :
Some Some
(fun x llv -> (fun x llv ->
let rand = Llvm.operand llv 0 in let rand = Llvm.operand llv 0 in
let pre, arg = xlate_value stk x rand in let pre, arg = xlate_value x rand in
let src = xlate_type x (Llvm.type_of rand) in let src = xlate_type x (Llvm.type_of rand) in
(pre, xlate_llvm_eh_typeid_for x src arg) ) (pre, xlate_llvm_eh_typeid_for x src arg) )
| _ -> None | _ -> None
and xlate_values stk x len val_i = and xlate_values x len val_i =
let rec loop i (pre, args) = let rec loop i (pre, args) =
if i < 0 then (pre, args) if i < 0 then (pre, args)
else else
let pre_i, arg_i = xlate_value stk x (val_i i) in let pre_i, arg_i = xlate_value x (val_i i) in
loop (i - 1) (pre_i @ pre, arg_i :: args) loop (i - 1) (pre_i @ pre, arg_i :: args)
in in
loop (len - 1) ([], []) loop (len - 1) ([], [])
and xlate_value ?(inline = false) stk : and xlate_value ?(inline = false) : x -> Llvm.llvalue -> Inst.t list * Exp.t
x -> Llvm.llvalue -> Inst.t list * Exp.t = =
fun x llv -> fun x llv ->
let xlate_value_ llv = let xlate_value_ llv =
match Llvm.classify_value llv with match Llvm.classify_value llv with
| Instruction Call -> ( | Instruction Call -> (
let func = Llvm.operand llv (Llvm.num_arg_operands llv) in let func = Llvm.operand llv (Llvm.num_arg_operands llv) in
let fname = Llvm.value_name func in let fname = Llvm.value_name func in
match xlate_intrinsic_exp stk fname with match xlate_intrinsic_exp fname with
| Some intrinsic when inline || should_inline llv -> intrinsic x llv | Some intrinsic when inline || should_inline llv -> intrinsic x llv
| _ -> ([], Exp.reg (xlate_name x llv)) ) | _ -> ([], Exp.reg (xlate_name x llv)) )
| Instruction (Invoke | Alloca | Load | PHI | LandingPad | VAArg) | Instruction (Invoke | Alloca | Load | PHI | LandingPad | VAArg)
|Argument -> |Argument ->
([], Exp.reg (xlate_name x llv)) ([], Exp.reg (xlate_name x llv))
| Function | GlobalVariable -> ([], Exp.reg (xlate_global stk x llv).reg) | Function | GlobalVariable -> ([], Exp.reg (xlate_global x llv).reg)
| GlobalAlias -> xlate_value stk x (Llvm.operand llv 0) | GlobalAlias -> xlate_value x (Llvm.operand llv 0)
| ConstantInt -> ([], xlate_int x llv) | ConstantInt -> ([], xlate_int x llv)
| ConstantFP -> ([], xlate_float x llv) | ConstantFP -> ([], xlate_float x llv)
| ConstantPointerNull -> ([], Exp.null) | ConstantPointerNull -> ([], Exp.null)
@ -468,27 +468,23 @@ and xlate_value ?(inline = false) stk :
| ConstantVector | ConstantArray -> | ConstantVector | ConstantArray ->
let typ = xlate_type x (Llvm.type_of llv) in let typ = xlate_type x (Llvm.type_of llv) in
let len = Llvm.num_operands llv in let len = Llvm.num_operands llv in
let pre, args = xlate_values stk x len (Llvm.operand llv) in let pre, args = xlate_values x len (Llvm.operand llv) in
(pre, Exp.record typ (IArray.of_list args)) (pre, Exp.record typ (IArray.of_list args))
| ConstantDataVector -> | ConstantDataVector ->
let typ = xlate_type x (Llvm.type_of llv) in let typ = xlate_type x (Llvm.type_of llv) in
let len = Llvm.vector_size (Llvm.type_of llv) in let len = Llvm.vector_size (Llvm.type_of llv) in
let pre, args = xlate_values stk x len (Llvm.const_element llv) in let pre, args = xlate_values x len (Llvm.const_element llv) in
(pre, Exp.record typ (IArray.of_list args)) (pre, Exp.record typ (IArray.of_list args))
| ConstantDataArray -> | ConstantDataArray ->
let typ = xlate_type x (Llvm.type_of llv) in let typ = xlate_type x (Llvm.type_of llv) in
let len = Llvm.array_length (Llvm.type_of llv) in let len = Llvm.array_length (Llvm.type_of llv) in
let pre, args = xlate_values stk x len (Llvm.const_element llv) in let pre, args = xlate_values x len (Llvm.const_element llv) in
(pre, Exp.record typ (IArray.of_list args)) (pre, Exp.record typ (IArray.of_list args))
| ConstantStruct -> ( | ConstantStruct ->
let typ = xlate_type x (Llvm.type_of llv) in let typ = xlate_type x (Llvm.type_of llv) in
match List.find_idx ~f:(( == ) llv) stk with let len = Llvm.num_operands llv in
| Some (i, _) -> ([], Exp.rec_record i typ) let pre, args = xlate_values x len (Llvm.operand llv) in
| None -> (pre, Exp.record typ (IArray.of_list args))
let stk = llv :: stk in
let len = Llvm.num_operands llv in
let pre, args = xlate_values stk x len (Llvm.operand llv) in
(pre, Exp.record typ (IArray.of_list args)) )
| BlockAddress -> | BlockAddress ->
let parent = find_name (Llvm.operand llv 0) in let parent = find_name (Llvm.operand llv 0) in
let name = find_name (Llvm.operand llv 1) in let name = find_name (Llvm.operand llv 1) in
@ -510,9 +506,9 @@ and xlate_value ?(inline = false) stk :
| SRem | FRem | Shl | LShr | AShr | And | Or | Xor | ICmp | FCmp | SRem | FRem | Shl | LShr | AShr | And | Or | Xor | ICmp | FCmp
| Select | GetElementPtr | ExtractElement | InsertElement | Select | GetElementPtr | ExtractElement | InsertElement
| ShuffleVector | ExtractValue | InsertValue ) as opcode ) -> | ShuffleVector | ExtractValue | InsertValue ) as opcode ) ->
if inline || should_inline llv then xlate_opcode stk x llv opcode if inline || should_inline llv then xlate_opcode x llv opcode
else ([], Exp.reg (xlate_name x llv)) else ([], Exp.reg (xlate_name x llv))
| ConstantExpr -> xlate_opcode stk x llv (Llvm.constexpr_opcode llv) | ConstantExpr -> xlate_opcode x llv (Llvm.constexpr_opcode llv)
| GlobalIFunc -> todo "ifuncs: %a" pp_llvalue llv () | GlobalIFunc -> todo "ifuncs: %a" pp_llvalue llv ()
| Instruction (CatchPad | CleanupPad | CatchSwitch) -> | Instruction (CatchPad | CleanupPad | CatchSwitch) ->
todo "windows exception handling: %a" pp_llvalue llv () todo "windows exception handling: %a" pp_llvalue llv ()
@ -530,18 +526,18 @@ and xlate_value ?(inline = false) stk :
|> |>
[%Trace.retn fun {pf} -> pf "%a" pp_prefix_exp] ) [%Trace.retn fun {pf} -> pf "%a" pp_prefix_exp] )
and xlate_opcode stk : and xlate_opcode : x -> Llvm.llvalue -> Llvm.Opcode.t -> Inst.t list * Exp.t
x -> Llvm.llvalue -> Llvm.Opcode.t -> Inst.t list * Exp.t = =
fun x llv opcode -> fun x llv opcode ->
[%Trace.call fun {pf} -> pf "%a" pp_llvalue llv] [%Trace.call fun {pf} -> pf "%a" pp_llvalue llv]
; ;
let xlate_rand i = xlate_value stk x (Llvm.operand llv i) in let xlate_rand i = xlate_value x (Llvm.operand llv i) in
let typ = lazy (xlate_type x (Llvm.type_of llv)) in let typ = lazy (xlate_type x (Llvm.type_of llv)) in
let convert opcode = let convert opcode =
let dst = Lazy.force typ in let dst = Lazy.force typ in
let rand = Llvm.operand llv 0 in let rand = Llvm.operand llv 0 in
let src = xlate_type x (Llvm.type_of rand) in let src = xlate_type x (Llvm.type_of rand) in
let pre, arg = xlate_value stk x rand in let pre, arg = xlate_value x rand in
( pre ( pre
, match (opcode : Llvm.Opcode.t) with , match (opcode : Llvm.Opcode.t) with
| Trunc -> Exp.signed (Typ.bit_size_of dst) arg ~to_:dst | Trunc -> Exp.signed (Typ.bit_size_of dst) arg ~to_:dst
@ -729,7 +725,7 @@ and xlate_opcode stk :
| ShuffleVector -> ( | ShuffleVector -> (
(* translate shufflevector <N x t> %x, _, <N x i32> zeroinitializer to (* translate shufflevector <N x t> %x, _, <N x i32> zeroinitializer to
%x *) %x *)
let exp = xlate_value stk x (Llvm.operand llv 0) in let exp = xlate_value x (Llvm.operand llv 0) in
let exp_typ = xlate_type x (Llvm.type_of (Llvm.operand llv 0)) in let exp_typ = xlate_type x (Llvm.type_of (Llvm.operand llv 0)) in
let llmask = Llvm.operand llv 2 in let llmask = Llvm.operand llv 2 in
let mask_typ = xlate_type x (Llvm.type_of llmask) in let mask_typ = xlate_type x (Llvm.type_of llmask) in
@ -745,7 +741,7 @@ and xlate_opcode stk :
|> |>
[%Trace.retn fun {pf} -> pf "%a" pp_prefix_exp] [%Trace.retn fun {pf} -> pf "%a" pp_prefix_exp]
and xlate_global stk : x -> Llvm.llvalue -> Global.t = and xlate_global : x -> Llvm.llvalue -> Global.t =
fun x llg -> fun x llg ->
GlobTbl.find_or_add memo_global llg ~default:(fun () -> GlobTbl.find_or_add memo_global llg ~default:(fun () ->
[%Trace.call fun {pf} -> pf "%a" pp_llvalue llg] [%Trace.call fun {pf} -> pf "%a" pp_llvalue llg]
@ -759,7 +755,7 @@ and xlate_global stk : x -> Llvm.llvalue -> Global.t =
match Llvm.classify_value llg with match Llvm.classify_value llg with
| GlobalVariable -> | GlobalVariable ->
Option.map (Llvm.global_initializer llg) ~f:(fun llv -> Option.map (Llvm.global_initializer llg) ~f:(fun llv ->
let pre, init = xlate_value stk x llv in let pre, init = xlate_value x llv in
(* Nondet insts to set up globals can be dropped to simply (* Nondet insts to set up globals can be dropped to simply
leave the undef regs unconstrained. Other insts to set up leave the undef regs unconstrained. Other insts to set up
globals are currently not supported *) globals are currently not supported *)
@ -773,12 +769,6 @@ and xlate_global stk : x -> Llvm.llvalue -> Global.t =
|> |>
[%Trace.retn fun {pf} -> pf "%a" Global.pp_defn] ) [%Trace.retn fun {pf} -> pf "%a" Global.pp_defn] )
let xlate_intrinsic_exp = xlate_intrinsic_exp []
let xlate_value ?inline = xlate_value ?inline []
let xlate_values = xlate_values []
let xlate_opcode = xlate_opcode []
let xlate_global = xlate_global []
type pop_thunk = Loc.t -> Llair.inst list type pop_thunk = Loc.t -> Llair.inst list
let pop_stack_frame_of_function : let pop_stack_frame_of_function :

@ -23,7 +23,7 @@ let rec classify e =
| Interpreted -> Interpreted | Interpreted -> Interpreted
| Uninterpreted -> Uninterpreted ) | Uninterpreted -> Uninterpreted )
| Sized _ | Extract _ | Concat _ -> Interpreted | Sized _ | Extract _ | Concat _ -> Interpreted
| Var _ | Z _ | Q _ | Ancestor _ -> Atomic | Var _ | Z _ | Q _ -> Atomic
| Splat _ | Select _ | Update _ | Record _ | Apply _ -> Uninterpreted | Splat _ | Select _ | Update _ | Record _ | Apply _ -> Uninterpreted
let interpreted e = equal_kind (classify e) Interpreted let interpreted e = equal_kind (classify e) Interpreted

@ -237,7 +237,6 @@ module Term = struct
ap2t (fun rcd elt -> Trm.update ~rcd ~idx ~elt) rcd elt ap2t (fun rcd elt -> Trm.update ~rcd ~idx ~elt) rcd elt
let record elts = apNt Trm.record elts let record elts = apNt Trm.record elts
let ancestor i = `Trm (Trm.ancestor i)
(* uninterpreted *) (* uninterpreted *)

@ -56,9 +56,6 @@ module rec Term : sig
val record : t array -> t val record : t array -> t
(** Record constant *) (** Record constant *)
val ancestor : int -> t
(** Reference to ancestor recursive record *)
(* uninterpreted *) (* uninterpreted *)
val apply : Funsym.t -> t array -> t val apply : Funsym.t -> t array -> t

@ -86,7 +86,6 @@ and Trm : sig
| Select of {idx: int; rcd: t} | Select of {idx: int; rcd: t}
| Update of {idx: int; rcd: t; elt: t} | Update of {idx: int; rcd: t; elt: t}
| Record of t array | Record of t array
| Ancestor of int
(* uninterpreted *) (* uninterpreted *)
| Apply of Funsym.t * t array | Apply of Funsym.t * t array
[@@deriving compare, equal, sexp] [@@deriving compare, equal, sexp]
@ -104,7 +103,6 @@ and Trm : sig
val _Select : int -> t -> t val _Select : int -> t -> t
val _Update : int -> t -> t -> t val _Update : int -> t -> t -> t
val _Record : t array -> t val _Record : t array -> t
val _Ancestor : int -> t
val _Apply : Funsym.t -> t array -> t val _Apply : Funsym.t -> t array -> t
val add : t -> t -> t val add : t -> t -> t
val sub : t -> t -> t val sub : t -> t -> t
@ -126,7 +124,6 @@ end = struct
| Select of {idx: int; rcd: t} | Select of {idx: int; rcd: t}
| Update of {idx: int; rcd: t; elt: t} | Update of {idx: int; rcd: t; elt: t}
| Record of t array | Record of t array
| Ancestor of int
| Apply of Funsym.t * t array | Apply of Funsym.t * t array
[@@deriving compare, equal, sexp] [@@deriving compare, equal, sexp]
@ -163,7 +160,6 @@ end = struct
| Update {idx; rcd; elt} -> | Update {idx; rcd; elt} ->
pf "[%a@ @[| %i → %a@]]" pp rcd idx pp elt pf "[%a@ @[| %i → %a@]]" pp rcd idx pp elt
| Record xs -> pf "{%a}" (ppx_record strength) xs | Record xs -> pf "{%a}" (ppx_record strength) xs
| Ancestor i -> pf "(ancestor %i)" i
| Apply (f, [||]) -> pf "%a" Funsym.pp f | Apply (f, [||]) -> pf "%a" Funsym.pp f
| Apply | Apply
( ( (Rem | BitAnd | BitOr | BitXor | BitShl | BitLshr | BitAshr) ( ( (Rem | BitAnd | BitOr | BitXor | BitShl | BitLshr | BitAshr)
@ -361,7 +357,6 @@ end = struct
let _Select idx rcd = Select {idx; rcd} |> check invariant let _Select idx rcd = Select {idx; rcd} |> check invariant
let _Update idx rcd elt = Update {idx; rcd; elt} |> check invariant let _Update idx rcd elt = Update {idx; rcd; elt} |> check invariant
let _Record es = Record es |> check invariant let _Record es = Record es |> check invariant
let _Ancestor i = Ancestor i |> check invariant
let _Apply f es = let _Apply f es =
( match Funsym.eval ~equal ~get_z ~ret_z:_Z ~get_q ~ret_q:_Q f es with ( match Funsym.eval ~equal ~get_z ~ret_z:_Z ~get_q ~ret_q:_Q f es with
@ -374,7 +369,7 @@ end = struct
let rec iter_vars e ~f = let rec iter_vars e ~f =
match e with match e with
| Var _ as v -> f (Var.of_ v) | Var _ as v -> f (Var.of_ v)
| Z _ | Q _ | Ancestor _ -> () | Z _ | Q _ -> ()
| Splat x | Select {rcd= x} -> iter_vars ~f x | Splat x | Select {rcd= x} -> iter_vars ~f x
| Sized {seq= x; siz= y} | Update {rcd= x; elt= y} -> | Sized {seq= x; siz= y} | Update {rcd= x; elt= y} ->
iter_vars ~f x ; iter_vars ~f x ;
@ -438,7 +433,6 @@ let concat elts = _Concat elts
let select ~rcd ~idx = _Select idx rcd let select ~rcd ~idx = _Select idx rcd
let update ~rcd ~idx ~elt = _Update idx rcd elt let update ~rcd ~idx ~elt = _Update idx rcd elt
let record elts = _Record elts let record elts = _Record elts
let ancestor i = _Ancestor i
(* uninterpreted *) (* uninterpreted *)
@ -458,7 +452,6 @@ let rec map_vars e ~f =
| Select {idx; rcd} -> map1 (map_vars ~f) e (_Select idx) rcd | Select {idx; rcd} -> map1 (map_vars ~f) e (_Select idx) rcd
| Update {idx; rcd; elt} -> map2 (map_vars ~f) e (_Update idx) rcd elt | Update {idx; rcd; elt} -> map2 (map_vars ~f) e (_Update idx) rcd elt
| Record xs -> mapN (map_vars ~f) e _Record xs | Record xs -> mapN (map_vars ~f) e _Record xs
| Ancestor _ -> e
| Apply (g, xs) -> mapN (map_vars ~f) e (_Apply g) xs | Apply (g, xs) -> mapN (map_vars ~f) e (_Apply g) xs
let map e ~f = let map e ~f =
@ -472,14 +465,13 @@ let map e ~f =
| Select {idx; rcd} -> map1 f e (_Select idx) rcd | Select {idx; rcd} -> map1 f e (_Select idx) rcd
| Update {idx; rcd; elt} -> map2 f e (_Update idx) rcd elt | Update {idx; rcd; elt} -> map2 f e (_Update idx) rcd elt
| Record xs -> mapN f e _Record xs | Record xs -> mapN f e _Record xs
| Ancestor _ -> e
| Apply (g, xs) -> mapN f e (_Apply g) xs | Apply (g, xs) -> mapN f e (_Apply g) xs
(** Traverse *) (** Traverse *)
let iter_subtrms e ~f = let iter_subtrms e ~f =
match e with match e with
| Var _ | Z _ | Q _ | Ancestor _ -> () | Var _ | Z _ | Q _ -> ()
| Arith a -> Iter.iter ~f (Arith.trms a) | Arith a -> Iter.iter ~f (Arith.trms a)
| Splat x | Select {rcd= x} -> f x | Splat x | Select {rcd= x} -> f x
| Sized {seq= x; siz= y} | Update {rcd= x; elt= y} -> | Sized {seq= x; siz= y} | Update {rcd= x; elt= y} ->

@ -25,7 +25,6 @@ type t = private
| Select of {idx: int; rcd: t} | Select of {idx: int; rcd: t}
| Update of {idx: int; rcd: t; elt: t} | Update of {idx: int; rcd: t; elt: t}
| Record of t array | Record of t array
| Ancestor of int
(* uninterpreted *) (* uninterpreted *)
| Apply of Funsym.t * t array | Apply of Funsym.t * t array
[@@deriving compare, equal, sexp] [@@deriving compare, equal, sexp]
@ -81,7 +80,6 @@ val concat : t array -> t
val select : rcd:t -> idx:int -> t val select : rcd:t -> idx:int -> t
val update : rcd:t -> idx:int -> elt:t -> t val update : rcd:t -> idx:int -> elt:t -> t
val record : t array -> t val record : t array -> t
val ancestor : int -> t
(* uninterpreted *) (* uninterpreted *)
val apply : Funsym.t -> t array -> t val apply : Funsym.t -> t array -> t

@ -70,7 +70,6 @@ module T = struct
| Ap2 of op2 * Typ.t * t * t | Ap2 of op2 * Typ.t * t * t
| Ap3 of op3 * Typ.t * t * t * t | Ap3 of op3 * Typ.t * t * t * t
| ApN of opN * Typ.t * t iarray | ApN of opN * Typ.t * t iarray
| RecRecord of int * Typ.t
[@@deriving compare, equal, hash, sexp] [@@deriving compare, equal, hash, sexp]
end end
@ -143,7 +142,6 @@ let rec pp fs exp =
| Ap3 (Conditional, _, cnd, thn, els) -> | Ap3 (Conditional, _, cnd, thn, els) ->
pf "(%a@ ? %a@ : %a)" pp cnd pp thn pp els pf "(%a@ ? %a@ : %a)" pp cnd pp thn pp els
| ApN (Record, _, elts) -> pf "{%a}" pp_record elts | ApN (Record, _, elts) -> pf "{%a}" pp_record elts
| RecRecord (i, _) -> pf "rec_record %i" i
[@@warning "-9"] [@@warning "-9"]
and pp_record fs elts = and pp_record fs elts =
@ -240,7 +238,6 @@ let rec invariant exp =
IArray.for_all2_exn elts args ~f:(fun (_, typ) arg -> IArray.for_all2_exn elts args ~f:(fun (_, typ) arg ->
Typ.castable typ (typ_of arg) ) ) Typ.castable typ (typ_of arg) ) )
| _ -> assert false ) | _ -> assert false )
| RecRecord _ -> ()
[@@warning "-9"] [@@warning "-9"]
(** Type query *) (** Type query *)
@ -268,8 +265,7 @@ and typ_of exp =
, _ , _
, _ ) , _ )
|Ap3 (Conditional, typ, _, _, _) |Ap3 (Conditional, typ, _, _, _)
|ApN (Record, typ, _) |ApN (Record, typ, _) ->
|RecRecord (_, typ) ->
typ typ
[@@warning "-9"] [@@warning "-9"]
@ -406,8 +402,6 @@ let select typ rcd idx = Ap1 (Select idx, typ, rcd) |> check invariant
let update typ ~rcd idx ~elt = let update typ ~rcd idx ~elt =
Ap2 (Update idx, typ, rcd, elt) |> check invariant Ap2 (Update idx, typ, rcd, elt) |> check invariant
let rec_record i typ = RecRecord (i, typ)
(** Traverse *) (** Traverse *)
let rec fold_exps e z ~f = let rec fold_exps e z ~f =

@ -81,7 +81,6 @@ type t = private
| Ap2 of op2 * Typ.t * t * t | Ap2 of op2 * Typ.t * t * t
| Ap3 of op3 * Typ.t * t * t * t | Ap3 of op3 * Typ.t * t * t * t
| ApN of opN * Typ.t * t iarray | ApN of opN * Typ.t * t iarray
| RecRecord of int * Typ.t (** Reference to ancestor recursive record *)
[@@deriving compare, equal, hash, sexp] [@@deriving compare, equal, hash, sexp]
val pp : t pp val pp : t pp
@ -179,7 +178,6 @@ val splat : Typ.t -> t -> t
val record : Typ.t -> t iarray -> t val record : Typ.t -> t iarray -> t
val select : Typ.t -> t -> int -> t val select : Typ.t -> t -> int -> t
val update : Typ.t -> rcd:t -> int -> elt:t -> t val update : Typ.t -> rcd:t -> int -> elt:t -> t
val rec_record : int -> Typ.t -> t
(** Traverse *) (** Traverse *)

@ -125,7 +125,6 @@ and term : Llair.Exp.t -> T.t =
T.update ~rcd:(term rcd) ~idx ~elt:(term elt) T.update ~rcd:(term rcd) ~idx ~elt:(term elt)
| ApN (Record, _, elts) -> | ApN (Record, _, elts) ->
T.record (Array.map ~f:term (IArray.to_array elts)) T.record (Array.map ~f:term (IArray.to_array elts))
| RecRecord (i, _) -> T.ancestor i
| Ap1 (Splat, _, byt) -> T.splat (term byt) | Ap1 (Splat, _, byt) -> T.splat (term byt)
and formula e = F.dq0 (term e) and formula e = F.dq0 (term e)

Loading…
Cancel
Save