Auphics
Auphics is an esoteric programming language by User:BoundedBeans featuring:
- Graphical Input
- Audio output
- Tree variables
Variables and expressions
All variables in Auphics are immutable binary trees of signed 64-bit integers. Expressions are either trees or integers. The variables can be reassigned, but the underlying trees cannot be modified.
To create a tree:
(name) = :(number of levels);
var = :<3<;
:(expression)
is itself an expression, and evaluates to the tree it creates. It can be immediately indexed or whatever.
The name should contain only lowercase letters. Names beginning with auph
are reserved; auphx
for the implementation, auphi
for the language, auphc
for internal variables by compilers to Auphics (if such a thing is ever made), and the rest for further reservations.
To delete a tree:
-(name);
-var;
Tree elements are accessed by the format:
(name)[(path)]
Path is a list of 1’s and 2’s, with 2 being the right branch and the first digit representing the top branching point. <0<
represents the root node.
Example:
var[<211211222<] var[(<1< * <10<) + <2<]
Also, the var may be replaced with a tree expression.
Additionally, the form:
(tree)[(path),(new value)]
returns a new tree with that is the same as the original but with a single modification.
Every tree t
has two parents, t >++ <1<
and t >++ <2<
. t
itself is accessed with t >++ <0<
. t >++ <3<
or t >++ <4<
creates a special type not assignable to variables. This special type can be turned into a tree with it >++
(another tree). This creates a tree that is the same as t
, but with one of its parents set to the other tree. If <3<
was passed in, parent 1 changes, and if <4<
was passed in, parent 2 changes. Both are automatically copied in this operation.
The parent mechanic is a solution to infinite data structures. Normally, trees can only have so many levels, because of the 64-bit integer size limit. Now you can have an infinitely sized tree of trees, built from the leaves down. You can use this to represent two stacks. The actual reason this was done was to allow a sufficient data structure to represent a convolutional neural network to allow the graphical input to be somewhat useful. The way to actually represent the network has not been determined, but a single tree of integers is probably not good enough. A convenient representation is not known, but an inconvenient representation exists by emulating two stacks as taking the same branch each time for the two branches, and emulating a Turing machine.
You can use the operators +-*/%
on integers. Note that as a special case, x / <0<
= <0<
, allowing division of a number by itself to boolean-ize it. (This allows various gates:
Not: <1< - a
And: a * b
Or: (a + b)/(a + b)
)
Constants can be represented in a format like <53<
I/O
To output one of the sounds in the sound library, you use an exclamation point followed by a numerical expression.
Command:
!(expression);
Yes, there is a certain sound library, and you may only use these sounds.
Sounds get put into a queue, and do not overlap playback. Sound <0<
(silence), counts as a sound, and outputting it creates pauses. All sounds should take exactly one second to finish.
You can wait a certain number of milliseconds with WAIT
(expression);
Sound library:
0 - silence 1 - piano note middle c 2 - dog bark 3 - cat meow 4 - snare drum 5 - chomp 6 - applause 7 - saying "0" 8 - saying "1" 9 - whisper "0" 10 - whisper "1" 11 - shout "0" 12 - shout "1" 13 - say "Auphics" 14 - horn middle c 15 - water drop 16 - guitar middle c 17 - organ middle c 18 - camera shutter 19 - door creak 20 - growl 21-46 - English letter names spoken 47-57 - English number names spoken
$$
as an expression evaluates to input as an image.
var = $$;
All graphical input is black and white, 64x64 pixels, and stored as a matrix of integers from 0-255, each number being a pixel. It will be stored in the tree by putting 11 levels of 0’s on the tree, then on the 12th level putting rows of the matrix in standard English reading order, folded out into 1 dimension, and spread across all branches of the tree.
There is a way to print things in text, but it is designed to encourage audio output. Assigning to auphipr
will cause a single bit to be printed. The bit depends on the "favorite digit" which is the digit that appears most times throughout the program. If there is a tie, the numbers should be concatenated in decreasing order. Add 57 to the result. Convert to UTF-8, then add A
if it happens on an odd statement index from the beginning of the program (one-based), and .
otherwise. Take the MD5 hash, then take the 3rd bit. That bit will be added to a queue. Once the queue has 8 elements, the corresponding ascii character will be printed.
Loops
Start (jump to command after matching _
if the expression evaluates to zero):
@(numerical expression);
End (jump to command after matching @
if the expression does not evaluate to zero):
_(numerical expression);
The end can be _<0<;
to form an if statement.
Libraries
You can have libraries in Auphics. They are simple Auphics scripts, but variables beginning with libcom
(library communication) are shared between them.
By convention:
If a name starts with libcomi
it is an input.
If a name starts with libcomo
it is an output.
If a name starts with libcomg
it is a global.
Auphics libraries should have the relative path (from the directory containing the Auphics implementation) as follows:
auphlib/(namespace)/(script name).auph
To call a library, use:
||(namespace)||(script name)
Such as:
||numerics||factorial;
Multiple namespace levels can be included, they should each be a separate directory level, and have a separate ||
in the call.
Such as:
auphlib/kronosta/games/chess/pawn.auph ||kronosta||games||chess||pawn;
The form:
~[(a)].(b).(c)
is usable as an expression.
a:
A comma separated list of the forms:
#(tree expression)#(variable name)
b:
The lib path, with ||
replaced with |~
c: A variable name
Example:
~[#mytree#vara,#((:<1<)[<0<,<256<])#varb].|~kronosta|~create.out
It uses a to bind the trees to variable name with libcomi
prepended, then executes b, then returns the value of variable c with libcomo
prepended. The inputs, outputs, and any new globals created by the library are immediately unbound. Any globals that exist directly before the call will not be deleted, and can be modified by the library. Note that "new globals" refers to all new globals created by the library, not just the ones with a name starting with libcomg
.
Comments
NOTE (anything);
is a comment and will be ignored up until a semicolon.
Extensions
If you would like to implement extensions to the language, use either some action or operation on a variable with a name starting with auphx
, or as an operator or statement. If using an operator or statement, please start the name with ^
.
Examples
HELLO WORLD
Reads the spelling out loud.
!<28<;!<25<;!<32<;!<32<;!<35<;!<0<;!<43<;!<35<;!<38<;!<32<;!<24<;
Truth machine
Accepts an image as input. If the top left is nonzero, it is a 1, otherwise it is a zero. Says 0 or infinite 1's out loud.
truth = $$; nonzero = (:<1<)[<0<, (truth[<111111111111<]) / (truth[<111111111111<])]; @(nonzero[<0<]); !<8<; _(nonzero[<0<]); !<7<;