Execute HQ9+: Difference between revisions

57,790 bytes added ,  15 days ago
m
 
(77 intermediate revisions by 34 users not shown)
Line 1:
{{task}}
{{task}}Implement a [[HQ9+]] interpreter or compiler for Rosetta Code.
 
;Task:
Implement a   ''' [[HQ9+]] '''   interpreter or compiler.
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F hello()
print(‘Hello, world!’)
 
String src
F quine()
print(:src)
 
F bottles()
L(i) (99.<2).step(-1)
print(‘#. bottles of beer on the wall’.format(i))
print(‘#. bottles of beer’.format(i))
print(‘Take one down, pass it around’)
print(‘#. bottles of beer on the wall’.format(i - 1))
print()
 
print(‘2 bottles of beer on the wall’)
print(‘2 bottles of beer’)
print(‘Take one down, pass it around’)
print(‘1 bottle of beer on the wall’)
print()
 
print(‘1 bottle of beer on the wall’)
print(‘1 bottle of beer’)
print(‘Take one down, pass it around’)
print(‘No more bottles of beer on the wall’)
print()
 
print(‘No more bottles of beer on the wall’)
print(‘No more bottles of beer on the wall’)
print(‘Go to the store and buy some more’)
print(‘99 bottles of beer on the wall.’)
print()
 
V acc = 0
F incr()
:acc++
 
:start:
src = File(:argv[1]).read()
 
[Char = (() -> Void)] dispatch
dispatch[Char(‘h’)] = hello
dispatch[Char(‘q’)] = quine
dispatch[Char(‘9’)] = bottles
dispatch[Char(‘+’)] = incr
 
L(i) src.lowercase()
I i C dispatch
dispatch[i]()</syntaxhighlight>
 
=={{header|8080 Assembly}}==
 
This program runs under CP/M. The HQ9+ source code is read from the file given
on the command line. After the program is finished, the final value of the
accumulator can be found at address <code>0252H</code>. (If you are running the
code on an emulator or on a machine that has a front panel, this is easy to do.
Alternatively, DDT can be used, though you will have to set up the FCB by hand.)
 
<syntaxhighlight lang="8080asm">putch: equ 2 ; Write character
puts: equ 9 ; Write string
fopen: equ 15 ; Open file
fread: equ 20 ; Read record
setdma: equ 26 ; Set DMA address
fcb: equ 5Ch ; FCB for first file on command line
org 100h
;;; Open source file given on command line
lxi d,fcb
mvi c,fopen
call 5 ; Open file
inr a ; A=FF = error
lxi d,efile
jz s_out ; If error, print error message and stop
lxi d,src ; Start reading file at src
;;; Load the entire source file into memory
block: push d ; Set DMA address to next free location
mvi c,setdma
call 5
lxi d,fcb ; Read 128-byte record
mvi c,fread
call 5
pop d ; Advance pointer by 128 bytes
lxi h,128
dad d
xchg
dcr a ; A=1 = end of file
jz block ; If not EOF, read next block
xchg
mvi m,26 ; Terminate last block with EOF byte to be sure
lxi b,src ; BC = source pointer
ins: ldax b ; Get current instruction
cpi 26 ; If EOF, stop
rz
ori 32 ; Make lowercase
push b ; Keep source pointer
cpi 'h' ; H=hello
cz hello
cpi 'q' ; Q=quine
cz quine
cpi '9' ; 9=bottles
cz botls
cpi '+' ; +=increment
cz incr
pop b ; Restore source pointer
inx b ; Next instruction
jmp ins
;;; Increment accumulator
incr: lxi h,accum
inr m
ret
;;; Print "Hello, World"
hello: lxi d,histr
jmp s_out
;;; Print the source
quine: lxi h,src ; Pointer to source
qloop: mov a,m ; Load byte
cpi 26 ; Reached the end?
rz ; If so, stop
push h ; Otherwise, keep pointer
mov e,a
mvi c,putch ; Print character
call 5
pop h ; Restore pointer
inx h ; Next byte
jmp qloop
;;; 99 bottles of beer
botls: mvi e,99 ; 99 bottles
bverse: call nbeer ; _ bottle(s) of beer
lxi h,otw ; on the wall
call bstr
call nbeer ; _ bottle(s) of beer
lxi h,nl ; \r\n
call bstr
lxi h,tod ; Take one down and pass it around
call bstr
dcr e ; Decrement counter
push psw ; Keep status
call nbeer ; _ bottle(s) of beer
lxi h,otw
call bstr ; on the wall
lxi h,nl ; \r\n
call bstr
pop psw ; restore status
jnz bverse ; If not at 0, next verse
ret
nbeer: push d ; keep counter
call btlstr ; _ bottle(s)
lxi d,ofbeer
call s_out ; of beer
pop d
ret
bstr: push d ; keep counter
xchg ; print string in HL
call s_out
pop d ; restore counter
ret
;;; Print "N bottle(s)"
btlstr: push d ; Keep counter
mov a,e ; Print number
call num
lxi d,bottle
call s_out ; Print " bottle"
pop d ; Restore counter
dcr e ; If counter is 1,
rz ; then stop,
mvi e,'s' ; otherwise, print S
mvi c,putch
jmp 5
;;; Print number (0-99) in A
num: ana a ; If 0, print "no more"
lxi d,nomore
jz s_out
mvi b,'0'-1 ; Tens digit
nloop: inr b ; Increment tens digit
sui 10 ; Subtract 10
jnc nloop
adi '0'+10 ; Ones digit
lxi d,snum-1
stax d ; Store ones digit
mov a,b ; Tens digit zero?
cpi '0'
jz s_out ; If so, only print ones digit
dcx d ; Otherwise, store tens digit
stax d
s_out: mvi c,puts ; Print result
jmp 5
efile: db 'File error.$'
histr: db 'Hello, world!',13,10,'$'
db '..'
snum: db '$'
nomore: db 'No more$'
bottle: db ' bottle$'
ofbeer: db ' of beer$'
otw: db ' on the wall',13,10,'$'
tod: db 'Take one down and pass it around'
nl: db 13,10,'$'
accum: db 0 ; Accumulator
src: equ $ ; Program source</syntaxhighlight>
 
{{out}}
 
This shows the code being run in SIMH and the accumulator checked afterwards.
For brevity, no <code>9</code> instruction is included in the HQ9+ source file.
 
<pre>A>type test.hq
HQ+hq+
qh+QH+
 
A>hq9+ test.hq
Hello, world!
HQ+hq+
qh+QH+
Hello, world!
HQ+hq+
qh+QH+
HQ+hq+
qh+QH+
Hello, world!
HQ+hq+
qh+QH+
Hello, world!
 
A>^E
Simulation stopped, PC: 0F402 (JMP F3F8h)
sim> ex 0252
252: 04
</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">PROC Run(CHAR ARRAY code)
BYTE i,a
CHAR c
 
PrintF("Run ""%S""%E%E",code)
a=0
FOR i=1 TO code(0)
DO
c=code(i)
IF c='q OR c='Q THEN
PrintE(code)
ELSEIF c='h OR c='H THEN
PrintE("Hello, world!")
ELSEIF c='9 THEN
PrintE("99 bottles here...")
ELSEIF c='+ THEN
a==+1
ELSE
PrintF("Unrecognized character '%C'%E",c)
Break()
FI
OD
PrintF("%EAccumulator=%B%E",a)
RETURN
 
PROC Main()
Run("9++hQ+q9H+")
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Execute_HQ9+.png Screenshot from Atari 8-bit computer]
<pre>
Run "9++hQ+q9H+"
 
99 bottles here...
Hello, world!
9++hQ+q9H+
9++hQ+q9H+
99 bottles here...
Hello, world!
 
Accumulator=4
</pre>
 
=={{header|Ada}}==
 
see [[Execute HQ9+/Ada]]
 
=={{header|Agena}}==
Tested with Agena 2.9.5 Win32
<syntaxhighlight lang="agena"># HQ9+ interpreter
 
# execute an HQ9+ program in the code string - code is not case sensitive
hq9 := proc( code :: string ) is
local hq9Accumulator := 0; # the HQ9+ accumulator
local hq9Operations := # table of HQ9+ operations and their implemntations
[ "q" ~ proc() is print( code ) end
, "h" ~ proc() is print( "Hello, world!" ) end
, "9" ~ proc() is
local writeBottles := proc( bottleCount :: number, message :: string ) is
print( bottleCount
& " bottle"
& if bottleCount <> 1 then "s " else " " fi
& message
)
end;
 
for bottles from 99 to 1 by -1 do
writeBottles( bottles, "of beer on the wall" );
writeBottles( bottles, "of beer" );
print( "Take one down, pass it around," );
if bottles > 1 then
writeBottles( bottles - 1, "of beer on the wall." )
fi;
print()
od;
print( "No more bottles of beer on the wall." )
end
, "+" ~ proc() is inc hq9Accumulator, 1 end
];
for op in lower( code ) do
if hq9Operations[ op ] <> null then
hq9Operations[ op ]()
else
print( '"' & op & '" not implemented' )
fi
od
end;
 
# prompt for HQ9+ code and execute it, repeating until an empty code string is entered
scope
local code;
do
write( "HQ9+> " );
code := io.read();
hq9( code )
until code = ""
epocs;</syntaxhighlight>
 
=={{header|ALGOL 68}}==
Translation of DWScript. the accumulator is global.
<langsyntaxhighlight lang="algol68"># the increment-only accumulator #
INT hq9accumulator := 0;
 
Line 53 ⟶ 382:
read( ( code, newline ) );
hq9( code )
END</langsyntaxhighlight>
 
=={{header|ALGOL W}}==
Based on ALGOL 68 (which is a translation of DWScript)...
<syntaxhighlight lang="algolw">begin
 
procedure writeBottles( integer value bottleCount ) ;
begin
write( bottleCount, " bottle" );
if bottleCount not = 1 then writeon( "s " ) else writeon( " " );
end writeBottles ;
 
procedure hq9 ( string(32) value code % code to execute %
; integer value length % length of code %
) ;
for i := 0 until length - 1 do begin
string(1) op;
 
% the increment-only accumulator %
integer hq9accumulator;
 
hq9accumulator := 0;
op := code(i//1);
 
if op = "Q" or op = "q" then write( code )
else if op = "H" OR op = "h" then write( "Hello, World!" )
else if op = "9" then begin
% 99 bottles of beer %
i_w := 1; s_w := 0;
for bottles := 99 step -1 until 1 do begin
writeBottles( bottles ); writeon( "of beer on the wall" );
writeBottles( bottles ); writeon( "of beer" );;
write( "Take one down, pass it around," );
if bottles > 1 then begin
writeBottles( bottles - 1 ); writeon( "of beer on the wall." )
end;
write()
end;
write( "No more bottles of beer on the wall." )
end
else if op = "+" then hq9accumulator := hq9accumulator + 1
else write( """", op, """ not implemented" )
end hq9 ;
 
 
% test the interpreter %
begin
string(32) code;
integer codeLength;
write( "HQ9+> " );
read( code );
codeLength := 31;
while codeLength >= 0 and code(codeLength//1) = " " do codeLength := codeLength - 1;
hq9( code, codeLength + 1 )
end
end.</syntaxhighlight>
 
=={{header|Applesoft BASIC}}==
<langsyntaxhighlight ApplesoftBasiclang="applesoftbasic">100 INPUT "HQ9+ : "; I$
110 LET J$ = I$ + CHR$(13)
120 LET H$ = "HELLO, WORLD!"
Line 69 ⟶ 453:
210 IF C$ <> "9" THEN 280
220 FOR B = 99 TO 1 STEP -1
230 PRINT B; " " B$ W$; B; " " B$
240 PRINT "TAKE ONE DOWN, ";
250 PRINT "PASS IT AROUND"
260 PRINT B - 1; " " B$ W$
270 NEXT B
280 NEXT I</langsyntaxhighlight>
 
=={{header|x86 AssemblyArturo}}==
<lang X86 Assembly>
 
<syntaxhighlight lang="rebol">hq9: function [source][
;ds:si: pointer to asciiz string containing HQ9++ source code
acc: 0
ExecuteHQ9:
loop split source 'ch [
push ax
case [(lower ch)=]
push dx
when? ["h"]-> print "Hello, world!"
push si
when? ["q"]-> print source
push di
when? ["9"]-> print "99 bottles here ..."
push es
when? ["+"]-> acc: acc+1
push bx
else []
mov bx, si
.interpret:
lodsb
cmp al, 'H'
je .doHelloWorld
cmp al, 'Q'
je .doPrintCode
cmp al, '9'
je .doDrinkBeer
cmp al, '+'
je .doCounter
pop bx
pop es
pop di
pop si
pop dx
pop ax
ret
.doHelloWorld:
push ds
mov ax, cs
mov ds, ax
push si
mov si, .dataHelloWorld
call .printString
pop si
pop ds
jmp .interpret
.doPrintCode:
push si
mov si, bx
call .printString
pop si
jmp .interpret
.doDrinkBeer:
push ds
push si
push ax
mov ax, cs
mov ds, ax
mov ax, 99
.beer_loop:
call .printHexNumber
mov si, .dataBeerSong1
call .printString
call .printHexNumber
mov si, .dataBeerSong2
call .printString
dec ax
call .printHexNumber
mov si, .dataBeerSong3
call .printString
test ax, ax
jnz .beer_loop
pop ax
pop si
pop ds
jmp .interpret
.doCounter:
push ax
inc ax
pop ax
jmp .interpret
.printString:
push ax
push si
.looping:
lodsb
test al, al
jz .done
mov ah, 0Eh
int 10h
jmp .looping
.done:
pop si
pop ax
ret
.printHexNumber:
pusha
push ds
mov ax, cs
mov ds, ax
push word 0
mov bx, ax
xor dx, dx
mov cx, 4r
.convert_loop:
mov ax, bx
and ax, 0Fh
cmp ax, 9
ja .greater_than_9
add ax, '0'
jmp .converted
.greater_than_9:
add ax, 'A'-0Ah
.converted:
push ax
shr bx, 4
dec cx
jnz .convert_loop
.popoff:
pop ax
cmp ax, 0
je .done
mov ah, 0Eh
int 10h
jmp .popoff
.done:
pop ds
popa
ret
 
]
.dataHelloWorld: db "Hello World!", 0
return acc
.dataBeerSong1: db " bottles of beer on the wall ", 0
]
.dataBeerSong2: db " bottles of beer", 13, 10, "Take one down, pass it around "
.dataBeerSong3: db 0, " bottles of beer on the wall", 0
 
acc: hq9 {+qhp;+9Q}
</lang>
print ["accumulator:" acc]</syntaxhighlight>
 
{{out}}
 
<pre>+qhp;+9Q
Hello, world!
99 bottles here ...
+qhp;+9Q
accumulator: 2</pre>
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">; http://www.autohotkey.com/forum/viewtopic.php?p=356268#356268
 
testCode := "hq9+HqQ+Qq"
Line 240 ⟶ 515:
}
Return output
}</langsyntaxhighlight>
 
=={{header|BBC BASIC}}==
==={{header|BASIC256}}===
<lang bbcbasic> PROChq9plus("hq9+HqQ+Qq")
{{trans|FreeBASIC}}
<syntaxhighlight lang="basic256">
# Intérprete de HQ9+
 
global codigo
codigo = ""
 
function HQ9plus(codigo)
acumulador = 0
HQ9plus1 = ""
for cont = 1 to length(codigo)
op = upper(mid(codigo, cont, 1))
begin case
case op = "H"
HQ9plus1 = HQ9plus1 + "Hello, world!"
case op = "Q"
HQ9plus1 = HQ9plus1 + codigo
case op = "9"
for botellas = 99 to 1 step -1
HQ9plus1 = HQ9plus1 + string(botellas) + " bottle"
if (botellas > 1) then HQ9plus1 = HQ9plus1 + "s"
HQ9plus1 = HQ9plus1 + " of beer on the wall, " + string(botellas) + " bottle"
if (botellas > 1) then HQ9plus1 = HQ9plus1 + "s"
HQ9plus1 = HQ9plus1 + " of beer," + chr(13) + chr(10) + "Take one down, pass it around, " + string(botellas - 1) + " bottle"
if (botellas > 2) then HQ9plus1 = HQ9plus1 + "s"
HQ9plus1 = HQ9plus1 + " of beer on the wall." + chr(13) + chr(10) + chr(10)
next botellas
HQ9plus1 = HQ9plus1 + "No more bottles of beer on the wall, no more bottles of beer." + chr(13) + chr(10) + "Go to the store and buy some more, 99 bottles of beer on the wall."
case op = "+"
acumulador = (acumulador + 1)
case op = "E"
end
end case
if mid(codigo, cont, 1) <> "+" then
HQ9plus1 = HQ9plus1 + chr(13) + chr(10)
end if
next cont
HQ9plus = left(HQ9plus1, (length(HQ9plus1) - 2))
end function
 
 
cls
do
input codigo
print HQ9plus(codigo): print
until false
end
</syntaxhighlight>
 
==={{header|BBC BASIC}}===
<syntaxhighlight lang="bbcbasic"> PROChq9plus("hq9+HqQ+Qq")
END
Line 264 ⟶ 590:
ENDCASE
NEXT i%
ENDPROC</langsyntaxhighlight>
'''Output:'''
<pre>
Line 286 ⟶ 612:
hq9+HqQ+Qq
</pre>
 
 
=={{header|BQN}}==
'''Works in:''' [[CBQN]]
 
Takes a single line HQ9+ program from stdin, and displays the output.
 
<syntaxhighlight lang="bqn">Pl ← {(𝕩≠1)/"s"}
Lwr ← +⟜(32×1="A["⊸⍋)
nn ← {(•Fmt 𝕨)∾" "∾𝕩}´¨∾{
⟨𝕩,"bottle"∾(Pl 𝕩)∾" of beer on the wall"⟩
⟨𝕩,"bottle"∾(Pl 𝕩)∾" of beer"⟩
⟨"Take one down, pass it around"⟩
⟨𝕩-1,"bottle"∾(Pl 𝕩-1)∾" of beer on the wall"⟩
}¨⌽1+↕99
 
HQ9 ← {
out ← ⟨⟨"Hello, World!"⟩, ⟨𝕩⟩, nn⟩
acc ← +´'+'=𝕩
∾out⊏˜3⊸≠⊸/"hq9"⊐Lwr 𝕩
}
 
•Out¨HQ9 •GetLine@</syntaxhighlight>
 
=={{header|C}}==
<langsyntaxhighlight lang="c">void runCode(const char *code)
{
int c_len = strlen(code);
int i, accumulator, bottles;
unsigned accumulator=0;
for(i=0;i<c_len;i++)
{
Line 321 ⟶ 673:
}
}
};</langsyntaxhighlight>
 
=={{header|C sharp|C#}}==
 
<syntaxhighlight lang="csharp">
using System;
using System.Collections.Generic;
using System.Linq;
 
class Program
{
static void RunCode(string code)
{
int accumulator = 0;
var opcodes = new Dictionary<char, Action>
{
{'H', () => Console.WriteLine("Hello, World!"))},
{'Q', () => Console.WriteLine(code) },
{'9', () => Console.WriteLine(Enumerable.Range(1,100).Reverse().Select(n => string.Format("{0} bottles of beer on the wall\n{0} bottles of beer\nTake one down, pass it around\n{1} bottles of beer on the wall\n", n, n-1)).Aggregate((a,b) => a + "\n" + b))},
{'+', () => accumulator++ }
}
 
foreach(var c in code)
opcodes[c]();
}
}
</syntaxhighlight>
 
=={{header|C++}}==
Basically the same as the C example, although this has been C++'ified with strings and streams.
<langsyntaxhighlight lang="cpp">void runCode(string code)
{
int c_len = code.length();
intunsigned accumulator, bottles=0;
int bottles;
for(int i=0;i<c_len;i++)
{
Line 358 ⟶ 737:
}
}
};</langsyntaxhighlight>
 
=={{header|C sharp}}==
 
<lang csharp>
using System;
using System.Collections.Generic;
using System.Linq;
 
class Program
{
static void RunCode(string code)
{
int accumulator = 0;
var opcodes = new Dictionary<char, Action>
{
{'H', () => Console.WriteLine("Hello, World!"))},
{'Q', () => Console.WriteLine(code) },
{'9', () => Console.WriteLine(Enumerable.Range(1,100).Reverse().Select(n => string.Format("{0} bottles of beer on the wall\n{0} bottles of beer\nTake one down, pass it around\n{1} bottles of beer on the wall\n", n, n-1)).Aggregate((a,b) => a + "\n" + b))},
{'+', () => accumulator++ }
}
 
foreach(var c in code)
opcodes[c]();
}
}
</lang>
 
