Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New vernacular command: theory aliases #685

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/ecCommands.ml
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,11 @@ and process_th_clone (scope : EcScope.scope) thcl =
EcScope.Cloning.clone scope (Pragma.get ()).pm_check thcl

(* -------------------------------------------------------------------- *)
and process_th_alias (scope : EcScope.scope) (thcl : psymbol * pqsymbol) =
EcScope.check_state `InTop "theory alias" scope;
EcScope.Theory.alias scope thcl

(* -------------------------------------------------------------------- *)
and process_mod_import (scope : EcScope.scope) mods =
EcScope.check_state `InTop "module var import" scope;
List.fold_left EcScope.Mod.import scope mods
Expand Down Expand Up @@ -730,6 +735,7 @@ and process (ld : Loader.loader) (scope : EcScope.scope) g =
| GthImport name -> `Fct (fun scope -> process_th_import scope name)
| GthExport name -> `Fct (fun scope -> process_th_export scope name)
| GthClone thcl -> `Fct (fun scope -> process_th_clone scope thcl)
| GthAlias als -> `Fct (fun scope -> process_th_alias scope als)
| GModImport mods -> `Fct (fun scope -> process_mod_import scope mods)
| GsctOpen name -> `Fct (fun scope -> process_sct_open scope name)
| GsctClose name -> `Fct (fun scope -> process_sct_close scope name)
Expand Down
2 changes: 1 addition & 1 deletion src/ecCorePrinting.ml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ module type PrinterAPI = sig
val pp_tyname : PPEnv.t -> path pp
val pp_axname : PPEnv.t -> path pp
val pp_tcname : PPEnv.t -> path pp
val pp_thname : PPEnv.t -> path pp
val pp_thname : ?alias:bool -> PPEnv.t -> path pp

val pp_mem : PPEnv.t -> EcIdent.t pp
val pp_memtype : PPEnv.t -> EcMemory.memtype pp
Expand Down
48 changes: 38 additions & 10 deletions src/ecEnv.ml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ type preenv = {
env_atbase : (path list Mint.t) Msym.t;
env_redbase : mredinfo;
env_ntbase : ntbase Mop.t;
env_albase : path Mp.t; (* theory aliases *)
env_modlcs : Sid.t; (* declared modules *)
env_item : theory_item list; (* in reverse order *)
env_norm : env_norm ref;
Expand Down Expand Up @@ -308,6 +309,7 @@ let empty gstate =
env_atbase = Msym.empty;
env_redbase = Mrd.empty;
env_ntbase = Mop.empty;
env_albase = Mp.empty;
env_modlcs = Sid.empty;
env_item = [];
env_norm = ref empty_norm_cache;
Expand Down Expand Up @@ -632,9 +634,9 @@ module MC = struct
(IPPath (root env))
env.env_comps; }

let import up p obj env =
let name = ibasename p in
{ env with env_current = up env.env_current name (p, obj) }
let import ?name up p obj env =
let name = odfl (ibasename p) name in
{ env with env_current = up env.env_current name (p, obj) }

(* -------------------------------------------------------------------- *)
let lookup_var qnx env =
Expand Down Expand Up @@ -972,20 +974,20 @@ module MC = struct
| None -> lookup_error (`QSymbol qnx)
| Some (p, (args, obj)) -> (_downpath_for_th env p args, obj)

let import_theory p th env =
import (_up_theory true) (IPPath p) th env
let import_theory ?name p th env =
import ?name (_up_theory true) (IPPath p) th env

(* -------------------------------------------------------------------- *)
let _up_mc candup mc p =
let name = ibasename p in
let _up_mc ?name candup mc p =
let name = odfl (ibasename p) name in
if not candup && MMsym.last name mc.mc_components <> None then
raise (DuplicatedBinding name);
{ mc with mc_components =
MMsym.add name p mc.mc_components }

let import_mc p env =
let mc = _up_mc true env.env_current p in
{ env with env_current = mc }
let import_mc ?name p env =
let mc = _up_mc ?name true env.env_current p in
{ env with env_current = mc }

(* ------------------------------------------------------------------ *)
let rec mc_of_module_r (p1, args, p2, lc) me =
Expand Down Expand Up @@ -1105,6 +1107,10 @@ module MC = struct
| Th_baserw (x, _) ->
(add2mc _up_rwbase x (expath x) mc, None)

| Th_alias _ ->
(* FIXME:ALIAS *)
(mc, None)

