Blues++

From Esolang
Jump to navigation Jump to search
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:

Caption text
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.


First Part
Second Part
Third Part

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