- Commit
- 0d4597ae00fd7ba03f4df60137f4bc2ec4143741
- Author
- Pablo <pablo-escobar@riseup.net>
- Date
Initial commit
A OCaml module for manipulating unlimited register machines
Initial commit
4 files changed, 111 insertions, 0 deletions
Status | File Name | N° Changes | Insertions | Deletions |
Added | Makefile | 5 | 5 | 0 |
Added | docs.pdf | 0 | 0 | 0 |
Added | urm.ml | 68 | 68 | 0 |
Added | urm.mli | 38 | 38 | 0 |
diff --git a/Makefile b/Makefile @@ -0,0 +1,5 @@ +docs.pdf: urm.mli + ocamldoc -latex -o docs.tex urm.mli + latexmk -pdflatex docs.tex + texclear docs.tex + rm docs.tex ocamldoc.sty
diff --git a/urm.ml b/urm.ml @@ -0,0 +1,68 @@ +open Array + +type instruction = + | T of int * int + | Z of int + | S of int + | J of int * int * int + +type machine = + { instruction_pointer : int; + registers : nat -> nat; + } + +let from_registers (f : int -> int) : machine = + { intruction_pointer = 0; + registers = f + } + +let zero : machines = from_registers (fun _ -> 0) + +let register (m : machine) (i : int) : int = m.registers i + +(** Executes the next instruction. Returns [Some _] is the instruction pointer + points to a valid adress and [None] otherwise. *) +let step (program : instruction array) (m : machine) : machine option = + if m.instruction_pointer >= length program || m.instruction_pointer < 0 + then None + else + let updated = + match program.(m.instruction_pointer) with + | T (r1, r2) -> + { registers = + (fun n -> if n == r2 then m.registers r1 else m.registers n); + instruction_pointer = m.instruction_pointer + 1; + } + | Z r -> + { registers = (fun n -> if n == r then 0 else m.registers n); + instruction_pointer = m.instruction_pointer + 1; + } + | S r -> + { registers = + (fun n -> if n == r then 1 + (m.registers n) else m.registers n); + instruction_pointer = m.instruction_pointer + 1; + } + | J (r1, r2, i) when m.registers r1 == m.registers r2 -> + { m with instruction_pointer = i } + | J _ -> + { m with instruction_pointer = m.instruction_pointer + 1 } + in Some updated + +let rec exec (program : instruction array) (m : machine) : machine = + match step program m with + | None -> { m with instruction_pointer = 0 } + | Some n -> exec program n + +let exec_safe program (m : machine) (max : int) : machine option = + if max <= 0 + then raise (Invalid_argument "the number of clock-cycles must be positive ") + else + let rec exec_safe_tail m clock_cycles = + if clock_cycles <= max + then + match step program m with + | None -> Some { m with instruction_pointer = 0 } + | Some n -> exec_safe_tail n (clock_cycles + 1) + else None + in exec_safe_tail m 0 +
diff --git a/urm.mli b/urm.mli @@ -0,0 +1,38 @@ +(** Functions and types for manipulation unlimited register machines. *) + +(** The type of instructions. *) +type instruction = + | T of int * int (** Transfers values between registers. *) + | Z of int (** Sets a register to zero. *) + | S of int (** Increments a register *) + | J of int * int * int + (** Jumps to a given point if the values of two registers coincide. *) + +(** The type of all possible states of a URM. *) +type machine + +(** Returns a machine whose value of the [n]-th register is given by [f n]. *) +val from_registers : f:(int -> int) -> machine + +(** Returns the value of the [i]-th register of [m]. *) +val register : m:machine -> i:int -> int + +(** A machine whose registers are all zeros. *) +val zeros : machine + +(** Returns a machine whose register values are given by the register values of + [m] with updates corresponding to the execution of [program]. + + This function only returns when [program] actually halts. Please use {! + exec_safe } if you don't trust the [program]. *) +val exec : program:instruction array -> m:machine -> machine + +(** A safe version of {! exec }, where the max number of clock-cycles + allowed is controlled by [max]. Each instruction takes a single clock-cycle + to execute. + + Returns [Some _] if [program] halts in at most [max] clock-cycles and + [None] otherwise. Throws [Invalid_argument] if [max] is not a positive + integer. *) +val exec_safe : program: instruction array -> + machine -> max:int -> machine option