| Th_export _ | Th_addrw _ | Th_instance _
| Th_auto _ | Th_reduction _ ->
(mc, None)
Expand Down Expand Up @@ -2852,6 +2858,25 @@ module Theory = struct
else
Option.get (Mp.find_opt p env.env_thenvs)

(* ------------------------------------------------------------------ *)
let rebind_alias (name : symbol) (path : path) (env : env) =
let th = by_path path env in
let src = EcPath.pqname (root env) name in
let env = MC.import_theory ~name path th env in
let env = MC.import_mc ~name (IPPath path) env in
let env = { env with env_albase = Mp.add path src env.env_albase } in
env

(* ------------------------------------------------------------------ *)
let alias ?(import = import0) (name : symbol) (path : path) (env : env) =
let env =
if import.im_immediate then rebind_alias name path env else env in
{ env with env_item = mkitem import (Th_alias (name, path)) :: env.env_item }

(* ------------------------------------------------------------------ *)
let aliases (env : env) =
env.env_albase

(* ------------------------------------------------------------------ *)
let rec bind_instance_th path inst cth =
List.fold_left (bind_instance_th_item path) inst cth
Expand Down Expand Up @@ -3054,6 +3079,9 @@ module Theory = struct
| Th_baserw (x, _) ->
MC.import_rwbase (xpath x) env

| Th_alias (name, path) ->
rebind_alias name path env

| Th_addrw _ | Th_instance _ | Th_auto _ | Th_reduction _ ->
env

Expand Down
3 changes: 3 additions & 0 deletions src/ecEnv.mli
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@ module Theory : sig
-> EcTypes.is_local
-> EcTheory.thmode
-> env -> compiled_theory option

val alias : ?import:import -> symbol -> path -> env -> env
val aliases : env -> path Mp.t
end

(* -------------------------------------------------------------------- *)
Expand Down
10 changes: 9 additions & 1 deletion src/ecParser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -1964,7 +1964,7 @@ theory_clear_items:
| xs=theory_clear_item1* { xs }

theory_open:
| loca=is_local b=boption(ABSTRACT) THEORY x=uident
| loca=is_local b=iboption(ABSTRACT) THEORY x=uident
{ (loca, b, x) }

theory_close:
Expand Down Expand Up @@ -3620,6 +3620,13 @@ realize:
| REALIZE x=qident BY bracket(empty)
{ { pr_name = x; pr_proof = Some None; } }


(* -------------------------------------------------------------------- *)
(* Theory aliasing *)

theory_alias: (* FIXME: THEORY ALIAS -> S/R conflict *)
| THEORY name=uident EQ target=uqident { (name, target) }

(* -------------------------------------------------------------------- *)
(* Printing *)
print:
Expand Down Expand Up @@ -3739,6 +3746,7 @@ global_action:
| theory_export { GthExport $1 }
| theory_clone { GthClone $1 }
| theory_clear { GthClear $1 }
| theory_alias { GthAlias $1 }
| module_import { GModImport $1 }
| section_open { GsctOpen $1 }
| section_close { GsctClose $1 }
Expand Down
1 change: 1 addition & 0 deletions src/ecParsetree.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,7 @@ type global_action =
| GthImport of pqsymbol list
| GthExport of pqsymbol list
| GthClone of theory_cloning
| GthAlias of (psymbol * pqsymbol)
| GModImport of pmsymbol located list
| GsctOpen of osymbol_r
| GsctClose of osymbol_r
Expand Down
53 changes: 38 additions & 15 deletions src/ecPrinting.ml
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,18 @@ module PPEnv = struct
(fun env x -> EcEnv.Mod.bind_param x mty env)
ppe.ppe_env xs; }

let p_shorten cond p =
let reverse_theory_alias (ppe : t) (path : P.path) : P.path =
let aliases = EcEnv.Theory.aliases ppe.ppe_env in

let rec reverse (suffix : symbol list) (p : P.path option) =
Option.bind p (fun prefix ->
match P.Mp.find_opt prefix aliases with
| None -> reverse (P.basename prefix :: suffix) (P.prefix prefix)
| Some prefix -> Some (EcPath.extend prefix suffix)
)
in Option.value ~default:path (reverse [] (Some path))

let p_shorten ?(alias = true) ?(istheory = false) (ppe : t) (cond : qsymbol -> bool) (p : P.path) =
let rec shorten prefix (nm, x) =
match cond (nm, x) with
| true -> (nm, x)
Expand All @@ -154,36 +165,45 @@ module PPEnv = struct
end
in

