big commit, will surely need to be reversed
This commit is contained in:
parent
260c56ad58
commit
d02475f1bf
@ -23,279 +23,5 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(*****************************************************************************)
|
(*****************************************************************************)
|
||||||
|
|
||||||
type annot = string list
|
include Micheline_main
|
||||||
|
module Michelson_primitives = Michelson_primitives
|
||||||
type ('l, 'p) node =
|
|
||||||
| Int of 'l * Z.t
|
|
||||||
| String of 'l * string
|
|
||||||
| Bytes of 'l * MBytes.t
|
|
||||||
| Prim of 'l * 'p * ('l, 'p) node list * annot
|
|
||||||
| Seq of 'l * ('l, 'p) node list
|
|
||||||
|
|
||||||
type canonical_location = int
|
|
||||||
|
|
||||||
type 'p canonical = Canonical of (canonical_location, 'p) node
|
|
||||||
|
|
||||||
let canonical_location_encoding =
|
|
||||||
let open Data_encoding in
|
|
||||||
def
|
|
||||||
"micheline.location"
|
|
||||||
~title:
|
|
||||||
"Canonical location in a Micheline expression"
|
|
||||||
~description:
|
|
||||||
"The location of a node in a Micheline expression tree \
|
|
||||||
in prefix order, with zero being the root and adding one \
|
|
||||||
for every basic node, sequence and primitive application." @@
|
|
||||||
int31
|
|
||||||
|
|
||||||
let location = function
|
|
||||||
| Int (loc, _) -> loc
|
|
||||||
| String (loc, _) -> loc
|
|
||||||
| Bytes (loc, _) -> loc
|
|
||||||
| Seq (loc, _) -> loc
|
|
||||||
| Prim (loc, _, _, _) -> loc
|
|
||||||
|
|
||||||
let annotations = function
|
|
||||||
| Int (_, _) -> []
|
|
||||||
| String (_, _) -> []
|
|
||||||
| Bytes (_, _) -> []
|
|
||||||
| Seq (_, _) -> []
|
|
||||||
| Prim (_, _, _, annots) -> annots
|
|
||||||
|
|
||||||
let root (Canonical expr) = expr
|
|
||||||
|
|
||||||
let strip_locations root =
|
|
||||||
let id = let id = ref (-1) in fun () -> incr id ; !id in
|
|
||||||
let rec strip_locations l =
|
|
||||||
let id = id () in
|
|
||||||
match l with
|
|
||||||
| Int (_, v) ->
|
|
||||||
Int (id, v)
|
|
||||||
| String (_, v) ->
|
|
||||||
String (id, v)
|
|
||||||
| Bytes (_, v) ->
|
|
||||||
Bytes (id, v)
|
|
||||||
| Seq (_, seq) ->
|
|
||||||
Seq (id, List.map strip_locations seq)
|
|
||||||
| Prim (_, name, seq, annots) ->
|
|
||||||
Prim (id, name, List.map strip_locations seq, annots) in
|
|
||||||
Canonical (strip_locations root)
|
|
||||||
|
|
||||||
let extract_locations root =
|
|
||||||
let id = let id = ref (-1) in fun () -> incr id ; !id in
|
|
||||||
let loc_table = ref [] in
|
|
||||||
let rec strip_locations l =
|
|
||||||
let id = id () in
|
|
||||||
match l with
|
|
||||||
| Int (loc, v) ->
|
|
||||||
loc_table := (id, loc) :: !loc_table ;
|
|
||||||
Int (id, v)
|
|
||||||
| String (loc, v) ->
|
|
||||||
loc_table := (id, loc) :: !loc_table ;
|
|
||||||
String (id, v)
|
|
||||||
| Bytes (loc, v) ->
|
|
||||||
loc_table := (id, loc) :: !loc_table ;
|
|
||||||
Bytes (id, v)
|
|
||||||
| Seq (loc, seq) ->
|
|
||||||
loc_table := (id, loc) :: !loc_table ;
|
|
||||||
Seq (id, List.map strip_locations seq)
|
|
||||||
| Prim (loc, name, seq, annots) ->
|
|
||||||
loc_table := (id, loc) :: !loc_table ;
|
|
||||||
Prim (id, name, List.map strip_locations seq, annots) in
|
|
||||||
let stripped = strip_locations root in
|
|
||||||
Canonical stripped, List.rev !loc_table
|
|
||||||
|
|
||||||
let inject_locations lookup (Canonical root) =
|
|
||||||
let rec inject_locations l =
|
|
||||||
match l with
|
|
||||||
| Int (loc, v) ->
|
|
||||||
Int (lookup loc, v)
|
|
||||||
| String (loc, v) ->
|
|
||||||
String (lookup loc, v)
|
|
||||||
| Bytes (loc, v) ->
|
|
||||||
Bytes (lookup loc, v)
|
|
||||||
| Seq (loc, seq) ->
|
|
||||||
Seq (lookup loc, List.map inject_locations seq)
|
|
||||||
| Prim (loc, name, seq, annots) ->
|
|
||||||
Prim (lookup loc, name, List.map inject_locations seq, annots) in
|
|
||||||
inject_locations root
|
|
||||||
|
|
||||||
let map f (Canonical expr) =
|
|
||||||
let rec map_node f = function
|
|
||||||
| Int _ | String _ | Bytes _ as node -> node
|
|
||||||
| Seq (loc, seq) ->
|
|
||||||
Seq (loc, List.map (map_node f) seq)
|
|
||||||
| Prim (loc, name, seq, annots) ->
|
|
||||||
Prim (loc, f name, List.map (map_node f) seq, annots) in
|
|
||||||
Canonical (map_node f expr)
|
|
||||||
|
|
||||||
let rec map_node fl fp = function
|
|
||||||
| Int (loc, v) ->
|
|
||||||
Int (fl loc, v)
|
|
||||||
| String (loc, v) ->
|
|
||||||
String (fl loc, v)
|
|
||||||
| Bytes (loc, v) ->
|
|
||||||
Bytes (fl loc, v)
|
|
||||||
| Seq (loc, seq) ->
|
|
||||||
Seq (fl loc, List.map (map_node fl fp) seq)
|
|
||||||
| Prim (loc, name, seq, annots) ->
|
|
||||||
Prim (fl loc, fp name, List.map (map_node fl fp) seq, annots)
|
|
||||||
|
|
||||||
type semantics = V0 | V1
|
|
||||||
|
|
||||||
let internal_canonical_encoding ~semantics ~variant prim_encoding =
|
|
||||||
let open Data_encoding in
|
|
||||||
let int_encoding =
|
|
||||||
obj1 (req "int" z) in
|
|
||||||
let string_encoding =
|
|
||||||
obj1 (req "string" string) in
|
|
||||||
let bytes_encoding =
|
|
||||||
obj1 (req "bytes" bytes) in
|
|
||||||
let int_encoding tag =
|
|
||||||
case tag int_encoding
|
|
||||||
~title:"Int"
|
|
||||||
(function Int (_, v) -> Some v | _ -> None)
|
|
||||||
(fun v -> Int (0, v)) in
|
|
||||||
let string_encoding tag =
|
|
||||||
case tag string_encoding
|
|
||||||
~title:"String"
|
|
||||||
(function String (_, v) -> Some v | _ -> None)
|
|
||||||
(fun v -> String (0, v)) in
|
|
||||||
let bytes_encoding tag =
|
|
||||||
case tag bytes_encoding
|
|
||||||
~title:"Bytes"
|
|
||||||
(function Bytes (_, v) -> Some v | _ -> None)
|
|
||||||
(fun v -> Bytes (0, v)) in
|
|
||||||
let seq_encoding tag expr_encoding =
|
|
||||||
case tag (list expr_encoding)
|
|
||||||
~title:"Sequence"
|
|
||||||
(function Seq (_, v) -> Some v | _ -> None)
|
|
||||||
(fun args -> Seq (0, args)) in
|
|
||||||
let annots_encoding =
|
|
||||||
let split s =
|
|
||||||
if s = "" && semantics <> V0 then []
|
|
||||||
else
|
|
||||||
let annots = String.split_on_char ' ' s in
|
|
||||||
List.iter (fun a ->
|
|
||||||
if String.length a > 255 then failwith "Oversized annotation"
|
|
||||||
) annots;
|
|
||||||
if String.concat " " annots <> s then
|
|
||||||
failwith "Invalid annotation string, \
|
|
||||||
must be a sequence of valid annotations with spaces" ;
|
|
||||||
annots in
|
|
||||||
splitted
|
|
||||||
~json:(list (Bounded.string 255))
|
|
||||||
~binary:(conv (String.concat " ") split string) in
|
|
||||||
let application_encoding tag expr_encoding =
|
|
||||||
case tag
|
|
||||||
~title:"Generic prim (any number of args with or without annot)"
|
|
||||||
(obj3 (req "prim" prim_encoding)
|
|
||||||
(dft "args" (list expr_encoding) [])
|
|
||||||
(dft "annots" annots_encoding []))
|
|
||||||
(function Prim (_, prim, args, annots) -> Some (prim, args, annots)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (prim, args, annots) -> Prim (0, prim, args, annots)) in
|
|
||||||
let node_encoding = mu ("micheline." ^ variant ^ ".expression") (fun expr_encoding ->
|
|
||||||
splitted
|
|
||||||
~json:(union ~tag_size:`Uint8
|
|
||||||
[ int_encoding Json_only;
|
|
||||||
string_encoding Json_only ;
|
|
||||||
bytes_encoding Json_only ;
|
|
||||||
seq_encoding Json_only expr_encoding ;
|
|
||||||
application_encoding Json_only expr_encoding ])
|
|
||||||
~binary:(union ~tag_size:`Uint8
|
|
||||||
[ int_encoding (Tag 0) ;
|
|
||||||
string_encoding (Tag 1) ;
|
|
||||||
seq_encoding (Tag 2) expr_encoding ;
|
|
||||||
(* No args, no annot *)
|
|
||||||
case (Tag 3)
|
|
||||||
~title:"Prim (no args, annot)"
|
|
||||||
(obj1 (req "prim" prim_encoding))
|
|
||||||
(function Prim (_, v, [], []) -> Some v
|
|
||||||
| _ -> None)
|
|
||||||
(fun v -> Prim (0, v, [], [])) ;
|
|
||||||
(* No args, with annots *)
|
|
||||||
case (Tag 4)
|
|
||||||
~title:"Prim (no args + annot)"
|
|
||||||
(obj2 (req "prim" prim_encoding)
|
|
||||||
(req "annots" annots_encoding))
|
|
||||||
(function
|
|
||||||
| Prim (_, v, [], annots) -> Some (v, annots)
|
|
||||||
| _ -> None)
|
|
||||||
(function (prim, annots) -> Prim (0, prim, [], annots)) ;
|
|
||||||
(* Single arg, no annot *)
|
|
||||||
case (Tag 5)
|
|
||||||
~title:"Prim (1 arg, no annot)"
|
|
||||||
(obj2 (req "prim" prim_encoding)
|
|
||||||
(req "arg" expr_encoding))
|
|
||||||
(function
|
|
||||||
| Prim (_, v, [ arg ], []) -> Some (v, arg)
|
|
||||||
| _ -> None)
|
|
||||||
(function (prim, arg) -> Prim (0, prim, [ arg ], [])) ;
|
|
||||||
(* Single arg, with annot *)
|
|
||||||
case (Tag 6)
|
|
||||||
~title:"Prim (1 arg + annot)"
|
|
||||||
(obj3 (req "prim" prim_encoding)
|
|
||||||
(req "arg" expr_encoding)
|
|
||||||
(req "annots" annots_encoding))
|
|
||||||
(function
|
|
||||||
| Prim (_, prim, [ arg ], annots) -> Some (prim, arg, annots)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (prim, arg, annots) -> Prim (0, prim, [ arg ], annots)) ;
|
|
||||||
(* Two args, no annot *)
|
|
||||||
case (Tag 7)
|
|
||||||
~title:"Prim (2 args, no annot)"
|
|
||||||
(obj3 (req "prim" prim_encoding)
|
|
||||||
(req "arg1" expr_encoding)
|
|
||||||
(req "arg2" expr_encoding))
|
|
||||||
(function
|
|
||||||
| Prim (_, prim, [ arg1 ; arg2 ], []) -> Some (prim, arg1, arg2)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (prim, arg1, arg2) -> Prim (0, prim, [ arg1 ; arg2 ], [])) ;
|
|
||||||
(* Two args, with annots *)
|
|
||||||
case (Tag 8)
|
|
||||||
~title:"Prim (2 args + annot)"
|
|
||||||
(obj4 (req "prim" prim_encoding)
|
|
||||||
(req "arg1" expr_encoding)
|
|
||||||
(req "arg2" expr_encoding)
|
|
||||||
(req "annots" annots_encoding))
|
|
||||||
(function
|
|
||||||
| Prim (_, prim, [ arg1 ; arg2 ], annots) -> Some (prim, arg1, arg2, annots)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (prim, arg1, arg2, annots) -> Prim (0, prim, [ arg1 ; arg2 ], annots)) ;
|
|
||||||
(* General case *)
|
|
||||||
application_encoding (Tag 9) expr_encoding ;
|
|
||||||
bytes_encoding (Tag 10) ]))
|
|
||||||
in
|
|
||||||
conv
|
|
||||||
(function Canonical node -> node)
|
|
||||||
(fun node -> strip_locations node)
|
|
||||||
node_encoding
|
|
||||||
|
|
||||||
let canonical_encoding ~variant prim_encoding =
|
|
||||||
internal_canonical_encoding ~semantics:V1 ~variant prim_encoding
|
|
||||||
let canonical_encoding_v1 ~variant prim_encoding =
|
|
||||||
internal_canonical_encoding ~semantics:V1 ~variant prim_encoding
|
|
||||||
let canonical_encoding_v0 ~variant prim_encoding =
|
|
||||||
internal_canonical_encoding ~semantics:V0 ~variant prim_encoding
|
|
||||||
|
|
||||||
let table_encoding ~variant location_encoding prim_encoding =
|
|
||||||
let open Data_encoding in
|
|
||||||
conv
|
|
||||||
(fun node ->
|
|
||||||
let canon, assoc = extract_locations node in
|
|
||||||
let _, table = List.split assoc in
|
|
||||||
(canon, table))
|
|
||||||
(fun (canon, table) ->
|
|
||||||
let table = Array.of_list table in
|
|
||||||
inject_locations (fun i -> table.(i)) canon)
|
|
||||||
(obj2
|
|
||||||
(req "expression" (canonical_encoding ~variant prim_encoding))
|
|
||||||
(req "locations" (list location_encoding)))
|
|
||||||
|
|
||||||
let erased_encoding ~variant default_location prim_encoding =
|
|
||||||
let open Data_encoding in
|
|
||||||
conv
|
|
||||||
(fun node -> strip_locations node)
|
|
||||||
(fun canon -> inject_locations (fun _ -> default_location) canon)
|
|
||||||
(canonical_encoding ~variant prim_encoding)
|
|
||||||
|
@ -23,82 +23,6 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(*****************************************************************************)
|
(*****************************************************************************)
|
||||||
|
|
||||||
type annot = string list
|
include module type of Micheline_main
|
||||||
|
module Michelson_primitives = Michelson_primitives
|
||||||
|
|
||||||
(** The abstract syntax tree of Micheline expressions. The first
|
|
||||||
parameter is used to contain locations, but can also embed custom
|
|
||||||
data. The second parameter is the type of primitive names. *)
|
|
||||||
type ('l, 'p) node =
|
|
||||||
| Int of 'l * Z.t
|
|
||||||
| String of 'l * string
|
|
||||||
| Bytes of 'l * MBytes.t
|
|
||||||
| Prim of 'l * 'p * ('l, 'p) node list * annot
|
|
||||||
| Seq of 'l * ('l, 'p) node list
|
|
||||||
|
|
||||||
(** Encoding for expressions, as their {!canonical} encoding.
|
|
||||||
Locations are stored in a side table.
|
|
||||||
See {!canonical_encoding} for the [variant] parameter. *)
|
|
||||||
val table_encoding : variant:string ->
|
|
||||||
'l Data_encoding.encoding -> 'p Data_encoding.encoding ->
|
|
||||||
('l, 'p) node Data_encoding.encoding
|
|
||||||
|
|
||||||
(** Encoding for expressions, as their {!canonical} encoding.
|
|
||||||
Locations are erased when serialized, and restored to a provided
|
|
||||||
default value when deserialized.
|
|
||||||
See {!canonical_encoding} for the [variant] parameter. *)
|
|
||||||
val erased_encoding : variant:string ->
|
|
||||||
'l -> 'p Data_encoding.encoding -> ('l, 'p) node Data_encoding.encoding
|
|
||||||
|
|
||||||
(** Extract the location of the node. *)
|
|
||||||
val location : ('l, 'p) node -> 'l
|
|
||||||
|
|
||||||
(** Extract the annotations of the node. *)
|
|
||||||
val annotations : ('l, 'p) node -> string list
|
|
||||||
|
|
||||||
(** Expression form using canonical integer numbering as
|
|
||||||
locations. The root has number zero, and each node adds one in the
|
|
||||||
order of infix traversal. To be used when locations are not
|
|
||||||
important, or when one wants to attach properties to nodes in an
|
|
||||||
expression without rewriting it (using an indirection table with
|
|
||||||
canonical locations as keys). *)
|
|
||||||
type 'p canonical
|
|
||||||
|
|
||||||
(** Canonical integer locations that appear inside {!canonical} expressions. *)
|
|
||||||
type canonical_location = int
|
|
||||||
|
|
||||||
(** Encoding for canonical integer locations. *)
|
|
||||||
val canonical_location_encoding : canonical_location Data_encoding.encoding
|
|
||||||
|
|
||||||
(** Encoding for expressions in canonical form. The first parameter
|
|
||||||
is a name used to produce named definitions in the schemas. Make
|
|
||||||
sure to use different names if two expression variants with
|
|
||||||
different primitive encodings are used in the same schema. *)
|
|
||||||
val canonical_encoding : variant:string -> 'l Data_encoding.encoding -> 'l canonical Data_encoding.encoding
|
|
||||||
|
|
||||||
(** Old version of {!canonical_encoding} for retrocompatibility.
|
|
||||||
Do not use in new code. *)
|
|
||||||
val canonical_encoding_v0 : variant:string -> 'l Data_encoding.encoding -> 'l canonical Data_encoding.encoding
|
|
||||||
|
|
||||||
(** Alias for {!canonical_encoding}. *)
|
|
||||||
val canonical_encoding_v1 : variant:string -> 'l Data_encoding.encoding -> 'l canonical Data_encoding.encoding
|
|
||||||
|
|
||||||
(** Compute the canonical form of an expression.
|
|
||||||
Drops the concrete locations completely. *)
|
|
||||||
val strip_locations : (_, 'p) node -> 'p canonical
|
|
||||||
|
|
||||||
(** Give the root node of an expression in canonical form. *)
|
|
||||||
val root : 'p canonical -> (canonical_location, 'p) node
|
|
||||||
|
|
||||||
(** Compute the canonical form of an expression.
|
|
||||||
Saves the concrete locations in an association list. *)
|
|
||||||
val extract_locations : ('l, 'p) node -> 'p canonical * (canonical_location * 'l) list
|
|
||||||
|
|
||||||
(** Transforms an expression in canonical form into a polymorphic one.
|
|
||||||
Takes a mapping function to inject the concrete locations. *)
|
|
||||||
val inject_locations : (canonical_location -> 'l) -> 'p canonical -> ('l, 'p) node
|
|
||||||
|
|
||||||
(** Copies the tree, updating its primitives. *)
|
|
||||||
val map : ('a -> 'b) -> 'a canonical -> 'b canonical
|
|
||||||
|
|
||||||
(** Copies the tree, updating its primitives and locations. *)
|
|
||||||
val map_node : ('la -> 'lb) -> ('pa -> 'pb) -> ('la, 'pa) node -> ('lb, 'pb) node
|
|
||||||
|
301
src/lib_micheline/micheline_main.ml
Normal file
301
src/lib_micheline/micheline_main.ml
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
(*****************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Open Source License *)
|
||||||
|
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
||||||
|
(* *)
|
||||||
|
(*****************************************************************************)
|
||||||
|
|
||||||
|
type annot = string list
|
||||||
|
|
||||||
|
type ('l, 'p) node =
|
||||||
|
| Int of 'l * Z.t
|
||||||
|
| String of 'l * string
|
||||||
|
| Bytes of 'l * MBytes.t
|
||||||
|
| Prim of 'l * 'p * ('l, 'p) node list * annot
|
||||||
|
| Seq of 'l * ('l, 'p) node list
|
||||||
|
|
||||||
|
type canonical_location = int
|
||||||
|
|
||||||
|
type 'p canonical = Canonical of (canonical_location, 'p) node
|
||||||
|
|
||||||
|
let canonical_location_encoding =
|
||||||
|
let open Data_encoding in
|
||||||
|
def
|
||||||
|
"micheline.location"
|
||||||
|
~title:
|
||||||
|
"Canonical location in a Micheline expression"
|
||||||
|
~description:
|
||||||
|
"The location of a node in a Micheline expression tree \
|
||||||
|
in prefix order, with zero being the root and adding one \
|
||||||
|
for every basic node, sequence and primitive application." @@
|
||||||
|
int31
|
||||||
|
|
||||||
|
let location = function
|
||||||
|
| Int (loc, _) -> loc
|
||||||
|
| String (loc, _) -> loc
|
||||||
|
| Bytes (loc, _) -> loc
|
||||||
|
| Seq (loc, _) -> loc
|
||||||
|
| Prim (loc, _, _, _) -> loc
|
||||||
|
|
||||||
|
let annotations = function
|
||||||
|
| Int (_, _) -> []
|
||||||
|
| String (_, _) -> []
|
||||||
|
| Bytes (_, _) -> []
|
||||||
|
| Seq (_, _) -> []
|
||||||
|
| Prim (_, _, _, annots) -> annots
|
||||||
|
|
||||||
|
let root (Canonical expr) = expr
|
||||||
|
|
||||||
|
let strip_locations root =
|
||||||
|
let id = let id = ref (-1) in fun () -> incr id ; !id in
|
||||||
|
let rec strip_locations l =
|
||||||
|
let id = id () in
|
||||||
|
match l with
|
||||||
|
| Int (_, v) ->
|
||||||
|
Int (id, v)
|
||||||
|
| String (_, v) ->
|
||||||
|
String (id, v)
|
||||||
|
| Bytes (_, v) ->
|
||||||
|
Bytes (id, v)
|
||||||
|
| Seq (_, seq) ->
|
||||||
|
Seq (id, List.map strip_locations seq)
|
||||||
|
| Prim (_, name, seq, annots) ->
|
||||||
|
Prim (id, name, List.map strip_locations seq, annots) in
|
||||||
|
Canonical (strip_locations root)
|
||||||
|
|
||||||
|
let extract_locations root =
|
||||||
|
let id = let id = ref (-1) in fun () -> incr id ; !id in
|
||||||
|
let loc_table = ref [] in
|
||||||
|
let rec strip_locations l =
|
||||||
|
let id = id () in
|
||||||
|
match l with
|
||||||
|
| Int (loc, v) ->
|
||||||
|
loc_table := (id, loc) :: !loc_table ;
|
||||||
|
Int (id, v)
|
||||||
|
| String (loc, v) ->
|
||||||
|
loc_table := (id, loc) :: !loc_table ;
|
||||||
|
String (id, v)
|
||||||
|
| Bytes (loc, v) ->
|
||||||
|
loc_table := (id, loc) :: !loc_table ;
|
||||||
|
Bytes (id, v)
|
||||||
|
| Seq (loc, seq) ->
|
||||||
|
loc_table := (id, loc) :: !loc_table ;
|
||||||
|
Seq (id, List.map strip_locations seq)
|
||||||
|
| Prim (loc, name, seq, annots) ->
|
||||||
|
loc_table := (id, loc) :: !loc_table ;
|
||||||
|
Prim (id, name, List.map strip_locations seq, annots) in
|
||||||
|
let stripped = strip_locations root in
|
||||||
|
Canonical stripped, List.rev !loc_table
|
||||||
|
|
||||||
|
let inject_locations lookup (Canonical root) =
|
||||||
|
let rec inject_locations l =
|
||||||
|
match l with
|
||||||
|
| Int (loc, v) ->
|
||||||
|
Int (lookup loc, v)
|
||||||
|
| String (loc, v) ->
|
||||||
|
String (lookup loc, v)
|
||||||
|
| Bytes (loc, v) ->
|
||||||
|
Bytes (lookup loc, v)
|
||||||
|
| Seq (loc, seq) ->
|
||||||
|
Seq (lookup loc, List.map inject_locations seq)
|
||||||
|
| Prim (loc, name, seq, annots) ->
|
||||||
|
Prim (lookup loc, name, List.map inject_locations seq, annots) in
|
||||||
|
inject_locations root
|
||||||
|
|
||||||
|
let map f (Canonical expr) =
|
||||||
|
let rec map_node f = function
|
||||||
|
| Int _ | String _ | Bytes _ as node -> node
|
||||||
|
| Seq (loc, seq) ->
|
||||||
|
Seq (loc, List.map (map_node f) seq)
|
||||||
|
| Prim (loc, name, seq, annots) ->
|
||||||
|
Prim (loc, f name, List.map (map_node f) seq, annots) in
|
||||||
|
Canonical (map_node f expr)
|
||||||
|
|
||||||
|
let rec map_node fl fp = function
|
||||||
|
| Int (loc, v) ->
|
||||||
|
Int (fl loc, v)
|
||||||
|
| String (loc, v) ->
|
||||||
|
String (fl loc, v)
|
||||||
|
| Bytes (loc, v) ->
|
||||||
|
Bytes (fl loc, v)
|
||||||
|
| Seq (loc, seq) ->
|
||||||
|
Seq (fl loc, List.map (map_node fl fp) seq)
|
||||||
|
| Prim (loc, name, seq, annots) ->
|
||||||
|
Prim (fl loc, fp name, List.map (map_node fl fp) seq, annots)
|
||||||
|
|
||||||
|
type semantics = V0 | V1
|
||||||
|
|
||||||
|
let internal_canonical_encoding ~semantics ~variant prim_encoding =
|
||||||
|
let open Data_encoding in
|
||||||
|
let int_encoding =
|
||||||
|
obj1 (req "int" z) in
|
||||||
|
let string_encoding =
|
||||||
|
obj1 (req "string" string) in
|
||||||
|
let bytes_encoding =
|
||||||
|
obj1 (req "bytes" bytes) in
|
||||||
|
let int_encoding tag =
|
||||||
|
case tag int_encoding
|
||||||
|
~title:"Int"
|
||||||
|
(function Int (_, v) -> Some v | _ -> None)
|
||||||
|
(fun v -> Int (0, v)) in
|
||||||
|
let string_encoding tag =
|
||||||
|
case tag string_encoding
|
||||||
|
~title:"String"
|
||||||
|
(function String (_, v) -> Some v | _ -> None)
|
||||||
|
(fun v -> String (0, v)) in
|
||||||
|
let bytes_encoding tag =
|
||||||
|
case tag bytes_encoding
|
||||||
|
~title:"Bytes"
|
||||||
|
(function Bytes (_, v) -> Some v | _ -> None)
|
||||||
|
(fun v -> Bytes (0, v)) in
|
||||||
|
let seq_encoding tag expr_encoding =
|
||||||
|
case tag (list expr_encoding)
|
||||||
|
~title:"Sequence"
|
||||||
|
(function Seq (_, v) -> Some v | _ -> None)
|
||||||
|
(fun args -> Seq (0, args)) in
|
||||||
|
let annots_encoding =
|
||||||
|
let split s =
|
||||||
|
if s = "" && semantics <> V0 then []
|
||||||
|
else
|
||||||
|
let annots = String.split_on_char ' ' s in
|
||||||
|
List.iter (fun a ->
|
||||||
|
if String.length a > 255 then failwith "Oversized annotation"
|
||||||
|
) annots;
|
||||||
|
if String.concat " " annots <> s then
|
||||||
|
failwith "Invalid annotation string, \
|
||||||
|
must be a sequence of valid annotations with spaces" ;
|
||||||
|
annots in
|
||||||
|
splitted
|
||||||
|
~json:(list (Bounded.string 255))
|
||||||
|
~binary:(conv (String.concat " ") split string) in
|
||||||
|
let application_encoding tag expr_encoding =
|
||||||
|
case tag
|
||||||
|
~title:"Generic prim (any number of args with or without annot)"
|
||||||
|
(obj3 (req "prim" prim_encoding)
|
||||||
|
(dft "args" (list expr_encoding) [])
|
||||||
|
(dft "annots" annots_encoding []))
|
||||||
|
(function Prim (_, prim, args, annots) -> Some (prim, args, annots)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (prim, args, annots) -> Prim (0, prim, args, annots)) in
|
||||||
|
let node_encoding = mu ("micheline." ^ variant ^ ".expression") (fun expr_encoding ->
|
||||||
|
splitted
|
||||||
|
~json:(union ~tag_size:`Uint8
|
||||||
|
[ int_encoding Json_only;
|
||||||
|
string_encoding Json_only ;
|
||||||
|
bytes_encoding Json_only ;
|
||||||
|
seq_encoding Json_only expr_encoding ;
|
||||||
|
application_encoding Json_only expr_encoding ])
|
||||||
|
~binary:(union ~tag_size:`Uint8
|
||||||
|
[ int_encoding (Tag 0) ;
|
||||||
|
string_encoding (Tag 1) ;
|
||||||
|
seq_encoding (Tag 2) expr_encoding ;
|
||||||
|
(* No args, no annot *)
|
||||||
|
case (Tag 3)
|
||||||
|
~title:"Prim (no args, annot)"
|
||||||
|
(obj1 (req "prim" prim_encoding))
|
||||||
|
(function Prim (_, v, [], []) -> Some v
|
||||||
|
| _ -> None)
|
||||||
|
(fun v -> Prim (0, v, [], [])) ;
|
||||||
|
(* No args, with annots *)
|
||||||
|
case (Tag 4)
|
||||||
|
~title:"Prim (no args + annot)"
|
||||||
|
(obj2 (req "prim" prim_encoding)
|
||||||
|
(req "annots" annots_encoding))
|
||||||
|
(function
|
||||||
|
| Prim (_, v, [], annots) -> Some (v, annots)
|
||||||
|
| _ -> None)
|
||||||
|
(function (prim, annots) -> Prim (0, prim, [], annots)) ;
|
||||||
|
(* Single arg, no annot *)
|
||||||
|
case (Tag 5)
|
||||||
|
~title:"Prim (1 arg, no annot)"
|
||||||
|
(obj2 (req "prim" prim_encoding)
|
||||||
|
(req "arg" expr_encoding))
|
||||||
|
(function
|
||||||
|
| Prim (_, v, [ arg ], []) -> Some (v, arg)
|
||||||
|
| _ -> None)
|
||||||
|
(function (prim, arg) -> Prim (0, prim, [ arg ], [])) ;
|
||||||
|
(* Single arg, with annot *)
|
||||||
|
case (Tag 6)
|
||||||
|
~title:"Prim (1 arg + annot)"
|
||||||
|
(obj3 (req "prim" prim_encoding)
|
||||||
|
(req "arg" expr_encoding)
|
||||||
|
(req "annots" annots_encoding))
|
||||||
|
(function
|
||||||
|
| Prim (_, prim, [ arg ], annots) -> Some (prim, arg, annots)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (prim, arg, annots) -> Prim (0, prim, [ arg ], annots)) ;
|
||||||
|
(* Two args, no annot *)
|
||||||
|
case (Tag 7)
|
||||||
|
~title:"Prim (2 args, no annot)"
|
||||||
|
(obj3 (req "prim" prim_encoding)
|
||||||
|
(req "arg1" expr_encoding)
|
||||||
|
(req "arg2" expr_encoding))
|
||||||
|
(function
|
||||||
|
| Prim (_, prim, [ arg1 ; arg2 ], []) -> Some (prim, arg1, arg2)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (prim, arg1, arg2) -> Prim (0, prim, [ arg1 ; arg2 ], [])) ;
|
||||||
|
(* Two args, with annots *)
|
||||||
|
case (Tag 8)
|
||||||
|
~title:"Prim (2 args + annot)"
|
||||||
|
(obj4 (req "prim" prim_encoding)
|
||||||
|
(req "arg1" expr_encoding)
|
||||||
|
(req "arg2" expr_encoding)
|
||||||
|
(req "annots" annots_encoding))
|
||||||
|
(function
|
||||||
|
| Prim (_, prim, [ arg1 ; arg2 ], annots) -> Some (prim, arg1, arg2, annots)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (prim, arg1, arg2, annots) -> Prim (0, prim, [ arg1 ; arg2 ], annots)) ;
|
||||||
|
(* General case *)
|
||||||
|
application_encoding (Tag 9) expr_encoding ;
|
||||||
|
bytes_encoding (Tag 10) ]))
|
||||||
|
in
|
||||||
|
conv
|
||||||
|
(function Canonical node -> node)
|
||||||
|
(fun node -> strip_locations node)
|
||||||
|
node_encoding
|
||||||
|
|
||||||
|
let canonical_encoding ~variant prim_encoding =
|
||||||
|
internal_canonical_encoding ~semantics:V1 ~variant prim_encoding
|
||||||
|
let canonical_encoding_v1 ~variant prim_encoding =
|
||||||
|
internal_canonical_encoding ~semantics:V1 ~variant prim_encoding
|
||||||
|
let canonical_encoding_v0 ~variant prim_encoding =
|
||||||
|
internal_canonical_encoding ~semantics:V0 ~variant prim_encoding
|
||||||
|
|
||||||
|
let table_encoding ~variant location_encoding prim_encoding =
|
||||||
|
let open Data_encoding in
|
||||||
|
conv
|
||||||
|
(fun node ->
|
||||||
|
let canon, assoc = extract_locations node in
|
||||||
|
let _, table = List.split assoc in
|
||||||
|
(canon, table))
|
||||||
|
(fun (canon, table) ->
|
||||||
|
let table = Array.of_list table in
|
||||||
|
inject_locations (fun i -> table.(i)) canon)
|
||||||
|
(obj2
|
||||||
|
(req "expression" (canonical_encoding ~variant prim_encoding))
|
||||||
|
(req "locations" (list location_encoding)))
|
||||||
|
|
||||||
|
let erased_encoding ~variant default_location prim_encoding =
|
||||||
|
let open Data_encoding in
|
||||||
|
conv
|
||||||
|
(fun node -> strip_locations node)
|
||||||
|
(fun canon -> inject_locations (fun _ -> default_location) canon)
|
||||||
|
(canonical_encoding ~variant prim_encoding)
|
104
src/lib_micheline/micheline_main.mli
Normal file
104
src/lib_micheline/micheline_main.mli
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
(*****************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Open Source License *)
|
||||||
|
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
||||||
|
(* *)
|
||||||
|
(*****************************************************************************)
|
||||||
|
|
||||||
|
type annot = string list
|
||||||
|
|
||||||
|
(** The abstract syntax tree of Micheline expressions. The first
|
||||||
|
parameter is used to contain locations, but can also embed custom
|
||||||
|
data. The second parameter is the type of primitive names. *)
|
||||||
|
type ('l, 'p) node =
|
||||||
|
| Int of 'l * Z.t
|
||||||
|
| String of 'l * string
|
||||||
|
| Bytes of 'l * MBytes.t
|
||||||
|
| Prim of 'l * 'p * ('l, 'p) node list * annot
|
||||||
|
| Seq of 'l * ('l, 'p) node list
|
||||||
|
|
||||||
|
(** Encoding for expressions, as their {!canonical} encoding.
|
||||||
|
Locations are stored in a side table.
|
||||||
|
See {!canonical_encoding} for the [variant] parameter. *)
|
||||||
|
val table_encoding : variant:string ->
|
||||||
|
'l Data_encoding.encoding -> 'p Data_encoding.encoding ->
|
||||||
|
('l, 'p) node Data_encoding.encoding
|
||||||
|
|
||||||
|
(** Encoding for expressions, as their {!canonical} encoding.
|
||||||
|
Locations are erased when serialized, and restored to a provided
|
||||||
|
default value when deserialized.
|
||||||
|
See {!canonical_encoding} for the [variant] parameter. *)
|
||||||
|
val erased_encoding : variant:string ->
|
||||||
|
'l -> 'p Data_encoding.encoding -> ('l, 'p) node Data_encoding.encoding
|
||||||
|
|
||||||
|
(** Extract the location of the node. *)
|
||||||
|
val location : ('l, 'p) node -> 'l
|
||||||
|
|
||||||
|
(** Extract the annotations of the node. *)
|
||||||
|
val annotations : ('l, 'p) node -> string list
|
||||||
|
|
||||||
|
(** Expression form using canonical integer numbering as
|
||||||
|
locations. The root has number zero, and each node adds one in the
|
||||||
|
order of infix traversal. To be used when locations are not
|
||||||
|
important, or when one wants to attach properties to nodes in an
|
||||||
|
expression without rewriting it (using an indirection table with
|
||||||
|
canonical locations as keys). *)
|
||||||
|
type 'p canonical
|
||||||
|
|
||||||
|
(** Canonical integer locations that appear inside {!canonical} expressions. *)
|
||||||
|
type canonical_location = int
|
||||||
|
|
||||||
|
(** Encoding for canonical integer locations. *)
|
||||||
|
val canonical_location_encoding : canonical_location Data_encoding.encoding
|
||||||
|
|
||||||
|
(** Encoding for expressions in canonical form. The first parameter
|
||||||
|
is a name used to produce named definitions in the schemas. Make
|
||||||
|
sure to use different names if two expression variants with
|
||||||
|
different primitive encodings are used in the same schema. *)
|
||||||
|
val canonical_encoding : variant:string -> 'l Data_encoding.encoding -> 'l canonical Data_encoding.encoding
|
||||||
|
|
||||||
|
(** Old version of {!canonical_encoding} for retrocompatibility.
|
||||||
|
Do not use in new code. *)
|
||||||
|
val canonical_encoding_v0 : variant:string -> 'l Data_encoding.encoding -> 'l canonical Data_encoding.encoding
|
||||||
|
|
||||||
|
(** Alias for {!canonical_encoding}. *)
|
||||||
|
val canonical_encoding_v1 : variant:string -> 'l Data_encoding.encoding -> 'l canonical Data_encoding.encoding
|
||||||
|
|
||||||
|
(** Compute the canonical form of an expression.
|
||||||
|
Drops the concrete locations completely. *)
|
||||||
|
val strip_locations : (_, 'p) node -> 'p canonical
|
||||||
|
|
||||||
|
(** Give the root node of an expression in canonical form. *)
|
||||||
|
val root : 'p canonical -> (canonical_location, 'p) node
|
||||||
|
|
||||||
|
(** Compute the canonical form of an expression.
|
||||||
|
Saves the concrete locations in an association list. *)
|
||||||
|
val extract_locations : ('l, 'p) node -> 'p canonical * (canonical_location * 'l) list
|
||||||
|
|
||||||
|
(** Transforms an expression in canonical form into a polymorphic one.
|
||||||
|
Takes a mapping function to inject the concrete locations. *)
|
||||||
|
val inject_locations : (canonical_location -> 'l) -> 'p canonical -> ('l, 'p) node
|
||||||
|
|
||||||
|
(** Copies the tree, updating its primitives. *)
|
||||||
|
val map : ('a -> 'b) -> 'a canonical -> 'b canonical
|
||||||
|
|
||||||
|
(** Copies the tree, updating its primitives and locations. *)
|
||||||
|
val map_node : ('la -> 'lb) -> ('pa -> 'pb) -> ('la, 'pa) node -> ('lb, 'pb) node
|
563
src/lib_micheline/michelson_primitives.ml
Normal file
563
src/lib_micheline/michelson_primitives.ml
Normal file
@ -0,0 +1,563 @@
|
|||||||
|
(*****************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Open Source License *)
|
||||||
|
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
||||||
|
(* *)
|
||||||
|
(*****************************************************************************)
|
||||||
|
|
||||||
|
open Micheline_main
|
||||||
|
|
||||||
|
type prim =
|
||||||
|
| K_parameter
|
||||||
|
| K_storage
|
||||||
|
| K_code
|
||||||
|
| D_False
|
||||||
|
| D_Elt
|
||||||
|
| D_Left
|
||||||
|
| D_None
|
||||||
|
| D_Pair
|
||||||
|
| D_Right
|
||||||
|
| D_Some
|
||||||
|
| D_True
|
||||||
|
| D_Unit
|
||||||
|
| I_PACK
|
||||||
|
| I_UNPACK
|
||||||
|
| I_BLAKE2B
|
||||||
|
| I_SHA256
|
||||||
|
| I_SHA512
|
||||||
|
| I_ABS
|
||||||
|
| I_ADD
|
||||||
|
| I_AMOUNT
|
||||||
|
| I_AND
|
||||||
|
| I_BALANCE
|
||||||
|
| I_CAR
|
||||||
|
| I_CDR
|
||||||
|
| I_CHECK_SIGNATURE
|
||||||
|
| I_COMPARE
|
||||||
|
| I_CONCAT
|
||||||
|
| I_CONS
|
||||||
|
| I_CREATE_ACCOUNT
|
||||||
|
| I_CREATE_CONTRACT
|
||||||
|
| I_IMPLICIT_ACCOUNT
|
||||||
|
| I_DIP
|
||||||
|
| I_DROP
|
||||||
|
| I_DUP
|
||||||
|
| I_EDIV
|
||||||
|
| I_EMPTY_MAP
|
||||||
|
| I_EMPTY_SET
|
||||||
|
| I_EQ
|
||||||
|
| I_EXEC
|
||||||
|
| I_FAILWITH
|
||||||
|
| I_GE
|
||||||
|
| I_GET
|
||||||
|
| I_GT
|
||||||
|
| I_HASH_KEY
|
||||||
|
| I_IF
|
||||||
|
| I_IF_CONS
|
||||||
|
| I_IF_LEFT
|
||||||
|
| I_IF_NONE
|
||||||
|
| I_INT
|
||||||
|
| I_LAMBDA
|
||||||
|
| I_LE
|
||||||
|
| I_LEFT
|
||||||
|
| I_LOOP
|
||||||
|
| I_LSL
|
||||||
|
| I_LSR
|
||||||
|
| I_LT
|
||||||
|
| I_MAP
|
||||||
|
| I_MEM
|
||||||
|
| I_MUL
|
||||||
|
| I_NEG
|
||||||
|
| I_NEQ
|
||||||
|
| I_NIL
|
||||||
|
| I_NONE
|
||||||
|
| I_NOP
|
||||||
|
| I_NOT
|
||||||
|
| I_NOW
|
||||||
|
| I_OR
|
||||||
|
| I_PAIR
|
||||||
|
| I_PUSH
|
||||||
|
| I_RIGHT
|
||||||
|
| I_SIZE
|
||||||
|
| I_SOME
|
||||||
|
| I_SOURCE
|
||||||
|
| I_SENDER
|
||||||
|
| I_SELF
|
||||||
|
| I_SLICE
|
||||||
|
| I_STEPS_TO_QUOTA
|
||||||
|
| I_SUB
|
||||||
|
| I_SWAP
|
||||||
|
| I_TRANSFER_TOKENS
|
||||||
|
| I_SET_DELEGATE
|
||||||
|
| I_UNIT
|
||||||
|
| I_UPDATE
|
||||||
|
| I_XOR
|
||||||
|
| I_ITER
|
||||||
|
| I_LOOP_LEFT
|
||||||
|
| I_ADDRESS
|
||||||
|
| I_CONTRACT
|
||||||
|
| I_ISNAT
|
||||||
|
| I_CAST
|
||||||
|
| I_RENAME
|
||||||
|
| T_bool
|
||||||
|
| T_contract
|
||||||
|
| T_int
|
||||||
|
| T_key
|
||||||
|
| T_key_hash
|
||||||
|
| T_lambda
|
||||||
|
| T_list
|
||||||
|
| T_map
|
||||||
|
| T_big_map
|
||||||
|
| T_nat
|
||||||
|
| T_option
|
||||||
|
| T_or
|
||||||
|
| T_pair
|
||||||
|
| T_set
|
||||||
|
| T_signature
|
||||||
|
| T_string
|
||||||
|
| T_bytes
|
||||||
|
| T_mutez
|
||||||
|
| T_timestamp
|
||||||
|
| T_unit
|
||||||
|
| T_operation
|
||||||
|
| T_address
|
||||||
|
|
||||||
|
let valid_case name =
|
||||||
|
let is_lower = function '_' | 'a'..'z' -> true | _ -> false in
|
||||||
|
let is_upper = function '_' | 'A'..'Z' -> true | _ -> false in
|
||||||
|
let rec for_all a b f =
|
||||||
|
Compare.Int.(a > b) || f a && for_all (a + 1) b f in
|
||||||
|
let len = String.length name in
|
||||||
|
Compare.Int.(len <> 0)
|
||||||
|
&&
|
||||||
|
Compare.Char.(String.get name 0 <> '_')
|
||||||
|
&&
|
||||||
|
((is_upper (String.get name 0)
|
||||||
|
&& for_all 1 (len - 1) (fun i -> is_upper (String.get name i)))
|
||||||
|
||
|
||||||
|
(is_upper (String.get name 0)
|
||||||
|
&& for_all 1 (len - 1) (fun i -> is_lower (String.get name i)))
|
||||||
|
||
|
||||||
|
(is_lower (String.get name 0)
|
||||||
|
&& for_all 1 (len - 1) (fun i -> is_lower (String.get name i))))
|
||||||
|
|
||||||
|
let string_of_prim = function
|
||||||
|
| K_parameter -> "parameter"
|
||||||
|
| K_storage -> "storage"
|
||||||
|
| K_code -> "code"
|
||||||
|
| D_False -> "False"
|
||||||
|
| D_Elt -> "Elt"
|
||||||
|
| D_Left -> "Left"
|
||||||
|
| D_None -> "None"
|
||||||
|
| D_Pair -> "Pair"
|
||||||
|
| D_Right -> "Right"
|
||||||
|
| D_Some -> "Some"
|
||||||
|
| D_True -> "True"
|
||||||
|
| D_Unit -> "Unit"
|
||||||
|
| I_PACK -> "PACK"
|
||||||
|
| I_UNPACK -> "UNPACK"
|
||||||
|
| I_BLAKE2B -> "BLAKE2B"
|
||||||
|
| I_SHA256 -> "SHA256"
|
||||||
|
| I_SHA512 -> "SHA512"
|
||||||
|
| I_ABS -> "ABS"
|
||||||
|
| I_ADD -> "ADD"
|
||||||
|
| I_AMOUNT -> "AMOUNT"
|
||||||
|
| I_AND -> "AND"
|
||||||
|
| I_BALANCE -> "BALANCE"
|
||||||
|
| I_CAR -> "CAR"
|
||||||
|
| I_CDR -> "CDR"
|
||||||
|
| I_CHECK_SIGNATURE -> "CHECK_SIGNATURE"
|
||||||
|
| I_COMPARE -> "COMPARE"
|
||||||
|
| I_CONCAT -> "CONCAT"
|
||||||
|
| I_CONS -> "CONS"
|
||||||
|
| I_CREATE_ACCOUNT -> "CREATE_ACCOUNT"
|
||||||
|
| I_CREATE_CONTRACT -> "CREATE_CONTRACT"
|
||||||
|
| I_IMPLICIT_ACCOUNT -> "IMPLICIT_ACCOUNT"
|
||||||
|
| I_DIP -> "DIP"
|
||||||
|
| I_DROP -> "DROP"
|
||||||
|
| I_DUP -> "DUP"
|
||||||
|
| I_EDIV -> "EDIV"
|
||||||
|
| I_EMPTY_MAP -> "EMPTY_MAP"
|
||||||
|
| I_EMPTY_SET -> "EMPTY_SET"
|
||||||
|
| I_EQ -> "EQ"
|
||||||
|
| I_EXEC -> "EXEC"
|
||||||
|
| I_FAILWITH -> "FAILWITH"
|
||||||
|
| I_GE -> "GE"
|
||||||
|
| I_GET -> "GET"
|
||||||
|
| I_GT -> "GT"
|
||||||
|
| I_HASH_KEY -> "HASH_KEY"
|
||||||
|
| I_IF -> "IF"
|
||||||
|
| I_IF_CONS -> "IF_CONS"
|
||||||
|
| I_IF_LEFT -> "IF_LEFT"
|
||||||
|
| I_IF_NONE -> "IF_NONE"
|
||||||
|
| I_INT -> "INT"
|
||||||
|
| I_LAMBDA -> "LAMBDA"
|
||||||
|
| I_LE -> "LE"
|
||||||
|
| I_LEFT -> "LEFT"
|
||||||
|
| I_LOOP -> "LOOP"
|
||||||
|
| I_LSL -> "LSL"
|
||||||
|
| I_LSR -> "LSR"
|
||||||
|
| I_LT -> "LT"
|
||||||
|
| I_MAP -> "MAP"
|
||||||
|
| I_MEM -> "MEM"
|
||||||
|
| I_MUL -> "MUL"
|
||||||
|
| I_NEG -> "NEG"
|
||||||
|
| I_NEQ -> "NEQ"
|
||||||
|
| I_NIL -> "NIL"
|
||||||
|
| I_NONE -> "NONE"
|
||||||
|
| I_NOP -> "NOP"
|
||||||
|
| I_NOT -> "NOT"
|
||||||
|
| I_NOW -> "NOW"
|
||||||
|
| I_OR -> "OR"
|
||||||
|
| I_PAIR -> "PAIR"
|
||||||
|
| I_PUSH -> "PUSH"
|
||||||
|
| I_RIGHT -> "RIGHT"
|
||||||
|
| I_SIZE -> "SIZE"
|
||||||
|
| I_SOME -> "SOME"
|
||||||
|
| I_SOURCE -> "SOURCE"
|
||||||
|
| I_SENDER -> "SENDER"
|
||||||
|
| I_SELF -> "SELF"
|
||||||
|
| I_SLICE -> "SLICE"
|
||||||
|
| I_STEPS_TO_QUOTA -> "STEPS_TO_QUOTA"
|
||||||
|
| I_SUB -> "SUB"
|
||||||
|
| I_SWAP -> "SWAP"
|
||||||
|
| I_TRANSFER_TOKENS -> "TRANSFER_TOKENS"
|
||||||
|
| I_SET_DELEGATE -> "SET_DELEGATE"
|
||||||
|
| I_UNIT -> "UNIT"
|
||||||
|
| I_UPDATE -> "UPDATE"
|
||||||
|
| I_XOR -> "XOR"
|
||||||
|
| I_ITER -> "ITER"
|
||||||
|
| I_LOOP_LEFT -> "LOOP_LEFT"
|
||||||
|
| I_ADDRESS -> "ADDRESS"
|
||||||
|
| I_CONTRACT -> "CONTRACT"
|
||||||
|
| I_ISNAT -> "ISNAT"
|
||||||
|
| I_CAST -> "CAST"
|
||||||
|
| I_RENAME -> "RENAME"
|
||||||
|
| T_bool -> "bool"
|
||||||
|
| T_contract -> "contract"
|
||||||
|
| T_int -> "int"
|
||||||
|
| T_key -> "key"
|
||||||
|
| T_key_hash -> "key_hash"
|
||||||
|
| T_lambda -> "lambda"
|
||||||
|
| T_list -> "list"
|
||||||
|
| T_map -> "map"
|
||||||
|
| T_big_map -> "big_map"
|
||||||
|
| T_nat -> "nat"
|
||||||
|
| T_option -> "option"
|
||||||
|
| T_or -> "or"
|
||||||
|
| T_pair -> "pair"
|
||||||
|
| T_set -> "set"
|
||||||
|
| T_signature -> "signature"
|
||||||
|
| T_string -> "string"
|
||||||
|
| T_bytes -> "bytes"
|
||||||
|
| T_mutez -> "mutez"
|
||||||
|
| T_timestamp -> "timestamp"
|
||||||
|
| T_unit -> "unit"
|
||||||
|
| T_operation -> "operation"
|
||||||
|
| T_address -> "address"
|
||||||
|
|
||||||
|
type failure =
|
||||||
|
Unknown_primitive_name of string
|
||||||
|
| Invalid_case of string
|
||||||
|
| Invalid_primitive_name of string Micheline_main.canonical * Micheline_main.canonical_location
|
||||||
|
|
||||||
|
let prim_of_string : string -> (prim , failure) result = function
|
||||||
|
| "parameter" -> Ok K_parameter
|
||||||
|
| "storage" -> Ok K_storage
|
||||||
|
| "code" -> Ok K_code
|
||||||
|
| "False" -> Ok D_False
|
||||||
|
| "Elt" -> Ok D_Elt
|
||||||
|
| "Left" -> Ok D_Left
|
||||||
|
| "None" -> Ok D_None
|
||||||
|
| "Pair" -> Ok D_Pair
|
||||||
|
| "Right" -> Ok D_Right
|
||||||
|
| "Some" -> Ok D_Some
|
||||||
|
| "True" -> Ok D_True
|
||||||
|
| "Unit" -> Ok D_Unit
|
||||||
|
| "PACK" -> Ok I_PACK
|
||||||
|
| "UNPACK" -> Ok I_UNPACK
|
||||||
|
| "BLAKE2B" -> Ok I_BLAKE2B
|
||||||
|
| "SHA256" -> Ok I_SHA256
|
||||||
|
| "SHA512" -> Ok I_SHA512
|
||||||
|
| "ABS" -> Ok I_ABS
|
||||||
|
| "ADD" -> Ok I_ADD
|
||||||
|
| "AMOUNT" -> Ok I_AMOUNT
|
||||||
|
| "AND" -> Ok I_AND
|
||||||
|
| "BALANCE" -> Ok I_BALANCE
|
||||||
|
| "CAR" -> Ok I_CAR
|
||||||
|
| "CDR" -> Ok I_CDR
|
||||||
|
| "CHECK_SIGNATURE" -> Ok I_CHECK_SIGNATURE
|
||||||
|
| "COMPARE" -> Ok I_COMPARE
|
||||||
|
| "CONCAT" -> Ok I_CONCAT
|
||||||
|
| "CONS" -> Ok I_CONS
|
||||||
|
| "CREATE_ACCOUNT" -> Ok I_CREATE_ACCOUNT
|
||||||
|
| "CREATE_CONTRACT" -> Ok I_CREATE_CONTRACT
|
||||||
|
| "IMPLICIT_ACCOUNT" -> Ok I_IMPLICIT_ACCOUNT
|
||||||
|
| "DIP" -> Ok I_DIP
|
||||||
|
| "DROP" -> Ok I_DROP
|
||||||
|
| "DUP" -> Ok I_DUP
|
||||||
|
| "EDIV" -> Ok I_EDIV
|
||||||
|
| "EMPTY_MAP" -> Ok I_EMPTY_MAP
|
||||||
|
| "EMPTY_SET" -> Ok I_EMPTY_SET
|
||||||
|
| "EQ" -> Ok I_EQ
|
||||||
|
| "EXEC" -> Ok I_EXEC
|
||||||
|
| "FAILWITH" -> Ok I_FAILWITH
|
||||||
|
| "GE" -> Ok I_GE
|
||||||
|
| "GET" -> Ok I_GET
|
||||||
|
| "GT" -> Ok I_GT
|
||||||
|
| "HASH_KEY" -> Ok I_HASH_KEY
|
||||||
|
| "IF" -> Ok I_IF
|
||||||
|
| "IF_CONS" -> Ok I_IF_CONS
|
||||||
|
| "IF_LEFT" -> Ok I_IF_LEFT
|
||||||
|
| "IF_NONE" -> Ok I_IF_NONE
|
||||||
|
| "INT" -> Ok I_INT
|
||||||
|
| "LAMBDA" -> Ok I_LAMBDA
|
||||||
|
| "LE" -> Ok I_LE
|
||||||
|
| "LEFT" -> Ok I_LEFT
|
||||||
|
| "LOOP" -> Ok I_LOOP
|
||||||
|
| "LSL" -> Ok I_LSL
|
||||||
|
| "LSR" -> Ok I_LSR
|
||||||
|
| "LT" -> Ok I_LT
|
||||||
|
| "MAP" -> Ok I_MAP
|
||||||
|
| "MEM" -> Ok I_MEM
|
||||||
|
| "MUL" -> Ok I_MUL
|
||||||
|
| "NEG" -> Ok I_NEG
|
||||||
|
| "NEQ" -> Ok I_NEQ
|
||||||
|
| "NIL" -> Ok I_NIL
|
||||||
|
| "NONE" -> Ok I_NONE
|
||||||
|
| "NOP" -> Ok I_NOP
|
||||||
|
| "NOT" -> Ok I_NOT
|
||||||
|
| "NOW" -> Ok I_NOW
|
||||||
|
| "OR" -> Ok I_OR
|
||||||
|
| "PAIR" -> Ok I_PAIR
|
||||||
|
| "PUSH" -> Ok I_PUSH
|
||||||
|
| "RIGHT" -> Ok I_RIGHT
|
||||||
|
| "SIZE" -> Ok I_SIZE
|
||||||
|
| "SOME" -> Ok I_SOME
|
||||||
|
| "SOURCE" -> Ok I_SOURCE
|
||||||
|
| "SENDER" -> Ok I_SENDER
|
||||||
|
| "SELF" -> Ok I_SELF
|
||||||
|
| "SLICE" -> Ok I_SLICE
|
||||||
|
| "STEPS_TO_QUOTA" -> Ok I_STEPS_TO_QUOTA
|
||||||
|
| "SUB" -> Ok I_SUB
|
||||||
|
| "SWAP" -> Ok I_SWAP
|
||||||
|
| "TRANSFER_TOKENS" -> Ok I_TRANSFER_TOKENS
|
||||||
|
| "SET_DELEGATE" -> Ok I_SET_DELEGATE
|
||||||
|
| "UNIT" -> Ok I_UNIT
|
||||||
|
| "UPDATE" -> Ok I_UPDATE
|
||||||
|
| "XOR" -> Ok I_XOR
|
||||||
|
| "ITER" -> Ok I_ITER
|
||||||
|
| "LOOP_LEFT" -> Ok I_LOOP_LEFT
|
||||||
|
| "ADDRESS" -> Ok I_ADDRESS
|
||||||
|
| "CONTRACT" -> Ok I_CONTRACT
|
||||||
|
| "ISNAT" -> Ok I_ISNAT
|
||||||
|
| "CAST" -> Ok I_CAST
|
||||||
|
| "RENAME" -> Ok I_RENAME
|
||||||
|
| "bool" -> Ok T_bool
|
||||||
|
| "contract" -> Ok T_contract
|
||||||
|
| "int" -> Ok T_int
|
||||||
|
| "key" -> Ok T_key
|
||||||
|
| "key_hash" -> Ok T_key_hash
|
||||||
|
| "lambda" -> Ok T_lambda
|
||||||
|
| "list" -> Ok T_list
|
||||||
|
| "map" -> Ok T_map
|
||||||
|
| "big_map" -> Ok T_big_map
|
||||||
|
| "nat" -> Ok T_nat
|
||||||
|
| "option" -> Ok T_option
|
||||||
|
| "or" -> Ok T_or
|
||||||
|
| "pair" -> Ok T_pair
|
||||||
|
| "set" -> Ok T_set
|
||||||
|
| "signature" -> Ok T_signature
|
||||||
|
| "string" -> Ok T_string
|
||||||
|
| "bytes" -> Ok T_bytes
|
||||||
|
| "mutez" -> Ok T_mutez
|
||||||
|
| "timestamp" -> Ok T_timestamp
|
||||||
|
| "unit" -> Ok T_unit
|
||||||
|
| "operation" -> Ok T_operation
|
||||||
|
| "address" -> Ok T_address
|
||||||
|
| n ->
|
||||||
|
if valid_case n then
|
||||||
|
Error (Unknown_primitive_name n)
|
||||||
|
else
|
||||||
|
Error (Invalid_case n)
|
||||||
|
|
||||||
|
let (>>?) x f : (_ , failure) result = match x with
|
||||||
|
| Ok x -> f x
|
||||||
|
| Error _ as err -> err
|
||||||
|
|
||||||
|
let prims_of_strings : string canonical -> (prim Micheline_main.canonical , failure) result = fun expr ->
|
||||||
|
let rec convert : (canonical_location , string) node -> ((canonical_location , prim) node , failure) result = function
|
||||||
|
| Int _ | String _ | Bytes _ as expr -> Ok expr
|
||||||
|
| Seq (_, args) -> (
|
||||||
|
let aux : ((canonical_location , prim) node list , failure) result -> (canonical_location , string) node -> ((_ , prim) node list , failure) result =
|
||||||
|
fun acc arg ->
|
||||||
|
acc >>? fun acc' ->
|
||||||
|
convert arg >>? fun arg' ->
|
||||||
|
Ok (arg' :: acc')
|
||||||
|
in
|
||||||
|
(List.fold_left aux (Ok []) args) >>? fun args' ->
|
||||||
|
Ok (Seq (0, List.rev args'))
|
||||||
|
)
|
||||||
|
| Prim (_, prim, args, annot) -> (
|
||||||
|
prim_of_string prim >>? fun prim' ->
|
||||||
|
let aux : (_ list , failure) result -> _ -> (_ list , failure) result = fun acc arg ->
|
||||||
|
acc >>? fun args ->
|
||||||
|
convert arg >>? fun arg ->
|
||||||
|
Ok (arg :: args)
|
||||||
|
in
|
||||||
|
List.fold_left aux (Ok []) args >>? fun args' ->
|
||||||
|
Ok (Prim (0, prim', List.rev args', annot))
|
||||||
|
)
|
||||||
|
in
|
||||||
|
convert (root expr) >>? fun expr ->
|
||||||
|
Ok (strip_locations expr)
|
||||||
|
|
||||||
|
let strings_of_prims expr =
|
||||||
|
let rec convert = function
|
||||||
|
| Int _ | String _ | Bytes _ as expr -> expr
|
||||||
|
| Prim (_, prim, args, annot) ->
|
||||||
|
let prim = string_of_prim prim in
|
||||||
|
let args = List.map convert args in
|
||||||
|
Prim (0, prim, args, annot)
|
||||||
|
| Seq (_, args) ->
|
||||||
|
let args = List.map convert args in
|
||||||
|
Seq (0, args) in
|
||||||
|
strip_locations (convert (root expr))
|
||||||
|
|
||||||
|
let prim_encoding =
|
||||||
|
let open Data_encoding in
|
||||||
|
def "michelson.v1.primitives" @@
|
||||||
|
string_enum [
|
||||||
|
("parameter", K_parameter) ;
|
||||||
|
("storage", K_storage) ;
|
||||||
|
("code", K_code) ;
|
||||||
|
("False", D_False) ;
|
||||||
|
("Elt", D_Elt) ;
|
||||||
|
("Left", D_Left) ;
|
||||||
|
("None", D_None) ;
|
||||||
|
("Pair", D_Pair) ;
|
||||||
|
("Right", D_Right) ;
|
||||||
|
("Some", D_Some) ;
|
||||||
|
("True", D_True) ;
|
||||||
|
("Unit", D_Unit) ;
|
||||||
|
("PACK", I_PACK) ;
|
||||||
|
("UNPACK", I_UNPACK) ;
|
||||||
|
("BLAKE2B", I_BLAKE2B) ;
|
||||||
|
("SHA256", I_SHA256) ;
|
||||||
|
("SHA512", I_SHA512) ;
|
||||||
|
("ABS", I_ABS) ;
|
||||||
|
("ADD", I_ADD) ;
|
||||||
|
("AMOUNT", I_AMOUNT) ;
|
||||||
|
("AND", I_AND) ;
|
||||||
|
("BALANCE", I_BALANCE) ;
|
||||||
|
("CAR", I_CAR) ;
|
||||||
|
("CDR", I_CDR) ;
|
||||||
|
("CHECK_SIGNATURE", I_CHECK_SIGNATURE) ;
|
||||||
|
("COMPARE", I_COMPARE) ;
|
||||||
|
("CONCAT", I_CONCAT) ;
|
||||||
|
("CONS", I_CONS) ;
|
||||||
|
("CREATE_ACCOUNT", I_CREATE_ACCOUNT) ;
|
||||||
|
("CREATE_CONTRACT", I_CREATE_CONTRACT) ;
|
||||||
|
("IMPLICIT_ACCOUNT", I_IMPLICIT_ACCOUNT) ;
|
||||||
|
("DIP", I_DIP) ;
|
||||||
|
("DROP", I_DROP) ;
|
||||||
|
("DUP", I_DUP) ;
|
||||||
|
("EDIV", I_EDIV) ;
|
||||||
|
("EMPTY_MAP", I_EMPTY_MAP) ;
|
||||||
|
("EMPTY_SET", I_EMPTY_SET) ;
|
||||||
|
("EQ", I_EQ) ;
|
||||||
|
("EXEC", I_EXEC) ;
|
||||||
|
("FAILWITH", I_FAILWITH) ;
|
||||||
|
("GE", I_GE) ;
|
||||||
|
("GET", I_GET) ;
|
||||||
|
("GT", I_GT) ;
|
||||||
|
("HASH_KEY", I_HASH_KEY) ;
|
||||||
|
("IF", I_IF) ;
|
||||||
|
("IF_CONS", I_IF_CONS) ;
|
||||||
|
("IF_LEFT", I_IF_LEFT) ;
|
||||||
|
("IF_NONE", I_IF_NONE) ;
|
||||||
|
("INT", I_INT) ;
|
||||||
|
("LAMBDA", I_LAMBDA) ;
|
||||||
|
("LE", I_LE) ;
|
||||||
|
("LEFT", I_LEFT) ;
|
||||||
|
("LOOP", I_LOOP) ;
|
||||||
|
("LSL", I_LSL) ;
|
||||||
|
("LSR", I_LSR) ;
|
||||||
|
("LT", I_LT) ;
|
||||||
|
("MAP", I_MAP) ;
|
||||||
|
("MEM", I_MEM) ;
|
||||||
|
("MUL", I_MUL) ;
|
||||||
|
("NEG", I_NEG) ;
|
||||||
|
("NEQ", I_NEQ) ;
|
||||||
|
("NIL", I_NIL) ;
|
||||||
|
("NONE", I_NONE) ;
|
||||||
|
("NOT", I_NOT) ;
|
||||||
|
("NOW", I_NOW) ;
|
||||||
|
("OR", I_OR) ;
|
||||||
|
("PAIR", I_PAIR) ;
|
||||||
|
("PUSH", I_PUSH) ;
|
||||||
|
("RIGHT", I_RIGHT) ;
|
||||||
|
("SIZE", I_SIZE) ;
|
||||||
|
("SOME", I_SOME) ;
|
||||||
|
("SOURCE", I_SOURCE) ;
|
||||||
|
("SENDER", I_SENDER) ;
|
||||||
|
("SELF", I_SELF) ;
|
||||||
|
("STEPS_TO_QUOTA", I_STEPS_TO_QUOTA) ;
|
||||||
|
("SUB", I_SUB) ;
|
||||||
|
("SWAP", I_SWAP) ;
|
||||||
|
("TRANSFER_TOKENS", I_TRANSFER_TOKENS) ;
|
||||||
|
("SET_DELEGATE", I_SET_DELEGATE) ;
|
||||||
|
("UNIT", I_UNIT) ;
|
||||||
|
("UPDATE", I_UPDATE) ;
|
||||||
|
("XOR", I_XOR) ;
|
||||||
|
("ITER", I_ITER) ;
|
||||||
|
("LOOP_LEFT", I_LOOP_LEFT) ;
|
||||||
|
("ADDRESS", I_ADDRESS) ;
|
||||||
|
("CONTRACT", I_CONTRACT) ;
|
||||||
|
("ISNAT", I_ISNAT) ;
|
||||||
|
("CAST", I_CAST) ;
|
||||||
|
("RENAME", I_RENAME) ;
|
||||||
|
("bool", T_bool) ;
|
||||||
|
("contract", T_contract) ;
|
||||||
|
("int", T_int) ;
|
||||||
|
("key", T_key) ;
|
||||||
|
("key_hash", T_key_hash) ;
|
||||||
|
("lambda", T_lambda) ;
|
||||||
|
("list", T_list) ;
|
||||||
|
("map", T_map) ;
|
||||||
|
("big_map", T_big_map) ;
|
||||||
|
("nat", T_nat) ;
|
||||||
|
("option", T_option) ;
|
||||||
|
("or", T_or) ;
|
||||||
|
("pair", T_pair) ;
|
||||||
|
("set", T_set) ;
|
||||||
|
("signature", T_signature) ;
|
||||||
|
("string", T_string) ;
|
||||||
|
("bytes", T_bytes) ;
|
||||||
|
("mutez", T_mutez) ;
|
||||||
|
("timestamp", T_timestamp) ;
|
||||||
|
("unit", T_unit) ;
|
||||||
|
("operation", T_operation) ;
|
||||||
|
("address", T_address) ;
|
||||||
|
(* Alpha_002 addition *)
|
||||||
|
("SLICE", I_SLICE) ;
|
||||||
|
]
|
||||||
|
|
@ -49,3 +49,136 @@ val annotations : ('l, 'p) node -> string list
|
|||||||
val strip_locations : (_, 'p) node -> 'p canonical
|
val strip_locations : (_, 'p) node -> 'p canonical
|
||||||
val extract_locations : ('l, 'p) node -> 'p canonical * (canonical_location * 'l) list
|
val extract_locations : ('l, 'p) node -> 'p canonical * (canonical_location * 'l) list
|
||||||
val inject_locations : (canonical_location -> 'l) -> 'p canonical -> ('l, 'p) node
|
val inject_locations : (canonical_location -> 'l) -> 'p canonical -> ('l, 'p) node
|
||||||
|
|
||||||
|
module Michelson_primitives : sig
|
||||||
|
type prim =
|
||||||
|
| K_parameter
|
||||||
|
| K_storage
|
||||||
|
| K_code
|
||||||
|
| D_False
|
||||||
|
| D_Elt
|
||||||
|
| D_Left
|
||||||
|
| D_None
|
||||||
|
| D_Pair
|
||||||
|
| D_Right
|
||||||
|
| D_Some
|
||||||
|
| D_True
|
||||||
|
| D_Unit
|
||||||
|
| I_PACK
|
||||||
|
| I_UNPACK
|
||||||
|
| I_BLAKE2B
|
||||||
|
| I_SHA256
|
||||||
|
| I_SHA512
|
||||||
|
| I_ABS
|
||||||
|
| I_ADD
|
||||||
|
| I_AMOUNT
|
||||||
|
| I_AND
|
||||||
|
| I_BALANCE
|
||||||
|
| I_CAR
|
||||||
|
| I_CDR
|
||||||
|
| I_CHECK_SIGNATURE
|
||||||
|
| I_COMPARE
|
||||||
|
| I_CONCAT
|
||||||
|
| I_CONS
|
||||||
|
| I_CREATE_ACCOUNT
|
||||||
|
| I_CREATE_CONTRACT
|
||||||
|
| I_IMPLICIT_ACCOUNT
|
||||||
|
| I_DIP
|
||||||
|
| I_DROP
|
||||||
|
| I_DUP
|
||||||
|
| I_EDIV
|
||||||
|
| I_EMPTY_MAP
|
||||||
|
| I_EMPTY_SET
|
||||||
|
| I_EQ
|
||||||
|
| I_EXEC
|
||||||
|
| I_FAILWITH
|
||||||
|
| I_GE
|
||||||
|
| I_GET
|
||||||
|
| I_GT
|
||||||
|
| I_HASH_KEY
|
||||||
|
| I_IF
|
||||||
|
| I_IF_CONS
|
||||||
|
| I_IF_LEFT
|
||||||
|
| I_IF_NONE
|
||||||
|
| I_INT
|
||||||
|
| I_LAMBDA
|
||||||
|
| I_LE
|
||||||
|
| I_LEFT
|
||||||
|
| I_LOOP
|
||||||
|
| I_LSL
|
||||||
|
| I_LSR
|
||||||
|
| I_LT
|
||||||
|
| I_MAP
|
||||||
|
| I_MEM
|
||||||
|
| I_MUL
|
||||||
|
| I_NEG
|
||||||
|
| I_NEQ
|
||||||
|
| I_NIL
|
||||||
|
| I_NONE
|
||||||
|
| I_NOP
|
||||||
|
| I_NOT
|
||||||
|
| I_NOW
|
||||||
|
| I_OR
|
||||||
|
| I_PAIR
|
||||||
|
| I_PUSH
|
||||||
|
| I_RIGHT
|
||||||
|
| I_SIZE
|
||||||
|
| I_SOME
|
||||||
|
| I_SOURCE
|
||||||
|
| I_SENDER
|
||||||
|
| I_SELF
|
||||||
|
| I_SLICE
|
||||||
|
| I_STEPS_TO_QUOTA
|
||||||
|
| I_SUB
|
||||||
|
| I_SWAP
|
||||||
|
| I_TRANSFER_TOKENS
|
||||||
|
| I_SET_DELEGATE
|
||||||
|
| I_UNIT
|
||||||
|
| I_UPDATE
|
||||||
|
| I_XOR
|
||||||
|
| I_ITER
|
||||||
|
| I_LOOP_LEFT
|
||||||
|
| I_ADDRESS
|
||||||
|
| I_CONTRACT
|
||||||
|
| I_ISNAT
|
||||||
|
| I_CAST
|
||||||
|
| I_RENAME
|
||||||
|
| T_bool
|
||||||
|
| T_contract
|
||||||
|
| T_int
|
||||||
|
| T_key
|
||||||
|
| T_key_hash
|
||||||
|
| T_lambda
|
||||||
|
| T_list
|
||||||
|
| T_map
|
||||||
|
| T_big_map
|
||||||
|
| T_nat
|
||||||
|
| T_option
|
||||||
|
| T_or
|
||||||
|
| T_pair
|
||||||
|
| T_set
|
||||||
|
| T_signature
|
||||||
|
| T_string
|
||||||
|
| T_bytes
|
||||||
|
| T_mutez
|
||||||
|
| T_timestamp
|
||||||
|
| T_unit
|
||||||
|
| T_operation
|
||||||
|
| T_address
|
||||||
|
|
||||||
|
val prim_encoding : prim Data_encoding.encoding
|
||||||
|
|
||||||
|
val string_of_prim : prim -> string
|
||||||
|
|
||||||
|
type failure =
|
||||||
|
Unknown_primitive_name of string
|
||||||
|
| Invalid_case of string
|
||||||
|
| Invalid_primitive_name of string canonical * canonical_location
|
||||||
|
|
||||||
|
|
||||||
|
val prim_of_string : string -> (prim , failure) result
|
||||||
|
|
||||||
|
val prims_of_strings : string canonical -> (prim canonical , failure) result
|
||||||
|
|
||||||
|
val strings_of_prims : prim canonical -> string canonical
|
||||||
|
end
|
||||||
|
@ -176,6 +176,7 @@ module Make (Context : CONTEXT) = struct
|
|||||||
and type Signature.t = Signature.t
|
and type Signature.t = Signature.t
|
||||||
and type Signature.watermark = Signature.watermark
|
and type Signature.watermark = Signature.watermark
|
||||||
and type 'a Micheline.canonical = 'a Micheline.canonical
|
and type 'a Micheline.canonical = 'a Micheline.canonical
|
||||||
|
and type Micheline.Michelson_primitives.prim = Micheline.Michelson_primitives.prim
|
||||||
and type ('a, 'b) RPC_path.t = ('a, 'b) RPC_path.t
|
and type ('a, 'b) RPC_path.t = ('a, 'b) RPC_path.t
|
||||||
and type Z.t = Z.t
|
and type Z.t = Z.t
|
||||||
and type ('a, 'b) Micheline.node = ('a, 'b) Micheline.node
|
and type ('a, 'b) Micheline.node = ('a, 'b) Micheline.node
|
||||||
|
@ -155,6 +155,7 @@ module Make (Context : CONTEXT) : sig
|
|||||||
and type 'a Micheline.canonical = 'a Micheline.canonical
|
and type 'a Micheline.canonical = 'a Micheline.canonical
|
||||||
and type Z.t = Z.t
|
and type Z.t = Z.t
|
||||||
and type ('a, 'b) Micheline.node = ('a, 'b) Micheline.node
|
and type ('a, 'b) Micheline.node = ('a, 'b) Micheline.node
|
||||||
|
and type Micheline.Michelson_primitives.prim = Micheline.Michelson_primitives.prim
|
||||||
and type Data_encoding.json_schema = Data_encoding.json_schema
|
and type Data_encoding.json_schema = Data_encoding.json_schema
|
||||||
and type ('a, 'b) RPC_path.t = ('a, 'b) RPC_path.t
|
and type ('a, 'b) RPC_path.t = ('a, 'b) RPC_path.t
|
||||||
and type RPC_service.meth = RPC_service.meth
|
and type RPC_service.meth = RPC_service.meth
|
||||||
|
7
src/lib_utils/.gitignore
vendored
7
src/lib_utils/.gitignore
vendored
@ -1,7 +0,0 @@
|
|||||||
*.install
|
|
||||||
*.merlin
|
|
||||||
#*
|
|
||||||
*_opam
|
|
||||||
*~
|
|
||||||
_build/*
|
|
||||||
*/_build/*
|
|
@ -1,59 +0,0 @@
|
|||||||
open Format
|
|
||||||
let string : formatter -> string -> unit = fun ppf s -> fprintf ppf "%s" s
|
|
||||||
let tag tag : formatter -> unit -> unit = fun ppf () -> fprintf ppf tag
|
|
||||||
let bool ppf b = fprintf ppf "%b" b
|
|
||||||
let pair f g ppf (a , b) = fprintf ppf "%a , %a" f a g b
|
|
||||||
let new_line : formatter -> unit -> unit = tag "@;"
|
|
||||||
let rec new_lines n ppf () =
|
|
||||||
match n with
|
|
||||||
| 0 -> new_line ppf ()
|
|
||||||
| n -> new_line ppf () ; new_lines (n-1) ppf ()
|
|
||||||
let const const : formatter -> unit -> unit = fun ppf () -> fprintf ppf "%s" const
|
|
||||||
let comment : formatter -> string -> unit = fun ppf s -> fprintf ppf "(* %s *)" s
|
|
||||||
let list_sep value separator = pp_print_list ~pp_sep:separator value
|
|
||||||
let list value = pp_print_list ~pp_sep:(tag "") value
|
|
||||||
let ne_list_sep value separator ppf (hd, tl) =
|
|
||||||
value ppf hd ;
|
|
||||||
separator ppf () ;
|
|
||||||
pp_print_list ~pp_sep:separator value ppf tl
|
|
||||||
|
|
||||||
let prepend s f ppf a =
|
|
||||||
fprintf ppf "%s%a" s f a
|
|
||||||
|
|
||||||
let option = fun f ppf opt ->
|
|
||||||
match opt with
|
|
||||||
| Some x -> fprintf ppf "Some(%a)" f x
|
|
||||||
| None -> fprintf ppf "None"
|
|
||||||
|
|
||||||
let lr = fun ppf lr ->
|
|
||||||
match lr with
|
|
||||||
| `Left -> fprintf ppf "left"
|
|
||||||
| `Right -> fprintf ppf "right"
|
|
||||||
|
|
||||||
let int = fun ppf n -> fprintf ppf "%d" n
|
|
||||||
|
|
||||||
let map = fun f pp ppf x ->
|
|
||||||
pp ppf (f x)
|
|
||||||
|
|
||||||
let pair_sep value sep ppf (a, b) = fprintf ppf "%a %s %a" value a sep value b
|
|
||||||
let smap_sep value sep ppf m =
|
|
||||||
let module SMap = X_map.String in
|
|
||||||
let lst = SMap.to_kv_list m in
|
|
||||||
let new_pp ppf (k, v) = fprintf ppf "%s -> %a" k value v in
|
|
||||||
fprintf ppf "%a" (list_sep new_pp sep) lst
|
|
||||||
|
|
||||||
(* TODO: remove all uses. this is bad. *)
|
|
||||||
let printer : ('a -> unit) -> _ -> 'a -> unit = fun f ppf x ->
|
|
||||||
let oldstdout = Unix.dup Unix.stdout in
|
|
||||||
let name = "/tmp/wtf-" ^ (string_of_int @@ Random.bits ()) in
|
|
||||||
let newstdout = open_out name in
|
|
||||||
Unix.dup2 (Unix.descr_of_out_channel newstdout) Unix.stdout;
|
|
||||||
f x;
|
|
||||||
flush stdout;
|
|
||||||
Unix.dup2 oldstdout Unix.stdout;
|
|
||||||
let ic = open_in name in
|
|
||||||
let n = in_channel_length ic in
|
|
||||||
let s = Bytes.create n in
|
|
||||||
really_input ic s 0 n;
|
|
||||||
close_in ic;
|
|
||||||
fprintf ppf "%s" (Bytes.to_string s)
|
|
@ -1,190 +0,0 @@
|
|||||||
module Error_monad = X_error_monad
|
|
||||||
open Tezos_micheline
|
|
||||||
|
|
||||||
let env = Error_monad.force_lwt ~msg:"Cast:init environment" @@ Init_proto_alpha.init_environment ()
|
|
||||||
|
|
||||||
open Memory_proto_alpha
|
|
||||||
open Alpha_context
|
|
||||||
|
|
||||||
exception Expr_from_string
|
|
||||||
let expr_of_string str =
|
|
||||||
let (ast, errs) = Michelson_parser.V1.parse_expression ~check:false str in
|
|
||||||
(match errs with
|
|
||||||
| [] -> ()
|
|
||||||
| lst -> (
|
|
||||||
Format.printf "expr_from_string: %a\n" Error_monad.pp_print_error lst;
|
|
||||||
raise Expr_from_string
|
|
||||||
));
|
|
||||||
ast.expanded
|
|
||||||
|
|
||||||
let tl_of_string str =
|
|
||||||
let (ast, errs) = Michelson_parser.V1.parse_toplevel ~check:false str in
|
|
||||||
(match errs with
|
|
||||||
| [] -> ()
|
|
||||||
| lst -> (
|
|
||||||
Format.printf "expr_from_string: %a\n" Error_monad.pp_print_error lst;
|
|
||||||
raise Expr_from_string
|
|
||||||
));
|
|
||||||
ast.expanded
|
|
||||||
|
|
||||||
let lexpr_of_string str =
|
|
||||||
Script.lazy_expr @@ expr_of_string str
|
|
||||||
|
|
||||||
let ltl_of_string str =
|
|
||||||
Script.lazy_expr @@ tl_of_string str
|
|
||||||
|
|
||||||
let node_of_string str =
|
|
||||||
Micheline.root @@ expr_of_string str
|
|
||||||
|
|
||||||
let node_to_string (node:_ Micheline.node) =
|
|
||||||
let stripped = Micheline.strip_locations node in
|
|
||||||
let print_node = Micheline_printer.printable Michelson_v1_primitives.string_of_prim stripped in
|
|
||||||
Micheline_printer.print_expr Format.str_formatter print_node ;
|
|
||||||
Format.flush_str_formatter ()
|
|
||||||
|
|
||||||
open Script_ir_translator
|
|
||||||
|
|
||||||
let rec mapper (Ex_typed_value (ty, a)) =
|
|
||||||
let open Alpha_environment.Error_monad in
|
|
||||||
let open Script_typed_ir in
|
|
||||||
let open Micheline in
|
|
||||||
match ty, a with
|
|
||||||
| Big_map_t (kt, vt, Some (`Type_annot "toto")), map ->
|
|
||||||
let kt = ty_of_comparable_ty kt in
|
|
||||||
fold_left_s
|
|
||||||
(fun l (k, v) ->
|
|
||||||
match v with
|
|
||||||
| None -> return l
|
|
||||||
| Some v -> (
|
|
||||||
let key = data_to_node (Ex_typed_value (kt, k)) in
|
|
||||||
let value = data_to_node (Ex_typed_value (vt, v)) in
|
|
||||||
return (Prim (-1, Michelson_v1_primitives.D_Elt, [ key ; value ], []) :: l))
|
|
||||||
)
|
|
||||||
[]
|
|
||||||
(map_fold (fun k v acc -> (k, v) :: acc) map.diff []) >>=? fun items ->
|
|
||||||
return (Some (Micheline.Seq (-1, String (-1, "...") :: items)))
|
|
||||||
| _ -> return None
|
|
||||||
|
|
||||||
and data_to_node (Ex_typed_value (ty, data)) =
|
|
||||||
let tc = env.tezos_context in
|
|
||||||
let node_lwt = Script_ir_translator.unparse_data tc ~mapper Readable ty data in
|
|
||||||
let node = fst @@ Error_monad.force_lwt_alpha ~msg:"data to string" node_lwt in
|
|
||||||
node
|
|
||||||
|
|
||||||
let data_to_string ty data =
|
|
||||||
let node = data_to_node (Ex_typed_value (ty, data)) in
|
|
||||||
node_to_string node
|
|
||||||
|
|
||||||
open Script_typed_ir
|
|
||||||
open Script_interpreter
|
|
||||||
type ex_typed_stack =
|
|
||||||
Ex_typed_stack : ('a stack_ty * 'a stack) -> ex_typed_stack
|
|
||||||
|
|
||||||
let stack_to_string stack_ty stack =
|
|
||||||
let rec aux acc fst (Ex_typed_stack(stack_ty,stack)) =
|
|
||||||
match (stack_ty, stack) with
|
|
||||||
| Item_t (hd_ty, tl_ty, _), Item (hd, tl) -> (
|
|
||||||
let separator = if not fst then " ; " else "" in
|
|
||||||
let str = data_to_string hd_ty hd in
|
|
||||||
let acc = acc ^ separator ^ str in
|
|
||||||
let new_value = aux acc false (Ex_typed_stack (tl_ty, tl)) in
|
|
||||||
new_value
|
|
||||||
)
|
|
||||||
| _ -> acc in
|
|
||||||
aux "" true @@ Ex_typed_stack(stack_ty, stack)
|
|
||||||
|
|
||||||
let ty_to_node ty =
|
|
||||||
let (node, _) = Error_monad.force_lwt_alpha ~msg:"ty to node" @@ Script_ir_translator.unparse_ty env.tezos_context ty in
|
|
||||||
node
|
|
||||||
|
|
||||||
type ex_descr =
|
|
||||||
Ex_descr : (_, _) Script_typed_ir.descr -> ex_descr
|
|
||||||
|
|
||||||
let descr_to_node x =
|
|
||||||
let open Alpha_context.Script in
|
|
||||||
let open Micheline in
|
|
||||||
let open Script_typed_ir in
|
|
||||||
let rec f : ex_descr -> Script.node = fun descr ->
|
|
||||||
let prim ?children ?children_nodes p =
|
|
||||||
match (children, children_nodes) with
|
|
||||||
| Some children, None ->
|
|
||||||
Prim (0, p, List.map f children, [])
|
|
||||||
| Some _, Some _ ->
|
|
||||||
raise @@ Failure "descr_to_node: too many parameters"
|
|
||||||
| None, Some children_nodes ->
|
|
||||||
Prim (0, p, children_nodes, [])
|
|
||||||
| None, None ->
|
|
||||||
Prim (0, p, [], [])
|
|
||||||
in
|
|
||||||
let (Ex_descr descr) = descr in
|
|
||||||
match descr.instr with
|
|
||||||
| Dup -> prim I_DUP
|
|
||||||
| Drop -> prim I_DROP
|
|
||||||
| Swap -> prim I_SWAP
|
|
||||||
| Dip c -> prim ~children:[Ex_descr c] I_DIP
|
|
||||||
| Car -> prim I_CAR
|
|
||||||
| Cdr -> prim I_CDR
|
|
||||||
| Cons_pair -> prim I_PAIR
|
|
||||||
| Nop -> prim I_NOP
|
|
||||||
| Seq (a, b) -> Micheline.Seq (0, List.map f [Ex_descr a ; Ex_descr b])
|
|
||||||
| Const v -> (
|
|
||||||
let (Item_t (ty, _, _)) = descr.aft in
|
|
||||||
prim ~children_nodes:[data_to_node (Ex_typed_value (ty, v))] I_PUSH
|
|
||||||
)
|
|
||||||
| Failwith _ -> prim I_FAILWITH
|
|
||||||
| If (a, b) -> prim ~children:[Ex_descr a ; Ex_descr b] I_IF
|
|
||||||
| Loop c -> prim ~children:[Ex_descr c] I_LOOP
|
|
||||||
| If_left (a, b) -> prim ~children:[Ex_descr a ; Ex_descr b] I_IF_LEFT
|
|
||||||
| Left -> prim I_LEFT
|
|
||||||
| Right -> prim I_RIGHT
|
|
||||||
| Loop_left c -> prim ~children:[Ex_descr c] I_LOOP_LEFT
|
|
||||||
| If_none (a, b) -> prim ~children:[Ex_descr a ; Ex_descr b] I_IF_NONE
|
|
||||||
| Cons_none _ -> prim I_NONE
|
|
||||||
| Cons_some -> prim I_SOME
|
|
||||||
| Nil -> prim I_NIL
|
|
||||||
| Cons_list -> prim I_CONS
|
|
||||||
| If_cons (a, b) -> prim ~children:[Ex_descr a ; Ex_descr b] I_IF_CONS
|
|
||||||
| List_iter _ -> prim I_ITER
|
|
||||||
| Compare _ -> prim I_COMPARE
|
|
||||||
| Int_nat -> prim I_INT
|
|
||||||
| Add_natnat -> prim I_ADD
|
|
||||||
| Add_natint -> prim I_ADD
|
|
||||||
| Add_intnat -> prim I_ADD
|
|
||||||
| Sub_int -> prim I_SUB
|
|
||||||
| Mul_natnat -> prim I_MUL
|
|
||||||
| Ediv_natnat -> prim I_MUL
|
|
||||||
| Map_get -> prim I_GET
|
|
||||||
| Map_update -> prim I_UPDATE
|
|
||||||
| Big_map_get -> prim I_GET
|
|
||||||
| Big_map_update -> prim I_UPDATE
|
|
||||||
| Gt -> prim I_GT
|
|
||||||
| Ge -> prim I_GE
|
|
||||||
| Pack _ -> prim I_PACK
|
|
||||||
| Unpack _ -> prim I_UNPACK
|
|
||||||
| Blake2b -> prim I_BLAKE2B
|
|
||||||
| And -> prim I_AND
|
|
||||||
| Xor -> prim I_XOR
|
|
||||||
| _ -> raise @@ Failure "descr to node" in
|
|
||||||
f @@ Ex_descr x
|
|
||||||
|
|
||||||
let rec flatten_node =
|
|
||||||
let open Micheline in
|
|
||||||
function
|
|
||||||
| Seq (a, lst) -> (
|
|
||||||
let aux = function
|
|
||||||
| Prim (loc, p, children, annot) -> [ Prim (loc, p, List.map flatten_node children, annot) ]
|
|
||||||
| Seq (_, lst) -> List.map flatten_node lst
|
|
||||||
| x -> [ x ] in
|
|
||||||
let seqs = List.map aux @@ List.map flatten_node lst in
|
|
||||||
Seq (a, List.concat seqs) )
|
|
||||||
| x -> x
|
|
||||||
|
|
||||||
let descr_to_string descr =
|
|
||||||
let node = descr_to_node descr in
|
|
||||||
let node = flatten_node node in
|
|
||||||
node_to_string node
|
|
||||||
|
|
||||||
let n_of_int n =
|
|
||||||
match Script_int.is_nat @@ Script_int.of_int n with
|
|
||||||
| None -> raise @@ Failure "n_of_int"
|
|
||||||
| Some n -> n
|
|
@ -1,53 +0,0 @@
|
|||||||
open Trace
|
|
||||||
|
|
||||||
module type DICTIONARY = sig
|
|
||||||
type ('a, 'b) t
|
|
||||||
|
|
||||||
val get_exn : ('a, 'b) t -> 'a -> 'b
|
|
||||||
val get : ('a, 'b) t -> 'a -> 'b result
|
|
||||||
|
|
||||||
val set :
|
|
||||||
?equal:('a -> 'a -> bool) ->
|
|
||||||
('a, 'b) t -> 'a -> 'b -> ('a, 'b) t
|
|
||||||
|
|
||||||
val del :
|
|
||||||
?equal:('a -> 'a -> bool) ->
|
|
||||||
('a, 'b) t -> 'a -> ('a, 'b) t
|
|
||||||
|
|
||||||
val to_list : ('a, 'b) t -> ('a * 'b) list
|
|
||||||
end
|
|
||||||
|
|
||||||
module Assoc : DICTIONARY = struct
|
|
||||||
|
|
||||||
type ('a, 'b) t = ('a * 'b) list
|
|
||||||
|
|
||||||
let get_exn x y = List.assoc y x
|
|
||||||
|
|
||||||
let get x y = generic_try (simple_error "Dictionry.get") @@ fun () -> get_exn x y
|
|
||||||
|
|
||||||
let set ?equal lst a b =
|
|
||||||
let equal : 'a -> 'a -> bool =
|
|
||||||
X_option.unopt
|
|
||||||
~default:(=) equal
|
|
||||||
in
|
|
||||||
let rec aux acc = function
|
|
||||||
| [] -> List.rev acc
|
|
||||||
| (key, _)::tl when equal key a -> aux ((key, b) :: acc) tl
|
|
||||||
| hd::tl -> aux (hd :: acc) tl
|
|
||||||
in
|
|
||||||
aux [] lst
|
|
||||||
|
|
||||||
let del ?equal lst a =
|
|
||||||
let equal : 'a -> 'a -> bool =
|
|
||||||
X_option.unopt
|
|
||||||
~default:(=) equal
|
|
||||||
in
|
|
||||||
let rec aux acc = function
|
|
||||||
| [] -> List.rev acc
|
|
||||||
| (key, _)::tl when equal key a -> aux acc tl
|
|
||||||
| hd::tl -> aux (hd :: acc) tl
|
|
||||||
in
|
|
||||||
aux [] lst
|
|
||||||
|
|
||||||
let to_list x = x
|
|
||||||
end
|
|
@ -1,14 +0,0 @@
|
|||||||
(library
|
|
||||||
(name tezos_utils)
|
|
||||||
(public_name tezos-utils)
|
|
||||||
(libraries
|
|
||||||
tezos-stdlib-unix
|
|
||||||
tezos-crypto
|
|
||||||
tezos-data-encoding
|
|
||||||
tezos-protocol-environment
|
|
||||||
tezos-protocol-alpha
|
|
||||||
tezos-micheline
|
|
||||||
michelson-parser
|
|
||||||
yojson
|
|
||||||
)
|
|
||||||
)
|
|
@ -1,8 +0,0 @@
|
|||||||
let constant x _ = x
|
|
||||||
|
|
||||||
let compose = fun f g x -> f (g x)
|
|
||||||
let (>|) = compose
|
|
||||||
|
|
||||||
let compose_2 = fun f g x y -> f (g x y)
|
|
||||||
let compose_3 = fun f g x y z -> f (g x y z)
|
|
||||||
let compose_4 = fun f g a b c d -> f (g a b c d)
|
|
@ -1,291 +0,0 @@
|
|||||||
open Memory_proto_alpha
|
|
||||||
module Signature = Tezos_base.TzPervasives.Signature
|
|
||||||
module Data_encoding = Alpha_environment.Data_encoding
|
|
||||||
module MBytes = Alpha_environment.MBytes
|
|
||||||
module Error_monad = X_error_monad
|
|
||||||
open Error_monad
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module Context_init = struct
|
|
||||||
|
|
||||||
type account = {
|
|
||||||
pkh : Signature.Public_key_hash.t ;
|
|
||||||
pk : Signature.Public_key.t ;
|
|
||||||
sk : Signature.Secret_key.t ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let generate_accounts n : (account * Tez_repr.t) list =
|
|
||||||
let amount = Tez_repr.of_mutez_exn 4_000_000_000_000L in
|
|
||||||
List.map (fun _ ->
|
|
||||||
let (pkh, pk, sk) = Signature.generate_key () in
|
|
||||||
let account = { pkh ; pk ; sk } in
|
|
||||||
account, amount)
|
|
||||||
(X_list.range n)
|
|
||||||
|
|
||||||
let make_shell
|
|
||||||
~level ~predecessor ~timestamp ~fitness ~operations_hash =
|
|
||||||
Tezos_base.Block_header.{
|
|
||||||
level ;
|
|
||||||
predecessor ;
|
|
||||||
timestamp ;
|
|
||||||
fitness ;
|
|
||||||
operations_hash ;
|
|
||||||
(* We don't care of the following values, only the shell validates them. *)
|
|
||||||
proto_level = 0 ;
|
|
||||||
validation_passes = 0 ;
|
|
||||||
context = Alpha_environment.Context_hash.zero ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let default_proof_of_work_nonce =
|
|
||||||
MBytes.create Alpha_context.Constants.proof_of_work_nonce_size
|
|
||||||
|
|
||||||
let protocol_param_key = [ "protocol_parameters" ]
|
|
||||||
|
|
||||||
let check_constants_consistency constants =
|
|
||||||
let open Constants_repr in
|
|
||||||
let open Error_monad in
|
|
||||||
let { blocks_per_cycle ; blocks_per_commitment ;
|
|
||||||
blocks_per_roll_snapshot ; _ } = constants in
|
|
||||||
Error_monad.unless (blocks_per_commitment <= blocks_per_cycle)
|
|
||||||
(fun () -> failwith "Inconsistent constants : blocks per commitment must be \
|
|
||||||
less than blocks per cycle") >>=? fun () ->
|
|
||||||
Error_monad.unless (blocks_per_cycle >= blocks_per_roll_snapshot)
|
|
||||||
(fun () -> failwith "Inconsistent constants : blocks per cycle \
|
|
||||||
must be superior than blocks per roll snapshot") >>=?
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
let initial_context
|
|
||||||
constants
|
|
||||||
header
|
|
||||||
commitments
|
|
||||||
initial_accounts
|
|
||||||
security_deposit_ramp_up_cycles
|
|
||||||
no_reward_cycles
|
|
||||||
=
|
|
||||||
let open Tezos_base.TzPervasives.Error_monad in
|
|
||||||
let bootstrap_accounts =
|
|
||||||
List.map (fun ({ pk ; pkh ; _ }, amount) ->
|
|
||||||
Parameters_repr.{ public_key_hash = pkh ; public_key = Some pk ; amount }
|
|
||||||
) initial_accounts
|
|
||||||
in
|
|
||||||
let json =
|
|
||||||
Data_encoding.Json.construct
|
|
||||||
Parameters_repr.encoding
|
|
||||||
Parameters_repr.{
|
|
||||||
bootstrap_accounts ;
|
|
||||||
bootstrap_contracts = [] ;
|
|
||||||
commitments ;
|
|
||||||
constants ;
|
|
||||||
security_deposit_ramp_up_cycles ;
|
|
||||||
no_reward_cycles ;
|
|
||||||
}
|
|
||||||
in
|
|
||||||
let proto_params =
|
|
||||||
Data_encoding.Binary.to_bytes_exn Data_encoding.json json
|
|
||||||
in
|
|
||||||
Tezos_protocol_environment_memory.Context.(
|
|
||||||
set empty ["version"] (MBytes.of_string "genesis")
|
|
||||||
) >>= fun ctxt ->
|
|
||||||
Tezos_protocol_environment_memory.Context.(
|
|
||||||
set ctxt protocol_param_key proto_params
|
|
||||||
) >>= fun ctxt ->
|
|
||||||
Main.init ctxt header
|
|
||||||
>|= Alpha_environment.wrap_error >>=? fun { context; _ } ->
|
|
||||||
return context
|
|
||||||
|
|
||||||
let genesis
|
|
||||||
?(preserved_cycles = Constants_repr.default.preserved_cycles)
|
|
||||||
?(blocks_per_cycle = Constants_repr.default.blocks_per_cycle)
|
|
||||||
?(blocks_per_commitment = Constants_repr.default.blocks_per_commitment)
|
|
||||||
?(blocks_per_roll_snapshot = Constants_repr.default.blocks_per_roll_snapshot)
|
|
||||||
?(blocks_per_voting_period = Constants_repr.default.blocks_per_voting_period)
|
|
||||||
?(time_between_blocks = Constants_repr.default.time_between_blocks)
|
|
||||||
?(endorsers_per_block = Constants_repr.default.endorsers_per_block)
|
|
||||||
?(hard_gas_limit_per_operation = Constants_repr.default.hard_gas_limit_per_operation)
|
|
||||||
?(hard_gas_limit_per_block = Constants_repr.default.hard_gas_limit_per_block)
|
|
||||||
?(proof_of_work_threshold = Int64.(neg one))
|
|
||||||
?(tokens_per_roll = Constants_repr.default.tokens_per_roll)
|
|
||||||
?(michelson_maximum_type_size = Constants_repr.default.michelson_maximum_type_size)
|
|
||||||
?(seed_nonce_revelation_tip = Constants_repr.default.seed_nonce_revelation_tip)
|
|
||||||
?(origination_size = Constants_repr.default.origination_size)
|
|
||||||
?(block_security_deposit = Constants_repr.default.block_security_deposit)
|
|
||||||
?(endorsement_security_deposit = Constants_repr.default.endorsement_security_deposit)
|
|
||||||
?(block_reward = Constants_repr.default.block_reward)
|
|
||||||
?(endorsement_reward = Constants_repr.default.endorsement_reward)
|
|
||||||
?(cost_per_byte = Constants_repr.default.cost_per_byte)
|
|
||||||
?(hard_storage_limit_per_operation = Constants_repr.default.hard_storage_limit_per_operation)
|
|
||||||
?(commitments = [])
|
|
||||||
?(security_deposit_ramp_up_cycles = None)
|
|
||||||
?(no_reward_cycles = None)
|
|
||||||
(initial_accounts : (account * Tez_repr.t) list)
|
|
||||||
=
|
|
||||||
if initial_accounts = [] then
|
|
||||||
Pervasives.failwith "Must have one account with a roll to bake";
|
|
||||||
|
|
||||||
(* Check there is at least one roll *)
|
|
||||||
let open Tezos_base.TzPervasives.Error_monad in
|
|
||||||
begin try
|
|
||||||
let (>>?=) x y = match x with
|
|
||||||
| Ok(a) -> y a
|
|
||||||
| Error(b) -> fail @@ List.hd b in
|
|
||||||
fold_left_s (fun acc (_, amount) ->
|
|
||||||
Alpha_environment.wrap_error @@
|
|
||||||
Tez_repr.(+?) acc amount >>?= fun acc ->
|
|
||||||
if acc >= tokens_per_roll then
|
|
||||||
raise Exit
|
|
||||||
else return acc
|
|
||||||
) Tez_repr.zero initial_accounts >>=? fun _ ->
|
|
||||||
failwith "Insufficient tokens in initial accounts to create one roll"
|
|
||||||
with Exit -> return ()
|
|
||||||
end >>=? fun () ->
|
|
||||||
|
|
||||||
let constants : Constants_repr.parametric = {
|
|
||||||
preserved_cycles ;
|
|
||||||
blocks_per_cycle ;
|
|
||||||
blocks_per_commitment ;
|
|
||||||
blocks_per_roll_snapshot ;
|
|
||||||
blocks_per_voting_period ;
|
|
||||||
time_between_blocks ;
|
|
||||||
endorsers_per_block ;
|
|
||||||
hard_gas_limit_per_operation ;
|
|
||||||
hard_gas_limit_per_block ;
|
|
||||||
proof_of_work_threshold ;
|
|
||||||
tokens_per_roll ;
|
|
||||||
michelson_maximum_type_size ;
|
|
||||||
seed_nonce_revelation_tip ;
|
|
||||||
origination_size ;
|
|
||||||
block_security_deposit ;
|
|
||||||
endorsement_security_deposit ;
|
|
||||||
block_reward ;
|
|
||||||
endorsement_reward ;
|
|
||||||
cost_per_byte ;
|
|
||||||
hard_storage_limit_per_operation ;
|
|
||||||
} in
|
|
||||||
check_constants_consistency constants >>=? fun () ->
|
|
||||||
|
|
||||||
let hash =
|
|
||||||
Alpha_environment.Block_hash.of_b58check_exn "BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU"
|
|
||||||
in
|
|
||||||
let shell = make_shell
|
|
||||||
~level:0l
|
|
||||||
~predecessor:hash
|
|
||||||
~timestamp:Tezos_base.TzPervasives.Time.epoch
|
|
||||||
~fitness: (Fitness_repr.from_int64 0L)
|
|
||||||
~operations_hash: Alpha_environment.Operation_list_list_hash.zero in
|
|
||||||
initial_context
|
|
||||||
constants
|
|
||||||
shell
|
|
||||||
commitments
|
|
||||||
initial_accounts
|
|
||||||
security_deposit_ramp_up_cycles
|
|
||||||
no_reward_cycles
|
|
||||||
>>=? fun context ->
|
|
||||||
return (context, shell, hash)
|
|
||||||
|
|
||||||
let init
|
|
||||||
?(slow=false)
|
|
||||||
?preserved_cycles
|
|
||||||
?endorsers_per_block
|
|
||||||
?commitments
|
|
||||||
n =
|
|
||||||
let open Error_monad in
|
|
||||||
let accounts = generate_accounts n in
|
|
||||||
let contracts = List.map (fun (a, _) ->
|
|
||||||
Alpha_context.Contract.implicit_contract (a.pkh)) accounts in
|
|
||||||
begin
|
|
||||||
if slow then
|
|
||||||
genesis
|
|
||||||
?preserved_cycles
|
|
||||||
?endorsers_per_block
|
|
||||||
?commitments
|
|
||||||
accounts
|
|
||||||
else
|
|
||||||
genesis
|
|
||||||
?preserved_cycles
|
|
||||||
~blocks_per_cycle:32l
|
|
||||||
~blocks_per_commitment:4l
|
|
||||||
~blocks_per_roll_snapshot:8l
|
|
||||||
~blocks_per_voting_period:(Int32.mul 32l 8l)
|
|
||||||
?endorsers_per_block
|
|
||||||
?commitments
|
|
||||||
accounts
|
|
||||||
end >>=? fun ctxt ->
|
|
||||||
return (ctxt, accounts, contracts)
|
|
||||||
|
|
||||||
let contents
|
|
||||||
?(proof_of_work_nonce = default_proof_of_work_nonce)
|
|
||||||
?(priority = 0) ?seed_nonce_hash () =
|
|
||||||
Alpha_context.Block_header.({
|
|
||||||
priority ;
|
|
||||||
proof_of_work_nonce ;
|
|
||||||
seed_nonce_hash ;
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
let begin_construction ?(priority=0) ~timestamp ~(header:Alpha_context.Block_header.shell_header) ~hash ctxt =
|
|
||||||
let contents = contents ~priority () in
|
|
||||||
let protocol_data = Alpha_context.Block_header.{
|
|
||||||
contents ;
|
|
||||||
signature = Signature.zero ;
|
|
||||||
} in
|
|
||||||
let timestamp = Alpha_environment.Time.add timestamp @@ Int64.of_int 180 in
|
|
||||||
Main.begin_construction
|
|
||||||
~chain_id: Alpha_environment.Chain_id.zero
|
|
||||||
~predecessor_context: ctxt
|
|
||||||
~predecessor_timestamp: header.timestamp
|
|
||||||
~predecessor_fitness: header.fitness
|
|
||||||
~predecessor_level: header.level
|
|
||||||
~predecessor:hash
|
|
||||||
~timestamp
|
|
||||||
~protocol_data
|
|
||||||
() >>= fun x -> Lwt.return @@ Alpha_environment.wrap_error x >>=? fun state ->
|
|
||||||
return state.ctxt
|
|
||||||
|
|
||||||
let main n =
|
|
||||||
init n >>=? fun ((ctxt, header, hash), accounts, contracts) ->
|
|
||||||
let timestamp = Tezos_base.Time.now () in
|
|
||||||
begin_construction ~timestamp ~header ~hash ctxt >>=? fun ctxt ->
|
|
||||||
return (ctxt, accounts, contracts)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
type identity = {
|
|
||||||
public_key_hash : Signature.public_key_hash;
|
|
||||||
public_key : Signature.public_key;
|
|
||||||
secret_key : Signature.secret_key;
|
|
||||||
implicit_contract : Alpha_context.Contract.t;
|
|
||||||
}
|
|
||||||
|
|
||||||
type environment = {
|
|
||||||
tezos_context : Alpha_context.t ;
|
|
||||||
identities : identity list ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let init_environment () =
|
|
||||||
Context_init.main 10 >>=? fun (tezos_context, accounts, contracts) ->
|
|
||||||
let accounts = List.map fst accounts in
|
|
||||||
let tezos_context = Alpha_context.Gas.set_limit tezos_context @@ Z.of_int 350000 in
|
|
||||||
let identities =
|
|
||||||
List.map (fun ((a:Context_init.account), c) -> {
|
|
||||||
public_key = a.pk ;
|
|
||||||
public_key_hash = a.pkh ;
|
|
||||||
secret_key = a.sk ;
|
|
||||||
implicit_contract = c ;
|
|
||||||
}) @@
|
|
||||||
List.combine accounts contracts in
|
|
||||||
return {tezos_context ; identities}
|
|
||||||
|
|
||||||
let contextualize ~msg ?environment f =
|
|
||||||
let lwt =
|
|
||||||
let environment = match environment with
|
|
||||||
| None -> init_environment ()
|
|
||||||
| Some x -> return x in
|
|
||||||
environment >>=? f
|
|
||||||
in
|
|
||||||
force_ok ~msg @@ Lwt_main.run lwt
|
|
||||||
|
|
||||||
let dummy_environment =
|
|
||||||
X_error_monad.force_lwt ~msg:"Init_proto_alpha : initing dummy environment" @@
|
|
||||||
init_environment ()
|
|
@ -1,37 +0,0 @@
|
|||||||
(* type file_location = { *)
|
|
||||||
(* filename : string ; *)
|
|
||||||
(* start_line : int ; *)
|
|
||||||
(* start_column : int ; *)
|
|
||||||
(* end_line : int ; *)
|
|
||||||
(* end_column : int ; *)
|
|
||||||
(* } *)
|
|
||||||
|
|
||||||
type virtual_location = string
|
|
||||||
|
|
||||||
type t =
|
|
||||||
| File of Region.t (* file_location *)
|
|
||||||
| Virtual of virtual_location
|
|
||||||
|
|
||||||
let make (start_pos:Lexing.position) (end_pos:Lexing.position) : t =
|
|
||||||
(* TODO: give correct unicode offsets (the random number is here so
|
|
||||||
that searching for wrong souce locations appearing in messages
|
|
||||||
will quickly lead here *)
|
|
||||||
File (Region.make
|
|
||||||
~start:(Pos.make ~byte:start_pos ~point_num:(-1897000) ~point_bol:(-1897000))
|
|
||||||
~stop:(Pos.make ~byte:end_pos ~point_num:(-1897000) ~point_bol:(-1897000)))
|
|
||||||
|
|
||||||
let virtual_location s = Virtual s
|
|
||||||
let dummy = virtual_location "dummy"
|
|
||||||
|
|
||||||
type 'a wrap = {
|
|
||||||
wrap_content : 'a ;
|
|
||||||
location : t ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let wrap ~loc wrap_content = { wrap_content ; location = loc }
|
|
||||||
let unwrap { wrap_content ; _ } = wrap_content
|
|
||||||
let map f x = { x with wrap_content = f x.wrap_content }
|
|
||||||
let pp_wrap f ppf { wrap_content ; _ } = Format.fprintf ppf "%a" f wrap_content
|
|
||||||
|
|
||||||
let lift_region : 'a Region.reg -> 'a wrap = fun x ->
|
|
||||||
wrap ~loc:(File x.region) x.value
|
|
@ -1,11 +0,0 @@
|
|||||||
module Stateful () : sig
|
|
||||||
val log : string -> unit
|
|
||||||
val get : unit -> string
|
|
||||||
end = struct
|
|
||||||
|
|
||||||
let logger = ref ""
|
|
||||||
let log : string -> unit =
|
|
||||||
fun s -> logger := !logger ^ s
|
|
||||||
let get () : string = !logger
|
|
||||||
|
|
||||||
end
|
|
@ -1,15 +0,0 @@
|
|||||||
(library
|
|
||||||
(name michelson_parser)
|
|
||||||
(public_name michelson-parser)
|
|
||||||
(libraries
|
|
||||||
tezos-base
|
|
||||||
tezos-memory-proto-alpha
|
|
||||||
)
|
|
||||||
(flags (:standard -w -9-32 -safe-string
|
|
||||||
-open Tezos_base__TzPervasives
|
|
||||||
)))
|
|
||||||
|
|
||||||
(alias
|
|
||||||
(name runtest_indent)
|
|
||||||
(deps (glob_files *.ml*))
|
|
||||||
(action (run bash %{libexec:tezos-stdlib:test-ocp-indent.sh} %{deps})))
|
|
@ -1,21 +0,0 @@
|
|||||||
name: "michelson-parser"
|
|
||||||
opam-version: "2.0"
|
|
||||||
version: "1.0"
|
|
||||||
maintainer: "gabriel.alfour@gmail.com"
|
|
||||||
authors: [ "Galfour" ]
|
|
||||||
homepage: "https://gitlab.com/gabriel.alfour/tezos"
|
|
||||||
bug-reports: "https://gitlab.com/gabriel.alfour/tezos/issues"
|
|
||||||
dev-repo: "git+https://gitlab.com/gabriel.alfour/tezos.git"
|
|
||||||
license: "MIT"
|
|
||||||
depends: [
|
|
||||||
"ocamlfind" { build }
|
|
||||||
"dune"
|
|
||||||
"tezos-memory-proto-alpha"
|
|
||||||
]
|
|
||||||
build: [
|
|
||||||
[ "dune" "build" "-p" name "-j" jobs ]
|
|
||||||
[ "mv" "src/lib_utils/michelson-parser/michelson-parser.install" "." ]
|
|
||||||
]
|
|
||||||
url {
|
|
||||||
src: "https://gitlab.com/gabriel.alfour/tezos/-/archive/master/tezos.tar.gz"
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,62 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
open Tezos_micheline
|
|
||||||
|
|
||||||
type 'l node = ('l, string) Micheline.node
|
|
||||||
|
|
||||||
type error += Unexpected_macro_annotation of string
|
|
||||||
type error += Sequence_expected of string
|
|
||||||
type error += Invalid_arity of string * int * int
|
|
||||||
|
|
||||||
val expand : 'l node -> 'l node tzresult
|
|
||||||
val expand_rec : 'l node -> 'l node * error list
|
|
||||||
|
|
||||||
val expand_caddadr : 'l node -> 'l node option tzresult
|
|
||||||
val expand_set_caddadr : 'l node -> 'l node option tzresult
|
|
||||||
val expand_map_caddadr : 'l node -> 'l node option tzresult
|
|
||||||
val expand_dxiiivp : 'l node -> 'l node option tzresult
|
|
||||||
val expand_pappaiir : 'l node -> 'l node option tzresult
|
|
||||||
val expand_duuuuup : 'l node -> 'l node option tzresult
|
|
||||||
val expand_compare : 'l node -> 'l node option tzresult
|
|
||||||
val expand_asserts : 'l node -> 'l node option tzresult
|
|
||||||
val expand_unpappaiir : 'l node -> 'l node option tzresult
|
|
||||||
val expand_if_some : 'l node -> 'l node option tzresult
|
|
||||||
val expand_if_right : 'l node -> 'l node option tzresult
|
|
||||||
|
|
||||||
val unexpand : 'l node -> 'l node
|
|
||||||
val unexpand_rec : 'l node -> 'l node
|
|
||||||
|
|
||||||
val unexpand_caddadr : 'l node -> 'l node option
|
|
||||||
val unexpand_set_caddadr : 'l node -> 'l node option
|
|
||||||
val unexpand_map_caddadr : 'l node -> 'l node option
|
|
||||||
val unexpand_dxiiivp : 'l node -> 'l node option
|
|
||||||
val unexpand_pappaiir : 'l node -> 'l node option
|
|
||||||
val unexpand_duuuuup : 'l node -> 'l node option
|
|
||||||
val unexpand_compare : 'l node -> 'l node option
|
|
||||||
val unexpand_asserts : 'l node -> 'l node option
|
|
||||||
val unexpand_unpappaiir : 'l node -> 'l node option
|
|
||||||
val unexpand_if_some : 'l node -> 'l node option
|
|
||||||
val unexpand_if_right : 'l node -> 'l node option
|
|
@ -1,91 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
open Memory_proto_alpha
|
|
||||||
open Tezos_micheline
|
|
||||||
open Micheline_parser
|
|
||||||
open Micheline
|
|
||||||
|
|
||||||
type parsed =
|
|
||||||
{ source : string ;
|
|
||||||
unexpanded : string canonical ;
|
|
||||||
expanded : Michelson_v1_primitives.prim canonical ;
|
|
||||||
expansion_table : (int * (Micheline_parser.location * int list)) list ;
|
|
||||||
unexpansion_table : (int * int) list }
|
|
||||||
|
|
||||||
(* Unexpanded toplevel expression should be a sequence *)
|
|
||||||
let expand_all source ast errors =
|
|
||||||
let unexpanded, loc_table =
|
|
||||||
extract_locations ast in
|
|
||||||
let expanded, expansion_errors =
|
|
||||||
Michelson_v1_macros.expand_rec (root unexpanded) in
|
|
||||||
let expanded, unexpansion_table =
|
|
||||||
extract_locations expanded in
|
|
||||||
let expansion_table =
|
|
||||||
let sorted =
|
|
||||||
List.sort (fun (_, a) (_, b) -> compare a b) unexpansion_table in
|
|
||||||
let grouped =
|
|
||||||
let rec group = function
|
|
||||||
| acc, [] -> acc
|
|
||||||
| [], (u, e) :: r ->
|
|
||||||
group ([ (e, [ u ]) ], r)
|
|
||||||
| ((pe, us) :: racc as acc), (u, e) :: r ->
|
|
||||||
if e = pe then
|
|
||||||
group (((e, u :: us) :: racc), r)
|
|
||||||
else
|
|
||||||
group (((e, [ u ]) :: acc), r) in
|
|
||||||
group ([], sorted) in
|
|
||||||
List.map2
|
|
||||||
(fun (l, ploc) (l', elocs) ->
|
|
||||||
assert (l = l') ;
|
|
||||||
(l, (ploc, elocs)))
|
|
||||||
(List.sort compare loc_table)
|
|
||||||
(List.sort compare grouped) in
|
|
||||||
match Alpha_environment.wrap_error (Michelson_v1_primitives.prims_of_strings expanded) with
|
|
||||||
| Ok expanded ->
|
|
||||||
{ source ; unexpanded ; expanded ;
|
|
||||||
expansion_table ; unexpansion_table },
|
|
||||||
errors @ expansion_errors
|
|
||||||
| Error errs ->
|
|
||||||
{ source ; unexpanded ;
|
|
||||||
expanded = Micheline.strip_locations (Seq ((), [])) ;
|
|
||||||
expansion_table ; unexpansion_table },
|
|
||||||
errors @ expansion_errors @ errs
|
|
||||||
|
|
||||||
let parse_toplevel ?check source =
|
|
||||||
let tokens, lexing_errors = Micheline_parser.tokenize source in
|
|
||||||
let asts, parsing_errors = Micheline_parser.parse_toplevel ?check tokens in
|
|
||||||
let ast =
|
|
||||||
let start = min_point asts and stop = max_point asts in
|
|
||||||
Seq ({ start ; stop }, asts) in
|
|
||||||
expand_all source ast (lexing_errors @ parsing_errors)
|
|
||||||
|
|
||||||
let parse_expression ?check source =
|
|
||||||
let tokens, lexing_errors = Micheline_parser.tokenize source in
|
|
||||||
let ast, parsing_errors = Micheline_parser.parse_expression ?check tokens in
|
|
||||||
expand_all source ast (lexing_errors @ parsing_errors)
|
|
||||||
|
|
||||||
let expand_all ~source ~original =
|
|
||||||
expand_all source original []
|
|
@ -1,51 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
open Memory_proto_alpha
|
|
||||||
open Alpha_context
|
|
||||||
|
|
||||||
open Tezos_micheline
|
|
||||||
|
|
||||||
(** The result of parsing and expanding a Michelson V1 script or data. *)
|
|
||||||
type parsed =
|
|
||||||
{
|
|
||||||
source : string ;
|
|
||||||
(** The original source code. *)
|
|
||||||
unexpanded : string Micheline.canonical ;
|
|
||||||
(** Original expression with macros. *)
|
|
||||||
expanded : Script.expr ;
|
|
||||||
(** Expression with macros fully expanded. *)
|
|
||||||
expansion_table :
|
|
||||||
(int * (Micheline_parser.location * int list)) list ;
|
|
||||||
(** Associates unexpanded nodes to their parsing locations and
|
|
||||||
the nodes expanded from it in the expanded expression. *)
|
|
||||||
unexpansion_table : (int * int) list ;
|
|
||||||
(** Associates an expanded node to its source in the unexpanded
|
|
||||||
expression. *)
|
|
||||||
}
|
|
||||||
|
|
||||||
val parse_toplevel : ?check:bool -> string -> parsed Micheline_parser.parsing_result
|
|
||||||
val parse_expression : ?check:bool -> string -> parsed Micheline_parser.parsing_result
|
|
||||||
val expand_all : source:string -> original:Micheline_parser.node -> parsed Micheline_parser.parsing_result
|
|
@ -1,138 +0,0 @@
|
|||||||
type t = <
|
|
||||||
byte : Lexing.position;
|
|
||||||
point_num : int;
|
|
||||||
point_bol : int;
|
|
||||||
file : string;
|
|
||||||
line : int;
|
|
||||||
|
|
||||||
set_file : string -> t;
|
|
||||||
set_line : int -> t;
|
|
||||||
set_offset : int -> t;
|
|
||||||
set : file:string -> line:int -> offset:int -> t;
|
|
||||||
new_line : string -> t;
|
|
||||||
add_nl : t;
|
|
||||||
|
|
||||||
shift_bytes : int -> t;
|
|
||||||
shift_one_uchar : int -> t;
|
|
||||||
|
|
||||||
offset : [`Byte | `Point] -> int;
|
|
||||||
column : [`Byte | `Point] -> int;
|
|
||||||
|
|
||||||
line_offset : [`Byte | `Point] -> int;
|
|
||||||
byte_offset : int;
|
|
||||||
|
|
||||||
is_ghost : bool;
|
|
||||||
|
|
||||||
to_string : ?offsets:bool -> [`Byte | `Point] -> string;
|
|
||||||
compact : ?offsets:bool -> [`Byte | `Point] -> string;
|
|
||||||
anonymous : ?offsets:bool -> [`Byte | `Point] -> string
|
|
||||||
>
|
|
||||||
|
|
||||||
type pos = t
|
|
||||||
|
|
||||||
(* Constructors *)
|
|
||||||
|
|
||||||
let sprintf = Printf.sprintf
|
|
||||||
|
|
||||||
let make ~byte ~point_num ~point_bol =
|
|
||||||
let () = assert (point_num >= point_bol) in
|
|
||||||
object (self)
|
|
||||||
val byte = byte
|
|
||||||
method byte = byte
|
|
||||||
|
|
||||||
val point_num = point_num
|
|
||||||
method point_num = point_num
|
|
||||||
|
|
||||||
val point_bol = point_bol
|
|
||||||
method point_bol = point_bol
|
|
||||||
|
|
||||||
method set_file file =
|
|
||||||
{< byte = Lexing.{byte with pos_fname = file} >}
|
|
||||||
|
|
||||||
method set_line line =
|
|
||||||
{< byte = Lexing.{byte with pos_lnum = line} >}
|
|
||||||
|
|
||||||
method set_offset offset =
|
|
||||||
{< byte = Lexing.{byte with pos_cnum = byte.pos_bol + offset} >}
|
|
||||||
|
|
||||||
method set ~file ~line ~offset =
|
|
||||||
let pos = self#set_file file in
|
|
||||||
let pos = pos#set_line line in
|
|
||||||
let pos = pos#set_offset offset
|
|
||||||
in pos
|
|
||||||
|
|
||||||
(* The string must not contain '\n'. See [new_line]. *)
|
|
||||||
|
|
||||||
method shift_bytes len =
|
|
||||||
{< byte = Lexing.{byte with pos_cnum = byte.pos_cnum + len};
|
|
||||||
point_num = point_num + len >}
|
|
||||||
|
|
||||||
method shift_one_uchar len =
|
|
||||||
{< byte = Lexing.{byte with pos_cnum = byte.pos_cnum + len};
|
|
||||||
point_num = point_num + 1 >}
|
|
||||||
|
|
||||||
method add_nl =
|
|
||||||
{< byte = Lexing.{byte with
|
|
||||||
pos_lnum = byte.pos_lnum + 1;
|
|
||||||
pos_bol = byte.pos_cnum};
|
|
||||||
point_bol = point_num >}
|
|
||||||
|
|
||||||
method new_line string =
|
|
||||||
let len = String.length string
|
|
||||||
in (self#shift_bytes len)#add_nl
|
|
||||||
|
|
||||||
method is_ghost = byte = Lexing.dummy_pos
|
|
||||||
|
|
||||||
method file = byte.Lexing.pos_fname
|
|
||||||
|
|
||||||
method line = byte.Lexing.pos_lnum
|
|
||||||
|
|
||||||
method offset = function
|
|
||||||
`Byte -> Lexing.(byte.pos_cnum - byte.pos_bol)
|
|
||||||
| `Point -> point_num - point_bol
|
|
||||||
|
|
||||||
method column mode = 1 + self#offset mode
|
|
||||||
|
|
||||||
method line_offset = function
|
|
||||||
`Byte -> byte.Lexing.pos_bol
|
|
||||||
| `Point -> point_bol
|
|
||||||
|
|
||||||
method byte_offset = byte.Lexing.pos_cnum
|
|
||||||
|
|
||||||
method to_string ?(offsets=true) mode =
|
|
||||||
let offset = self#offset mode in
|
|
||||||
let horizontal, value =
|
|
||||||
if offsets then "character", offset else "column", offset + 1
|
|
||||||
in sprintf "File \"%s\", line %i, %s %i"
|
|
||||||
self#file self#line horizontal value
|
|
||||||
|
|
||||||
method compact ?(offsets=true) mode =
|
|
||||||
if self#is_ghost then "ghost"
|
|
||||||
else
|
|
||||||
let offset = self#offset mode in
|
|
||||||
sprintf "%s:%i:%i"
|
|
||||||
self#file self#line (if offsets then offset else offset + 1)
|
|
||||||
|
|
||||||
method anonymous ?(offsets=true) mode =
|
|
||||||
if self#is_ghost then "ghost"
|
|
||||||
else sprintf "%i:%i" self#line
|
|
||||||
(if offsets then self#offset mode else self#column mode)
|
|
||||||
end
|
|
||||||
|
|
||||||
let ghost = make ~byte:Lexing.dummy_pos ~point_num:(-1) ~point_bol:(-1)
|
|
||||||
|
|
||||||
let min =
|
|
||||||
let byte = Lexing.{
|
|
||||||
pos_fname = "";
|
|
||||||
pos_lnum = 1;
|
|
||||||
pos_bol = 0;
|
|
||||||
pos_cnum = 0}
|
|
||||||
in make ~byte ~point_num:0 ~point_bol:0
|
|
||||||
|
|
||||||
(* Comparisons *)
|
|
||||||
|
|
||||||
let equal pos1 pos2 =
|
|
||||||
pos1#file = pos2#file && pos1#byte_offset = pos2#byte_offset
|
|
||||||
|
|
||||||
let lt pos1 pos2 =
|
|
||||||
pos1#file = pos2#file && pos1#byte_offset < pos2#byte_offset
|
|
@ -1,107 +0,0 @@
|
|||||||
(* Positions in a file
|
|
||||||
|
|
||||||
A position in a file denotes a single unit belonging to it, for
|
|
||||||
example, in an ASCII text file, it is a particular character within
|
|
||||||
that file (the unit is the byte in this instance, since in ASCII
|
|
||||||
one character is encoded with one byte).
|
|
||||||
|
|
||||||
Units can be either bytes (as ASCII characters) or, more
|
|
||||||
generally, unicode points.
|
|
||||||
|
|
||||||
The type for positions is the object type [t].
|
|
||||||
|
|
||||||
We use here lexing positions to denote byte-oriented positions
|
|
||||||
(field [byte]), and we manage code points by means of the fields
|
|
||||||
[point_num] and [point_bol]. These two fields have a meaning
|
|
||||||
similar to the fields [pos_cnum] and [pos_bol], respectively, from
|
|
||||||
the standard module [Lexing]. That is to say, [point_num] holds the
|
|
||||||
number of code points since the beginning of the file, and
|
|
||||||
[point_bol] the number of code points since the beginning of the
|
|
||||||
current line.
|
|
||||||
|
|
||||||
The name of the file is given by the field [file], and the line
|
|
||||||
number by the field [line].
|
|
||||||
*)
|
|
||||||
|
|
||||||
type t = <
|
|
||||||
(* Payload *)
|
|
||||||
|
|
||||||
byte : Lexing.position;
|
|
||||||
point_num : int;
|
|
||||||
point_bol : int;
|
|
||||||
file : string;
|
|
||||||
line : int;
|
|
||||||
|
|
||||||
(* Setters *)
|
|
||||||
|
|
||||||
set_file : string -> t;
|
|
||||||
set_line : int -> t;
|
|
||||||
set_offset : int -> t;
|
|
||||||
set : file:string -> line:int -> offset:int -> t;
|
|
||||||
|
|
||||||
(* The call [pos#new_line s], where the string [s] is either "\n" or
|
|
||||||
"\c\r", updates the position [pos] with a new line. *)
|
|
||||||
|
|
||||||
new_line : string -> t;
|
|
||||||
add_nl : t;
|
|
||||||
|
|
||||||
(* The call [pos#shift_bytes n] evaluates in a position that is the
|
|
||||||
translation of position [pos] of [n] bytes forward in the
|
|
||||||
file. The call [pos#shift_one_uchar n] is similar, except that it
|
|
||||||
assumes that [n] is the number of bytes making up one unicode
|
|
||||||
point. *)
|
|
||||||
|
|
||||||
shift_bytes : int -> t;
|
|
||||||
shift_one_uchar : int -> t;
|
|
||||||
|
|
||||||
(* Getters *)
|
|
||||||
|
|
||||||
(* The call [pos#offset `Byte] provides the horizontal offset of the
|
|
||||||
position [pos] in bytes. (An offset is the number of units, like
|
|
||||||
bytes, since the beginning of the current line.) The call
|
|
||||||
[pos#offset `Point] is the offset counted in number of unicode
|
|
||||||
points.
|
|
||||||
|
|
||||||
The calls to the method [column] are similar to those to
|
|
||||||
[offset], except that they give the curren column number.
|
|
||||||
|
|
||||||
The call [pos#line_offset `Byte] is the offset of the line of
|
|
||||||
position [pos], counted in bytes. Dually, [pos#line_offset
|
|
||||||
`Point] counts the same offset in code points.
|
|
||||||
|
|
||||||
The call [pos#byte_offset] is the offset of the position [pos]
|
|
||||||
since the begininng of the file, counted in bytes.
|
|
||||||
*)
|
|
||||||
|
|
||||||
offset : [`Byte | `Point] -> int;
|
|
||||||
column : [`Byte | `Point] -> int;
|
|
||||||
|
|
||||||
line_offset : [`Byte | `Point] -> int;
|
|
||||||
byte_offset : int;
|
|
||||||
|
|
||||||
(* Predicates *)
|
|
||||||
|
|
||||||
is_ghost : bool;
|
|
||||||
|
|
||||||
(* Conversions to [string] *)
|
|
||||||
|
|
||||||
to_string : ?offsets:bool -> [`Byte | `Point] -> string;
|
|
||||||
compact : ?offsets:bool -> [`Byte | `Point] -> string;
|
|
||||||
anonymous : ?offsets:bool -> [`Byte | `Point] -> string
|
|
||||||
>
|
|
||||||
|
|
||||||
type pos = t
|
|
||||||
|
|
||||||
(* Constructors *)
|
|
||||||
|
|
||||||
val make : byte:Lexing.position -> point_num:int -> point_bol:int -> t
|
|
||||||
|
|
||||||
(* Special positions *)
|
|
||||||
|
|
||||||
val ghost : t (* Same as [Lexing.dummy_pos] *)
|
|
||||||
val min : t (* Lexing convention: line 1, offsets to 0 and file to "". *)
|
|
||||||
|
|
||||||
(* Comparisons *)
|
|
||||||
|
|
||||||
val equal : t -> t -> bool
|
|
||||||
val lt : t -> t -> bool
|
|
5
src/lib_utils/ppx_let_generalized/.gitignore
vendored
5
src/lib_utils/ppx_let_generalized/.gitignore
vendored
@ -1,5 +0,0 @@
|
|||||||
_build
|
|
||||||
*.install
|
|
||||||
*.merlin
|
|
||||||
_opam
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
|||||||
## git version
|
|
||||||
|
|
||||||
- Support for `%map.A.B.C` syntax to use values from a specific module, rather
|
|
||||||
than the one in scope.
|
|
||||||
|
|
||||||
## v0.11
|
|
||||||
|
|
||||||
- Depend on ppxlib instead of (now deprecated) ppx\_core and ppx\_driver.
|
|
||||||
|
|
||||||
## 113.43.00
|
|
||||||
|
|
||||||
- Dropped `Open_in_body` support from ppx\_let, since it was only ever used
|
|
||||||
in confusing chains of `Let_syntax` modules that introduced other
|
|
||||||
`Let_syntax` modules in the "body" (e.g. for defining Commands whose
|
|
||||||
bodies use Async). In this case it was decided that the better
|
|
||||||
practice is to be explicit with `open ___.Let_syntax` at the different
|
|
||||||
transition points, even though this is more verbose.
|
|
@ -1,67 +0,0 @@
|
|||||||
This repository contains open source software that is developed and
|
|
||||||
maintained by [Jane Street][js].
|
|
||||||
|
|
||||||
Contributions to this project are welcome and should be submitted via
|
|
||||||
GitHub pull requests.
|
|
||||||
|
|
||||||
Signing contributions
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
We require that you sign your contributions. Your signature certifies
|
|
||||||
that you wrote the patch or otherwise have the right to pass it on as
|
|
||||||
an open-source patch. The rules are pretty simple: if you can certify
|
|
||||||
the below (from [developercertificate.org][dco]):
|
|
||||||
|
|
||||||
```
|
|
||||||
Developer Certificate of Origin
|
|
||||||
Version 1.1
|
|
||||||
|
|
||||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
|
||||||
1 Letterman Drive
|
|
||||||
Suite D4700
|
|
||||||
San Francisco, CA, 94129
|
|
||||||
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies of this
|
|
||||||
license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
Developer's Certificate of Origin 1.1
|
|
||||||
|
|
||||||
By making a contribution to this project, I certify that:
|
|
||||||
|
|
||||||
(a) The contribution was created in whole or in part by me and I
|
|
||||||
have the right to submit it under the open source license
|
|
||||||
indicated in the file; or
|
|
||||||
|
|
||||||
(b) The contribution is based upon previous work that, to the best
|
|
||||||
of my knowledge, is covered under an appropriate open source
|
|
||||||
license and I have the right under that license to submit that
|
|
||||||
work with modifications, whether created in whole or in part
|
|
||||||
by me, under the same open source license (unless I am
|
|
||||||
permitted to submit under a different license), as indicated
|
|
||||||
in the file; or
|
|
||||||
|
|
||||||
(c) The contribution was provided directly to me by some other
|
|
||||||
person who certified (a), (b) or (c) and I have not modified
|
|
||||||
it.
|
|
||||||
|
|
||||||
(d) I understand and agree that this project and the contribution
|
|
||||||
are public and that a record of the contribution (including all
|
|
||||||
personal information I submit with it, including my sign-off) is
|
|
||||||
maintained indefinitely and may be redistributed consistent with
|
|
||||||
this project or the open source license(s) involved.
|
|
||||||
```
|
|
||||||
|
|
||||||
Then you just add a line to every git commit message:
|
|
||||||
|
|
||||||
```
|
|
||||||
Signed-off-by: Joe Smith <joe.smith@email.com>
|
|
||||||
```
|
|
||||||
|
|
||||||
Use your real name (sorry, no pseudonyms or anonymous contributions.)
|
|
||||||
|
|
||||||
If you set your `user.name` and `user.email` git configs, you can sign
|
|
||||||
your commit automatically with git commit -s.
|
|
||||||
|
|
||||||
[dco]: http://developercertificate.org/
|
|
||||||
[js]: https://opensource.janestreet.com/
|
|
@ -1,4 +0,0 @@
|
|||||||
This folder contains a generalization of ppx_let from Jane Street.
|
|
||||||
See git log this_folder for the development history.
|
|
||||||
|
|
||||||
https://github.com/janestreet/ppx_let.git
|
|
@ -1,21 +0,0 @@
|
|||||||
The MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2015--2019 Jane Street Group, LLC <opensource@janestreet.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.
|
|
@ -1,17 +0,0 @@
|
|||||||
INSTALL_ARGS := $(if $(PREFIX),--prefix $(PREFIX),)
|
|
||||||
|
|
||||||
default:
|
|
||||||
dune build
|
|
||||||
|
|
||||||
install:
|
|
||||||
dune install $(INSTALL_ARGS)
|
|
||||||
|
|
||||||
uninstall:
|
|
||||||
dune uninstall $(INSTALL_ARGS)
|
|
||||||
|
|
||||||
reinstall: uninstall install
|
|
||||||
|
|
||||||
clean:
|
|
||||||
dune clean
|
|
||||||
|
|
||||||
.PHONY: default install uninstall reinstall clean
|
|
@ -1,169 +0,0 @@
|
|||||||
ppx_let
|
|
||||||
=======
|
|
||||||
|
|
||||||
A ppx rewriter for monadic and applicative let bindings, match expressions, and
|
|
||||||
if expressions.
|
|
||||||
|
|
||||||
Overview
|
|
||||||
--------
|
|
||||||
|
|
||||||
The aim of this rewriter is to make monadic and applicative code look nicer by
|
|
||||||
writing custom binders the same way that we normally bind variables. In OCaml,
|
|
||||||
the common way to bind the result of a computation to a variable is:
|
|
||||||
|
|
||||||
```ocaml
|
|
||||||
let VAR = EXPR in BODY
|
|
||||||
```
|
|
||||||
|
|
||||||
ppx\_let simply adds two new binders: `let%bind` and `let%map`. These are
|
|
||||||
rewritten into calls to the `bind` and `map` functions respectively. These
|
|
||||||
functions are expected to have
|
|
||||||
|
|
||||||
```ocaml
|
|
||||||
val map : 'a t -> f:('a -> 'b) -> 'b t
|
|
||||||
val bind : 'a t -> f:('a -> 'b t) -> 'b t
|
|
||||||
```
|
|
||||||
|
|
||||||
for some type `t`, as one might expect.
|
|
||||||
|
|
||||||
These functions are to be provided by the user, and are generally expected to be
|
|
||||||
part of the signatures of monads and applicatives modules. This is the case for
|
|
||||||
all monads and applicatives defined by the Jane Street's Core suite of
|
|
||||||
libraries. (see the section below on getting the right names into scope).
|
|
||||||
|
|
||||||
### Parallel bindings
|
|
||||||
|
|
||||||
ppx\_let understands parallel bindings as well. i.e.:
|
|
||||||
|
|
||||||
```ocaml
|
|
||||||
let%bind VAR1 = EXPR1 and VAR2 = EXPR2 and VAR3 = EXPR3 in BODY
|
|
||||||
```
|
|
||||||
|
|
||||||
The `and` keyword is seen as a binding combination operator. To do so it expects
|
|
||||||
the presence of a `both` function, that lifts the OCaml pair operation to the
|
|
||||||
type `t` in question:
|
|
||||||
|
|
||||||
```ocaml
|
|
||||||
val both : 'a t -> 'b t -> ('a * 'b) t
|
|
||||||
```
|
|
||||||
|
|
||||||
### Match statements
|
|
||||||
|
|
||||||
We found that this form was quite useful for match statements as well. So for
|
|
||||||
convenience ppx\_let also accepts `%bind` and `%map` on the `match` keyword.
|
|
||||||
Morally `match%bind expr with cases` is seen as `let%bind x = expr in match x
|
|
||||||
with cases`.
|
|
||||||
|
|
||||||
### If statements
|
|
||||||
|
|
||||||
As a further convenience, ppx\_let accepts `%bind` and `%map` on the `if`
|
|
||||||
keyword. The expression `if%bind expr1 then expr2 else expr3` is morally
|
|
||||||
equivalent to `let%bind p = expr1 in if p then expr2 else expr3`.
|
|
||||||
|
|
||||||
Syntactic forms and actual rewriting
|
|
||||||
------------------------------------
|
|
||||||
|
|
||||||
`ppx_let` adds six syntactic forms
|
|
||||||
|
|
||||||
```ocaml
|
|
||||||
let%bind P = M in E
|
|
||||||
|
|
||||||
let%map P = M in E
|
|
||||||
|
|
||||||
match%bind M with P1 -> E1 | P2 -> E2 | ...
|
|
||||||
|
|
||||||
match%map M with P1 -> E1 | P2 -> E2 | ...
|
|
||||||
|
|
||||||
if%bind M then E1 else E2
|
|
||||||
|
|
||||||
if%map M then E1 else E2
|
|
||||||
```
|
|
||||||
|
|
||||||
that expand into
|
|
||||||
|
|
||||||
```ocaml
|
|
||||||
bind M ~f:(fun P -> E)
|
|
||||||
|
|
||||||
map M ~f:(fun P -> E)
|
|
||||||
|
|
||||||
bind M ~f:(function P1 -> E1 | P2 -> E2 | ...)
|
|
||||||
|
|
||||||
map M ~f:(function P1 -> E1 | P2 -> E2 | ...)
|
|
||||||
|
|
||||||
bind M ~f:(function true -> E1 | false -> E2)
|
|
||||||
|
|
||||||
map M ~f:(function true -> E1 | false -> E2)
|
|
||||||
```
|
|
||||||
|
|
||||||
respectively.
|
|
||||||
|
|
||||||
As with `let`, `let%bind` and `let%map` also support multiple *parallel*
|
|
||||||
bindings via the `and` keyword:
|
|
||||||
|
|
||||||
```ocaml
|
|
||||||
let%bind P1 = M1 and P2 = M2 and P3 = M3 and P4 = M4 in E
|
|
||||||
|
|
||||||
let%map P1 = M1 and P2 = M2 and P3 = M3 and P4 = M4 in E
|
|
||||||
```
|
|
||||||
|
|
||||||
that expand into
|
|
||||||
|
|
||||||
```ocaml
|
|
||||||
let x1 = M1 and x2 = M2 and x3 = M3 and x4 = M4 in
|
|
||||||
bind
|
|
||||||
(both x1 (both x2 (both x3 x4)))
|
|
||||||
~f:(fun (P1, (P2, (P3, P4))) -> E)
|
|
||||||
|
|
||||||
let x1 = M1 and x2 = M2 and x3 = M3 and x4 = M4 in
|
|
||||||
map
|
|
||||||
(both x1 (both x2 (both x3 x4)))
|
|
||||||
~f:(fun (P1, (P2, (P3, P4))) -> E)
|
|
||||||
```
|
|
||||||
|
|
||||||
respectively. (Instead of `x1`, `x2`, ... ppx\_let uses variable names that are
|
|
||||||
unlikely to clash with other names)
|
|
||||||
|
|
||||||
As with `let`, names introduced by left-hand sides of the let bindings are not
|
|
||||||
available in subsequent right-hand sides of the same sequence.
|
|
||||||
|
|
||||||
Getting the right names in scope
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
The description of how the `%bind` and `%map` syntax extensions expand left out
|
|
||||||
the fact that the names `bind`, `map`, `both`, and `return` are not used
|
|
||||||
directly., but rather qualified by `Let_syntax`. For example, we use
|
|
||||||
`Let_syntax.bind` rather than merely `bind`.
|
|
||||||
|
|
||||||
This means one just needs to get a properly loaded `Let_syntax` module
|
|
||||||
in scope to use `%bind` and `%map`.
|
|
||||||
|
|
||||||
Alternatively, the extension can use values from a `Let_syntax` module
|
|
||||||
other than the one in scope. If you write `%map.A.B.C` instead of
|
|
||||||
`%map`, the expansion will use `A.B.C.Let_syntax.map` instead of
|
|
||||||
`Let_syntax.map` (and similarly for all extension points).
|
|
||||||
|
|
||||||
For monads, `Core.Monad.Make` produces a submodule `Let_syntax` of the
|
|
||||||
appropriate form.
|
|
||||||
|
|
||||||
For applicatives, the convention for these modules is to have a submodule
|
|
||||||
`Let_syntax` of the form:
|
|
||||||
|
|
||||||
```ocaml
|
|
||||||
module Let_syntax : sig
|
|
||||||
val return : 'a -> 'a t
|
|
||||||
val map : 'a t -> f:('a -> 'b) -> 'b t
|
|
||||||
val both : 'a t -> 'b t -> ('a * 'b) t
|
|
||||||
module Open_on_rhs : << some signature >>
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
The `Open_on_rhs` submodule is used by variants of `%map` and `%bind` called
|
|
||||||
`%map_open` and `%bind_open`. It is locally opened on the right hand sides of
|
|
||||||
the rewritten let bindings in `%map_open` and `%bind_open` expressions. For
|
|
||||||
`match%map_open` and `match%bind_open` expressions, `Open_on_rhs` is opened for
|
|
||||||
the expression being matched on.
|
|
||||||
|
|
||||||
`Open_on_rhs` is useful when programming with applicatives, which operate in a
|
|
||||||
staged manner where the operators used to construct the applicatives are
|
|
||||||
distinct from the operators used to manipulate the values those applicatives
|
|
||||||
produce. For monads, `Open_on_rhs` contains `return`.
|
|
@ -1,2 +0,0 @@
|
|||||||
(library (name ppx_let_expander) (public_name tezos-utils.ppx_let_generalized.expander)
|
|
||||||
(libraries base ppxlib) (preprocess no_preprocessing))
|
|
@ -1,155 +0,0 @@
|
|||||||
open Base
|
|
||||||
open Ppxlib
|
|
||||||
open Ast_builder.Default
|
|
||||||
|
|
||||||
module List = struct
|
|
||||||
include List
|
|
||||||
|
|
||||||
let reduce_exn l ~f =
|
|
||||||
match l with
|
|
||||||
| [] -> invalid_arg "List.reduce_exn"
|
|
||||||
| hd :: tl -> fold_left tl ~init:hd ~f
|
|
||||||
;;
|
|
||||||
end
|
|
||||||
|
|
||||||
let let_syntax ~modul : Longident.t =
|
|
||||||
match modul with
|
|
||||||
| None -> Lident "Let_syntax"
|
|
||||||
| Some id -> Ldot (id.txt, "Let_syntax")
|
|
||||||
;;
|
|
||||||
|
|
||||||
let open_on_rhs ~loc ~modul ~extension_name_s =
|
|
||||||
Located.mk ~loc (Longident.Ldot (let_syntax ~modul, "Open_on_rhs_" ^ extension_name_s))
|
|
||||||
;;
|
|
||||||
|
|
||||||
let eoperator ~loc ~modul func =
|
|
||||||
let lid : Longident.t = Ldot (let_syntax ~modul, func) in
|
|
||||||
pexp_ident ~loc (Located.mk ~loc lid)
|
|
||||||
;;
|
|
||||||
|
|
||||||
let expand_with_tmp_vars ~loc bindings expr ~f =
|
|
||||||
match bindings with
|
|
||||||
| [ _ ] -> f ~loc bindings expr
|
|
||||||
| _ ->
|
|
||||||
let tmp_vars =
|
|
||||||
List.map bindings ~f:(fun _ -> gen_symbol ~prefix:"__let_syntax" ())
|
|
||||||
in
|
|
||||||
let s_rhs_tmp_var (* s/rhs/tmp_var *) =
|
|
||||||
List.map2_exn bindings tmp_vars ~f:(fun vb var ->
|
|
||||||
{ vb with pvb_expr = evar ~loc:vb.pvb_expr.pexp_loc var })
|
|
||||||
in
|
|
||||||
let s_lhs_tmp_var (* s/lhs/tmp_var *) =
|
|
||||||
List.map2_exn bindings tmp_vars ~f:(fun vb var ->
|
|
||||||
{ vb with pvb_pat = pvar ~loc:vb.pvb_pat.ppat_loc var })
|
|
||||||
in
|
|
||||||
pexp_let ~loc Nonrecursive s_lhs_tmp_var (f ~loc s_rhs_tmp_var expr)
|
|
||||||
;;
|
|
||||||
|
|
||||||
let bind_apply ~loc ~modul extension_name_s ~arg ~fn =
|
|
||||||
pexp_apply
|
|
||||||
~loc
|
|
||||||
(eoperator ~loc ~modul extension_name_s)
|
|
||||||
[ Nolabel, arg; Labelled "f", fn ]
|
|
||||||
;;
|
|
||||||
|
|
||||||
(* Change by Georges: Always open for all extension names. *)
|
|
||||||
let maybe_open ~to_open:module_to_open expr =
|
|
||||||
let loc = expr.pexp_loc in
|
|
||||||
pexp_open ~loc Override (module_to_open ~loc) expr
|
|
||||||
;;
|
|
||||||
|
|
||||||
let expand_let extension_name_s ~loc ~modul bindings body =
|
|
||||||
if List.is_empty bindings
|
|
||||||
then invalid_arg "expand_let: list of bindings must be non-empty";
|
|
||||||
(* Build expression [both E1 (both E2 (both ...))] *)
|
|
||||||
let nested_boths =
|
|
||||||
let rev_boths = List.rev_map bindings ~f:(fun vb -> vb.pvb_expr) in
|
|
||||||
List.reduce_exn rev_boths ~f:(fun acc e ->
|
|
||||||
let loc = e.pexp_loc in
|
|
||||||
eapply ~loc (eoperator ~loc ~modul "both") [ e; acc ])
|
|
||||||
in
|
|
||||||
(* Build pattern [(P1, (P2, ...))] *)
|
|
||||||
let nested_patterns =
|
|
||||||
let rev_patts = List.rev_map bindings ~f:(fun vb -> vb.pvb_pat) in
|
|
||||||
List.reduce_exn rev_patts ~f:(fun acc p ->
|
|
||||||
let loc = p.ppat_loc in
|
|
||||||
ppat_tuple ~loc [ p; acc ])
|
|
||||||
in
|
|
||||||
bind_apply
|
|
||||||
~loc
|
|
||||||
~modul
|
|
||||||
extension_name_s
|
|
||||||
~arg:nested_boths
|
|
||||||
~fn:(pexp_fun ~loc Nolabel None nested_patterns body)
|
|
||||||
;;
|
|
||||||
|
|
||||||
let expand_match extension_name_s ~loc ~modul expr cases =
|
|
||||||
bind_apply
|
|
||||||
~loc
|
|
||||||
~modul
|
|
||||||
extension_name_s
|
|
||||||
~arg:(maybe_open ~to_open:(open_on_rhs ~modul ~extension_name_s) expr)
|
|
||||||
~fn:(pexp_function ~loc cases)
|
|
||||||
;;
|
|
||||||
|
|
||||||
let expand_if extension_name ~loc expr then_ else_ =
|
|
||||||
expand_match
|
|
||||||
extension_name
|
|
||||||
~loc
|
|
||||||
expr
|
|
||||||
[ case ~lhs:(pbool ~loc true) ~guard:None ~rhs:then_
|
|
||||||
; case ~lhs:(pbool ~loc false) ~guard:None ~rhs:else_
|
|
||||||
]
|
|
||||||
;;
|
|
||||||
|
|
||||||
let expand ~modul extension_name_s expr =
|
|
||||||
let loc = expr.pexp_loc in
|
|
||||||
let expansion =
|
|
||||||
match expr.pexp_desc with
|
|
||||||
| Pexp_let (Nonrecursive, bindings, expr) ->
|
|
||||||
let bindings =
|
|
||||||
List.map bindings ~f:(fun vb ->
|
|
||||||
let pvb_pat =
|
|
||||||
(* Temporary hack tentatively detecting that the parser
|
|
||||||
has expanded `let x : t = e` into `let x : t = (e : t)`.
|
|
||||||
|
|
||||||
For reference, here is the relevant part of the parser:
|
|
||||||
https://github.com/ocaml/ocaml/blob/4.07/parsing/parser.mly#L1628 *)
|
|
||||||
match vb.pvb_pat.ppat_desc, vb.pvb_expr.pexp_desc with
|
|
||||||
| ( Ppat_constraint (p, { ptyp_desc = Ptyp_poly ([], t1); _ })
|
|
||||||
, Pexp_constraint (_, t2) )
|
|
||||||
when phys_equal t1 t2 -> p
|
|
||||||
| _ -> vb.pvb_pat
|
|
||||||
in
|
|
||||||
{ vb with
|
|
||||||
pvb_pat
|
|
||||||
; pvb_expr =
|
|
||||||
maybe_open ~to_open:(open_on_rhs ~modul ~extension_name_s) vb.pvb_expr
|
|
||||||
})
|
|
||||||
in
|
|
||||||
expand_with_tmp_vars ~loc bindings expr ~f:(expand_let extension_name_s ~modul)
|
|
||||||
| Pexp_let (Recursive, _, _) ->
|
|
||||||
Location.raise_errorf
|
|
||||||
~loc
|
|
||||||
"'let%%%s' may not be recursive"
|
|
||||||
extension_name_s
|
|
||||||
| Pexp_match (expr, cases) -> expand_match extension_name_s ~loc ~modul expr cases
|
|
||||||
| Pexp_ifthenelse (expr, then_, else_) ->
|
|
||||||
let else_ =
|
|
||||||
match else_ with
|
|
||||||
| Some else_ -> else_
|
|
||||||
| None ->
|
|
||||||
Location.raise_errorf
|
|
||||||
~loc
|
|
||||||
"'if%%%s' must include an else branch"
|
|
||||||
extension_name_s
|
|
||||||
in
|
|
||||||
expand_if extension_name_s ~loc ~modul expr then_ else_
|
|
||||||
| _ ->
|
|
||||||
Location.raise_errorf
|
|
||||||
~loc
|
|
||||||
"'%%%s' can only be used with 'let', 'match', and 'if'"
|
|
||||||
extension_name_s
|
|
||||||
in
|
|
||||||
{ expansion with pexp_attributes = expr.pexp_attributes @ expansion.pexp_attributes }
|
|
||||||
;;
|
|
@ -1,3 +0,0 @@
|
|||||||
open Ppxlib
|
|
||||||
|
|
||||||
val expand : modul:longident loc option -> string -> expression -> expression
|
|
@ -1,2 +0,0 @@
|
|||||||
(library (name ppx_let) (public_name tezos-utils.ppx_let_generalized) (kind ppx_rewriter)
|
|
||||||
(libraries ppxlib ppx_let_expander) (preprocess no_preprocessing))
|
|
@ -1,19 +0,0 @@
|
|||||||
open Ppxlib
|
|
||||||
|
|
||||||
let ext extension_name_s =
|
|
||||||
Extension.declare_with_path_arg
|
|
||||||
extension_name_s
|
|
||||||
Extension.Context.expression
|
|
||||||
Ast_pattern.(single_expr_payload __)
|
|
||||||
(fun ~loc:_ ~path:_ ~arg expr ->
|
|
||||||
Ppx_let_expander.expand extension_name_s ~modul:arg expr)
|
|
||||||
;;
|
|
||||||
|
|
||||||
let () =
|
|
||||||
Driver.register_transformation
|
|
||||||
"let"
|
|
||||||
~extensions:(List.map ext [
|
|
||||||
"bind";
|
|
||||||
"xxx";
|
|
||||||
])
|
|
||||||
;;
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1 +0,0 @@
|
|||||||
(executables (names test) (preprocess (pps ppx_let_generalized)))
|
|
@ -1,27 +0,0 @@
|
|||||||
(* -*- tuareg -*- *)
|
|
||||||
|
|
||||||
module Let_syntax = struct
|
|
||||||
type 'a t = T of 'a
|
|
||||||
|
|
||||||
let map (T x) ~f = T (f x)
|
|
||||||
let both (T x) (T y) = T (x, y)
|
|
||||||
|
|
||||||
module Open_on_rhs = struct
|
|
||||||
let return x = T x
|
|
||||||
let f x ~(doc : string) = T (x, doc)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
let _ =
|
|
||||||
[%map_open
|
|
||||||
let x = return 42
|
|
||||||
and y = f 42 in
|
|
||||||
()]
|
|
||||||
;;
|
|
||||||
|
|
||||||
[%%expect
|
|
||||||
{|
|
|
||||||
Line _, characters 12-16:
|
|
||||||
Error: This expression has type doc:string -> (int * string) Let_syntax.t
|
|
||||||
but an expression was expected of type 'a Let_syntax.t
|
|
||||||
|}]
|
|
@ -1,189 +0,0 @@
|
|||||||
module Monad_example = struct
|
|
||||||
module Let_syntax = struct
|
|
||||||
let bind x ~f = f x
|
|
||||||
module Open_on_rhs_bind = struct
|
|
||||||
let return _ = "foo"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
let _mf a =
|
|
||||||
let%bind xyz = return a in
|
|
||||||
(int_of_string xyz + 1)
|
|
||||||
;;
|
|
||||||
end
|
|
||||||
|
|
||||||
(* TODO: re-enable some tests *)
|
|
||||||
|
|
||||||
(*
|
|
||||||
module Monad_example = struct
|
|
||||||
module X : sig
|
|
||||||
type 'a t
|
|
||||||
|
|
||||||
module Let_syntax : sig
|
|
||||||
val return : 'a -> 'a t
|
|
||||||
|
|
||||||
module Let_syntax : sig
|
|
||||||
val return : 'a -> 'a t
|
|
||||||
val bind : 'a t -> f:('a -> 'b t) -> 'b t
|
|
||||||
val map : 'a t -> f:('a -> 'b) -> 'b t
|
|
||||||
val both : 'a t -> 'b t -> ('a * 'b) t
|
|
||||||
|
|
||||||
module Open_on_rhs : sig
|
|
||||||
val return : 'a -> 'a t
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end = struct
|
|
||||||
type 'a t = 'a
|
|
||||||
|
|
||||||
let return x = x
|
|
||||||
let bind x ~f = f x
|
|
||||||
let map x ~f = f x
|
|
||||||
let both x y = x, y
|
|
||||||
|
|
||||||
module Let_syntax = struct
|
|
||||||
let return = return
|
|
||||||
|
|
||||||
module Let_syntax = struct
|
|
||||||
let return = return
|
|
||||||
let bind = bind
|
|
||||||
let map = map
|
|
||||||
let both = both
|
|
||||||
|
|
||||||
module Open_on_rhs = struct
|
|
||||||
let return = return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
open X.Let_syntax
|
|
||||||
|
|
||||||
let _mf a : _ X.t =
|
|
||||||
let%bind_open x = a in
|
|
||||||
return (x + 1)
|
|
||||||
;;
|
|
||||||
|
|
||||||
let _mf' a b c : _ X.t =
|
|
||||||
let%bind_open x = a
|
|
||||||
and y = b
|
|
||||||
and u, v = c in
|
|
||||||
return (x + y + (u * v))
|
|
||||||
;;
|
|
||||||
|
|
||||||
let _mg a : _ X.t =
|
|
||||||
let%map x : int X.t = a in
|
|
||||||
x + 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
let _mg' a b c : _ X.t =
|
|
||||||
let%map x = a
|
|
||||||
and y = b
|
|
||||||
and u, v = c in
|
|
||||||
x + y + (u * v)
|
|
||||||
;;
|
|
||||||
|
|
||||||
let _mh a : _ X.t =
|
|
||||||
match%bind_open a with
|
|
||||||
| 0 -> return true
|
|
||||||
| _ -> return false
|
|
||||||
;;
|
|
||||||
|
|
||||||
let _mi a : _ X.t =
|
|
||||||
match%map a with
|
|
||||||
| 0 -> true
|
|
||||||
| _ -> false
|
|
||||||
;;
|
|
||||||
|
|
||||||
let _mif a : _ X.t = if%bind_open a then return true else return false
|
|
||||||
let _mif' a : _ X.t = if%map a then true else false
|
|
||||||
end
|
|
||||||
|
|
||||||
module Applicative_example = struct
|
|
||||||
module X : sig
|
|
||||||
type 'a t
|
|
||||||
|
|
||||||
module Let_syntax : sig
|
|
||||||
val return : 'a -> 'a t
|
|
||||||
|
|
||||||
module Let_syntax : sig
|
|
||||||
val return : 'a -> 'a t
|
|
||||||
val map : 'a t -> f:('a -> 'b) -> 'b t
|
|
||||||
val both : 'a t -> 'b t -> ('a * 'b) t
|
|
||||||
|
|
||||||
module Open_on_rhs : sig
|
|
||||||
val flag : int t
|
|
||||||
val anon : int t
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end = struct
|
|
||||||
type 'a t = 'a
|
|
||||||
|
|
||||||
let return x = x
|
|
||||||
let map x ~f = f x
|
|
||||||
let both x y = x, y
|
|
||||||
|
|
||||||
module Let_syntax = struct
|
|
||||||
let return = return
|
|
||||||
|
|
||||||
module Let_syntax = struct
|
|
||||||
let return = return
|
|
||||||
let map = map
|
|
||||||
let both = both
|
|
||||||
|
|
||||||
module Open_on_rhs = struct
|
|
||||||
let flag = 66
|
|
||||||
let anon = 77
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
open X.Let_syntax
|
|
||||||
|
|
||||||
(* {[
|
|
||||||
let _af a : _ X.t =
|
|
||||||
let%bind x = a in (* "Error: Unbound value Let_syntax.bind" *)
|
|
||||||
return (x + 1)
|
|
||||||
]} *)
|
|
||||||
|
|
||||||
(* {[
|
|
||||||
let _af' a b c : _ X.t =
|
|
||||||
let%bind x = a and y = b and (u, v) = c in (* "Error: Unbound value Let_syntax.bind" *)
|
|
||||||
return (x + y + (u * v))
|
|
||||||
]} *)
|
|
||||||
|
|
||||||
let _ag a : _ X.t =
|
|
||||||
let%map x = a in
|
|
||||||
x + 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
let _ag' a b c : _ X.t =
|
|
||||||
let%map x = a
|
|
||||||
and y = b
|
|
||||||
and u, v = c in
|
|
||||||
x + y + (u * v)
|
|
||||||
;;
|
|
||||||
|
|
||||||
(* {[
|
|
||||||
let _ah a : _ X.t =
|
|
||||||
match%bind a with (* "Error: Unbound value Let_syntax.bind" *)
|
|
||||||
| 0 -> return true
|
|
||||||
| _ -> return false
|
|
||||||
]} *)
|
|
||||||
|
|
||||||
let _ai a : _ X.t =
|
|
||||||
match%map a with
|
|
||||||
| 0 -> true
|
|
||||||
| _ -> false
|
|
||||||
;;
|
|
||||||
end
|
|
||||||
|
|
||||||
module Example_without_open = struct
|
|
||||||
let _ag a : _ Applicative_example.X.t =
|
|
||||||
let%map.Applicative_example.X.Let_syntax x = a in
|
|
||||||
x + 1
|
|
||||||
;;
|
|
||||||
end
|
|
||||||
*)
|
|
@ -1,128 +0,0 @@
|
|||||||
(* Regions of a file *)
|
|
||||||
|
|
||||||
let sprintf = Printf.sprintf
|
|
||||||
|
|
||||||
type t = <
|
|
||||||
start : Pos.t;
|
|
||||||
stop : Pos.t;
|
|
||||||
|
|
||||||
(* Setters *)
|
|
||||||
|
|
||||||
shift_bytes : int -> t;
|
|
||||||
shift_one_uchar : int -> t;
|
|
||||||
set_file : string -> t;
|
|
||||||
|
|
||||||
(* Getters *)
|
|
||||||
|
|
||||||
file : string;
|
|
||||||
pos : Pos.t * Pos.t;
|
|
||||||
byte_pos : Lexing.position * Lexing.position;
|
|
||||||
|
|
||||||
(* Predicates *)
|
|
||||||
|
|
||||||
is_ghost : bool;
|
|
||||||
|
|
||||||
(* Conversions to [string] *)
|
|
||||||
|
|
||||||
to_string : ?file:bool -> ?offsets:bool -> [`Byte | `Point] -> string;
|
|
||||||
compact : ?file:bool -> ?offsets:bool -> [`Byte | `Point] -> string
|
|
||||||
>
|
|
||||||
|
|
||||||
type region = t
|
|
||||||
|
|
||||||
type 'a reg = {region: t; value: 'a}
|
|
||||||
|
|
||||||
(* Injections *)
|
|
||||||
|
|
||||||
exception Invalid
|
|
||||||
|
|
||||||
let make ~(start: Pos.t) ~(stop: Pos.t) =
|
|
||||||
if start#file <> stop#file || start#byte_offset > stop#byte_offset
|
|
||||||
then raise Invalid
|
|
||||||
else
|
|
||||||
object
|
|
||||||
val start = start
|
|
||||||
method start = start
|
|
||||||
val stop = stop
|
|
||||||
method stop = stop
|
|
||||||
|
|
||||||
method shift_bytes len =
|
|
||||||
let start = start#shift_bytes len
|
|
||||||
and stop = stop#shift_bytes len
|
|
||||||
in {< start = start; stop = stop >}
|
|
||||||
|
|
||||||
method shift_one_uchar len =
|
|
||||||
let start = start#shift_one_uchar len
|
|
||||||
and stop = stop#shift_one_uchar len
|
|
||||||
in {< start = start; stop = stop >}
|
|
||||||
|
|
||||||
method set_file name =
|
|
||||||
let start = start#set_file name
|
|
||||||
and stop = stop#set_file name
|
|
||||||
in {< start = start; stop = stop >}
|
|
||||||
|
|
||||||
(* Getters *)
|
|
||||||
|
|
||||||
method file = start#file
|
|
||||||
method pos = start, stop
|
|
||||||
method byte_pos = start#byte, stop#byte
|
|
||||||
|
|
||||||
(* Predicates *)
|
|
||||||
|
|
||||||
method is_ghost = start#is_ghost && stop#is_ghost
|
|
||||||
|
|
||||||
(* Conversions to strings *)
|
|
||||||
|
|
||||||
method to_string ?(file=true) ?(offsets=true) mode =
|
|
||||||
let horizontal = if offsets then "character" else "column"
|
|
||||||
and start_offset =
|
|
||||||
if offsets then start#offset mode else start#column mode
|
|
||||||
and stop_offset =
|
|
||||||
if offsets then stop#offset mode else stop#column mode in
|
|
||||||
let info =
|
|
||||||
if file
|
|
||||||
then sprintf "in file \"%s\", line %i, %s"
|
|
||||||
(String.escaped start#file) start#line horizontal
|
|
||||||
else sprintf "at line %i, %s" start#line horizontal
|
|
||||||
in if stop#line = start#line
|
|
||||||
then sprintf "%ss %i-%i" info start_offset stop_offset
|
|
||||||
else sprintf "%s %i to line %i, %s %i"
|
|
||||||
info start_offset stop#line horizontal stop_offset
|
|
||||||
|
|
||||||
method compact ?(file=true) ?(offsets=true) mode =
|
|
||||||
let start_str = start#anonymous ~offsets mode
|
|
||||||
and stop_str = stop#anonymous ~offsets mode in
|
|
||||||
if start#file = stop#file then
|
|
||||||
if file then sprintf "%s:%s-%s" start#file start_str stop_str
|
|
||||||
else sprintf "%s-%s" start_str stop_str
|
|
||||||
else sprintf "%s:%s-%s:%s" start#file start_str stop#file stop_str
|
|
||||||
end
|
|
||||||
|
|
||||||
(* Special regions *)
|
|
||||||
|
|
||||||
let ghost = make ~start:Pos.ghost ~stop:Pos.ghost
|
|
||||||
|
|
||||||
let min = make ~start:Pos.min ~stop:Pos.min
|
|
||||||
|
|
||||||
(* Comparisons *)
|
|
||||||
|
|
||||||
let equal r1 r2 =
|
|
||||||
r1#file = r2#file
|
|
||||||
&& Pos.equal r1#start r2#start
|
|
||||||
&& Pos.equal r1#stop r2#stop
|
|
||||||
|
|
||||||
let lt r1 r2 =
|
|
||||||
r1#file = r2#file
|
|
||||||
&& not r1#is_ghost
|
|
||||||
&& not r2#is_ghost
|
|
||||||
&& Pos.lt r1#start r2#start
|
|
||||||
&& Pos.lt r1#stop r2#stop
|
|
||||||
|
|
||||||
let cover r1 r2 =
|
|
||||||
if r1#is_ghost
|
|
||||||
then r2
|
|
||||||
else if r2#is_ghost
|
|
||||||
then r1
|
|
||||||
else if lt r1 r2
|
|
||||||
then make ~start:r1#start ~stop:r2#stop
|
|
||||||
else make ~start:r2#start ~stop:r1#stop
|
|
@ -1,125 +0,0 @@
|
|||||||
(* Regions of a file
|
|
||||||
|
|
||||||
A _region_ is a contiguous series of bytes, for example, in a text
|
|
||||||
file. It is here denoted by the object type [t].
|
|
||||||
|
|
||||||
The start (included) of the region is given by the field [start],
|
|
||||||
which is a _position_, and the end (excluded) is the position given
|
|
||||||
by the field [stop]. The convention of including the start and
|
|
||||||
excluding the end enables to have empty regions if, and only if,
|
|
||||||
[start = stop]. See module [Pos] for the definition of positions.
|
|
||||||
|
|
||||||
The first byte of a file starts at the offset zero (that is,
|
|
||||||
column one), and [start] is always lower than or equal to [stop],
|
|
||||||
and they must refer to the same file.
|
|
||||||
*)
|
|
||||||
|
|
||||||
type t = <
|
|
||||||
start : Pos.t;
|
|
||||||
stop : Pos.t;
|
|
||||||
|
|
||||||
(* Setters *)
|
|
||||||
|
|
||||||
(* The call [region#shift_bytes n] evaluates in a region that is the
|
|
||||||
translation of region [region] of [n] bytes forward in the
|
|
||||||
file. The call [region#shift_one_uchar n] is similar, except that
|
|
||||||
it assumes that [n] is the number of bytes making up one unicode
|
|
||||||
point. The call [region#set_file f] sets the file name to be
|
|
||||||
[f]. *)
|
|
||||||
|
|
||||||
shift_bytes : int -> t;
|
|
||||||
shift_one_uchar : int -> t;
|
|
||||||
set_file : string -> t;
|
|
||||||
|
|
||||||
(* Getters *)
|
|
||||||
|
|
||||||
(* The method [file] returns the file name.
|
|
||||||
The method [pos] returns the values of the fields [start] and [stop].
|
|
||||||
The method [byte_pos] returns the start and end positions of the
|
|
||||||
region at hand _interpreting them as lexing positions_, that is,
|
|
||||||
the unit is the byte. *)
|
|
||||||
|
|
||||||
file : string;
|
|
||||||
pos : Pos.t * Pos.t;
|
|
||||||
byte_pos : Lexing.position * Lexing.position;
|
|
||||||
|
|
||||||
(* Predicates *)
|
|
||||||
|
|
||||||
is_ghost : bool;
|
|
||||||
|
|
||||||
(* Conversions to [string] *)
|
|
||||||
|
|
||||||
(* The call [region#to_string ~file ~offsets mode] evaluates in a
|
|
||||||
string denoting the region [region].
|
|
||||||
|
|
||||||
The name of the file is present if, and only if, [file = true] or
|
|
||||||
[file] is missing.
|
|
||||||
|
|
||||||
The positions in the file are expressed horizontal offsets if
|
|
||||||
[offsets = true] or [offsets] is missing (the default), otherwise
|
|
||||||
as columns.
|
|
||||||
|
|
||||||
If [mode = `Byte], those positions will be assumed to have bytes
|
|
||||||
as their unit, otherwise, if [mode = `Point], they will be
|
|
||||||
assumed to refer to code points.
|
|
||||||
|
|
||||||
The method [compact] has the same signature and calling
|
|
||||||
convention as [to_string], except that the resulting string is
|
|
||||||
more compact.
|
|
||||||
*)
|
|
||||||
|
|
||||||
to_string : ?file:bool -> ?offsets:bool -> [`Byte | `Point] -> string;
|
|
||||||
compact : ?file:bool -> ?offsets:bool -> [`Byte | `Point] -> string
|
|
||||||
>
|
|
||||||
|
|
||||||
type region = t
|
|
||||||
|
|
||||||
type 'a reg = {region: t; value: 'a}
|
|
||||||
|
|
||||||
(* Constructors *)
|
|
||||||
|
|
||||||
(* The function [make] creates a region from two positions. If the
|
|
||||||
positions are not properly ordered or refer to different files, the
|
|
||||||
exception [Invalid] is raised. *)
|
|
||||||
|
|
||||||
exception Invalid
|
|
||||||
|
|
||||||
val make : start:Pos.t -> stop:Pos.t -> t
|
|
||||||
|
|
||||||
(* Special regions *)
|
|
||||||
|
|
||||||
(* To deal with ghost expressions, that is, pieces of abstract syntax
|
|
||||||
that have not been built from excerpts of concrete syntax, we need
|
|
||||||
_ghost regions_. The module [Pos] provides a [ghost] position, and
|
|
||||||
we also provide a [ghost] region and, in type [t], the method
|
|
||||||
[is_ghost] to check it. *)
|
|
||||||
|
|
||||||
val ghost : t (* Two [Pos.ghost] positions *)
|
|
||||||
|
|
||||||
(* Occasionnally, we may need a minimum region. It is here made of two
|
|
||||||
minimal positions. *)
|
|
||||||
|
|
||||||
val min : t (* Two [Pos.min] positions *)
|
|
||||||
|
|
||||||
(* Comparisons *)
|
|
||||||
|
|
||||||
(* Two regions are equal if, and only if, they refer to the same file
|
|
||||||
and their start positions are equal and their stop positions are
|
|
||||||
equal. See [Pos.equal]. Note that [r1] and [r2] can be ghosts. *)
|
|
||||||
|
|
||||||
val equal : t -> t -> bool
|
|
||||||
|
|
||||||
(* The call [lt r1 r2] ("lower than") has the value [true] if, and
|
|
||||||
only if, regions [r1] and [r2] refer to the same file, none is a
|
|
||||||
ghost and the start position of [r1] is lower than that of
|
|
||||||
[r2]. (See [Pos.lt].) *)
|
|
||||||
|
|
||||||
val lt : t -> t -> bool
|
|
||||||
|
|
||||||
(* Given two regions [r1] and [r2], we may want the region [cover r1
|
|
||||||
r2] that covers [r1] and [r2]. We property [equal (cover r1 r2)
|
|
||||||
(cover r2 r1)]. (In a sense, it is the maximum region, but we avoid
|
|
||||||
that name because of the [min] function above.) If [r1] is a ghost,
|
|
||||||
the cover is [r2], and if [r2] is a ghost, the cover is [r1]. *)
|
|
||||||
|
|
||||||
val cover : t -> t -> t
|
|
@ -1,54 +0,0 @@
|
|||||||
opam-version: "2.0"
|
|
||||||
name: "tezos-utils"
|
|
||||||
version: "1.0"
|
|
||||||
synopsis: "Tezos Utilities defined in the Tezos repository, to be used by other libraries"
|
|
||||||
maintainer: "Galfour <gabriel.alfour@gmail.com>"
|
|
||||||
authors: "Galfour <gabriel.alfour@gmail.com>"
|
|
||||||
license: "MIT"
|
|
||||||
homepage: "https://gitlab.com/gabriel.alfour/tezos"
|
|
||||||
bug-reports: "https://gitlab.com/gabriel.alfour/tezos/issues"
|
|
||||||
depends: [
|
|
||||||
"dune"
|
|
||||||
"base"
|
|
||||||
"base"
|
|
||||||
"bigstring"
|
|
||||||
"calendar"
|
|
||||||
"cohttp-lwt-unix"
|
|
||||||
"cstruct"
|
|
||||||
"ezjsonm"
|
|
||||||
"hex"
|
|
||||||
"hidapi"
|
|
||||||
"ipaddr"
|
|
||||||
"irmin"
|
|
||||||
"js_of_ocaml"
|
|
||||||
"lwt"
|
|
||||||
"lwt_log"
|
|
||||||
"mtime"
|
|
||||||
"ocplib-endian"
|
|
||||||
"ocp-ocamlres"
|
|
||||||
"re"
|
|
||||||
"rresult"
|
|
||||||
"stdio"
|
|
||||||
"uri"
|
|
||||||
"uutf"
|
|
||||||
"zarith"
|
|
||||||
"ocplib-json-typed"
|
|
||||||
"ocplib-json-typed-bson"
|
|
||||||
"tezos-crypto"
|
|
||||||
"tezos-stdlib-unix"
|
|
||||||
"tezos-data-encoding"
|
|
||||||
"tezos-protocol-environment"
|
|
||||||
"tezos-protocol-alpha"
|
|
||||||
"michelson-parser"
|
|
||||||
# from ppx_let:
|
|
||||||
"ocaml" {>= "4.04.2" & < "4.08.0"}
|
|
||||||
"dune" {build & >= "1.5.1"}
|
|
||||||
"ppxlib" {>= "0.5.0"}
|
|
||||||
]
|
|
||||||
build: [
|
|
||||||
["dune" "build" "-p" name]
|
|
||||||
]
|
|
||||||
dev-repo: "git+https://gitlab.com/gabriel.alfour/tezos"
|
|
||||||
url {
|
|
||||||
src: "https://gitlab.com/gabriel.alfour/tezos/-/archive/master/tezos.master.tar.gz"
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
module Stdlib_unix = Tezos_stdlib_unix
|
|
||||||
module Data_encoding = Tezos_data_encoding
|
|
||||||
module Crypto = Tezos_crypto
|
|
||||||
module Signature = Tezos_base.TzPervasives.Signature
|
|
||||||
module Time = Tezos_base.TzPervasives.Time
|
|
||||||
module Memory_proto_alpha = X_memory_proto_alpha
|
|
||||||
module Micheline = X_tezos_micheline
|
|
||||||
|
|
||||||
|
|
||||||
module Function = Function
|
|
||||||
module Error_monad = X_error_monad
|
|
||||||
module Trace = Trace
|
|
||||||
module Logger = Logger
|
|
||||||
module PP_helpers = PP
|
|
||||||
module Location = Location
|
|
||||||
|
|
||||||
module List = X_list
|
|
||||||
module Option = X_option
|
|
||||||
module Cast = Cast
|
|
||||||
module Tuple = Tuple
|
|
||||||
module Map = X_map
|
|
||||||
module Dictionary = Dictionary
|
|
||||||
module Tree = Tree
|
|
||||||
module Region = Region
|
|
||||||
module Pos = Pos
|
|
||||||
|
|
@ -1,412 +0,0 @@
|
|||||||
module J = Yojson.Basic
|
|
||||||
|
|
||||||
type error = [`Assoc of (string * J.t) list]
|
|
||||||
|
|
||||||
module JSON_string_utils = struct
|
|
||||||
let member = J.Util.member
|
|
||||||
let string = J.Util.to_string_option
|
|
||||||
let int = J.Util.to_int_option
|
|
||||||
|
|
||||||
let swap f l r = f r l
|
|
||||||
|
|
||||||
let unit x = Some x
|
|
||||||
let bind f = function None -> None | Some x -> Some (f x)
|
|
||||||
let bind2 f = fun l r -> match l, r with
|
|
||||||
None, None -> None
|
|
||||||
| None, Some _ -> None
|
|
||||||
| Some _, None -> None
|
|
||||||
| Some l, Some r -> Some (f l r)
|
|
||||||
|
|
||||||
let default d = function
|
|
||||||
Some x -> x
|
|
||||||
| None -> d
|
|
||||||
|
|
||||||
let string_of_int = bind string_of_int
|
|
||||||
|
|
||||||
let (||) l r = l |> default r
|
|
||||||
let (|^) = bind2 (^)
|
|
||||||
end
|
|
||||||
|
|
||||||
let mk_error ?(error_code : int option) ~(title : string) ?(message : string option) () =
|
|
||||||
let collapse l =
|
|
||||||
List.fold_left (fun acc -> function None -> acc | Some e -> e::acc) [] (List.rev l) in
|
|
||||||
`Assoc
|
|
||||||
(collapse
|
|
||||||
[(match error_code with Some c -> Some ("error_code", `Int c) | None -> None);
|
|
||||||
Some ("title", `String title);
|
|
||||||
(match message with Some m -> Some ("message", `String m) | None -> None)])
|
|
||||||
|
|
||||||
|
|
||||||
type error_thunk = unit -> error
|
|
||||||
|
|
||||||
type annotation = J.t (* feel free to add different annotations here. *)
|
|
||||||
type annotation_thunk = unit -> annotation
|
|
||||||
|
|
||||||
type 'a result =
|
|
||||||
Ok of 'a * annotation_thunk list
|
|
||||||
| Errors of error_thunk list
|
|
||||||
|
|
||||||
let ok x = Ok (x, [])
|
|
||||||
let fail err = Errors [err]
|
|
||||||
|
|
||||||
(* When passing a constant string where a thunk is expected, we wrap it with thunk, as follows:
|
|
||||||
(thunk "some string")
|
|
||||||
We always put the parentheses around the call, to increase grep and sed efficiency.
|
|
||||||
|
|
||||||
When a trace function is called, it is passed a `(fun () -> …)`.
|
|
||||||
If the `…` is e.g. error then we write `(fun () -> error title msg ()` *)
|
|
||||||
let thunk x () = x
|
|
||||||
|
|
||||||
let error title message () = mk_error ~title:(title ()) ~message:(message ()) ()
|
|
||||||
|
|
||||||
let simple_error str () = mk_error ~title:str ()
|
|
||||||
|
|
||||||
let simple_fail str = fail @@ simple_error str
|
|
||||||
|
|
||||||
(* To be used when wrapped by a "trace_strong" for instance *)
|
|
||||||
let dummy_fail = simple_fail "dummy"
|
|
||||||
|
|
||||||
let map f = function
|
|
||||||
| Ok (x, annotations) ->
|
|
||||||
(match f x with
|
|
||||||
Ok (x', annotations') -> Ok (x', annotations' @ annotations)
|
|
||||||
| Errors _ as e' -> ignore annotations; e')
|
|
||||||
| Errors _ as e -> e
|
|
||||||
|
|
||||||
let apply f = function
|
|
||||||
| Ok (x, annotations) -> Ok (f x, annotations)
|
|
||||||
| Errors _ as e -> e
|
|
||||||
|
|
||||||
let (>>?) x f = map f x
|
|
||||||
let (>>|?) = apply
|
|
||||||
|
|
||||||
module Let_syntax = struct
|
|
||||||
let bind m ~f = m >>? f
|
|
||||||
module Open_on_rhs_bind = struct end
|
|
||||||
end
|
|
||||||
|
|
||||||
let trace_strong err = function
|
|
||||||
| Ok _ as o -> o
|
|
||||||
| Errors _ -> Errors [err]
|
|
||||||
|
|
||||||
let trace err = function
|
|
||||||
| Ok _ as o -> o
|
|
||||||
| Errors errs -> Errors (err :: errs)
|
|
||||||
|
|
||||||
let trace_r err_thunk_may_fail = function
|
|
||||||
| Ok _ as o -> o
|
|
||||||
| Errors errs ->
|
|
||||||
match err_thunk_may_fail () with
|
|
||||||
| Ok (err, annotations) -> ignore annotations; Errors (err :: errs)
|
|
||||||
| Errors errors_while_generating_error ->
|
|
||||||
(* TODO: the complexity could be O(n*n) in the worst case,
|
|
||||||
this should use some catenable lists. *)
|
|
||||||
Errors (errors_while_generating_error
|
|
||||||
@ errs)
|
|
||||||
|
|
||||||
let trace_f f error x =
|
|
||||||
trace error @@ f x
|
|
||||||
|
|
||||||
let trace_f_2 f error x y =
|
|
||||||
trace error @@ f x y
|
|
||||||
|
|
||||||
let trace_f_ez f name =
|
|
||||||
trace_f f (error (thunk "in function") name)
|
|
||||||
|
|
||||||
let trace_f_2_ez f name =
|
|
||||||
trace_f_2 f (error (thunk "in function") name)
|
|
||||||
|
|
||||||
let to_bool = function
|
|
||||||
| Ok _ -> true
|
|
||||||
| Errors _ -> false
|
|
||||||
|
|
||||||
let to_option = function
|
|
||||||
| Ok (o, annotations) -> ignore annotations; Some o
|
|
||||||
| Errors _ -> None
|
|
||||||
|
|
||||||
let trace_option error = function
|
|
||||||
| None -> fail error
|
|
||||||
| Some s -> ok s
|
|
||||||
|
|
||||||
let bind_map_option f = function
|
|
||||||
| None -> ok None
|
|
||||||
| Some s -> f s >>? fun x -> ok (Some x)
|
|
||||||
|
|
||||||
let rec bind_list = function
|
|
||||||
| [] -> ok []
|
|
||||||
| hd :: tl -> (
|
|
||||||
hd >>? fun hd ->
|
|
||||||
bind_list tl >>? fun tl ->
|
|
||||||
ok @@ hd :: tl
|
|
||||||
)
|
|
||||||
let bind_ne_list = fun (hd , tl) ->
|
|
||||||
hd >>? fun hd ->
|
|
||||||
bind_list tl >>? fun tl ->
|
|
||||||
ok @@ (hd , tl)
|
|
||||||
|
|
||||||
let bind_smap (s:_ X_map.String.t) =
|
|
||||||
let open X_map.String in
|
|
||||||
let aux k v prev =
|
|
||||||
prev >>? fun prev' ->
|
|
||||||
v >>? fun v' ->
|
|
||||||
ok @@ add k v' prev' in
|
|
||||||
fold aux s (ok empty)
|
|
||||||
|
|
||||||
let bind_fold_smap f init (smap : _ X_map.String.t) =
|
|
||||||
let aux k v prev =
|
|
||||||
prev >>? fun prev' ->
|
|
||||||
f prev' k v
|
|
||||||
in
|
|
||||||
X_map.String.fold aux smap init
|
|
||||||
|
|
||||||
let bind_map_smap f smap = bind_smap (X_map.String.map f smap)
|
|
||||||
|
|
||||||
let bind_map_list f lst = bind_list (List.map f lst)
|
|
||||||
let bind_map_ne_list : _ -> 'a X_list.Ne.t -> 'b X_list.Ne.t result = fun f lst -> bind_ne_list (X_list.Ne.map f lst)
|
|
||||||
let bind_iter_list : (_ -> unit result) -> _ list -> unit result = fun f lst ->
|
|
||||||
bind_map_list f lst >>? fun _ -> ok ()
|
|
||||||
|
|
||||||
let bind_location (x:_ Location.wrap) =
|
|
||||||
x.wrap_content >>? fun wrap_content ->
|
|
||||||
ok { x with wrap_content }
|
|
||||||
|
|
||||||
let bind_map_location f x = bind_location (Location.map f x)
|
|
||||||
|
|
||||||
let bind_fold_list f init lst =
|
|
||||||
let aux x y =
|
|
||||||
x >>? fun x ->
|
|
||||||
f x y
|
|
||||||
in
|
|
||||||
List.fold_left aux (ok init) lst
|
|
||||||
|
|
||||||
let bind_fold_map_list = fun f acc lst ->
|
|
||||||
let rec aux (acc , prev) f = function
|
|
||||||
| [] -> ok (acc , prev)
|
|
||||||
| hd :: tl ->
|
|
||||||
f acc hd >>? fun (acc' , hd') ->
|
|
||||||
aux (acc' , hd' :: prev) f tl
|
|
||||||
in
|
|
||||||
aux (acc , []) f lst >>? fun (_acc' , lst') ->
|
|
||||||
ok @@ List.rev lst'
|
|
||||||
|
|
||||||
let bind_fold_map_right_list = fun f acc lst ->
|
|
||||||
let rec aux (acc , prev) f = function
|
|
||||||
| [] -> ok (acc , prev)
|
|
||||||
| hd :: tl ->
|
|
||||||
f acc hd >>? fun (acc' , hd') ->
|
|
||||||
aux (acc' , hd' :: prev) f tl
|
|
||||||
in
|
|
||||||
aux (acc , []) f (List.rev lst) >>? fun (_acc' , lst') ->
|
|
||||||
ok lst'
|
|
||||||
|
|
||||||
let bind_fold_right_list f init lst =
|
|
||||||
let aux x y =
|
|
||||||
x >>? fun x ->
|
|
||||||
f x y
|
|
||||||
in
|
|
||||||
X_list.fold_right' aux (ok init) lst
|
|
||||||
|
|
||||||
let bind_find_map_list error f lst =
|
|
||||||
let rec aux lst =
|
|
||||||
match lst with
|
|
||||||
| [] -> fail error
|
|
||||||
| hd :: tl -> (
|
|
||||||
match f hd with
|
|
||||||
| Errors _ -> aux tl
|
|
||||||
| o -> o
|
|
||||||
)
|
|
||||||
in
|
|
||||||
aux lst
|
|
||||||
|
|
||||||
let bind_list_iter f lst =
|
|
||||||
let aux () y = f y in
|
|
||||||
bind_fold_list aux () lst
|
|
||||||
|
|
||||||
let bind_or (a, b) =
|
|
||||||
match a with
|
|
||||||
| Ok _ as o -> o
|
|
||||||
| _ -> b
|
|
||||||
|
|
||||||
let bind_lr (type a b) ((a : a result), (b:b result)) : [`Left of a | `Right of b] result =
|
|
||||||
match (a, b) with
|
|
||||||
| (Ok _ as o), _ -> apply (fun x -> `Left x) o
|
|
||||||
| _, (Ok _ as o) -> apply (fun x -> `Right x) o
|
|
||||||
| _, Errors b -> Errors b
|
|
||||||
|
|
||||||
let bind_lr_lazy (type a b) ((a : a result), (b:unit -> b result)) : [`Left of a | `Right of b] result =
|
|
||||||
match a with
|
|
||||||
| Ok _ as o -> apply (fun x -> `Left x) o
|
|
||||||
| _ -> (
|
|
||||||
match b() with
|
|
||||||
| Ok _ as o -> apply (fun x -> `Right x) o
|
|
||||||
| Errors b -> Errors b
|
|
||||||
)
|
|
||||||
|
|
||||||
let bind_and (a, b) =
|
|
||||||
a >>? fun a ->
|
|
||||||
b >>? fun b ->
|
|
||||||
ok (a, b)
|
|
||||||
|
|
||||||
let bind_pair = bind_and
|
|
||||||
let bind_map_pair f (a, b) =
|
|
||||||
bind_pair (f a, f b)
|
|
||||||
|
|
||||||
module AE = Memory_proto_alpha.Alpha_environment
|
|
||||||
module TP = Tezos_base__TzPervasives
|
|
||||||
|
|
||||||
let of_tz_error (err:X_error_monad.error) : error_thunk =
|
|
||||||
let str () = X_error_monad.(to_string err) in
|
|
||||||
error (thunk "alpha error") str
|
|
||||||
|
|
||||||
let of_alpha_tz_error err = of_tz_error (AE.Ecoproto_error err)
|
|
||||||
|
|
||||||
let trace_alpha_tzresult err : 'a AE.Error_monad.tzresult -> 'a result =
|
|
||||||
function
|
|
||||||
| Result.Ok x -> ok x
|
|
||||||
| Error errs -> Errors (err :: List.map of_alpha_tz_error errs)
|
|
||||||
|
|
||||||
let trace_alpha_tzresult_lwt error (x:_ AE.Error_monad.tzresult Lwt.t) : _ result =
|
|
||||||
trace_alpha_tzresult error @@ Lwt_main.run x
|
|
||||||
|
|
||||||
let trace_tzresult err =
|
|
||||||
function
|
|
||||||
| Result.Ok x -> ok x
|
|
||||||
| Error errs -> Errors (err :: List.map of_tz_error errs)
|
|
||||||
|
|
||||||
(* TODO: should be a combination of trace_tzresult and trace_r *)
|
|
||||||
let trace_tzresult_r err_thunk_may_fail =
|
|
||||||
function
|
|
||||||
| Result.Ok x -> ok x
|
|
||||||
| Error errs ->
|
|
||||||
let tz_errs = List.map of_tz_error errs in
|
|
||||||
match err_thunk_may_fail () with
|
|
||||||
| Ok (err, annotations) -> ignore annotations; Errors (err :: tz_errs)
|
|
||||||
| Errors errors_while_generating_error ->
|
|
||||||
(* TODO: the complexity could be O(n*n) in the worst case,
|
|
||||||
this should use some catenable lists. *)
|
|
||||||
Errors (errors_while_generating_error
|
|
||||||
@ tz_errs)
|
|
||||||
|
|
||||||
let trace_tzresult_lwt err (x:_ TP.Error_monad.tzresult Lwt.t) : _ result =
|
|
||||||
trace_tzresult err @@ Lwt_main.run x
|
|
||||||
|
|
||||||
let trace_tzresult_lwt_r err (x:_ TP.Error_monad.tzresult Lwt.t) : _ result =
|
|
||||||
trace_tzresult_r err @@ Lwt_main.run x
|
|
||||||
|
|
||||||
let generic_try err f =
|
|
||||||
try (
|
|
||||||
ok @@ f ()
|
|
||||||
) with _ -> fail err
|
|
||||||
|
|
||||||
let specific_try handler f =
|
|
||||||
try (
|
|
||||||
ok @@ f ()
|
|
||||||
) with exn -> fail ((handler ()) exn)
|
|
||||||
|
|
||||||
let sys_try f =
|
|
||||||
let handler () = function
|
|
||||||
| Sys_error str -> error (thunk "Sys_error") (fun () -> str)
|
|
||||||
| exn -> raise exn
|
|
||||||
in
|
|
||||||
specific_try handler f
|
|
||||||
|
|
||||||
let sys_command command =
|
|
||||||
sys_try (fun () -> Sys.command command) >>? function
|
|
||||||
| 0 -> ok ()
|
|
||||||
| n -> fail (fun () -> error (thunk "Nonzero return code") (fun () -> (string_of_int n)) ())
|
|
||||||
|
|
||||||
let trace_sequence f lst =
|
|
||||||
let lazy_map_force : 'a . (unit -> 'a) list -> (unit -> 'a list) = fun l ->
|
|
||||||
fun () ->
|
|
||||||
List.rev @@ List.rev_map (fun a -> a ()) l in
|
|
||||||
let rec aux acc_x acc_annotations = function
|
|
||||||
| hd :: tl -> (
|
|
||||||
match f hd with
|
|
||||||
(* TODO: what should we do with the annotations? *)
|
|
||||||
| Ok (x, annotations) -> aux (x :: acc_x) (lazy_map_force annotations :: acc_annotations) tl
|
|
||||||
| Errors _ as errs -> errs
|
|
||||||
)
|
|
||||||
| [] ->
|
|
||||||
let old_annotations () = List.map (fun a -> `List (a ())) @@ List.rev acc_annotations in
|
|
||||||
(* Builds a JSON annotation { "type": "list"; "content": [[…], …] } *)
|
|
||||||
let annotation = fun () -> `Assoc [("type", `String "list"); ("content", `List (old_annotations ()))]
|
|
||||||
in Ok (List.rev acc_x, [annotation]) in
|
|
||||||
aux [] lst
|
|
||||||
|
|
||||||
let json_of_error = J.to_string
|
|
||||||
let error_pp out (e : error) =
|
|
||||||
let open JSON_string_utils in
|
|
||||||
let e : J.t = (match e with `Assoc _ as e -> e) in
|
|
||||||
let message = e |> member "message" |> string in
|
|
||||||
let title = e |> member "title" |> string || "(no title)" in
|
|
||||||
let error_code = unit " " |^ (e |> member "error_code" |> int |> string_of_int) || "" in
|
|
||||||
Format.fprintf out "%s" (error_code ^ ": " ^ title ^ (unit ":" |^ message || ""))
|
|
||||||
|
|
||||||
let error_pp_short out (e : error) =
|
|
||||||
let open JSON_string_utils in
|
|
||||||
let e : J.t = (match e with `Assoc _ as e -> e) in
|
|
||||||
let title = e |> member "title" |> string || "(no title)" in
|
|
||||||
let error_code = unit " " |^ (e |> member "error_code" |> int |> string_of_int) || "" in
|
|
||||||
Format.fprintf out "%s" (error_code ^ ": " ^ title)
|
|
||||||
|
|
||||||
let errors_pp =
|
|
||||||
Format.pp_print_list
|
|
||||||
~pp_sep:Format.pp_print_newline
|
|
||||||
error_pp
|
|
||||||
|
|
||||||
let errors_pp_short =
|
|
||||||
Format.pp_print_list
|
|
||||||
~pp_sep:Format.pp_print_newline
|
|
||||||
error_pp_short
|
|
||||||
|
|
||||||
let pp_to_string pp () x =
|
|
||||||
Format.fprintf Format.str_formatter "%a" pp x ;
|
|
||||||
Format.flush_str_formatter ()
|
|
||||||
|
|
||||||
let errors_to_string = pp_to_string errors_pp
|
|
||||||
|
|
||||||
module Assert = struct
|
|
||||||
let assert_fail ?(msg="didn't fail") = function
|
|
||||||
| Ok _ -> simple_fail msg
|
|
||||||
| _ -> ok ()
|
|
||||||
|
|
||||||
let assert_true ?(msg="not true") = function
|
|
||||||
| true -> ok ()
|
|
||||||
| false -> simple_fail msg
|
|
||||||
|
|
||||||
let assert_equal ?msg expected actual =
|
|
||||||
assert_true ?msg (expected = actual)
|
|
||||||
|
|
||||||
let assert_equal_int ?msg expected actual =
|
|
||||||
let msg =
|
|
||||||
let default = Format.asprintf "Not equal int : expected %d, got %d" expected actual in
|
|
||||||
X_option.unopt ~default msg in
|
|
||||||
assert_equal ~msg expected actual
|
|
||||||
|
|
||||||
let assert_equal_bool ?msg expected actual =
|
|
||||||
let msg =
|
|
||||||
let default = Format.asprintf "Not equal bool : expected %b, got %b" expected actual in
|
|
||||||
X_option.unopt ~default msg in
|
|
||||||
assert_equal ~msg expected actual
|
|
||||||
|
|
||||||
let assert_none ?(msg="not a none") opt = match opt with
|
|
||||||
| None -> ok ()
|
|
||||||
| _ -> simple_fail msg
|
|
||||||
|
|
||||||
let assert_list_size ?(msg="lst doesn't have the right size") lst n =
|
|
||||||
assert_true ~msg List.(length lst = n)
|
|
||||||
|
|
||||||
let assert_list_empty ?(msg="lst isn't empty") lst =
|
|
||||||
assert_true ~msg List.(length lst = 0)
|
|
||||||
|
|
||||||
let assert_list_same_size ?(msg="lists don't have same size") a b =
|
|
||||||
assert_true ~msg List.(length a = length b)
|
|
||||||
|
|
||||||
let assert_list_size_2 ~msg = function
|
|
||||||
| [a;b] -> ok (a, b)
|
|
||||||
| _ -> simple_fail msg
|
|
||||||
|
|
||||||
let assert_list_size_1 ~msg = function
|
|
||||||
| [a] -> ok a
|
|
||||||
| _ -> simple_fail msg
|
|
||||||
end
|
|
@ -1,130 +0,0 @@
|
|||||||
[@@@warning "-9"]
|
|
||||||
|
|
||||||
module Append = struct
|
|
||||||
type 'a t' =
|
|
||||||
| Leaf of 'a
|
|
||||||
| Node of {
|
|
||||||
a : 'a t' ;
|
|
||||||
b : 'a t' ;
|
|
||||||
size : int ;
|
|
||||||
full : bool ;
|
|
||||||
}
|
|
||||||
|
|
||||||
type 'a t =
|
|
||||||
| Empty
|
|
||||||
| Full of 'a t'
|
|
||||||
|
|
||||||
let node (a, b, size, full) = Node {a;b;size;full}
|
|
||||||
|
|
||||||
let rec exists' f = function
|
|
||||||
| Leaf s' when f s' -> true
|
|
||||||
| Leaf _ -> false
|
|
||||||
| Node{a;b} -> exists' f a || exists' f b
|
|
||||||
let exists f = function
|
|
||||||
| Empty -> false
|
|
||||||
| Full x -> exists' f x
|
|
||||||
|
|
||||||
let rec exists_path' f = function
|
|
||||||
| Leaf x -> if f x then Some [] else None
|
|
||||||
| Node {a;b} -> (
|
|
||||||
match exists_path' f a with
|
|
||||||
| Some a -> Some (false :: a)
|
|
||||||
| None -> (
|
|
||||||
match exists_path' f b with
|
|
||||||
| Some b -> Some (true :: b)
|
|
||||||
| None -> None
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
let exists_path f = function
|
|
||||||
| Empty -> None
|
|
||||||
| Full x -> exists_path' f x
|
|
||||||
|
|
||||||
let empty : 'a t = Empty
|
|
||||||
|
|
||||||
let size' = function
|
|
||||||
| Leaf _ -> 1
|
|
||||||
| Node {size} -> size
|
|
||||||
|
|
||||||
let size = function
|
|
||||||
| Empty -> 0
|
|
||||||
| Full x -> size' x
|
|
||||||
|
|
||||||
let rec append' x = function
|
|
||||||
| Leaf e -> node (Leaf e, Leaf x, 1, true)
|
|
||||||
| Node({full=true;size}) as n -> node(n, Leaf x, size + 1, false)
|
|
||||||
| Node({a=Node a;b;full=false} as n) -> (
|
|
||||||
match append' x b with
|
|
||||||
| Node{full=false} as b -> Node{n with b}
|
|
||||||
| Node({full=true} as b) -> Node{n with b = Node b ; full = b.size = a.size}
|
|
||||||
| Leaf _ -> assert false
|
|
||||||
)
|
|
||||||
| Node{a=Leaf _;full=false} -> assert false
|
|
||||||
|
|
||||||
let append x = function
|
|
||||||
| Empty -> Full (Leaf x)
|
|
||||||
| Full t -> Full (append' x t)
|
|
||||||
|
|
||||||
let of_list lst =
|
|
||||||
let rec aux = function
|
|
||||||
| [] -> Empty
|
|
||||||
| hd :: tl -> append hd (aux tl)
|
|
||||||
in
|
|
||||||
aux @@ List.rev lst
|
|
||||||
|
|
||||||
let rec to_list' t' =
|
|
||||||
match t' with
|
|
||||||
| Leaf x -> [x]
|
|
||||||
| Node {a;b} -> (to_list' a) @ (to_list' b)
|
|
||||||
|
|
||||||
let to_list t =
|
|
||||||
match t with
|
|
||||||
| Empty -> []
|
|
||||||
| Full x -> to_list' x
|
|
||||||
|
|
||||||
let rec fold' leaf node = function
|
|
||||||
| Leaf x -> leaf x
|
|
||||||
| Node {a;b} -> node (fold' leaf node a) (fold' leaf node b)
|
|
||||||
|
|
||||||
let rec fold_s' : type a b . a -> (a -> b -> a) -> b t' -> a = fun init leaf -> function
|
|
||||||
| Leaf x -> leaf init x
|
|
||||||
| Node {a;b} -> fold_s' (fold_s' init leaf a) leaf b
|
|
||||||
|
|
||||||
let fold_ne leaf node = function
|
|
||||||
| Empty -> raise (Failure "Tree.Append.fold_ne")
|
|
||||||
| Full x -> fold' leaf node x
|
|
||||||
|
|
||||||
let fold_s_ne : type a b . a -> (a -> b -> a) -> b t -> a = fun init leaf -> function
|
|
||||||
| Empty -> raise (Failure "Tree.Append.fold_s_ne")
|
|
||||||
| Full x -> fold_s' init leaf x
|
|
||||||
|
|
||||||
let fold empty leaf node = function
|
|
||||||
| Empty -> empty
|
|
||||||
| Full x -> fold' leaf node x
|
|
||||||
|
|
||||||
|
|
||||||
let rec assoc_opt' : ('a * 'b) t' -> 'a -> 'b option = fun t k ->
|
|
||||||
match t with
|
|
||||||
| Leaf (k', v) when k = k' -> Some v
|
|
||||||
| Leaf _ -> None
|
|
||||||
| Node {a;b} -> (
|
|
||||||
match assoc_opt' a k with
|
|
||||||
| None -> assoc_opt' b k
|
|
||||||
| Some v -> Some v
|
|
||||||
)
|
|
||||||
|
|
||||||
let assoc_opt : ('a * 'b) t -> 'a -> 'b option = fun t k ->
|
|
||||||
match t with
|
|
||||||
| Empty -> None
|
|
||||||
| Full t' -> assoc_opt' t' k
|
|
||||||
|
|
||||||
let rec pp' : _ -> _ -> 'a t' -> unit = fun f ppf t' ->
|
|
||||||
match t' with
|
|
||||||
| Leaf x -> Format.fprintf ppf "%a" f x
|
|
||||||
| Node {a;b} -> Format.fprintf ppf "N(%a , %a)" (pp' f) a (pp' f) b
|
|
||||||
|
|
||||||
let pp : _ -> _ -> 'a t -> unit = fun f ppf t ->
|
|
||||||
match t with
|
|
||||||
| Empty -> Format.fprintf ppf "[]"
|
|
||||||
| Full x -> Format.fprintf ppf "[%a]" (pp' f) x
|
|
||||||
end
|
|
@ -1,9 +0,0 @@
|
|||||||
let map_h_2 f g (a , b) = (f a , g b)
|
|
||||||
let map2 f (a, b) = (f a, f b)
|
|
||||||
let apply2 f (a, b) = f a b
|
|
||||||
let list2 (a, b) = [a;b]
|
|
||||||
|
|
||||||
module Pair = struct
|
|
||||||
let map = map2
|
|
||||||
let apply f (a, b) = f a b
|
|
||||||
end
|
|
@ -1,21 +0,0 @@
|
|||||||
module Make (P : sig type meta end) = struct
|
|
||||||
type meta = P.meta
|
|
||||||
type 'value t = {
|
|
||||||
value : 'value ;
|
|
||||||
meta : meta ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let make meta value = { value ; meta }
|
|
||||||
let value t = t.value
|
|
||||||
let meta t = t.meta
|
|
||||||
|
|
||||||
let apply : ('a -> 'b) -> 'a t -> 'b = fun f x -> f x.value
|
|
||||||
end
|
|
||||||
|
|
||||||
module Location = struct
|
|
||||||
include Make(struct type meta = Location.t end)
|
|
||||||
|
|
||||||
let make_f f : loc:_ -> _ -> _ t = fun ~loc x -> make loc (f x)
|
|
||||||
let make ~loc x : _ t = make loc x
|
|
||||||
let update_location ~loc t = {t with meta = loc}
|
|
||||||
end
|
|
@ -1,50 +0,0 @@
|
|||||||
module Error_monad = Tezos_error_monad.Error_monad
|
|
||||||
include Error_monad
|
|
||||||
|
|
||||||
let to_string err =
|
|
||||||
let json = json_of_error err in
|
|
||||||
Tezos_data_encoding.Json.to_string json
|
|
||||||
|
|
||||||
let print err =
|
|
||||||
Format.printf "%s\n" @@ to_string err
|
|
||||||
|
|
||||||
let force_ok ?(msg = "") = function
|
|
||||||
| Ok x -> x
|
|
||||||
| Error errs ->
|
|
||||||
Format.printf "Errors :\n";
|
|
||||||
List.iter print errs ;
|
|
||||||
raise @@ Failure ("force_ok : " ^ msg)
|
|
||||||
|
|
||||||
let is_ok = function
|
|
||||||
| Ok _ -> true
|
|
||||||
| Error _ -> false
|
|
||||||
|
|
||||||
let force_ok_str ?(msg = "") = function
|
|
||||||
| Ok x -> x
|
|
||||||
| Error err ->
|
|
||||||
Format.printf "Error : %s\n" err;
|
|
||||||
raise @@ Failure ("force_ok : " ^ msg)
|
|
||||||
|
|
||||||
open Memory_proto_alpha
|
|
||||||
|
|
||||||
let (>>??) = Alpha_environment.Error_monad.(>>?)
|
|
||||||
|
|
||||||
let alpha_wrap a = Alpha_environment.wrap_error a
|
|
||||||
|
|
||||||
let force_ok_alpha ~msg a = force_ok ~msg @@ alpha_wrap a
|
|
||||||
|
|
||||||
let force_lwt ~msg a = force_ok ~msg @@ Lwt_main.run a
|
|
||||||
|
|
||||||
let force_lwt_alpha ~msg a = force_ok ~msg @@ alpha_wrap @@ Lwt_main.run a
|
|
||||||
|
|
||||||
let assert_error () = function
|
|
||||||
| Ok _ -> fail @@ failure "assert_error"
|
|
||||||
| Error _ -> return ()
|
|
||||||
|
|
||||||
let (>>=??) a f =
|
|
||||||
a >>= fun a ->
|
|
||||||
match alpha_wrap a with
|
|
||||||
| Ok result -> f result
|
|
||||||
| Error errs -> Lwt.return (Error errs)
|
|
||||||
|
|
||||||
|
|
@ -1,159 +0,0 @@
|
|||||||
include Tezos_base.TzPervasives.List
|
|
||||||
|
|
||||||
let map ?(acc = []) f lst =
|
|
||||||
let rec aux acc f = function
|
|
||||||
| [] -> acc
|
|
||||||
| hd :: tl -> aux (f hd :: acc) f tl
|
|
||||||
in
|
|
||||||
aux acc f (List.rev lst)
|
|
||||||
|
|
||||||
let fold_map_right : type acc ele ret . (acc -> ele -> (acc * ret)) -> acc -> ele list -> ret list =
|
|
||||||
fun f acc lst ->
|
|
||||||
let rec aux (acc , prev) f = function
|
|
||||||
| [] -> (acc , prev)
|
|
||||||
| hd :: tl ->
|
|
||||||
let (acc' , hd') = f acc hd in
|
|
||||||
aux (acc' , hd' :: prev) f tl
|
|
||||||
in
|
|
||||||
snd @@ aux (acc , []) f (List.rev lst)
|
|
||||||
|
|
||||||
let fold_map : type acc ele ret . (acc -> ele -> (acc * ret)) -> acc -> ele list -> ret list =
|
|
||||||
fun f acc lst ->
|
|
||||||
let rec aux (acc , prev) f = function
|
|
||||||
| [] -> (acc , prev)
|
|
||||||
| hd :: tl ->
|
|
||||||
let (acc' , hd') = f acc hd in
|
|
||||||
aux (acc' , hd' :: prev) f tl
|
|
||||||
in
|
|
||||||
List.rev @@ snd @@ aux (acc , []) f lst
|
|
||||||
|
|
||||||
let fold_right' f init lst = List.fold_left f init (List.rev lst)
|
|
||||||
|
|
||||||
let rec remove_element x lst =
|
|
||||||
match lst with
|
|
||||||
| [] -> raise (Failure "X_list.remove_element")
|
|
||||||
| hd :: tl when x = hd -> tl
|
|
||||||
| hd :: tl -> hd :: remove_element x tl
|
|
||||||
|
|
||||||
let filter_map f =
|
|
||||||
let rec aux acc lst = match lst with
|
|
||||||
| [] -> List.rev acc
|
|
||||||
| hd :: tl -> aux (
|
|
||||||
match f hd with
|
|
||||||
| Some x -> x :: acc
|
|
||||||
| None -> acc
|
|
||||||
) tl
|
|
||||||
in
|
|
||||||
aux []
|
|
||||||
|
|
||||||
let cons_iter = fun fhd ftl lst ->
|
|
||||||
match lst with
|
|
||||||
| [] -> ()
|
|
||||||
| hd :: tl -> fhd hd ; List.iter ftl tl
|
|
||||||
|
|
||||||
let range n =
|
|
||||||
let rec aux acc n =
|
|
||||||
if n = 0
|
|
||||||
then acc
|
|
||||||
else aux ((n-1) :: acc) (n-1)
|
|
||||||
in
|
|
||||||
aux [] n
|
|
||||||
|
|
||||||
let find_map f lst =
|
|
||||||
let rec aux = function
|
|
||||||
| [] -> None
|
|
||||||
| hd::tl -> (
|
|
||||||
match f hd with
|
|
||||||
| Some _ as s -> s
|
|
||||||
| None -> aux tl
|
|
||||||
)
|
|
||||||
in
|
|
||||||
aux lst
|
|
||||||
|
|
||||||
let find_index f lst =
|
|
||||||
let rec aux n = function
|
|
||||||
| [] -> raise (Failure "find_index")
|
|
||||||
| hd :: _ when f hd -> n
|
|
||||||
| _ :: tl -> aux (n + 1) tl in
|
|
||||||
aux 0 lst
|
|
||||||
|
|
||||||
let find_full f lst =
|
|
||||||
let rec aux n = function
|
|
||||||
| [] -> raise (Failure "find_index")
|
|
||||||
| hd :: _ when f hd -> (hd, n)
|
|
||||||
| _ :: tl -> aux (n + 1) tl in
|
|
||||||
aux 0 lst
|
|
||||||
|
|
||||||
let assoc_i x lst =
|
|
||||||
let rec aux n = function
|
|
||||||
| [] -> raise (Failure "List:assoc_i")
|
|
||||||
| (x', y) :: _ when x = x' -> (y, n)
|
|
||||||
| _ :: tl -> aux (n + 1) tl
|
|
||||||
in
|
|
||||||
aux 0 lst
|
|
||||||
|
|
||||||
let rec from n lst =
|
|
||||||
if n = 0
|
|
||||||
then lst
|
|
||||||
else from (n - 1) (tl lst)
|
|
||||||
|
|
||||||
let until n lst =
|
|
||||||
let rec aux acc n lst =
|
|
||||||
if n = 0
|
|
||||||
then acc
|
|
||||||
else aux ((hd lst) :: acc) (n - 1) (tl lst)
|
|
||||||
in
|
|
||||||
rev (aux [] n lst)
|
|
||||||
|
|
||||||
let uncons_opt = function
|
|
||||||
| [] -> None
|
|
||||||
| hd :: tl -> Some (hd, tl)
|
|
||||||
|
|
||||||
let rev_uncons_opt = function
|
|
||||||
| [] -> None
|
|
||||||
| lst ->
|
|
||||||
let r = rev lst in
|
|
||||||
let last = hd r in
|
|
||||||
let hds = rev @@ tl r in
|
|
||||||
Some (hds , last)
|
|
||||||
|
|
||||||
let hds lst = match rev_uncons_opt lst with
|
|
||||||
| None -> failwith "toto"
|
|
||||||
| Some (hds , _) -> hds
|
|
||||||
|
|
||||||
let to_pair = function
|
|
||||||
| [a ; b] -> Some (a , b)
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let to_singleton = function
|
|
||||||
| [a] -> Some a
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
module Ne = struct
|
|
||||||
|
|
||||||
type 'a t = 'a * 'a list
|
|
||||||
|
|
||||||
let of_list lst = List.(hd lst, tl lst)
|
|
||||||
let to_list (hd, tl : _ t) = hd :: tl
|
|
||||||
let singleton hd : 'a t = hd , []
|
|
||||||
let hd : 'a t -> 'a = fst
|
|
||||||
let cons : 'a -> 'a t -> 'a t = fun hd' (hd , tl) -> hd' , hd :: tl
|
|
||||||
let iter f (hd, tl : _ t) = f hd ; List.iter f tl
|
|
||||||
let map f (hd, tl : _ t) = f hd, List.map f tl
|
|
||||||
let hd_map : _ -> 'a t -> 'a t = fun f (hd , tl) -> (f hd , tl)
|
|
||||||
let mapi f (hd, tl : _ t) =
|
|
||||||
let lst = List.mapi f (hd::tl) in
|
|
||||||
of_list lst
|
|
||||||
let concat (hd, tl : _ t) = hd @ List.concat tl
|
|
||||||
let rev (hd, tl : _ t) =
|
|
||||||
match tl with
|
|
||||||
| [] -> (hd, [])
|
|
||||||
| lst ->
|
|
||||||
let r = List.rev lst in
|
|
||||||
(List.hd r, List.tl r @ [hd])
|
|
||||||
let find_map = fun f (hd , tl : _ t) ->
|
|
||||||
match f hd with
|
|
||||||
| Some x -> Some x
|
|
||||||
| None -> find_map f tl
|
|
||||||
|
|
||||||
end
|
|
@ -1,27 +0,0 @@
|
|||||||
module type OrderedType = Map.OrderedType
|
|
||||||
|
|
||||||
module type S = sig
|
|
||||||
include Map.S
|
|
||||||
|
|
||||||
val of_list : (key * 'a) list -> 'a t
|
|
||||||
val to_list : 'a t -> 'a list
|
|
||||||
val to_kv_list : 'a t -> (key * 'a) list
|
|
||||||
end
|
|
||||||
|
|
||||||
module Make(Ord : Map.OrderedType) : S with type key = Ord.t = struct
|
|
||||||
include Map.Make(Ord)
|
|
||||||
|
|
||||||
let of_list (lst: (key * 'a) list) : 'a t =
|
|
||||||
let aux prev (k, v) = add k v prev in
|
|
||||||
List.fold_left aux empty lst
|
|
||||||
|
|
||||||
let to_list (t: 'a t) : 'a list =
|
|
||||||
let aux _k v prev = v :: prev in
|
|
||||||
fold aux t []
|
|
||||||
|
|
||||||
let to_kv_list (t: 'a t) : (key * 'a) list =
|
|
||||||
let aux k v prev = (k, v) :: prev in
|
|
||||||
fold aux t []
|
|
||||||
end
|
|
||||||
|
|
||||||
module String = Make(String)
|
|
@ -1,133 +0,0 @@
|
|||||||
module Michelson = X_tezos_micheline.Michelson
|
|
||||||
|
|
||||||
include Memory_proto_alpha
|
|
||||||
let init_environment = Init_proto_alpha.init_environment
|
|
||||||
let dummy_environment = Init_proto_alpha.dummy_environment
|
|
||||||
|
|
||||||
open X_error_monad
|
|
||||||
open Script_typed_ir
|
|
||||||
open Script_ir_translator
|
|
||||||
open Script_interpreter
|
|
||||||
|
|
||||||
let stack_ty_eq (type a b)
|
|
||||||
?(tezos_context = dummy_environment.tezos_context)
|
|
||||||
(a:a stack_ty) (b:b stack_ty) =
|
|
||||||
alpha_wrap (Script_ir_translator.stack_ty_eq tezos_context 0 a b) >>? fun (Eq, _) ->
|
|
||||||
ok Eq
|
|
||||||
|
|
||||||
let ty_eq (type a b)
|
|
||||||
?(tezos_context = dummy_environment.tezos_context)
|
|
||||||
(a:a ty) (b:b ty)
|
|
||||||
=
|
|
||||||
alpha_wrap (Script_ir_translator.ty_eq tezos_context a b) >>? fun (Eq, _) ->
|
|
||||||
ok Eq
|
|
||||||
|
|
||||||
let parse_michelson (type aft)
|
|
||||||
?(tezos_context = dummy_environment.tezos_context)
|
|
||||||
?(top_level = Lambda) (michelson:Michelson.t)
|
|
||||||
?type_logger
|
|
||||||
(bef:'a Script_typed_ir.stack_ty) (aft:aft Script_typed_ir.stack_ty)
|
|
||||||
=
|
|
||||||
let michelson = Michelson.strip_annots michelson in
|
|
||||||
let michelson = Michelson.strip_nops michelson in
|
|
||||||
parse_instr
|
|
||||||
?type_logger
|
|
||||||
top_level tezos_context
|
|
||||||
michelson bef >>=?? fun (j, _) ->
|
|
||||||
match j with
|
|
||||||
| Typed descr -> (
|
|
||||||
Lwt.return (
|
|
||||||
alpha_wrap (Script_ir_translator.stack_ty_eq tezos_context 0 descr.aft aft) >>? fun (Eq, _) ->
|
|
||||||
let descr : (_, aft) Script_typed_ir.descr = {descr with aft} in
|
|
||||||
Ok descr
|
|
||||||
)
|
|
||||||
)
|
|
||||||
| _ -> Lwt.return @@ error_exn (Failure "Typing instr failed")
|
|
||||||
|
|
||||||
let parse_michelson_fail (type aft)
|
|
||||||
?(tezos_context = dummy_environment.tezos_context)
|
|
||||||
?(top_level = Lambda) (michelson:Michelson.t)
|
|
||||||
?type_logger
|
|
||||||
(bef:'a Script_typed_ir.stack_ty) (aft:aft Script_typed_ir.stack_ty)
|
|
||||||
=
|
|
||||||
let michelson = Michelson.strip_annots michelson in
|
|
||||||
let michelson = Michelson.strip_nops michelson in
|
|
||||||
parse_instr
|
|
||||||
?type_logger
|
|
||||||
top_level tezos_context
|
|
||||||
michelson bef >>=?? fun (j, _) ->
|
|
||||||
match j with
|
|
||||||
| Typed descr -> (
|
|
||||||
Lwt.return (
|
|
||||||
alpha_wrap (Script_ir_translator.stack_ty_eq tezos_context 0 descr.aft aft) >>? fun (Eq, _) ->
|
|
||||||
let descr : (_, aft) Script_typed_ir.descr = {descr with aft} in
|
|
||||||
Ok descr
|
|
||||||
)
|
|
||||||
)
|
|
||||||
| Failed { descr } ->
|
|
||||||
Lwt.return (Ok (descr aft))
|
|
||||||
|
|
||||||
let parse_michelson_data
|
|
||||||
?(tezos_context = dummy_environment.tezos_context)
|
|
||||||
michelson ty =
|
|
||||||
let michelson = Michelson.strip_annots michelson in
|
|
||||||
let michelson = Michelson.strip_nops michelson in
|
|
||||||
parse_data tezos_context ty michelson >>=?? fun (data, _) ->
|
|
||||||
return data
|
|
||||||
|
|
||||||
let parse_michelson_ty
|
|
||||||
?(tezos_context = dummy_environment.tezos_context)
|
|
||||||
?(allow_big_map = true) ?(allow_operation = true)
|
|
||||||
michelson =
|
|
||||||
let michelson = Michelson.strip_annots michelson in
|
|
||||||
let michelson = Michelson.strip_nops michelson in
|
|
||||||
Lwt.return @@ parse_ty tezos_context ~allow_big_map ~allow_operation michelson >>=?? fun (ty, _) ->
|
|
||||||
return ty
|
|
||||||
|
|
||||||
let unparse_michelson_data
|
|
||||||
?(tezos_context = dummy_environment.tezos_context)
|
|
||||||
?mapper ty value : Michelson.t tzresult Lwt.t =
|
|
||||||
Script_ir_translator.unparse_data tezos_context ?mapper
|
|
||||||
Readable ty value >>=?? fun (michelson, _) ->
|
|
||||||
return michelson
|
|
||||||
|
|
||||||
let unparse_michelson_ty
|
|
||||||
?(tezos_context = dummy_environment.tezos_context)
|
|
||||||
ty : Michelson.t tzresult Lwt.t =
|
|
||||||
Script_ir_translator.unparse_ty tezos_context ty >>=?? fun (michelson, _) ->
|
|
||||||
return michelson
|
|
||||||
|
|
||||||
type options = {
|
|
||||||
tezos_context: Alpha_context.t ;
|
|
||||||
source: Alpha_context.Contract.t ;
|
|
||||||
payer: Alpha_context.Contract.t ;
|
|
||||||
self: Alpha_context.Contract.t ;
|
|
||||||
amount: Alpha_context.Tez.t ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let make_options
|
|
||||||
?(tezos_context = dummy_environment.tezos_context)
|
|
||||||
?(source = (List.nth dummy_environment.identities 0).implicit_contract)
|
|
||||||
?(self = (List.nth dummy_environment.identities 0).implicit_contract)
|
|
||||||
?(payer = (List.nth dummy_environment.identities 1).implicit_contract)
|
|
||||||
?(amount = Alpha_context.Tez.one) ()
|
|
||||||
= {
|
|
||||||
tezos_context ;
|
|
||||||
source ;
|
|
||||||
self ;
|
|
||||||
payer ;
|
|
||||||
amount ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let default_options = make_options ()
|
|
||||||
|
|
||||||
let interpret ?(options = default_options) ?visitor (instr:('a, 'b) descr) (bef:'a stack) : 'b stack tzresult Lwt.t =
|
|
||||||
let {
|
|
||||||
tezos_context ;
|
|
||||||
source ;
|
|
||||||
self ;
|
|
||||||
payer ;
|
|
||||||
amount ;
|
|
||||||
} = options in
|
|
||||||
Script_interpreter.step tezos_context ~source ~self ~payer ?visitor amount instr bef >>=??
|
|
||||||
fun (stack, _) -> return stack
|
|
@ -1,39 +0,0 @@
|
|||||||
include Tezos_stdlib.Option
|
|
||||||
|
|
||||||
let lr (a , b) = match (a , b) with
|
|
||||||
| Some x , _ -> Some (`Left x)
|
|
||||||
| None , Some x -> Some (`Right x)
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
(* TODO: recursive terminal *)
|
|
||||||
let rec bind_list = fun lst ->
|
|
||||||
match lst with
|
|
||||||
| [] -> Some []
|
|
||||||
| hd :: tl -> (
|
|
||||||
match hd with
|
|
||||||
| None -> None
|
|
||||||
| Some hd' -> (
|
|
||||||
match bind_list tl with
|
|
||||||
| None -> None
|
|
||||||
| Some tl' -> Some (hd' :: tl')
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
let bind_pair = fun (a , b) ->
|
|
||||||
a >>= fun a' ->
|
|
||||||
b >>= fun b' ->
|
|
||||||
Some (a' , b')
|
|
||||||
|
|
||||||
let bind_map_list = fun f lst -> bind_list (X_list.map f lst)
|
|
||||||
|
|
||||||
let bind_map_pair = fun f (a , b) -> bind_pair (f a , f b)
|
|
||||||
|
|
||||||
let bind_smap (s:_ X_map.String.t) =
|
|
||||||
let open X_map.String in
|
|
||||||
let aux k v prev =
|
|
||||||
prev >>= fun prev' ->
|
|
||||||
v >>= fun v' ->
|
|
||||||
Some (add k v' prev') in
|
|
||||||
fold aux s (Some empty)
|
|
||||||
|
|
||||||
let bind_map_smap f smap = bind_smap (X_map.String.map f smap)
|
|
@ -1,95 +0,0 @@
|
|||||||
include Tezos_micheline
|
|
||||||
|
|
||||||
module Michelson = struct
|
|
||||||
open Micheline
|
|
||||||
include Memory_proto_alpha.Michelson_v1_primitives
|
|
||||||
|
|
||||||
type michelson = (int, prim) node
|
|
||||||
type t = michelson
|
|
||||||
|
|
||||||
let prim ?(annot=[]) ?(children=[]) p : michelson =
|
|
||||||
Prim (0, p, children, annot)
|
|
||||||
|
|
||||||
let annotate annot = function
|
|
||||||
| Prim (l, p, c, []) -> Prim (l, p, c, [annot])
|
|
||||||
| _ -> raise (Failure "annotate")
|
|
||||||
|
|
||||||
let seq s : michelson = Seq (0, s)
|
|
||||||
|
|
||||||
let i_comment s : michelson = prim ~annot:["\"" ^ s ^ "\""] I_NOP
|
|
||||||
|
|
||||||
let contract parameter storage code =
|
|
||||||
seq [
|
|
||||||
prim ~children:[parameter] K_parameter ;
|
|
||||||
prim ~children:[storage] K_storage ;
|
|
||||||
prim ~children:[code] K_code ;
|
|
||||||
]
|
|
||||||
|
|
||||||
let int n : michelson = Int (0, n)
|
|
||||||
let string s : michelson = String (0, s)
|
|
||||||
let bytes s : michelson = Bytes (0, s)
|
|
||||||
|
|
||||||
let t_unit = prim T_unit
|
|
||||||
let t_string = prim T_string
|
|
||||||
let t_pair a b = prim ~children:[a;b] T_pair
|
|
||||||
let t_lambda a b = prim ~children:[a;b] T_lambda
|
|
||||||
|
|
||||||
let d_unit = prim D_Unit
|
|
||||||
let d_pair a b = prim ~children:[a;b] D_Pair
|
|
||||||
|
|
||||||
let i_dup = prim I_DUP
|
|
||||||
let i_car = prim I_CAR
|
|
||||||
let i_cdr = prim I_CDR
|
|
||||||
let i_pair = prim I_PAIR
|
|
||||||
let i_swap = prim I_SWAP
|
|
||||||
let i_piar = seq [ i_swap ; i_pair ]
|
|
||||||
let i_push ty code = prim ~children:[ty;code] I_PUSH
|
|
||||||
let i_push_unit = i_push t_unit d_unit
|
|
||||||
let i_push_string str = i_push t_string (string str)
|
|
||||||
let i_none ty = prim ~children:[ty] I_NONE
|
|
||||||
let i_nil ty = prim ~children:[ty] I_NIL
|
|
||||||
let i_some = prim I_SOME
|
|
||||||
let i_lambda arg ret body = prim ~children:[arg;ret;body] I_LAMBDA
|
|
||||||
let i_empty_map src dst = prim ~children:[src;dst] I_EMPTY_MAP
|
|
||||||
let i_drop = prim I_DROP
|
|
||||||
let i_exec = prim I_EXEC
|
|
||||||
|
|
||||||
let i_if a b = prim ~children:[seq [a] ; seq[b]] I_IF
|
|
||||||
let i_if_none a b = prim ~children:[seq [a] ; seq[b]] I_IF_NONE
|
|
||||||
let i_if_left a b = prim ~children:[seq [a] ; seq[b]] I_IF_LEFT
|
|
||||||
let i_failwith = prim I_FAILWITH
|
|
||||||
let i_assert_some = i_if_none (seq [i_push_string "ASSERT_SOME" ; i_failwith]) (seq [])
|
|
||||||
let i_assert_some_msg msg = i_if_none (seq [msg ; i_failwith]) (seq [])
|
|
||||||
|
|
||||||
let dip code : michelson = prim ~children:[seq [code]] I_DIP
|
|
||||||
let i_unpair = seq [i_dup ; i_car ; dip i_cdr]
|
|
||||||
let i_unpiar = seq [i_dup ; i_cdr ; dip i_car]
|
|
||||||
|
|
||||||
let rec strip_annots : michelson -> michelson = function
|
|
||||||
| Seq(l, s) -> Seq(l, List.map strip_annots s)
|
|
||||||
| Prim (l, p, lst, _) -> Prim (l, p, List.map strip_annots lst, [])
|
|
||||||
| x -> x
|
|
||||||
|
|
||||||
let rec strip_nops : michelson -> michelson = function
|
|
||||||
| Seq(l, s) -> Seq(l, List.map strip_nops s)
|
|
||||||
| Prim (l, I_NOP, _, _) -> Seq (l, [])
|
|
||||||
| Prim (l, p, lst, a) -> Prim (l, p, List.map strip_nops lst, a)
|
|
||||||
| x -> x
|
|
||||||
|
|
||||||
let pp ppf (michelson:michelson) =
|
|
||||||
let open Micheline_printer in
|
|
||||||
let canonical = strip_locations michelson in
|
|
||||||
let node = printable string_of_prim canonical in
|
|
||||||
print_expr ppf node
|
|
||||||
|
|
||||||
let pp_stripped ppf (michelson:michelson) =
|
|
||||||
let open Micheline_printer in
|
|
||||||
let michelson' = strip_nops @@ strip_annots michelson in
|
|
||||||
let canonical = strip_locations michelson' in
|
|
||||||
let node = printable string_of_prim canonical in
|
|
||||||
print_expr ppf node
|
|
||||||
|
|
||||||
let pp_naked ppf m =
|
|
||||||
let naked = strip_annots m in
|
|
||||||
pp ppf naked
|
|
||||||
end
|
|
@ -185,7 +185,7 @@ end
|
|||||||
|
|
||||||
module Script : sig
|
module Script : sig
|
||||||
|
|
||||||
type prim = Michelson_v1_primitives.prim =
|
type prim = Micheline.Michelson_primitives.prim =
|
||||||
| K_parameter
|
| K_parameter
|
||||||
| K_storage
|
| K_storage
|
||||||
| K_code
|
| K_code
|
||||||
@ -300,6 +300,7 @@ module Script : sig
|
|||||||
| T_operation
|
| T_operation
|
||||||
| T_address
|
| T_address
|
||||||
|
|
||||||
|
|
||||||
type location = Micheline.canonical_location
|
type location = Micheline.canonical_location
|
||||||
|
|
||||||
type annot = Micheline.annot
|
type annot = Micheline.annot
|
||||||
|
@ -25,576 +25,20 @@
|
|||||||
|
|
||||||
open Micheline
|
open Micheline
|
||||||
|
|
||||||
type error += Unknown_primitive_name of string
|
include Michelson_primitives
|
||||||
type error += Invalid_case of string
|
|
||||||
type error += Invalid_primitive_name of string Micheline.canonical * Micheline.canonical_location
|
|
||||||
|
|
||||||
type prim =
|
type error += Unknown_primitive_name of string (* `Permanent *)
|
||||||
| K_parameter
|
type error += Invalid_case of string (* `Permanent *)
|
||||||
| K_storage
|
type error += Invalid_primitive_name of string Micheline.canonical * Micheline.canonical_location (* `Permanent *)
|
||||||
| K_code
|
|
||||||
| D_False
|
|
||||||
| D_Elt
|
|
||||||
| D_Left
|
|
||||||
| D_None
|
|
||||||
| D_Pair
|
|
||||||
| D_Right
|
|
||||||
| D_Some
|
|
||||||
| D_True
|
|
||||||
| D_Unit
|
|
||||||
| I_PACK
|
|
||||||
| I_UNPACK
|
|
||||||
| I_BLAKE2B
|
|
||||||
| I_SHA256
|
|
||||||
| I_SHA512
|
|
||||||
| I_ABS
|
|
||||||
| I_ADD
|
|
||||||
| I_AMOUNT
|
|
||||||
| I_AND
|
|
||||||
| I_BALANCE
|
|
||||||
| I_CAR
|
|
||||||
| I_CDR
|
|
||||||
| I_CHECK_SIGNATURE
|
|
||||||
| I_COMPARE
|
|
||||||
| I_CONCAT
|
|
||||||
| I_CONS
|
|
||||||
| I_CREATE_ACCOUNT
|
|
||||||
| I_CREATE_CONTRACT
|
|
||||||
| I_IMPLICIT_ACCOUNT
|
|
||||||
| I_DIP
|
|
||||||
| I_DROP
|
|
||||||
| I_DUP
|
|
||||||
| I_EDIV
|
|
||||||
| I_EMPTY_MAP
|
|
||||||
| I_EMPTY_SET
|
|
||||||
| I_EQ
|
|
||||||
| I_EXEC
|
|
||||||
| I_FAILWITH
|
|
||||||
| I_GE
|
|
||||||
| I_GET
|
|
||||||
| I_GT
|
|
||||||
| I_HASH_KEY
|
|
||||||
| I_IF
|
|
||||||
| I_IF_CONS
|
|
||||||
| I_IF_LEFT
|
|
||||||
| I_IF_NONE
|
|
||||||
| I_INT
|
|
||||||
| I_LAMBDA
|
|
||||||
| I_LE
|
|
||||||
| I_LEFT
|
|
||||||
| I_LOOP
|
|
||||||
| I_LSL
|
|
||||||
| I_LSR
|
|
||||||
| I_LT
|
|
||||||
| I_MAP
|
|
||||||
| I_MEM
|
|
||||||
| I_MUL
|
|
||||||
| I_NEG
|
|
||||||
| I_NEQ
|
|
||||||
| I_NIL
|
|
||||||
| I_NONE
|
|
||||||
| I_NOP
|
|
||||||
| I_NOT
|
|
||||||
| I_NOW
|
|
||||||
| I_OR
|
|
||||||
| I_PAIR
|
|
||||||
| I_PUSH
|
|
||||||
| I_RIGHT
|
|
||||||
| I_SIZE
|
|
||||||
| I_SOME
|
|
||||||
| I_SOURCE
|
|
||||||
| I_SENDER
|
|
||||||
| I_SELF
|
|
||||||
| I_SLICE
|
|
||||||
| I_STEPS_TO_QUOTA
|
|
||||||
| I_SUB
|
|
||||||
| I_SWAP
|
|
||||||
| I_TRANSFER_TOKENS
|
|
||||||
| I_SET_DELEGATE
|
|
||||||
| I_UNIT
|
|
||||||
| I_UPDATE
|
|
||||||
| I_XOR
|
|
||||||
| I_ITER
|
|
||||||
| I_LOOP_LEFT
|
|
||||||
| I_ADDRESS
|
|
||||||
| I_CONTRACT
|
|
||||||
| I_ISNAT
|
|
||||||
| I_CAST
|
|
||||||
| I_RENAME
|
|
||||||
| T_bool
|
|
||||||
| T_contract
|
|
||||||
| T_int
|
|
||||||
| T_key
|
|
||||||
| T_key_hash
|
|
||||||
| T_lambda
|
|
||||||
| T_list
|
|
||||||
| T_map
|
|
||||||
| T_big_map
|
|
||||||
| T_nat
|
|
||||||
| T_option
|
|
||||||
| T_or
|
|
||||||
| T_pair
|
|
||||||
| T_set
|
|
||||||
| T_signature
|
|
||||||
| T_string
|
|
||||||
| T_bytes
|
|
||||||
| T_mutez
|
|
||||||
| T_timestamp
|
|
||||||
| T_unit
|
|
||||||
| T_operation
|
|
||||||
| T_address
|
|
||||||
|
|
||||||
let valid_case name =
|
let prim_of_string x = match prim_of_string x with
|
||||||
let is_lower = function '_' | 'a'..'z' -> true | _ -> false in
|
| Ok x -> ok x
|
||||||
let is_upper = function '_' | 'A'..'Z' -> true | _ -> false in
|
| Error (Unknown_primitive_name x) -> error (Unknown_primitive_name x)
|
||||||
let rec for_all a b f =
|
| Error (Invalid_case x) -> error (Invalid_case x)
|
||||||
Compare.Int.(a > b) || f a && for_all (a + 1) b f in
|
| Error (Invalid_primitive_name (a , b)) -> error (Invalid_primitive_name (a , b))
|
||||||
let len = String.length name in
|
|
||||||
Compare.Int.(len <> 0)
|
|
||||||
&&
|
|
||||||
Compare.Char.(String.get name 0 <> '_')
|
|
||||||
&&
|
|
||||||
((is_upper (String.get name 0)
|
|
||||||
&& for_all 1 (len - 1) (fun i -> is_upper (String.get name i)))
|
|
||||||
||
|
|
||||||
(is_upper (String.get name 0)
|
|
||||||
&& for_all 1 (len - 1) (fun i -> is_lower (String.get name i)))
|
|
||||||
||
|
|
||||||
(is_lower (String.get name 0)
|
|
||||||
&& for_all 1 (len - 1) (fun i -> is_lower (String.get name i))))
|
|
||||||
|
|
||||||
let string_of_prim = function
|
let prims_of_strings x = match prims_of_strings x with
|
||||||
| K_parameter -> "parameter"
|
| Ok x -> ok x
|
||||||
| K_storage -> "storage"
|
| Error (Unknown_primitive_name x) -> error (Unknown_primitive_name x)
|
||||||
| K_code -> "code"
|
| Error (Invalid_case x) -> error (Invalid_case x)
|
||||||
| D_False -> "False"
|
| Error (Invalid_primitive_name (a , b)) -> error (Invalid_primitive_name (a , b))
|
||||||
| D_Elt -> "Elt"
|
|
||||||
| D_Left -> "Left"
|
|
||||||
| D_None -> "None"
|
|
||||||
| D_Pair -> "Pair"
|
|
||||||
| D_Right -> "Right"
|
|
||||||
| D_Some -> "Some"
|
|
||||||
| D_True -> "True"
|
|
||||||
| D_Unit -> "Unit"
|
|
||||||
| I_PACK -> "PACK"
|
|
||||||
| I_UNPACK -> "UNPACK"
|
|
||||||
| I_BLAKE2B -> "BLAKE2B"
|
|
||||||
| I_SHA256 -> "SHA256"
|
|
||||||
| I_SHA512 -> "SHA512"
|
|
||||||
| I_ABS -> "ABS"
|
|
||||||
| I_ADD -> "ADD"
|
|
||||||
| I_AMOUNT -> "AMOUNT"
|
|
||||||
| I_AND -> "AND"
|
|
||||||
| I_BALANCE -> "BALANCE"
|
|
||||||
| I_CAR -> "CAR"
|
|
||||||
| I_CDR -> "CDR"
|
|
||||||
| I_CHECK_SIGNATURE -> "CHECK_SIGNATURE"
|
|
||||||
| I_COMPARE -> "COMPARE"
|
|
||||||
| I_CONCAT -> "CONCAT"
|
|
||||||
| I_CONS -> "CONS"
|
|
||||||
| I_CREATE_ACCOUNT -> "CREATE_ACCOUNT"
|
|
||||||
| I_CREATE_CONTRACT -> "CREATE_CONTRACT"
|
|
||||||
| I_IMPLICIT_ACCOUNT -> "IMPLICIT_ACCOUNT"
|
|
||||||
| I_DIP -> "DIP"
|
|
||||||
| I_DROP -> "DROP"
|
|
||||||
| I_DUP -> "DUP"
|
|
||||||
| I_EDIV -> "EDIV"
|
|
||||||
| I_EMPTY_MAP -> "EMPTY_MAP"
|
|
||||||
| I_EMPTY_SET -> "EMPTY_SET"
|
|
||||||
| I_EQ -> "EQ"
|
|
||||||
| I_EXEC -> "EXEC"
|
|
||||||
| I_FAILWITH -> "FAILWITH"
|
|
||||||
| I_GE -> "GE"
|
|
||||||
| I_GET -> "GET"
|
|
||||||
| I_GT -> "GT"
|
|
||||||
| I_HASH_KEY -> "HASH_KEY"
|
|
||||||
| I_IF -> "IF"
|
|
||||||
| I_IF_CONS -> "IF_CONS"
|
|
||||||
| I_IF_LEFT -> "IF_LEFT"
|
|
||||||
| I_IF_NONE -> "IF_NONE"
|
|
||||||
| I_INT -> "INT"
|
|
||||||
| I_LAMBDA -> "LAMBDA"
|
|
||||||
| I_LE -> "LE"
|
|
||||||
| I_LEFT -> "LEFT"
|
|
||||||
| I_LOOP -> "LOOP"
|
|
||||||
| I_LSL -> "LSL"
|
|
||||||
| I_LSR -> "LSR"
|
|
||||||
| I_LT -> "LT"
|
|
||||||
| I_MAP -> "MAP"
|
|
||||||
| I_MEM -> "MEM"
|
|
||||||
| I_MUL -> "MUL"
|
|
||||||
| I_NEG -> "NEG"
|
|
||||||
| I_NEQ -> "NEQ"
|
|
||||||
| I_NIL -> "NIL"
|
|
||||||
| I_NONE -> "NONE"
|
|
||||||
| I_NOP -> "NOP"
|
|
||||||
| I_NOT -> "NOT"
|
|
||||||
| I_NOW -> "NOW"
|
|
||||||
| I_OR -> "OR"
|
|
||||||
| I_PAIR -> "PAIR"
|
|
||||||
| I_PUSH -> "PUSH"
|
|
||||||
| I_RIGHT -> "RIGHT"
|
|
||||||
| I_SIZE -> "SIZE"
|
|
||||||
| I_SOME -> "SOME"
|
|
||||||
| I_SOURCE -> "SOURCE"
|
|
||||||
| I_SENDER -> "SENDER"
|
|
||||||
| I_SELF -> "SELF"
|
|
||||||
| I_SLICE -> "SLICE"
|
|
||||||
| I_STEPS_TO_QUOTA -> "STEPS_TO_QUOTA"
|
|
||||||
| I_SUB -> "SUB"
|
|
||||||
| I_SWAP -> "SWAP"
|
|
||||||
| I_TRANSFER_TOKENS -> "TRANSFER_TOKENS"
|
|
||||||
| I_SET_DELEGATE -> "SET_DELEGATE"
|
|
||||||
| I_UNIT -> "UNIT"
|
|
||||||
| I_UPDATE -> "UPDATE"
|
|
||||||
| I_XOR -> "XOR"
|
|
||||||
| I_ITER -> "ITER"
|
|
||||||
| I_LOOP_LEFT -> "LOOP_LEFT"
|
|
||||||
| I_ADDRESS -> "ADDRESS"
|
|
||||||
| I_CONTRACT -> "CONTRACT"
|
|
||||||
| I_ISNAT -> "ISNAT"
|
|
||||||
| I_CAST -> "CAST"
|
|
||||||
| I_RENAME -> "RENAME"
|
|
||||||
| T_bool -> "bool"
|
|
||||||
| T_contract -> "contract"
|
|
||||||
| T_int -> "int"
|
|
||||||
| T_key -> "key"
|
|
||||||
| T_key_hash -> "key_hash"
|
|
||||||
| T_lambda -> "lambda"
|
|
||||||
| T_list -> "list"
|
|
||||||
| T_map -> "map"
|
|
||||||
| T_big_map -> "big_map"
|
|
||||||
| T_nat -> "nat"
|
|
||||||
| T_option -> "option"
|
|
||||||
| T_or -> "or"
|
|
||||||
| T_pair -> "pair"
|
|
||||||
| T_set -> "set"
|
|
||||||
| T_signature -> "signature"
|
|
||||||
| T_string -> "string"
|
|
||||||
| T_bytes -> "bytes"
|
|
||||||
| T_mutez -> "mutez"
|
|
||||||
| T_timestamp -> "timestamp"
|
|
||||||
| T_unit -> "unit"
|
|
||||||
| T_operation -> "operation"
|
|
||||||
| T_address -> "address"
|
|
||||||
|
|
||||||
let prim_of_string = function
|
|
||||||
| "parameter" -> ok K_parameter
|
|
||||||
| "storage" -> ok K_storage
|
|
||||||
| "code" -> ok K_code
|
|
||||||
| "False" -> ok D_False
|
|
||||||
| "Elt" -> ok D_Elt
|
|
||||||
| "Left" -> ok D_Left
|
|
||||||
| "None" -> ok D_None
|
|
||||||
| "Pair" -> ok D_Pair
|
|
||||||
| "Right" -> ok D_Right
|
|
||||||
| "Some" -> ok D_Some
|
|
||||||
| "True" -> ok D_True
|
|
||||||
| "Unit" -> ok D_Unit
|
|
||||||
| "PACK" -> ok I_PACK
|
|
||||||
| "UNPACK" -> ok I_UNPACK
|
|
||||||
| "BLAKE2B" -> ok I_BLAKE2B
|
|
||||||
| "SHA256" -> ok I_SHA256
|
|
||||||
| "SHA512" -> ok I_SHA512
|
|
||||||
| "ABS" -> ok I_ABS
|
|
||||||
| "ADD" -> ok I_ADD
|
|
||||||
| "AMOUNT" -> ok I_AMOUNT
|
|
||||||
| "AND" -> ok I_AND
|
|
||||||
| "BALANCE" -> ok I_BALANCE
|
|
||||||
| "CAR" -> ok I_CAR
|
|
||||||
| "CDR" -> ok I_CDR
|
|
||||||
| "CHECK_SIGNATURE" -> ok I_CHECK_SIGNATURE
|
|
||||||
| "COMPARE" -> ok I_COMPARE
|
|
||||||
| "CONCAT" -> ok I_CONCAT
|
|
||||||
| "CONS" -> ok I_CONS
|
|
||||||
| "CREATE_ACCOUNT" -> ok I_CREATE_ACCOUNT
|
|
||||||
| "CREATE_CONTRACT" -> ok I_CREATE_CONTRACT
|
|
||||||
| "IMPLICIT_ACCOUNT" -> ok I_IMPLICIT_ACCOUNT
|
|
||||||
| "DIP" -> ok I_DIP
|
|
||||||
| "DROP" -> ok I_DROP
|
|
||||||
| "DUP" -> ok I_DUP
|
|
||||||
| "EDIV" -> ok I_EDIV
|
|
||||||
| "EMPTY_MAP" -> ok I_EMPTY_MAP
|
|
||||||
| "EMPTY_SET" -> ok I_EMPTY_SET
|
|
||||||
| "EQ" -> ok I_EQ
|
|
||||||
| "EXEC" -> ok I_EXEC
|
|
||||||
| "FAILWITH" -> ok I_FAILWITH
|
|
||||||
| "GE" -> ok I_GE
|
|
||||||
| "GET" -> ok I_GET
|
|
||||||
| "GT" -> ok I_GT
|
|
||||||
| "HASH_KEY" -> ok I_HASH_KEY
|
|
||||||
| "IF" -> ok I_IF
|
|
||||||
| "IF_CONS" -> ok I_IF_CONS
|
|
||||||
| "IF_LEFT" -> ok I_IF_LEFT
|
|
||||||
| "IF_NONE" -> ok I_IF_NONE
|
|
||||||
| "INT" -> ok I_INT
|
|
||||||
| "LAMBDA" -> ok I_LAMBDA
|
|
||||||
| "LE" -> ok I_LE
|
|
||||||
| "LEFT" -> ok I_LEFT
|
|
||||||
| "LOOP" -> ok I_LOOP
|
|
||||||
| "LSL" -> ok I_LSL
|
|
||||||
| "LSR" -> ok I_LSR
|
|
||||||
| "LT" -> ok I_LT
|
|
||||||
| "MAP" -> ok I_MAP
|
|
||||||
| "MEM" -> ok I_MEM
|
|
||||||
| "MUL" -> ok I_MUL
|
|
||||||
| "NEG" -> ok I_NEG
|
|
||||||
| "NEQ" -> ok I_NEQ
|
|
||||||
| "NIL" -> ok I_NIL
|
|
||||||
| "NONE" -> ok I_NONE
|
|
||||||
| "NOP" -> ok I_NOP
|
|
||||||
| "NOT" -> ok I_NOT
|
|
||||||
| "NOW" -> ok I_NOW
|
|
||||||
| "OR" -> ok I_OR
|
|
||||||
| "PAIR" -> ok I_PAIR
|
|
||||||
| "PUSH" -> ok I_PUSH
|
|
||||||
| "RIGHT" -> ok I_RIGHT
|
|
||||||
| "SIZE" -> ok I_SIZE
|
|
||||||
| "SOME" -> ok I_SOME
|
|
||||||
| "SOURCE" -> ok I_SOURCE
|
|
||||||
| "SENDER" -> ok I_SENDER
|
|
||||||
| "SELF" -> ok I_SELF
|
|
||||||
| "SLICE" -> ok I_SLICE
|
|
||||||
| "STEPS_TO_QUOTA" -> ok I_STEPS_TO_QUOTA
|
|
||||||
| "SUB" -> ok I_SUB
|
|
||||||
| "SWAP" -> ok I_SWAP
|
|
||||||
| "TRANSFER_TOKENS" -> ok I_TRANSFER_TOKENS
|
|
||||||
| "SET_DELEGATE" -> ok I_SET_DELEGATE
|
|
||||||
| "UNIT" -> ok I_UNIT
|
|
||||||
| "UPDATE" -> ok I_UPDATE
|
|
||||||
| "XOR" -> ok I_XOR
|
|
||||||
| "ITER" -> ok I_ITER
|
|
||||||
| "LOOP_LEFT" -> ok I_LOOP_LEFT
|
|
||||||
| "ADDRESS" -> ok I_ADDRESS
|
|
||||||
| "CONTRACT" -> ok I_CONTRACT
|
|
||||||
| "ISNAT" -> ok I_ISNAT
|
|
||||||
| "CAST" -> ok I_CAST
|
|
||||||
| "RENAME" -> ok I_RENAME
|
|
||||||
| "bool" -> ok T_bool
|
|
||||||
| "contract" -> ok T_contract
|
|
||||||
| "int" -> ok T_int
|
|
||||||
| "key" -> ok T_key
|
|
||||||
| "key_hash" -> ok T_key_hash
|
|
||||||
| "lambda" -> ok T_lambda
|
|
||||||
| "list" -> ok T_list
|
|
||||||
| "map" -> ok T_map
|
|
||||||
| "big_map" -> ok T_big_map
|
|
||||||
| "nat" -> ok T_nat
|
|
||||||
| "option" -> ok T_option
|
|
||||||
| "or" -> ok T_or
|
|
||||||
| "pair" -> ok T_pair
|
|
||||||
| "set" -> ok T_set
|
|
||||||
| "signature" -> ok T_signature
|
|
||||||
| "string" -> ok T_string
|
|
||||||
| "bytes" -> ok T_bytes
|
|
||||||
| "mutez" -> ok T_mutez
|
|
||||||
| "timestamp" -> ok T_timestamp
|
|
||||||
| "unit" -> ok T_unit
|
|
||||||
| "operation" -> ok T_operation
|
|
||||||
| "address" -> ok T_address
|
|
||||||
| n ->
|
|
||||||
if valid_case n then
|
|
||||||
error (Unknown_primitive_name n)
|
|
||||||
else
|
|
||||||
error (Invalid_case n)
|
|
||||||
|
|
||||||
let prims_of_strings expr =
|
|
||||||
let rec convert = function
|
|
||||||
| Int _ | String _ | Bytes _ as expr -> ok expr
|
|
||||||
| Prim (loc, prim, args, annot) ->
|
|
||||||
Error_monad.record_trace
|
|
||||||
(Invalid_primitive_name (expr, loc))
|
|
||||||
(prim_of_string prim) >>? fun prim ->
|
|
||||||
List.fold_left
|
|
||||||
(fun acc arg ->
|
|
||||||
acc >>? fun args ->
|
|
||||||
convert arg >>? fun arg ->
|
|
||||||
ok (arg :: args))
|
|
||||||
(ok []) args >>? fun args ->
|
|
||||||
ok (Prim (0, prim, List.rev args, annot))
|
|
||||||
| Seq (_, args) ->
|
|
||||||
List.fold_left
|
|
||||||
(fun acc arg ->
|
|
||||||
acc >>? fun args ->
|
|
||||||
convert arg >>? fun arg ->
|
|
||||||
ok (arg :: args))
|
|
||||||
(ok []) args >>? fun args ->
|
|
||||||
ok (Seq (0, List.rev args)) in
|
|
||||||
convert (root expr) >>? fun expr ->
|
|
||||||
ok (strip_locations expr)
|
|
||||||
|
|
||||||
let strings_of_prims expr =
|
|
||||||
let rec convert = function
|
|
||||||
| Int _ | String _ | Bytes _ as expr -> expr
|
|
||||||
| Prim (_, prim, args, annot) ->
|
|
||||||
let prim = string_of_prim prim in
|
|
||||||
let args = List.map convert args in
|
|
||||||
Prim (0, prim, args, annot)
|
|
||||||
| Seq (_, args) ->
|
|
||||||
let args = List.map convert args in
|
|
||||||
Seq (0, args) in
|
|
||||||
strip_locations (convert (root expr))
|
|
||||||
|
|
||||||
let prim_encoding =
|
|
||||||
let open Data_encoding in
|
|
||||||
def "michelson.v1.primitives" @@
|
|
||||||
string_enum [
|
|
||||||
("parameter", K_parameter) ;
|
|
||||||
("storage", K_storage) ;
|
|
||||||
("code", K_code) ;
|
|
||||||
("False", D_False) ;
|
|
||||||
("Elt", D_Elt) ;
|
|
||||||
("Left", D_Left) ;
|
|
||||||
("None", D_None) ;
|
|
||||||
("Pair", D_Pair) ;
|
|
||||||
("Right", D_Right) ;
|
|
||||||
("Some", D_Some) ;
|
|
||||||
("True", D_True) ;
|
|
||||||
("Unit", D_Unit) ;
|
|
||||||
("PACK", I_PACK) ;
|
|
||||||
("UNPACK", I_UNPACK) ;
|
|
||||||
("BLAKE2B", I_BLAKE2B) ;
|
|
||||||
("SHA256", I_SHA256) ;
|
|
||||||
("SHA512", I_SHA512) ;
|
|
||||||
("ABS", I_ABS) ;
|
|
||||||
("ADD", I_ADD) ;
|
|
||||||
("AMOUNT", I_AMOUNT) ;
|
|
||||||
("AND", I_AND) ;
|
|
||||||
("BALANCE", I_BALANCE) ;
|
|
||||||
("CAR", I_CAR) ;
|
|
||||||
("CDR", I_CDR) ;
|
|
||||||
("CHECK_SIGNATURE", I_CHECK_SIGNATURE) ;
|
|
||||||
("COMPARE", I_COMPARE) ;
|
|
||||||
("CONCAT", I_CONCAT) ;
|
|
||||||
("CONS", I_CONS) ;
|
|
||||||
("CREATE_ACCOUNT", I_CREATE_ACCOUNT) ;
|
|
||||||
("CREATE_CONTRACT", I_CREATE_CONTRACT) ;
|
|
||||||
("IMPLICIT_ACCOUNT", I_IMPLICIT_ACCOUNT) ;
|
|
||||||
("DIP", I_DIP) ;
|
|
||||||
("DROP", I_DROP) ;
|
|
||||||
("DUP", I_DUP) ;
|
|
||||||
("EDIV", I_EDIV) ;
|
|
||||||
("EMPTY_MAP", I_EMPTY_MAP) ;
|
|
||||||
("EMPTY_SET", I_EMPTY_SET) ;
|
|
||||||
("EQ", I_EQ) ;
|
|
||||||
("EXEC", I_EXEC) ;
|
|
||||||
("FAILWITH", I_FAILWITH) ;
|
|
||||||
("GE", I_GE) ;
|
|
||||||
("GET", I_GET) ;
|
|
||||||
("GT", I_GT) ;
|
|
||||||
("HASH_KEY", I_HASH_KEY) ;
|
|
||||||
("IF", I_IF) ;
|
|
||||||
("IF_CONS", I_IF_CONS) ;
|
|
||||||
("IF_LEFT", I_IF_LEFT) ;
|
|
||||||
("IF_NONE", I_IF_NONE) ;
|
|
||||||
("INT", I_INT) ;
|
|
||||||
("LAMBDA", I_LAMBDA) ;
|
|
||||||
("LE", I_LE) ;
|
|
||||||
("LEFT", I_LEFT) ;
|
|
||||||
("LOOP", I_LOOP) ;
|
|
||||||
("LSL", I_LSL) ;
|
|
||||||
("LSR", I_LSR) ;
|
|
||||||
("LT", I_LT) ;
|
|
||||||
("MAP", I_MAP) ;
|
|
||||||
("MEM", I_MEM) ;
|
|
||||||
("MUL", I_MUL) ;
|
|
||||||
("NEG", I_NEG) ;
|
|
||||||
("NEQ", I_NEQ) ;
|
|
||||||
("NIL", I_NIL) ;
|
|
||||||
("NONE", I_NONE) ;
|
|
||||||
("NOT", I_NOT) ;
|
|
||||||
("NOW", I_NOW) ;
|
|
||||||
("OR", I_OR) ;
|
|
||||||
("PAIR", I_PAIR) ;
|
|
||||||
("PUSH", I_PUSH) ;
|
|
||||||
("RIGHT", I_RIGHT) ;
|
|
||||||
("SIZE", I_SIZE) ;
|
|
||||||
("SOME", I_SOME) ;
|
|
||||||
("SOURCE", I_SOURCE) ;
|
|
||||||
("SENDER", I_SENDER) ;
|
|
||||||
("SELF", I_SELF) ;
|
|
||||||
("STEPS_TO_QUOTA", I_STEPS_TO_QUOTA) ;
|
|
||||||
("SUB", I_SUB) ;
|
|
||||||
("SWAP", I_SWAP) ;
|
|
||||||
("TRANSFER_TOKENS", I_TRANSFER_TOKENS) ;
|
|
||||||
("SET_DELEGATE", I_SET_DELEGATE) ;
|
|
||||||
("UNIT", I_UNIT) ;
|
|
||||||
("UPDATE", I_UPDATE) ;
|
|
||||||
("XOR", I_XOR) ;
|
|
||||||
("ITER", I_ITER) ;
|
|
||||||
("LOOP_LEFT", I_LOOP_LEFT) ;
|
|
||||||
("ADDRESS", I_ADDRESS) ;
|
|
||||||
("CONTRACT", I_CONTRACT) ;
|
|
||||||
("ISNAT", I_ISNAT) ;
|
|
||||||
("CAST", I_CAST) ;
|
|
||||||
("RENAME", I_RENAME) ;
|
|
||||||
("bool", T_bool) ;
|
|
||||||
("contract", T_contract) ;
|
|
||||||
("int", T_int) ;
|
|
||||||
("key", T_key) ;
|
|
||||||
("key_hash", T_key_hash) ;
|
|
||||||
("lambda", T_lambda) ;
|
|
||||||
("list", T_list) ;
|
|
||||||
("map", T_map) ;
|
|
||||||
("big_map", T_big_map) ;
|
|
||||||
("nat", T_nat) ;
|
|
||||||
("option", T_option) ;
|
|
||||||
("or", T_or) ;
|
|
||||||
("pair", T_pair) ;
|
|
||||||
("set", T_set) ;
|
|
||||||
("signature", T_signature) ;
|
|
||||||
("string", T_string) ;
|
|
||||||
("bytes", T_bytes) ;
|
|
||||||
("mutez", T_mutez) ;
|
|
||||||
("timestamp", T_timestamp) ;
|
|
||||||
("unit", T_unit) ;
|
|
||||||
("operation", T_operation) ;
|
|
||||||
("address", T_address) ;
|
|
||||||
(* Alpha_002 addition *)
|
|
||||||
("SLICE", I_SLICE) ;
|
|
||||||
]
|
|
||||||
|
|
||||||
let () =
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"unknownPrimitiveNameTypeError"
|
|
||||||
~title: "Unknown primitive name (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"In a script or data expression, a primitive was unknown."
|
|
||||||
~pp:(fun ppf n -> Format.fprintf ppf "Unknown primitive %s." n)
|
|
||||||
Data_encoding.(obj1 (req "wrongPrimitiveName" string))
|
|
||||||
(function
|
|
||||||
| Unknown_primitive_name got -> Some got
|
|
||||||
| _ -> None)
|
|
||||||
(fun got ->
|
|
||||||
Unknown_primitive_name got) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"invalidPrimitiveNameCaseTypeError"
|
|
||||||
~title: "Invalid primitive name case (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"In a script or data expression, a primitive name is \
|
|
||||||
neither uppercase, lowercase or capitalized."
|
|
||||||
~pp:(fun ppf n -> Format.fprintf ppf "Primitive %s has invalid case." n)
|
|
||||||
Data_encoding.(obj1 (req "wrongPrimitiveName" string))
|
|
||||||
(function
|
|
||||||
| Invalid_case name -> Some name
|
|
||||||
| _ -> None)
|
|
||||||
(fun name ->
|
|
||||||
Invalid_case name) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"invalidPrimitiveNameTypeErro"
|
|
||||||
~title: "Invalid primitive name (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"In a script or data expression, a primitive name is \
|
|
||||||
unknown or has a wrong case."
|
|
||||||
~pp:(fun ppf _ -> Format.fprintf ppf "Invalid primitive.")
|
|
||||||
Data_encoding.(obj2
|
|
||||||
(req "expression" (Micheline.canonical_encoding ~variant:"generic" string))
|
|
||||||
(req "location" Micheline.canonical_location_encoding))
|
|
||||||
(function
|
|
||||||
| Invalid_primitive_name (expr, loc) -> Some (expr, loc)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (expr, loc) ->
|
|
||||||
Invalid_primitive_name (expr, loc))
|
|
||||||
|
@ -27,7 +27,7 @@ type error += Unknown_primitive_name of string (* `Permanent *)
|
|||||||
type error += Invalid_case of string (* `Permanent *)
|
type error += Invalid_case of string (* `Permanent *)
|
||||||
type error += Invalid_primitive_name of string Micheline.canonical * Micheline.canonical_location (* `Permanent *)
|
type error += Invalid_primitive_name of string Micheline.canonical * Micheline.canonical_location (* `Permanent *)
|
||||||
|
|
||||||
type prim =
|
type prim = Micheline.Michelson_primitives.prim =
|
||||||
| K_parameter
|
| K_parameter
|
||||||
| K_storage
|
| K_storage
|
||||||
| K_code
|
| K_code
|
||||||
|
Loading…
Reference in New Issue
Block a user