blob: eb477db5bc431a4653e32ccba20964b3685f87d9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
type noun =
| Atom of Z.t
| Cell of noun * noun
exception Exit
let ensure_non_negative z =
if Z.sign z < 0 then raise Exit else z
let atom z =
Atom (ensure_non_negative z)
let atom_of_int n =
if n < 0 then raise Exit else Atom (Z.of_int n)
(* Convert ASCII string to atom (bytes in little-endian order) *)
let atom_of_string s =
if String.length s = 0 then atom Z.zero
else
let bytes = Bytes.of_string s in
atom (Z.of_bits (Bytes.to_string bytes))
let cell h t = Cell (h, t)
let zero = atom_of_int 0
let one = atom_of_int 1
let is_atom = function
| Atom _ -> true
| Cell _ -> false
let is_cell = function
| Cell _ -> true
| Atom _ -> false
let rec equal a b =
match a, b with
| Atom x, Atom y -> Z.equal x y
| Cell (ah, at), Cell (bh, bt) -> equal ah bh && equal at bt
| _ -> false
let inc = function
| Atom z -> Atom (Z.succ z)
| Cell _ -> raise Exit
let head = function
| Cell (h, _) -> h
| Atom _ -> raise Exit
let tail = function
| Cell (_, t) -> t
| Atom _ -> raise Exit
let rec slot axis noun =
if Z.equal axis Z.one then noun
else if Z.equal axis Z.zero then raise Exit
else
let bit = Z.testbit axis 0 in
let parent = Z.shift_right axis 1 in
let sub = slot parent noun in
if bit then tail sub else head sub
let rec to_list noun =
match noun with
| Atom z when Z.equal z Z.zero -> []
| Cell (h, t) -> h :: to_list t
| _ -> raise Exit
|