Execute SNUSP: Difference between revisions
(Added FreeBASIC) |
|||
(16 intermediate revisions by 11 users not shown) | |||
Line 3: | Line 3: | ||
An implementation need only properly implement the Core SNUSP instructions <nowiki>('$', '\', '/', '+', '-', '<', '>', ',', '.', '!', and '?')</nowiki>. 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. |
An implementation need only properly implement the Core SNUSP instructions <nowiki>('$', '\', '/', '+', '-', '<', '>', ',', '.', '!', and '?')</nowiki>. 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. |
||
=={{header|11l}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight 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)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Hello World! |
|||
</pre> |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
See [[Execute SNUSP/Ada]]. |
See [[Execute SNUSP/Ada]]. |
||
=={{header|ALGOL 68}}== |
|||
See [[Execute SNUSP/Algol68]]. |
|||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
Line 21: | Line 84: | ||
=={{header|D}}== |
=={{header|D}}== |
||
See [[RCSNUSP/D]]. |
See [[RCSNUSP/D]]. |
||
=={{header|EasyLang}}== |
|||
{{trans|Go}} |
|||
<syntaxhighlight> |
|||
proc snusp dlen raw$ . . |
|||
len ds[] dlen |
|||
is$[] = strsplit raw$ "\n" |
|||
for s$ in is$[] |
|||
is$[][] &= strchars s$ |
|||
. |
|||
for ipr to len is$[][] |
|||
for ipc to len is$[ipr][] |
|||
if is$[ipr][ipc] = "$" |
|||
break 2 |
|||
. |
|||
. |
|||
. |
|||
dp = 1 |
|||
id = 0 |
|||
# |
|||
subr step |
|||
if id mod 2 = 0 |
|||
ipc += 1 - bitand id 2 |
|||
else |
|||
ipr += 1 - bitand id 2 |
|||
. |
|||
. |
|||
while ipr >= 1 and ipr <= len is$[][] and ipc >= 1 and ipc <= len is$[ipr][] |
|||
c$ = is$[ipr][ipc] |
|||
if c$ = ">" |
|||
dp += 1 |
|||
elif c$ = "<" |
|||
dp -= 1 |
|||
elif c$ = "+" |
|||
ds[dp] += 1 |
|||
elif c$ = "-" |
|||
ds[dp] -= 1 |
|||
elif c$ = "." |
|||
write strchar ds[dp] |
|||
elif c$ = "," |
|||
# ds[dp] = strcode input |
|||
elif c$ = "/" |
|||
id = bitxor id 3 |
|||
elif c$ = "\\" |
|||
id = bitxor id 1 |
|||
elif c$ = "!" |
|||
step |
|||
elif c$ = "?" |
|||
if ds[dp] = 0 |
|||
step |
|||
. |
|||
. |
|||
step |
|||
. |
|||
. |
|||
s$ = input |
|||
while s$ <> "" |
|||
cod$ &= "\n" & s$ |
|||
s$ = input |
|||
. |
|||
snusp 5 cod$ |
|||
# |
|||
input_data |
|||
/++++!/===========?\>++.>+.+++++++..+++\ |
|||
\+++\ | /+>+++++++>/ /++++++++++<<.++>./ |
|||
$+++/ | \+++++++++>\ \+++++.>.+++.-----\ |
|||
\==-<<<<+>+++/ /=.>.+>.--------.-/ |
|||
</syntaxhighlight> |
|||
=={{header|F_Sharp|F#}}== |
=={{header|F_Sharp|F#}}== |
||
See [[RCSNUSP/F Sharp]]. |
See [[RCSNUSP/F Sharp]]. |
||
=={{header|Factor}}== |
|||
See [[RCSNUSP/Factor]]. |
|||
=={{header|FreeBASIC}}== |
|||
<syntaxhighlight lang="vbnet">' Rosetta Code problem: https://rosettacode.org/wiki/Execute_SNUSP |
|||
' by Jjuanhdez, 05/2024 |
|||
' The interpreter below implements Core SNUSP: |
|||
Const HW = "/++++!/===========?\>++.>+.+++++++..+++" & Chr(10) & _ |
|||
"\+++\ | /+>+++++++>/ /++++++++++<<.++>./" & Chr(10) & _ |
|||
"$+++/ | \+++++++++>\ \+++++.>.+++.-----\" & Chr(10) & _ |
|||
" \==-<<<<+>+++/ /=.>.+>.--------.-/" |
|||
Dim Shared As Integer ipf, ipc ' instruction pointers in row and column |
|||
Dim Shared As Integer direcc ' direction (0 = right, 1 = down, 2 = left, 3 = up) |
|||
Sub Paso() |
|||
If direcc And 1 Then |
|||
ipf += 1 - (direcc And 2) |
|||
Else |
|||
ipc += 1 - (direcc And 2) |
|||
End If |
|||
End Sub |
|||
Sub SNUSP (dsLen As Integer, SNUSPcode As String) |
|||
Dim As Ubyte ad(dsLen - 1) ' data store |
|||
Dim As Integer dp ' data pointer |
|||
Dim As String cb(dsLen) ' two-way code storage |
|||
Dim As String fila, op, linea |
|||
Dim As Integer r, i, j |
|||
dp = 0 |
|||
i = 1 |
|||
j = 1 |
|||
ipf = 0 |
|||
ipc = 0 |
|||
direcc = 0 |
|||
While i <= Len(SNUSPcode) |
|||
If Mid(SNUSPcode, i, 1) = Chr(10) Then |
|||
cb(j) = linea |
|||
linea = "" |
|||
j += 1 |
|||
Else |
|||
linea &= Mid(SNUSPcode, i, 1) |
|||
End If |
|||
i += 1 |
|||
Wend |
|||
cb(j) = linea |
|||
For r = 0 To Ubound(cb) |
|||
fila = cb(r) |
|||
ipc = Instr(fila, "$") - 1 |
|||
If ipc >= 0 Then |
|||
ipf = r |
|||
Exit For |
|||
End If |
|||
Next r |
|||
While ipf >= 0 And ipf <= Ubound(cb) And ipc >= 0 And ipc < Len(cb(ipf)) |
|||
op = Mid(cb(ipf), ipc + 1, 1) |
|||
Select Case op |
|||
Case ">": dp += 1 ' RIGTH |
|||
Case "<": dp -= 1 ' LEFT |
|||
Case "+": ad(dp) += 1 ' INCR |
|||
Case "-": ad(dp) -= 1 ' DECR |
|||
Case ",": Input ad(dp) ' READ |
|||
Case ".": Print Chr(ad(dp)); ' WRITE |
|||
Case "/": direcc = Not direcc ' RULD |
|||
Case "\": direcc Xor= 1 ' LURD |
|||
Case "!": Paso ' SKIP |
|||
Case "?": If ad(dp) = 0 Then Paso ' SKIPZ |
|||
End Select |
|||
Paso |
|||
Wend |
|||
Print Chr(ad(dp)); |
|||
End Sub |
|||
SNUSP(5, HW) |
|||
Sleep</syntaxhighlight> |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
See [[RCSNUSP/Go]]. |
See [[RCSNUSP/Go]]. |
||
Line 29: | Line 244: | ||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
See [[RCSNUSP/Haskell]]. |
See [[RCSNUSP/Haskell]]. |
||
=={{header|Icon}} and {{header|Unicon}}== |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
{{out}} |
|||
Using the Modular SNUSP sample |
|||
<pre>prompt$ unicon -s snusp.icn -x hello.snusp |
|||
Hello, world!</pre> |
|||
=={{header|J}}== |
=={{header|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. |
This program places no limits on the program or data size. Perhaps I'll revisit and write a tacit version of the SNUSP interpreter. |
||
<syntaxhighlight lang="j"> |
|||
<lang J> |
|||
Note 'snusp' |
Note 'snusp' |
||
Line 86: | Line 495: | ||
end. |
end. |
||
) |
) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Store < |
Store <syntaxhighlight lang="snusp">\ display JJ and linefeed, then loop forever |
||
\ +++++++++++++++++++++++++++++++++++++\ |
\ +++++++++++++++++++++++++++++++++++++\ |
||
! /+++++++++++++++++++++++++++++++++++++/ |
! /+++++++++++++++++++++++++++++++++++++/ |
||
/ \..<+++++\ |
/ \..<+++++\ |
||
\ . +++++/ |
\ . +++++/ |
||
</ |
</syntaxhighlight> as J.snusp |
||
<pre> |
<pre> |
||
load'snusp.ijs' NB. the j code above |
load'snusp.ijs' NB. the j code above |
||
Line 112: | Line 521: | ||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
This Modular SNUSP interpreter uses modular calls to echo the first 2 characters entered. Try typing "Hi" at the prompt. |
This Modular SNUSP interpreter uses modular calls to echo the first 2 characters entered. Try typing "Hi" at the prompt. |
||
< |
<syntaxhighlight lang="julia">const echo2 = raw""" |
||
/==!/======ECHO==,==.==# |
/==!/======ECHO==,==.==# |
||
| | |
| | |
||
Line 134: | Line 543: | ||
end |
end |
||
instruction = Dict([('>', ()->dp += 1), |
instruction = Dict([('>', ()-> dp += 1), |
||
('<', ()-> (dp -= 1; if dp < 0 running = false end)), ('+', ()-> data[dp] += 1), |
('<', ()-> (dp -= 1; if dp < 0 running = false end)), ('+', ()-> data[dp] += 1), |
||
('-', ()-> data[dp] -= 1), (',', ()-> (data[dp] = read(stdin, UInt8))), |
('-', ()-> data[dp] -= 1), (',', ()-> (data[dp] = read(stdin, UInt8))), |
||
Line 166: | Line 575: | ||
end |
end |
||
snusp(100, echo2)</ |
snusp(100, echo2)</syntaxhighlight> {{output}} <pre> |
||
> Hi |
> Hi |
||
Hi |
Hi |
||
Line 174: | Line 583: | ||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
{{trans|Go}} |
{{trans|Go}} |
||
< |
<syntaxhighlight lang="scala">// version 1.1.2 |
||
// requires 5 chars (10 bytes) of data store |
// requires 5 chars (10 bytes) of data store |
||
Line 236: | Line 645: | ||
fun main(args: Array<String>) { |
fun main(args: Array<String>) { |
||
snusp(5, hw) |
snusp(5, hw) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 246: | Line 655: | ||
See [[RCSNUSP/Lua]]. |
See [[RCSNUSP/Lua]]. |
||
=={{header|Mathematica}}== |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
See [[RCSNUSP/Mathematica]]. |
See [[RCSNUSP/Mathematica]]. |
||
=={{header| |
=={{header|Nim}}== |
||
{{trans|Python}} |
|||
See [[RCSNUSP/OCaml]]. |
|||
<syntaxhighlight lang="nim">import strutils |
|||
# Requires 5 bytes of data store. |
|||
=={{header|Perl}}== |
|||
const Hw = r""" |
|||
See [[RCSNUSP/Perl]]. |
|||
/++++!/===========?\>++.>+.+++++++..+++\ |
|||
\+++\ | /+>+++++++>/ /++++++++++<<.++>./ |
|||
$+++/ | \+++++++++>\ \+++++.>.+++.-----\ |
|||
\==-<<<<+>+++/ /=.>.+>.--------.-/""" |
|||
#--------------------------------------------------------------------------------------------------- |
|||
=={{header|Perl 6}}== |
|||
{{works with|Rakudo|2017.02}} |
|||
Implementation of modular SNUSP. |
|||
<lang perl6>class SNUSP { |
|||
proc snusp(dsLen: int; code: string) = |
|||
has @!inst-pointer; |
|||
## The interpreter. |
|||
has @!call-stack; |
|||
has @!direction; |
|||
has @!memory; |
|||
has $!mem-pointer; |
|||
var |
|||
method run ($code) { |
|||
ds = newSeq[byte](dsLen) # Data store. |
|||
init(); |
|||
dp = 0 # Data pointer. |
|||
my @code = pad( |$code.lines ); |
|||
cs = code.splitLines() # Two dimensional code store. |
|||
for @code.kv -> $r, @l { |
|||
ipr, ipc = 0 # Instruction pointers in row ans column. |
|||
my $index = @l.grep( /'$'/, :k ); |
|||
dir = 0 # Direction (0 = right, 1 = down, 2 = left, 3 = up). |
|||
if $index { |
|||
@!inst-pointer = $r, $index; |
|||
last |
|||
} |
|||
} |
|||
# Initialize instruction pointers. |
|||
loop { |
|||
for r, row in cs: |
|||
my $instruction = @code[@!inst-pointer[0]; @!inst-pointer[1]]; |
|||
ipc = row.find('$') |
|||
given $instruction { |
|||
if ipc >= 0: |
|||
when '>' { $!mem-pointer++ } |
|||
ipr = r |
|||
when '<' { $!mem-pointer-- } |
|||
break |
|||
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 = () |
|||
} |
|||
func step() = |
|||
sub nexti () { @!inst-pointer Z+= @!direction } |
|||
## Update the instruction pointers acccording to the direction. |
|||
if (dir and 1) == 0: |
|||
inc ipc, 1 - (dir and 2) |
|||
else: |
|||
my @pad = @lines.map: $max - *.chars; |
|||
inc ipr, 1 - (dir and 2) |
|||
map -> $i { flat @lines[$i].comb, ' ' xx @pad[$i] }, ^@lines; |
|||
} |
|||
} |
|||
} |
|||
#................................................................................................. |
|||
# TESTING |
|||
my $hw = q:to/END/; |
|||
# 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)</syntaxhighlight> |
|||
my $snusp = SNUSP.new; |
|||
$snusp.run($hw)</lang> |
|||
{{out}} |
{{out}} |
||
<pre>Hello World!</pre> |
<pre>Hello World!</pre> |
||
=={{header| |
=={{header|OCaml}}== |
||
See [[RCSNUSP/OCaml]]. |
|||
{{trans|Go}}<lang Phix>integer id = 0, ipr = 1, ipc = 1 |
|||
=={{header|Perl}}== |
|||
procedure step() |
|||
See [[RCSNUSP/Perl]]. |
|||
if and_bits(id,1) == 0 then |
|||
ipc += 1 - and_bits(id,2) |
|||
else |
|||
ipr += 1 - and_bits(id,2) |
|||
end if |
|||
end procedure |
|||
=={{header|Phix}}== |
|||
procedure snusp(integer dlen, string s) |
|||
{{trans|Go}} |
|||
sequence ds = repeat(0,dlen) -- data store |
|||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
integer dp = 1 -- data pointer |
|||
<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> |
|||
-- remove leading '\n' from string if present |
|||
s = trim_head(s,'\n') |
|||
<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> |
|||
-- make 2 dimensional instruction store and set instruction pointers |
|||
<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> |
|||
sequence cs = split(s,'\n') |
|||
<span style="color: #008080;">else</span> |
|||
ipr = 1 |
|||
<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> |
|||
ipc = 1 |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
-- look for starting instruction |
|||
for i=1 to length(cs) do |
|||
<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> |
|||
ipc = find('$',cs[i]) |
|||
<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> |
|||
if ipc then |
|||
<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 |
|||
ipr = i |
|||
exit |
|||
-- remove leading '\n' from string if present</span> |
|||
end if |
|||
<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> |
|||
end for |
|||
<span style="color: #000080;font-style:italic;">-- make 2 dimensional instruction store and set instruction pointers</span> |
|||
id = 0 |
|||
<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> |
|||
-- execute |
|||
<span style="color: #000000;">ipc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
|||
while ipr>=1 and ipr<=length(cs) |
|||
and ipc>=1 and ipc<=length(cs[ipr]) do |
|||
<span style="color: #000080;font-style:italic;">-- look for starting instruction</span> |
|||
integer op = cs[ipr][ipc] |
|||
<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> |
|||
switch op do |
|||
<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> |
|||
case '>' : dp += 1 |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">ipc</span> <span style="color: #008080;">then</span> |
|||
case '<' : dp -= 1 |
|||
<span style="color: #000000;">ipr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span> |
|||
case '+' : ds[dp] += 1 |
|||
<span style="color: #008080;">exit</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
case '.' : puts(1,ds[dp]) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
case ',' : ds[dp] = getc(0) |
|||
case '/' : id = not_bits(id) |
|||
<span style="color: #000000;">id</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
case '\\': id = xor_bits(id,1) |
|||
case '!' : step() |
|||
<span style="color: #000080;font-style:italic;">-- execute</span> |
|||
case '?' : if ds[dp]=0 then step() end if |
|||
<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> |
|||
end switch |
|||
<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> |
|||
step() |
|||
<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> |
|||
end while |
|||
<span style="color: #008080;">switch</span> <span style="color: #000000;">op</span> <span style="color: #008080;">do</span> |
|||
end procedure |
|||
<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> |
|||
constant hw = """ |
|||
<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> |
|||
snusp(5, hw)</lang> |
|||
<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> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 403: | Line 805: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
{{trans|Go}} |
{{trans|Go}} |
||
< |
<syntaxhighlight lang="python">#!/usr/bin/env python3 |
||
HW = r''' |
HW = r''' |
||
Line 457: | Line 859: | ||
if __name__ == '__main__': |
if __name__ == '__main__': |
||
snusp(5, HW)</ |
snusp(5, HW)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 465: | Line 867: | ||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
See [[RCSNUSP/Racket]]. |
See [[RCSNUSP/Racket]]. |
||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
{{works with|Rakudo|2017.02}} |
|||
Implementation of modular SNUSP. |
|||
<syntaxhighlight lang="raku" line>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)</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Hello World!</pre> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
Line 472: | Line 952: | ||
The interpreter below implements Core SNUSP: |
The interpreter below implements Core SNUSP: |
||
< |
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i"; |
||
const proc: snusp (in string: sourceCode, in integer: memSize, inout file: input, inout file: output) is func |
const proc: snusp (in string: sourceCode, in integer: memSize, inout file: input, inout file: output) is func |
||
Line 532: | Line 1,012: | ||
begin |
begin |
||
snusp(helloWorld, 5, IN, OUT); |
snusp(helloWorld, 5, IN, OUT); |
||
end func;</ |
end func;</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 541: | Line 1,021: | ||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
See [[RCSNUSP/Tcl]]. |
See [[RCSNUSP/Tcl]]. |
||
=={{header|Wren}}== |
|||
{{trans|Go}} |
|||
<syntaxhighlight lang="wren">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)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Hello World! |
|||
</pre> |
|||
{{omit from|GUISS}} |
{{omit from|GUISS}} |
Latest revision as of 19:18, 21 May 2024
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
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)
- 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.
EasyLang
proc snusp dlen raw$ . .
len ds[] dlen
is$[] = strsplit raw$ "\n"
for s$ in is$[]
is$[][] &= strchars s$
.
for ipr to len is$[][]
for ipc to len is$[ipr][]
if is$[ipr][ipc] = "$"
break 2
.
.
.
dp = 1
id = 0
#
subr step
if id mod 2 = 0
ipc += 1 - bitand id 2
else
ipr += 1 - bitand id 2
.
.
while ipr >= 1 and ipr <= len is$[][] and ipc >= 1 and ipc <= len is$[ipr][]
c$ = is$[ipr][ipc]
if c$ = ">"
dp += 1
elif c$ = "<"
dp -= 1
elif c$ = "+"
ds[dp] += 1
elif c$ = "-"
ds[dp] -= 1
elif c$ = "."
write strchar ds[dp]
elif c$ = ","
# ds[dp] = strcode input
elif c$ = "/"
id = bitxor id 3
elif c$ = "\\"
id = bitxor id 1
elif c$ = "!"
step
elif c$ = "?"
if ds[dp] = 0
step
.
.
step
.
.
s$ = input
while s$ <> ""
cod$ &= "\n" & s$
s$ = input
.
snusp 5 cod$
#
input_data
/++++!/===========?\>++.>+.+++++++..+++\
\+++\ | /+>+++++++>/ /++++++++++<<.++>./
$+++/ | \+++++++++>\ \+++++.>.+++.-----\
\==-<<<<+>+++/ /=.>.+>.--------.-/
F#
See RCSNUSP/F Sharp.
Factor
See RCSNUSP/Factor.
FreeBASIC
' Rosetta Code problem: https://rosettacode.org/wiki/Execute_SNUSP
' by Jjuanhdez, 05/2024
' The interpreter below implements Core SNUSP:
Const HW = "/++++!/===========?\>++.>+.+++++++..+++" & Chr(10) & _
"\+++\ | /+>+++++++>/ /++++++++++<<.++>./" & Chr(10) & _
"$+++/ | \+++++++++>\ \+++++.>.+++.-----\" & Chr(10) & _
" \==-<<<<+>+++/ /=.>.+>.--------.-/"
Dim Shared As Integer ipf, ipc ' instruction pointers in row and column
Dim Shared As Integer direcc ' direction (0 = right, 1 = down, 2 = left, 3 = up)
Sub Paso()
If direcc And 1 Then
ipf += 1 - (direcc And 2)
Else
ipc += 1 - (direcc And 2)
End If
End Sub
Sub SNUSP (dsLen As Integer, SNUSPcode As String)
Dim As Ubyte ad(dsLen - 1) ' data store
Dim As Integer dp ' data pointer
Dim As String cb(dsLen) ' two-way code storage
Dim As String fila, op, linea
Dim As Integer r, i, j
dp = 0
i = 1
j = 1
ipf = 0
ipc = 0
direcc = 0
While i <= Len(SNUSPcode)
If Mid(SNUSPcode, i, 1) = Chr(10) Then
cb(j) = linea
linea = ""
j += 1
Else
linea &= Mid(SNUSPcode, i, 1)
End If
i += 1
Wend
cb(j) = linea
For r = 0 To Ubound(cb)
fila = cb(r)
ipc = Instr(fila, "$") - 1
If ipc >= 0 Then
ipf = r
Exit For
End If
Next r
While ipf >= 0 And ipf <= Ubound(cb) And ipc >= 0 And ipc < Len(cb(ipf))
op = Mid(cb(ipf), ipc + 1, 1)
Select Case op
Case ">": dp += 1 ' RIGTH
Case "<": dp -= 1 ' LEFT
Case "+": ad(dp) += 1 ' INCR
Case "-": ad(dp) -= 1 ' DECR
Case ",": Input ad(dp) ' READ
Case ".": Print Chr(ad(dp)); ' WRITE
Case "/": direcc = Not direcc ' RULD
Case "\": direcc Xor= 1 ' LURD
Case "!": Paso ' SKIP
Case "?": If ad(dp) = 0 Then Paso ' SKIPZ
End Select
Paso
Wend
Print Chr(ad(dp));
End Sub
SNUSP(5, HW)
Sleep
Go
See RCSNUSP/Go.
Haskell
See RCSNUSP/Haskell.
Icon and Unicon
- 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.
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.
)
Store
\ display JJ and linefeed, then loop forever
\ +++++++++++++++++++++++++++++++++++++\
! /+++++++++++++++++++++++++++++++++++++/
/ \..<+++++\
\ . +++++/
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.
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)
- Output:
> Hi Hi >
Kotlin
// 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)
}
- Output:
Hello World!
Lua
See RCSNUSP/Lua.
Mathematica/Wolfram Language
See RCSNUSP/Mathematica.
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)
- 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
#!/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)
- Output:
Hello World!
Racket
See RCSNUSP/Racket.
Raku
(formerly Perl 6)
Implementation of modular SNUSP.
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)
- Output:
Hello World!
Ruby
See RCSNUSP/Ruby.
Seed7
The interpreter below implements Core SNUSP:
$ 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;
- Output:
Hello World!
Tcl
See RCSNUSP/Tcl.
Wren
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)
- 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
- EasyLang
- F Sharp
- Factor
- FreeBASIC
- 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