diff --git a/src/whyml/mlw_decl.ml b/src/whyml/mlw_decl.ml index 5f57f674af8eefc99f9a23464cec70e8b8427cd8..5e53511d9827da6611497313662ffbafa12aaf51 100644 --- a/src/whyml/mlw_decl.ml +++ b/src/whyml/mlw_decl.ml @@ -81,7 +81,7 @@ let create_data_decl tdl = let projections = Hid.create 17 in (* id -> plsymbol *) let build_constructor its (id,al) = (* check well-formedness *) - let vtvs = List.map (fun (pv,_) -> vtv_of_pv pv) al in + let vtvs = List.map (fun (pv,_) -> pv.pv_vtv) al in let tvs = List.fold_right Stv.add its.its_args Stv.empty in let regs = List.fold_right Sreg.add its.its_regs Sreg.empty in let check_tv tv = @@ -107,7 +107,7 @@ let create_data_decl tdl = pls in let build_proj (pv,pj) = - let vtv = vtv_of_pv pv in + let vtv = pv.pv_vtv in syms := ity_s_fold syms_its syms_ts !syms vtv.vtv_ity; if pj then Some (build_proj pv.pv_vs.vs_name vtv) else None in diff --git a/src/whyml/mlw_expr.ml b/src/whyml/mlw_expr.ml index 4b10299d8241d7e86fe2ab97d790ff3e1dea0249..ff420557058cb93c98eb6a96d2537a8915764057 100644 --- a/src/whyml/mlw_expr.ml +++ b/src/whyml/mlw_expr.ml @@ -27,10 +27,8 @@ open Mlw_ty (** program variables *) type pvsymbol = { - pv_vs : vsymbol; (* has a dummy type if pv_vty is an arrow *) - pv_vty : vty; - pv_tvs : Stv.t; - pv_regs : Sreg.t; + pv_vs : vsymbol; + pv_vtv : vty_value; } module Pv = Util.StructMake (struct @@ -45,21 +43,17 @@ let pv_equal : pvsymbol -> pvsymbol -> bool = (==) let create_pvsymbol id vtv = { pv_vs = create_vsymbol id (ty_of_ity vtv.vtv_ity); - pv_vty = VTvalue vtv; - pv_tvs = vtv.vtv_tvs; - pv_regs = vtv.vtv_regs; + pv_vtv = vtv; } -exception ValueExpected of pvsymbol -exception ArrowExpected of pvsymbol - -let vtv_of_pv pv = match pv.pv_vty with - | VTvalue vtv -> vtv - | VTarrow _ -> raise (ValueExpected pv) +type pasymbol = { + pa_name : ident; + pa_vta : vty_arrow; + pa_tvs : Stv.t; + pa_regs : Sreg.t; +} -let vta_of_pv pv = match pv.pv_vty with - | VTarrow vta -> vta - | VTvalue _ -> raise (ArrowExpected pv) +let pa_equal : pasymbol -> pasymbol -> bool = (==) (** program symbols *) @@ -105,11 +99,6 @@ type pre = term (* precondition *) type post = term (* postcondition *) type xpost = (vsymbol * post) Mexn.t (* exceptional postconditions *) -type variant = { - v_term : term; (* : tau *) - v_rel : lsymbol option; (* tau tau : prop *) -} - type expr = { e_node : expr_node; e_vty : vty; @@ -122,9 +111,9 @@ type expr = { and expr_node = | Elogic of term - | Evar of pvsymbol - | Esym of psymbol * ity_subst - | Eapp of pvsymbol * pvsymbol + | Earrow of pasymbol + | Einst of psymbol * ity_subst + | Eapp of pasymbol * pvsymbol | Elet of let_defn * expr | Erec of rec_defn list * expr | Eif of pvsymbol * expr * expr @@ -132,13 +121,17 @@ and expr_node = | Eany and let_defn = { - ld_pv : pvsymbol; - ld_expr : expr; + let_var : let_var; + let_expr : expr; } +and let_var = + | LetV of pvsymbol + | LetA of pasymbol + and rec_defn = { - rd_ps : psymbol; - rd_lambda : lambda; + rec_ps : psymbol; + rec_lambda : lambda; } and lambda = { @@ -150,6 +143,12 @@ and lambda = { l_xpost : xpost; } +and variant = { + v_term : term; (* : tau *) + v_rel : lsymbol option; (* tau tau : prop *) +} + + (* smart constructors *) let e_label ?loc l e = { e with e_label = l; e_loc = loc } @@ -172,8 +171,11 @@ let e_dummy node vty = { e_loc = None; } -let add_pv_tvs s pv = Mid.add pv.pv_vs.vs_name pv.pv_tvs s -let add_pv_regs s pv = Mid.add pv.pv_vs.vs_name pv.pv_regs s +let add_pv_tvs s pv = Mid.add pv.pv_vs.vs_name pv.pv_vtv.vtv_tvs s +let add_pv_regs s pv = Mid.add pv.pv_vs.vs_name pv.pv_vtv.vtv_regs s + +let add_pa_tvs s pa = Mid.add pa.pa_name pa.pa_tvs s +let add_pa_regs s pa = Mid.add pa.pa_name pa.pa_regs s let add_expr_tvs m e = Mid.union (fun _ s1 s2 -> Some (Stv.union s1 s2)) m e.e_tvs @@ -181,22 +183,23 @@ let add_expr_tvs m e = let add_expr_regs m e = Mid.union (fun _ s1 s2 -> Some (Sreg.union s1 s2)) m e.e_regs -let e_var pv = - let node = match pv.pv_vty with - | VTarrow _ -> Evar pv - | VTvalue _ -> Elogic (t_var pv.pv_vs) - in - { (e_dummy node pv.pv_vty) with +let e_value pv = + { (e_dummy (Elogic (t_var pv.pv_vs)) (VTvalue pv.pv_vtv)) with e_tvs = add_pv_tvs Mid.empty pv; e_regs = add_pv_regs Mid.empty pv; } -let e_sym ps sbs = +let e_arrow pa = + { (e_dummy (Earrow pa) (VTarrow pa.pa_vta)) with + e_tvs = add_pa_tvs Mid.empty pa; + e_regs = add_pa_regs Mid.empty pa; } + +let e_inst ps sbs = let vty = if not (Mtv.is_empty sbs.ity_subst_tv && Mreg.is_empty sbs.ity_subst_reg) then VTarrow (vta_full_inst (ity_subst_union ps.ps_subst sbs) ps.ps_vta) else VTarrow ps.ps_vta in - { (e_dummy (Esym (ps,sbs)) vty) with + { (e_dummy (Einst (ps,sbs)) vty) with e_tvs = Mid.singleton ps.ps_name ps.ps_tvs; e_regs = Mid.singleton ps.ps_name ps.ps_regs; } (* we only count the fixed type variables and regions of ps, so that @@ -216,35 +219,34 @@ let ghost_effect e = else e else e -let e_app pvf pva = - let eff,vty = vty_app_arrow (vta_of_pv pvf) (vtv_of_pv pva) in - ghost_effect { (e_dummy (Eapp (pvf,pva)) vty) with +let e_app pa pv = + let eff,vty = vty_app_arrow pa.pa_vta pv.pv_vtv in + ghost_effect { (e_dummy (Eapp (pa,pv)) vty) with e_effect = eff; - e_tvs = add_pv_tvs (add_pv_tvs Mid.empty pvf) pva; - e_regs = add_pv_regs (add_pv_regs Mid.empty pvf) pva; } - -let ts_dummy = create_tysymbol (id_fresh "arrow_dummy") [] None -let ty_dummy = ty_app ts_dummy [] + e_tvs = add_pv_tvs (add_pa_tvs Mid.empty pa) pv; + e_regs = add_pv_regs (add_pa_regs Mid.empty pa) pv; } let create_let_defn id e = - let pv = match e.e_vty with - | VTvalue vtv -> - create_pvsymbol id vtv - | VTarrow vta -> - { pv_vs = create_vsymbol id ty_dummy; - pv_vty = e.e_vty; - pv_tvs = Mid.fold (fun _ -> Stv.union) e.e_tvs vta.vta_tvs; - pv_regs = Mid.fold (fun _ -> Sreg.union) e.e_regs vta.vta_regs; } + let lv = match e.e_vty with + | VTvalue vtv -> LetV (create_pvsymbol id vtv) + | VTarrow vta -> LetA { + pa_name = Ident.id_register id; + pa_vta = vta; + pa_tvs = Mid.fold (fun _ -> Stv.union) e.e_tvs vta.vta_tvs; + pa_regs = Mid.fold (fun _ -> Sreg.union) e.e_regs vta.vta_regs; } in - { ld_pv = pv ; ld_expr = e } + { let_var = lv ; let_expr = e } exception StaleRegion of region * ident * expr -let e_let ld e = - let { ld_pv = pv ; ld_expr = d } = ld in +let e_let ({ let_var = lv ; let_expr = d } as ld) e = let eff = d.e_effect in - let tvs = Mid.remove pv.pv_vs.vs_name e.e_tvs in - let regs = Mid.remove pv.pv_vs.vs_name e.e_regs in + let id = match lv with + | LetV pv -> pv.pv_vs.vs_name + | LetA pa -> pa.pa_name + in + let tvs = Mid.remove id e.e_tvs in + let regs = Mid.remove id e.e_regs in (* If we reset some region in the first expression d, then it may only pccur in the second expression e in association to pv. Otherwise, this is a freshness violation: some symbol defined earlier carries diff --git a/src/whyml/mlw_expr.mli b/src/whyml/mlw_expr.mli index c468e226bc2459f90455c5f369238b985d82627d..84336582b5939f8615054cd55a3eb2c282fed638 100644 --- a/src/whyml/mlw_expr.mli +++ b/src/whyml/mlw_expr.mli @@ -26,31 +26,31 @@ open Mlw_ty (** program variables *) -(* pvsymbols represent function arguments (then they must be VTvalue's), - pattern variables (again, VTvalue) or intermediate computation results - introduced by let-expressions. They cannot be type-instantiated. *) +(* pvsymbols represent function arguments and pattern variables *) type pvsymbol = private { - pv_vs : vsymbol; (* has a dummy type if pv_vty is an arrow *) - pv_vty : vty; - pv_tvs : Stv.t; - pv_regs : Sreg.t; - (* If pv_vty is a value, these sets coinside with pv_vty.vty_tvs/regs. - If pv_vty is an arrow, we additionally count all type variables - and regions of the defining expression, in order to cover effects - and specification and not overgeneralize. *) + pv_vs : vsymbol; + pv_vtv : vty_value; } val pv_equal : pvsymbol -> pvsymbol -> bool -(* a value-typed pvsymbol to use in function arguments and patterns *) val create_pvsymbol : preid -> vty_value -> pvsymbol -exception ValueExpected of pvsymbol -exception ArrowExpected of pvsymbol +(* pasymbols represent higher-order intermediate computation results + introduced by let-expressions. They cannot be type-instantiated. *) + +type pasymbol = private { + pa_name : ident; + pa_vta : vty_arrow; + pa_tvs : Stv.t; + pa_regs : Sreg.t; + (* these sets contain pa_vta.vta_tvs/regs together with all type + variables and regions of the defining expression, in order to + cover effects and specification and not overgeneralize *) +} -val vtv_of_pv : pvsymbol -> vty_value -val vta_of_pv : pvsymbol -> vty_arrow +val pa_equal : pasymbol -> pasymbol -> bool (** program symbols *) @@ -103,11 +103,6 @@ type pre = term (* precondition *) type post = term (* postcondition *) type xpost = (vsymbol * post) Mexn.t (* exceptional postconditions *) -type variant = { - v_term : term; (* : tau *) - v_rel : lsymbol option; (* tau tau : prop *) -} - type expr = private { e_node : expr_node; e_vty : vty; @@ -120,9 +115,9 @@ type expr = private { and expr_node = private | Elogic of term - | Evar of pvsymbol - | Esym of psymbol * ity_subst - | Eapp of pvsymbol * pvsymbol + | Earrow of pasymbol + | Einst of psymbol * ity_subst + | Eapp of pasymbol * pvsymbol | Elet of let_defn * expr | Erec of rec_defn list * expr | Eif of pvsymbol * expr * expr @@ -130,13 +125,17 @@ and expr_node = private | Eany and let_defn = private { - ld_pv : pvsymbol; - ld_expr : expr; + let_var : let_var; + let_expr : expr; } +and let_var = + | LetV of pvsymbol + | LetA of pasymbol + and rec_defn = private { - rd_ps : psymbol; - rd_lambda : lambda; + rec_ps : psymbol; + rec_lambda : lambda; } and lambda = { @@ -148,14 +147,19 @@ and lambda = { l_xpost : xpost; } +and variant = { + v_term : term; (* : tau *) + v_rel : lsymbol option; (* tau tau : prop *) +} + val e_label : ?loc:Loc.position -> Slab.t -> expr -> expr val e_label_add : label -> expr -> expr val e_label_copy : expr -> expr -> expr -val e_var : pvsymbol -> expr -(* produces Elogic if a value or Evar if an arrow *) +val e_value : pvsymbol -> expr +val e_arrow : pasymbol -> expr -val e_sym : psymbol -> ity_subst -> expr +val e_inst : psymbol -> ity_subst -> expr (* FIXME? We store the substitution in the expr as given, though it could be restricted to type variables and regions (both top and subordinate) of ps_vta.vta_tvs/regs. *) @@ -164,7 +168,7 @@ exception GhostWrite of expr * region exception GhostRaise of expr * xsymbol (* a ghost expression writes in a non-ghost region or raises an exception *) -val e_app : pvsymbol -> pvsymbol -> expr +val e_app : pasymbol -> pvsymbol -> expr val create_let_defn : preid -> expr -> let_defn diff --git a/src/whyml/mlw_module.ml b/src/whyml/mlw_module.ml index e64278127726dbe479223bfd104a2ec5f93ff81d..6c8f3701e631a6ef27b8f65621fbda8509f62632 100644 --- a/src/whyml/mlw_module.ml +++ b/src/whyml/mlw_module.ml @@ -43,6 +43,7 @@ open Mlw_decl type prgsymbol = | PV of pvsymbol + | PA of pasymbol | PS of psymbol | PL of plsymbol @@ -68,6 +69,7 @@ let ns_union eq chk = let prg_equal p1 p2 = match p1,p2 with | PV p1, PV p2 -> pv_equal p1 p2 + | PA p1, PA p2 -> pa_equal p1 p2 | PS p1, PS p2 -> ps_equal p1 p2 | PL p1, PL p2 -> pl_equal p1 p2 | _, _ -> false diff --git a/src/whyml/mlw_module.mli b/src/whyml/mlw_module.mli index 1983333a9542e87dc5473bde1e0bea26cd8bd461..c6b43f3aa0432e68f396e3768afc02c57f72f88a 100644 --- a/src/whyml/mlw_module.mli +++ b/src/whyml/mlw_module.mli @@ -31,6 +31,7 @@ open Mlw_decl type prgsymbol = | PV of pvsymbol + | PA of pasymbol | PS of psymbol | PL of plsymbol diff --git a/src/whyml/mlw_pretty.ml b/src/whyml/mlw_pretty.ml index b96a8ad88c091807e5edf5bfb3594d9cadc6c93d..90eb9548ad11b5f84c8372c5b8b4459a2c0c8e3a 100644 --- a/src/whyml/mlw_pretty.ml +++ b/src/whyml/mlw_pretty.ml @@ -50,7 +50,7 @@ let print_reg fmt reg = (id_unique rprinter reg.reg_name) let print_pv fmt pv = - fprintf fmt "%s%a" (if vty_ghost pv.pv_vty then "?" else "") + fprintf fmt "%s%a" (if pv.pv_vtv.vtv_ghost then "?" else "") print_vs pv.pv_vs let forget_pv pv = forget_var pv.pv_vs diff --git a/src/whyml/mlw_typing.ml b/src/whyml/mlw_typing.ml index 5d06b4575a662d6de0df53cb5c936c7f86ef7a24..a6b7164de63bd8a4b91ea11637c2833608569947 100644 --- a/src/whyml/mlw_typing.ml +++ b/src/whyml/mlw_typing.ml @@ -232,7 +232,7 @@ let add_types uc tdl = | Some id -> try let pv = Hashtbl.find projs id.id in - let ty = (vtv_of_pv pv).vtv_ity in + let ty = pv.pv_vtv.vtv_ity in (* once we have ghost/mutable fields in algebraics, don't forget to check here that they coincide, too *) ignore (Loc.try3 id.id_loc ity_match sbs ty ity); @@ -319,7 +319,7 @@ let add_types uc tdl = | Some id -> try let pv = Hashtbl.find projs id.id in - let ty = (vtv_of_pv pv).vtv_ity in + let ty = pv.pv_vtv.vtv_ity in (* once we have ghost/mutable fields in algebraics, don't forget to check here that they coincide, too *) Loc.try2 id.id_loc ity_equal_check ty ity; @@ -353,7 +353,7 @@ let add_types uc tdl = option_apply false check ts.its_def in let check (pv,_) = - let vtv = vtv_of_pv pv in + let vtv = pv.pv_vtv in vtv.vtv_ghost || vtv.vtv_mut <> None || check vtv.vtv_ity in let is_impure_data (ts,csl) = is_impure_type ts ||