=={{header|Ceylon}}==
<langsyntaxhighlight lang="ceylon">shared void run() {
void eval(String code) {
Line 424 ⟶ 777:
eval("hq9+");
}</langsyntaxhighlight>
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">(ns anthony.random.hq9plus
(:require [clojure.string :as str]))
 
Line 449 ⟶ 802:
\9 (bottles)
\+ (reset! accumulator (inc @accumulator)))
(if-not (= (inc pointer) (count commands)) (recur (inc pointer))))))</langsyntaxhighlight>
 
=={{header|CLU}}==
<syntaxhighlight lang="clu">% This program uses the "get_argv" function from PCLU's "useful.lib"
 
hq9plus = cluster is load, run
rep = string
own po: stream := stream$primary_output()
bottles = proc (n: int) returns (string)
if n=0 then return("No more bottles ")
elseif n=1 then return("1 bottle ")
else return(int$unparse(n) || " bottles ")
end
end bottles
 
beer = proc ()
for i: int in int$from_to_by(99,1,-1) do
stream$putl(po, bottles(i) || "of beer on the wall,")
stream$putl(po, bottles(i) || "of beer,")
stream$puts(po, "Take ")
if i=1
then stream$puts(po, "it")
else stream$puts(po, "one")
end
stream$putl(po, " down and pass it around,")
stream$putl(po, bottles(i-1) || "of beer on the wall!\n")
end
end beer
quine = proc (c: rep) stream$puts(po, c) end quine
hello = proc () stream$putl(po, "Hello, world!") end hello
load = proc (fn: file_name) returns (cvt) signals (not_possible(string))
prog: array[char] := array[char]$[]
s: stream := stream$open(fn, "read") resignal not_possible
while true do
array[char]$addh(prog, stream$getc(s))
except when end_of_file: break end
end
stream$close(s)
return(rep$ac2s(prog))
end load
run = proc (prog: cvt) returns (int)
acc: int := 0
for c: char in rep$chars(prog) do
if c='h' | c='H' then hello()
elseif c='q' | c='Q' then quine(prog)
elseif c='9' then beer()
elseif c='+' then acc := acc + 1
end
end
return(acc)
end run
end hq9plus
 
