123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262(** This module provides a function to translate a simply typed signature to
the XTC format used in the termination competition.
@see <https://raw.githubusercontent.com/TermCOMP/TPDB/master/xml/xtc.xsd>
Remarks:
- SizeChangeTool accepts an extension of the XTC format with lambda and
application in types and:
<arrow> <var>...</var> <type>...</type> <type>...</type> </arrow>
<typeLevelRule> <TLlhs>...</TLlhs> <TLrhs>...</TLrhs> </typeLevelRule>
*)openLplibopenBaseopenExtraopenCoreopenTermopenCommonopenError(** [syms] maps every symbol to a name. *)letsyms=refSymMap.empty(** [bvars] is the set of abstracted variables. *)letbvars=refStrSet.empty(** [nb_rules] is the number of rewrite rules. *)letnb_rules=ref0(** [pvars] is the list of all pattern variables with their type. *)letpvars=ref[](** [typ] is a reference to the types of the pvars of the current rules. *)lettype_of_pvar=ref[||](** [sym_name s] translates the symbol name of [s]. *)letsym_name:sympp=funppfs->outppf"%a.%s"Path.pps.sym_paths.sym_name(** [add_sym] declares a Lambdapi symbol. *)letadd_sym:sym->unit=funs->syms:=SymMap.adds(Format.asprintf"%a"sym_names)!syms(** [type_sym ppf s] translates the Lambdapi type symbol [s]. *)lettype_sym:sympp=funppfs->outppf"<type><basic>%a</basic></type>"sym_names(** [sym ppf s] translates the Lambdapi symbol [s]. *)letsym:sympp=funppfs->outppf"<name>%s</name>"(trySymMap.finds!symswithNot_found->assertfalse)(** [add_bvar v] declares an abstracted Lambdapi variable. *)letadd_bvar:var->unit=funv->bvars:=StrSet.add(base_namev)!bvars(** [bvar v] translates the Lambdapi bound variable [v]. *)letbvar:varpp=funppfv->outppf"<var>%s</var>"(base_namev)(** [pvar i] translates the Lambdapi pattern variable [i]. *)letpvar:intpp=funppfi->outppf"<var>%d_%d</var>"!nb_rulesi(** [term ppf t] translates the term [t]. *)letrecterm:termpp=funppft->leth,ts=get_argstinmatchhwith|SymbswhenLibTerm.is_kindTimed.(!(s.sym_type))->fatals.sym_pos"Type symbol in a term."|Symbs->add_syms;letargppft=outppf"<arg>%a</arg>"termtinoutppf"<funapp>%a%a</funapp>"syms(List.pparg"")ts|_->matchtswith|[]->headppfh|t::ts->letrecargs:(term*termlist)pp=funppf(t,ts)->matchtswith|[]->termppft|u::us->outppf"<application>%a%a</application>"termtargs(u,us)inoutppf"<application>%a%a</application>"headhargs(t,ts)andhead:termpp=funppft->matchunfoldtwith|Meta_->assertfalse|Plac_->assertfalse|TRef_->assertfalse|Bvar_->assertfalse|Wild->assertfalse|Kind->assertfalse|Type->assertfalse|Variv->bvarppfv|Symb_->assertfalse(* done in term *)|Patt(None,_,_)->assertfalse|Patt(Somei,_,ts)->pvar_appppf(i,ts)|Appl(t,u)->outppf"<application>%a%a</application>"termttermu|Abst(a,b)->letx,b=unbindbinadd_bvarx;outppf"<lambda>%a%a%a</lambda>"bvarxtypatermb|Prod_->assertfalse|LLet(a,t,b)->termppf(mk_Appl(mk_Abst(a,b),t))andpvar_app:(int*termarray)pp=funppf(i,ts)->letarity=Array.lengthtsinletrecargppfk=ifk<0thenpvarppfielseoutppf"<application>%a%a</application>"arg(k-1)termts.(k)inargppf(arity-1)andtyp:termpp=funppft->matchunfoldtwith|Meta_->assertfalse|Plac_->assertfalse|TRef_->assertfalse|Bvar_->assertfalse|Wild->assertfalse|Kind->assertfalse|Type->assertfalse|Vari_->assertfalse|Symbs->type_symppfs|Patt(None,_,_)->assertfalse|Patt(Somei,_,[||])->typppf!type_of_pvar.(i)|Patt(Some_,_,_)->assertfalse|Appl_->fatal_no_pos"Dependent type."|Abst_->fatal_no_pos"Dependent type."|Prod(a,b)->ifbinder_occurbthenfatal_no_pos"Dependent type."elseletx,b=unbindbinadd_bvarx;outppf"<type><arrow>%a%a</arrow></type>"typatypb|LLet(_,t,b)->typppf(substbt)(** [add_pvars s r] adds the types of the pvars of [r] in [pvars]. *)letadd_pvars:sym->rule->unit=funsr->letn=r.vars_nbin(* Generate n fresh variables and n fresh metas for their types. *)letvar=Array.initn(new_var_ind"$")inletp=new_problem()intype_of_pvar:=Array.initn(fun_->LibMeta.makep[]mk_Type);(* Replace in lhs pattern variables by variables. *)letrecsubst_pattt=matchunfoldtwith|Type->assertfalse|Kind->assertfalse|Bvar_->assertfalse|Meta_->assertfalse|Plac_->assertfalse|TRef_->assertfalse|Wild->assertfalse|Prod_->assertfalse|LLet_->assertfalse|Vari_|Symb_->t|Abst(a,b)->beginmatchunfoldawith|Patt(Somei,_,[||])->letx,b=unbindbinmk_Abst(!type_of_pvar.(i),bind_varx(subst_pattb))|Patt(Some_,_,_)->assertfalse(*FIXME*)|_->assertfalseend|Appl(a,b)->mk_Appl(subst_patta,subst_pattb)|Patt(None,_,_)->assertfalse|Patt(Somei,_,ts)->Array.fold_left(funacct->mk_Appl(acc,t))(mk_Varivar.(i))tsinletlhs=List.fold_left(funht->mk_Appl(h,subst_pattt))(mk_Symbs)r.lhsin(* Create a typing context mapping every variable to its type. *)letctx=Array.to_list(Array.mapi(funiv->v,!type_of_pvar.(i),None)var)in(* Infer the type of lhs in ctx. *)(*Logger.set_debug true "+iu"; Console.set_flag "print_domaines" true;*)matchInfer.infer_noexnpctxlhswith|None->assertfalse|Some_->(* Solve constraints. *)ifUnif.solve_noexn~type_check:falsepthen(* Add the infered type of each pvar. *)fori=0ton-1dopvars:=(!nb_rules,i,!type_of_pvar.(i))::!pvarsdoneelsefatal_no_pos"Cannot infer the type of %a"Print.sym_rule(s,r)(** [rule ppf r] translates the pair of terms [r] as a rule. *)letrule:(term*term)pp=funppf(l,r)->outppf"
<rule>
<lhs>
%a
</lhs>
<rhs>
%a
</rhs>
</rule>"termltermr(** [sym_rule ppf s r] increases the number of rules and translates the
sym_rule [r]. *)letsym_rule:sym->rulepp=funsppfr->incrnb_rules;add_pvarssr;letsr=s,rinruleppf(lhssr,rhssr)(** Translate the rules of symbol [s]. *)letrules_of_sym:sympp=funppfs->matchTimed.(!(s.sym_def))with|Somed->ruleppf(mk_Symbs,d)|None->List.iter(sym_rulesppf)Timed.(!(s.sym_rules))(** Translate the rules of a dependency except if it is a ghost signature. *)letrules_of_sign:Sign.tpp=funppfsign->ifsign!=Sign.Ghost.signthenStrMap.iter(fun_->rules_of_symppf)Timed.(!(sign.sign_symbols))(** [sign ppf s] translates the Lambdapi signature [s]. *)letsign:Sign.tpp=funppfsign->(* First, generate the RULES section in a buffer, because it generates data
necessary for the other sections. *)letbuf_rules=Buffer.create1000inletppf_rules=Format.formatter_of_bufferbuf_rulesinSign.iterate(rules_of_signppf_rules)sign;Format.pp_print_flushppf_rules();(* Function for printing the types of function symbols. *)letpp_syms:stringSymMap.tpp=funppfsyms->letsym_decl:(sym*string)pp=funppf(s,n)->outppf"
<funcDeclaration>
<name>%s</name>
<typeDeclaration>%a</typeDeclaration>
</funcDeclaration>"ntypTimed.(!(s.sym_type))inletsym_declsn=sym_declppf(s,n)inSymMap.itersym_declsymsin(* Function for printing the types of pattern variables. *)letpp_pvars:(int*int*term)listpp=funppfpvars->letpvar_decl(n,i,t)=outppf"
<varDeclaration>
<var>$%d_%d</var>
%a
</varDeclaration>"nityptinList.iterpvar_declpvarsin(* Finally, generate the whole hrs file. *)outppf"\
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<?xml-stylesheet href=\"xtc2tpdb.xsl\" type=\"text/xsl\"?>
<problem xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \
type=\"termination\" \
xsi:noNamespaceSchemaLocation=\"http://dev.aspsimon.org/xtc.xsd\">
<trs>
<rules>%s
</rules>
<higherOrderSignature>
<variableTypeInfo>%a
</variableTypeInfo>
<functionSymbolTypeInfo>%a
</functionSymbolTypeInfo>
</higherOrderSignature>
</trs>
<strategy>FULL</strategy>
<metainformation>
<originalfilename>%a.lp</originalfilename>
</metainformation>
</problem>\n"(Buffer.contentsbuf_rules)pp_pvars!pvarspp_syms!symsPath.ppsign.sign_path