# Module type `Theory.Basic`

The Basic theory of bitvector machines.

The Basic theory could be derived from the `Minimal` theory using the Basic functor.

`include Minimal`
`include Init`
`val var : 'a var -> 'a pure`

`var v` is the value of the variable `v`.

`val unk : 'a Value.sort -> 'a pure`

`unk s` an unknown value of sort `s`.

This term explicitly denotes a term with undefined or unknown value.

`val let_ : 'a var -> 'a pure -> 'b pure -> 'b pure`

`let_ v exp body` bind the value of `exp` to `v` `body`.

`val ite : bool -> 'a pure -> 'a pure -> 'a pure`

`ite c x y` is `x` if `c` evaluates to `b1` else `y`.

`include Bool`
`val b0 : bool`

`b0` is `false` aka `0` bit

`val b1 : bool`

`b1` is `true` aka `1` bit

`val inv : bool -> bool`

`inv x` inverts `x`.

`val and_ : bool -> bool -> bool`

`and_ x y` is a conjunction of `x` and `y`.

`val or_ : bool -> bool -> bool`

`or_ x y` is a disjunction of `x` and `y`.

`include Bitv`
`val int : 's Bitv.t Value.sort -> word -> 's bitv`

`int s x` is a bitvector constant `x` of sort `s`.

`val msb : 's bitv -> bool`

`msb x` is the most significant bit of `x`.

`val lsb : 's bitv -> bool`

`lsb x` is the least significant bit of `x`.

`val neg : 's bitv -> 's bitv`

`neg x` is two-complement unary minus

`val not : 's bitv -> 's bitv`

`not x` is one-complement negation.

`val add : 's bitv -> 's bitv -> 's bitv`

`add x y` addition modulo `2^'s`

`val sub : 's bitv -> 's bitv -> 's bitv`

`sub x y` subtraction modulo `2^'s`

`val mul : 's bitv -> 's bitv -> 's bitv`

`mul x y` multiplication modulo `2^'s`

`val div : 's bitv -> 's bitv -> 's bitv`

`div x y` unsigned division modulo `2^'s` truncating towards 0.

The division by zero is defined to be a vector of all ones of size `'s`.

`val sdiv : 's bitv -> 's bitv -> 's bitv`

`sdiv x y` is signed division of `x` by `y` modulo `2^'s`,

The signed division operator is defined in terms of the `div` operator as follows:

```                             /
| div x y : if not mx /\ not my
| neg (div (neg x) y) if mx /\ not my
x sdiv y = <
| neg (div x (neg y)) if not mx /\ my
| div (neg x) (neg y) if mx /\ my
\

where mx = msb x, and my = msb y.```
`val modulo : 's bitv -> 's bitv -> 's bitv`

`modulo x y` is the remainder of `div x y` modulo `2^'s`.

`val smodulo : 's bitv -> 's bitv -> 's bitv`

`smodulo x y` is the signed remainder of `div x y` modulo `2^'s`.

This version of the signed remainder where the sign follows the dividend, and is defined via the `% = modulo` operation as follows

```                           /
| x % y : if not mx /\ not my
| neg (neg x % y) if mx /\ not my
x smodulo y = <
| neg (x % (neg y)) if not mx /\ my
| neg (neg x % neg y) mod m if mx /\ my
\

where mx = msb x  and my = msb y.```
`val logand : 's bitv -> 's bitv -> 's bitv`

`logand x y` is a bitwise logical and of `x` and `y`.

`val logor : 's bitv -> 's bitv -> 's bitv`

`logor x y` is a bitwise logical or of `x` and `y`.

`val logxor : 's bitv -> 's bitv -> 's bitv`

`logxor x y` is a bitwise logical xor of `x` and `y`.

`val shiftr : bool -> 's bitv -> 'b bitv -> 's bitv`

`shiftr s x m` shifts `x` right by `m` bits filling with `s`.

`val shiftl : bool -> 's bitv -> 'b bitv -> 's bitv`

`shiftl s x m` shifts `x` left by `m` bits filling with `s`.

`val sle : 'a bitv -> 'a bitv -> bool`