start_up = proc ()
fn: file_name := file_name$parse(sequence[string]$bottom(get_argv()))
hq9plus$run(hq9plus$load(fn))
end start_up</syntaxhighlight>
{{out}}
<pre>$ cat test.hq
HQ+hq+
qh+QH+
$ ./hq9+ test.hq
Hello, world!
HQ+hq+
qh+QH+
Hello, world!
HQ+hq+
qh+QH+
HQ+hq+
qh+QH+
Hello, world!
HQ+hq+
qh+QH+
Hello, world!</pre>
 
=={{header|COBOL}}==
<langsyntaxhighlight lang="cobol"> IDENTIFICATION DIVISION.
PROGRAM-ID. Exec-Hq9.
 
Line 495 ⟶ 925:
 
GOBACK
.</langsyntaxhighlight>
 
=={{header|Common Lisp}}==
Line 502 ⟶ 932:
 
=={{header|D}}==
<langsyntaxhighlight lang="d">import std.stdio, std.string;
 
void main(in string[] args) {
Line 537 ⟶ 967:
}
}
}</langsyntaxhighlight>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{Trans|C}}
<syntaxhighlight lang="delphi">
uses
System.SysUtils;
 
procedure runCode(code: string);
var
c_len, i, bottles: Integer;
accumulator: Cardinal;
begin
c_len := Length(code);
accumulator := 0;
for i := 1 to c_len do
begin
case code[i] of
'Q':
writeln(code);
'H':
Writeln('Hello, world!');
'9':
begin
bottles := 99;
repeat
writeln(format('%d bottles of beer on the wall', [bottles]));
writeln(format('%d bottles of beer', [bottles]));
Writeln('Take one down, pass it around');
dec(bottles);
writeln(format('%d bottles of beer on the wall' + sLineBreak, [bottles]));
until (bottles <= 0);
end;
'+':
inc(accumulator);
end;
end;
end;</syntaxhighlight>
 
=={{header|DWScript}}==
 
{{Trans|D}}
<langsyntaxhighlight lang="dwscript">procedure RunCode(code : String);
var
i : Integer;
Line 569 ⟶ 1,036:
end;
end;
end;</langsyntaxhighlight>
 
=={{header|Dyalect}}==
 
<syntaxhighlight lang="dyalect">func eval(code) {
var accumulator = 0
var opcodes = (
"h": () => print("Hello, World!"),
"q": () => print(code),
"9": () => {
var quantity = 99
while quantity > 1 {
print("\(quantity) bottles of beer on the wall, \(quantity) bottles of beer.")
print("Take one down and pass it around, \(quantity - 1) bottles of beer.")
quantity -= 1
}
print("1 bottle of beer on the wall, 1 bottle of beer.")
print("Take one down and pass it around, no more bottles of beer on the wall.\n")
print("No more bottles of beer on the wall, no more bottles of beer.")
print("Go to the store and buy some more, 99 bottles of beer on the wall.")
},
"+": () => { accumulator += 1 }
)
for c in code {
opcodes[c.Lower()]()
}
}</syntaxhighlight>
 
=={{header|E}}==
 
See [[Execute HQ9+/E]].
 
=={{header|EasyLang}}==
<syntaxhighlight>
proc run code$ . .
for c$ in strchars code$
if c$ = "Q"
print code$
elif c$ = "H"
print "Hello, world!"
elif c$ = "9"
for b = 99 downto 1
print b & " bottles of beer on the wall"
print b & " bottles of beer"
print "Take one down, pass it around"
print b & " bottles of beer on the wall"
print ""
.
elif c$ = "+"
acc += 1
print acc
.
.
.
run "HQ9+"
</syntaxhighlight>
 
=={{header|Ela}}==
Line 579 ⟶ 1,098:
===Impure approach===
 
<langsyntaxhighlight lang="ela">open unsafe.console char unsafe.cell imperative
eval src = eval' src
Line 589 ⟶ 1,108:
| else = fail ("Unrecognized " ++ x)
where r = ref 0
be c = char.upper x == c
h () = writen "Hello, world!"
q () = writen src
Line 599 ⟶ 1,118:
(show x) " bottles of beer\r\n"
"Take one down, pass it around\r\n"
`seq` bottles xs</langsyntaxhighlight>
 
===Pure version===
Line 605 ⟶ 1,124:
An interpreter itself has no side effects:
 
<langsyntaxhighlight lang="ela">open list char
eval src = eval' src 0
Line 614 ⟶ 1,133:
| be '+' = eval' xs (a+1)
| else = fail "Invalid instruction."
where be c = char.upper x == c
h = "Hello, world!"
q = src
Line 623 ⟶ 1,142:
++ show x ++ " bottles of beer\r\n"
++ "Take one down, pass it around\r\n"
++ bottles xs</langsyntaxhighlight>
 
It slightly alters an original HQ9+ specification. HQ9+ is an impure language that does console output. However console output is the only interaction that a user can see when executing HQ9+ program. This interpreter doesn't output to console but instead generates a list with all outputs. An accumulator is moved to the interpter arguments and the need for a reference cell is eliminated. Once an interpreter completes a client code can output to console using monads like so:
 
<syntaxhighlight lang="ela">open imperative monad io
 
print_and_eval src = do
It slightly alters an original HQ9+ specification. HQ9+ is an impure language that does console output. However console output is the only interaction that a user can see when executing HQ9+ program. This interpreter doesn't output to console but instead generates a list with all outputs. An accumulator is moved to the interpter arguments and the need for a reference cell is eliminated. Once an interpreter completes a client code can output to console like so:
res <- return $ eval src
return $ each print res
where print x = do putStrLn x
 
print_and_eval "HQ9+" ::: IO</syntaxhighlight>
<lang ela>open console imperative
each writen <| eval "HQ9+"</lang>
 
=={{header|Erlang}}==
<langsyntaxhighlight Erlanglang="erlang">% hq9+ Erlang implementation (JWL)
% http://www.erlang.org/
-module(hq9p).
Line 688 ⟶ 1,213:
main(Compiled, Prog, 0).
 
</syntaxhighlight>
</lang>
 
=={{header|Factor}}==
<syntaxhighlight lang="factor">USING: combinators command-line formatting interpolate io kernel
math math.ranges multiline namespaces sequences ;
IN: rosetta-code.hq9+
 
STRING: verse
${3} bottle${1} of beer on the wall
${3} bottle${1} of beer
Take one down, pass it around
${2} bottle${0} of beer on the wall
;
 
: bottles ( -- )
99 1 [a,b]
[ dup 1 - 2dup [ 1 = "" "s" ? ] bi@ verse interpolate nl ]
each ;
 
SYMBOL: accumulator
 
CONSTANT: commands
{
{ CHAR: H [ drop "Hello, world!" print ] }
{ CHAR: Q [ print ] }
{ CHAR: 9 [ drop bottles ] }
{ CHAR: + [ drop accumulator inc ] }
[ nip "Invalid command: %c" sprintf throw ]
}
 
: interpret-HQ9+ ( str -- )
dup [ commands case ] with each accumulator off ;
 
: main ( -- ) command-line get first interpret-HQ9+ ;
 
MAIN: main</syntaxhighlight>
{{out}}
Test run on the command line:
<pre>
>factor -run=rosetta-code.hq9+ H+Q+9+
Hello, world!
H+Q+9+
99 bottles of beer on the wall
99 bottles of beer
Take one down, pass it around
98 bottles of beer on the wall
. . .
1 bottle of beer on the wall
1 bottle of beer
Take one down, pass it around
0 bottles of beer on the wall
</pre>
 
=={{header|Forth}}==
 
<langsyntaxhighlight lang="forth">variable accumulator
: H cr ." Hello, world!" ;
: Q cr 2dup type ;
Line 702 ⟶ 1,278:
i 1 [ get-current literal ] search-wordlist
if execute else true abort" invalid HQ9+ instruction"
then loop 2drop ;</langsyntaxhighlight>
 
=={{header|Fortran}}==
This is F77 style except for the END SUBROUTINE HQ9, since F90+ allows the END statement to name its subroutine, and more seriously, the SELECT CASE construction that avoids interminable IF ... THEN ... ELSE IF ... sequences or even, a computed GO TO. The obvious data structure is the CHARACTER type, introduced with F77.
 