let p =
if alias then begin
if istheory then
reverse_theory_alias ppe p
else
let thpath, base = P.prefix p, P.basename p in
let thpath = Option.map (reverse_theory_alias ppe) thpath in
P.pqoname thpath base
end else p in
let (nm, x) = P.toqsymbol p in
shorten (List.rev nm) ([], x)

let ty_symb (ppe : t) p =
let exists sm =
let exists sm =
try EcPath.p_equal (EcEnv.Ty.lookup_path ~unique:true sm ppe.ppe_env) p
with EcEnv.LookupFailure _ -> false
in
p_shorten exists p
p_shorten ppe exists p

let tc_symb (ppe : t) p =
let exists sm =
let exists sm =
try EcPath.p_equal (EcEnv.TypeClass.lookup_path sm ppe.ppe_env) p
with EcEnv.LookupFailure _ -> false
in
p_shorten exists p
p_shorten ppe exists p

let rw_symb (ppe : t) p =
let exists sm =
let exists sm =
try EcPath.p_equal (EcEnv.BaseRw.lookup_path sm ppe.ppe_env) p
with EcEnv.LookupFailure _ -> false
in
p_shorten exists p
p_shorten ppe exists p

let ax_symb (ppe : t) p =
let exists sm =
let exists sm =
try EcPath.p_equal (EcEnv.Ax.lookup_path sm ppe.ppe_env) p
with EcEnv.LookupFailure _ -> false
in
p_shorten exists p
p_shorten ppe exists p

let op_symb (ppe : t) p info =
let specs = [1, EcPath.pqoname (EcPath.prefix EcCoreLib.CI_Bool.p_eq) "<>"] in
Expand Down Expand Up @@ -221,21 +241,21 @@ module PPEnv = struct
(* FIXME: for special operators, do check `info` *)
if List.exists (fun (_, sp) -> EcPath.p_equal sp p) specs
then ([], EcPath.basename p)
else p_shorten exists p
else p_shorten ppe exists p

let ax_symb (ppe : t) p =
let exists sm =
try EcPath.p_equal (EcEnv.Ax.lookup_path sm ppe.ppe_env) p
with EcEnv.LookupFailure _ -> false
in
p_shorten exists p
p_shorten ppe exists p

let th_symb (ppe : t) p =
let th_symb ?alias (ppe : t) p =
let exists sm =
try EcPath.p_equal (EcEnv.Theory.lookup_path sm ppe.ppe_env) p
with EcEnv.LookupFailure _ -> false
in
p_shorten exists p
p_shorten ?alias ~istheory:true ppe exists p

let rec mod_symb (ppe : t) mp : EcSymbols.msymbol =
let (nm, x, p2) =
Expand Down Expand Up @@ -477,8 +497,8 @@ let pp_axname ppe fmt p =
Format.fprintf fmt "%a" EcSymbols.pp_qsymbol (PPEnv.ax_symb ppe p)

(* -------------------------------------------------------------------- *)
let pp_thname ppe fmt p =
EcSymbols.pp_qsymbol fmt (PPEnv.th_symb ppe p)
let pp_thname ?alias ppe fmt p =
EcSymbols.pp_qsymbol fmt (PPEnv.th_symb ?alias ppe p)

(* -------------------------------------------------------------------- *)
let pp_funname (ppe : PPEnv.t) fmt p =
Expand Down Expand Up @@ -3509,6 +3529,9 @@ let rec pp_theory ppe (fmt : Format.formatter) (path, cth) =
lvl (odfl "" base)
(pp_list "@ " (pp_axname ppe)) p

| EcTheory.Th_alias (name, target) ->
Format.fprintf fmt "theory %s = %a." name (pp_thname ~alias:false ppe) target

(* -------------------------------------------------------------------- *)
let pp_stmt_with_nums (ppe : PPEnv.t) fmt stmt =
let ppnode = collect2_s ppe stmt.s_node [] in
Expand Down
11 changes: 11 additions & 0 deletions src/ecScope.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2152,7 +2152,18 @@ module Theory = struct
raise (ImportError (None, name.rqd_name, e))
end

(* -------------------------------------------------------------------- *)
let required scope = scope.sc_required

