# # snusp.icn, A Modular SNUSP interpreter # $define VERSION 0.6 # allow a couple of cli options link options # directions $define DRIGHT 1 $define DLEFT 2 $define DUP 3 $define DDOWN 4 record position(row, col) global dir, ip, ram procedure main(argv) local ch, codespace, col, dp, fn, line local row := 1 local wid := 0 local dirs := [] local ips := [] local opts, verbose, debug opts := options(argv, "-h! -v! -d!", errorproc) \opts["v"] & verbose := 1 \opts["h"] & show_help(verbose) \opts["d"] & debug := 1 ip := position(1,1) # initial direction dir := DRIGHT # prepare initial memory ram := list(1, 0) # prepare code field codespace := [] fn := open(argv[1], "r") | &input if (fn === &input) & \opts["h"] then return while line := read(fn) do { put(codespace, line) wid := max(*line, wid) } if *codespace = 0 then return every line := !codespace do { codespace[row] := left(codespace[row], wid) # track starting indicator if /col := find("$", codespace[row]) then { ip.row := row ip.col := col } row +:= 1 } if \verbose then { write("Starting at ", ip.row, ", ", ip.col, " with codespace:") every write(!codespace) } dp := 1 repeat { if not (ch := codespace[ip.row][ip.col]) then break if \debug then { write(&errout, "dir: ", dir, " ch: ", ch, " [", ord(ch), "]", " row: ", ip.row, " col: ", ip.col, " dp: ", dp, " ram[dp]: ", ram[dp]) } case ch of { # six of the bf instructions "+": ram[dp] +:= 1 "-": ram[dp] -:= 1 ">": resize(dp +:= 1) "<": dp -:= 1 ".": writes(char(ram[dp]) | char(0)) ",": ram[dp] := getche() # direction change, LURD, RULD, SKIP, SKIPZ "\\": { # LURD case dir of { DRIGHT: dir := DDOWN DLEFT: dir := DUP DUP: dir := DLEFT DDOWN: dir := DRIGHT } } "/": { # RULD case dir of { DRIGHT: dir := DUP DLEFT: dir := DDOWN DUP: dir := DRIGHT DDOWN: dir := DLEFT } } "!": step() "?": { # skipz if ram[dp] = 0 then { step() } } # modular SNUSP "@": { # Enter push(dirs, dir) push(ips, copy(ip)) } "#": { # Leave if *dirs < 1 then break dir := pop(dirs) ip := pop(ips) step() } } step() } end # advance the ip depending on direction procedure step() case dir of { DRIGHT: ip.col +:= 1 DLEFT: ip.col -:= 1 DUP: ip.row -:= 1 DDOWN: ip.row +:= 1 } end # enlarge memory when needed procedure resize(elements) until *ram >= elements do put(ram, 0) end # quick help or verbose help procedure show_help(verbose) write("SNUSP interpeter in Unicon, version ", VERSION) write("CORE and MODULAR, not yet BLOATED") write() write("Usage: unicon snusp.icn -x [filename] [-h|-v|-d]") write(" -h, help") write(" -v, verbose (and verbose help") write(" -d, debug (step tracer)") if \verbose then { write() write("Instructions:") write(" + INCR, Increment current memory location") write(" - DECR, Decrement current memory location") write(" > RIGHT, Advance memory pointer") write(" < LEFT, Retreat memory pointer") write(" . WRITE, Output contents of current memory cell, in ASCII") write(" , READ, Accept key and place byte value in current memory cell") write(" \\ LURD, If going:") write(" left, go up") write(" up, go left") write(" right, go down") write(" down, go right") write(" / RULD, If going:") write(" right, go up") write(" up, go right") write(" left, go down") write(" down, go left") write(" !, SKIP, Move forward one step in current direction") write(" ?, SKIPZ, If current memory cell is zero then SKIP") write("Modular SNUSP adds:") write(" @, ENTER, Push direction and instruction pointer") write(" #, LEAVE, Pop direction and instruction pointer and SKIP") write() write("All other characters are NOOP, explicitly includes =,|,spc") write(" $, can set the starting location; first one found") write() write("Hello world examples:") write() write("CORE SNUSP:") write("/++++!/===========?\\>++.>+.+++++++..+++\\") write("\\+++\\ | /+>+++++++>/ /++++++++++<<.++>./") write("$+++/ | \\+++++++++>\\ \\+++++.>.+++.-----\\") write(" \\==-<<<<+>+++/ /=.>.+>.--------.-/") write() write("Modular SNUSP:") write(" /@@@@++++# #+++@@\ #-----@@@\\n") write("$@\\H.@/e.+++++++l.l.+++o.>>++++.< .<@/w.@\\o.+++r.++@\\l.@\\d.>+.@/.#") write(" \\@@@@=>++++>+++++<<@+++++# #---@@/!=========/!==/") write() } end