`sle x y` binary predicate for singed less than or equal

`val ule : 'a bitv -> 'a bitv -> bool`

`ule x y` binary predicate for unsigned less than or equal

`val cast : 'a Bitv.t Value.sort -> bool -> 'b bitv -> 'a bitv`

`cast s b x` casts `x` to sort `s` filling with `b`.

If `m = size s - size (sort b) > 0` then `m` bits `b` are prepended to the most significant part of the vector.

Otherwise, if `m <= 0`, i.e., it is a narrowing cast, then the value of `b` doesn't affect the result of evaluation.

`val concat : 'a Bitv.t Value.sort -> 'b bitv list -> 'a bitv`

`concat s xs` concatenates a list of vectors `xs`.

All vectors are concatenated from left to right (so that the most significant bits of the resulting vector are defined by the first element of the list and so on).

The result of concatenation are then casted to sort `s` with all extra bits (if any) set to `zero`.

`val append : 'a Bitv.t Value.sort -> 'b bitv -> 'c bitv -> 'a bitv`

`append s x y` appends `x` and `y` and casts to `s`.

Appends `x` and `y` so that in the resulting vector the vector `x` occupies the most significant part and `y` the least significant part. The resulting vector is then casted to the sort `s` with extra bits (if any) set to zero.

`include Memory`
`val load : ('a, 'b) mem -> 'a bitv -> 'b bitv`

`load m k` is the value associated with the key `k` in the memory `m`.

`val store : ('a, 'b) mem -> 'a bitv -> 'b bitv -> ('a, 'b) mem`

`store m k x` a memory `m` in which the key `k` is associated with the word `x`.

`include Effect`
`val perform : 'a Effect.sort -> 'a eff`

`perform s` performs a generic effect of sort `s`.

`val set : 'a var -> 'a pure -> data eff`

`set v x` changes the value stored in `v` to the value of `x`.

`val jmp : _ bitv -> ctrl eff`

`jmp dst` passes the control to a program located at `dst`.

`val goto : label -> ctrl eff`

`goto lbl` passes the control to a program labeled with `lbl`.

`val seq : 'a eff -> 'a eff -> 'a eff`

`seq x y` performs effect `x`, after that perform effect `y`.

`val blk : label -> data eff -> ctrl eff -> unit eff`

`blk lbl data ctrl` an optionally labeled sequence of effects.

If `lbl` is `Label.null` then the block is unlabeled. If it is not `Label.null` then the denotations will preserve the label and assume that this `blk` is referenced from some other blocks.

• since 2.4.0 the [blk] operator accepts (and welcomes)

`Label.null` as the label in cases when the block is not really expected to be called from anywhere else.

`val repeat : bool -> data eff -> data eff`

`repeat c data` repeats data effects until the condition `c` holds.

`val branch : bool -> 'a eff -> 'a eff -> 'a eff`

`branch c lhs rhs` if `c` holds then performs `lhs` else `rhs`.

`val zero : 'a Bitv.t Value.sort -> 'a bitv`

`zero s` creates a bitvector of all zeros of sort `s`.

`val is_zero : 'a bitv -> bool`

`is_zero x` holds if `x` is a bitvector of all zeros

`val non_zero : 'a bitv -> bool`

`non_zero x` holds if `x` is not a zero bitvector.

`val succ : 'a bitv -> 'a bitv`

`succ x` is the successor of `x`.

`val pred : 'a bitv -> 'a bitv`

`pred x` is the predecessor of `x`.

`val nsucc : 'a bitv -> int -> 'a bitv`

`nsucc x n` is the `n`th successor of `x`.

`val npred : 'a bitv -> int -> 'a bitv`

`npred x` is the `n`th predecessor of `x`.

`val high : 'a Bitv.t Value.sort -> 'b bitv -> 'a bitv`

`high s x` is the high cast of `x` to sort `s`.

if `m = size (sort x) - size s > 0` then `high s x` evaluates to `m` most significant bits of `x`; else if `m = 0` then `high s x` evaluates to the value of `x`; else `m` zeros are prepended to the most significant part of `x`.

