Revision 5f92df59c8ea01930d2e9e1d238806885fb2d591 authored by Raphaƫl Proust on 27 June 2019, 00:19:25 UTC, committed by Pierre Boutillier on 21 October 2019, 12:25:24 UTC
The Michelson documentation states that `COMPARE` pushes -1 (resp. 1) if the top element of the stack is smaller (resp. greater) than the second. However, the implementation can actually push a negative number instead of -1 and a positive number instead of 1 depending on the type and values. This semantics should not break any code as the result of `COMPARE` is almost always comsumed by comparison projectors such as `GT` or `LT` who only care about the sign. However, for the sake of consistency, this patches makes `COMPARE` return only -1, 0 or 1. This fixes issue #546
1 parent 36fbc8d
irmin.ml
(*
* Copyright (c) 2013-2017 Thomas Gazagnaire <thomas@gazagnaire.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)
open Lwt.Infix
module Type = Type
module Diff = Diff
module Content_addressable = Store.Content_addressable
module Contents = struct
include Contents
module type S = S.CONTENTS
module type STORE = S.CONTENTS_STORE
end
module Merge = Merge
module Branch = struct
include Branch
module type S = S.BRANCH
module type STORE = S.BRANCH_STORE
end
module Info = Info
module Dot = Dot.Make
module Hash = struct
include Hash
module type S = S.HASH
module type TYPED = S.TYPED_HASH
end
module Path = struct
include Path
module type S = S.PATH
end
exception Closed
module CA_check_closed (CA : S.CONTENT_ADDRESSABLE_STORE_MAKER) :
S.CONTENT_ADDRESSABLE_STORE_MAKER =
functor
(K : S.HASH)
(V : Type.S)
->
struct
module S = CA (K) (V)
type 'a t = { closed : bool ref; t : 'a S.t }
type key = S.key
type value = S.value
let check_closed t = if !(t.closed) then raise Closed
let mem t k =
check_closed t;
S.mem t.t k
let find t k =
check_closed t;
S.find t.t k
let add t v =
check_closed t;
S.add t.t v
let unsafe_add t k v =
check_closed t;
S.unsafe_add t.t k v
let batch t f =
check_closed t;
S.batch t.t (fun w -> f { t = w; closed = t.closed })
let v conf = S.v conf >|= fun t -> { closed = ref false; t }
let close t =
if !(t.closed) then Lwt.return_unit
else (
t.closed := true;
S.close t.t )
end
module AW_check_closed (AW : S.ATOMIC_WRITE_STORE_MAKER) :
S.ATOMIC_WRITE_STORE_MAKER =
functor
(K : Type.S)
(V : Type.S)
->
struct
module S = AW (K) (V)
type t = { closed : bool ref; t : S.t }
type key = S.key
type value = S.value
let check_closed t = if !(t.closed) then raise Closed
let mem t k =
check_closed t;
S.mem t.t k
let find t k =
check_closed t;
S.find t.t k
let set t k v =
check_closed t;
S.set t.t k v
let test_and_set t k ~test ~set =
check_closed t;
S.test_and_set t.t k ~test ~set
let remove t k =
check_closed t;
S.remove t.t k
let list t =
check_closed t;
S.list t.t
type watch = S.watch
let watch t ?init f =
check_closed t;
S.watch t.t ?init f
let watch_key t k ?init f =
check_closed t;
S.watch_key t.t k ?init f
let unwatch t w =
check_closed t;
S.unwatch t.t w
let v conf = S.v conf >|= fun t -> { closed = ref false; t }
let close t =
if !(t.closed) then Lwt.return_unit
else (
t.closed := true;
S.close t.t )
end
module Make_ext
(CA : S.CONTENT_ADDRESSABLE_STORE_MAKER)
(AW : S.ATOMIC_WRITE_STORE_MAKER)
(M : S.METADATA)
(C : Contents.S)
(P : Path.S)
(B : Branch.S)
(H : Hash.S)
(N : S.NODE
with type metadata = M.t
and type hash = H.t
and type step = P.step)
(CT : S.COMMIT with type hash = H.t) =
struct
module CA = CA_check_closed (CA)
module AW = AW_check_closed (AW)
module X = struct
module Hash = H
module Contents = struct
module CA = struct
module Key = Hash
module Val = C
include CA (Key) (Val)
end
include Contents.Store (CA)
end
module Node = struct
module CA = struct
module Key = Hash
module Val = N
include CA (Key) (Val)
end
include Node.Store (Contents) (P) (M) (CA)
end
module Commit = struct
module CA = struct
module Key = Hash
module Val = CT
include CA (Key) (Val)
end
include Commit.Store (Node) (CA)
end
module Branch = struct
module Key = B
module Val = H
include AW (Key) (Val)
end
module Slice = Slice.Make (Contents) (Node) (Commit)
module Sync = Sync.None (H) (B)
module Repo = struct
type t = {
config : Conf.t;
contents : [ `Read ] Contents.t;
nodes : [ `Read ] Node.t;
commits : [ `Read ] Commit.t;
branch : Branch.t;
}
let contents_t t = t.contents
let node_t t = t.nodes
let commit_t t = t.commits
let branch_t t = t.branch
let batch t f =
Contents.CA.batch t.contents @@ fun c ->
Node.CA.batch (snd t.nodes) @@ fun n ->
Commit.CA.batch (snd t.commits) @@ fun ct ->
let contents_t = c in
let node_t = (contents_t, n) in
let commit_t = (node_t, ct) in
f contents_t node_t commit_t
let v config =
Contents.CA.v config >>= fun contents ->
Node.CA.v config >>= fun nodes ->
Commit.CA.v config >>= fun commits ->
let nodes = (contents, nodes) in
let commits = (nodes, commits) in
Branch.v config >|= fun branch ->
{ contents; nodes; commits; branch; config }
let close t =
Contents.CA.close t.contents >>= fun () ->
Node.CA.close (snd t.nodes) >>= fun () ->
Commit.CA.close (snd t.commits) >>= fun () -> Branch.close t.branch
end
end
include Store.Make (X)
end
module Make
(CA : S.CONTENT_ADDRESSABLE_STORE_MAKER)
(AW : S.ATOMIC_WRITE_STORE_MAKER)
(M : S.METADATA)
(C : S.CONTENTS)
(P : S.PATH)
(B : S.BRANCH)
(H : S.HASH) =
struct
module N = Node.Make (H) (P) (M)
module CT = Commit.Make (H)
include Make_ext (CA) (AW) (M) (C) (P) (B) (H) (N) (CT)
end
module Of_private = Store.Make
module type CONTENT_ADDRESSABLE_STORE = S.CONTENT_ADDRESSABLE_STORE
module type APPEND_ONLY_STORE = S.APPEND_ONLY_STORE
module type ATOMIC_WRITE_STORE = S.ATOMIC_WRITE_STORE
module type TREE = S.TREE
module type S = S.STORE
type config = Conf.t
type 'a diff = 'a Diff.t
module type CONTENT_ADDRESSABLE_STORE_MAKER = S.CONTENT_ADDRESSABLE_STORE_MAKER
module type APPEND_ONLY_STORE_MAKER = S.APPEND_ONLY_STORE_MAKER
module type ATOMIC_WRITE_STORE_MAKER = S.ATOMIC_WRITE_STORE_MAKER
module type S_MAKER = S.MAKER
module type KV =
S with type key = string list and type step = string and type branch = string
module type KV_MAKER = functor (C : Contents.S) -> KV with type contents = C.t
module Private = struct
module Conf = Conf
module Node = struct
include Node
module type S = S.NODE
module type GRAPH = S.NODE_GRAPH
module type STORE = S.NODE_STORE
end
module Commit = struct
include Commit
module type S = S.COMMIT
module type STORE = S.COMMIT_STORE
module type HISTORY = S.COMMIT_HISTORY
end
module Slice = struct
include Slice
module type S = S.SLICE
end
module Sync = struct
include Sync
module type S = S.SYNC
end
module type S = S.PRIVATE
module Watch = Watch
module Lock = Lock
end
let version = Version.current
module type SYNC = S.SYNC_STORE
module Sync = Sync_ext.Make
type remote = S.remote = ..
let remote_store (type t) (module M : S with type t = t) (t : t) =
let module X : S.STORE with type t = t = M in
Sync_ext.remote_store (module X) t
module Metadata = struct
module type S = S.METADATA
module None = Node.No_metadata
end
module Json_tree = Contents.Json_tree
Computing file changes ...