123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246(* This file is free software, part of Zipperposition. See file "license" for more details. *)(** {1 Utils for TIP} *)openLogtkmoduleE=CCResultmoduleA=Tip_astmoduleUA=UntypedASTmoduleT=STermtypeparser_res=(A.statementIter.t,string)E.ttype'aparser_='a->parser_resletparse_lexbuf_lex=letl=Tip_parser.parse_listTip_lexer.tokenlexinIter.of_listlletparse_lexbuffile:parser_res=tryparse_lexbuf_file|>E.returnwithe->E.of_exneletparse_stdin():parser_res=letlexbuf=Lexing.from_channelstdininParseLocation.set_filelexbuf"stdin";parse_lexbuflexbufletparse_filefile:parser_res=iffile="stdin"thenparse_stdin()elsetryCCIO.with_infile(funic->letlexbuf=Lexing.from_channelicinParseLocation.set_filelexbuffile;parse_lexbuf_lexbuf)|>E.returnwith|Sys_errore->CCResult.fail(Util.err_spf"sys_error when parsing `%s`:@ %s"filee)|e->E.of_exneletconv_loc(loc:A.Loc.t):ParseLocation.t=let{A.Loc.file;start_line;start_column;stop_line;stop_column}=locinParseLocation.mkfilestart_linestart_columnstop_linestop_columnletrecconv_tyty=matchtywith|A.Ty_bool->T.prop|A.Ty_arrow(args,ret)->T.fun_ty(List.mapconv_tyargs)(conv_tyret)|A.Ty_app("Int",[])->T.builtinBuiltin.TyInt|A.Ty_app("Rat",[])->T.builtinBuiltin.TyRat|A.Ty_app(s,[])->T.vars(* var or const: let type inference decide *)|A.Ty_app(s,args)->T.app(T.vars)(List.mapconv_tyargs)letapp?locxy=T.app?locx[y]letconv_tyvarv=T.Vv,SomeT.tTypeletconv_var(v,ty)=T.Vv,Some(conv_tyty)letconv_vars=List.mapconv_var(* left-associative *)letrecapp_reducefzerol=matchlwith|[]->zero|[x]->x|[x;y]->T.app_builtinf[x;y]|x::y::tail->app_reducefzero(T.app_builtinf[x;y]::tail)moduleBA=Builtin.Arithletzero=T.int_Z.zeroletone=T.int_Z.oneletplus_l=app_reduceBA.sumzeroletminus_l=app_reduceBA.differencezeroletprod_l=app_reduceBA.productoneletquotient_l=app_reduceBA.quotient_eoneletas_ints=trySome(Z.of_strings)with_->Noneletas_rats=trySome(Q.of_strings)with_->Noneletrecconv_term(t:A.term):T.t=matchtwith|A.True->T.true_|A.False->T.false_|A.App(s,[])|A.Consts->(* look for integer constants, but otherwise
let type inference distinguish constants and variables *)beginmatchas_ints,as_ratswith|Somez,_->T.int_z|None,Someq->T.ratq|None,None->T.varsend|A.App(f,l)->letl=List.mapconv_termlinbeginmatchf,lwith|"+",_->plus_ll|"-",_->minus_ll|"*",_->prod_ll|"/",_->quotient_ll|">=",[a;b]->T.app_builtinBA.greatereq[a;b]|"<=",[a;b]->T.app_builtinBA.lesseq[a;b]|">",[a;b]->T.app_builtinBA.greater[a;b]|"<",[a;b]->T.app_builtinBA.less[a;b]|"mod",[a;b]->T.app_builtinBA.remainder_e[a;b]|"div",[a;b]->T.app_builtinBA.quotient_e[a;b]|_->T.app_constflend|A.HO_app(a,b)->app(conv_terma)(conv_termb)|A.If(a,b,c)->T.ite(conv_terma)(conv_termb)(conv_termc)|A.Distinctl->l|>List.rev_mapconv_term|>CCList.diagonal|>List.rev_map(fun(a,b)->T.neqab)|>T.and_?loc:None|A.Match(u,l)->letu=conv_termuinletl=List.map(function|A.Match_defaultt->T.Match_default(conv_termt)|A.Match_case(s,vars,t)->letvars=List.map(funv->T.Vv)varsinT.Match_case(s,vars,conv_termt))linT.match_ul|A.Let(l,u)->letl=List.map(fun(v,t)->T.Vv,conv_termt)linletu=conv_termuinT.let_lu|A.Fun(v,t)->letv=conv_varvinlett=conv_termtinT.lambda[v]t|A.Eq(a,b)->T.eq(conv_terma)(conv_termb)|A.Imply(a,b)->T.imply(conv_terma)(conv_termb)|A.Andl->T.and_(List.mapconv_terml)|A.Orl->T.or_(List.mapconv_terml)|A.Nota->T.not_(conv_terma)|A.Forall(vars,body)->letvars=conv_varsvarsinletbody=conv_termbodyinT.forallvarsbody|A.Exists(vars,body)->letvars=conv_varsvarsinletbody=conv_termbodyinT.existsvarsbody|A.Cast(a,_)->conv_termaletconv_decl(d:A.tyA.fun_decl):string*T.t=lettyvars=List.mapconv_tyvard.A.fun_ty_varsinletty_args=List.mapconv_tyd.A.fun_argsinletty_ret=conv_tyd.A.fun_retinletty=T.forall_tytyvars(T.fun_tyty_argsty_ret)ind.A.fun_name,ty(* return [f, vars, ty_f] *)letconv_def(d:A.typed_varA.fun_decl):string*T.typed_varlist*T.t=lettyvars=List.mapconv_tyvard.A.fun_ty_varsinletvars=List.mapconv_vard.A.fun_argsinletty_args=List.map(CCFun.composesndconv_ty)d.A.fun_argsinletty_ret=conv_tyd.A.fun_retinletty=T.forall_tytyvars(T.fun_tyty_argsty_ret)ind.A.fun_name,tyvars@vars,tyletconv_def?locdeclbody=(* translate into definitions *)letf,vars,ty_f=conv_defdeclinletvars_as_t=List.map(function|T.Wildcard,_->assertfalse|T.Vs,_->T.vars)varsinletdef=letbody=conv_termbodyinT.forall?locvars(T.eq?loc(T.app_const?locfvars_as_t)body)inUA.mk_deffty_f[def]letconvert(st:A.statement):UA.statementlist=letloc=CCOpt.mapconv_locst.A.locinUtil.debugf3"@[<2>convert TIP statement@ @[%a@]@,%a@]"(funk->kA.pp_stmtstParseLocation.pp_optloc);matchst.A.stmtwith|A.Stmt_decl_sort(s,i)->letty=T.fun_ty(CCList.initi(fun_->T.tType))T.tTypein[UA.decl?locsty]|A.Stmt_decld->lets,ty=conv_decldin[UA.decl?locsty]|A.Stmt_assertt->lett=conv_termtin[UA.assert_?loct]|A.Stmt_lemmat->lett=conv_termtin[UA.lemma?loct]|A.Stmt_assert_not(tyvars,g)->(* goal *)lettyvars=List.mapconv_tyvartyvarsinletg=conv_termginletg=T.forall?loctyvarsgin[UA.goal?locg]|A.Stmt_data(tyvars,l)->letl=List.map(fun(id,cstors)->letcstors=List.map(func->letargs=c.A.cstor_args|>List.map(CCPair.mapCCOpt.returnconv_ty)inc.A.cstor_name,args)cstorsin{UA.data_name=id;data_vars=tyvars;data_cstors=cstors;})lin[UA.data?locl]|A.Stmt_check_sat->[](* trivial *)|A.Stmt_fun_deffr|A.Stmt_fun_recfr->(* translate into definitions *)letl=[conv_def?locfr.A.fr_declfr.A.fr_body]in[UA.def?locl]|A.Stmt_funs_rec{A.fsr_decls;fsr_bodies}->assert(List.lengthfsr_decls=List.lengthfsr_bodies);letl=List.map2(conv_def?loc)fsr_declsfsr_bodiesin[UA.def?locl]letconvert_seq=Iter.flat_map_lconvert