Talk:Minks
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
(orinp
) 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 ofINC
/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
- technically, they can hold negative values, but since
- 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;;