`val low : 'a Bitv.t Value.sort -> 'b bitv -> 'a bitv`

`low s x = cast s b0 x` is the low cast of `x` to sort `s`.

if `m = size (sort x) - size s < 0` then `low s x` evaluates to `size s` least significant bits of `x`; else if `m = 0` then `high s x` evaluates to the value of `x`; else `m` zeros are prepended to the most significant part of `x`.

`val signed : 'a Bitv.t Value.sort -> 'b bitv -> 'a bitv`

`signed s x = cast s (msb x) x` is the signed cast of `x` to sort `s`.

if `m = size s - (size (sort x)) > 0` then extends `x` on its most significant side with `m` bits equal to `msb x`; else if `m = 0` then `signed s x` evaluates to `x` else it evaluates to `size s` least significant bits of `x`.

`val unsigned : 'a Bitv.t Value.sort -> 'b bitv -> 'a bitv`

`unsigned s x = cast s b0 x` is the unsigned cast of `x` to sort `s`.

if `m = size s - (size (sort x)) > 0` then extends `x` on its most significant side with `m` zeros; else if `m = 0` then `unsigned s x` evaluates to `x` else it evaluates to `size s` least significant bits of `x`.

`val extract : 'a Bitv.t Value.sort -> 'b bitv -> 'b bitv -> _ bitv -> 'a bitv`

`extract s hi lo x` extracts bits of `x` between `hi` and `lo`.

Extracts `hi-lo+1` consecutive bits of `x` from `hi` to `lo`, and casts them to sort `s` with any excessive bits set to zero.

Note that `hi-lo+1` is taken modulo `2^'b`, so this operation is defined even if `lo` is greater or equal to `hi`.

`val loadw : 'c Bitv.t Value.sort -> bool -> ('a, _) mem -> 'a bitv -> 'c bitv`

`loadw s e m k` loads a word from the memory `m`.

if `e` evaluates to `b1` (big endian case), then the term evaluates to `low s (m[k] @ m[k+1] @ ... @ m[k+n] )`, else the term evaluates to `low s (m[k+n] @ m[k+n-1] @ ... @ m[k] )` where `x @ y` is `append (vals m) x y`, and `n` is the smallest natural number such that `n * size (vals (sort m)) >= size s`, an `m[i]` is the `i`'th value of memory `m`. .

This is a generic function that loads words using specified endianess (`e` could be read as `is_big_endian`) with arbitrary byte size.

`val storew : bool -> ('a, 'b) mem -> 'a bitv -> 'c bitv -> ('a, 'b) mem`

`storew e m k x` stores a word in the memory `m`.

Splits the word `x` into chunks of size equal to the size of memory elements and lays them out in the big endian order, if `e` evaluates to `b1`, or little endian order otherwise.

`val arshift : 'a bitv -> 'b bitv -> 'a bitv`

`arshift x m = shiftr (msb x) m` arithmetically shifts `x` right by `m` bits.

`val rshift : 'a bitv -> 'b bitv -> 'a bitv`

`rshift x m = shiftr b0 x m` shifts `x` right by `m` bits

`val lshift : 'a bitv -> 'b bitv -> 'a bitv`

`lshift x y = shiftl b0 x m` shifts `x` left by `m` bits.

`val eq : 'a bitv -> 'a bitv -> bool`

`eq x y` holds if `x` and `y` are bitwise equal.

`val neq : 'a bitv -> 'a bitv -> bool`

`eq x y` holds if `x` and `y` are not bitwise equal.

`val slt : 'a bitv -> 'a bitv -> bool`

`slt x y` signed strict less than.

`val ult : 'a bitv -> 'a bitv -> bool`

`ult x y` unsigned strict less than.

`val sgt : 'a bitv -> 'a bitv -> bool`

`sgt x y` signed strict greater than.

`val ugt : 'a bitv -> 'a bitv -> bool`

`ugt x y` unsigned strict greater than.

`val sge : 'a bitv -> 'a bitv -> bool`

`sge x y` signed greater or equal than.

`val uge : 'a bitv -> 'a bitv -> bool`

`sge x y` signed greater or equal than.