Subleq: Difference between revisions

33,175 bytes added ,  3 months ago
m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(40 intermediate revisions by 15 users not shown)
Line 16:
The program should load the initial contents of the emulated machine's memory, set the instruction pointer to the first address (which is defined to be address 0), and begin emulating the machine, which works as follows:
:#   Let '''A''' be the value in the memory location identified by the instruction pointer;   let '''B''' and '''C''' be the values stored in the next two consecutive addresses in memory.
:#   Advance the instruction pointer three words,   (it will thento point at the address ''after'' the address containing '''C''').
:#   If '''A''' is   '''-1'''   (negative unity),   then a character is read from the machine's input and its numeric value stored in the address given by '''B'''.   '''C''' is unused. (Most implementations adopt the C convention of signaling EOF by storing -1 as the read-in character.)
:#   If '''B''' is   '''-1'''   (negative unity),   then the number contained in the address given by '''A''' is interpreted as a character and written to the machine's output.   '''C''' is unused.
:#   Otherwise, both '''A''' and '''B''' are treated as addresses.   The number contained in address '''A''' is subtracted from the number in address '''B'''   (and the resultdifference stored backleft in address '''B'''). &nbspIf the result is positive, execution continues uninterrupted; Ifif the result is zero or negative, the numberinstruction inpointer is set to '''C''' becomes the new instruction pointer.
:#   If the instruction pointer becomes negative, execution halts.
 
