123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)(* Copyright (c) 2021-2022 Nomadic Labs <contact@nomadic-labs.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)typen=Natural_tagtypez=Integer_tag(* We could define `num` as a GADT with constructors for `n` and `z`.
This would enable factorizing the code a bit in the Michelson interpreter and
also make formal the claim that `num` is only instantiated with `n` and `z`,
but it would result in space and time overheads when manipulating `num`s, by
having to deconstruct to and reconstruct from `Z.t`. *)type'trepr=Z.ttype'tnum=Num_tagof'trepr[@@ocaml.unboxed]letcompare(Num_tagx)(Num_tagy)=Z.comparexyletzero=Num_tagZ.zeroletone=Num_tagZ.oneletzero_n=Num_tagZ.zeroletone_n=Num_tagZ.oneletto_string(Num_tagx)=Z.to_stringxletof_strings=Option.catch(fun()->Num_tag(Z.of_strings))letof_int32n=Num_tag(Z.of_int64@@Int64.of_int32n)letto_int64(Num_tagx)=Option.catch(fun()->Z.to_int64x)letof_int64n=Num_tag(Z.of_int64n)letto_int(Num_tagx)=Option.catch(fun()->Z.to_intx)letof_intn=Num_tag(Z.of_intn)letof_zintx=Num_tagxletto_zint(Num_tagx)=xletadd(Num_tagx)(Num_tagy)=Num_tag(Z.addxy)letsub(Num_tagx)(Num_tagy)=Num_tag(Z.subxy)letmul(Num_tagx)(Num_tagy)=Num_tag(Z.mulxy)letediv(Num_tagx)(Num_tagy)=letediv_taggedxy=letquo,rem=Z.ediv_remxyin(Num_tagquo,Num_tagrem)inOption.catch(fun()->ediv_taggedxy)letadd_n=addletsucc_n(Num_tagx)=Num_tag(Z.succx)letmul_n=mulletediv_n=edivletabs(Num_tagx)=Num_tag(Z.absx)letis_nat(Num_tagx)=ifCompare.Z.(x<Z.zero)thenNoneelseSome(Num_tagx)letneg(Num_tagx)=Num_tag(Z.negx)letint(Num_tagx)=Num_tagxletshift_left(Num_tagx)(Num_tagy)=ifCompare.Int.(Z.comparey(Z.of_int256)>0)thenNoneelselety=Z.to_intyinSome(Num_tag(Z.shift_leftxy))letshift_right(Num_tagx)(Num_tagy)=ifCompare.Int.(Z.comparey(Z.of_int256)>0)thenNoneelselety=Z.to_intyinSome(Num_tag(Z.shift_rightxy))letshift_left_n=shift_leftletshift_right_n=shift_rightletlogor(Num_tagx)(Num_tagy)=Num_tag(Z.logorxy)letlogxor(Num_tagx)(Num_tagy)=Num_tag(Z.logxorxy)letlogand(Num_tagx)(Num_tagy)=Num_tag(Z.logandxy)letlognot(Num_tagx)=Num_tag(Z.lognotx)letz_encoding:znumData_encoding.encoding=Data_encoding.(conv(fun(Num_tagz)->z)(funz->Num_tagz)z)letn_encoding:nnumData_encoding.encoding=Data_encoding.(conv(fun(Num_tagn)->n)(funn->Num_tagn)n)