Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/takenobu-hs/ghci-hexcalc

Haskell/GHCi as a Hex-Calculator interactive
https://github.com/takenobu-hs/ghci-hexcalc

calclator ghc ghci haskell

Last synced: about 2 hours ago
JSON representation

Haskell/GHCi as a Hex-Calculator interactive

Awesome Lists containing this project

README

        

GHCi as a Hex-Calculator interactive
====================================

The GHCi (REPL for Haskell) is a very useful interactive tool, it's not only for debugging :)
This package "ghci-hexcalc" is an interactive hex-calculator using Haskell/GHCi.
This is a simple and casual tool like Perl and Excel for our daily work.

Interactive oriented features:
* Short-named operators and functions
* Show values in hexadecimal format by default
* Suppress type annotation of numeric literals by type inference
* Postfix-notation available
* Highlight available

See also [description on Hackage](https://hackage.haskell.org/package/ghci-hexcalc).

Contents
--------

* [Run](#run)
* [Example of use](#example-of-use)
* [Specification](#specification)
* [Appendix](#appendix)

Run
---

Bare GHCi:
```
$ ghci src/Data/GHex.hs
```
or
```
$ ghci -ghci-script example/example.ghci
```

Stack:
```
$ stack exec -- ghci src/Data/GHex.hs
```

Example of use
--------------

#### Numeric literals by `Hex` type annotation

The value of `Hex` type is shown as hexadecimal format.

```
ghci> 1 :: Hex
0x0000_0000_0000_0001
```

```
ghci> 0xff :: Hex
0x0000_0000_0000_00ff
```

```
ghci> 0b1011 :: Hex
0x0000_0000_0000_000b
```

```
ghci> 16 + 3 :: Hex
0x0000_0000_0000_0013
```

#### Variables on GHCi

You could use variables of Haskell syntax on GHCi.

```
ghci> x = 255 :: Hex
ghci> x + 3
ghci> y = it -- `it` is GHCi's variable. It stores the previous result.
```

#### Arithmetic operations

You could also use arithmetic operators in `Hex` type.

```
ghci> x + 3
ghci> (x * 256) -1
ghci> x + 2^10
ghci> neg x
```

#### Logical operations

Numeric literals applied to functions of this package are inferred as `Hex` type.

```
ghci> 0xff .& 6
ghci> 256 .| 16
ghci> 100 .^ 5
ghci> inv 255
```

#### Shift operations

```
ghci> 1 .<< 16
ghci> 256 .>> 1
```

#### Div and mod operations

```
ghci> 0xff0000 ./ 256
ghci> 0xfedc .% 256
```

#### Generate bit and byte with position

```
ghci> bit1 15
0x0000_0000_0000_8000
```

```
ghci> bits 7 4
0x0000_0000_0000_00f0
```

```
ghci> bitList [15, 14, 1]
0x0000_0000_0000_c002
```

```
ghci> byte1 2
0x0000_0000_00ff_0000
```

```
ghci> bytes 4 3
0x0000_00ff_ff00_0000
```

#### Extract and replace bits
```
ghci> gets 0xabcd 15 12
0x0000_0000_0000_000a
```
```
ghci> puts 0xabcd 15 12 7
0x0000_0000_0000_7bcd
```

#### Set and clear bits

```
ghci> sbits 0x1234 11 8
0x0000_0000_0000_1f34
```

```
ghci> cbits 0x1234 7 4
0x0000_0000_0000_1204
```

#### Get asserted bit positions and count bits

```
ghci> pos1 0x0081
[7,0]
```

```
ghci> pos0 $ inv 0x0100
[8]
```

```
ghci> count1 0b11001
3
```

#### Permute, split and merge

```
ghci> gather 0x12345678 0x0ff000f0
0x0000_0000_0000_0237
```

```
ghci> scatter 0x12345678 0xff00ff00 0xabcd
0x0000_0000_ab34_cd78
```

```
ghci> (3,0b101) .++ (2,0b11)
(5,0x0000_0000_0000_0017)
```

#### Predefined-constants

```
ghci> mega
0x0000_0000_0010_0000
```

```
ghci> giga
0x0000_0000_4000_0000
```

```
ghci> 4 * giga - 1
0x0000_0000_ffff_ffff
```

```
ghci> 2^32 ./ giga
0x0000_0000_0000_0004
```

#### Postfix-notation

The operator `.@` is an operator for postfix notation.
It's the same as `Data.Function.(&)`.

The following two are the same:

```
ghci> pos1 0xf0
[7,6,5,4]
```

```
ghci> 0xf0 .@pos1
[7,6,5,4]
```

#### Formatting for hex, bin, dec, Tera,Giga,Mega,Kilo, signed and floating

Formatting functions convert a `Hex` type value to a string type for each format.

```
ghci> 2^16 .@hex
"0x0000_0000_0001_0000"
```

```
ghci> 100 .@bin
"0b110_0100"
```

```
ghci> 100 .@bin16
"0b0000_0000_0110_0100"
```

```
ghci> giga .@dec
"1073741824"
```

```
ghci> bit 43 .@decT
"8"
```

```
ghci> 0xffffffffffffffff .@signed
"-1"
```

```
ghci> 0x3fc00000 .@float
"1.5"
```

#### Hilighting specified bits

The function `color` highlights specified bits. It inverts the color in the ANSI sequence for the specified bits.

```
ghci> 0xff .@color (bits 7 4)
0b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_1111_1111
^^^^
```

```
ghci> 0xffffffff .@color mega
0b0000_0000_0000_0000_0000_0000_0000_0000_1111_1111_1111_1111_1111_1111_1111_1111
^
```

```
ghci> 0 .@color (bitList [54,53,4,3,2])
0b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000
^^ ^ ^^
```

#### Input and convert

The function `inputRawHexIO` inputs a string and converts it to a `Hex` type.

```
ghci> inputRawHexIO
ff aa (your input)
ghci> x = it
ghci> x
0x0000_0000_0000_ffaa
```

```
ghci> x <- inputRawHexIO
ff aa (your input)
ghci> x
0x0000_0000_0000_ffaa
```

#### Floating conversion examples

```
ghci> float2hex 1.0
0x0000_0000_3f80_0000
```

```
ghci> hex2float 0x3fc00000
1.5
```

```
ghci> double2hex 1.0
0x3ff0_0000_0000_0000
```

```
ghci> hex2double 0x40091eb851eb851f
3.14
```

```
ghci> splitFloat (-1)
[1,127,0]
```

```
ghci> mergeFloat [0, 127, 2^22]
1.5
```

```
ghci> splitDouble (-0.5)
[1,1022,0]
```

```
ghci> mergeDouble [0, 1023, 2^51]
1.5
```

#### Combination examples

```
ghci> x .| bit1 18
ghci> (x .<< 4) .& 0xf0
ghci> bit1 33 ./ giga
ghci> 2 * mega .@dec
ghci> 4 * tera .@pos1
ghci> foldr1 (.|) [0xa, 0xcc, 0xd1b]
ghci> 0 .@color (tera .| giga .| mega .| kilo)
```

#### Using Data.Bits library

`Hex` type is deriving `Data.Bits` type. So you could use functions of `Data.Bits`.

```
ghci> x `testBit` 8
ghci> x `clearBit` 15
ghci> x .&. 0xff
ghci> x `rotateL` 4
ghci> countLeadingZeros x
```

#### Clear screen

```
ghci> cls
```

#### Simple help

Show simple usage:

```
ghci> usage
```

Listing APIs with `:browse` ghci command:

```
ghci> :browse
newtype Hex = Hex Word
(.&) :: Hex -> Hex -> Hex
(.|) :: Hex -> Hex -> Hex
(.^) :: Hex -> Hex -> Hex
inv :: Hex -> Hex
:
```

When you run with `ghci -haddock`, you could also use `:doc` ghci command (ghc8.6 or later):

```
ghci> :doc bits
Set bits from n1 to n2

>>> bits 15 8
0x0000_0000_0000_ff00
```

Specification
-------------

Please see also [Hackage document](http://hackage.haskell.org/package/ghci-hexcalc/docs/Data-GHex.html) in detail.

#### General

* Core type:
* The core type of this package is the `Hex` type.
* `Hex` type is implemented in unsigned `Word`.
* `Hex` type is 64 bit length on x86_64.
* Operators and functions:
* Operators in this package begin with `.`(dot), like `.&` and `.|`.
* Most functions align bits to the LSB side.

#### Numeric literals by `Hex` type annotation

| Operation | Description |
|:------------------------------|:--------------------------------------|
| `:: Hex` | Type annotation for basic type `Hex` |
| `255 :: Hex` | Decimal number literal |
| `0xff :: Hex` | Hexadecimal number literal |
| `0b1101 :: Hex` | binary number literal |

#### Derived operations

| Operation | Description |
|:------------------------------|:--------------------------------------|
| Many operations | Eq, Ord, Num, Enum, Real, Bounded, Integral, Bits and FiniteBits class available |

#### Postfix operator

| Operation | Description |
|:------------------------------|:--------------------------------------|
| `.@` | Postfix-notation operator |

#### Arithmetic operations

| Operation | Description |
|:------------------------------|:--------------------------------------|
| `+`, `-`, `*`, `^`, ... | Num, Real class available |
| `neg` x1 | Negation. (inv x1 + 1) |
| `signext` x1 n1 | Sign extention |
| x1 `./` x2 | Integer division |
| x1 `.%` x2 | Integer modulo |

#### Logical operations

| Operation | Description |
|:------------------------------|:--------------------------------------|
| x1 `.&` x2 | Bitwise "and" |
| x1 `.\|` x2 | Bitwise "or" |
| x1 `.^` x2 | Bitwise "xor" |
| `inv` x1 | Bitwise "not" (invert) |

#### Shift operations

| Operation | Description |
|:------------------------------|:--------------------------------------|
| x1 `.<<` n1 | Logical left shift |
| x1 `.>>` n1 | Logical right shift |

#### Generate bit and byte with position

| Operation | Description |
|:------------------------------|:--------------------------------------|
| `bit1` n1 | Set a bit |
| `bits` n1 n2 | Set bits from n1 to n2 |
| `bitList` [n1, n2, ... nn] | Set bits with List |
| `byte1` n1 | Set a byte |
| `bytes` n1 n2 | Set bytes from n1 to n2 |
| `mask` n1 | Set bits from 0 to n1 |

#### Extract and replace bits

| Operation | Description |
|:------------------------------|:--------------------------------------|
| `gets` x1 n1 n2 | Extract bits from n1 to n2 |
| `puts` x1 n1 n2 x2 | Replace bits from n1 to n2 |
| | |
| `getBit1` x1 n1 | Extract bit at n1 |
| `getBits` x1 n1 n2 | Synonym to gets |
| `getByte1` x1 n1 | Extract bytes from n1 to 0 |
| `getBytes` x1 n1 n2 | Extract bytes from n1 to n2 |
| `putBit1` x1 n1 x2 | Replace byte at n1 |
| `putBits` x1 n1 n2 x2 | Synonym to puts |
| `putBytes` x1 n1 n2 x2 | Replace bytes from n1 to n2 |

#### Set and clear bits

| Operation | Description |
|:------------------------------|:--------------------------------------|
| `sbits` x1 n1 n2 | Set bits from n1 to n2 of x1 |
| `cbits` x1 n1 n2 | Clear bits from n1 to n2 of x1 |

#### Get asserted bit positions and count bits

| Operation | Description |
|:------------------------------|:--------------------------------------|
| `pos1` x1 | Get bit positions asserted with 1 |
| `pos0` x1 | Get bit positions asserted with 0 |
| | |
| `range` x1 | Get upper and lower boundaries |
| | |
| `count1` x1 | Count bit-1 |
| `count0` x1 | Count bit-0 |

#### Permute

| Operation | Description |
|:------------------------------|:--------------------------------------|
| `bitrev` x1 | Reverse bits |
| `byterev` x1 | Reverse bytes |
| | |
| `gather` x1 x2 | Gather bits from x1 by x2 |
| `scatter` x1 x2 x3 | Scatter bits from x3 to x1 by x2 |

#### Split and merge

| Operation | Description |
|:------------------------------|:--------------------------------------|
| `splitBits` x1 | Split bits to List |
| `splitBytes` x1 | Split bytes to List |
| `mergeBits` [x1, x2, .. xn] | Merge bits from List |
| `mergeBytes` [x1, x2, .. xn] | Merge bytes from List |
| | |
| `splitPairs` [n1, .. nn] x1 | Split bits to pair of (length,Hex) |
| `mergePairs` [(n1,x1),..] | Merge bits from pair of (length,Hex) |
| (n1,x1) `.++` (n2,x2) | Concatinate pairs of (length,Hex) |

#### Predefined-constants

| Constant | Description |
|:------------------------------|:--------------------------------------|
| `exa` | 2^60 (It's not 10^18) |
| `peta` | 2^50 (It's not 10^15) |
| `tera` | 2^40 (It's not 10^12) |
| `giga` | 2^30 (It's not 10^9) |
| `mega` | 2^20 (It's not 10^6) |
| `kilo` | 2^10 (It's not 10^3) |
| | |
| `zero` | 0 |
| `one` | 1 |
| `all0` | 0x0 |
| `all1` | inv all0 |
| | |
| `hexBitSize` | 64 on x86_64. Thus size of `Word` |
| `hexBitSeq` | [hexBitSize-1, hexBitSize-2, .. 0] |

#### Formatting for hex, bin, dec, Tera,Giga,Mega,Kilo, signed and floating

| Operation | Description |
|:------------------------------|:----------------------------------------|
| `.@hex` | Show in hexadecimal string |
| `.@hex8` | Show in hexadecimal string of 8bit |
| `.@hex16` | Show in hexadecimal string of 16bit |
| `.@hex32` | Show in hexadecimal string of 32bit |
| `.@hex64` | Show in hexadecimal string of 64bit |
| `.@hexN` n1 | Show in hexadecimal string of n1 bit |
| `.@hexs` | Show in hexadecimal string of List |
| | |
| `.@bin` | Show in binary string |
| `.@bin8` | Show in binary string of 8bit |
| `.@bin16` | Show in binary string of 16bit |
| `.@bin32` | Show in binary string of 32bit |
| `.@bin64` | Show in binary string of 64bit |
| `.@binN` n1 | Show in binary string of n1 bit |
| | |
| `.@dec` | Show in decimal string |
| `.@decE` | Show in decimal of Exa unit |
| `.@decP` | Show in decimal of Peta unit |
| `.@decT` | Show in decimal of Tera unit |
| `.@decG` | Show in decimal of Giga unit |
| `.@decM` | Show in decimal of Mega unit |
| `.@decK` | Show in decimal of Kilo unit |
| | |
| `.@signed` | Show in singed decimal with `Word` |
| | |
| `.@float` | Show in float string |
| `.@double` | Show in double string |
| | |
| `.@hexSized` | Show in hexadecimal string of (len,Hex) |
| `.@binSized` | Show in binary string of (len,Hex) |

#### Hilighting and pretty-print

| Operation | Description |
|:------------------------------|:--------------------------------------|
| `color` x1 x2 | Highlight bit of x1 specified with x2 |
| `ppr` fun x1 | Print x1 applied with fun |

#### Input and convert

| Operation | Description |
|:------------------------------|:--------------------------------------|
| `inputRawHexIO` | Input string and convert to Hex type |

#### Floating convert

| Operation | Description |
|:------------------------------|:--------------------------------------|
| `float2hex` | Convert Float to Hex type |
| `hex2float` | Convert Hex to Float type |
| `double2hex` | Convert Double to Hex type |
| `hex2double` | Convert Hex to Double type |
| | |
| `splitFloat` | Split Float to elements |
| `mergeFloat` | Merge Float from elements |
| `splitDouble` | Split Double to elements |
| `mergeDouble` | Merge Double from elements |

#### Miscellaneous

| Operation | Description |
|:------------------------------|:--------------------------------------|
| `cls` | Clear screen by ANSI sequence |
| `usage` | Show simple help |

Appendix
--------

#### GHC language extention for numeric literals

When `-XBinaryLiterals` extention enabled, you can use binary literals on GHC and GHCi, like `0b1101`.

When `-XNumericUnderscores` extention enabled, you can use underscores in numeric literals on GHC and GHCi, like `0xff_ff`.
`-XNumericUnderscores` extension is available GHC 8.6 or later.

GHC language extensions can be described in `~/.ghci` or `./ghci` file:
```
:set -XBinaryLiterals
:set -XNumericUnderscores
```

GHC language extensions can also be specified as an option when starting GHC and GHCi:
```bash
$ ghci -XBinaryLiterals -XNumericUnderscores
```

#### Shell alias

It is useful to set the alias of the shell:
```bash
alias ghex="(cd $XXX/ghci-hexcalc; ghci -ghci-script example/example.ghci)"
```

#### Expression evaluation mode of GHC

You can also run in one shot mode (a expression evaluation mod) by `ghc -e`:
```bash
$ ghc src/Data/GHex.hs -e '4 * giga'
0x0000_0004_0000_0000
```

#### Default declaration on GHCi

With the [`default` declaration](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#extended-rules-around-default-declarations), integer literals are inferred as `Hex` types.

```
ghci> default (Hex)
ghci> 255
0x0000_0000_0000_00ff
```