The only difficulty lies in the phasing of the various components of the recital (note the lines ending with commas or periods), and especially, producing correct grammar for the singular case. One could simply produce the likes of *"1 bottles of beer", or perhaps "1 bottle(s) of beer" but having been hounded for decades by compilers quibbling over syntax trivia, a certain sensitivity has arisen. For this case, the requirement is to append a "s" or not to "bottle" and the task is quite vexing because Fortran does not allow within expressions syntax such as <syntaxhighlight lang="fortran">"bottle" // IF (B.NE.1) THEN "s" FI // " of beer"</syntaxhighlight> so alternative schemes must be devised. There are many possibilities. The output line could be written piecemeal using the "non-advancing" options introduced in F90 with the "s" being written or not, or, the output line could be developed piecemeal in a CHARACTER variable in a similar way then written in one go. Alternatively, a character variable SUFFIX could be employed, which contains either "s" or " " with its usage being <code>..."bottle"//SUFFIX(1:LSTNB(SUFFIX))//...</code> where function LSTNB fingers the last non-blank character (if function TRIM or LEN_TRIM are unavailable), or, with F2003 there is a facility whereby SUFFIX can be declared with a varying length so as to be either "s" or "". Still another ploy would be to replace the "s" by a "null" character (character code zero) that will be passed over by the device showing the output. Or maybe not...
 
However, because the tail end of the recital does not conform to the structure of the earlier verses, it seemed easier to combine the singular case with the coda, especially since "No bottles" is to be produced instead of "0 bottles". It would be easy enough to devise a function CARDINAL(N) that would return "Ninety-nine", ... "One", "No" but the required code would swamp the rest of the project.
 
So, there is a careful factorisation of the text phrases into FORMAT and WRITE statements. Note that "free-format" output (as with <code>WRITE (6,*)</code>) starts in the second column, whereas formatted output starts in the first column. Inspection of the code file HQ9.exe shows that the compiler has recognised that the multiple appearances of the text literals "bottles" (three) and "bottle" (two) are the same and there is only one value of each constant in the code file. However, it has not noticed that the text "bottle" can be extracted from "bottles", which could in turn be found within a larger text literal "No bottles of beer on the wall" which also contains the subsequence " on the wall" - perhaps the code to do this would consume more space than would be saved by having a single multiple-use text constant in the code for those, or perhaps the problem is just too difficult in general to be worth the effort of devising and executing a worthwhile analysis, given that only a few bytes might be saved in a code file of 480Kb. This of course must contain the format interpretation subsystem and so forth, not just the code for the Fortran source. Even so, this program (with minor changes to the syntax) could be written in Fortran IV for an IBM1130, and would run in a computer with a total memory size of 8Kb. On such systems, much thought would go in to minimising space lost to verbose texts and good exposition as well as such reuse opportunities: gaining access to 32Kb or even 64Kb systems would be a great relief. But these days, memory space is not at a premium, and we are told that modern compilers produce excellent code.
 
<syntaxhighlight lang="fortran">
SUBROUTINE HQ9(CODE) !Implement the rather odd HQ9+ instruction set.
CHARACTER*(*) CODE !One operation code per character.
INTEGER I,B !Steppers.
INTEGER A !An accumulator.
A = 0 !Initialised.
DO I = 1,LEN(CODE) !Step through the code.
SELECT CASE(CODE(I:I))!Inspect the operation code.
CASE(" ") !Might as well do nothing.
CASE("+") !Increment the accumulator.
A = A + 1 !Thus. Though, nothing refers to it...
CASE("h","H") !Might as well allow upper or lower case.
WRITE (6,*) "Hello, world!" !Hi there!
CASE("q","Q") !Show the (rather questionable) code.
WRITE (6,*) CODE !Thus.
CASE("9") !Recite "99 bottles of beer"...
DO B = 99,2,-1 !Grammar is to be upheld, so the singular case is special.
WRITE (6,1) B,"bottles"," on the wall,",B,"bottles","." !Two lots: number, text, text.
1 FORMAT (I2,1X,A," of beer",A) !Exhausted by the first triplet, so a new line for the second.
WRITE (6,2) !Now for the reduction.
2 FORMAT ("Take one down, pass it around,") !Announce.
IF (B.GT.2) WRITE (6,1) B - 1,"bottles"," on the wall." !But, not for the singular state.
END DO !Recite the next stanza.
WRITE (6,1) 1,"bottle"," on the wall,",1,"bottle","." !The singular case. No longer "bottles".
WRITE (6,2) !There's nothing so lonesome, morbid or drear,
WRITE (6,*) "No bottles of beer on the wall." !Than to stand at the bar of a pub with no beer.
WRITE (6,*) "Go to the store, buy some more." !Take action.
CASE DEFAULT !Denounce any unknown operation codes.
WRITE (6,*) "Unrecognised code:",CODE(I:I) !This is why a space is treated separately.
END SELECT !So much for that operation code.
END DO !On to the next.
END SUBROUTINE HQ9 !That was odd.
 
PROGRAM POKE
CALL HQ9("hq9")
END</syntaxhighlight>
 
To show that the juggling works,
<pre>
Hello, world!
hq9
99 bottles of beer on the wall,
99 bottles of beer.
Take one down, pass it around,
98 bottles of beer on the wall.
98 bottles of beer on the wall,
98 bottles of beer.
Take one down, pass it around,
97 bottles of beer on the wall.
...
Take one down, pass it around,
2 bottles of beer on the wall.
2 bottles of beer on the wall,
2 bottles of beer.
Take one down, pass it around,
1 bottle of beer on the wall,
1 bottle of beer.
Take one down, pass it around,
No bottles of beer on the wall.
Go to the store, buy some more.
</pre>
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">
' Intérprete de HQ9+
' FB 1.05.0 Win64
'
 
Dim Shared codigo As String: codigo = ""
 
Function HQ9plus(codigo As String) As String
Dim As Byte botellas, cont
Dim acumulador As Uinteger = 0
Dim HQ9plus1 As String
For cont = 1 To Len(codigo)
Select Case Ucase(Mid(codigo, cont, 1))
Case "H"
HQ9plus1 = HQ9plus1 + "Hello, world!"
Case "Q"
HQ9plus1 = HQ9plus1 + codigo
Case "9"
For botellas = 99 To 1 Step -1
HQ9plus1 = HQ9plus1 + Str(botellas) + " bottle"
If (botellas > 1) Then HQ9plus1 = HQ9plus1 + "s"
HQ9plus1 = HQ9plus1 + " of beer on the wall, " + Str(botellas) + " bottle"
If (botellas > 1) Then HQ9plus1 = HQ9plus1 + "s"
HQ9plus1 = HQ9plus1 + " of beer," + Chr(13) + Chr(10) +_
"Take one down, pass it around, " + Str(botellas - 1) + " bottle"
If (botellas > 2) Then HQ9plus1 = HQ9plus1 + "s"
HQ9plus1 = HQ9plus1 + " of beer on the wall." + Chr(13) + Chr(10) + Chr(10)
Next botellas
HQ9plus1 = HQ9plus1 + "No more bottles of beer on the wall, no more bottles of beer." +_
Chr(13) + Chr(10) + "Go to the store and buy some more, 99 bottles of beer on the wall."
Case "+"
acumulador = (acumulador + 1)
Case "E"
End
Case Else
'no es una instrucción válida
End Select
If Mid(codigo, cont, 1) <> "+" Then
HQ9plus1 = HQ9plus1 + Chr(13) + Chr(10)
End If
Next cont
HQ9plus = Left(HQ9plus1, (Len(HQ9plus1) - 2))
End Function
 
 
Cls
Do
Input codigo
Print HQ9plus(codigo): Print
Loop While Inkey <> Chr(27)
End
</syntaxhighlight>
 
=={{header|Go}}==
 
See [[RCHQ9+/Go]].
 
=={{header|Golo}}==
<syntaxhighlight lang="golo">module hq9plus
 
function main = |args| {
var accumulator = 0
let source = readln("please enter your source code: ")
foreach ch in source: chars() {
case {
when ch == 'h' or ch == 'H' {
println("Hello, world!")
}
when ch == 'q' or ch == 'Q' {
println(source)
}
when ch == '9' {
ninety9Bottles()
}
when ch == '+' {
accumulator = accumulator + 1
}
otherwise {
println("syntax error")
}
}
}
}
 
function bottles = |amount| -> match {
when amount == 1 then "One bottle"
when amount == 0 then "No bottles"
otherwise amount + " bottles"
}
 
function ninety9Bottles = {
foreach n in [99..0]: decrementBy(1) {
println(bottles(n) + " of beer on the wall,")
println(bottles(n) + " of beer!")
println("Take one down, pass it around,")
println(bottles(n - 1) + " of beer on the wall!")
}
}
</syntaxhighlight>
 
=={{header|Haskell}}==
Line 715 ⟶ 1,457:
 
=={{header|Haxe}}==
<langsyntaxhighlight lang="javascript">// live demo: http://try.haxe.org/#2E7D4
static function hq9plus(code:String):String {
var out:String = "";
Line 735 ⟶ 1,477:
}
return out;
}</langsyntaxhighlight>
 
=={{header|Inform 7}}==
 
<lang inform7>HQ9+ is a room.
 
After reading a command:
interpret the player's command;
reject the player's command.
 
To interpret (code - indexed text):
let accumulator be 0;
repeat with N running from 1 to the number of characters in code:
let C be character number N in code in upper case;
if C is "H":
say "Hello, world!";
otherwise if C is "Q":
say "[code][line break]";
otherwise if C is "9":
repeat with iteration running from 1 to 99:
let M be 100 - iteration;
say "[M] bottle[s] of beer on the wall[line break]";
say "[M] bottle[s] of beer[line break]";
say "Take one down, pass it around[line break]";
say "[M - 1] bottle[s] of beer on the wall[paragraph break]";
otherwise if C is "+":
increase accumulator by 1.</lang>
 
=={{header|Icon}} and {{header|Unicon}}==
Process HQ9+ from command line arguments and input until an error or end-of file.
<langsyntaxhighlight Iconlang="icon">procedure main(A)
repeat writes("Enter HQ9+ code: ") & HQ9(get(A)|read()|break)
end
Line 791 ⟶ 1,507:
}
return
end</langsyntaxhighlight>
 
=={{header|Inform 7}}==
 
<syntaxhighlight lang="inform7">HQ9+ is a room.
 
After reading a command:
interpret the player's command;
reject the player's command.
 
