Michelson: replace all numbers with only int and nat

This commit is contained in:
Fabrice Le Fessant 2017-05-23 15:04:31 +02:00 committed by Benjamin Canou
parent efdf8c74eb
commit 4dd1ef9988
12 changed files with 646 additions and 750 deletions

View File

@ -371,7 +371,7 @@ proto/embedded_proto_%.cmxa: \
CLIENT_PROTO_INCLUDES := \
minutils utils compiler node/updater node/db node/net node/shell client \
$(shell ocamlfind query lwt ocplib-json-typed sodium)
$(shell ocamlfind query lwt ocplib-json-typed sodium zarith)
proto/client_embedded_proto_%.cmxa: \
${TZCOMPILER} \

View File

@ -12,6 +12,7 @@ $(addprefix proto/environment/, \
buffer.mli \
format.mli \
\
z.mli \
lwt_sequence.mli lwt.mli lwt_list.mli \
\
mBytes.mli \
@ -114,6 +115,7 @@ UTILS_LIB_IMPLS := \
UTILS_PACKAGES := \
${MINUTILS_PACKAGES} \
zarith \
base64 \
calendar \
ezjsonm \

View File

@ -197,7 +197,6 @@ let collect_error_locations errs =
| Invalid_case (loc, _)
| Invalid_kind (loc, _, _)
| Fail_not_in_tail_position loc
| Undefined_cast (loc, _, _)
| Undefined_binop (loc, _, _, _)
| Undefined_unop (loc, _, _)
| Bad_return (loc, _, _)
@ -208,8 +207,7 @@ let collect_error_locations errs =
| Invalid_contract (loc, _)
| Comparable_type_expected (loc, _)
| Overflow loc
| Reject loc
| Division_by_zero loc) :: rest ->
| Reject loc) :: rest ->
collect (loc :: acc) rest
| _ :: rest -> collect acc rest in
collect [] errs
@ -336,13 +334,6 @@ let report_errors cctxt errs =
cctxt.warning
"%aThe FAIL instruction must appear in a tail position."
print_loc loc
| Undefined_cast (loc, tya, tyb) ->
cctxt.warning
"@[<hov 0>@[<hov 2>%atype cast is undefined from@ %a@]@ \
@[<hov 2>to@ %a.@]@]"
print_loc loc
print_ty tya
print_ty tyb
| Undefined_binop (loc, name, tya, tyb) ->
cctxt.warning
"@[<hov 0>@[<hov 2>%aoperator %s is undefined between@ %a@]@ \
@ -404,24 +395,6 @@ let report_errors cctxt errs =
print_loc loc >>= fun () ->
cctxt.warning "@[<hov 0>@[<hov 2>Type@ %a@]@ is not comparable.@]"
print_ty ty
| Bad_sign ty ->
begin match ty with
| Int_t kind ->
let signed = match kind with
| Script_int.Int8 -> true
| Script_int.Int16 -> true
| Script_int.Int32 -> true
| Script_int.Int64 -> true
| Script_int.Uint8 -> false
| Script_int.Uint16 -> false
| Script_int.Uint32 -> false
| Script_int.Uint64 -> false in
if signed then
cctxt.warning "Unsigned integer type expected."
else
cctxt.warning "Signed integer type expected."
| _ -> assert false
end
| Inconsistent_types (tya, tyb) ->
cctxt.warning
"@[<hov 0>@[<hov 2>Type@ %a@]@ \
@ -429,7 +402,6 @@ let report_errors cctxt errs =
print_ty tya print_ty tyb
| Reject _ -> cctxt.warning "Script reached FAIL instruction"
| Overflow _ -> cctxt.warning "Unexpected arithmetic overflow"
| Division_by_zero _ -> cctxt.warning "Division by zero"
| err ->
cctxt.warning "%a"
Local_environment.Environment.Error_monad.pp_print_error [ err ] in

View File

@ -243,6 +243,7 @@ module Make(Param : sig val name: string end)() = struct
module Buffer = Buffer
module Format = Format
module Hex_encode = Hex_encode
module Z = Z
module Lwt_sequence = Lwt_sequence
module Lwt = Lwt
module Lwt_list = Lwt_list

View File

