Talk:Minks

From Esolang
Jump to navigation Jump to search

How can any instructions be executed if all of them have to be preceded by a condition, and it is not possible to set a condition without executing an instruction? Are undefined conditions true by default? --Marinus 16:01, 21 Jul 2006 (UTC)

Apparently so. --Ihope127 21:59, 21 Jul 2006 (UTC)

Implementation

I have written an interpreter in Ocaml which I believe is working. I have tested it on the Minks programs blabla DEC blabla (exits without doing anything), b INP b DEC b b INC b OUT (cat program), and b INC b INC b INC b INC b INC b INC b INC b INC b INC b INC b OUT b dec b (prints a newline, then exits.)

Features:

  • if INP (or inp) is executed while input has reached end of file, the number 0 is stored in the REGISTER (or register)
  • each register can hold a value between 0 and Ocaml's max_int
    • technically, they can hold negative values, but since DEC/dec never go below 0, the only way to do that is to overflow them with a lot of INC/inc instructions
    • trying to output a negative value will display an error like Invalid_argument "char_of_int", because Ocaml's modulo function is such that -1 mod 256 results in -1
  • whitespace (spaces, newlines, tabulations) are mostly ignored, except every condition must be separated from the next instruction or condition with at least one space/tab/newline
  • conditions can have any alphabetic names (except the empty string); whether a word is an instruction or a condition depends entirely on its position within the program

Here is the source:

(* conditions are A-Za-z only, case insensitive *)
type condition = int
(* REGISTER is true, register is false *)
type instruction = Inc of bool | Dec of bool * condition | Out of bool | Inp of bool
type item = I of instruction | C of condition

exception Syntax_error

let string_of_list l =
  let length = List.length l in
  let s = String.create length and l = ref l in
  for k = length - 1 downto 0 do
    s.[k] <- List.hd !l;
    l := List.tl !l
  done;
  s

let l_pos =
  let l_of_conds = ref [] and n = ref 0
  in
  let rec pos s k l =
    match l with
    | h :: t -> if h = s then !n - k else pos s (succ k) t
    | [] ->
      (l_of_conds := s :: !l_of_conds;
       incr n;
       pred !n)
  in
  function s ->
    pos s 1 !l_of_conds

let rec take_cond l =
  match l with
  | ' ' :: t | '\n' :: t | '\t' :: t ->
    take_cond t
  | _ -> t_2 [] l
and t_2 acc l =
  match l with
  | ' ' :: t | '\n' :: t | '\t' :: t ->
    let s = string_of_list acc in
    (l_pos s, t)
  | [] ->
    let s = string_of_list acc in
    (l_pos s, [])
  | h :: t ->
    t_2
      ((let x = int_of_char h in
        if (x > 64 && x < 91) then h
        else if x > 96 && x < 123 then Char.lowercase h
        else raise Syntax_error
       ) :: acc)
       t

let rec parser acc prev p_list =
  match (prev, p_list) with
  | (C s, 'I' :: 'N' :: 'C' :: t) ->
    parser ((s, Inc true) :: acc) (I (Inc true)) t
  | (C s, 'i' :: 'n' :: 'c' :: t) ->
    parser ((s, Inc false) :: acc) (I (Inc false)) t
  | (C s, 'O' :: 'U' :: 'T' :: t) ->
    parser ((s, Out true) :: acc) (I (Out true)) t
  | (C s, 'o' :: 'u' :: 't' :: t) ->
    parser ((s, Out false) :: acc) (I (Out false)) t
  | (C s, 'I' :: 'N' :: 'P' :: t) ->
    parser ((s, Inp true) :: acc) (I (Inp true)) t
  | (C s, 'i' :: 'n' :: 'p' :: t) ->
    parser ((s, Inp false) :: acc) (I (Inp false)) t
  | (C s, 'D' :: 'E' :: 'C' :: t) ->
    parser acc (I (Dec (true, s))) t
  | (C s, 'd' :: 'e' :: 'c' :: t) ->
    parser acc (I (Dec (false, s))) t
  | (_, ' ' :: t) | (_, '\n' :: t) | (_, '\t' :: t) ->
    parser acc prev t
  | (I (Dec (b, s)), l) ->
    let (s2, t2) = take_cond l in
    parser ((s, Dec (b, s2)) :: acc) (I (Inc b)) t2
  | (C s, _) -> raise Syntax_error
  | (I _, []) ->
    (let n = l_pos "" in Array.make n true,
    List.rev acc)
  | (I _, l) ->
    let (s, t) = take_cond l in
    parser acc (C s) t;;

let list_of_string s =
  let l = ref [] in
  for k = String.length s - 1 downto 0 do
    l := s.[k] :: !l
  done;
  !l

let (cond_tab, program) = parser [] (I (Inc true)) (list_of_string Sys.argv.(1))

let is_true c = cond_tab.(c)
let set_cond c b = cond_tab.(c) <- b

let (register, rEGISTER) = (ref 0, ref 0)

let rec execution have_met p_list =
  match p_list with
  | (c, Inc b) :: t ->
    if is_true c then
      (incr (if b then rEGISTER else register);
       execution true t)
    else execution have_met t
  | (c, Out b) :: t ->
    if is_true c then
      (print_char
        (char_of_int (!(if b then rEGISTER else register) mod 256)
        );
       execution true t)
    else execution have_met t
  | (c, Inp b) :: t ->
    if is_true c then
      ((if b then rEGISTER else register) :=
          begin try int_of_char (input_char stdin) with
          | End_of_file -> 0 end;
       execution true t)
    else execution have_met t
  | (c, Dec (b, c2)) :: t ->
     (if is_true c then let reg = (if b then rEGISTER else register)
      in
      if !reg = 0
        then set_cond c2 false
        else (decr reg; set_cond c2 true)
    ); execution (have_met || is_true c) t
  | [] -> if have_met then execution false program;;

execution false program;;

--Koen (talk) 16:21, 12 October 2012 (UTC)