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. *)