123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115(* This file is part of the Catala compiler, a specification language for tax
and social benefits computation rules. Copyright (C) 2020-2022 Inria,
contributor: Louis Gesbert <louis.gesbert@inria.fr>
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy of
the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License. *)openCatala_utilsopenDefinitions(** {1 Variables and their collections} *)(** This module provides types and helpers for Bindlib variables on the [gexpr]
type *)type'et=('a,'t)naked_gexprBindlib.varconstraint'e=('a,'t)gexprtype'evars=('a,'t)naked_gexprBindlib.mvarconstraint'e=('a,'t)gexprletmake(name:string):'et=Bindlib.new_var(funx->EVarx)nameletcompare=Bindlib.compare_varsletequal=Bindlib.eq_varslethash=Bindlib.hash_varlettranslate(v:'e1t):'e2t=Bindlib.copy_varv(funx->EVarx)(Bindlib.name_ofv)type'evar='et(* The purpose of this module is just to lift a type parameter outside of
[Set.S] and [Map.S], so that we can have ['e Var.Set.t] for sets of variables
bound to the ['e = ('a, 't) gexpr] expression type. This is made possible by
the fact that [Bindlib.compare_vars] is polymorphic in that parameter; we
first hide that parameter inside an existential, then re-add a phantom type
outside of the set to ensure consistency. Extracting the elements is then
done with [Bindlib.copy_var] but technically it's not much different from an
[Obj] conversion.
If anyone has a better solution, besides a copy-paste of Set.Make / Map.Make
code... *)moduleGeneric=struct(* Existentially quantify the type parameters to allow application of
Set.Make *)typet=Var:'evar->t(* Note: adding [[@@ocaml.unboxed]] would be OK and make our wrappers live at
the type-level without affecting the actual data representation. But
[Bindlib.var] being abstract, we can't convince OCaml it's ok at the moment
and have to hold it *)lettv=Varvletget(Varv)=Bindlib.copy_varv(funx->EVarx)(Bindlib.name_ofv)letcompare(Varx)(Vary)=Bindlib.compare_varsxyleteq(Varx)(Vary)=Bindlib.eq_varsxy[@@ocaml.warning"-32"]letformatppfv=String.formatppf(Bindlib.name_of(getv))end(* Wrapper around Set.Make to re-add type parameters (avoid inconsistent
sets) *)moduleSet=structopenGenericopenSet.Make(Generic)typenonrec'et=tletempty=emptyletsingletonx=singleton(tx)letaddxs=add(tx)sletremovexs=remove(tx)sletunions1s2=unions1s2letmemxs=mem(tx)sletof_listl=of_list(List.maptl)letelementss=elementss|>List.mapgetletdiffs1s2=diffs1s2letiterfs=iter(funx->f(getx))s(* Add more as needed *)end(* Wrapper around Map.Make to re-add type parameters (avoid inconsistent
maps) *)moduleMap=structopenGenericmoduleM=Map.Make(Generic)openMtypek0=M.keyexceptionNot_found=M.Not_foundtypenonrec('e,'x)t='xtletempty=emptyletsingletonvx=singleton(tv)xletaddvxm=add(tv)xmletupdatevfm=update(tv)fmletfindvm=find(tv)mletfind_optvm=find_opt(tv)mletbindingsm=bindingsm|>List.map(fun(v,x)->getv,x)letmemxm=mem(tx)mletunionfm1m2=union(funvx1x2->f(getv)x1x2)m1m2letfoldfmacc=fold(funvxacc->f(getv)xacc)maccletkeysm=keysm|>List.mapgetletvaluesm=valuesmletformat_keys?pp_sepm=format_keys?pp_sepm(* Add more as needed *)end