Execute SNUSP: Difference between revisions
m →{{header|Phix}}: added syntax colouring, marked p2js compatible |
|||
Line 583:
=={{header|Phix}}==
{{trans|Go}}
<!--<lang Phix>(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">id</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ipr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ipc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">ipc</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> <span style="color: #0000FF;">-</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">ipr</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> <span style="color: #0000FF;">-</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">snusp</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">dlen</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ds</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dlen</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- data store</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">dp</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- data pointer
-- remove leading '\n' from string if present</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim_head</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- make 2 dimensional instruction store and set instruction pointers</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cs</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ipr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">ipc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #000080;font-style:italic;">-- look for starting instruction</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cs</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">ipc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'$'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ipc</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">ipr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">id</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000080;font-style:italic;">-- execute</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">ipr</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ipr</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cs</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">ipc</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ipc</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ipr</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">op</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ipr</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ipc</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">switch</span> <span style="color: #000000;">op</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'>'</span> <span style="color: #0000FF;">:</span> <span style="color: #000000;">dp</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'<'</span> <span style="color: #0000FF;">:</span> <span style="color: #000000;">dp</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'+'</span> <span style="color: #0000FF;">:</span> <span style="color: #000000;">ds</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dp</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'-'</span> <span style="color: #0000FF;">:</span> <span style="color: #000000;">ds</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dp</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'.'</span> <span style="color: #0000FF;">:</span> <span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ds</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dp</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">','</span> <span style="color: #0000FF;">:</span> <span style="color: #000000;">ds</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dp</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getc</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'/'</span> <span style="color: #0000FF;">:</span> <span style="color: #000000;">id</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">not_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">id</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'\\'</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">id</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'!'</span> <span style="color: #0000FF;">:</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'?'</span> <span style="color: #0000FF;">:</span> <span style="color: #008080;">if</span> <span style="color: #000000;">ds</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dp</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<span style="color: #000000;">step</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">hw</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
/++++!/===========?\>++.>+.+++++++..+++\
\+++\ | /+>+++++++>/ /++++++++++<<.++>./
$+++/ | \+++++++++>\ \+++++.>.+++.-----\
\==-<<<<+>+++/ /=.>.+>.--------.-/"""</span>
<span style="color: #000000;">snusp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hw</span><span style="color: #0000FF;">)</span>
<!--</lang>-->
{{out}}
<pre>
|
Revision as of 17:00, 14 January 2022
You are encouraged to solve this task according to the task description, using any language you may know.
RCSNUSP is a set of SNUSP compilers and interpreters written for Rosetta Code in a variety of languages. Below are links to each of the versions of RCSNUSP.
An implementation need only properly implement the Core SNUSP instructions ('$', '\', '/', '+', '-', '<', '>', ',', '.', '!', and '?'). Modular SNUSP ('#', '@') and Bloated SNUSP (':', ';', '%', and '&') are also allowed, but not required. Any extra characters that you implement should be noted in the description of your implementation. Any cell size is allowed, EOF support is optional, as is whether you have bounded or unbounded memory.
11l
<lang 11l>V HW = ‘ /++++!/===========?\>++.>+.+++++++..+++\ \+++\ | /+>+++++++>/ /++++++++++<<.++>./ $+++/ | \+++++++++>\ \+++++.>.+++.-----\
\==-<<<<+>+++/ /=.>.+>.--------.-/’
F snusp(store, code)
V ds = [Byte(0)] * store V dp = 0 V cs = code.split("\n") V ipr = 0 V ipc = 0
L(row) cs ipc = row.findi(‘$’) I ipc != -1 ipr = L.index L.break
V id = 0
F step() I @id [&] 1 @ipr += 1 - (@id [&] 2) E @ipc += 1 - (@id [&] 2)
L ipr >= 0 & ipr < cs.len & ipc >= 0 & ipc < cs[ipr].len S cs[ipr][ipc] ‘>’ dp++ ‘<’ dp-- ‘+’ ds[dp]++ ‘-’ ds[dp]-- ‘.’ :stdout.write(Char(code' ds[dp])) ‘,’ ds[dp] = Byte(:stdin.read(1).code) ‘/’ id = (-)id ‘\’ id (+)= 1 ‘!’ step() ‘?’ I !(ds[dp]) step() step()
snusp(5, HW)</lang>
- Output:
Hello World!
Ada
See Execute SNUSP/Ada.
ALGOL 68
AutoHotkey
See RCSNUSP/AutoHotkey.
C
See RCSNUSP/C.
C++
See RCSNUSP/C++.
COBOL
See RCSNUSP/COBOL.
D
See RCSNUSP/D.
F#
See RCSNUSP/F Sharp.
Factor
See RCSNUSP/Factor.
Go
See RCSNUSP/Go.
Haskell
See RCSNUSP/Haskell.
Icon and Unicon
<lang icon>#
- 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</lang>
- Output:
Using the Modular SNUSP sample
prompt$ unicon -s snusp.icn -x hello.snusp Hello, world!
J
This program places no limits on the program or data size. Perhaps I'll revisit and write a tacit version of the SNUSP interpreter. <lang J> Note 'snusp'
Without $ character the program counter starts at top left (0 0) moving to the right (0 1)
> increment the pointer (to point to the next cell to the right). < decrement the pointer (to point to the next cell to the left). + increment (increase by one) the cell at the pointer. - decrement (decrease by one) the cell at the pointer. . output the value of the cell at the pointer as a character. , accept one character of input, storing its value in the cell at the pointer. \/ mirrors ? skip if memory pointer is 0 ! skip $ optional start program here (also heading to the right)
)
smoutput 'Toroidal programs run forever. Use ^C to interrupt.'
main =: 3 : 0 NB. use: main 'program.snusp'
PROGRAM =: [;._2 LF ,~ 1!:1 boxopen y SHAPE =: $PROGRAM PC =: SHAPE#:(,PROGRAM) i.'$' PCSTEP =: 0 1 CELL =: 0 CELLS =: ,0 while. 1 do. NB. for_i. i.400 do. INSTRUCTION =: (<PC) { PROGRAM STEP =: PCSTEP select. INSTRUCTION case. '<' do. CELL =: <: CELL if. CELL < 0 do. CELL =: 0 CELLS =: 0 , CELLS end. case. '>' do. CELL =: >: CELL if. CELL >: # CELLS do. CELLS =: CELLS , 0 end. case. ;/'-+' do. CELLS =: CELL ((<:'- +'i.INSTRUCTION)+{)`[`]} CELLS case. '.' do. 1!:2&4 (CELL{CELLS){a. case. ',' do. CELLS =: (1!:1<1) CELL } CELLS fcase. '/' do. STEP =: - STEP case. '\' do. STEP =: PCSTEP =: |. STEP case. '?' do. STEP =: +:^:(0 = CELL{CELLS) STEP case. '!' do. STEP =: +: STEP end. PC =: (| (PC + STEP + ])) SHAPE NB. toroidal NB. smoutput PC;CELL;CELLS NB. debug end.
) </lang> Store <lang SNUSP>\ display JJ and linefeed, then loop forever \ +++++++++++++++++++++++++++++++++++++\
! /+++++++++++++++++++++++++++++++++++++/ / \..<+++++\ \ . +++++/
</lang> as J.snusp
load'snusp.ijs' NB. the j code above Toroidal programs run forever. Use ^C to interrupt. main'J.snusp' JJ ^C |attention interrupt: main
Java
See RCSNUSP/Java
JavaScript
See RCSNUSP/JavaScript.
Julia
This Modular SNUSP interpreter uses modular calls to echo the first 2 characters entered. Try typing "Hi" at the prompt. <lang julia>const echo2 = raw"""
/==!/======ECHO==,==.==# | |
$==>==@/==@/==<==#"""
@enum Direction left up right down
function snusp(datalength, progstring)
stack = Vector{Tuple{Int, Int, Direction}}() data = zeros(datalength) dp = ipx = ipy = 1 direction = right # default to go to right at beginning
lines = split(progstring, "\n") lmax = maximum(map(length, lines)) lines = map(x -> rpad(x, lmax), lines) for (y, li) in enumerate(lines) if (x = findfirst("\$", li)) != nothing (ipx, ipy) = (x[1], y) end end
instruction = Dict([('>', ()-> dp += 1), ('<', ()-> (dp -= 1; if dp < 0 running = false end)), ('+', ()-> data[dp] += 1), ('-', ()-> data[dp] -= 1), (',', ()-> (data[dp] = read(stdin, UInt8))), ('.', ()->print(Char(data[dp]))), ('/', ()-> (d = Int(direction); d += (iseven(d) ? 3 : 5); direction = Direction(d % 4))), ('\\', ()-> (d = Int(direction); d += (iseven(d) ? 1 : -1); direction = Direction(d))), ('!', () -> ipnext()), ('?', ()-> if data[dp] == 0 ipnext() end), ('@', ()-> push!(stack, (ipx, ipy, direction))), ('#', ()-> if length(stack) > 0 (ipx, ipy, direction) = pop!(stack) end), ('\n', ()-> (running = false))])
inboundsx(plus) = (plus ? (ipx < lmax) : (ipx > 1)) ? true : exit(data[dp]) inboundsy(plus) = (plus ? (ipy < length(lines)) : (ipy > 1)) ? true : exit(data[dp]) function ipnext() if direction == right && inboundsx(true) ipx += 1 elseif direction == left && inboundsx(false) ipx -= 1 elseif direction == down && inboundsy(true) ipy += 1 elseif direction == up && inboundsy(false) ipy -= 1 end end
running = true while running cmdcode = lines[ipy][ipx] if haskey(instruction, cmdcode) instruction[cmdcode]() end ipnext() end exit(data[dp])
end
snusp(100, echo2)</lang>
- Output:
> Hi Hi >
Kotlin
<lang scala>// version 1.1.2
// requires 5 chars (10 bytes) of data store const val hw = """ /++++!/===========?\>++.>+.+++++++..+++\ \+++\ | /+>+++++++>/ /++++++++++<<.++>./ $+++/ | \+++++++++>\ \+++++.>.+++.-----\
\==-<<<<+>+++/ /=.>.+>.--------.-/"""
// input is a multi-line string. fun snusp(dlen: Int, raw: String) {
val ds = CharArray(dlen) // data store var dp = 0 // data pointer var s = raw
// remove leading '\n' from string if present s = s.trimStart('\n')
// make 2 dimensional instruction store and declare instruction pointers val cs = s.split('\n') var ipr = 0 var ipc = 0
// look for starting instruction findStart@ for ((r, row) in cs.withIndex()) { for ((i, c) in row.withIndex()) { if (c == '$') { ipr = r ipc = i break@findStart } } }
var id = 0 val step = fun() { if (id and 1 == 0) ipc += 1 - (id and 2) else ipr += 1 - (id and 2) }
// execute while ((ipr in 0 until cs.size) && (ipc in 0 until cs[ipr].length)) { when (cs[ipr][ipc]) { '>' -> dp++ '<' -> dp-- '+' -> ds[dp]++ '-' -> ds[dp]-- '.' -> print(ds[dp]) ',' -> ds[dp] = readLine()!![0] '/' -> id = id.inv() '\\' -> id = id xor 1 '!' -> step() '?' -> if (ds[dp] == '\u0000') step() } step() }
}
fun main(args: Array<String>) {
snusp(5, hw)
}</lang>
- Output:
Hello World!
Lua
See RCSNUSP/Lua.
Mathematica /Wolfram Language
See RCSNUSP/Mathematica.
Nim
<lang Nim>import strutils
- Requires 5 bytes of data store.
const Hw = r""" /++++!/===========?\>++.>+.+++++++..+++\ \+++\ | /+>+++++++>/ /++++++++++<<.++>./ $+++/ | \+++++++++>\ \+++++.>.+++.-----\
\==-<<<<+>+++/ /=.>.+>.--------.-/"""
- ---------------------------------------------------------------------------------------------------
proc snusp(dsLen: int; code: string) =
## The interpreter.
var ds = newSeq[byte](dsLen) # Data store. dp = 0 # Data pointer. cs = code.splitLines() # Two dimensional code store. ipr, ipc = 0 # Instruction pointers in row ans column. dir = 0 # Direction (0 = right, 1 = down, 2 = left, 3 = up).
# Initialize instruction pointers. for r, row in cs: ipc = row.find('$') if ipc >= 0: ipr = r break
#.................................................................................................
func step() = ## Update the instruction pointers acccording to the direction.
if (dir and 1) == 0: inc ipc, 1 - (dir and 2) else: inc ipr, 1 - (dir and 2)
#.................................................................................................
# Interpreter loop. while ipr in 0..cs.high and ipc in 0..cs[ipr].high: case cs[ipr][ipc] of '>': inc dp of '<': dec dp of '+': inc ds[dp] of '-': dec ds[dp] of '.': stdout.write chr(ds[dp]) of ',': ds[dp] = byte(stdin.readLine()[0]) of '/': dir = not dir of '\\': dir = dir xor 1 of '!': step() of '?': (if ds[dp] == 0: step()) else: discard step()
- ———————————————————————————————————————————————————————————————————————————————————————————————————
when isMainModule:
snusp(5, Hw)</lang>
- Output:
Hello World!
OCaml
See RCSNUSP/OCaml.
Perl
See RCSNUSP/Perl.
Phix
with javascript_semantics integer id = 0, ipr = 1, ipc = 1 procedure step() if and_bits(id,1) == 0 then ipc += 1 - and_bits(id,2) else ipr += 1 - and_bits(id,2) end if end procedure procedure snusp(integer dlen, string s) sequence ds = repeat(0,dlen) -- data store integer dp = 1 -- data pointer -- remove leading '\n' from string if present s = trim_head(s,'\n') -- make 2 dimensional instruction store and set instruction pointers sequence cs = split(s,'\n') ipr = 1 ipc = 1 -- look for starting instruction for i=1 to length(cs) do ipc = find('$',cs[i]) if ipc then ipr = i exit end if end for id = 0 -- execute while ipr>=1 and ipr<=length(cs) and ipc>=1 and ipc<=length(cs[ipr]) do integer op = cs[ipr][ipc] switch op do case '>' : dp += 1 case '<' : dp -= 1 case '+' : ds[dp] += 1 case '-' : ds[dp] -= 1 case '.' : puts(1,ds[dp]) case ',' : ds[dp] = getc(0) case '/' : id = not_bits(id) case '\\': id = xor_bits(id,1) case '!' : step() case '?' : if ds[dp]=0 then step() end if end switch step() end while end procedure constant hw = """ /++++!/===========?\>++.>+.+++++++..+++\ \+++\ | /+>+++++++>/ /++++++++++<<.++>./ $+++/ | \+++++++++>\ \+++++.>.+++.-----\ \==-<<<<+>+++/ /=.>.+>.--------.-/""" snusp(5, hw)
- Output:
Hello World!
PicoLisp
See RCSNUSP/PicoLisp.
Python
<lang python>#!/usr/bin/env python3
HW = r /++++!/===========?\>++.>+.+++++++..+++\ \+++\ | /+>+++++++>/ /++++++++++<<.++>./ $+++/ | \+++++++++>\ \+++++.>.+++.-----\
\==-<<<<+>+++/ /=.>.+>.--------.-/
def snusp(store, code):
ds = bytearray(store) # data store dp = 0 # data pointer cs = code.splitlines() # 2 dimensional code store ipr, ipc = 0, 0 # instruction pointers in row and column for r, row in enumerate(cs): try: ipc = row.index('$') ipr = r break except ValueError: pass rt, dn, lt, up = range(4) id = rt # instruction direction. starting direction is always rt def step(): nonlocal ipr, ipc if id&1: ipr += 1 - (id&2) else: ipc += 1 - (id&2) while ipr >= 0 and ipr < len(cs) and ipc >= 0 and ipc < len(cs[ipr]): op = cs[ipr][ipc] if op == '>': dp += 1 elif op == '<': dp -= 1 elif op == '+': ds[dp] += 1 elif op == '-': ds[dp] -= 1 elif op == '.': print(chr(ds[dp]), end=) elif op == ',': ds[dp] = input() elif op == '/': id = ~id elif op == '\\': id ^= 1 elif op == '!': step() elif op == '?': if not ds[dp]: step() step()
if __name__ == '__main__':
snusp(5, HW)</lang>
- Output:
Hello World!
Racket
See RCSNUSP/Racket.
Raku
(formerly Perl 6)
Implementation of modular SNUSP. <lang perl6>class SNUSP {
has @!inst-pointer; has @!call-stack; has @!direction; has @!memory; has $!mem-pointer;
method run ($code) { init(); my @code = pad( |$code.lines ); for @code.kv -> $r, @l { my $index = @l.grep( /'$'/, :k ); if $index { @!inst-pointer = $r, $index; last } }
loop { my $instruction = @code[@!inst-pointer[0]; @!inst-pointer[1]]; given $instruction { when '>' { $!mem-pointer++ } when '<' { $!mem-pointer-- } when '+' { @!memory[$!mem-pointer]++ } when '-' { @!memory[$!mem-pointer]-- } when '.' { print @!memory[$!mem-pointer].chr } when ',' { @!memory[$!mem-pointer] = $*IN.getc.ord } when '/' { @!direction = @!direction.reverse «*» -1 } when '\\' { @!direction = @!direction.reverse } when '!' { nexti() } when '?' { nexti() unless @!memory[$!mem-pointer] } when '@' { @!call-stack.push: @!inst-pointer.Array } when '#' { last unless +@!call-stack; @!inst-pointer = |@!call-stack.pop; nexti(); } } nexti(); last if @!inst-pointer[0] > +@code or @!inst-pointer[1] > +@code[0]; }
sub init () { @!inst-pointer = 0, 0; @!direction = 0, 1; $!mem-pointer = 0; @!memory = () }
sub nexti () { @!inst-pointer Z+= @!direction }
sub pad ( *@lines ) { my $max = max @lines».chars; my @pad = @lines.map: $max - *.chars; map -> $i { flat @lines[$i].comb, ' ' xx @pad[$i] }, ^@lines; } }
}
- TESTING
my $hw = q:to/END/;
/++++!/===========?\>++.>+.+++++++..+++\ \+++\ | /+>+++++++>/ /++++++++++<<.++>./ $+++/ | \+++++++++>\ \+++++.>.+++.-----\ \==-<<<<+>+++/ /=.>.+>.--------.-/ END
my $snusp = SNUSP.new; $snusp.run($hw)</lang>
- Output:
Hello World!
Ruby
See RCSNUSP/Ruby.
Seed7
The interpreter below implements Core SNUSP:
<lang seed7>$ include "seed7_05.s7i";
const proc: snusp (in string: sourceCode, in integer: memSize, inout file: input, inout file: output) is func
local var array string: instructions is 0 times ""; var array char: memory is 0 times ' '; var integer: dataPointer is 1; var integer: instrPtrRow is 0; var integer: instrPtrColumn is 0; var integer: rowDir is 0; var integer: columnDir is 1; var integer: helpDir is 0; var integer: row is 0; begin instructions := split(sourceCode, "\n"); memory := memSize times '\0;';
for key row range instructions do if pos(instructions[row], '$') <> 0 then instrPtrRow := row; instrPtrColumn := pos(instructions[row], '$'); end if; end for;
while instrPtrRow >= 1 and instrPtrRow <= length(instructions) and instrPtrColumn >= 1 and instrPtrColumn <= length(instructions[instrPtrRow]) do case instructions[instrPtrRow][instrPtrColumn] of when {'>'}: incr(dataPointer); when {'<'}: decr(dataPointer); when {'+'}: incr(memory[dataPointer]); when {'-'}: decr(memory[dataPointer]); when {'.'}: write(output, memory[dataPointer]); when {','}: memory[dataPointer] := getc(input); when {'/'}: helpDir := rowDir; rowDir := -columnDir; columnDir := -helpDir; when {'\\'}: helpDir := rowDir; rowDir := columnDir; columnDir := helpDir; when {'!'}: instrPtrRow +:= rowDir; instrPtrColumn +:= columnDir; when {'?'}: if memory[dataPointer] = '\0;' then instrPtrRow +:= rowDir; instrPtrColumn +:= columnDir; end if; end case; instrPtrRow +:= rowDir; instrPtrColumn +:= columnDir; end while; end func;
- SNUSP implementation of Hello World.
const string: helloWorld is "/++++!/===========?\\>++.>+.+++++++..+++\\\n\
\\\+++\\ | /+>+++++++>/ /++++++++++<<.++>./\n\ \$+++/ | \\+++++++++>\\ \\+++++.>.+++.-----\\\n\ \ \\==-<<<<+>+++/ /=.>.+>.--------.-/";
const proc: main is func
begin snusp(helloWorld, 5, IN, OUT); end func;</lang>
- Output:
Hello World!
Tcl
See RCSNUSP/Tcl.
Wren
<lang ecmascript>import "io" for Stdin
// 'raw' is a multi-line string var snusp = Fn.new { |dlen, raw|
var ds = List.filled(dlen, 0) // data store var dp = 0 // data pointer
// remove leading \n if it's there if (raw[0] == "\n") raw = raw[1..-1]
// make 2 dimensional instruction store & declare instruction pointers var s = raw.split("\n") var ipr = 0 var ipc = 0
// look for starting instruction for (r in 0...s.count) { var row = s[r] var outer = false for (c in 0...row.count) { var i = row[c] if (i == "$") { ipr = r ipc = c outer = true break } } if (outer) break }
var id = 0 var step = Fn.new { if (id&1 == 0) { ipc = ipc + 1 - (id&2) } else { ipr = ipr + 1 - (id&2) } }
// execute while (ipr >= 0 && ipr < s.count && ipc >= 0 && ipc < s[ipr].count) { var c = s[ipr][ipc] if (c == ">") { dp = dp + 1 } else if (c == "<") { dp = dp - 1 } else if (c == "+") { ds[dp] = ds[dp] + 1 } else if (c == "-") { ds[dp] = ds[dp] - 1 } else if (c == ".") { System.write(String.fromByte(ds[dp])) } else if (c == ",") { ds[dp] = Stdin.readByte() } else if (c == "/") { id = ~id } else if (c == "\\") { id = id ^ 1 } else if (c == "!") { step.call() } else if (c == "?") { if (ds[dp] == 0) step.call() } step.call() }
}
var hw =
"/++++!/===========?\\>++.>+.+++++++..+++\\\n" + "\\+++\\ | /+>+++++++>/ /++++++++++<<.++>./\n" + "$+++/ | \\+++++++++>\\ \\+++++.>.+++.-----\\\n" + " \\==-<<<<+>+++/ /=.>.+>.--------.-/"
snusp.call(5, hw)</lang>
- Output:
Hello World!
- Programming Tasks
- Solutions by Programming Task
- Compilers and Interpreters
- Implementations
- SNUSP Implementations
- SNUSP related
- 11l
- Ada
- ALGOL 68
- AutoHotkey
- C
- C++
- COBOL
- D
- F Sharp
- Factor
- Go
- Haskell
- Icon
- Unicon
- J
- Java
- JavaScript
- Julia
- Kotlin
- Lua
- Mathematica
- Wolfram Language
- Nim
- OCaml
- Perl
- Phix
- PicoLisp
- Python
- Racket
- Raku
- Ruby
- Seed7
- Tcl
- Wren
- GUISS/Omit