(* -------------------------------------------------------------------- *)
let alias (scope : scope) ?(import = EcTheory.import0) ((name, target) : psymbol * pqsymbol) =
let thpath = EcEnv.Theory.lookup_opt (unloc target) (env scope) in
let thpath, _ = ofdfl (fun () ->
hierror ~loc:(loc target) "unknown theory: %a" pp_qsymbol (unloc target)
) thpath in
let item = EcTheory.mkitem import (Th_alias (unloc name, thpath)) in

{ scope with sc_env = EcSection.add_item item scope.sc_env }
end

(* -------------------------------------------------------------------- *)
Expand Down
4 changes: 4 additions & 0 deletions src/ecScope.mli
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ module Theory : sig
val add_clears : (pqsymbol option) list -> scope -> scope

val required : scope -> required

(* [alias scope (name, thname)] create a theory alias [name] to
* [thname] *)
val alias : scope -> ?import:EcTheory.import -> psymbol * pqsymbol -> scope
end

(* -------------------------------------------------------------------- *)
Expand Down
4 changes: 4 additions & 0 deletions src/ecSection.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,7 @@ let rec set_local_item item =
| Th_addrw (p,ps,lc) -> Th_addrw (p, ps, set_local lc)
| Th_reduction r -> Th_reduction r
| Th_auto (i,s,p,lc) -> Th_auto (i, s, p, set_local lc)
| Th_alias alias -> Th_alias alias

in { item with ti_item = lcitem }

Expand Down Expand Up @@ -1348,6 +1349,7 @@ let add_item_ (item : theory_item) (scenv:scenv) =
| Th_baserw (s,lc) -> EcEnv.BaseRw.add s lc env
| Th_addrw (p,ps,lc) -> EcEnv.BaseRw.addto p ps lc env
| Th_auto (level, base, ps, lc) -> EcEnv.Auto.add ~level ?base ps lc env
| Th_alias (n,p) -> EcEnv.Theory.alias n p env
| Th_reduction r -> EcEnv.Reduction.add r env
| _ -> assert false
in
Expand Down Expand Up @@ -1376,6 +1378,7 @@ let rec generalize_th_item (to_gen : to_gen) (prefix : path) (th_item : theory_i
| Th_addrw (p,ps,lc) -> generalize_addrw to_gen (p, ps, lc)
| Th_reduction rl -> generalize_reduction to_gen rl
| Th_auto hints -> generalize_auto to_gen hints
| Th_alias _ -> (to_gen, None) (* FIXME:ALIAS *)

in

Expand Down Expand Up @@ -1498,6 +1501,7 @@ let check_item scenv item =
hierror "local hint can only be declared inside section";
| Th_reduction _ -> ()
| Th_theory _ -> assert false
| Th_alias _ -> () (* FIXME:ALIAS *)

let rec add_item (item : theory_item) (scenv : scenv) =
let item = if scenv.sc_loca = `Local then set_local_item item else item in
Expand Down
3 changes: 3 additions & 0 deletions src/ecSubst.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,9 @@ let rec subst_theory_item_r (s : subst) (item : theory_item_r) =
| Th_auto (lvl, base, ps, lc) ->
Th_auto (lvl, base, List.map (subst_path s) ps, lc)

| Th_alias (name, target) ->
Th_alias (name, subst_path s target)

(* -------------------------------------------------------------------- *)
and subst_theory (s : subst) (items : theory) =
List.map (subst_theory_item s) items
Expand Down
1 change: 1 addition & 0 deletions src/ecThCloning.ml
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@ end = struct
| Th_addrw _ -> (proofs, evc)
| Th_reduction _ -> (proofs, evc)
| Th_auto _ -> (proofs, evc)
| Th_alias _ -> (proofs, evc)

and doit prefix (proofs, evc) dth =
doit_r prefix (proofs, evc) dth.ti_item
Expand Down
1 change: 1 addition & 0 deletions src/ecTheory.ml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ and theory_item_r =
| Th_addrw of EcPath.path * EcPath.path list * is_local
| Th_reduction of (EcPath.path * rule_option * rule option) list
| Th_auto of (int * symbol option * path list * is_local)
| Th_alias of (symbol * path) (* FIXME: currently, only theories *)

and thsource = {
ths_base : EcPath.path;
Expand Down
1 change: 1 addition & 0 deletions src/ecTheory.mli
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ and theory_item_r =
(* reduction rule does not survive to section so no locality *)
| Th_reduction of (EcPath.path * rule_option * rule option) list
| Th_auto of (int * symbol option * path list * is_local)
| Th_alias of (symbol * path)

and thsource = {
ths_base : EcPath.path;
Expand Down
Loading