caml-urm

A OCaml module for manipulating unlimited register machines

Commit
baf83aba711df406475b77c276bea38c5545f40e
Parent
1bbe53693337efb75a1fbef33faffd2d3319ad57
Author
Pablo <pablo-escobar@riseup.net>
Date

Added the P instruction to the machine architecture

Added an intruction (P) to decrement the value of a given register, so that users can set registers to negative values

Diffstat

3 files changed, 16 insertions, 8 deletions

Status File Name N° Changes Insertions Deletions
Modified docs.pdf 0 0 0
Modified urm.ml 17 12 5
Modified urm.mli 7 4 3
diff --git a/docs.pdf b/docs.pdf
Binary files differ.
diff --git a/urm.ml b/urm.ml
@@ -5,6 +5,7 @@ type instruction =
   | T of int * int
   | Z of int
   | S of int
+  | P of int
   | J of int * int * int
 
 type t = 
@@ -44,6 +45,11 @@ let step (program : instruction array) (m : machine) : machine option =
             (fun n -> if n == r then 1 + (m.registers n) else m.registers n);
           instruction_pointer = m.instruction_pointer + 1;
         }
+      | P r -> 
+        { registers = 
+            (fun n -> if n == r then (m.registers n) - 1 else m.registers n);
+          instruction_pointer = m.instruction_pointer + 1;
+        }
       | J (r1, r2, i) when m.registers r1 == m.registers r2 -> 
         (* [i - 1] is used so that the instruction count starts at 1 instead of
          0 *)
@@ -79,7 +85,7 @@ let nexec max program m =
 exception Syntax_error of string
 
 (** A simple lexer for instructions *)
-let lex = make_lexer ["T"; "Z"; "S"; "J"; "("; ")"; ","]
+let lex = make_lexer ["T"; "Z"; "S"; "P"; "J"; "("; ")"; ","]
 
 (** Parse a single instruction *)
 let parse_instruction (i : token list) : instruction =
@@ -90,6 +96,8 @@ let parse_instruction (i : token list) : instruction =
       Z r
   | [ Kwd "S"; Kwd "("; Int r; Kwd ")" ] ->
       S r
+  | [ Kwd "P"; Kwd "("; Int r; Kwd ")" ] ->
+      P r
   | [ Kwd "J"; Kwd "("; Int r1; Kwd ","; Int r2; Kwd ","; Int i; Kwd ")" ]
   when i > 0 ->
       J (r1, r2, i)
@@ -100,11 +108,10 @@ let parse_instruction (i : token list) : instruction =
 
 let parse (s : string) : instruction array =
     let f s = 
-      if "" = String.trim s 
-      then None
+      let s = String.trim s in
+      if s = "" then None
       else
-          s |> String.trim
-            |> Stream.of_string
+          s |> Stream.of_string
             |> lex
             |> Stream.npeek 8
             |> parse_instruction
diff --git a/urm.mli b/urm.mli
@@ -9,6 +9,7 @@
  - [T(n, m)] transfers the contents of the [n]-th register to [m]-th register.
  - [Z(n)] sets the value of the [n]-th register to zero.
  - [S(n)] increments the value of the [n]-th register.
+ - [P(n)] decrements the value of the [n]-th register.
  - [J(n, m, i)] Jumps to the [i]-th instruction if the values of the [n]-th and
  [m]-th coincide. The instruction count starts at 1, so [i = 1] jumps to the
  first instruction.
@@ -17,9 +18,8 @@
  registers are indexed by natural numbers (starting from 1), while in this
  implementation the registers are indexed by arbitrary integers. Also, in
  Nigel's specification store natural numbers (starting from 0) and in this
- implementation they store arbitrary integers. Good luck getting a negative
- integer from a machine whose registers are initially set to natural numbers
- though.
+ implementation they store arbitrary integers. I have also added the [P]
+ instruction to help users handle negative integers.
 
  @see <https://sites.oxy.edu/rnaimi/home/URMsim.htm> URM simulator. 
  @see <libgen.li/file.php?md5=147d472c8ebc58b832a0d93d02c03f3a> Computability,
@@ -30,6 +30,7 @@ type instruction =
   | T of int * int 
   | Z of int 
   | S of int 
+  | P of int
   | J of int * int * int 
 
 (** The type of all possible states of a URM. *)