An esoteric programming language for when you're wanting to code with ducks. Jump to the sandbox and have some fun.
Notice
Quack Quack was an experiment developed a long, long, long time ago before going professional so both the interpreter & synax-highlighter source-code leave a lot to be desired.
The features on this page still work though, so have fun. I've tried to keep it as close to how it was when first developed.
To Do:
- Allow for more flexibility in syntax.
Reintroduce conditionals.conditionals reintroduced but interpreter needs work.- Loops.
- Proper comments (see proposal)
- Build syntax highlighter anew (it's a hacky mess) -- Needs redoing as incompatible with conditional statements.
Contents
How the ducks work
The ducks operate on ponds, when they quack they make ripples in the pond they're in, all these ripples stack up eventually and an output is formed.
Depending on which direction a duck is shouting the rippes will have different effects. To have full flexibility you will need to use ducks facing both directions.
@< ./ ./ ./
###
./ >@
###
@=
###
counts to 3, then takes 1, then stops the quacking.
Output: 2
Types of duck
There can be a variety of ducks on each pond, each type of duck performs a seperate task.
These examples are written in shorthand.
Loose Directional Ducks,
These ducks can face left or right:
@< Opens a new line facing right.
>@ Opens a new line facing left.
@= Saves the current ripple to the pond.
Fixed Directional Ducks,
These ducks must face given way:
0= Begins function definition
=0 Closes function definition
O= Calls defined function
Disembodied Ducks (shorthand)
When writing the code the ducks are not required to have bodies or feet, only the head of the duck performs any method. However it is best practice to keep your ducks bodied.
@< ./ ./ ./
./ >@
@=
counts to 3, then takes 1, then stops the quacking.
Output: 2
Quacks
Quacking allows you to manipulate and store the ripples (bit) on the pond, these are what make up your output.
The direction a duck is facing when it shouts out these quacks will have an effect on the action the quacks perform.
Basic names and descriptions:
./ --> bit (+1 or -1)
,/ --> dive (clone)
! --> dub (*2 or /2)
? --> poft (shift or pop)
* --> multi (multiply)
// --> divide (divide)
+ --> plus (addition)
- --> sub (subtraction)
% --> strint (toString or toNumber)
Right facing effects:
./ --> increase current bit by one.
,/ --> clone a stored bit down from right most of pond,
can be used multiple times to reach deeper bits.
! --> double the current bit.
? --> remove the stored bit on the left most side of the pond.
* --> multiply the current bit by the right most bit of the pond.
// --> divide the current bit by the right most bit of the pond.
+ --> add the current bit by the right most bit of the pond.
- --> add the current bit by the right most bit of the pond.
Left facing effects:
./ --> decrease current bit by one.
,/ --> clone a stored bit down from right most of pond,
can be used multiple times to reach deeper bits.
! --> half the current bit.
? --> remove the stored bit on the right most side of the pond.
* --> multiply the current bit by the left most bit of the pond.
// --> divide the current bit by the left most bit of the pond.
+ --> add the current bit by the left most bit of the pond.
- --> add the current bit by the left most bit of the pond.
Either facing effects
% --> flip the current bit between integer or alphanumeric.
Other Ponds (functions)
Your ducks are not restricted to one pond, if your ducks are having to shout the same quacks over and over then an function should be defined instead.
Functions are scoping and can be defined within other functions.
Functions can accept defined ripple stacks to work with (almost like arguments).
Defining
The function defining ducks are used: 0= and =0 act as brackets. 0= --> open
=0 --> close
A function requires a name, arguments are not listed.
0= namey
###
ducks go here
=0
###
Calling
The function call duck is used: O=
O= namey --> calls the above
###
Calling a function with defined ripples (arguments)
O= namey ** *1 *-2 10
###
Calls the function using:
the current bit,
the top most bit of the pond,
the 2nd bottom most bit of the pond &
the number 10 as a predefined stack of ripples for the function to use.
Conditionally Calling
The conditional function call duck is used: Q=
Q= ** === 5 ? namey --> calls namey if current bit is equal to 5
###
Q= ** === 5 ? namey byebye --> calls namey if current bit is equal to 5, or if not calls byebye instead (true / false)
###
Q= ** === 5 ? ** 5 *1 ? namey byebye --> this time a set of defined ripples is put in too (see below)
###
Calling With Arguments
Calling a function with defined ripples (arguments)
O= namey ** *1 *-2 10
###
Calls the function using:
the current bit,
the top most bit of the pond,
the 2nd bottom most bit of the pond &
the number 10 as a predefined stack of ripples for the function to use.
Nasty Bugs Features:
Unfortunately because the interpetter isn't quite up to scratch yet the following rules must be met by your layout:
- When defining functions at the root of the script (outside any functions) the definitions must be before any other code.
- When defining functions inside any functions the definitions must be after any other code (at the bottom of the function).
- When calling functions the pond from which it is being called must have at least 1 existing value in its stack. This can be easily removed after the function is called. The sandbox demonstrates this bug workaround.
Proposals
Comments
Comments will be placed as if the ducks are thinking.
. o O ( this is a comment )
=0 ( spanning multiple )
### ( lines )
``
( this is a comment )
( comments can be ) O o .
( different lengths ) O=
###
``
. o O ( the stem will indicate )
=0 ( which line the comment )
### ( relates to )
``
( Perhaps an empty headed )
( comment duck can be )
( used to use where a )
( comment is needed but no)
. o O( operation is required. )
=C
###
``
Sandbox
(joined) Output: