(**************************************************************************)
(*  This file is part of BINSEC.                                          *)
(*                                                                        *)
(*  Copyright (C) 2016-2024                                               *)
(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
(*         alternatives)                                                  *)
(*                                                                        *)
(*  you can redistribute it and/or modify it under the terms of the GNU   *)
(*  Lesser General Public License as published by the Free Software       *)
(*  Foundation, version 2.1.                                              *)
(*                                                                        *)
(*  It is distributed in the hope that it will be useful,                 *)
(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
(*  GNU Lesser General Public License for more details.                   *)
(*                                                                        *)
(*  See the GNU Lesser General Public License version 2.1                 *)
(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
(*                                                                        *)
(**************************************************************************)

module Integer = Z

module type Arity = sig
  (* Symbols and their arities. 'r represents the result type. *)
  type 'r ar0
  type ('a, 'r) ar1
  type ('a, 'b, 'r) ar2
  type ('a, 'b, 'c, 'r) ar3
  type ('a, 'r) variadic
end

(* Note: in the following, we distinguish between backward and forward
   because there is no need to implement backward transfer functions
   for symbols with arity 0. *)

(****************************************************************)
(* Boolean transfer functions.  *)

module type Boolean_Backward = sig
  type boolean

  module Arity : Arity

  val not : (boolean, boolean) Arity.ar1
  val ( && ) : (boolean, boolean, boolean) Arity.ar2
  val ( || ) : (boolean, boolean, boolean) Arity.ar2
end

module type Boolean_Forward = sig
  include Boolean_Backward

  val true_ : boolean Arity.ar0
  val false_ : boolean Arity.ar0
end

(****************************************************************)
(* Binary transfer functions.  *)

(* Note: the size argument, when provided, refers to the size of the
   result. *)
module type Binary_Backward = sig
  type binary
  type boolean

  module Arity : Arity

  val biadd : size:int -> (binary, binary, binary) Arity.ar2
  val bisub : size:int -> (binary, binary, binary) Arity.ar2
  val bimul : size:int -> (binary, binary, binary) Arity.ar2
  val beq : size:int -> (binary, binary, boolean) Arity.ar2
  val bisle : size:int -> (binary, binary, boolean) Arity.ar2
  val bislt : size:int -> (binary, binary, boolean) Arity.ar2
  val biule : size:int -> (binary, binary, boolean) Arity.ar2
  val biult : size:int -> (binary, binary, boolean) Arity.ar2

  (* First argument become most significant. *)
  val bconcat : size1:int -> size2:int -> (binary, binary, binary) Arity.ar2
  val bextract : lo:int -> hi:int -> oldsize:int -> (binary, binary) Arity.ar1
  val band : size:int -> (binary, binary, binary) Arity.ar2
  val bor : size:int -> (binary, binary, binary) Arity.ar2
  val bxor : size:int -> (binary, binary, binary) Arity.ar2
  val buext : size:int -> oldsize:int -> (binary, binary) Arity.ar1
  val bsext : size:int -> oldsize:int -> (binary, binary) Arity.ar1

  (* Correspond to truncated division, used in C99 and processors. *)
  val bisdiv : size:int -> (binary, binary, binary) Arity.ar2
  val bisrem : size:int -> (binary, binary, binary) Arity.ar2
  val biudiv : size:int -> (binary, binary, binary) Arity.ar2
  val biurem : size:int -> (binary, binary, binary) Arity.ar2
  val bshl : size:int -> (binary, binary, binary) Arity.ar2
  val bashr : size:int -> (binary, binary, binary) Arity.ar2
  val blshr : size:int -> (binary, binary, binary) Arity.ar2
  val bv_left_rotate : size:int -> (binary, binary, binary) Arity.ar2
  val bv_right_rotate : size:int -> (binary, binary, binary) Arity.ar2
end

module type Binary_Forward = sig
  include Binary_Backward

  val biconst : size:int -> Integer.t -> binary Arity.ar0
end
