Blues++
Paradigm(s) | imperative |
---|---|
Designed by | User:Faustify |
Appeared in | 2024 |
Computational class | Turing complete |
Reference implementation | |
Influenced by | Velato |
File extension(s) |
Blues++ is an esoteric programming language that uses note sheets as its source code. It is based on the Blues Scale (with an additional 7th note) and the x86 Assembly. Blues++ focuses on musical expression without scarificing functionality.
Computational class
Blues++ is Turing-complete as the command set of brainfuck is a subset of the command set of Blues++.
Language overview
Blues++ uses two staffs - a trebble and a bass voice. The bass one defines the instructions, while the trebble provides the inputs (registers or values). Blues++ uses 6 registers (rax, rbx, rsp, r10, rdi, and rcx) - corresponding to the 6th notes on the blues scale (1, ♭3, 4, ♭5, 5, ♭7). All values used in Blues++ have a size of 64 bits (8 bytes). Additional note sheet notation is used to define loops (repeat signs) and conditional blocks (volta brackets).
Syntax
Blues++ uses the bass voice to denote the type and duration of instruction. The trebble voice specifies the operands. Operands without an instruction being played in the bass cleff are simply interpreted as comments.
Registers and Values
Blues++ distinguishes between two possible operands - registers and values. Registers are always half the duration of the instruction. Thus if the instruction is a whole note, specifying a register is performed by playing a half note. If the instruction is a half note, registers are a quarter note. Registers played as a detached (stacatto) note are interpreted as dereferencing the register value. Values are a combination of notes with a duration of less than register one. So with a whole note as instruction length, values are palyed as any combination of notes with duration under a half note.
Registers
The registers available (additionally their order number in the blues scale is provided for the aid of the reader):
Register | Note |
---|---|
rax | root (or a rest) - 1st note |
rbx | Minor third - 2nd note |
rsp | Perfect fourth - 3rd note |
rdi | Minor fifth - 4th note |
rcx | Perfect fifth - 5th note |
r10 | Minor sevent - 6th note |
Caller-saved registers: rax, r10
Callee-saved registers: rbx, rcx, rsp, rdi
Values
Values are a combination of notes with a duration of less than register one. Each note from the blues scale has a corresponding number:
Note | Value |
---|---|
Root | 1 |
Minor third | 2 |
Perfect fourth | 3 |
Minor fifth | 0 |
Perfect fifth | 4 |
Minor seventh | 5 |
Major seventh | 6 |
Notes played in order are added to form the number they represent. For example playing ♭3, 4, 4, ♭5, 7 is interpreted as 2 + 3 + 3 + 0 + 6 = 14. Chords are interpreted per voicing. For example in a triad of the minor chord (5, 1, ♭3 - in this case second inversion), the values will be interpreted as 4 + (1*7 + 1) + (2*7 + 2) = 4 + 8 + 16 = 28. Thus Blues++ operates in base-7.
Commands
Command | Note(s) | Description |
---|---|---|
movq | root (1st note) | Moves quadword from the source (first operand) to the destination (second operand). |
addq | minor third (2nd note) | Adds the source and destination operand and stores the result in the source (first operand). |
put | perfect fourth (3rd note) | Stores the source (value or register's value) on the tape, where the rsp register is currently pointing to. |
multq | Minor fifth (4th note) | Multiplies the source and destination operand and stores the result in the source (first operand). |
negq | Perfect fifth (5th note) | Negation of the given register |
get | Minor sevent (6th note) | Moves the value stored where the rsp register is currently pointing to to the source register |
xor | Major sevent (7th note) | Logical Exclusive OR between the source and destination operand and stores the result in the source (first operand). |
cmpq | Perfect fifth interval (1st + 5th note, 2nd + 6th note, 3rd + 1st note...) | Compares the source (first operand) to the destination (second operand) and stores the result in FLAG register (0 or 1). 0 is assigned if source is a register, the destination is a value, and the stored register value is not equal to the value. 1 is assigned if they are equal. 0 is assigned if both are registers and the source is larger than the destination. 1 if it is equal or smaller. |
cmovq | Minor third interval | Conditionally performs a movq operation if the FLAG register is currently 1. Sets the FLAG register to 0 |
syscall | Any triad | Performs a system call (specified by the RAX register) with inputs RBX, RCX, and R10. Return value is stored in RAX |
Octaves are interpreted as a single note and the corresponding instruction to that note.
System Calls
callnum (rax value) | Type | Description |
---|---|---|
0 | Read | Read number of bytes (number specified by rcx) from fd as specified by rbx onto memory location as specified by rdi. Success of operation is stored in rax. |
1 | write | Write the value of rcx into a fd as specified by rbx (2 for stdout, 1 stderr...). Success of operation is stored in rax. |
60 | exit | Exit the program. Return code is given by rbx. |
Programs
Hello World
An example of a Hello World program (will output ASCII codes of the string "hello world" to standard output) in Blues++ in C minor.
The program in pseudo-assembly:
movq %rax, $1 movq %rbx, $2 movq %rcx, $8 addq %rcx, $2 multq %rcx, $4 multq %rcx, $2 syscall movq %rax, $1 movq %rdi, $3 negq %rdi // 8 addq %rax, %rdi syscall addq %rcx, $7 movq %rax, $1 syscall movq %rax, $1 syscall addq %rcx, $3 movq %rax, $1 syscall movq %rax, $1 movq %rcx, $8 multq %rcx, $4 syscall movq %rax, $1 multq %rcx, $3 addq %rcx, $10 addq %rcx, $10 addq %rcx, $3 syscall movq %rax, $1 multq %multq, $3 addq %rcx, %rdi addq %rcx, $1 movq %rax, $1 addq %rcx, $3 syscall movq %rax, $1 addq %rcx, %rdi addq %rcx, %rdi syscall movq %rax, $1 addq %rcx, %rdi addq %rcx, $2 syscall movq %rax, $10 multq %rax, $6 movq %rbx, $0 syscall
An audio version of the note sheets can be found on YouTube