123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113(* This file is free software, part of dolmen. See file "LICENSE" for more information *)(* Value definition *)(* ************************************************************************* *)typet=Z.tletcompare=Z.compareletprintfmtz=Format.fprintffmt"Z:%a"Z.pp_printzletops:tValue.ops=Value.ops~compare~print()(* Configuration for corner cases *)(* ************************************************************************* *)exceptionModulo_by_zeroexceptionDivision_by_zero(* Helper functions on unbounded integers *)(* ************************************************************************* *)letceilx=Z.cdivx.Q.numx.Q.denletfloorx=Z.fdivx.Q.numx.Q.denlettruncatex=Z.divx.Q.numx.Q.den(* it is truncated toward zero *)letdiv_eab=lets=Z.signbinletd=Q.div(Q.of_biginta)(Q.of_bigintb)inifs>0thenfloordelseceildletmod_eab=Z.suba(Z.mul(div_eab)b)letdiv_fab=floor(Q.div(Q.of_biginta)(Q.of_bigintb))letmod_fab=Z.suba(Z.mul(div_fab)b)letdiv_tab=truncate(Q.div(Q.of_biginta)(Q.of_bigintb))letmod_tab=Z.suba(Z.mul(div_tab)b)letpowxy=ifZ.equalZ.zeroxthenZ.zeroelseifZ.equalZ.onexthenZ.oneelseifZ.equalZ.minus_onexthenifZ.is_oddythenZ.minus_oneelseZ.oneelse(* TODO: add check that y is in range of ints *)Z.powx(Z.to_inty)(* Builtins *)(* ************************************************************************* *)moduleE=Dolmen.Std.ExprmoduleB=Dolmen.Std.Builtinletmki=Value.mk~opsiletfun1f~cst=Fun.fun_1~cst(funx->mk@@f(Value.extract_exn~opsx))letfun2f~cst=Fun.fun_2~cst(funxy->f(Value.extract_exn~opsx)(Value.extract_exn~opsy))letop1~cstf=Some(fun1~cst(funx->fx))letop2~cstf=Some(fun2~cst(funxy->mk@@fxy))letcmp~cstp=Some(fun2~cst(funxy->Bool.mk@@pxy))letop2_zero~env~cst~zero~exnf=Some(Fun.fun_2~cst(funxy->letv_x=Value.extract_exn~opsxinletv_y=Value.extract_exn~opsyinifZ.equalZ.zerov_ythenbeginmatchModel.Cst.find_optzero(Env.modelenv)with|Somevalue->Fun.apply_val~eval:Eval.evalenvvalue[x;y]|None->raiseexnendelsemk@@fv_xv_y))letbuiltinsenv(cst:Dolmen.Std.Expr.Term.Const.t)=matchcst.builtinwith|B.Integeri->Some(mk(Z.of_stringi))|B.Lt`Int->cmp~cstZ.lt|B.Gt`Int->cmp~cstZ.gt|B.Geq`Int->cmp~cstZ.geq|B.Leq`Int->cmp~cstZ.leq|B.Minus`Int->Some(fun1~cst(funx->Z.negx))|B.Add`Int->op2~cstZ.add|B.Sub`Int->op2~cstZ.sub|B.Mul`Int->op2~cstZ.mul|B.Pow`Int->op2~cstpow|B.Div_e`Int->op2_zero~env~exn:Division_by_zero~zero:E.Term.Int.div_zero~cstdiv_e|B.Div_t`Int->op2~cstdiv_t|B.Div_f`Int->op2~cstdiv_f|B.Modulo_e`Int->op2_zero~env~exn:Modulo_by_zero~zero:E.Term.Int.rem_zero~cstmod_e|B.Modulo_t`Int->op2~cstmod_t|B.Modulo_f`Int->op2~cstmod_f|B.Divisible->Some(fun2~cst(funxy->Bool.mk@@Z.divisiblexy))|B.Abs->op1~cstZ.abs|B.Is_int`Int|B.Is_rat`Int->Some(Fun.fun_1~cst(fun_->Bool.mktrue))|B.Floor`Int|B.Ceiling`Int|B.Truncate`Int|B.Round`Int->op1~cst(funx->x)|_->None