Execute Brain****/OCaml: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
m (Fixed syntax highlighting.)
 
(5 intermediate revisions by 5 users not shown)
Line 1: Line 1:
{{implementation|Brainf***}}{{collection|RCBF}}[[Category:OCaml]]
{{implementation|Brainf***}}{{collection|RCBF}}
Quick implementation of a [[Brainfuck]] interpreter in OCaml.
Quick implementation of a [[Brainfuck]] interpreter in [[OCaml]].


Like the Haskell version but without the lazy lists:
Like the [[Haskell]] [[RCBF/Haskell|version]] but without the lazy lists:


Pairs of lists are used to implement both the two-side infinite band of cells, and the program storage.
Pairs of lists are used to implement both the two-side infinite band of cells, and the program storage.
Line 10: Line 10:
A more efficient implementation could for example only admit well-bracketed brainfuck programs, and parse bracket blocks first, to replace the ''match_left'' and ''match_right'' which need linear time.
A more efficient implementation could for example only admit well-bracketed brainfuck programs, and parse bracket blocks first, to replace the ''match_left'' and ''match_right'' which need linear time.


<syntaxhighlight lang="ocaml">let move_left (x::l, r) = (l, x::r)
<ocaml>
let move_left (x::l, r) = (l, x::r)
let move_right (l, x::r) = (x::l, r)
let move_right (l, x::r) = (x::l, r)


Line 39: Line 38:


let modify f (l, x::r) = l, f x :: r
let modify f (l, x::r) = l, f x :: r

let dec x =
if x = 0 then 0
else x - 1


let rec exec p d =
let rec exec p d =
Line 54: Line 49:
exec (move_right p) (modify succ d)
exec (move_right p) (modify succ d)
| (_, '-'::_), _ ->
| (_, '-'::_), _ ->
exec (move_right p) (modify dec d)
exec (move_right p) (modify pred d)
| (_, ','::_), _ ->
| (_, ','::_), _ ->
let c = read_int () in
let c = read_int () in
Line 71: Line 66:
exec (match_left (move_left p)) d
exec (match_left (move_left p)) d


let run s = exec ([], s) ([0], [0])
let run s = exec ([], s) ([0], [0])</syntaxhighlight>
</ocaml>


Example output:
Example output:


# let char_list_of_string s =
<pre># let char_list_of_string s =
let result = ref [] in
let result = ref [] in
String.iter (fun c -> result := c :: !result) s;
String.iter (fun c -> result := c :: !result) s;
List.rev !result;;
List.rev !result;;
val char_list_of_string : string -> char list = <fun>
val char_list_of_string : string -> char list = <fun>

# run (char_list_of_string ",[>+<-].>.");;
# run (char_list_of_string ",[>+<-].>.");;
''5''
''5''
0
0
5
5
- : unit = ()
- : unit = ()</pre>

Latest revision as of 11:48, 1 September 2022

Execute Brain****/OCaml is an implementation of Brainf***. Other implementations of Brainf***.
Execute Brain****/OCaml is part of RCBF. You may find other members of RCBF at Category:RCBF.

Quick implementation of a Brainfuck interpreter in OCaml.

Like the Haskell version but without the lazy lists:

Pairs of lists are used to implement both the two-side infinite band of cells, and the program storage.

run interprets a Brainfuck program as a list of characters and reads integers from stdin and outputs them to stdout.

A more efficient implementation could for example only admit well-bracketed brainfuck programs, and parse bracket blocks first, to replace the match_left and match_right which need linear time.

let move_left  (x::l, r) = (l, x::r)
let move_right (l, x::r) = (x::l, r)

let rec match_left d =
  match d with
    '['::_, _ ->
      d
  | ']'::_, _ ->
      match_left (move_left (match_left (move_left d)))
  | _ ->
      match_left (move_left d)

let rec match_right d =
  match d with
    _, '['::_ ->
      move_right d
  | _, '['::_ ->
      match_right (match_right (move_right d))
  | _ ->
      match_right (move_right d)

let pad = function
    [], [] -> [0], [0]
  | [], r  -> [0], r
  | l,  [] -> l,   [0]
  | d      -> d;;

let modify f (l, x::r) = l, f x :: r

let rec exec p d =
  match p, d with
    (_, []),     _         -> ()
  | (_, '>'::_), _         ->
      exec (move_right p) (pad (move_right d))
  | (_, '<'::_), _         ->
      exec (move_right p) (pad (move_left  d))
  | (_, '+'::_), _         ->
      exec (move_right p) (modify succ d)
  | (_, '-'::_), _         ->
      exec (move_right p) (modify pred d)
  | (_, ','::_), _         ->
      let c = read_int () in
        exec (move_right p) (modify (fun _ -> c) d)
  | (_, '.'::_), (_, x::_) ->
      print_int x;
      print_newline ();
      exec (move_right p) d
  | (_, '['::_), (_, 0::_) ->
      exec (match_right (move_right p)) d
  | (_, '['::_), _         ->
      exec (move_right p) d
  | (_, ']'::_), (_, 0::_) ->
      exec (move_right p) d
  | (_, ']'::_), _         ->
      exec (match_left (move_left p)) d

let run s = exec ([], s) ([0], [0])

Example output:

# let char_list_of_string s =
  let result = ref [] in
    String.iter (fun c -> result := c :: !result) s;
    List.rev !result;;
val char_list_of_string : string -> char list = <fun>

# run (char_list_of_string ",[>+<-].>.");;
''5''
0
5
- : unit = ()