Your solution may initialize the emulated machine's memory in any convenient manner, but if you accept it as input, it should be a separate input stream from the one fed to the emulated machine once it is running. And if fed as text input, it should be in the form of raw subleq "machine code" - whitespace-separated decimal numbers, with no symbolic names or other assembly-level extensions, to be loaded into memory starting at address   '''0'''   (zero).
Your solution should accept as input a program to execute on the machine, separately from the input fed to the emulated machine once it is running.
 
This program should be in the form of raw subleq "machine code" - whitespace-separated decimal numbers, with no symbolic names or other assembly-level extensions, to be loaded into memory starting at address   '''0'''   (zero).
 
For purposes of this task, show the output of your solution when fed the below   "Hello, world!"   program.
 
As written, thethis example assumes ASCII or a superset of it, such as any of the Latin-N character sets or Unicode;   you may translate the numbers representing characters (starting with 72=ASCII 'H') into another character set if your implementation runs in a non-ASCII-compatible environment. If 0 is not an appropriate terminator in your character set, the program logic will need some adjustment as well.
 
<pre>15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0</pre>
Line 35 ⟶ 33:
 
<pre>start:
0f 11 ff subleq (zero), (message), -1 ; subtract 0 from next character value to print;
; terminate if it's <=0
11 ff ff output (message)
1011 01ff ff subleq (neg1message), (start+-1), -1 ; output character
10 0301 ff subleq (neg1), (start+31), -1 ; modify above two instructions by subtracting -1
0f10 0f03 00ff subleq (zeroneg1), (zerostart+3), start-1 ; (adding 1) to their target addresses
0f 0f 00 subleq (zero), (zero), start ; if 0-0 <= 0 (i.e. always) goto start
 
; useful constants
zero:
Line 53:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">F subleq(&a)
V i = 0
L i >= 0
Line 68:
 
subleq(&[15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1, 72,
101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 10, 0])</langsyntaxhighlight>
 
{{out}}
Line 77:
=={{header|8080 Assembly}}==
 
<langsyntaxhighlight lang="8080asm"> ;;; ---------------------------------------------------------------
;;; SUBLEQ for CP/M. The word size is 16 bits, and the program
;;; is given 16 Kwords (32 KB) of memory. (If the system doesn't
Line 421:
emem: db 'Memory error$'
einv: db 'Invalid integer: '
eiloc: db ' $' </langsyntaxhighlight>
 
=={{header|8086 Assembly}}==
Line 427:
This program reads a file given on the command line. Optional CR/LF translation is included, for SUBLEQ programs that expect the UNIX line ending convention. The word size is 16 bits, and the program is given 64 KB (32 Kwords) of memory.
 
<langsyntaxhighlight lang="asm"> ;;; -------------------------------------------------------------
;;; SUBLEQ interpreter that runs under MS-DOS.
;;; The word size is 16 bits, and the SUBLEQ program gets a 64KB
Line 716:
fbuf: resb RBUFSZ ; File buffer
stack: resw 128 ; 128 words for main stack (should be enough)
memtop: equ $</langsyntaxhighlight>
 
=={{header|Ada}}==
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO;
 
procedure Subleq is
Line 786:
Execute_Program(Memory);
end Subleq;</langsyntaxhighlight>
 
<pre>>./subleq
Line 794:
 
=={{header|ALGOL 68}}==
<langsyntaxhighlight lang="algol68"># Subleq program interpreter #
# executes the program specified in code, stops when the instruction pointer #
# becomes negative #
Line 841:
)
)
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 849:
=={{header|ALGOL W}}==
{{Trans|Algol 68}}
<langsyntaxhighlight lang="algolw">% Subleq program interpreter %
begin
 
Line 914:
end
 
end.</langsyntaxhighlight>
{{out}}
<pre>
Line 922:
{{works with|GNU APL}}
 
<langsyntaxhighlight APLlang="apl">#!/usr/local/bin/apl -s --
⎕IO←0 ⍝ Index origin 0 is more intuitive with 'pointers'
∇Subleq;fn;text;M;A;B;C;X
Line 951:
Subleq
)OFF
</syntaxhighlight>
</lang>
 
 
=={{header|ARM Assembly}}==
<syntaxhighlight lang="text"> @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@ ARM SUBLEQ for Linux @@@
@@@ Word size is 32 bits. The program is @@@
Line 1,103:
prog: .space 0x400000 @ Lower half of program memory
fbuf: .space 0x400000 @ File buffer and top half of program memory
mem_end = .</langsyntaxhighlight>
 
{{out}}
Line 1,111:
$ ./subleq hello.sub
Hello, world!</pre>
 
=={{header|Arturo}}==
<syntaxhighlight lang="arturo">run: function [prog][
mem: new prog
ip: 0
while [ip >= 0][
A: mem\[ip]
B: mem\[ip+1]
C: mem\[ip+2]
 
ip: ip + 3
 
if? A = neg 1 -> mem\[B]: to :integer first input ""
else [
if? B = neg 1 -> prints to :char mem\[A]
else [
mem\[B]: mem\[B] - mem\[A]
if mem\[B] =< 0 -> ip: C
]
]
 
]
]
 
test: @[15, 17, neg 1, 17, neg 1, neg 1, 16, 1, neg 1, 16, 3, neg 1, 15, 15, 0, 0, neg 1,
72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 10, 0]
 
run test</syntaxhighlight>
 
{{out}}
 
<pre>Hello, world!</pre>
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f SUBLEQ.AWK SUBLEQ.TXT
# converted from Java
Line 1,156 ⟶ 1,188:
exit(0)
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,166 ⟶ 1,198:
Hello, world!
</pre>
 
=={{header|BASIC}}==
{{works with|GW-BASIC}}
{{works with|QBasic}}
<syntaxhighlight lang="basic">10 DEFINT A-Z: DIM M(8192)
20 INPUT "Filename";F$
30 OPEN "I",1,F$
40 GOTO 70
50 INPUT #1,M(I)
60 I=I+1
70 IF EOF(1) THEN CLOSE(1) ELSE GOTO 50
80 I=0
90 A=M(I): B=M(I+1): C=M(I+2): I=I+3
100 IF A=-1 GOTO 150 ELSE IF B=-1 GOTO 190
120 M(B) = M(B) - M(A)
130 IF M(B)<=0 THEN I=C
140 IF I>=0 GOTO 90 ELSE END
150 A$ = INPUT$(1): PRINT A$;
160 C = ASC(A$): IF C=13 THEN C=10
170 M(B) = C
180 GOTO 90
190 IF M(A)=10 THEN PRINT ELSE PRINT(CHR$(M(A) AND 255));
200 GOTO 90</syntaxhighlight>
{{out}}
<pre>Filename? HELLO.SUB
Hello, world!</pre>
 
==={{header|BASIC256}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="vbnet">dim memoria(255)
contador = 0
 
input "SUBLEQ> ", codigo
 
while instr(codigo, " ")
memoria[contador] = int(left(codigo, instr(codigo, " ") - 1))
codigo = mid(codigo, instr(codigo, " ") + 1, length(codigo))
contador += 1
end while
 
memoria[contador] = int(codigo)
contador = 0
do
a = memoria[contador]
b = memoria[contador + 1]
c = memoria[contador + 2]
contador += 3
if a = -1 then
input "SUBLEQ> ", caracter
memoria[b] = asc(caracter)
else
if b = -1 then
print chr(memoria[a]);
else
memoria[b] -= memoria[a]
if memoria[b] <= 0 then contador = c
end if
end if
until contador < 0</syntaxhighlight>
 
==={{header|FreeBASIC}}===
<syntaxhighlight lang="vbnet">
Dim As Integer memoria(255), contador = 0
Dim As String codigo, caracter
 
Input "SUBLEQ> ", codigo
 
While Instr(codigo, " ")
memoria(contador) = Val(Left(codigo, Instr(codigo, " ") - 1))
codigo = Mid(codigo, Instr(codigo, " ") + 1)
contador += 1
Wend
 
memoria(contador) = Val(codigo)
contador = 0
Do
Dim As Integer a = memoria(contador)
Dim As Integer b = memoria(contador + 1)
Dim As Integer c = memoria(contador + 2)
contador += 3
If a = -1 Then
Input "SUBLEQ> ", caracter
memoria(b) = Asc(caracter)
Else
If b = -1 Then
Print Chr(memoria(a));
Else
memoria(b) -= memoria(a)
If memoria(b) <= 0 Then contador = c
End If
End If
Loop Until contador < 0
Sleep</syntaxhighlight>
{{out}}
<pre>SUBLEQ> 15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0
Hello, world!</pre>
 
==={{header|Gambas}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="vbnet">Public memoria[255] As Integer
 
Public Sub Main()
Dim contador As Integer = 0
Dim codigo As String, caracter As String
Print "SUBLEQ> ";
Input codigo
While InStr(codigo, " ")
memoria[contador] = Val(Left(codigo, InStr(codigo, " ") - 1))
codigo = Mid(codigo, InStr(codigo, " ") + 1)
contador += 1
Wend
memoria[contador] = Val(codigo)
contador = 0
Do
Dim a As Integer = memoria[contador]
Dim b As Integer = memoria[contador + 1]
Dim c As Integer = memoria[contador + 2]
contador += 3
If a = -1 Then
Print "SUBLEQ> ";
Input caracter
memoria[b] = Asc(caracter)
Else
If b = -1 Then
Print Chr(memoria[a]);
Else
memoria[b] -= memoria[a]
If memoria[b] <= 0 Then contador = c
End If
End If
Loop Until contador < 0
 
End</syntaxhighlight>
 
==={{header|GW-BASIC}}===
The [[#BASIC|BASIC]] solution works without any changes.
 
==={{header|QBasic}}===
The [[#BASIC|BASIC]] solution works without any changes.
 
==={{header|Yabasic}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="vbnet">dim memoria(255)
contador = 0
input "SUBLEQ> " codigo$
while instr(codigo$, " ")
memoria(contador) = val(left$(codigo$, instr(codigo$, " ") - 1))
codigo$ = mid$(codigo$,instr(codigo$," ")+1,len(codigo$))
contador = contador + 1
wend
 
memoria(contador) = val(codigo$)
contador = 0
repeat
a = memoria(contador)
b = memoria(contador+ 1)
c = memoria(contador+ 2)
contador = contador + 3
if a = -1 then
input "SUBLEQ> " caracter$
memoria(b) = asc(caracter$)
else
if b = -1 then
print chr$(memoria(a));
else
memoria(b) = memoria(b) - memoria(a)
if memoria(b) <= 0 contador = c
fi
fi
until contador < 0
end</syntaxhighlight>
 
=={{header|BBC BASIC}}==
The BBC BASIC implementation reads the machine code program as a string from standard input and stores it in an array of signed 32-bit integers. The default size of the array is 256, but other values could easily be substituted. No attempt is made to handle errors arising from invalid Subleq programs.
<langsyntaxhighlight lang="bbcbasic">REM >subleq
DIM memory%(255)
counter% = 0
Line 1,196 ⟶ 1,403:
ENDIF
ENDIF
UNTIL counter% < 0</langsyntaxhighlight>
 
Output:
<pre>SUBLEQ> 15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0
Hello, world!</pre>
 
=={{header|BCPL}}==
<syntaxhighlight lang="bcpl">get "libhdr"
 
// Read a string
let reads(v) be
$( let ch = ?
v%0 := 0
ch := rdch()
until ch = '*N' do
$( v%0 := v%0 + 1
v%(v%0) := ch
ch := rdch()
$)
$)
 
// Try to read a number, fail on EOF
// (Alas, the included READN just returns 0 and that's a valid number)
let readnum(n) = valof
$( let neg, ch = false, ?
!n := 0
$( ch := rdch()
if ch = endstreamch then resultis false
$) repeatuntil ch = '-' | '0' <= ch <= '9'
if ch = '-' then
$( neg := true
ch := rdch()
$)
while '0' <= ch <= '9' do
$( !n := !n * 10 + ch - '0'
ch := rdch()
$)
if neg then !n := -!n
resultis true
$)
 
// Read SUBLEQ code
let readfile(file, v) = valof
$( let i, oldin = 0, input()
selectinput(file)
while readnum(v+i) do i := i + 1
endread()
selectinput(oldin)
resultis i
$)
 
// Run SUBLEQ code
let run(v) be
$( let ip = 0
until ip < 0 do
$( let a, b, c = v!ip, v!(ip+1), v!(ip+2)
ip := ip + 3
test a=-1
then v!b := rdch()
else test b=-1
then wrch(v!a)
else
$( v!b := v!b - v!a
if v!b <= 0 then ip := c
$)
$)
$)
 
let start() be
$( let filename = vec 64
let file = ?
writes("Filename? ")
reads(filename)
file := findinput(filename)
test file = 0 then
writes("Cannot open file.*N")
else
$( let top = maxvec()
let mem = getvec(top)
let progtop = readfile(file, mem)
for i = progtop to top do mem!i := 0
run(mem)
freevec(mem)
$)
$)</syntaxhighlight>
{{out}}
<pre>Filename? hello.sub
Hello, world!</pre>
 
Line 1,209 ⟶ 1,500:
Also note that in some buggy interpreters you may need to pad the Befunge playfield with additional blank lines or spaces in order to initialise a writable memory area (without which the Subleq source may fail to load).
 
<langsyntaxhighlight lang="befunge">01-00p00g:0`*2/00p010p0>$~>:4v4:-1g02p+5/"P"\%"P":p01+1:g01+g00*p02+1_v#!`"/":<
\0_v#-"-":\1_v#!`\*84:_^#- *8< >\#%"P"/#:5#<+g00g-\1+:"P"%\"P"v>5+#\*#<+"0"-~>^
<~0>#<$#-0#\<>$0>:3+\::"P"%\"P"/5+g00g-:1+#^_$:~>00gvv0gp03:+5/"P"\p02:%"P":< ^
>>>>>> , >>>>>> ^$p+5/"P"\%"P":-g00g+5/"P"\%"P":+1\+<>0g-\-:0v>5+g00g-:1+>>#^_$
-:0\`#@_^<<<<<_1#`-#0:#p2#g5#08#3*#g*#0%#2\#+2#g5#08#<**/5+g00g</langsyntaxhighlight>
 
{{out}}
<pre>15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0
Hello, world!</pre>
 
=={{header|BQN}}==
Since Subleq programs can potentially run forever, this program prints each character with a newline.
 
<syntaxhighlight lang="bqn">
# Helpers
_while_ ← {𝔽⍟𝔾∘𝔽_𝕣_𝔾∘𝔽⍟𝔾𝕩}
ToNum ← {neg ← '-'=⊑𝕩 ⋄ (¯1⋆neg)×10⊸×⊸+˜´·⌽-⟜'0'neg↓𝕩}
 
Subleq ← {
𝕊 memory:
{
𝕊 ip‿mem:
{
¯1‿b‿·: ⟨ip+3, (@-˜•term.CharB@)⌾(b⊸⊑) mem⟩;
a‿¯1‿·: •Out @+a⊑mem, ⟨ip+3, mem⟩;
a‿b‿c : d ← b-○(⊑⟜mem)a, ⟨(0<d)⊑⟨c, ip+3⟩, d⌾(b⊸⊑) mem⟩
} mem⊏˜ip+↕3
} _while_ {𝕊 ip‿mem: ip≥0} 0‿memory
}
 
Subleq ToNum¨•args</syntaxhighlight>
<syntaxhighlight lang="text">$ cbqn subleq.bqn 15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0
H
e
l
l
o
,
 
w
o
r
l
d
!
</syntaxhighlight>
 
=={{header|C}}==
Takes the subleq instruction file as input, prints out usage on incorrect invocation.
<syntaxhighlight lang="c">#include <stdlib.h>
<lang C>
#include <stdlibstdio.h>
#include<stdio.h>
 
void
void subleq(int* code){
subleq(int *code)
int ip = 0, a, b, c, nextIP,i;
{
int ip = 0, a, b, c, nextIP;
char ch;
while(0 <= ip) {
while(0<=ip){
nextIP = ip + 3;
a = code[ip];
b = code[ip + 1];
c = code[ip + 2];
if(a == -1) {
scanf("%c", &ch);
if(a==-1){
scanf("%c",&ch);
code[b] = (int)ch;
} else if(b == -1) {
}
printf("%c", (char)code[a]);
else if(b==-1){
} else {
printf("%c",(char)code[a]);
}
else{
code[b] -= code[a];
if(code[b] <= 0)
nextIP = c;
}
Line 1,251 ⟶ 1,576:
}
 
void
void processFile(char* fileName){
processFile(char *fileName)
{
int *dataSet, i, num;
FILE *fp = fopen(fileName, "r");
fscanf(fp, "%d", &num);
FILE* fp = fopen(fileName,"r");
dataSet = (int *)malloc(num * sizeof(int));
fscanffor(fp,"%d",&i = 0; i < num); i++)
fscanf(fp, "%d", &dataSet[i]);
dataSet = (int*)malloc(num*sizeof(int));
for(i=0;i<num;i++)
fscanf(fp,"%d",&dataSet[i]);
fclose(fp);
subleq(dataSet);
}
 
int
int main(int argC,char* argV[])
main(int argC, char *argV[])
{
if(argC != 2)
printf("Usage : %s <subleq code file>\n", argV[0]);
else
processFile(argV[1]);
return 0;
}
</syntaxhighlight>
</lang>
Input file (subleqCode.txt), first row contains the number of code points ( integers in 2nd row):
<pre>
Line 1,290 ⟶ 1,612:
=={{header|C sharp|C#}}==
{{trans|Java}}
<langsyntaxhighlight lang="csharp">using System;
 
namespace Subleq {
Line 1,326 ⟶ 1,648:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>Hello, world!</pre>
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">
#include <fstream>
#include <iostream>
Line 1,378 ⟶ 1,700:
return 0;
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,385 ⟶ 1,707:
Hello, world!
</pre>
 
=={{header|CLU}}==
<syntaxhighlight lang="clu">% Read numbers from a stream
read_nums = iter (s: stream) yields (int)
while true do
c: char := stream$getc(s)
while c~='-' & ~(c>='0' & c<='9') do
c := stream$getc(s)
end
acc: int := 0
neg: bool
if c='-' then
neg := true
c := stream$getc(s)
else
neg := false
end
while c>='0' & c<='9' do
acc := acc*10 + char$c2i(c) - char$c2i('0')
c := stream$getc(s)
except when end_of_file: break end
end
if neg then acc := -acc end
yield(acc)
end except when end_of_file: end
end read_nums
% Auto-resizing array
mem = cluster is new, load, fetch, store
rep = array[int]
new = proc () returns (cvt)
return(rep$predict(0,2**9))
end new
fill_to = proc (a: rep, lim: int)
while rep$high(a) < lim do rep$addh(a,0) end
end fill_to
fetch = proc (a: cvt, n: int) returns (int) signals (bounds)
fill_to(a,n)
return(a[n]) resignal bounds
end fetch
store = proc (a: cvt, n: int, v: int) signals (bounds)
fill_to(a,n)
a[n] := v resignal bounds
end store
load = proc (a: cvt, s: stream)
i: int := 0
for n: int in read_nums(s) do
up(a)[i] := n
i := i + 1
end
end load
end mem
 
% Run a Subleq program
subleq = proc (m: mem, si, so: stream)
ip: int := 0
while ip >= 0 do
a: int := m[ip]
b: int := m[ip+1]
c: int := m[ip+2]
ip := ip + 3
if a=-1 then m[b] := char$c2i(stream$getc(si))
elseif b=-1 then stream$putc(so,char$i2c(m[a] // 256))
else
m[b] := m[b] - m[a]
if m[b] <= 0 then ip := c end
end
end
end subleq
 
start_up = proc ()
pi: stream := stream$primary_input()
po: stream := stream$primary_output()
args: sequence[string] := get_argv()
if sequence[string]$size(args) ~= 1 then
stream$putl(stream$error_output(), "Usage: subleq file_name")
return
end
fname: file_name := file_name$parse(sequence[string]$bottom(args))
file: stream := stream$open(fname, "read")
m: mem := mem$new()
mem$load(m, file)
stream$close(file)
subleq(m, pi, po)
end start_up</syntaxhighlight>
{{out}}
<pre>$ cat hello.sub
15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0
$ ./subleq hello.sub
Hello, world!</pre>
 
=={{header|COBOL}}==
For compatibility with online COBOL compilers, where file IO is not supported, this implementation reads the Subleq program from the console. Note that COBOL tables (arrays) are indexed from 1 rather than 0, and so are character sets: in an ASCII environment 'A' is coded as 66 (the sixty-sixth character), not 65.
<langsyntaxhighlight lang="cobol">identification division.
program-id. subleq-program.
data division.
Line 1,468 ⟶ 1,887:
if memory(adjusted-index-b) is equal to zero
or memory(adjusted-index-b) is negative
then move c to instruction-pointer.</langsyntaxhighlight>
{{out}}
<pre>READING SUBLEQ PROGRAM... 0032 WORDS READ.
Line 1,476 ⟶ 1,895:
 
HALTED AFTER 0073 INSTRUCTIONS.</pre>
 
=={{header|Commodore BASIC}}==
The sample program is the one from the task description with a slightly different text string: it starts with the control code to convert to mixed-case mode (14), and the rest
is in PETSCII rather than standard ASCII.
 
<syntaxhighlight lang="basic">100 READ N:REM SIZE OF PROGRAM
110 DIM M%(N-1)
120 FOR I=1 TO N
130 : READ M%(I-1)
140 NEXT I
150 IP=0
160 FOR D=0 TO 1 STEP 0
170 : IF IP < 0 OR IP > N-3 THEN D=1:GOTO 290
180 : A=M%(IP):B=M%(IP+1):C=M%(IP+2)
190 : IP=IP+3
200 : IF A >= 0 THEN 240
210 : GET K$: IF K$="" THEN 210
220 : M%(B) = ASC(K$)
230 : GOTO 290
240 : IF B >= 0 THEN 270
250 : PRINT CHR$(M%(A));
260 : GOTO 290
270 : M%(B)=M%(B)-M%(A)
280 : IF M%(B) <= 0 THEN IP=C
290 NEXT D
300 END
310 DATA 33
320 DATA 15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1
330 DATA 14, 200, 69, 76, 76, 79, 44, 32, 87, 79, 82, 76, 68, 33, 13, 0</syntaxhighlight>
 
{{Out}}
<pre>Hello, world!</pre>
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defun run (memory)
(loop for pc = 0 then next-pc
until (minusp pc)
Line 1,498 ⟶ 1,949:
(let ((memory (vector 15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72
101 108 108 111 44 32 119 111 114 108 100 33 10 0)))
(run memory)))</langsyntaxhighlight>
{{out}}<pre>Hello, world!</pre>
 
=={{header|D}}==
<langsyntaxhighlight Dlang="d">import std.stdio;
 
void main() {
Line 1,534 ⟶ 1,985:
instructionPointer += 3;
} while (instructionPointer >= 0);
}</langsyntaxhighlight>
 
{{out}}
Line 1,541 ⟶ 1,992:
=={{header|Delphi}}==
{{Trans|Java}}
<syntaxhighlight lang="delphi">
<lang Delphi>
program SubleqTest;
 
Line 1,586 ⟶ 2,037:
readln;
end.
</syntaxhighlight>
</lang>
 
=={{header|Draco}}==
<syntaxhighlight lang="draco">\util.g
 
proc nonrec rdch() byte:
char c;
if read(c) then
pretend(c, byte)
else
case ioerror()
incase CH_MISSING: readln(); 10
default: 0
esac
fi
corp
 
proc nonrec wrch(byte b) void:
if b=10
then writeln()
else write(pretend(b, char))
fi
corp
 
proc nonrec main() void:
[16384] int mem;
file() srcfile;
channel input text srcch;
*char fname;
int a, b, c, i;
byte iob;
BlockFill(pretend(&mem[0], *byte), sizeof(byte), 0);
fname := GetPar();
if fname = nil then
writeln("usage: SUBLEQ filename");
exit(1);
fi;
if not open(srcch, srcfile, fname) then
writeln("Cannot open input file");
exit(1)
fi;
i := 0;
while read(srcch; mem[i]) do i := i + 1 od;
close(srcch);
i := 0;
while i>=0 do
a := mem[i];
b := mem[i+1];
c := mem[i+2];
i := i + 3;
if a=-1 then mem[b] := rdch()
elif b=-1 then wrch(mem[a])
else
mem[b] := mem[b] - mem[a];
if mem[b] <= 0 then i := c fi
fi
od
corp</syntaxhighlight>
{{out}}
<pre>A>type hello.sub
15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0
 
A>subleq hello.sub
Hello, world!</pre>
 
=={{header|EasyLang}}==
{{trans|FreeBASIC}}
<syntaxhighlight>
global inpos inp$ .
func inp .
if inpos = 0
inp$ = input
if error = 1
return 255
.
inpos = 1
.
if inpos <= len inp$
h = strcode substr inp$ inpos 1
inpos += 1
return h
.
inpos = 0
return 10
.
proc subleq . mem[] .
repeat
a = mem[p]
b = mem[p + 1]
c = mem[p + 2]
p += 3
if a = -1
mem[b] = inp
elif b = -1
write strchar mem[a]
else
mem[b] -= mem[a]
if mem[b] <= 0
p = c
.
.
until p < 0
.
.
prog[] = [ 15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0 ]
arrbase prog[] 0
#
subleq prog[]
#
input_data
dummy data
</syntaxhighlight>
 
 
=={{header|Forth}}==
Note that Forth is stack oriented. Hence, the code is toggled in in reverse.
<syntaxhighlight lang="text">create M 32 cells allot
 
: enter refill drop parse-word evaluate ; : M[] cells M + ;
Line 1,603 ⟶ 2,172:
-1 0 0 15 15 -1 3 16 -1 1 16 -1 -1 17 -1 17 15
 
init subleq</langsyntaxhighlight>
{{out}}
<pre>init subleq
Line 1,616 ⟶ 2,185:
But Fortran 90 introduced the ability to specify the lower bounds of an array, so MEM(0:LOTS) is available without difficulty, and formulae may be translated with greater ease: handling offsets is a simple clerical task; computers excel at simple clerical tasks, so, let the computer do it. Otherwise, the following code would work with F77, except possibly for the odd usage of $ in a FORMAT statement so that each character of output is not on successive lines.
 
<syntaxhighlight lang="fortran">
<lang Fortran>
PROGRAM SUBLEQ0 !Simulates a One-Instruction computer, with Subtract and Branch if <= 0.
INTEGER LOTS,LOAD !Document some bounds.
Line 1,646 ⟶ 2,215:
IF (IAR.GE.0) GO TO 100 !Keep at it.
END !That was simple.
</syntaxhighlight>
</lang>
For simplicity there are no checks on memory bounds or endless looping, nor any trace output. The result is
<pre>
Line 1,654 ⟶ 2,223:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,700 ⟶ 2,269:
log.Fatalln("write:", err)
}
}</langsyntaxhighlight>
A much longer version using types, methods, etc
and that supports supplying a program via a file or the command line,
Line 1,708 ⟶ 2,277:
=={{header|Haskell}}==
Inspired by the Racket solution.
<langsyntaxhighlight Haskelllang="haskell">{-# LANGUAGE FlexibleContexts #-}
import Control.Monad.State
import Data.Char (chr, ord)
Line 1,737 ⟶ 2,306:
zip [0..]
[15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33, 10, 0]
</syntaxhighlight>
</lang>
 
=={{header|J}}==
 
<langsyntaxhighlight Jlang="j">readchar=:3 :0
if.0=#INBUF do. INBUF=:LF,~1!:1]1 end.
r=.3 u:{.INBUF
Line 1,767 ⟶ 2,336:
end.
OUTBUF
)</langsyntaxhighlight>
 
Example:
 
<langsyntaxhighlight Jlang="j"> subleq 15 17 _1 17 _1 _1 16 1 _1 16 3 _1 15 15 0 0 _1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0
Hello, world!</langsyntaxhighlight>
 
=={{header|Janet}}==
<syntaxhighlight lang="clojure">(defn main [& args]
(let [filename (get args 1)
fh (file/open filename)
program (file/read fh :all)
memory (eval-string (string "@[" program "]"))
size (length memory)]
 
(var pc 0)
 
(while (<= 0 pc size)
(let [a (get memory pc)
b (get memory (inc pc))
c (get memory (+ pc 2))]
(set pc (+ pc 3))
(cond
(< a 0) (put memory b (first (file/read stdin 1)))
(< b 0) (file/write stdout (buffer/push-byte @"" (get memory a)))
true
(do
(put memory b (- (get memory b) (get memory a)))
(if (<= (get memory b) 0)
(set pc c))))))))</syntaxhighlight>
 
{{Out}}
<pre>$ janet subleq.janet hello.sq
Hello, world!
</pre>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import java.util.Scanner;
 
public class Subleq {
Line 1,809 ⟶ 2,407:
} while (instructionPointer >= 0);
}
}</langsyntaxhighlight>
 
<pre>Hello, world!</pre>
Line 1,824 ⟶ 2,422:
or some post-processing. The output shown below assumes the -j
(--join-output) command-line option is available.
<langsyntaxhighlight lang="jq"># If your jq has while/2 then the following definition can be omitted:
def while(cond; update):
def _while: if cond then ., (update | _while) else empty end;
Line 1,855 ⟶ 2,453:
 
subleq([15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1,
72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 10, 0])</langsyntaxhighlight>
{{out}}
<langsyntaxhighlight lang="sh">$ jq -r -j -n -f subleq.jq
Hello, world!</langsyntaxhighlight>
 
=={{header|Julia}}==
Line 1,864 ⟶ 2,462:
 
'''Module''':
<langsyntaxhighlight lang="julia">module Subleq
using OffsetArrays
Line 1,894 ⟶ 2,492:
end # module Subleq
</syntaxhighlight>
</lang>
 
'''Main''':
<langsyntaxhighlight lang="julia">using .Subleq
 
print(Subleq.interpret("15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101
108 108 111 44 32 119 111 114 108 100 33 10 0"))
</langsyntaxhighlight>{{out}}
<pre>
Hello, world!
Line 1,907 ⟶ 2,505:
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.1.2
 
fun subleq(program: String) {
Line 1,937 ⟶ 2,535:
val program = "15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0"
subleq(program)
}</langsyntaxhighlight>
 
{{out}}
Line 1,945 ⟶ 2,543:
 
=={{header|Logo}}==
<langsyntaxhighlight lang="logo">make "memory (array 32 0)
 
to load_subleq
Line 1,983 ⟶ 2,581:
load_subleq
run_subleq
bye</langsyntaxhighlight>
 
{{Out}}
Line 1,992 ⟶ 2,590:
 
=={{header|Lua}}==
<langsyntaxhighlight Lualang="lua">function subleq (prog)
local mem, p, A, B, C = {}, 0
for word in prog:gmatch("%S+") do
Line 2,013 ⟶ 2,611:
end
 
subleq("15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0")</langsyntaxhighlight>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
{{trans|R}}
<syntaxhighlight lang="mathematica">ClearAll[memory, MemoryGet, MemorySet, MemorySubtract]
memory = {15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0,
0, -1, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33,
10, 0};
MemoryGet[addr_] := memory[[addr + 1]]
MemorySet[addr_, value_] := memory[[addr + 1]] = value
MemorySubtract[addr1_, addr2_] := MemorySet[addr1, MemoryGet[addr1] - MemoryGet[addr2]]
p = 0;
While[p >= 0,
a = MemoryGet[p];
b = MemoryGet[p + 1];
c = MemoryGet[p + 2];
If[b == -1,
Print[FromCharacterCode[MemoryGet[a]]]
,
MemorySubtract[b, a];
If[MemoryGet[b] < 1,
p = MemoryGet[p + 2];
Continue[]
]
];
p += 3;
]</syntaxhighlight>
{{out}}
<pre>H
e
l
l
o
,
w
o
r
l
d
!
 
</pre>
 
 
=={{header|MiniScript}}==
<langsyntaxhighlight MiniScriptlang="miniscript">memory = []
step = 3
currentAddress = 0
Line 2,054 ⟶ 2,694:
print out
print "-------------------"
print "Execution Complete"</langsyntaxhighlight>
{{out}}
<pre>
Line 2,069 ⟶ 2,709:
 
=={{header|Modula-2}}==
<langsyntaxhighlight lang="modula2">MODULE Subleq;
FROM Terminal IMPORT Write,WriteString,WriteLn,ReadChar;
 
Line 2,108 ⟶ 2,748:
 
ReadChar
END Subleq.</langsyntaxhighlight>
=={{header|Nim}}==
<langsyntaxhighlight lang="nim">import streams
 
type
Interpreter = object
mem: seq[int]
ip: int
input, output: Stream
 
proc load(prog: seq[int], inp,outp: Stream): Interpreter = Interpreter(
proc load(prog: openArray[int]; inp, outp: Stream): Interpreter =
mem: prog, input: inp, output: outp)
Interpreter(mem: prog, input: inp, output: outp)
 
proc run(i: var Interpreter) =
Line 2,134 ⟶ 2,776:
i.ip = C
 
let test = @[15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1, 72,
72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 10, 0]
var intr = load(test, newFileStream(stdin), newFileStream(stdout))
 
try:
intr.run()
except IndexDefect:
echo "ip: ", intr.ip
echo "mem: ", intr.mem</syntaxhighlight>
 
</lang>
{{out}}
<pre>Hello, world!</pre>
 
=={{header|Objeck}}==
{{trans|Java}}
<langsyntaxhighlight lang="objeck">use System.IO;
 
class Sublet {
Line 2,183 ⟶ 2,828:
while (instructionPointer >= 0);
}
}</langsyntaxhighlight>
 
<pre>
Line 2,191 ⟶ 2,836:
=={{header|Oforth}}==
 
<langsyntaxhighlight lang="oforth">: subleq(program)
| ip a b c newb |
program asListBuffer ->program
Line 2,206 ⟶ 2,851:
[15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 10, 0 ]
subleq</langsyntaxhighlight>
 
=={{header|ooRexx}}==
Line 2,212 ⟶ 2,857:
{{trans|REXX}}
reformatted and long variable names that suit all Rexxes.
<langsyntaxhighlight lang="oorexx">/*REXX program simulates execution of a One-Instruction Set Computer (OISC). */
Signal on Halt /*enable user to halt the simulation. */
cell.=0 /*zero-out all of real memory locations*/
Line 2,249 ⟶ 2,894:
Return cell._ /*return the contents of "memory" loc _*/
halt: Say 'REXX program halted by user.'
Exit 1</langsyntaxhighlight>
{{out}}
<pre>Hello, world!</pre>
Line 2,257 ⟶ 2,902:
Using an array object instead of a stem for cells.
<br>Array indexes must be positive!
<langsyntaxhighlight lang="oorexx">/*REXX program simulates execution of a One-Instruction Set Computer (OISC). */
Signal on Halt /*enable user to halt the simulation. */
cell=.array~new /*zero-out all of real memory locations*/
Line 2,292 ⟶ 2,937:
Exit
halt: Say 'REXX program halted by user.';
Exit 1</langsyntaxhighlight>
 
=={{header|Pascal}}==
{{works with|Free Pascal|1.06}}
<langsyntaxhighlight lang="pascal">PROGRAM OISC;
 
CONST
Line 2,356 ⟶ 3,001:
LOADTEXT (FILENAME, MEM);
SUBLEQ (MEM);
END.</langsyntaxhighlight>
 
{{in}}
Line 2,367 ⟶ 3,012:
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">#!/usr/bin/env perl
use strict;
use warnings;
Line 2,391 ⟶ 3,036:
}
}
}</langsyntaxhighlight>
{{Output}}<pre>Hello, world!</pre>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>procedure subleq(sequence code)
<span style="color: #008080;">procedure</span> <span style="color: #000000;">subleq</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">)</span>
integer ip := 0
<span style="color: #004080;">integer</span> <span style="color: #000000;">ip</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">0</span>
while ip>=0 do
<span style="color: #008080;">while</span> <span style="color: #000000;">ip</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0</span> <span style="color: #008080;">do</span>
integer {a,b,c} = code[ip+1..ip+3]
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ip</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">ip</span><span style="color: #0000FF;">+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span>
ip += 3
<span style="color: #000000;">ip</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">3</span>
if a=-1 then
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
code[b+1] = getc(0)
<span style="color: #000000;">code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">b</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: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span><span style="color: #0000FF;">?</span><span style="color: #008000;">'?'</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>
elsif b=-1 then
<span style="color: #008080;">elsif</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
puts(1,code[a+1])
<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;">code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">a</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
else
<span code[b+1] -style="color: code[a+1]#008080;">else</span>
<span style="color: #000000;">code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">b</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;">code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">a</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
if code[b+1]<=0 then
<span style="color: #008080;">if</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">b</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]<=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
ip := c
<span style="color: #000000;">ip</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">c</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
subleq({15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1,
<span style="color: #000000;">subleq</span><span style="color: #0000FF;">({</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">17</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">17</span><span style="color: #0000FF;">,</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;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">16</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;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">16</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
15, 15, 0, 0, -1, 72, 101, 108, 108, 111, 44, 32,
<span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">72</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">101</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">108</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">108</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">111</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">44</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">,</span>
119, 111, 114, 108, 100, 33, 10, 0})</lang>
<span style="color: #000000;">119</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">111</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">114</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">108</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">100</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">33</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 2,422 ⟶ 3,069:
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de mem (N)
(nth
(quote
Line 2,435 ⟶ 3,082:
((lt0 B) (prin (char (car (mem A)))))
((le0 (dec (mem B) (car (mem A))))
(setq IP (mem C)) ) ) ) )</langsyntaxhighlight>
Output:
<pre>Hello, world!</pre>
Line 2,441 ⟶ 3,088:
=={{header|PowerShell}}==
{{trans|Python}}
<syntaxhighlight lang="powershell">
<lang PowerShell>
function Invoke-Subleq ([int[]]$Program)
{
Line 2,479 ⟶ 3,126:
}
}
</syntaxhighlight>
</lang>
<syntaxhighlight lang="powershell">
<lang PowerShell>
Invoke-Subleq -Program 15,17,-1,17,-1,-1,16,1,-1,16,3,-1,15,15,0,0,-1,72,101,108,108,111,44,32,119,111,114,108,100,33,10,0
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Hello, world!
</pre>
 
=={{header|PureBasic}}==
<syntaxhighlight lang="purebasic">DataSection
StartData:
Data.i 15,17,-1,17,-1,-1,16,1,-1,16,3,-1,15,15,0,0,-1,72,101,108,108,111,44,32,119,111,114,108,100,33,10,0
StopData:
EndDataSection
 
If OpenConsole("Subleq")=0 : End 1 : EndIf
Dim code.i((?StopData-?StartData)/SizeOf(Integer)-1)
CopyMemory(?StartData,@code(0),?StopData-?StartData)
Define.i ip=0,a,b,c,nip
While 0<=ip
nip=ip+3 : a=code(ip) : b=code(ip+1) : c=code(ip+2)
If a=-1 : code(b)=Asc(Input())
ElseIf b=-1 : Print(Chr(code(a)))
Else : code(b)-code(a) : If code(b)<=0 : nip=c : EndIf
EndIf
ip=nip
Wend
Input()</syntaxhighlight>
 
=={{header|Python}}==
 
<langsyntaxhighlight lang="python">import sys
 
def subleq(a):
Line 2,512 ⟶ 3,180:
subleq([15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15,
0, 0, -1, 72, 101, 108, 108, 111, 44, 32, 119, 111,
114, 108, 100, 33, 10, 0])</langsyntaxhighlight>
 
=={{header|Quackery}}==
 
Quackery understands a subset of ASCII, namely the printable characters, 32 (space) and 13 (carriage return). To accommodate this, the 10 (line feed) at the end of Hello, world! has been replaced with a 13.
 
The input stream to the Subleq program is passed to <code>subleq</code> as a string, along with the Subleq code, which is a nest of numbers. <code>getch</code> puts successive characters from the string into the address given by A. When the string is exhausted, <code>getch</code> puts a 0.
 
In the task program no input is required, so the empty string is passed.
 
<code>subleq</code> returns the output stream as a string.
 
<syntaxhighlight lang="Quackery"> ( O = Output string I = Input string S = Subleq code )
[ stack 0 ] is ip ( --> s )
[ stack 0 ] is a ( --> s )
[ stack 0 ] is b ( --> s )
[ stack 0 ] is c ( --> s )
 
[ over $ "" = iff 0
else
[ swap behead dip swap ]
swap b share poke ] is getch ( O I S --> O I S )
 
[ dup a share peek
dip rot join unrot ] is putch ( O I S --> O I S )
 
[ $ "" unrot
0 ip replace
[ dup ip share
2dup peek a replace
2dup 1 + peek b replace
2 + peek c replace
3 ip tally
a share -1 = iff getch again
b share -1 = iff putch again
dup b share peek
over a share peek -
tuck dip [ b share poke ]
1 < until
c share dup ip replace
0 < until ]
2drop ] is subleq ( I S --> O )
 
$ ""
' [ 15 17 -1 17 -1 -1 16 1
-1 16 3 -1 15 15 0 0
-1 72 101 108 108 111 44 32
119 111 114 108 100 33 13 0 ]
subleq echo$</syntaxhighlight>
 
{{out}}
 
<pre>Hello, world!</pre>
 
=={{header|R}}==
 
<langsyntaxhighlight lang="rsplus">
mem <- c(15, 17, -1, 17, -1, -1, 16, 1,
-1, 16, 3, -1, 15, 15, 0, 0,
Line 2,543 ⟶ 3,264:
instructionPointer <- instructionPointer + 3
}
</syntaxhighlight>
</lang>
{{out}}
<pre>Hello, world!</pre>
Line 2,549 ⟶ 3,270:
=={{header|Racket}}==
{{trans|Go}} The negative addresses are treated as -1.
<langsyntaxhighlight Racketlang="racket">#lang racket
 
(define (subleq v)
Line 2,576 ⟶ 3,297:
0))
 
(subleq Hello)</langsyntaxhighlight>
{{out}}
<pre>Hello, world!</pre>
Line 2,583 ⟶ 3,304:
(formerly Perl 6)
{{trans|Perl}}
<syntaxhighlight lang="raku" line>my @hello-world =
<lang perl6>my @hello-world = <15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0>;
|<15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1>,
|"Hello, world!\n\0".comb.map(*.ord);
 
mysub run-subleq(@memory) = @hello-world;{
my $ip = 0;
while $ip >= 0 && $ip < @memory {
my ($a, $b, $c) = @memory[$ip, $ip+1, $ip+2..*];
$ip += 3;
if $a < 0 {
@memory[$b] = getc.ord;
} elsif $b < 0 {
print @memory[$a].chr;
} else {
if (@memory[$b] -= @memory[$a]) <= 0 {
$ip = $c;
}
}
}
}</lang>
}
 
run-subleq @hello-world;</syntaxhighlight>
 
{{out}}
Line 2,608 ⟶ 3,334:
 
The REXX language has no concept of a &nbsp; ''word'', &nbsp; but for storing numbers, the default is nine decimal digits.
<langsyntaxhighlight lang="rexx">/*REXX program simulates the execution of a One─Instruction Set Computer (OISC). */
signal on halt /*enable user to halt the simulation.*/
parse arg $ /*get optional low memory vals from CL.*/
Line 2,630 ⟶ 3,356:
/*──────────────────────────────────────────────────────────────────────────────────────*/
@: parse arg @z; return @.@z /*return a memory location (cell @Z).*/
halt: say 'The One─Instruction Set Computer simulation pgm was halted by user.'; exit 1</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
Hello, world!
</pre>
 
=={{header|RPL}}==
{{works with|HP|48G}}
« 'Ram' DUP ROT ←ptr + GET 1 + GET
» '<span style="color:blue">PEEKind</span>' STO <span style="color:grey">@ ''( n → Ram[Ram[←ptr + n]] )''</span>
« 0 "" → ←ptr stdout
« { } + RDM 'Ram' STO
'''WHILE''' ←ptr 0 ≥ '''REPEAT'''
'''CASE'''
'Ram' ←ptr 1 + GET -1 == '''THEN'''
'Ram' 2 <span style="color:blue">PEEKind</span> '''DO UNTIL''' KEY '''END''' PUT '''END'''
'Ram' ←ptr 2 + GET -1 == '''THEN'''
'stdout' 1 <span style="color:blue">PEEKind</span> CHR STO+ '''END'''
2 <span style="color:blue">PEEKind</span> 1 <span style="color:blue">PEEKind</span> -
'Ram' DUP ←ptr 2 + GET 1 + 3 PICK PUT
0 ≤ '''THEN'''
1 SF '''END'''
1 CF
'''END'''
'''IF''' 1 FS? '''THEN'''
'Ram' ←ptr 3 + GET '←ptr' STO
'''ELSE'''
3 '←ptr' STO+
'''END'''
'''END'''
stdout
» » '<span style="color:blue">SUBLEQ</span>' STO <span style="color:grey">@ ''( [ program ] mem_size → stdout ] )''</span>
 
[ 15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0 ] 256 <span style="color:blue">SUBLEQ</span>
{{out}}
<pre>
1: "Hello, world!
"
</pre>
 
=={{header|Ruby}}==
<langsyntaxhighlight Rubylang="ruby">class Computer
def initialize program
@memory = program.map{|instruction| instruction.&:to_i}
@instruction_pointer = 0
end
Line 2,654 ⟶ 3,415:
writechar @memory[a]
else
difference = @memory[b] -= @memory[a]
@memory[b] = difference
@instruction_pointer = c if difference <= 0
end
Line 2,680 ⟶ 3,440:
subleq = Computer.new ARGV
 
subleq.run</langsyntaxhighlight>
'''Sample usage:'''
<pre>
Line 2,689 ⟶ 3,449:
=={{header|Scala}}==
===Imperative, Javaish, destructible opcodes read===
<langsyntaxhighlight Scalalang="scala">import java.util.Scanner
 
object Subleq extends App {
Line 2,707 ⟶ 3,467:
instructionPointer += 3
} while (instructionPointer >= 0)
}</langsyntaxhighlight>
{{Out}}See it running in your browser by [https://scastie.scala-lang.org/f4MszRqZR5qtxI6YwarJhw Scastie (JVM)].
 
=={{header|SETL}}==
<syntaxhighlight lang="setl">program subleq;
if command_line(1) = om then
print("error: no file given");
stop;
end if;
 
mem := readprog(command_line(1));
 
loop init ip := 0; while ip >= 0 do
a := mem(ip) ? 0;
b := mem(ip+1) ? 0;
c := mem(ip+2) ? 0;
ip +:= 3;
if a = -1 then
mem(b) := ichar (getchar ? "\0");
elseif b = -1 then
putchar(char ((mem(a) ? 0) mod 256));
elseif (mem(b) +:= -(mem(a) ? 0)) <= 0 then
ip := c;
end if;
end loop;
 
proc readprog(fname);
if (f := open(fname, "r")) = om then
print("error: cannot open file");
stop;
end if;
 
mem := {};
mp := 0;
loop doing getb(f, n); while n/=om do
mem(mp) := n;
mp +:= 1;
end loop;
close(f);
return mem;
end proc;
end program;</syntaxhighlight>
{{out}}
<pre>$ cat hello.sub
15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0
$ setl subleq.setl hello.sub
Hello, world!</pre>
 
=={{header|Sidef}}==
{{trans|Raku}}
<langsyntaxhighlight lang="ruby">var memory = ARGV.map{.to_i};
var ip = 0;
 
Line 2,727 ⟶ 3,532:
ip = c
}
}</langsyntaxhighlight>
 
{{out}}
Line 2,739 ⟶ 3,544:
 
Requires at least 2k of RAM.
<langsyntaxhighlight lang="basic"> 10 DIM M(32)
20 INPUT P$
30 LET W=1
Line 2,771 ⟶ 3,576:
310 GOTO 160
320 PRINT CHR$ (M(A+1)-1);
330 GOTO 160</langsyntaxhighlight>
{{in}}
<pre>15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 46 43 50 50 53 27 1 61 53 56 50 42 28 118 0</pre>
{{out}}
<pre>HELLO, WORLD.</pre>
 
=={{header|SNOBOL4}}==
All "addresses" get 1 added to them before being used as array indexes.
<syntaxhighlight lang="snobol"> MEM = ARRAY('32')
MEM<1> = 15
MEM<2> = 17
MEM<3> = -1
MEM<4> = 17
MEM<5> = -1
MEM<6> = -1
MEM<7> = 16
MEM<8> = 1
MEM<9> = -1
MEM<10> = 16
MEM<11> = 3
MEM<12> = -1
MEM<13> = 15
MEM<14> = 15
MEM<15> = 0
MEM<16> = 0
MEM<17> = -1
MEM<18> = 72
MEM<19> = 101
MEM<20> = 108
MEM<21> = 108
MEM<22> = 111
MEM<23> = 44
MEM<24> = 32
MEM<25> = 119
MEM<26> = 111
MEM<27> = 114
MEM<28> = 108
MEM<29> = 100
MEM<30> = 33
MEM<31> = 10
MEM<32> = 0
 
INBUF =
OUTBUF =
BP = 0
IP = 0
 
LOOP GE(IP, 0) :F(DONE)
A = MEM<IP + 1>
B = MEM<IP + 2>
C = MEM<IP + 3>
IP = IP + 3
GE(A, 0) :S(NOIN)
 
LE(BP,SIZE(INBUF)) :S(GETCH)
INBUF = INPUT
BP = 1
 
GETCH &ALPHABET @N SUBSTR(INBUF,BP,1)
MEM<B + 1> = N
BP = BP + 1 :(LOOP)
 
NOIN GE(B, 0) :S(NOOUT)
 
EQ(MEM<A + 1>, 10) :F(PUTCH)
OUTPUT = OUTBUF
OUTBUF = :(LOOP)
 
PUTCH OUTBUF = OUTBUF CHAR(MEM<A + 1>) :(LOOP)
 
NOOUT MEM<B + 1> = MEM<B + 1> - MEM<A + 1>
LE(MEM<B + 1>, 0) :F(LOOP)
IP = C :(LOOP)
 
DONE EQ(SIZE(OUTBUF),0) :S(END)
OUTPUT = OUTBUF
END</syntaxhighlight>
 
{{Out}}
<pre>Hello, world!</pre>
 
=={{header|Swift}}==
Line 2,781 ⟶ 3,661:
{{trans|Python}}
 
<langsyntaxhighlight lang="swift">func subleq(_ inst: inout [Int]) {
var i = 0
Line 2,809 ⟶ 3,689:
 
subleq(&prog)
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,817 ⟶ 3,697:
=={{header|Tcl}}==
 
<syntaxhighlight lang="tcl">
<lang Tcl>
namespace import ::tcl::mathop::-
 
Line 2,842 ⟶ 3,722:
fconfigure stdout -buffering none
subleq {15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0}
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,848 ⟶ 3,728:
 
=={{header|uBasic/4tH}}==
<syntaxhighlight lang="text">GoSub _Initialize ' Initialize memory
 
i = 0 ' Reset instruction pointer
Line 2,899 ⟶ 3,779:
@(30) = 10 ' Replace with =ORD(c) when required
@(31) = 0
Return</langsyntaxhighlight>
{{out}}
<pre>Hello, world!
Line 2,907 ⟶ 3,787:
=={{header|UNIX Shell}}==
===dash===
<langsyntaxhighlight lang="bash">#!/bin/sh
 
mem="15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0 "
Line 2,949 ⟶ 3,829:
done
echo "Total step:"$STEP
</syntaxhighlight>
</lang>
===bash===
<langsyntaxhighlight lang="bash">#!/usr/bin/shenv bash
 
mem=(15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0 )
72 101 108 108 111 44 32 119 111 114 108 100 33 10 0)
 
ADDRaddr=0
STEPstep=0
 
while [[ $((STEP++ ))addr -lt>= 3000 )); ]]do
(( step++ ))
do
Aa=${mem[$ADDRaddr]}
Bb=${mem[(($ADDRaddr + 1))]}
Cc=${mem[(($ADDRaddr + 2))]}
ADDR=$((ADDR addr += 3 ))
if [[(( $Bb -lt< 0 ]])); then
printf '%b' '\x'$(printf '%x' ${mem[$Aa]})
else
mem[$B]=$if ((${ (mem[$Bb]} -= ${mem[$Aa]}) <= 0 )); then
addr=$c
if [[ ${mem[$B]} -le 0 ]]; then
if [[ $C -eq -1 ]]; then
echo "Total step:"$STEP
exit 0
fi
ADDR=$C
fi
fi
done
echoprintf "'Total step:%d\n' "$STEPstep"
</syntaxhighlight>
</lang>
 
=={{header|Wren}}==
{{trans|Kotlin}}
<langsyntaxhighlight ecmascriptlang="wren">import "io" for Stdin, Stdout
 
var subleq = Fn.new { |program|
Line 3,009 ⟶ 3,885:
 
var program = "15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0"
subleq.call(program)</langsyntaxhighlight>
 
{{out}}
<pre>
Hello, world!
</pre>
 
=={{header|XPL0}}==
{{trans|ALGOL W}}
<syntaxhighlight lang "XPL0">\Subleq program interpreter
 
\Executes the program specified in scode, stops when the instruction
\ pointer becomes negative.
procedure RunSubleq ( SCode, CodeLength);
integer SCode, CodeLength;
define MaxMemory = 3 * 1024;
integer Memory ( MaxMemory );
integer IP, A, B, C, I;
begin
begin
for I := 0 to MaxMemory - 1 do Memory( I ) := 0;
\Load the program into Memory
for I := 0 to CodeLength do Memory( I ) := SCode( I );
\Start at instruction 0
IP := 0;
\Execute the instructions to IP is < 0
while IP >= 0 do begin
\Get three words at IP and advance IP past them
A := Memory( IP );
B := Memory( IP + 1 );
C := Memory( IP + 2 );
IP := IP + 3;
\Execute according to A, B and C
if A = -1 then begin
\Input a character to B
Memory( B ) := ChIn(1)
end
else if B = -1 then begin
\Output character from A
ChOut(0, Memory ( A ) )
end
else begin
\Subtract and branch if <= 0
Memory( B ) := Memory( B ) - Memory( A );
if Memory( B ) <= 0 then IP := C
end
end \while-do
end
end \RunSubleq \;
 
\Test the interpreter with the hello-world program specified in the task
integer Code;
begin
Code := [ 15, 17, -1, 17, -1, -1
, 16, 1, -1, 16, 3, -1
, 15, 15, 0, 0, -1, 72
, 101, 108, 108, 111, 44, 32
, 119, 111, 114, 108, 100, 33
, 10, 0 ];
RunSubleq( Code, 31 )
end</syntaxhighlight>
{{out}}
<pre>
Line 3,018 ⟶ 3,953:
=={{header|zkl}}==
{{trans|Python}}
<langsyntaxhighlight lang="zkl">fcn subleq(a,a1,a2,etc){ a=vm.arglist.copy();
i:=0;
while(i>=0){ A,B,C:=a[i,3];
Line 3,026 ⟶ 3,961:
i+=3;
}
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">subleq(15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15,
0, 0, -1, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108,
100, 33, 10, 0);</langsyntaxhighlight>
{{out}}<pre>Hello, world!</pre>
 
=={{header|ZX Spectrum Basic}}==
Reads the Subleq program from the keyboard, as space-separated numbers, and executes it. A couple of implementation details (arrays being indexed from 1 rather than from 0; the control character ASCII 10 needing to be intercepted specially, because it would otherwise be printed as <code>?</code> rather than as a newline character) are hidden from the Subleq programmer. Lines <code>10</code> to <code>140</code> are the machine code loader, lines <code>150</code> to <code>310</code> the VM.
<langsyntaxhighlight lang="zxbasic"> 10 DIM m(512)
20 INPUT p$
30 LET word=1
Line 3,064 ⟶ 3,999:
290 IF m(a+1)=10 THEN PRINT : GO TO 160
300 PRINT CHR$ m(a+1);
310 GO TO 160</langsyntaxhighlight>
{{out}}
<pre>Hello, world!</pre>
9,476

edits