Pure BF/Implementation in Ocaml
Jump to navigation
Jump to search
This Ocaml program defines the types world and tape, then the function:
f : world * tape -> world * tape
that corresponds to the Pure BF program given as command line argument.
However, the function f is never applied. This implementation is for that reason not very powerful.
Note that functions . and , actually modify their input world, rather than a copy.
type world = { inp : in_channel; out : out_channel }
type tape = { back : char list; current : char; forth : char list }
let forwards (world, tape) =
match tape.forth with
| h :: t -> (world,
{ back = tape.current :: tape.back;
current = h;
forth = t })
| [] -> (world,
{ back = tape.current :: tape.back;
current = '\000';
forth = [] })
let backwards (world, tape) =
match tape.back with
| h :: t -> (world,
{ back = t;
current = h;
forth = tape.current :: tape.forth })
| [] -> (world,
{ back = [];
current = '\000';
forth = tape.current :: tape.forth })
let higher (world, tape) =
let succ c = if c = '\255' then '\000' else Char.chr (succ (Char.code c))
in let x = succ tape.current
in (world, { back = tape.back; current = x; forth = tape.forth })
let lower (world, tape) =
let pred c = if c = '\000' then '\255' else Char.chr (pred (Char.code c))
in let x = pred tape.current
in (world, { back = tape.back; current = x; forth = tape.forth })
let output (world, tape) =
output_char world.out tape.current;
(world, tape)
let input (world, tape) =
let x = try input_char world.inp with
| End_of_file -> '\000'
in (world, { back = tape.back; current = x; forth = tape.forth })
let id (world, tape) = (world, tape)
let compose f g x = f (g x)
let rec loop f (world, tape) =
if tape.current = '\000' then id (world, tape)
else compose (loop f) f (world, tape)
let rec parse acc p =
match p with
| '[' :: p ->
let (q, p) = parse id p in parse (compose (loop q) acc) p
| ']' :: p -> (acc, p)
| [] -> (acc, [])
| '>' :: p -> parse (compose forwards acc) p
| '<' :: p -> parse (compose backwards acc) p
| '+' :: p -> parse (compose higher acc) p
| '-' :: p -> parse (compose lower acc) p
| '.' :: p -> parse (compose output acc) p
| ',' :: p -> parse (compose input acc) p
| _ :: p -> parse acc p
let str_to_list s =
let l = ref [] in
for k = String.length s - 1 downto 0 do
l := s.[k] :: !l done;
!l
let (f, _) = parse id (str_to_list Sys.argv.(1))