To interpret (code - indexed text):
let accumulator be 0;
repeat with N running from 1 to the number of characters in code:
let C be character number N in code in upper case;
if C is "H":
say "Hello, world!";
otherwise if C is "Q":
say "[code][line break]";
otherwise if C is "9":
repeat with iteration running from 1 to 99:
let M be 100 - iteration;
say "[M] bottle[s] of beer on the wall[line break]";
say "[M] bottle[s] of beer[line break]";
say "Take one down, pass it around[line break]";
say "[M - 1] bottle[s] of beer on the wall[paragraph break]";
otherwise if C is "+":
increase accumulator by 1.</syntaxhighlight>
 
=={{header|J}}==
 
From [[99_Bottles_of_Beer#J|99 Bottles of Beer]]
<langsyntaxhighlight Jlang="j">bob =: ": , ' bottle' , (1 = ]) }. 's of beer'"_
bobw=: bob , ' on the wall'"_
beer=: bobw , ', ' , bob , '; take one down and pass it around, ' , bobw@<:</langsyntaxhighlight>
 
The rest of the interpreter:
<langsyntaxhighlight Jlang="j">H=: smoutput bind 'Hello, world!'
Q=: smoutput @ [
hq9=: smoutput @: (beer"0) bind (1+i.-99)
hqp=: (A=:1)1 :'0 0$A=:A+m[y'@]
 
hq9p=: H`H`Q`Q`hq9`hqp@.('HhQq9+' i. ])"_ 0~</langsyntaxhighlight>
 
Example use:
 
<langsyntaxhighlight Jlang="j"> hq9p 'hqQQq'
Hello, world!
hqQQq
hqQQq
hqQQq
hqQQq</langsyntaxhighlight>
 
=={{header|Java}}==
Line 822 ⟶ 1,565:
=={{header|JavaScript}}==
The function below executes a HQ9+ program and returns the program output as a string.
<langsyntaxhighlight lang="javascript">function hq9plus(code) {
var out = '';
var acc = 0;
Line 844 ⟶ 1,587:
}
return out;
}</langsyntaxhighlight>
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
<syntaxhighlight lang="julia">hello() = println("Hello, world!")
quine() = println(src)
bottles() = for i = 99:-1:1 print("\n$i bottles of beer on the wall\n$i bottles of beer\nTake one down, pass it around\n$(i-1) bottles of beer on the wall\n") end
acc = 0
incr() = global acc += 1
 
const dispatch = Dict(
'h' => hello,
'q' => quine,
'9' => bottles,
'+' => incr)
 
if length(ARGS) < 1
println("Usage: julia ./HQ9+.jl file.hq9")
exit(1)
else
file = ARGS[1]
end
 
try
open(file) do s
global src = readstring(s)
end
catch
warning("can't open $file")
exit(1)
end
 
for i in lowercase(src)
if haskey(dispatch, i) dispatch[i]() end
end</syntaxhighlight>
 
=={{header|Kotlin}}==
<syntaxhighlight lang="scala">// version 1.1.3
 
fun hq9plus(code: String) {
var acc = 0
val sb = StringBuilder()
for (c in code) {
sb.append(
when (c) {
'h', 'H' -> "Hello, world!\n"
'q', 'Q' -> code + "\n"
'9'-> {
val sb2 = StringBuilder()
for (i in 99 downTo 1) {
val s = if (i > 1) "s" else ""
sb2.append("$i bottle$s of beer on the wall\n")
sb2.append("$i bottle$s of beer\n")
sb2.append("Take one down, pass it around\n")
}
sb2.append("No more bottles of beer on the wall!\n")
sb2.toString()
}
'+' -> { acc++; "" } // yeah, it's weird!
else -> throw IllegalArgumentException("Code contains illegal operation '$c'")
}
)
}
println(sb)
}
 
fun main(args: Array<String>) {
val code = args[0] // pass in code as command line argument (using hq9+)
hq9plus(code)
}</syntaxhighlight>
 
{{out}}
<pre>
Hello, world!
hq9+
99 bottles of beer on the wall
99 bottles of beer
Take one down, pass it around
....
2 bottles of beer on the wall
2 bottles of beer
Take one down, pass it around
1 bottle of beer on the wall
1 bottle of beer
Take one down, pass it around
No more bottles of beer on the wall!
</pre>
 
=={{header|Liberty BASIC}}==
<langsyntaxhighlight lang="lb">'Try this hq9+ program - "hq9+HqQ+Qq"
Prompt "Please input your hq9+ program."; code$
Print hq9plus$(code$)
Line 879 ⟶ 1,708:
Next i
hq9plus$ = Left$(hq9plus$, (Len(hq9plus$) - 2))
End Function</langsyntaxhighlight>
 
=={{header|Lua}}==
<syntaxhighlight lang="lua">
function runCode( code )
local acc, lc = 0
for i = 1, #code do
lc = code:sub( i, i ):upper()
if lc == "Q" then print( lc )
elseif lc == "H" then print( "Hello, World!" )
elseif lc == "+" then acc = acc + 1
elseif lc == "9" then
for j = 99, 1, -1 do
if j > 1 then
print( string.format( "%d bottles of beer on the wall\n%d bottles of beer\nTake one down, pass it around\n%d bottles of beer on the wall\n", j, j, j - 1 ) )
else
print( "1 bottle of beer on the wall\n1 bottle of beer\nTake one down and pass it around\nno more bottles of beer on the wall\n\n"..
"No more bottles of beer on the wall\nNo more bottles of beer\n"..
"Go to the store and buy some more\n99 bottles of beer on the wall.\n" )
end
end
end
end
end
</syntaxhighlight>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
 
<syntaxhighlight lang="text">hq9plus[program_] :=
Module[{accumulator = 0, bottle},
bottle[n_] :=
Line 892 ⟶ 1,745:
"\ntake one down, pass it around\n" <> bottle[n - 1] <>
" on the wall" <> If[n == 1, "", "\n\n"], {n, 99, 1, -1}]],
"+", accumulator++], {chr, Characters@program}]; accumulator]</langsyntaxhighlight>
 
=={{header|MiniScript}}==
<syntaxhighlight lang="miniscript">code = input("Enter HQ9+ program: ")
 
sing = function()
for i in range(99,2)
print i + " bottles of beer on the wall, " + i + " bottles of beer"
print "Take one down, pass it around, " + (i-1) + " bottle" + "s"*(i>2) + " of beer on the wall"
end for
print "1 bottle of beer on the wall, 1 bottle of beer"
print "Take one down, pass it around, no bottles of beer on the wall!"
end function
 
accumulator = 0
for c in code
c = c.lower
if c == "h" then print "Hello World"
if c == "q" then print code
if c == "9" then sing
if c == "+" then accumulator = accumulator + 1
end for</syntaxhighlight>
{{out}}
<pre>Enter HQ9+ program: hq9+
Hello World
hq9+
99 bottles of beer on the wall, 99 bottles of beer
Take one down, pass it around, 98 bottles of beer on the wall
98 bottles of beer on the wall, 98 bottles of beer
Take one down, pass it around, 97 bottles of beer on the wall
...
2 bottles of beer on the wall, 2 bottles of beer
Take one down, pass it around, 1 bottle of beer on the wall
1 bottle of beer on the wall, 1 bottle of beer
Take one down, pass it around, no bottles of beer on the wall!</pre>
 
=={{header|Nanoquery}}==
<syntaxhighlight lang="nanoquery">import Nanoquery.IO
 
// a function to handle fatal errors
def fatal_error(errtext)
println "%" + errtext
println "usage: " + args[1] + " [filename.cp]"
exit(1)
end
 
// a function to perform '99 bottles of beer'
def bottles(n)
for bottles in range(n, 1, -1)
bottlestr = ""
if bottles = 1
bottlestr = "bottle"
else
bottlestr = "bottles"
end if
println (bottles + " " + bottlestr + " of beer on the wall")
println (bottles + " " + bottlestr + " of beer")
println "Take one down, pass it around."
if !(bottles = 2)
println (bottles - 1 + " bottles of beer on the wall.\n")
else
println "1 bottle of beer on the wall.\n"
end if
end for
end
// get a filename from the command line and read the file in
fname = null
source = null
try
fname = args[2]
source = new(Nanoquery.IO.File, fname).readAll()
catch
fatal_error("error while trying to read from specified file")
end
 
// define an int to be the accumulator
accum = 0
 
// interpreter the hq9+
for char in source
if char = "h"
println "hello world!"
else if char = "q"
println source
else if char = "9"
bottles(99)
else if char = "+"
accum += 1
end
end</syntaxhighlight>
 
=={{header|NetRexx}}==
Line 901 ⟶ 1,847:
Modify contents of the program variable as you see fit.
 
<langsyntaxhighlight lang="nim">
var program = "9hHqQ+"
var i = 0
Line 933 ⟶ 1,879:
else:
echo("Unknown command: ", token)
</syntaxhighlight>
</lang>
 
=={{header|NS-HUBASIC}}==
<syntaxhighlight lang="ns-hubasic">10 INPUT "INPUT HQ9+ CODE: ",I$
20 B$="S"
30 W$=" ON THE WALL"
40 FOR I=1 TO LEN(I$)
50 C$=MID$(I$,I,1)
60 IF C$="H" THEN PRINT "HELLO, WORLD!"
70 IF C$="Q" THEN PRINT I$
80 A=A+(C$="+")
90 IF C$<>"9" GOTO 200
100 FOR B=99 TO 1 STEP -1
110 IF B=1 THEN B$=""
120 PRINT B " BOTTLE"B$" OF BEER" W$
130 PRINT B " BOTTLE"B$" OF BEER"
140 PRINT "TAKE ONE DOWN,"
150 PRINT "PASS IT AROUND"
160 IF B=2 THEN B$=""
170 IF B=1 THEN B$="S"
180 PRINT B-1 " BOTTLE"B$" OF BEER" W$
190 NEXT
200 NEXT</syntaxhighlight>
 
=={{header|OCaml}}==
Regrettably, HQ9+ suffers from remarkably poor implementations, even though the spec nailed down every aspect of the language (apart from the exact lyrics of the '9' operation, this obviously to allow for localization.) What's worse, the only implementation linked from the spec, when it was accessible, was an OCaml work that <i>refused to implement the '+' operation</i> among its several other deviations. The following code borrows 'beer' from its page.
 
<syntaxhighlight lang="ocaml">let hq9p line =
let accumulator = ref 0 in
for i = 0 to (String.length line - 1) do
match line.[i] with
| 'h' | 'H' -> print_endline "Hello, world!"
| 'q' | 'Q' -> print_endline line
| '9' -> beer 99
| '+' -> incr accumulator
done</syntaxhighlight>
 
=={{header|PARI/GP}}==
Line 939 ⟶ 1,920:
 
The lyrics are based on the reference implementation. The endline and case-insensitivity are from an example in the spec.
<langsyntaxhighlight lang="parigp">beer(n)={
if(n == 1,
print("1 bottle of beer on the wall");
Line 961 ⟶ 1,942:
if(v[i] == "+", accum++, error("Nasal demons"))
)
};</langsyntaxhighlight>
 
Sample input/output:
Line 969 ⟶ 1,950:
qqqq
qqqq</pre>
=={{header|Pascal}}==
==={{header|Free Pascal}}===
{{trans|Delphi}}
<syntaxhighlight lang="pascal">program HQ9;
 
procedure runCode(code: string);
var
c_len, i, bottles: Integer;
accumulator: Cardinal;
begin
c_len := Length(code);
accumulator := 0;
for i := 1 to c_len do
begin
case code[i] of
'Q','q':
writeln(code);
'H','h':
Writeln('Hello, world!');
'9':
begin
bottles := 99;
repeat
writeln(bottles,' bottles of beer on the wall');
writeln(bottles,' bottles of beer');
Writeln('Take one down, pass it around');
dec(bottles);
writeln(bottles,' bottles of beer on the wall',#13#10);
until (bottles <= 0);
end;
'+':
inc(accumulator);
end;
end;
end;
BEGIN
runCode('QqQh');
//runCode('HQ9+');// output to long
END.</syntaxhighlight>
{{out}}
<pre>
QqQh
QqQh
QqQh
Hello, world!</pre>
 
=={{header|Perl}}==
This implementation uses the ''switch'' feature.
<langsyntaxhighlight lang="perl">#!/usr/bin/perl
use warnings;
use strict;
Line 1,023 ⟶ 2,049:
return 'Take one down and pass it around' if $n > 0;
return 'Go to the store and buy some more';
}</langsyntaxhighlight>
 
=={{header|Perl 6Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
{{works with|rakudo|2015-09-10}}
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
The spec is kind of vague about how to do error handling... and whether white space is significant... and how the accumulator should be accessed... and pretty much everything else too.
<span style="color: #000080;font-style:italic;">-- copied from [[99_Bottles_of_Beer#Phix|99_Bottles_of_Beer]]</span>
 
<span style="color: #008080;">constant</span> <span style="color: #000000;">ninetynine</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span> <span style="color: #000080;font-style:italic;">-- (set this to 9 for testing)</span>
<lang perl6>class HQ9Interpreter {
has @!code;
has $!accumulator;
has $!pointer;
<span style="color: #008080;">function</span> <span style="color: #000000;">bottles</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">)</span>
method run ($code) {
<span style="color: #008080;">if</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"no more bottles"</span>
@!code = $code.comb;
<span style="color: #008080;">elsif</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"1 bottle"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
$!accumulator = 0;
<span style="color: #008080;">if</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ninetynine</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
$!pointer = 0;
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d bottles"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">count</span><span style="color: #0000FF;">)</span>
while $!pointer < @!code {
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
given @!code[$!pointer].lc {
when 'h' { say 'Hello world!' }
<span style="color: #008080;">function</span> <span style="color: #000000;">bob</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">)</span>
when 'q' { say @!code }
<span style="color: #008080;">return</span> <span style="color: #000000;">bottles</span><span style="color: #0000FF;">(</span><span style="color: #000000;">count</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">" of beer"</span>
when '9' { bob(99) }
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
when '+' { $!accumulator++ }
default { note "Syntax error: Unknown command \"{@!code[$!pointer]}\"" }
<span style="color: #008080;">function</span> <span style="color: #000000;">up1</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">bob</span><span style="color: #0000FF;">)</span>
}
<span style="color: #000080;font-style:italic;">-- Capitalise sentence start (needed just the once, "no more"=&gt;"No more")</span>
$!pointer++;
<span style="color: #000000;">bob</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: #7060A8;">upper</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bob</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
}
<span style="color: #008080;">return</span> <span style="color: #000000;">bob</span>
}
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
sub bob ($beer is copy) {
sub what { "{$beer??$beer!!'No more'} bottle{$beer-1??'s'!!''} of beer" };
<span style="color: #008080;">procedure</span> <span style="color: #000000;">ninetyninebottles</span><span style="color: #0000FF;">()</span>
sub where { 'on the wall' };
<span style="color: #004080;">string</span> <span style="color: #000000;">thus</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">bob</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ninetynine</span><span style="color: #0000FF;">),</span>
sub drink { $beer--; "Take one down, pass it around," }
<span style="color: #000000;">that</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"Take one down, pass it around,\n"</span>
while $beer {
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">ninetynine</span> <span style="color: #008080;">to</span> <span style="color: #000000;">0</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
.say for "&what() &where(),", "&what()!",
<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;">up1</span><span style="color: #0000FF;">(</span><span style="color: #000000;">thus</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">" on the wall,\n"</span><span style="color: #0000FF;">)</span>
"&drink()", "&what() &where()!", ''
<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;">thus</span><span style="color: #0000FF;">&</span><span style="color: #008000;">".\n"</span><span style="color: #0000FF;">)</span>
}
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">that</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"Go to the store, buy some more,\n"</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000000;">that</span><span style="color: #0000FF;">[</span><span style="color: #000000;">6</span><span style="color: #0000FF;">..</span><span style="color: #000000;">8</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"it"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">thus</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">bob</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</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;">that</span><span style="color: #0000FF;">&</span><span style="color: #000000;">thus</span><span style="color: #0000FF;">&</span><span style="color: #008000;">" on the wall.\n\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">-- if getc(0) then end if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000080;font-style:italic;">-- the interpreter</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">hq9</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">accumulator</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">code</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">switch</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">upper</span><span style="color: #0000FF;">(</span><span style="color: #000000;">code</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]))</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'H'</span><span style="color: #0000FF;">:</span> <span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Hello, world!\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'Q'</span><span style="color: #0000FF;">:</span> <span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">);</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'9'</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">ninetyninebottles</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;">accumulator</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">hq9</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"h9+HqQ+Qq"</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Hello, world!
2 bottles of beer on the wall,
2 bottles of beer.
Take one down, pass it around,
1 bottle of beer on the wall.
 
1 bottle of beer on the wall,
1 bottle of beer.
Take it down, pass it around,
no more bottles of beer on the wall.
 
No more bottles of beer on the wall,
no more bottles of beer.
Go to the store, buy some more,
2 bottles of beer on the wall.
 
Hello, world!
h9+HqQ+Qq
h9+HqQ+Qq
h9+HqQ+Qq
h9+HqQ+Qq
</pre>
 
=={{header|PHP}}==
<syntaxhighlight lang="php">
/*
H Prints "Hello, world!"
Q Prints the entire text of the source code file.
9 Prints the complete canonical lyrics to "99 Bottles of Beer on the Wall"
+ Increments the accumulator.
*/
$accumulator = 0;
echo 'HQ9+: ';
$program = trim(fgets(STDIN));
 
foreach (str_split($program) as $chr) {
switch ($chr) {
case 'H':
case 'h':
printHelloWorld();
break;
case 'Q':
case 'q':
printSource($program);
break;
case '9':
print99Bottles();
break;
case '+':
$accumulator = incrementAccumulator($accumulator);
break;
default:
printError($chr);
}
}
 
function printHelloWorld() {
# Feed it a command string:
echo 'Hello, world!'. PHP_EOL;
}
 
function printSource($program) {
my $hq9 = HQ9Interpreter.new;
echo var_export($program, true) . PHP_EOL;
$hq9.run("hHq+++Qq");
}
say '';
$hq9.run("Jhq.k+hQ");</lang>
 
function print99Bottles() {
Output:
$n = 99;
<pre>
while($n >= 1) {
Hello world!
echo $n;
Hello world!
echo ' Bottles of Beer on the Wall ';
hHq+++Qq
echo $n;
hHq+++Qq
echo ' bottles of beer, take one down pass it around ';
hHq+++Qq
echo $n-1;
echo ' bottles of beer on the wall.'. PHP_EOL;
$n--;
}
}
 
function incrementAccumulator($accumulator) {
Syntax error: Unknown command "J"
return ++$accumulator;
Hello world!
}
Jhq.k+hQ
 
Syntax error: Unknown command "."
function printError($chr) {
Syntax error: Unknown command "k"
echo "Invalid input: ". $chr;
Hello world!
}</syntaxhighlight>
Jhq.k+hQ
{{out}}
<pre>
HQ9+: qqqq
'qqqq'
'qqqq'
'qqqq'
'qqqq'
</pre>
 
Or start a REPL (Read Execute Print Loop) and interact at the command line:
<lang perl6>my $hq9 = HQ9Interpreter.new;
while 1 {
my $in = prompt('HQ9+>').chomp;
last unless $in.chars;
$hq9.run($in)
}</lang>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de hq9+ (Code)
(let Accu 0
(for C (chop Code)
Line 1,107 ⟶ 2,214:
(prinl) ) )
("+" (inc 'Accu)) ) )
Accu ) )</langsyntaxhighlight>
 
=={{header|PowerShell}}==
I'm not sure why, but it bothered me that the '+' function of HQ9+ was completely useless. So I added the <code>-Global</code>
switch option. When specified it creates and/or increments a variable named '+' in the global scope.
 
This program treats all text except for 'H','Q','9' and '+' as whitespace and when 'Q' is called, returns the exact text. This
is only my preference and could be easily modified.
 
As far as I can tell, there are no errors in HQ9+; but, supposing there are, a 'Default' could be added to the switch statement.
<syntaxhighlight lang="powershell">
function Invoke-HQ9PlusInterpreter ([switch]$Global)
{
$sb = New-Object -TypeName System.Text.StringBuilder
 
for ($i = 99; $i -gt 2; $i--)
{
$sb.Append((("{0,2} bottles of beer on the wall, " +
"{0,2} bottles of beer! Take one down, pass it around, " +
"{1,2} bottles of beer on the wall.`n") -f $i, ($i - 1))) | Out-Null
}
$sb.Append((" 2 bottles of beer on the wall, " +
" 2 bottles of beer! Take one down, pass it around, " +
" 1 bottle of beer on the wall.`n")) | Out-Null
$sb.Append((" 1 bottle of beer on the wall, " +
" 1 bottle of beer! Take one down, pass it around...`n")) | Out-Null
$sb.Append(("No more bottles of beer on the wall, No more bottles of beer!`n" +
"Go to the store and get us some more, 99 bottles of beer on the wall!")) | Out-Null
 
$99BottlesOfBeer = $sb.ToString()
 
$helloWorld = "Hello, world!"
 
if ($Global) {New-Variable -Name "+" -Value 0 -Scope Global -ErrorAction SilentlyContinue}
 
Write-Host "Press Ctrl-C or Enter nothing to exit." -ForegroundColor Cyan
 
while ($code -ne "")
{
$code = Read-Host -Prompt "HQ9+"
 
($code.ToCharArray() | Select-String -Pattern "[HQ9+]").Matches.Value | ForEach-Object {
switch ($_)
{
"H" {$helloWorld; break}
"Q" {$code; break}
"9" {$99BottlesOfBeer; break}
"+" {if ($Global) {${global:+}++}}
}
}
}
}
 
Set-Alias -Name HQ9+ -Value Invoke-HQ9PlusInterpreter
</syntaxhighlight>
Example sessions:
<pre>
PS C:\Scripts> HQ9+ -Global
Press Ctrl-C or Enter nothing to exit.
HQ9+: 9headquarters++
99 bottles of beer on the wall, 99 bottles of beer! Take one down, pass it around, 98 bottles of beer on the wall.
98 bottles of beer on the wall, 98 bottles of beer! Take one down, pass it around, 97 bottles of beer on the wall.
.
.
.
3 bottles of beer on the wall, 3 bottles of beer! Take one down, pass it around, 2 bottles of beer on the wall.
2 bottles of beer on the wall, 2 bottles of beer! Take one down, pass it around, 1 bottle of beer on the wall.
1 bottle of beer on the wall, 1 bottle of beer! Take one down, pass it around...
No more bottles of beer on the wall, No more bottles of beer!
Go to the store and get us some more, 99 bottles of beer on the wall!
Hello, world!
9headquarters++
HQ9+:
 
PS C:\Scripts> ${+}
2
 
PS C:\Scripts> HQ9+ -Global
Press Ctrl-C or Enter nothing to exit.
HQ9+: hq++
Hello, world!
hq++
HQ9+:
 
PS C:\Scripts> ${+}
4
 
</pre>
 
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">Procedure hq9plus(code.s)
Protected accumulator, i, bottles
For i = 1 To Len(code)
Line 1,137 ⟶ 2,331:
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
CloseConsole()
EndIf</langsyntaxhighlight>
 
=={{header|Python}}==
 
See [[RCHQ9+/Python]].
 
=={{header|Quackery}}==
 
<syntaxhighlight lang="quackery">$ "bottles.qky" loadfile ( if required, the source code for this can be found at
http://rosettacode.org/wiki/99_bottles_of_beer#Quackery )
 
[ stack ] is accumulator ( --> s )
 
[ stack ] is sourcecode ( --> s )
 
[ say "Hello, world!" cr ] is H.HQ9+ ( --> )
 
[ sourcecode share
echo$ cr ] is Q.HQ9+ ( --> )
 
[ 99 song echo$ ] is 9.HQ9+ ( --> )
 
[ 1 accumulator tally ] is +.HQ9+ ( --> )
 
[ dup sourcecode put
0 accumulator put
witheach
[ $ ".HQ9+" join
quackery ]
sourcecode release
cr say "Accumulator = "
accumulator take echo ] is HQ9+ ( $ --> )
 
$ "HH+QQQQ+" HQ9+</syntaxhighlight>
 
{{Out}}
 
<pre>Hello, world!
Hello, world!
HH+QQQQ+
HH+QQQQ+
HH+QQQQ+
HH+QQQQ+
 
Accumulator = 2</pre>
 
=={{header|Racket}}==
Line 1,150 ⟶ 2,384:
strictly case-sensitive.
 
<langsyntaxhighlight lang="racket">#lang racket
; if we `for` over the port, we won't have the program in memory for 'Q'
(define (parse-HQ9+ the-program)
Line 1,197 ⟶ 2,431:
(check-equal? (with-output-to-string (lambda () (parse-HQ9+ (make-string 10000 #\+)))) "")
;;; you can jolly well read (and sing along to) the output of '9'
)</langsyntaxhighlight>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|rakudo|2015-09-10}}
The spec is kind of vague about how to do error handling... and whether white space is significant... and how the accumulator should be accessed... and pretty much everything else too.
 
<syntaxhighlight lang="raku" line>class HQ9Interpreter {
has @!code;
has $!accumulator;
has $!pointer;
method run ($code) {
@!code = $code.comb;
$!accumulator = 0;
$!pointer = 0;
while $!pointer < @!code {
given @!code[$!pointer].lc {
when 'h' { say 'Hello world!' }
when 'q' { say @!code }
when '9' { bob(99) }
when '+' { $!accumulator++ }
default { note "Syntax error: Unknown command \"{@!code[$!pointer]}\"" }
}
$!pointer++;
}
}
sub bob ($beer is copy) {
sub what { "{$beer??$beer!!'No more'} bottle{$beer-1??'s'!!''} of beer" };
sub where { 'on the wall' };
sub drink { $beer--; "Take one down, pass it around," }
while $beer {
.say for "&what() &where(),", "&what()!",
"&drink()", "&what() &where()!", ''
}
}
}
 
# Feed it a command string:
 
my $hq9 = HQ9Interpreter.new;
$hq9.run("hHq+++Qq");
say '';
$hq9.run("Jhq.k+hQ");</syntaxhighlight>
 
Output:
<pre>
Hello world!
Hello world!
hHq+++Qq
hHq+++Qq
hHq+++Qq
 
Syntax error: Unknown command "J"
Hello world!
Jhq.k+hQ
Syntax error: Unknown command "."
Syntax error: Unknown command "k"
Hello world!
Jhq.k+hQ
</pre>
 
Or start a REPL (Read Execute Print Loop) and interact at the command line:
<syntaxhighlight lang="raku" line>my $hq9 = HQ9Interpreter.new;
while 1 {
my $in = prompt('HQ9+>').chomp;
last unless $in.chars;
$hq9.run($in)
}</syntaxhighlight>
 
=={{header|REXX}}==
Note that the actual text of the &nbsp; ''Hello, world!'' &nbsp; message can differ among definitions.
<lang rexx>/*REXX program to implement the HQ9+ language.*/ parse arg pgm .
<syntaxhighlight lang="rexx">/*REXX program implements the HQ9+ language. ───────────────────────────────────────*/
accumulator=0
arg pgm . /*obtain optional argument.*/
do instructions=1 for length(pgm); ?=substr(pgm,instructions,1)
accumulator=0 /*assign default to accum. */
select
 
when ?=='H' then say "hello, world" /*this salutation varies. */
when ?=='Q' then do jinstructions=1 for sourcelinelength(pgm); say sourceline ?=substr(j);pgm, instructions, end1)
when ?== 9 then call 99select
when ?=='+H' then accumulator=accumulator+1say "Hello, world!" /*text varies on definition*/
when ?=='Q' then do j=1 for sourceline(); say sourceline(j); end /*j*/
otherwise say 'invalid HQ9+ instruction:' ?
end /*select*/when ?== 9 then call 99
when ?=='+' then accumulator=accumulator+1
end /*instructions*/
otherwise say 'invalid HQ9+ instruction:' ?
exit /*stick a fork in it, we're done.*/
end /*select*/
/*──────────────────────────────────99 subroutine───────────────────────*/
end /*instructions*/
99: do j=99 by -1 to 1
exit /*stick a fork in it, we're all done. */
say j 'bottle's(j) "of beer the wall,"
/*──────────────────────────────────────────────────────────────────────────────────────*/
say j 'bottle's(j) "of beer."
99: do j=99 by -1 to 1
say 'Take one down, pass it around,'
say j 'bottle's(j) "of beer the wall,"
n=j-1
if n==0 then n='no' say j 'bottle's(j) "of /*cheating to use 0beer. */"
say 'Take one down, pass it around,'
say n 'bottle's(j-1) "of beer the wall."
say n=j-1
if n==0 then n='no' /*cheating to use 0. */
end
say n 'bottle's(j-1) "of beer the wall."
say 'No more bottles of beer on the wall,' /*finally, last verse.*/
say
say 'no more bottles of beer.'
end /*j*/
say 'Go to the store and buy some more,'
say '99No more bottles of beer on the wall.,' /*finally, last verse.*/
say 'no more bottles of beer.'
return
say 'Go to the store and buy some more,'
/*──────────────────────────────────S subroutine────────────────────────*/
say '99 bottles of beer on the wall.'
s: if arg(1)==1 then return ''; return "s" /*a simple pluralizer.*/</lang>
return
'''output''' when using the input of: <tt> H+Q </tt>
/*──────────────────────────────────────────────────────────────────────────────────────*/
<pre style="height:40ex">
s: if arg(1)==1 then return ''; return "s" /*a simple pluralizer.*/</syntaxhighlight>
hello, world
'''output''' &nbsp; when using the input of: &nbsp; <tt> HHH </tt>
/*REXX program to implement the HQ9+ language.*/ parse arg pgm .
<pre>
accumulator=0
Hello, world!
do instructions=1 for length(pgm); ?=substr(pgm,instructions,1)
Hello, world!
select
Hello, world!
when ?=='H' then say "hello, world"
</pre>
when ?=='Q' then do j=1 for sourceline(); say sourceline(j); end
 
when ?== 9 then call 99
=={{header|Ring}}==
when ?=='+' then accumulator=accumulator+1
<syntaxhighlight lang="ring">
otherwise say 'invalid HQ9+ instruction:' ?
# Project : Execute HQ9
end /*select*/
 
end /*instructions*/
bottle("hq9+HqQ+Qq")
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────99 subroutine───────────────────────*/
func bottle(code)
99: do j=99 by -1 to 1
accumulator = 0
say j 'bottle's(j) "of beer the wall,"
for i = 1 to len(code)
say j 'bottle's(j) "of beer."
switch code[i]
say 'Take one down, pass it around,'
on "h"
n=j-1
if n==0 then n='no' see "Hello, world!" + /*cheating to use 0. */nl
say n 'bottle's(j-1) "of beer the wall. on "H"
see "hello, world!" + nl
say
on "q"
end
say 'No more bottles of beer on the wall,' /*finally, last verse.*/ see code + nl
on "Q"
say 'no more bottles of beer.'
see code + nl
say 'Go to the store and buy some more,'
on "9"
say '99 bottles of beer on the wall.'
bottles = 99
return
while bottles > 0
/*──────────────────────────────────S subroutine────────────────────────*/
see "" + bottles + " bottles of beer on the wall, "
s: if arg(1)==1 then return ''; return "s" /*a simple pluralizer.*/
see "" + bottles + " bottles of beer," + nl
bottles = bottles - 1
see "take one down, pass it around, "
see "" + bottles + " bottles of beer on the wall." + nl
end
on "+"
accumulator = accumulator + 1
off
next
</syntaxhighlight>
Output:
<pre>
Hello, world!
hq9+HqQ+Qq
99 bottles of beer on the wall, 99 bottles of beer,
Take one down, pass it around, 98 bottles of beer on the wall.
98 bottles of beer on the wall, 98 bottles of beer,
Take one down, pass it around, 97 bottles of beer on the wall.
...
3 bottles of beer on the wall, 3 bottles of beer,
Take one down, pass it around, 2 bottles of beer on the wall.
2 bottles of beer on the wall, 2 bottles of beer,
Take one down, pass it around, 1 bottles of beer on the wall.
1 bottles of beer on the wall, 1 bottles of beer,
Take one down, pass it around, 0 bottles of beer on the wall.
Hello, world!
hq9+HqQ+Qq
hq9+HqQ+Qq
hq9+HqQ+Qq
hq9+HqQ+Qq
</pre>
 
Line 1,266 ⟶ 2,598:
 
See [[RCHQ9+/Ruby]].
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">use std::env;
 
// HQ9+ requires that '+' increments an accumulator, but it's inaccessible (and thus, unused).
#[allow(unused_variables)]
fn execute(code: &str) {
let mut accumulator = 0;
 
for c in code.chars() {
match c {
'Q' => println!("{}", code),
'H' => println!("Hello, World!"),
'9' => {
for n in (1..100).rev() {
println!("{} bottles of beer on the wall", n);
println!("{} bottles of beer", n);
println!("Take one down, pass it around");
if (n - 1) > 1 {
println!("{} bottles of beer on the wall\n", n - 1);
} else {
println!("1 bottle of beer on the wall\n");
}
}
}
'+' => accumulator += 1,
_ => panic!("Invalid character '{}' found in source.", c),
}
}
}
 
fn main() {
execute(&env::args().nth(1).unwrap());
}</syntaxhighlight>
 
=={{header|Scala}}==
<langsyntaxhighlight Scalalang="scala">def hq9plus(code: String) : String = {
var out = ""
var acc = 0
Line 1,302 ⟶ 2,668:
 
println(hq9plus("HQ9+"))
</syntaxhighlight>
</lang>
 
=={{header|Seed7}}==
The program below accepts the HQ9+ program as command line parameter:
 
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const proc: runCode (in string: code) is func
Line 1,338 ⟶ 2,704:
runCode(argv(PROGRAM)[1]);
end if;
end func;</langsyntaxhighlight>
 
=={{header|Sidef}}==
{{trans|Perl 6Raku}}
<langsyntaxhighlight lang="ruby">class HQ9Interpreter {
has pointer;
has accumulator;
Line 1,372 ⟶ 2,738:
}
}
}</langsyntaxhighlight>
 
Usage:
<langsyntaxhighlight lang="ruby">var hq9 = HQ9Interpreter();
hq9.run("hHq+++Qq");</langsyntaxhighlight>
 
{{out}}
Line 1,388 ⟶ 2,754:
 
Or start a REPL (Read Execute Print Loop) and interact at the command line:
<langsyntaxhighlight lang="ruby">var hq9 = HQ9Interpreter();
loop {
var in = read('HQ9+>', String) \\ break;
hq9.run(in)
}</langsyntaxhighlight>
 
=={{header|Tcl}}==
 
See [[RCHQ9+/Tcl]].
 
=={{header|Ursa}}==
 
see [[Execute HQ9+/Ursa]]
 
=={{header|Ursala}}==
 
See [[RCHQ9+/Ursala]].
 
=={{header|Wren}}==
{{trans|Kotlin}}
<syntaxhighlight lang="wren">import "os" for Process
 
var hq9plus = Fn.new { |code|
var acc = 0
var sb = ""
for (c in code) {
if (c == "h" || c == "H") {
sb = sb + "Hello, world!\n"
} else if (c == "q" || c == "Q") {
sb = sb + code + "\n"
} else if (c == "9") {
for (i in 99..1) {
var s = (i > 1) ? "s" : ""
sb = sb + "%(i) bottle%(s) of beer on the wall\n"
sb = sb + "%(i) bottle%(s) of beer\n"
sb = sb + "Take one down, pass it around\n"
}
sb = sb + "No more bottles of beer on the wall!\n"
} else if (c == "+") {
acc = acc + 1
} else {
Fiber.abort("Code contains illegal operation '%(c)'")
}
}
System.print(sb)
}
 
var args = Process.arguments
if (args.count != 1) {
System.print("Please pass in the HQ9+ code to be executed.")
} else {
hq9plus.call(args[0])
}</syntaxhighlight>
 
{{out}}
If a command line argument of hq9+ is passed in, the output is the same as the Kotlin entry.
 
=={{header|x86 Assembly}}==
<syntaxhighlight lang="x86 assembly">
 
;ds:si: pointer to asciiz string containing HQ9++ source code
ExecuteHQ9:
push ax
push dx
push si
push di
push es
push bx
mov bx, si
.interpret:
lodsb
cmp al, 'H'
je .doHelloWorld
cmp al, 'Q'
je .doPrintCode
cmp al, '9'
je .doDrinkBeer
cmp al, '+'
je .doCounter
pop bx
pop es
pop di
pop si
pop dx
pop ax
ret
.doHelloWorld:
push ds
mov ax, cs
mov ds, ax
push si
mov si, .dataHelloWorld
call .printString
pop si
pop ds
jmp .interpret
.doPrintCode:
push si
mov si, bx
call .printString
pop si
jmp .interpret
.doDrinkBeer:
push ds
push si
push ax
mov ax, cs
mov ds, ax
mov ax, 99
.beer_loop:
call .printHexNumber
mov si, .dataBeerSong1
call .printString
call .printHexNumber
mov si, .dataBeerSong2
call .printString
dec ax
call .printHexNumber
mov si, .dataBeerSong3
call .printString
test ax, ax
jnz .beer_loop
pop ax
pop si
pop ds
jmp .interpret
.doCounter:
push ax
inc ax
pop ax
jmp .interpret
.printString:
push ax
push si
.looping:
lodsb
test al, al
jz .done
mov ah, 0Eh
int 10h
jmp .looping
.done:
pop si
pop ax
ret
.printHexNumber:
pusha
push ds
mov ax, cs
mov ds, ax
push word 0
mov bx, ax
xor dx, dx
mov cx, 4r
.convert_loop:
mov ax, bx
and ax, 0Fh
cmp ax, 9
ja .greater_than_9
add ax, '0'
jmp .converted
.greater_than_9:
add ax, 'A'-0Ah
.converted:
push ax
shr bx, 4
dec cx
jnz .convert_loop
.popoff:
pop ax
cmp ax, 0
je .done
mov ah, 0Eh
int 10h
jmp .popoff
.done:
pop ds
popa
ret
 
.dataHelloWorld: db "Hello World!", 0
.dataBeerSong1: db " bottles of beer on the wall ", 0
.dataBeerSong2: db " bottles of beer", 13, 10, "Take one down, pass it around "
.dataBeerSong3: db 0, " bottles of beer on the wall", 0
 
</syntaxhighlight>
 
=={{header|XSLT}}==
Line 1,410 ⟶ 2,955:
Requires <code>bottles.xsl</code> (below).
 
<langsyntaxhighlight lang="xml"><?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- bottles.xsl defines $entire-bottles-song -->
Line 1,462 ⟶ 3,007:
</xsl:if>
</xsl:template>
</xsl:stylesheet></langsyntaxhighlight>
 
=====Details=====
Line 1,468 ⟶ 3,013:
Input to this sheet is given by placing the entire source as a single <code><nowiki><code/></nowiki></code> element. For example, to run the example program <code>qqqq</code>, use the sheet to transform the document
 
<syntaxhighlight lang ="xml"><code>qqqq</code></langsyntaxhighlight>
 
Newlines are added in roughly the same places as in the C version. For example, the program <code>qqqq</code> results in four lines of output rather than one long line.
Line 1,480 ⟶ 3,025:
Requires <code>bottles.xsl</code> (below)
 
<langsyntaxhighlight lang="xml"><?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- bottles.xsl defines $entire-bottles-song -->
Line 1,589 ⟶ 3,134:
</xsl:choose>
</xsl:template>
</xsl:stylesheet></langsyntaxhighlight>
 
=====Details=====
Line 1,597 ⟶ 3,142:
Input to this sheet is given by placing one or more sources as <code><nowiki><code/></nowiki></code> elements. For example, to run the example program <code>qqqq</code>, use the sheet to transform the document
 
<syntaxhighlight lang ="xml"><code>qqqq</code></langsyntaxhighlight>
 
or the programs <code>qqqq</code> and <code>++++</code> can be run in the same pass by transforming
 
<langsyntaxhighlight lang="xml"><programs>
<code>qqqq</code>
<code>++++</code>
</programs></langsyntaxhighlight>
 
The output document is a <code><nowiki><results/></nowiki></code> element containing a <code><nowiki><result/></nowiki></code> element for each <code><nowiki><code/></nowiki></code> element processed from the input. If a <code>+</code> appeared in the program, the <code><nowiki><result/></nowiki></code> element will indicate the final value of the accumulator in its <code>accumulator</code> attribute. For example, the output for the latter example, would be
 
<langsyntaxhighlight lang="xml"><results><result>qqqq
qqqq
qqqq
qqqq
</result><result accumulator="4"/></results></langsyntaxhighlight>
 
====bottles.xsl====
Line 1,618 ⟶ 3,163:
This sheet defines a value for the variable <code>$entire-bottles-song</code> (see [[99 Bottles of Beer]] for the general idea).
 
<langsyntaxhighlight lang="xml"><?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:lo="urn:uuid:59afd337-03a8-49d9-a7a8-8e2cbc4ef9cc">
<!-- Note: xmlns:lo is defined as a sort of pseudo-private namespace -->
Line 1,672 ⟶ 3,217:
</xsl:variable>
 
</xsl:stylesheet></langsyntaxhighlight>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">fcn runHQ9(code){
acc:=0;
foreach c in (code){
Line 1,697 ⟶ 3,242:
(n==0 and "No more bottles" or (n==1 and "1 bottle" or "" + n + " bottles"))
+ " of beer"
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">runHQ9("90HQ+junk");</langsyntaxhighlight>
{{out}}
<pre>
1,480

edits