123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117openASTopenASTUtilsopenErrorletvalue_as_intpos=function|L_Inti->(tryZ.to_intiwithZ.Overflow->failwith"Cannot slice with an integer more than machine size.")|v->fatal_frompos(Error.MismatchType(PP.literal_to_stringv,[integer']))letis_positivez=Z.signz!=-1letis_strict_positivez=Z.signz=1letbv_same_lengthb1b2=Bitvector.(lengthb1=lengthb2)letexp_realqz=ifQ.signq=0then(assert(Z.signz>=0)(* Case handled earlier *);ifZ.signz=0thenQ.oneelseQ.zero)elseletq,z=ifis_positivezthen(q,z)else(Q.invq,Z.negz)inletnum=Q.numqandden=Q.denqinleti=Z.to_intzinletres_num=Z.pownumiandres_den=Z.powdeniinQ.(res_num///res_den)letbinop_valuespostopv1v2=match(op,v1,v2)with(* int -> int -> int *)|PLUS,L_Intv1,L_Intv2->L_Int(Z.addv1v2)|MUL,L_Intv1,L_Intv2->L_Int(Z.mulv1v2)|MINUS,L_Intv1,L_Intv2->L_Int(Z.subv1v2)|DIV,L_Intv1,L_Intv2whenis_strict_positivev2&&Z.divisiblev1v2->L_Int(Z.divexactv1v2)|DIVRM,L_Intv1,L_Intv2whenis_strict_positivev2->L_Int(Z.fdivv1v2)(* Division rounded towards minus infinity. *)|MOD,L_Intv1,L_Intv2whenis_strict_positivev2->L_IntZ.(subv1(mulv2(fdivv1v2)))(* We cannot use any rem function in Z as we need the rounded towards minus infinity reminder. *)|POW,L_Intv1,L_Intv2whenis_positivev2->L_IntZ.(powv1(to_intv2))|SHL,L_Intv1,L_Intv2whenis_positivev2->L_IntZ.(shift_leftv1(to_intv2))|SHR,L_Intv1,L_Intv2whenis_positivev2->L_IntZ.(shift_rightv1(to_intv2))(* int -> int -> bool*)|EQ_OP,L_Intv1,L_Intv2->L_Bool(Z.equalv1v2)|NEQ,L_Intv1,L_Intv2->L_Bool(not(Z.equalv1v2))|LEQ,L_Intv1,L_Intv2->L_Bool(Z.leqv1v2)|LT,L_Intv1,L_Intv2->L_Bool(Z.ltv1v2)|GEQ,L_Intv1,L_Intv2->L_Bool(Z.geqv1v2)|GT,L_Intv1,L_Intv2->L_Bool(Z.gtv1v2)(* bool -> bool -> bool *)|BAND,L_Boolb1,L_Boolb2->L_Bool(b1&&b2)|BOR,L_Boolb1,L_Boolb2->L_Bool(b1||b2)|BEQ,L_Boolb1,L_Boolb2->L_Bool(b1==b2)|IMPL,L_Boolb1,L_Boolb2->L_Bool((notb1)||b2)|EQ_OP,L_Boolb1,L_Boolb2->L_Bool(b1==b2)|NEQ,L_Boolb1,L_Boolb2->L_Bool(b1<>b2)(* real -> real -> real *)|PLUS,L_Realv1,L_Realv2->L_Real(Q.addv1v2)|MUL,L_Realv1,L_Realv2->L_Real(Q.mulv1v2)|MINUS,L_Realv1,L_Realv2->L_Real(Q.subv1v2)|RDIV,L_Realv1,L_Realv2->L_Real(Q.divv1v2)|POW,L_Realq1,L_Intz2whennot(Q.signq1=0&&Z.signz2<0)->(* 0.0 ^ z is not defined for z < 0 *)L_Real(exp_realq1z2)(* real -> real -> bool *)|EQ_OP,L_Realv1,L_Realv2->L_Bool(Q.equalv1v2)|NEQ,L_Realv1,L_Realv2->L_Bool(not(Q.equalv1v2))|LEQ,L_Realv1,L_Realv2->L_Bool(Q.leqv1v2)|LT,L_Realv1,L_Realv2->L_Bool(Q.ltv1v2)|GEQ,L_Realv1,L_Realv2->L_Bool(Q.geqv1v2)|GT,L_Realv1,L_Realv2->L_Bool(Q.gtv1v2)(* bits -> bits -> bool *)|EQ_OP,L_BitVectorb1,L_BitVectorb2whenbv_same_lengthb1b2->L_Bool(Bitvector.equalb1b2)|NEQ,L_BitVectorb1,L_BitVectorb2whenbv_same_lengthb1b2->L_Bool(not@@Bitvector.equalb1b2)(* bits -> bits -> bits *)|OR,L_BitVectorb1,L_BitVectorb2whenbv_same_lengthb1b2->L_BitVector(Bitvector.logorb1b2)|AND,L_BitVectorb1,L_BitVectorb2whenbv_same_lengthb1b2->L_BitVector(Bitvector.logandb1b2)|EOR,L_BitVectorb1,L_BitVectorb2whenbv_same_lengthb1b2->L_BitVector(Bitvector.logxorb1b2)|PLUS,L_BitVectorb1,L_BitVectorb2whenbv_same_lengthb1b2->L_BitVectorBitvector.(of_z(lengthb1)(Z.add(to_z_unsignedb1)(to_z_unsignedb2)))|MINUS,L_BitVectorb1,L_BitVectorb2whenbv_same_lengthb1b2->L_BitVectorBitvector.(of_z(lengthb1)(Z.sub(to_z_unsignedb1)(to_z_unsignedb2)))|BV_CONCAT,L_BitVectorb1,L_BitVectorb2->L_BitVector(Bitvector.concat[b1;b2])(* bits -> integer -> bits *)|PLUS,L_BitVectorb1,L_Intz2->L_BitVectorBitvector.(of_z(lengthb1)(Z.add(to_z_unsignedb1)z2))|MINUS,L_BitVectorb1,L_Intz2->L_BitVectorBitvector.(of_z(lengthb1)(Z.sub(to_z_unsignedb1)z2))(* string -> string -> bool *)|EQ_OP,L_Strings1,L_Strings2->L_Bool(String.equals1s2)|NEQ,L_Strings1,L_Strings2->L_Bool(not(String.equals1s2))(* enum -> enum -> bool *)|EQ_OP,L_Labels1,L_Labels2->L_Bool(String.equals1s2)|NEQ,L_Labels1,L_Labels2->L_Bool(not(String.equals1s2))(* Failure *)|_->fatal_frompos(Error.UnsupportedBinop(t,op,v1,v2))letunop_valuespostopv=match(op,v)with|NEG,L_Inti->L_Int(Z.negi)|NEG,L_Realr->L_Real(Q.negr)|BNOT,L_Boolb->L_Bool(notb)|NOT,L_BitVectorbv->L_BitVector(Bitvector.lognotbv)|_->fatal_frompos(Error.UnsupportedUnop(t,op,v))