@ -7,224 +7,60 @@
(* *)
(**************************************************************************)
(* sign *)
type signed = Signed
type unsigned = Unsigned
type n = Natural_tag
type z = Integer_tag
type 't num = Z.t
(* length *)
type eight = Eight
type sixteen = Sixteen
type thirtytwo = Thirtytwo
type sixtyfour = Sixtyfour
let compare x y = Z.compare x y
(* int values *)
type ('s, 'l) int_val = Int of repr and repr = int64
let zero = Z.zero
let zero_n = Z.zero
(* types *)
and ('s, 'l) int_kind =
| Int8 : (signed, eight) int_kind
| Uint8 : (unsigned, eight) int_kind
| Int16 : (signed, sixteen) int_kind
| Uint16 : (unsigned, sixteen) int_kind
| Int32 : (signed, thirtytwo) int_kind
| Uint32 : (unsigned, thirtytwo) int_kind
| Int64 : (signed, sixtyfour) int_kind
| Uint64 : (unsigned, sixtyfour) int_kind
let to_string x = Z.to_string x
let of_string s = try Some (Z.of_string s) with _ -> None
(* homogeneous operator types *)
type ('s, 'l) binop =
('s, 'l) int_kind -> ('s, 'l) int_val -> ('s, 'l) int_val -> ('s, 'l) int_val
type ('s, 'l) unop =
('s, 'l) int_kind -> ('s, 'l) int_val -> ('s, 'l) int_val
type ('s, 'l) checked_binop =
('s, 'l) int_kind -> ('s, 'l) int_val -> ('s, 'l) int_val -> ('s, 'l) int_val option
type ('s, 'l) checked_unop =
('s, 'l) int_kind -> ('s, 'l) int_val -> ('s, 'l) int_val option
type ('s, 'l) shift =
('s, 'l) int_kind -> ('s, 'l) int_val -> ('s, eight) int_val -> ('s, 'l) int_val
let to_int64 x = try Some (Z.to_int64 x) with _ -> None
let of_int64 n = Z.of_int64 n
(* cast operators *)
let cast
: type tos tol. (tos, tol) int_kind -> (_, _) int_val -> (tos, tol) int_val
= fun to_kind (Int v) ->
let (land) = Int64.logand
and (lor) = Int64.logor
and (=) = Compare.Int64.(=) in
match to_kind with
| Int8 when v land 0x80L = 0x80L ->
Int ((v land 0x000000FFL) lor 0xFFFFFFFFFFFFFF00L)
| Int8 ->
Int (v land 0x000000FFL)
| Uint8 ->
Int (v land 0x000000FFL)
| Int16 when v land 0x8000L = 0x8000L ->
Int ((v land 0x0000FFFFL) lor 0xFFFFFFFFFFFF0000L)
| Int16 ->
Int (v land 0x0000FFFFL)
| Uint16 ->
Int (v land 0x0000FFFFL)
| Int32 when v land 0x80000000L = 0x80000000L ->
Int ((v land 0xFFFFFFFFL) lor 0xFFFFFFFF00000000L)
| Int32 ->
Int (v land 0xFFFFFFFFL)
| Uint32 ->
Int (v land 0xFFFFFFFFL)
| Int64 -> Int v
| Uint64 -> Int v
let to_int x = try Some (Z.to_int x) with _ -> None
let of_int n = Z.of_int n
let checked_cast
: type tos tol. (tos, tol) int_kind -> (_, _) int_val -> (tos, tol) int_val option
= fun to_kind (Int v as arg) ->
let Int casted as res = cast to_kind arg in
if Compare.Int64.(casted <> v) then None else Some res
let add x y = Z.add x y
let sub x y = Z.sub x y
let mul x y = Z.mul x y
(* to native int64s *)
let to_int64 _ (Int v) =
v
let of_int64 k v =
cast k (Int v)
let checked_of_int64 k v =
checked_cast k (Int v)
let ediv x y =
try
let (q, r) = Z.ediv_rem x y in
Some (q, r)
with _ -> None
(* arithmetics *)
let add kind (Int va) (Int vb) =
of_int64 kind (Int64.add va vb)
let sub kind (Int va) (Int vb) =
of_int64 kind (Int64.sub va vb)
let mul : type s l. (s, l) int_kind -> (s, l) int_val -> (s, l) int_val -> (s, l) int_val
= fun kind (Int va) (Int vb) -> let r = Int64.mul va vb in match kind with
| Int8 -> of_int64 Int8 r
| Uint8 -> of_int64 Uint8 r
| Int16 -> of_int64 Int16 r
| Uint16 -> of_int64 Uint16 r
| Int32 -> of_int64 Int32 r
| Uint32 -> of_int64 Uint32 r
| Int64 -> of_int64 Int64 r
| Uint64 -> invalid_arg "Script_int.mul"
let div : type s l. (s, l) int_kind -> (s, l) int_val -> (s, l) int_val -> (s, l) int_val
= fun kind (Int va) (Int vb) -> let r = Int64.div va vb in match kind with
| Int8 -> of_int64 Int8 r
| Uint8 -> of_int64 Uint8 r
| Int16 -> of_int64 Int16 r
| Uint16 -> of_int64 Uint16 r
| Int32 -> of_int64 Int32 r
| Uint32 -> of_int64 Uint32 r
| Int64 -> of_int64 Int64 r
| Uint64 -> invalid_arg "Script_int.div"
let rem : type s l. (s, l) int_kind -> (s, l) int_val -> (s, l) int_val -> (s, l) int_val
= fun kind (Int va) (Int vb) -> let r = Int64.rem va vb in match kind with
| Int8 -> of_int64 Int8 r
| Uint8 -> of_int64 Uint8 r
| Int16 -> of_int64 Int16 r
| Uint16 -> of_int64 Uint16 r
| Int32 -> of_int64 Int32 r
| Uint32 -> of_int64 Uint32 r
| Int64 -> of_int64 Int64 r
| Uint64 -> invalid_arg "Script_int.rem"
let neg kind (Int v) =
of_int64 kind (Int64.neg v)
let abs kind (Int v) =
of_int64 kind (Int64.abs v)
let add_n = add
let mul_n = mul
let ediv_n = ediv
(* bitwise logic *)
let logand _ (Int va) (Int vb) =
Int (Int64.logand va vb)
let logor _ (Int va) (Int vb) =
Int (Int64.logor va vb)
let logxor kind (Int va) (Int vb) =
cast kind (Int (Int64.logxor va vb))
let lognot kind (Int v) =
cast kind (Int (Int64.lognot v))
let logsl kind (Int va) (Int vb) =
cast kind (Int (Int64.shift_left va (Int64.to_int vb)))
let logsr _ (Int va) (Int vb) =
Int (Int64.shift_right_logical va (Int64.to_int vb))
let abs x = Z.abs x
let neg x = Z.neg x
let int x = x
(* sign aware comparison *)
let compare
: type s l. (s, l) int_kind -> (s, l) int_val -> (s, l) int_val -> (signed, sixtyfour) int_val
= fun kind (Int va) (Int vb) ->
let cmp = match kind with
| Int8 -> Compare.Int64.compare va vb
| Uint8 -> Compare.Uint64.compare va vb
| Int16 -> Compare.Int64.compare va vb
| Uint16 -> Compare.Uint64.compare va vb
| Int32 -> Compare.Int64.compare va vb
| Uint32 -> Compare.Uint64.compare va vb
| Int64 -> Compare.Int64.compare va vb
| Uint64 -> Compare.Uint64.compare va vb in
Int Compare.Int.(if cmp = 0 then 0L else if cmp > 0 then 1L else -1L)
let shift_left x y =
if Compare.Int.(Z.compare y (Z.of_int 256) > 0) then
None
else
let y = Z.to_int y in
Some (Z.shift_left x y)
let equal kind va vb =
Compare.Int64.(to_int64 kind va = to_int64 kind vb)
let shift_right x y =
if Compare.Int.(Z.compare y (Z.of_int 256) > 0) then
None
else
let y = Z.to_int y in
Some (Z.shift_right x y)
(* checked arithmetics *)
let checked_add : type s l. (s, l) int_kind -> (s, l) int_val -> (s, l) int_val -> (s, l) int_val option
= fun kind (Int va) (Int vb) -> let r = Int64.add va vb in match kind with
| Int8 -> checked_of_int64 Int8 r
| Uint8 -> checked_of_int64 Uint8 r
| Int16 -> checked_of_int64 Int16 r
| Uint16 -> checked_of_int64 Uint16 r
| Int32 -> checked_of_int64 Int32 r
| Uint32 -> checked_of_int64 Uint32 r
| Int64 when Compare.Int.(Compare.Int64.compare r va < 0) -> None
| Int64 -> Some (Int r)
| Uint64 when Compare.Int.(Compare.Uint64.compare r va < 0) -> None
| Uint64 -> Some (Int r)
let shift_left_n = shift_left
let shift_right_n = shift_right
let checked_sub : type s l. (s, l) int_kind -> (s, l) int_val -> (s, l) int_val -> (s, l) int_val option
= fun kind (Int va) (Int vb) -> let r = Int64.sub va vb in match kind with
| Int8 -> checked_of_int64 Int8 r
| Uint8 -> checked_of_int64 Uint8 r
| Int16 -> checked_of_int64 Int16 r
| Uint16 -> checked_of_int64 Uint16 r
| Int32 -> checked_of_int64 Int32 r
| Uint32 -> checked_of_int64 Uint32 r
| Int64 when Compare.Int64.(vb >= 0L) ->
if Compare.Int.(Compare.Int64.compare r va <= 0) then Some (Int r) else None
| Int64 ->
if Compare.Int.(Compare.Int64.compare r va >= 0) then Some (Int r) else None
| Uint64 when Compare.Int.(Compare.Uint64.compare r va > 0) -> None
| Uint64 -> Some (Int r)
let checked_neg : type l. (signed, l) int_kind -> (signed, l) int_val -> (signed, l) int_val option
= fun kind (Int v) -> let r = Int64.neg v in match kind with
| Int8 -> checked_of_int64 Int8 r
| Int16 -> checked_of_int64 Int16 r
| Int32 -> checked_of_int64 Int32 r
| Int64 when Compare.Int64.(v = Int64.min_int) -> None
| Int64 -> Some (Int r)
let checked_abs : type l. (signed, l) int_kind -> (signed, l) int_val -> (signed, l) int_val option
= fun kind (Int v) -> let r = Int64.abs v in match kind with
| Int8 -> checked_of_int64 Int8 r
| Int16 -> checked_of_int64 Int16 r
| Int32 -> checked_of_int64 Int32 r
| Int64 when Compare.Int64.(v = Int64.min_int) -> None
| Int64 -> Some (Int r)
let checked_mul : type s l. (s, l) int_kind -> (s, l) int_val -> (s, l) int_val -> (s, l) int_val option
= fun kind (Int va) (Int vb) -> let r = Int64.mul va vb in match kind with
| Int8 -> checked_of_int64 Int8 r
| Uint8 -> checked_of_int64 Uint8 r
| Int16 -> checked_of_int64 Int16 r
| Uint16 -> checked_of_int64 Uint16 r
| Int32 -> checked_of_int64 Int32 r
| Uint32 -> checked_of_int64 Uint32 r
| Int64 ->
if Compare.Int64.(vb = 0L || va = 0L) then Some (Int r)
else if Compare.Int64.(r = 0L) then None
else if Compare.Int64.(Int64.div r va = vb) then Some (Int r)
else None
| Uint64 -> invalid_arg "Script_int.checked_mul"
let string_of_int_kind (type s) (type l) (kind:(s,l) int_kind) =
match kind with
| Int8 -> "int8"
| Uint8 -> "uint8"
| Int16 -> "int16"
| Uint16 -> "uint16"
| Int32 -> "int32"
| Uint32 -> "uint32"
| Int64 -> "int64"
| Uint64 -> "uint64"
let logor x y = Z.logor x y
let logxor x y = Z.logxor x y
let logand x y = Z.logand x y
let lognot x = Z.lognot x

View File

@ -7,78 +7,113 @@
(* *)
(**************************************************************************)
(* sign *)
type signed = Signed
type unsigned = Unsigned
(** The types for arbitraty precision integers in Michelson.
The type variable ['t] is always [n] or [z],
[n num] and [z num] are incompatible.
(* length *)
type eight = Eight
type sixteen = Sixteen
type thirtytwo = Thirtytwo
type sixtyfour = Sixtyfour
This is internally a [Z.t].
This module mostly adds signedness preservation guarantees. *)
type 't num
(* int values *)
type ('s, 'l) int_val = Int of repr and repr
(** Flag for natural numbers. *)
and n = Natural_tag
(* int types *)
type ('s, 'l) int_kind =
| Int8 : (signed, eight) int_kind
| Uint8 : (unsigned, eight) int_kind
| Int16 : (signed, sixteen) int_kind
| Uint16 : (unsigned, sixteen) int_kind
| Int32 : (signed, thirtytwo) int_kind
| Uint32 : (unsigned, thirtytwo) int_kind
| Int64 : (signed, sixtyfour) int_kind
| Uint64 : (unsigned, sixtyfour) int_kind
(** Flag for relative numbers. *)
and z = Integer_tag
(* homogeneous operator types *)
type ('s, 'l) binop =
('s, 'l) int_kind -> ('s, 'l) int_val -> ('s, 'l) int_val -> ('s, 'l) int_val
type ('s, 'l) unop =
('s, 'l) int_kind -> ('s, 'l) int_val -> ('s, 'l) int_val
type ('s, 'l) checked_binop =
('s, 'l) int_kind -> ('s, 'l) int_val -> ('s, 'l) int_val -> ('s, 'l) int_val option
type ('s, 'l) checked_unop =
('s, 'l) int_kind -> ('s, 'l) int_val -> ('s, 'l) int_val option
type ('s, 'l) shift =
('s, 'l) int_kind -> ('s, 'l) int_val -> ('s, eight) int_val -> ('s, 'l) int_val
(** Natural zero. *)
val zero_n : n num
(* cast operators *)
val cast : ('tos, 'tol) int_kind -> ('s, 'l) int_val -> ('tos, 'tol) int_val
val checked_cast : ('tos, 'tol) int_kind -> ('s, 'l) int_val -> ('tos, 'tol) int_val option
(** Relative zero. *)
val zero : z num
(* to native int64s *)
val to_int64 : ('s, 'l) int_kind -> ('s, 'l) int_val -> int64
val of_int64 : ('s, 'l) int_kind -> int64 -> ('s, 'l) int_val
val checked_of_int64 : ('s, 'l) int_kind -> int64 -> ('s, 'l) int_val option
(** Compare two numbers as if they were *)
val compare : 'a num -> 'a num -> int
(* arithmetics *)
val abs : (signed, 'l) unop
val neg : (signed, 'l) unop
val add : ('s, 'l) binop
val sub : ('s, 'l) binop
val mul : ('s, 'l) binop
val div : ('s, 'l) binop
val rem : ('s, 'l) binop
val checked_abs : (signed, 'l) checked_unop
val checked_neg : (signed, 'l) checked_unop
val checked_add : ('s, 'l) checked_binop
val checked_sub : ('s, 'l) checked_binop
val checked_mul : ('s, 'l) checked_binop
(** Conversion to an OCaml [string] in decimal notation. *)
val to_string : _ num -> string
(* bitwise logic *)
val logand : (unsigned, 'l) binop
val logor : (unsigned, 'l) binop
val logxor : (unsigned, 'l) binop
val lognot : (unsigned, 'l) unop
val logsl : (unsigned, 'l) shift
val logsr : (unsigned, 'l) shift
(** Conversion from an OCaml [string].
Returns [None] in case of an invalid notation.
Supports [+] and [-] sign modifiers, and [0x], [0o] and [0b] base modifiers. *)
val of_string : string -> z num option
(* sign aware comparison *)
val compare : ('s, 'l) int_kind ->
('s, 'l) int_val -> ('s, 'l) int_val -> (signed, sixtyfour) int_val
val equal : ('s, 'l) int_kind ->
('s, 'l) int_val -> ('s, 'l) int_val -> bool
(** Conversion to an OCaml [int64], returns [None] on overflow. *)
val to_int64 : _ num -> int64 option
(* utilities *)
val string_of_int_kind : ('s, 'l) int_kind -> string
(** Conversion from an OCaml [int]. *)
val of_int64 : int64 -> z num
(** Conversion to an OCaml [int], returns [None] on overflow. *)
val to_int : _ num -> int option
(** Conversion from an OCaml [int64]. *)
val of_int : int -> z num
(** Addition between naturals. *)
val add_n : n num -> n num -> n num
(** Multiplication between naturals. *)
val mul_n : n num -> n num -> n num
(** Euclidean division between naturals.
[ediv_n n d] returns [None] if divisor is zero,
or [Some (q, r)] where [n = d * q + r] and [[0 <= r < d]] otherwise. *)
val ediv_n: n num -> n num -> (n num * n num) option
(** Sign agnostic addition.
Use {!add_n} when working with naturals to preserve the sign. *)
val add : _ num -> _ num -> z num
(** Sign agnostic subtraction.
Use {!sub_n} when working with naturals to preserve the sign. *)
val sub : _ num -> _ num -> z num
(** Sign agnostic multiplication.
Use {!mul_n} when working with naturals to preserve the sign. *)
val mul : _ num -> _ num -> z num
(** Sign agnostic euclidean division.
[ediv n d] returns [None] if divisor is zero,
or [Some (q, r)] where [n = d * q + r] and [[0 <= r < |d|]] otherwise.
Use {!ediv_n} when working with naturals to preserve the sign. *)
val ediv: _ num -> _ num -> (z num * n num) option
(** Compute the absolute value of a relative, turning it into a natural. *)
val abs : z num -> n num
(** Negates a number. *)
val neg : _ num -> z num
(** Turns a natural into a relative, not changing its value. *)
val int : n num -> z num
(** Reverses each bit in the representation of the number.
Also applies to the sign. *)
val lognot : _ num -> z num
(** Shifts the natural to the left of a number of bits between 0 and 256.
Returns [None] if the amount is too high. *)
val shift_left_n : n num -> n num -> n num option
(** Shifts the natural to the right of a number of bits between 0 and 256.
Returns [None] if the amount is too high. *)
val shift_right_n : n num -> n num -> n num option
(** Shifts the number to the left of a number of bits between 0 and 256.
Returns [None] if the amount is too high. *)
val shift_left : 'a num -> n num -> 'a num option
(** Shifts the number to the right of a number of bits between 0 and 256.
Returns [None] if the amount is too high. *)
val shift_right : 'a num -> n num -> 'a num option
(** Applies a boolean or operation to each bit. *)
val logor : n num -> n num -> n num
(** Applies a boolean and operation to each bit. *)
val logand : n num -> n num -> n num
(** Applies a boolean xor operation to each bit. *)
val logxor : n num -> n num -> n num

View File

@ -8,7 +8,6 @@
(**************************************************************************)
open Tezos_context
open Script_int
open Script
open Script_typed_ir
open Script_ir_translator
@ -21,7 +20,6 @@ let dummy_storage_fee = Tez.fifty_cents
type error += Quota_exceeded
type error += Overflow of Script.location
type error += Reject of Script.location
type error += Division_by_zero of Script.location
type error += Runtime_contract_error : Contract.t * Script.expr * _ ty * _ ty * _ ty -> error
let () =
@ -46,14 +44,6 @@ let () =
(obj1 (req "location" Script.location_encoding))
(function Overflow loc -> Some loc | _ -> None)
(fun loc -> Overflow loc) ;
register_error_kind
`Permanent
~id:"divisionByZeroRuntimeError"
~title: "Division by zero (runtime script error)"
~description: ""
(obj1 (req "location" Script.location_encoding))
(function Division_by_zero loc -> Some loc | _ -> None)
(fun loc -> Division_by_zero loc) ;
register_error_kind
`Temporary
~id:"scriptRejectedRuntimeError"
@ -230,20 +220,26 @@ let rec interp
| Map_update, Item (k, Item (v, Item (map, rest))) ->
logged_return (Item (map_update k v map, rest), qta - 1, ctxt)
(* timestamp operations *)
| Add_seconds_to_timestamp kind, Item (n, Item (t, rest)) ->
let n = Script_int.to_int64 kind n in
Lwt.return
(Period.of_seconds n >>? fun p ->
Timestamp.(t +? p) >>? fun res ->
Ok (Item (res, rest), qta - 1, ctxt)) >>=? fun res ->
logged_return res
| Add_timestamp_to_seconds kind, Item (t, Item (n, rest)) ->
let n = Script_int.to_int64 kind n in
Lwt.return
(Period.of_seconds n >>? fun p ->
Timestamp.(t +? p) >>? fun res ->
Ok (Item (res, rest), qta - 1, ctxt)) >>=? fun res ->
logged_return res
| Add_seconds_to_timestamp, Item (n, Item (t, rest)) ->
begin match Script_int.to_int64 n with
| None -> fail (Overflow loc)
| Some n ->
Lwt.return
(Period.of_seconds n >>? fun p ->
Timestamp.(t +? p) >>? fun res ->
Ok (Item (res, rest), qta - 1, ctxt)) >>=? fun res ->
logged_return res
end
| Add_timestamp_to_seconds, Item (t, Item (n, rest)) ->
begin match Script_int.to_int64 n with
| None -> fail (Overflow loc)
| Some n ->
Lwt.return
(Period.of_seconds n >>? fun p ->
Timestamp.(t +? p) >>? fun res ->
Ok (Item (res, rest), qta - 1, ctxt)) >>=? fun res ->
logged_return res
end
(* string operations *)
| Concat, Item (x, Item (y, rest)) ->
logged_return (Item (x ^ y, rest), qta - 1, ctxt)
@ -254,12 +250,22 @@ let rec interp
| Sub_tez, Item (x, Item (y, rest)) ->
Lwt.return Tez.(x -? y) >>=? fun res ->
logged_return (Item (res, rest), qta - 1, ctxt)
| Mul_tez kind, Item (x, Item (y, rest)) ->
Lwt.return Tez.(x *? Script_int.to_int64 kind y) >>=? fun res ->
logged_return (Item (res, rest), qta - 1, ctxt)
| Mul_tez' kind, Item (y, Item (x, rest)) ->
Lwt.return Tez.(x *? Script_int.to_int64 kind y) >>=? fun res ->
logged_return (Item (res, rest), qta - 1, ctxt)
| Mul_teznat, Item (x, Item (y, rest)) ->
begin
match Script_int.to_int64 y with
| None -> fail (Overflow loc)
| Some y ->
Lwt.return Tez.(x *? y) >>=? fun res ->
logged_return (Item (res, rest), qta - 1, ctxt)
end
| Mul_nattez, Item (y, Item (x, rest)) ->
begin
match Script_int.to_int64 y with
| None -> fail (Overflow loc)
| Some y ->
Lwt.return Tez.(x *? y) >>=? fun res ->
logged_return (Item (res, rest), qta - 1, ctxt)
end
(* boolean operations *)
| Or, Item (x, Item (y, rest)) ->
logged_return (Item (x || y, rest), qta - 1, ctxt)
@ -270,63 +276,98 @@ let rec interp
| Not, Item (x, rest) ->
logged_return (Item (not x, rest), qta - 1, ctxt)
(* integer operations *)
| Checked_abs_int kind, Item (x, rest) ->
begin match Script_int.checked_abs kind x with
| Abs_int, Item (x, rest) ->
logged_return (Item (Script_int.abs x, rest), qta - 1, ctxt)
| Int_nat, Item (x, rest) ->
logged_return (Item (Script_int.int x, rest), qta - 1, ctxt)
| Neg_int, Item (x, rest) ->
logged_return (Item (Script_int.neg x, rest), qta - 1, ctxt)
| Neg_nat, Item (x, rest) ->
logged_return (Item (Script_int.neg x, rest), qta - 1, ctxt)
| Add_intint, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.add x y, rest), qta - 1, ctxt)
| Add_intnat, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.add x y, rest), qta - 1, ctxt)
| Add_natint, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.add x y, rest), qta - 1, ctxt)
| Add_natnat, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.add_n x y, rest), qta - 1, ctxt)
| Sub_int, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.sub x y, rest), qta - 1, ctxt)
| Mul_intint, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.mul x y, rest), qta - 1, ctxt)
| Mul_intnat, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.mul x y, rest), qta - 1, ctxt)
| Mul_natint, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.mul x y, rest), qta - 1, ctxt)
| Mul_natnat, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.mul_n x y, rest), qta - 1, ctxt)
| Ediv_teznat, Item (x, Item (y, rest)) ->
let x = Script_int.of_int64 (Tez.to_cents x) in
let result =
match Script_int.ediv x y with
| None -> None
| Some (q, r) ->
match Script_int.to_int64 q,
Script_int.to_int64 r with
| Some q, Some r ->
begin
match Tez.of_cents q, Tez.of_cents r with
| Some q, Some r -> Some (q,r)
(* Cannot overflow *)
| _ -> assert false
end
(* Cannot overflow *)
| _ -> assert false
in
logged_return (Item (result, rest), qta -1, ctxt)
| Ediv_tez, Item (x, Item (y, rest)) ->
let x = Script_int.abs (Script_int.of_int64 (Tez.to_cents x)) in
let y = Script_int.abs (Script_int.of_int64 (Tez.to_cents y)) in
begin match Script_int.ediv_n x y with
| None ->
logged_return (Item (None, rest), qta -1, ctxt)
| Some (q, r) ->
let r =
match Script_int.to_int64 r with
| None -> assert false (* Cannot overflow *)
| Some r ->
match Tez.of_cents r with
| None -> assert false (* Cannot overflow *)
| Some r -> r in
logged_return (Item (Some (q, r), rest), qta -1, ctxt)
end
| Ediv_intint, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.ediv x y, rest), qta -1, ctxt)
| Ediv_intnat, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.ediv x y, rest), qta -1, ctxt)
| Ediv_natint, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.ediv x y, rest), qta -1, ctxt)
| Ediv_natnat, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.ediv_n x y, rest), qta -1, ctxt)
| Lsl_nat, Item (x, Item (y, rest)) ->
begin match Script_int.shift_left_n x y with
| None -> fail (Overflow loc)
| Some res -> logged_return (Item (res, rest), qta - 1, ctxt)
| Some r -> logged_return (Item (r, rest), qta - 1, ctxt)
end
| Checked_neg_int kind, Item (x, rest) ->
begin match Script_int.checked_neg kind x with
| Lsr_nat, Item (x, Item (y, rest)) ->
begin match Script_int.shift_right_n x y with
| None -> fail (Overflow loc)
| Some res -> logged_return (Item (res, rest), qta - 1, ctxt)
| Some r -> logged_return (Item (r, rest), qta - 1, ctxt)
end
| Checked_add_int kind, Item (x, Item (y, rest)) ->
begin match Script_int.checked_add kind x y with
| None -> fail (Overflow loc)
| Some res -> logged_return (Item (res, rest), qta - 1, ctxt)
end
| Checked_sub_int kind, Item (x, Item (y, rest)) ->
begin match Script_int.checked_sub kind x y with
| None -> fail (Overflow loc)
| Some res -> logged_return (Item (res, rest), qta - 1, ctxt)
end
| Checked_mul_int kind, Item (x, Item (y, rest)) ->
begin match Script_int.checked_mul kind x y with
| None -> fail (Overflow loc)
| Some res -> logged_return (Item (res, rest), qta - 1, ctxt)
end
| Abs_int kind, Item (x, rest) ->
logged_return (Item (Script_int.abs kind x, rest), qta - 1, ctxt)
| Neg_int kind, Item (x, rest) ->
logged_return (Item (Script_int.neg kind x, rest), qta - 1, ctxt)
| Add_int kind, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.add kind x y, rest), qta - 1, ctxt)
| Sub_int kind, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.sub kind x y, rest), qta - 1, ctxt)
| Mul_int kind, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.mul kind x y, rest), qta - 1, ctxt)
| Div_int kind, Item (x, Item (y, rest)) ->
if Compare.Int64.(Script_int.to_int64 kind y = 0L) then
fail (Division_by_zero loc)
else
logged_return (Item (Script_int.div kind x y, rest), qta - 1, ctxt)
| Mod_int kind, Item (x, Item (y, rest)) ->
if Compare.Int64.(Script_int.to_int64 kind y = 0L) then
fail (Division_by_zero loc)
else
logged_return (Item (Script_int.rem kind x y, rest), qta - 1, ctxt)
| Lsl_int kind, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.logsl kind x y, rest), qta - 1, ctxt)
| Lsr_int kind, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.logsr kind x y, rest), qta - 1, ctxt)
| Or_int kind, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.logor kind x y, rest), qta - 1, ctxt)
| And_int kind, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.logand kind x y, rest), qta - 1, ctxt)
| Xor_int kind, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.logxor kind x y, rest), qta - 1, ctxt)
| Not_int kind, Item (x, rest) ->
logged_return (Item (Script_int.lognot kind x, rest), qta - 1, ctxt)
| Or_nat, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.logor x y, rest), qta - 1, ctxt)
| And_nat, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.logand x y, rest), qta - 1, ctxt)
| Xor_nat, Item (x, Item (y, rest)) ->
logged_return (Item (Script_int.logxor x y, rest), qta - 1, ctxt)
| Not_int, Item (x, rest) ->
logged_return (Item (Script_int.lognot x, rest), qta - 1, ctxt)
| Not_nat, Item (x, rest) ->
logged_return (Item (Script_int.lognot x, rest), qta - 1, ctxt)
(* control *)
| Seq (hd, tl), stack ->
step origination qta ctxt hd stack >>=? fun (trans, qta, ctxt, origination) ->
@ -355,60 +396,57 @@ let rec interp
(* comparison *)
| Compare Bool_key, Item (a, Item (b, rest)) ->
let cmpres = Compare.Bool.compare a b in
let cmpres = Script_int.of_int64 Int64 (Int64.of_int cmpres) in
let cmpres = Script_int.of_int cmpres in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
| Compare String_key, Item (a, Item (b, rest)) ->
let cmpres = Compare.String.compare a b in
let cmpres = Script_int.of_int64 Int64 (Int64.of_int cmpres) in
let cmpres = Script_int.of_int cmpres in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
| Compare Tez_key, Item (a, Item (b, rest)) ->
let cmpres = Tez.compare a b in
let cmpres = Script_int.of_int64 Int64 (Int64.of_int cmpres) in
let cmpres = Script_int.of_int cmpres in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
| Compare (Int_key kind), Item (a, Item (b, rest)) ->
let cmpres = Script_int.compare kind a b in
| Compare Int_key, Item (a, Item (b, rest)) ->
let cmpres = Script_int.compare a b in
let cmpres = Script_int.of_int cmpres in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
| Compare Nat_key, Item (a, Item (b, rest)) ->
let cmpres = Script_int.compare a b in
let cmpres = Script_int.of_int cmpres in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
| Compare Key_key, Item (a, Item (b, rest)) ->
let cmpres = Ed25519.Public_key_hash.compare a b in
let cmpres = Script_int.of_int64 Int64 (Int64.of_int cmpres) in
let cmpres = Script_int.of_int cmpres in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
| Compare Timestamp_key, Item (a, Item (b, rest)) ->
let cmpres = Timestamp.compare a b in
let cmpres = Script_int.of_int64 Int64 (Int64.of_int cmpres) in
let cmpres = Script_int.of_int cmpres in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
(* comparators *)
| Eq, Item (cmpres, rest) ->
let cmpres = Script_int.to_int64 Int64 cmpres in
let cmpres = Compare.Int64.(cmpres = 0L) in
let cmpres = Script_int.compare cmpres Script_int.zero in
let cmpres = Compare.Int.(cmpres = 0) in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
| Neq, Item (cmpres, rest) ->
let cmpres = Script_int.to_int64 Int64 cmpres in
let cmpres = Compare.Int64.(cmpres <> 0L) in
let cmpres = Script_int.compare cmpres Script_int.zero in
let cmpres = Compare.Int.(cmpres <> 0) in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
| Lt, Item (cmpres, rest) ->
let cmpres = Script_int.to_int64 Int64 cmpres in
let cmpres = Compare.Int64.(cmpres < 0L) in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
| Gt, Item (cmpres, rest) ->
let cmpres = Script_int.to_int64 Int64 cmpres in
let cmpres = Compare.Int64.(cmpres > 0L) in
let cmpres = Script_int.compare cmpres Script_int.zero in
let cmpres = Compare.Int.(cmpres < 0) in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
| Le, Item (cmpres, rest) ->
let cmpres = Script_int.to_int64 Int64 cmpres in
let cmpres = Compare.Int64.(cmpres <= 0L) in
let cmpres = Script_int.compare cmpres Script_int.zero in
let cmpres = Compare.Int.(cmpres <= 0) in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
| Gt, Item (cmpres, rest) ->
let cmpres = Script_int.compare cmpres Script_int.zero in
let cmpres = Compare.Int.(cmpres > 0) in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
| Ge, Item (cmpres, rest) ->
let cmpres = Script_int.to_int64 Int64 cmpres in
let cmpres = Compare.Int64.(cmpres >= 0L) in
let cmpres = Script_int.compare cmpres Script_int.zero in
let cmpres = Compare.Int.(cmpres >= 0) in
logged_return (Item (cmpres, rest), qta - 1, ctxt)
(* casts *)
| Checked_int_of_int (_, kt), Item (v, rest) ->
begin match Script_int.checked_cast kt v with
| None -> fail (Overflow loc)
| Some res -> logged_return (Item (res, rest), qta - 1, ctxt)
end
| Int_of_int (_, kt), Item (v, rest) ->
logged_return (Item (Script_int.cast kt v, rest), qta - 1, ctxt)
(* protocol *)
| Manager, Item ((_, _, contract), rest) ->
Contract.get_manager ctxt contract >>=? fun manager ->
@ -506,7 +544,7 @@ let rec interp
let hash = Script.hash_expr (unparse_data ty v) in
logged_return (Item (hash, rest), qta - 1, ctxt)
| Steps_to_quota, rest ->
let steps = Script_int.of_int64 Uint32 (Int64.of_int qta) in
let steps = Script_int.abs (Script_int.of_int qta) in
logged_return (Item (steps, rest), qta - 1, ctxt)
| Source (ta, tb), rest ->
logged_return (Item ((ta, tb, orig), rest), qta - 1, ctxt)

