-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwhitespace.ml
86 lines (78 loc) · 2.9 KB
/
whitespace.ml
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
(* Lexical tokens *)
type token = Space | Tab | LineFeed | EOF
(* Heap access instructions *)
type heap_acces = Store | Retrieve
(* Flow control instructions *)
type flow_control =
| Mark of int
| Call of int
| UnconditionalJump of int
| JumpZero of int
| JumpNegative of int
| EndSubroutine
| EndProgram
(* Arithmetic instructions *)
type arithmetic = Addtion | Subtraction | Multiplication | Division | Modulo
(* Stack manipulation instructions *)
type stack_manipulation = Push of int | Duplicate | Swap | Discard
(* IO instructions *)
type io = OutputCharacter | OutputNumber | ReadCharacter | ReadNumber
(* Instruction modification parameters *)
type imp =
| StackManipulation of stack_manipulation
| Arithmetic of arithmetic
| HeapAccess of heap_acces
| FlowControl of flow_control
| IO of io
(* Encode a number and return its representation as a string. *)
let encode_number number =
let rec do_encode number result =
match number with
| x when x > 0 -> (
match x mod 2 with
| 1 -> do_encode (number / 2) ("\t" ^ result)
| 0 -> do_encode (number / 2) (" " ^ result)
| _ -> raise (Failure "This shouldn't happen...") )
| _ -> result ^ "\n"
in
let is_negative = number < 0 in
(* Encode number. *)
let result = do_encode (Int.abs number) "" in
(* Encode Sign. *)
if is_negative then "\t" ^ result else " " ^ result
(* Print the representation of an instruction modification parameter to
`output`. *)
let print output imp =
match imp with
| StackManipulation x -> (
match x with
| Push x' -> Printf.fprintf output " %s" (encode_number x')
| Duplicate -> Printf.fprintf output " \n "
| Swap -> Printf.fprintf output " \n\t"
| Discard -> Printf.fprintf output " \n\n" )
| Arithmetic x -> (
match x with
| Addtion -> Printf.fprintf output "\t "
| Subtraction -> Printf.fprintf output "\t \t"
| Multiplication -> Printf.fprintf output "\t \n"
| Division -> Printf.fprintf output "\t \t "
| Modulo -> Printf.fprintf output "\t \t\t" )
| HeapAccess x -> (
match x with
| Store -> Printf.fprintf output "\t\t "
| Retrieve -> Printf.fprintf output "\t\t\t" )
| FlowControl x -> (
match x with
| Mark x' -> Printf.fprintf output "\n %s" (encode_number x')
| Call x' -> Printf.fprintf output "\n \t%s" (encode_number x')
| UnconditionalJump x' -> Printf.fprintf output "\n \n%s" (encode_number x')
| JumpZero x' -> Printf.fprintf output "\n\t %s" (encode_number x')
| JumpNegative x' -> Printf.fprintf output "\n\t\t%s" (encode_number x')
| EndSubroutine -> Printf.fprintf output "\n\t\n"
| EndProgram -> Printf.fprintf output "\n\n\n" )
| IO x -> (
match x with
| OutputCharacter -> Printf.fprintf output "\t\n "
| OutputNumber -> Printf.fprintf output "\t\n \t"
| ReadCharacter -> Printf.fprintf output "\t\n\t "
| ReadNumber -> Printf.fprintf output "\t\n\t\t" )