View File

@ -13,15 +13,11 @@ open Script_typed_ir
type error += Quota_exceeded
type error += Overflow of Script.location
type error += Reject of Script.location
type error += Division_by_zero of Script.location
type error += Runtime_contract_error : Contract.t * Script.expr * _ ty * _ ty * _ ty -> error
val dummy_code_fee : Tez.t
val dummy_storage_fee : Tez.t
(* calling convention :
((amount, arg), globals)) -> (ret, globals) *)
val execute:
Contract.origination_nonce ->
Contract.t -> Contract.t -> Tezos_context.t ->

View File

@ -8,7 +8,6 @@
(**************************************************************************)
open Tezos_context
open Script_int
open Script
open Script_typed_ir
@ -28,7 +27,6 @@ type error += Invalid_kind of Script.location * kind list * kind
(* Instruction typing errors *)
type error += Fail_not_in_tail_position of Script.location
type error += Undefined_cast : Script.location * _ ty * _ ty -> error
type error += Undefined_binop : Script.location * string * _ ty * _ ty -> error
type error += Undefined_unop : Script.location * string * _ ty -> error
type error += Bad_return : Script.location * _ stack_ty * _ ty -> error
@ -43,7 +41,6 @@ type error += Invalid_constant : Script.location * Script.expr * _ ty -> error
type error += Invalid_contract of Script.location * Contract.t
type error += Comparable_type_expected : Script.location * _ ty -> error
type error += Inconsistent_types : _ ty * _ ty -> error
type error += Bad_sign : _ ty -> error
(* Toplevel errors *)
type error += Ill_typed_data : string option * Script.expr * _ ty -> error
@ -118,13 +115,18 @@ let compare_comparable
| Bool_key -> Compare.Bool.compare x y
| Tez_key -> Tez.compare x y
| Key_key -> Ed25519.Public_key_hash.compare x y
| Int_key kind ->
let res =
Script_int.to_int64 Script_int.Int64
(Script_int.compare kind x y) in
if Compare.Int64.(res = 0L) then 0
else if Compare.Int64.(res > 0L) then 1
| Int_key ->
let res = (Script_int.compare x y) in
if Compare.Int.(res = 0) then 0
else if Compare.Int.(res > 0) then 1
else -1
| Nat_key ->
let res = (Script_int.compare x y) in
if Compare.Int.(res = 0) then 0
else if Compare.Int.(res > 0) then 1
else -1
| Timestamp_key -> Timestamp.compare x y
let empty_set
@ -215,7 +217,8 @@ let map_fold
let ty_of_comparable_ty
: type a. a comparable_ty -> a ty = function
| Int_key k -> Int_t k
| Int_key -> Int_t
| Nat_key -> Nat_t
| String_key -> String_t
| Tez_key -> Tez_t
| Bool_key -> Bool_t
@ -224,14 +227,8 @@ let ty_of_comparable_ty
let unparse_comparable_ty
: type a. a comparable_ty -> Script.expr = function
| Int_key Int8 -> Prim (-1, "int8", [])
| Int_key Int16 -> Prim (-1, "int16", [])
| Int_key Int32 -> Prim (-1, "int32", [])
| Int_key Int64 -> Prim (-1, "int64", [])
| Int_key Uint8 -> Prim (-1, "uint8", [])
| Int_key Uint16 -> Prim (-1, "uint16", [])
| Int_key Uint32 -> Prim (-1, "uint32", [])
| Int_key Uint64 -> Prim (-1, "uint64", [])
| Nat_key -> Prim (-1, "nat", [])
| Int_key -> Prim (-1, "int", [])
| String_key -> Prim (-1, "string", [])
| Tez_key -> Prim (-1, "tez", [])
| Bool_key -> Prim (-1, "bool", [])
@ -241,14 +238,8 @@ let unparse_comparable_ty
let rec unparse_ty
: type a. a ty -> Script.expr = function
| Unit_t -> Prim (-1, "unit", [])
| Int_t Int8 -> Prim (-1, "int8", [])
| Int_t Int16 -> Prim (-1, "int16", [])
| Int_t Int32 -> Prim (-1, "int32", [])
| Int_t Int64 -> Prim (-1, "int64", [])
| Int_t Uint8 -> Prim (-1, "uint8", [])
| Int_t Uint16 -> Prim (-1, "uint16", [])
| Int_t Uint32 -> Prim (-1, "uint32", [])
| Int_t Uint64 -> Prim (-1, "uint64", [])
| Nat_t -> Prim (-1, "nat", [])
| Int_t -> Prim (-1, "int", [])
| String_t -> Prim (-1, "string", [])
| Tez_t -> Prim (-1, "tez", [])
| Bool_t -> Prim (-1, "bool", [])
@ -290,8 +281,10 @@ let rec unparse_data
= fun ty a -> match ty, a with
| Unit_t, () ->
Prim (-1, "Unit", [])
| Int_t k, v ->
Int (-1, Int64.to_string (to_int64 k v))
| Int_t, v ->
Int (-1, Script_int.to_string v)
| Nat_t, v ->
Int (-1, Script_int.to_string v)
| String_t, s ->
String (-1, s)
| Bool_t, true ->
@ -352,53 +345,20 @@ let rec unparse_data
(* ---- Equality witnesses --------------------------------------------------*)
type ('ta, 'tb) eq =
| Eq : 'same * 'same -> ('same, 'same) eq
type ('ta, 'tb) eq = Eq : 'same * 'same -> ('same, 'same) eq
let eq
: type t. t -> t -> (t, t) eq tzresult
= fun ta tb -> Ok (Eq (ta, tb))
let int_kind_eq
: type sa la sb lb. (sa, la) int_kind -> (sb, lb) int_kind ->
((sa, la) int_kind, (sb, lb) int_kind) eq tzresult
= fun ka kb -> match ka, kb with
| Int8, Int8 -> eq ka kb
| Uint8, Uint8 -> eq ka kb
| Int16, Int16 -> eq ka kb
| Uint16, Uint16 -> eq ka kb
| Int32, Int32 -> eq ka kb
| Uint32, Uint32 -> eq ka kb
| Int64, Int64 -> eq ka kb
| Uint64, Uint64 -> eq ka kb
| _ -> error @@ Inconsistent_types (Int_t ka, Int_t kb)
let unsigned_int_kind
: type sa la. (sa, la) int_kind -> (sa, unsigned) eq tzresult
= fun kind -> match kind with
| Uint8 -> eq Unsigned Unsigned
| Uint16 -> eq Unsigned Unsigned
| Uint32 -> eq Unsigned Unsigned
| Uint64 -> eq Unsigned Unsigned
| _ -> error @@ Bad_sign (Int_t kind)
let signed_int_kind
: type sa la. (sa, la) int_kind -> (sa, signed) eq tzresult
= fun kind -> match kind with
| Int8 -> eq Signed Signed
| Int16 -> eq Signed Signed
| Int32 -> eq Signed Signed
| Int64 -> eq Signed Signed
| _ -> error @@ Bad_sign (Int_t kind)
(* TODO: shall we allow operations to compare nats and ints ? *)
let comparable_ty_eq
: type ta tb.
ta comparable_ty -> tb comparable_ty ->
(ta comparable_ty, tb comparable_ty) eq tzresult
= fun ta tb -> match ta, tb with
| Int_key ka, Int_key kb ->
int_kind_eq ka kb >>? fun (Eq _) ->
(eq ta tb : (ta comparable_ty, tb comparable_ty) eq tzresult)
| Int_key, Int_key -> eq ta tb
| Nat_key, Nat_key -> eq ta tb
| String_key, String_key -> eq ta tb
| Tez_key, Tez_key -> eq ta tb
| Bool_key, Bool_key -> eq ta tb
@ -411,9 +371,8 @@ let rec ty_eq
= fun ta tb ->
match ta, tb with
| Unit_t, Unit_t -> eq ta tb
| Int_t ka, Int_t kb ->
int_kind_eq ka kb >>? fun (Eq _) ->
(eq ta tb : (ta ty, tb ty) eq tzresult)
| Int_t, Int_t -> eq ta tb
| Nat_t, Nat_t -> eq ta tb
| Key_t, Key_t -> eq ta tb
| String_t, String_t -> eq ta tb
| Signature_t, Signature_t -> eq ta tb
@ -505,24 +464,16 @@ let merge_branches
type ex_comparable_ty = Ex_comparable_ty : 'a comparable_ty -> ex_comparable_ty
type ex_ty = Ex_ty : 'a ty -> ex_ty
type ex_stack_ty = Ex_stack_ty : 'a stack_ty -> ex_stack_ty
type ex_int_kind = Ex_int_kind : ('s, 'l) int_kind -> ex_int_kind
let rec parse_comparable_ty : Script.expr -> ex_comparable_ty tzresult = function
| Prim (_, "int8", []) -> ok (Ex_comparable_ty (Int_key Int8))
| Prim (_, "int16", []) -> ok (Ex_comparable_ty (Int_key Int16))
| Prim (_, "int32", []) -> ok (Ex_comparable_ty (Int_key Int32))
| Prim (_, "int64", []) -> ok (Ex_comparable_ty (Int_key Int64))
| Prim (_, "uint8", []) -> ok (Ex_comparable_ty (Int_key Uint8))
| Prim (_, "uint16", []) -> ok (Ex_comparable_ty (Int_key Uint16))
| Prim (_, "uint32", []) -> ok (Ex_comparable_ty (Int_key Uint32))
| Prim (_, "uint64", []) -> ok (Ex_comparable_ty (Int_key Uint64))
| Prim (_, "int", []) -> ok (Ex_comparable_ty Int_key)
| Prim (_, "nat", []) -> ok (Ex_comparable_ty Nat_key)
| Prim (_, "string", []) -> ok (Ex_comparable_ty String_key)
| Prim (_, "tez", []) -> ok (Ex_comparable_ty Tez_key)
| Prim (_, "bool", []) -> ok (Ex_comparable_ty Bool_key)
| Prim (_, "key", []) -> ok (Ex_comparable_ty Key_key)
| Prim (_, "timestamp", []) -> ok (Ex_comparable_ty Timestamp_key)
| Prim (loc, ("int8" | "int16" | "int32" | "int64"
| "uint8" | "uint16" | "uint32" | "uint64"
| Prim (loc, ("int" | "nat"
| "string" | "tez" | "bool"
| "key" | "timestamp" as prim), l) ->
error (Invalid_arity (loc, prim, 0, List.length l))
@ -533,21 +484,14 @@ let rec parse_comparable_ty : Script.expr -> ex_comparable_ty tzresult = functio
error (Comparable_type_expected (loc, ty))
| expr ->
error @@ unexpected expr [] Type_namespace
[ "int8" ; "int16" ; "int32" ; "int64" ;
"uint8" ; "uint16" ; "uint32" ; "uint64" ;
[ "int" ; "nat" ;
"string" ; "tez" ; "bool" ;
"key" ; "timestamp" ]
and parse_ty : Script.expr -> ex_ty tzresult = function
| Prim (_, "unit", []) -> ok (Ex_ty Unit_t)
| Prim (_, "int8", []) -> ok (Ex_ty (Int_t Int8))
| Prim (_, "int16", []) -> ok (Ex_ty (Int_t Int16))
| Prim (_, "int32", []) -> ok (Ex_ty (Int_t Int32))
| Prim (_, "int64", []) -> ok (Ex_ty (Int_t Int64))
| Prim (_, "uint8", []) -> ok (Ex_ty (Int_t Uint8))
| Prim (_, "uint16", []) -> ok (Ex_ty (Int_t Uint16))
| Prim (_, "uint32", []) -> ok (Ex_ty (Int_t Uint32))
| Prim (_, "uint64", []) -> ok (Ex_ty (Int_t Uint64))
| Prim (_, "int", []) -> ok (Ex_ty Int_t)
| Prim (_, "nat", []) -> ok (Ex_ty Nat_t)
| Prim (_, "string", []) -> ok (Ex_ty String_t)
| Prim (_, "tez", []) -> ok (Ex_ty Tez_t)
| Prim (_, "bool", []) -> ok (Ex_ty Bool_t)
@ -586,8 +530,7 @@ and parse_ty : Script.expr -> ex_ty tzresult = function
| Prim (loc, ("pair" | "or" | "set" | "map"
| "list" | "option" | "lambda"
| "unit" | "signature" | "contract"
| "int8" | "int16" | "int32" | "int64"
| "uint8" | "uint16" | "uint32" | "uint64"
| "int" | "nat"
| "string" | "tez" | "bool"
| "key" | "timestamp" as prim), l) ->
error (Invalid_arity (loc, prim, 0, List.length l))
@ -596,15 +539,15 @@ and parse_ty : Script.expr -> ex_ty tzresult = function
[ "pair" ; "or" ; "set" ; "map" ;
"list" ; "option" ; "lambda" ;
"unit" ; "signature" ; "contract" ;
"int8" ; "int16" ; "int32" ; "int64" ;
"uint8" ; "uint16" ; "uint32" ; "uint64" ;
"string" ; "tez" ; "bool" ;
"int" ; "nat" ;
"string" ; "tez" ; "bool" ;
"key" ; "timestamp" ]
let comparable_ty_of_ty
: type a. int -> a ty -> a comparable_ty tzresult
= fun loc ty -> match ty with
| Int_t k -> ok (Int_key k)
| Int_t -> ok Int_key
| Nat_t -> ok Nat_key
| String_t -> ok String_key
| Tez_t -> ok Tez_key
| Bool_t -> ok Bool_key
@ -646,13 +589,22 @@ let rec parse_data
| String_t, expr ->
traced (fail (Invalid_kind (location expr, [ String_kind ], kind expr)))
(* Integers *)
| Int_t k, Int (_, v) -> begin try
match checked_of_int64 k (Int64.of_string v) with
| None -> raise Exit
| Some i -> return i
with _ -> fail (error ())
end
| Int_t _, expr ->
| Int_t, Int (_, v) ->
begin match Script_int.of_string v with
| None -> fail (error ())
| Some v -> return v
end
| Nat_t, Int (_, v) ->
begin match Script_int.of_string v with
| None -> fail (error ())
| Some v ->
if Compare.Int.(Script_int.compare v Script_int.zero >= 0) then
return (Script_int.abs v)
else fail (error ())
end
| Int_t, expr ->
traced (fail (Invalid_kind (location expr, [ Int_kind ], kind expr)))
| Nat_t, expr ->
traced (fail (Invalid_kind (location expr, [ Int_kind ], kind expr)))
(* Tez amounts *)
| Tez_t, String (_, v) -> begin try
@ -1060,13 +1012,11 @@ and parse_instr
return (Failed { descr })
(* timestamp operations *)
| Prim (loc, "ADD", []),
Item_t (Timestamp_t, Item_t (Int_t kind, rest)) ->
check_item (unsigned_int_kind kind) loc "ADD" 2 2 >>=? fun (Eq _) ->
return (typed loc (Add_timestamp_to_seconds kind, Item_t (Timestamp_t, rest)))
Item_t (Timestamp_t, Item_t (Nat_t, rest)) ->
return (typed loc (Add_timestamp_to_seconds, Item_t (Timestamp_t, rest)))
| Prim (loc, "ADD", []),
Item_t (Int_t kind, Item_t (Timestamp_t, rest)) ->
check_item (unsigned_int_kind kind) loc "ADD" 1 2 >>=? fun (Eq _) ->
return (typed loc (Add_seconds_to_timestamp kind, Item_t (Timestamp_t, rest)))
Item_t (Nat_t, Item_t (Timestamp_t, rest)) ->
return (typed loc (Add_seconds_to_timestamp, Item_t (Timestamp_t, rest)))
(* string operations *)
| Prim (loc, "CONCAT", []),
Item_t (String_t, Item_t (String_t, rest)) ->
@ -1079,13 +1029,11 @@ and parse_instr
Item_t (Tez_t, Item_t (Tez_t, rest)) ->
return (typed loc (Sub_tez, Item_t (Tez_t, rest)))
| Prim (loc, "MUL", []),
Item_t (Tez_t, Item_t (Int_t kind, rest)) ->
check_item (unsigned_int_kind kind) loc "MUL" 2 2 >>=? fun (Eq _) ->
return (typed loc (Mul_tez kind, Item_t (Tez_t, rest)))
Item_t (Tez_t, Item_t (Nat_t, rest)) ->
return (typed loc (Mul_teznat, Item_t (Tez_t, rest)))
| Prim (loc, "MUL", []),
Item_t (Int_t kind, Item_t (Tez_t, rest)) ->
check_item (unsigned_int_kind kind) loc "MUL" 1 2 >>=? fun (Eq _) ->
return (typed loc (Mul_tez' kind, Item_t (Tez_t, rest)))
Item_t (Nat_t, Item_t (Tez_t, rest)) ->
return (typed loc (Mul_nattez, Item_t (Tez_t, rest)))
(* boolean operations *)
| Prim (loc, "OR", []),
Item_t (Bool_t, Item_t (Bool_t, rest)) ->
@ -1100,144 +1048,140 @@ and parse_instr
Item_t (Bool_t, rest) ->
return (typed loc (Not, Item_t (Bool_t, rest)))
(* integer operations *)
| Prim (loc, "CHECKED_ABS", []),
Item_t (Int_t k, rest) ->
check_item (signed_int_kind k) loc "CHECKED_ABS" 1 1 >>=? fun (Eq _) ->
return (typed loc (Checked_abs_int k, Item_t (Int_t k, rest)))
| Prim (loc, "CHECKED_NEG", []),
Item_t (Int_t k, rest) ->
check_item (signed_int_kind k) loc "CHECKED_NEG" 1 1 >>=? fun (Eq _) ->
return (typed loc (Checked_neg_int k, Item_t (Int_t k, rest)))
| Prim (loc, "CHECKED_ADD", []),
Item_t (Int_t kl, Item_t (Int_t kr, rest)) ->
check_item (int_kind_eq kl kr) loc "CHECKED_ADD" 1 2 >>=? fun (Eq _) ->
return (typed loc (Checked_add_int kl, Item_t (Int_t kl, rest)))
| Prim (loc, "CHECKED_SUB", []),
Item_t (Int_t kl, Item_t (Int_t kr, rest)) ->
check_item (int_kind_eq kl kr) loc "CHECKED_SUB" 1 2 >>=? fun (Eq _) ->
return (typed loc (Checked_sub_int kl, Item_t (Int_t kl, rest)))
| Prim (loc, "CHECKED_MUL", []),
Item_t (Int_t kl, Item_t (Int_t kr, rest)) ->
check_item (int_kind_eq kl kr) loc "CHECKED_MUL" 1 2 >>=? fun (Eq _) ->
return (typed loc (Checked_mul_int kl, Item_t (Int_t kl, rest)))
| Prim (loc, "ABS", []),
Item_t (Int_t k, rest) ->
check_item (signed_int_kind k) loc "ABS" 1 1 >>=? fun (Eq _) ->
return (typed loc (Abs_int k, Item_t (Int_t k, rest)))
Item_t (Int_t, rest) ->
return (typed loc (Abs_int, Item_t (Nat_t, rest)))
| Prim (loc, "INT", []),
Item_t (Nat_t, rest) ->
return (typed loc (Int_nat, Item_t (Int_t, rest)))
| Prim (loc, "NEG", []),
Item_t (Int_t k, rest) ->
check_item (signed_int_kind k) loc "NEG" 1 1 >>=? fun (Eq _) ->
return (typed loc (Neg_int k, Item_t (Int_t k, rest)))
Item_t (Int_t, rest) ->
return (typed loc (Neg_int, Item_t (Int_t, rest)))
| Prim (loc, "NEG", []),
Item_t (Nat_t, rest) ->
return (typed loc (Neg_nat, Item_t (Int_t, rest)))
| Prim (loc, "ADD", []),
Item_t (Int_t kl, Item_t (Int_t kr, rest)) ->
check_item (int_kind_eq kl kr) loc "ADD" 1 2 >>=? fun (Eq _) ->
return (typed loc (Add_int kl, Item_t (Int_t kl, rest)))
Item_t (Int_t, Item_t (Int_t, rest)) ->
return (typed loc (Add_intint, Item_t (Int_t, rest)))
| Prim (loc, "ADD", []),
Item_t (Int_t, Item_t (Nat_t, rest)) ->
return (typed loc (Add_intnat, Item_t (Int_t, rest)))
| Prim (loc, "ADD", []),
Item_t (Nat_t, Item_t (Int_t, rest)) ->
return (typed loc (Add_natint, Item_t (Int_t, rest)))
| Prim (loc, "ADD", []),
Item_t (Nat_t, Item_t (Nat_t, rest)) ->
return (typed loc (Add_natnat, Item_t (Nat_t, rest)))
| Prim (loc, "SUB", []),
Item_t (Int_t kl, Item_t (Int_t kr, rest)) ->
check_item (int_kind_eq kl kr) loc "SUB" 1 2 >>=? fun (Eq _) ->
return (typed loc (Sub_int kl, Item_t (Int_t kl, rest)))
Item_t (Int_t, Item_t (Int_t, rest)) ->
return (typed loc (Sub_int, Item_t (Int_t, rest)))
| Prim (loc, "SUB", []),
Item_t (Int_t, Item_t (Nat_t, rest)) ->
return (typed loc (Sub_int, Item_t (Int_t, rest)))
| Prim (loc, "SUB", []),
Item_t (Nat_t, Item_t (Int_t, rest)) ->
return (typed loc (Sub_int, Item_t (Int_t, rest)))
| Prim (loc, "SUB", []),
Item_t (Nat_t, Item_t (Nat_t, rest)) ->
return (typed loc (Sub_int, Item_t (Int_t, rest)))
| Prim (loc, "MUL", []),
Item_t (Int_t kl, Item_t (Int_t kr, rest)) ->
check_item (int_kind_eq kl kr) loc "MUL" 1 2 >>=? fun (Eq _) ->
return (typed loc (Mul_int kl, Item_t (Int_t kl, rest)))
| Prim (loc, "DIV", []),
Item_t (Int_t kl, Item_t (Int_t kr, rest)) ->
check_item (int_kind_eq kl kr) loc "DIV" 1 2 >>=? fun (Eq _) ->
return (typed loc (Div_int kl, Item_t (Int_t kl, rest)))
| Prim (loc, "MOD", []),
Item_t (Int_t kl, Item_t (Int_t kr, rest)) ->
check_item (int_kind_eq kl kr) loc "MOD" 1 2 >>=? fun (Eq _) ->
return (typed loc (Mod_int kl, Item_t (Int_t kl, rest)))
Item_t (Int_t, Item_t (Int_t, rest)) ->
return (typed loc (Mul_intint, Item_t (Int_t, rest)))
| Prim (loc, "MUL", []),
Item_t (Int_t, Item_t (Nat_t, rest)) ->
return (typed loc (Mul_intnat, Item_t (Int_t, rest)))
| Prim (loc, "MUL", []),
Item_t (Nat_t, Item_t (Int_t, rest)) ->
return (typed loc (Mul_natint, Item_t (Int_t, rest)))
| Prim (loc, "MUL", []),
Item_t (Nat_t, Item_t (Nat_t, rest)) ->
return (typed loc (Mul_natnat, Item_t (Nat_t, rest)))
| Prim (loc, "EDIV", []),
Item_t (Tez_t, Item_t (Nat_t, rest)) ->
return (typed loc (Ediv_teznat,
Item_t (Option_t (Pair_t (Tez_t,Tez_t)), rest)))
| Prim (loc, "EDIV", []),
Item_t (Tez_t, Item_t (Tez_t, rest)) ->
return (typed loc (Ediv_tez,
Item_t (Option_t (Pair_t (Nat_t,Tez_t)), rest)))
| Prim (loc, "EDIV", []),
Item_t (Int_t, Item_t (Int_t, rest)) ->
return (typed loc (Ediv_intint,
Item_t (Option_t (Pair_t (Int_t,Nat_t)), rest)))
| Prim (loc, "EDIV", []),
Item_t (Int_t, Item_t (Nat_t, rest)) ->
return (typed loc (Ediv_intnat,
Item_t (Option_t (Pair_t (Int_t,Nat_t)), rest)))
| Prim (loc, "EDIV", []),
Item_t (Nat_t, Item_t (Int_t, rest)) ->
return (typed loc (Ediv_natint,
Item_t (Option_t (Pair_t (Int_t,Nat_t)), rest)))
| Prim (loc, "EDIV", []),
Item_t (Nat_t, Item_t (Nat_t, rest)) ->
return (typed loc (Ediv_natnat,
Item_t (Option_t (Pair_t (Nat_t,Nat_t)), rest)))
| Prim (loc, "LSL", []),
Item_t (Int_t k, Item_t (Int_t Uint8, rest)) ->
check_item (unsigned_int_kind k) loc "LSL" 1 2 >>=? fun (Eq _) ->
return (typed loc (Lsl_int k, Item_t (Int_t k, rest)))
Item_t (Nat_t, Item_t (Nat_t, rest)) ->
return (typed loc (Lsl_nat, Item_t (Nat_t, rest)))
| Prim (loc, "LSR", []),
Item_t (Int_t k, Item_t (Int_t Uint8, rest)) ->
check_item (unsigned_int_kind k) loc "LSR" 1 2 >>=? fun (Eq _) ->
return (typed loc (Lsr_int k, Item_t (Int_t k, rest)))
Item_t (Nat_t, Item_t (Nat_t, rest)) ->
return (typed loc (Lsr_nat, Item_t (Nat_t, rest)))
| Prim (loc, "OR", []),
Item_t (Int_t kl, Item_t (Int_t kr, rest)) ->
check_item (unsigned_int_kind kl) loc "OR" 1 2 >>=? fun (Eq _) ->
check_item (int_kind_eq kl kr) loc "OR" 1 2 >>=? fun (Eq _) ->
return (typed loc (Or_int kl, Item_t (Int_t kl, rest)))
Item_t (Nat_t, Item_t (Nat_t, rest)) ->
return (typed loc (Or_nat, Item_t (Nat_t, rest)))
| Prim (loc, "AND", []),
Item_t (Int_t kl, Item_t (Int_t kr, rest)) ->
check_item (unsigned_int_kind kl) loc "AND" 1 2 >>=? fun (Eq _) ->
check_item (int_kind_eq kl kr) loc "AND" 1 2 >>=? fun (Eq _) ->
return (typed loc (And_int kl, Item_t (Int_t kl, rest)))
Item_t (Nat_t, Item_t (Nat_t, rest)) ->
return (typed loc (And_nat, Item_t (Nat_t, rest)))
| Prim (loc, "XOR", []),
Item_t (Int_t kl, Item_t (Int_t kr, rest)) ->
check_item (unsigned_int_kind kl) loc "XOR" 1 2 >>=? fun (Eq _) ->
check_item (int_kind_eq kl kr) loc "XOR" 1 2 >>=? fun (Eq _) ->
return (typed loc (Xor_int kl, Item_t (Int_t kl, rest)))
Item_t (Nat_t, Item_t (Nat_t, rest)) ->
return (typed loc (Xor_nat, Item_t (Nat_t, rest)))
| Prim (loc, "NOT", []),
Item_t (Int_t k, rest) ->
check_item (unsigned_int_kind k) loc "NOT" 1 1 >>=? fun (Eq _) ->
return (typed loc (Not_int k, Item_t (Int_t k, rest)))
Item_t (Int_t, rest) ->
return (typed loc (Not_int, Item_t (Int_t, rest)))
| Prim (loc, "NOT", []),
Item_t (Nat_t, rest) ->
return (typed loc (Not_nat, Item_t (Int_t, rest)))
(* comparison *)
| Prim (loc, "COMPARE", []),
Item_t (Int_t kl, Item_t (Int_t kr, rest)) ->
check_item (int_kind_eq kl kr) loc "COMPARE" 1 2 >>=? fun (Eq _) ->
return (typed loc (Compare (Int_key kl), Item_t (Int_t Int64, rest)))
Item_t (Int_t, Item_t (Int_t, rest)) ->
return (typed loc (Compare Int_key, Item_t (Int_t, rest)))
| Prim (loc, "COMPARE", []),
Item_t (Nat_t, Item_t (Nat_t, rest)) ->
return (typed loc (Compare Nat_key, Item_t (Int_t, rest)))
| Prim (loc, "COMPARE", []),
Item_t (Bool_t, Item_t (Bool_t, rest)) ->
return (typed loc (Compare Bool_key, Item_t (Int_t Int64, rest)))
return (typed loc (Compare Bool_key, Item_t (Int_t, rest)))
| Prim (loc, "COMPARE", []),
Item_t (String_t, Item_t (String_t, rest)) ->
return (typed loc (Compare String_key, Item_t (Int_t Int64, rest)))
return (typed loc (Compare String_key, Item_t (Int_t, rest)))
| Prim (loc, "COMPARE", []),
Item_t (Tez_t, Item_t (Tez_t, rest)) ->
return (typed loc (Compare Tez_key, Item_t (Int_t Int64, rest)))
return (typed loc (Compare Tez_key, Item_t (Int_t, rest)))
| Prim (loc, "COMPARE", []),
Item_t (Key_t, Item_t (Key_t, rest)) ->
return (typed loc (Compare Key_key, Item_t (Int_t Int64, rest)))
return (typed loc (Compare Key_key, Item_t (Int_t, rest)))
| Prim (loc, "COMPARE", []),
Item_t (Timestamp_t, Item_t (Timestamp_t, rest)) ->
return (typed loc (Compare Timestamp_key, Item_t (Int_t Int64, rest)))
return (typed loc (Compare Timestamp_key, Item_t (Int_t, rest)))
(* comparators *)
| Prim (loc, "EQ", []),
Item_t (Int_t Int64, rest) ->
Item_t (Int_t, rest) ->
return (typed loc (Eq, Item_t (Bool_t, rest)))
| Prim (loc, "NEQ", []),
Item_t (Int_t Int64, rest) ->
Item_t (Int_t, rest) ->
return (typed loc (Neq, Item_t (Bool_t, rest)))
| Prim (loc, "LT", []),
Item_t (Int_t Int64, rest) ->
Item_t (Int_t, rest) ->
return (typed loc (Lt, Item_t (Bool_t, rest)))
| Prim (loc, "GT", []),
Item_t (Int_t Int64, rest) ->
Item_t (Int_t, rest) ->
return (typed loc (Gt, Item_t (Bool_t, rest)))
| Prim (loc, "LE", []),
Item_t (Int_t Int64, rest) ->
Item_t (Int_t, rest) ->
return (typed loc (Le, Item_t (Bool_t, rest)))
| Prim (loc, "GE", []),
Item_t (Int_t Int64, rest) ->
Item_t (Int_t, rest) ->
return (typed loc (Ge, Item_t (Bool_t, rest)))
(* casts *)
| Prim (loc, "CHECKED_CAST", [ t ]),
stack ->
(Lwt.return (parse_ty t)) >>=? fun (Ex_ty ty) -> begin match ty, stack with
| Int_t kt,
Item_t (Int_t kf, rest) ->
return (typed loc (Checked_int_of_int (kf, kt),
Item_t (Int_t kt, rest)))
| ty, Item_t (ty', _) ->
fail (Undefined_cast (loc, ty', ty))
| _, Empty_t ->
fail (Bad_stack (loc, "CHECKED_CAST", 1, stack))
end
| Prim (loc, "CAST", [ t ]),
stack ->
(Lwt.return (parse_ty t)) >>=? fun (Ex_ty ty) -> begin match ty, stack with
| Int_t kt, Item_t (Int_t kf, rest) ->
return (typed loc (Int_of_int (kf, kt),
Item_t (Int_t kt, rest)))
| ty, Item_t (ty', _) ->
fail (Undefined_cast (loc, ty', ty))
| _, Empty_t ->
fail (Bad_stack (loc, "CAST", 1, stack))
end
(* protocol *)
| Prim (loc, "MANAGER", []),
Item_t (Contract_t _, rest) ->
@ -1299,7 +1243,7 @@ and parse_instr
return (typed loc (H t, Item_t (String_t, rest)))
| Prim (loc, "STEPS_TO_QUOTA", []),
stack ->
return (typed loc (Steps_to_quota, Item_t (Int_t Uint32, stack)))
return (typed loc (Steps_to_quota, Item_t (Nat_t, stack)))
| Prim (loc, "SOURCE", [ ta; tb ]),
stack ->
(Lwt.return (parse_ty ta)) >>=? fun (Ex_ty ta) ->
@ -1311,9 +1255,8 @@ and parse_instr
| "MEM" | "UPDATE" | "MAP" | "REDUCE"
| "GET" | "EXEC" | "FAIL"
| "CONCAT" | "ADD" | "SUB"
| "MUL" | "DIV" | "MOD" | "OR" | "AND" | "XOR"
| "NOT" | "CHECKED_ABS" | "CHECKED_NEG"
| "CHECKED_ADD" | "CHECKED_SUB" | "CHECKED_MUL"
| "MUL" | "EDIV" | "OR" | "AND" | "XOR"
| "NOT"
| "ABS" | "NEG" | "LSL" | "LSR"
| "COMPARE" | "EQ" | "NEQ"
| "LT" | "GT" | "LE" | "GE"
@ -1324,7 +1267,7 @@ and parse_instr
as name), (_ :: _ as l)), _ ->
fail (Invalid_arity (loc, name, 0, List.length l))
| Prim (loc, ("NONE" | "LEFT" | "RIGHT" | "NIL"
| "EMPTY_SET" | "DIP" | "CHECKED_CAST" | "CAST" | "LOOP"
| "EMPTY_SET" | "DIP" | "LOOP"
as name), ([]
| _ :: _ :: _ as l)), _ ->
fail (Invalid_arity (loc, name, 1, List.length l))
@ -1337,11 +1280,9 @@ and parse_instr
| _ :: _ :: _ :: _ :: _ as l)), _ ->
fail (Invalid_arity (loc, "LAMBDA", 3, List.length l))
(* Stack errors *)
| Prim (loc, ("ADD" | "SUB" | "MUL" | "DIV" | "MOD"
| Prim (loc, ("ADD" | "SUB" | "MUL" | "EDIV"
| "AND" | "OR" | "XOR" | "LSL" | "LSR"
| "CONCAT" | "COMPARE"
| "CHECKED_ABS" | "CHECKED_NEG"
| "CHECKED_ADD" | "CHECKED_SUB" | "CHECKED_MUL" as name), []),
| "CONCAT" | "COMPARE" as name), []),
Item_t (ta, Item_t (tb, _)) ->
fail (Undefined_binop (loc, name, ta, tb))
| Prim (loc, ("NEG" | "ABS" | "NOT"
@ -1363,17 +1304,15 @@ and parse_instr
| Prim (loc, ("DROP" | "DUP" | "CAR" | "CDR" | "SOME" | "H" | "DIP"
| "IF_NONE" | "LEFT" | "RIGHT" | "IF_LEFT" | "IF"
| "LOOP" | "IF_CONS" | "MANAGER" | "DEFAULT_ACCOUNT"
| "NEG" | "ABS" | "NOT"
| "NEG" | "ABS" | "INT" | "NOT"
| "EQ" | "NEQ" | "LT" | "GT" | "LE" | "GE" as name), _),
stack ->
fail (Bad_stack (loc, name, 1, stack))
| Prim (loc, ("SWAP" | "PAIR" | "CONS"
| "MAP" | "GET" | "MEM" | "EXEC"
| "CHECK_SIGNATURE" | "ADD" | "SUB" | "MUL"
| "DIV" | "MOD" | "AND" | "OR" | "XOR"
| "LSL" | "LSR" | "CONCAT"
| "CHECKED_ABS" | "CHECKED_NEG" | "CHECKED_ADD"
| "CHECKED_SUB" | "CHECKED_MUL" | "COMPARE" as name), _),
| "EDIV" | "AND" | "OR" | "XOR"
| "LSL" | "LSR" | "CONCAT" as name), _),
stack ->
fail (Bad_stack (loc, name, 2, stack))
(* Generic parsing errors *)
@ -1384,17 +1323,16 @@ and parse_instr
"MEM" ; "UPDATE" ; "MAP" ; "REDUCE" ;
"GET" ; "EXEC" ; "FAIL" ;
"CONCAT" ; "ADD" ; "SUB" ;
"MUL" ; "DIV" ; "MOD" ; "OR" ; "AND" ; "XOR" ;
"NOT" ; "CHECKED_ABS" ; "CHECKED_NEG" ;
"CHECKED_ADD" ; "CHECKED_SUB" ; "CHECKED_MUL" ;
"ABS" ; "NEG" ; "LSL" ; "LSR" ;
"MUL" ; "EDIV" ; "OR" ; "AND" ; "XOR" ;
"NOT" ;
"ABS" ; "INT"; "NEG" ; "LSL" ; "LSR" ;
"COMPARE" ; "EQ" ; "NEQ" ;
"LT" ; "GT" ; "LE" ; "GE" ;
"MANAGER" ; "TRANSFER_TOKENS" ; "CREATE_ACCOUNT" ;
"CREATE_CONTRACT" ; "NOW" ; "AMOUNT" ; "BALANCE" ;
"DEFAULT_ACCOUNT" ; "CHECK_SIGNATURE" ; "H" ; "STEPS_TO_QUOTA" ;
"PUSH" ; "NONE" ; "LEFT" ; "RIGHT" ; "NIL" ;
"EMPTY_SET" ; "DIP" ; "CHECKED_CAST" ; "CAST" ; "LOOP" ;
"EMPTY_SET" ; "DIP" ; "LOOP" ;
"IF_NONE" ; "IF_LEFT" ; "IF_CONS" ;
"EMPTY_MAP" ; "IF" ; "SOURCE" ; "LAMBDA" ]
@ -1511,7 +1449,8 @@ let type_map descr =
= fun acc ty v ->
match ty, v with
| Unit_t, _ -> acc
| Int_t _, _ -> acc
| Int_t, _ -> acc
| Nat_t, _ -> acc
| Signature_t, _ -> acc
| String_t, _ -> acc
| Tez_t, _ -> acc
@ -1720,21 +1659,6 @@ let () =
| _ -> None)
(fun (loc, ()) ->
Fail_not_in_tail_position loc) ;
register_error_kind
`Permanent
~id:"undefinedCastTypeError"
~title: "Undefined cast (typechecking error)"
~description:
"A CAST operation is performed to or from an unsupported type."
(located (obj2
(req "wrongInputType" ex_ty_enc)
(req "wrongOutputType" ex_ty_enc)))
(function
| Undefined_cast (loc, tyl, tyr) ->
Some (loc, (Ex_ty tyl, Ex_ty tyr))
| _ -> None)
(fun (loc, (Ex_ty tyl, Ex_ty tyr)) ->
Undefined_cast (loc, tyl, tyr)) ;
register_error_kind
`Permanent
~id:"undefinedBinopTypeError"
@ -1912,21 +1836,7 @@ let () =
| _ -> None)
(fun (Ex_ty tya, Ex_ty tyb) ->
Inconsistent_types (tya, tyb)) ;
register_error_kind
`Permanent
~id:"badSignTypeError"
~title: "Bad sign (typechecking error)"
~description:
"A signed (resp. unsigned) integer kind was used in a place \
where only unsigned (resp. signed) integers can be used, \
this error is always accompanied \
with another error that provides more context."
(obj1 (req "wrongIntegerType" ex_ty_enc))
(function
| Bad_sign ty -> Some (Ex_ty ty)
| _ -> None)
(fun (Ex_ty ty) ->
Bad_sign ty) ;
(* Toplevel errors *)
register_error_kind
`Permanent

View File

@ -7,6 +7,17 @@
(* *)
(**************************************************************************)
(* A smart contract is some code and some storage. The storage has a
type and an initial value. The code is the code itself, the types of
its arguments, the type of its result, and the type of the storage
it is using.
All of them are expressed in a simple [expr] type, combining
[Int] (integer constant), [String] (string constant), [Prim]
(a generic primitive for most operations) and [Seq] a sequence
of operations.
*)
type location =
int

View File

@ -14,7 +14,8 @@ open Script_int
(* ---- Auxiliary types -----------------------------------------------------*)
type 'ty comparable_ty =
| Int_key : ('s, 'l) int_kind -> ('s, 'l) int_val comparable_ty
| Int_key : (z num) comparable_ty
| Nat_key : (n num) comparable_ty
| String_key : string comparable_ty
| Tez_key : Tez.t comparable_ty
| Bool_key : bool comparable_ty
@ -60,7 +61,8 @@ and ('arg, 'ret) typed_contract =
and 'ty ty =
| Unit_t : unit ty
| Int_t : ('s, 'l) int_kind -> ('s, 'l) int_val ty
| Int_t : z num ty
| Nat_t : n num ty
| Signature_t : signature ty
| String_t : string ty
| Tez_t : Tez.t ty
@ -162,19 +164,27 @@ and ('bef, 'aft) instr =
| Concat :
(string * (string * 'rest), string * 'rest) instr
(* timestamp operations *)
| Add_seconds_to_timestamp : (unsigned, 'l) int_kind ->
((unsigned, 'l) int_val * (Timestamp.t * 'rest), Timestamp.t * 'rest) instr
| Add_timestamp_to_seconds : (unsigned, 'l) int_kind ->
(Timestamp.t * ((unsigned, 'l) int_val * 'rest), Timestamp.t * 'rest) instr
(* TODO: check if we need int instead of nat *)
| Add_seconds_to_timestamp :
(n num * (Timestamp.t * 'rest), Timestamp.t * 'rest) instr
| Add_timestamp_to_seconds :
(Timestamp.t * (n num * 'rest), Timestamp.t * 'rest) instr
(* currency operations *)
(* TODO: we can either just have conversions to/from integers and
do all operations on integers, or we need more operations on
Tez. Also Sub_tez should return Tez.t option (if negative) and *)
| Add_tez :
(Tez.t * (Tez.t * 'rest), Tez.t * 'rest) instr
| Sub_tez :
(Tez.t * (Tez.t * 'rest), Tez.t * 'rest) instr
| Mul_tez : (unsigned, 'l) int_kind ->
(Tez.t * ((unsigned, 'l) int_val * 'rest), Tez.t * 'rest) instr
| Mul_tez' : (unsigned, 'l) int_kind ->
((unsigned, 'l) int_val * (Tez.t * 'rest), Tez.t * 'rest) instr
| Mul_teznat :
(Tez.t * (n num * 'rest), Tez.t * 'rest) instr
| Mul_nattez :
(n num * (Tez.t * 'rest), Tez.t * 'rest) instr
| Ediv_teznat :
(Tez.t * (n num * 'rest), ((Tez.t, Tez.t) pair) option * 'rest) instr
| Ediv_tez :
(Tez.t * (Tez.t * 'rest), ((n num, Tez.t) pair) option * 'rest) instr
(* boolean operations *)
| Or :
(bool * (bool * 'rest), bool * 'rest) instr
@ -185,42 +195,54 @@ and ('bef, 'aft) instr =
| Not :
(bool * 'rest, bool * 'rest) instr
(* integer operations *)
| Checked_neg_int : (signed, 'l) int_kind ->
((signed, 'l) int_val * 'rest, (signed, 'l) int_val * 'rest) instr
| Checked_abs_int : (signed, 'l) int_kind ->
((signed, 'l) int_val * 'rest, (signed, 'l) int_val * 'rest) instr
| Checked_add_int : ('s, 'l) int_kind ->
(('s, 'l) int_val * (('s, 'l) int_val * 'rest), ('s, 'l) int_val * 'rest) instr
| Checked_sub_int : ('s, 'l) int_kind ->
(('s, 'l) int_val * (('s, 'l) int_val * 'rest), ('s, 'l) int_val * 'rest) instr
| Checked_mul_int : ('s, 'l) int_kind ->
(('s, 'l) int_val * (('s, 'l) int_val * 'rest), ('s, 'l) int_val * 'rest) instr
| Neg_int : (signed, 'l) int_kind ->
((signed, 'l) int_val * 'rest, (signed, 'l) int_val * 'rest) instr
| Abs_int : (signed, 'l) int_kind ->
((signed, 'l) int_val * 'rest, (signed, 'l) int_val * 'rest) instr
| Add_int : ('s, 'l) int_kind ->
(('s, 'l) int_val * (('s, 'l) int_val * 'rest), ('s, 'l) int_val * 'rest) instr
| Sub_int : ('s, 'l) int_kind ->
(('s, 'l) int_val * (('s, 'l) int_val * 'rest), ('s, 'l) int_val * 'rest) instr
| Mul_int : ('s, 'l) int_kind ->
(('s, 'l) int_val * (('s, 'l) int_val * 'rest), ('s, 'l) int_val * 'rest) instr
| Div_int : ('s, 'l) int_kind ->
(('s, 'l) int_val * (('s, 'l) int_val * 'rest), ('s, 'l) int_val * 'rest) instr
| Mod_int : ('s, 'l) int_kind ->
(('s, 'l) int_val * (('s, 'l) int_val * 'rest), ('s, 'l) int_val * 'rest) instr
| Lsl_int : (unsigned, 'l) int_kind ->
((unsigned, 'l) int_val * ((unsigned, eight) int_val * 'rest), (unsigned, 'l) int_val * 'rest) instr
| Lsr_int : (unsigned, 'l) int_kind ->
((unsigned, 'l) int_val * ((unsigned, eight) int_val * 'rest), (unsigned, 'l) int_val * 'rest) instr
| Or_int : (unsigned, 'l) int_kind ->
((unsigned, 'l) int_val * ((unsigned, 'l) int_val * 'rest), (unsigned, 'l) int_val * 'rest) instr
| And_int : (unsigned, 'l) int_kind ->
((unsigned, 'l) int_val * ((unsigned, 'l) int_val * 'rest), (unsigned, 'l) int_val * 'rest) instr
| Xor_int : (unsigned, 'l) int_kind ->
((unsigned, 'l) int_val * ((unsigned, 'l) int_val * 'rest), (unsigned, 'l) int_val * 'rest) instr
| Not_int : (unsigned, 'l) int_kind ->
((unsigned, 'l) int_val * 'rest, (unsigned, 'l) int_val * 'rest) instr
| Neg_nat :
(n num * 'rest, z num * 'rest) instr
| Neg_int :
(z num * 'rest, z num * 'rest) instr
| Abs_int :
(z num * 'rest, n num * 'rest) instr
| Int_nat :
(n num * 'rest, z num * 'rest) instr
| Add_intint :
(z num * (z num * 'rest), z num * 'rest) instr
| Add_intnat :
(z num * (n num * 'rest), z num * 'rest) instr
| Add_natint :
(n num * (z num * 'rest), z num * 'rest) instr
| Add_natnat :
(n num * (n num * 'rest), n num * 'rest) instr
| Sub_int :
('s num * ('t num * 'rest), z num * 'rest) instr
| Mul_intint :
(z num * (z num * 'rest), z num * 'rest) instr
| Mul_intnat :
(z num * (n num * 'rest), z num * 'rest) instr
| Mul_natint :
(n num * (z num * 'rest), z num * 'rest) instr
| Mul_natnat :
(n num * (n num * 'rest), n num * 'rest) instr
| Ediv_intint :
(z num * (z num * 'rest), ((z num, n num) pair) option * 'rest) instr
| Ediv_intnat :
(z num * (n num * 'rest), ((z num, n num) pair) option * 'rest) instr
| Ediv_natint :
(n num * (z num * 'rest), ((z num, n num) pair) option * 'rest) instr
| Ediv_natnat :
(n num * (n num * 'rest), ((n num, n num) pair) option * 'rest) instr
| Lsl_nat :
(n num * (n num * 'rest), n num * 'rest) instr
| Lsr_nat :
(n num * (n num * 'rest), n num * 'rest) instr
| Or_nat :
(n num * (n num * 'rest), n num * 'rest) instr
| And_nat :
(n num * (n num * 'rest), n num * 'rest) instr
| Xor_nat :
(n num * (n num * 'rest), n num * 'rest) instr
| Not_nat :
(n num * 'rest, z num * 'rest) instr
| Not_int :
(z num * 'rest, z num * 'rest) instr
(* control *)
| Seq : ('bef, 'trans) descr * ('trans, 'aft) descr ->
('bef, 'aft) instr
@ -235,31 +257,27 @@ and ('bef, 'aft) instr =
| Lambda : ('arg, 'ret) lambda ->
('rest, ('arg, 'ret) lambda * 'rest) instr
| Fail :
('bef, 'aft) instr
('bef, 'aft) instr
| Nop :
('rest, 'rest) instr
(* comparison *)
| Compare : 'a comparable_ty ->
('a * ('a * 'rest), (signed, sixtyfour) int_val * 'rest) instr
('a * ('a * 'rest), z num * 'rest) instr
(* comparators *)
| Eq :
((signed, sixtyfour) int_val * 'rest, bool * 'rest) instr
(z num * 'rest, bool * 'rest) instr
| Neq :
((signed, sixtyfour) int_val * 'rest, bool * 'rest) instr
(z num * 'rest, bool * 'rest) instr
| Lt :
((signed, sixtyfour) int_val * 'rest, bool * 'rest) instr
(z num * 'rest, bool * 'rest) instr
| Gt :
((signed, sixtyfour) int_val * 'rest, bool * 'rest) instr
(z num * 'rest, bool * 'rest) instr
| Le :
((signed, sixtyfour) int_val * 'rest, bool * 'rest) instr
(z num * 'rest, bool * 'rest) instr
| Ge :
((signed, sixtyfour) int_val * 'rest, bool * 'rest) instr
(* casts *)
| Int_of_int : ('sf, 'lf) int_kind * ('st, 'lt) int_kind ->
(('sf, 'lf) int_val * 'rest, ('st, 'lt) int_val * 'rest) instr
| Checked_int_of_int : ('sf, 'lf) int_kind * ('st, 'lt) int_kind ->
(('sf, 'lf) int_val * 'rest, ('st, 'lt) int_val * 'rest) instr
(* protocol *)
(z num * 'rest, bool * 'rest) instr
(* protocol *)
| Manager :
(('arg, 'ret) typed_contract * 'rest, public_key_hash * 'rest) instr
| Transfer_tokens : 'sto ty ->
@ -267,10 +285,11 @@ and ('bef, 'aft) instr =
| Create_account :
(public_key_hash * (public_key_hash option * (bool * (Tez.t * 'rest))),
(unit, unit) typed_contract * 'rest) instr
| Default_account : (public_key_hash * 'rest, (unit, unit) typed_contract * 'rest) instr
| Default_account :
(public_key_hash * 'rest, (unit, unit) typed_contract * 'rest) instr
| Create_contract : 'g ty * 'p ty * 'r ty ->
(public_key_hash * (public_key_hash option * (bool * (bool * (Tez.t *
(('p * 'g, 'r * 'g) lambda * ('g * 'rest)))))),
(('p * 'g, 'r * 'g) lambda * ('g * 'rest)))))),
('p, 'r) typed_contract * 'rest) instr
| Now :
('rest, Timestamp.t * 'rest) instr
@ -280,8 +299,8 @@ and ('bef, 'aft) instr =
(public_key_hash * ((signature * string) * 'rest), bool * 'rest) instr
| H : 'a ty ->
('a * 'rest, string * 'rest) instr
| Steps_to_quota :
('rest, (unsigned, thirtytwo) int_val * 'rest) instr
| Steps_to_quota : (* TODO: check that it always returns a nat *)
('rest, n num * 'rest) instr
| Source : 'p ty * 'r ty ->
('rest, ('p, 'r) typed_contract * 'rest) instr
| Amount :

View File

@ -0,0 +1,76 @@
(**************************************************************************)
(* *)
(* Copyright (c) 2014 - 2016. *)
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* All rights reserved. No warranty, explicit or implicit, provided. *)
(* *)
(**************************************************************************)
type t
val zero: t
val one: t
external abs: t -> t = "ml_z_abs" "ml_as_z_abs"
(** Absolute value. *)
external neg: t -> t = "ml_z_neg" "ml_as_z_neg"
(** Unary negation. *)
external add: t -> t -> t = "ml_z_add" "ml_as_z_add"
(** Addition. *)
external sub: t -> t -> t = "ml_z_sub" "ml_as_z_sub"
(** Subtraction. *)
external mul: t -> t -> t = "ml_z_mul" "ml_as_z_mul"
(** Multiplication. *)
val ediv_rem: t -> t -> (t * t)
(** Euclidean division and remainder. [ediv_rem a b] returns a pair [(q, r)]
such that [a = b * q + r] and [0 <= r < |b|].
Raises [Division_by_zero] if [b = 0].
*)
external logand: t -> t -> t = "ml_z_logand" "ml_as_z_logand"
(** Bitwise logical and. *)
external logor: t -> t -> t = "ml_z_logor" "ml_as_z_logor"
(** Bitwise logical or. *)
external logxor: t -> t -> t = "ml_z_logxor" "ml_as_z_logxor"
(** Bitwise logical exclusive or. *)
external lognot: t -> t = "ml_z_lognot" "ml_as_z_lognot"
(** Bitwise logical negation.
The identity [lognot a]=[-a-1] always hold.
*)
external shift_left: t -> int -> t = "ml_z_shift_left" "ml_as_z_shift_left"
(** Shifts to the left.
Equivalent to a multiplication by a power of 2.
The second argument must be non-negative.
*)
external shift_right: t -> int -> t = "ml_z_shift_right" "ml_as_z_shift_right"
(** Shifts to the right.
This is an arithmetic shift,
equivalent to a division by a power of 2 with rounding towards -oo.
The second argument must be non-negative.
*)
val to_string: t -> string
val of_string: string -> t
external to_int64: t -> int64 = "ml_z_to_int64"
(** Converts to a 64-bit integer. May raise [Overflow]. *)
external of_int64: int64 -> t = "ml_z_of_int64"
(** Converts from a 64-bit integer. *)
external to_int: t -> int = "ml_z_to_int"
(** Converts to a base integer. May raise an [Overflow]. *)
external of_int: int -> t = "ml_z_of_int" [@@ noalloc]
(** Converts from a base integer. *)
external equal: t -> t -> bool = "ml_z_equal" [@@ noalloc]
external compare: t -> t -> int = "ml_z_compare" [@@ noalloc]