LayerCake
LayerCake is an infinite array of stacks which are used to store both data and executable code. LayerCake is dynamically typed. It is meant to be interpreted, although it does not yet have an interpreter.
History
I looked at esolangs.org and thought, "I wanna make one. I wanna have it force you to think differently about data, kind-of, somewhat, in-a-way like Brainfuck."
The only names I could think of sucked and were super generic ("Pancakes, Jenga") so don't tell anybody but I asked ChatGPT to name it for me. BUT IT'S OKAY CAUSE I HELD A POLL IN MY DISCORD GROUPCHAT and humans couldn't think of a better name either.
Specification
Static stacks (stacktic?)
Some stacks are always present. These are:
Param: The arguments passed to the program when it started. Arguments start from the top, including the name of the program. For example:
gcc -Wall -o my_program my_program.c
becomes,
Gcc
-Wall
-o
my_program
My_program.c
Stdin: Every time input is requested, the user becomes able to type in a string. When the user presses Enter, the string (without Enter) gets pushed onto the Stdin stack. In order to request input, push anything to this stack. For the programmer’s convenience, that push mysteriously vanishes without any manual fiddling involved.
Stdout: Every time this stack is pushed to, the interpreter prints it. Newlines must be deliberately specified.
Main: Stacks are both storage and code. See eval() later in the spec. It can be deleted, and that is the intended way to exit the program.
If it walks like a duck...
Everything is represented as a string internally. Math is done in the interpreter by converting strings to doubles, and bitwise operations are done by converting strings to longs. The LayerCake programmer never has to worry about parsing numeric strings or stringifying numbers, because the interpreter is magic.
Syntax
new (stackname)
Makes a new stack titled stackname.
del (stackname)
Deletes the stack called stackname.
lit (stackname, literal)
Pushes a constant to the top of the stack called stackname.
ptr (target, content)
Pushes whatever is at the top of stack content to whichever stack is pointed to by the top of stack target. For example:
dont | noob | hehe |
push | get | noob |
me | rekt | stak |
noob | targ | cont |
---|
Becomes this ⬇️ when ptr (targ, cont) is ran:
hehe | --- | --- |
dont | noob | hehe |
push | get | noob |
me | rekt | stak |
noob | targ | cont |
---|
The top of targ said ‘noob,’ which was a valid stack, so the top of cont was pushed to it.
len (stack1, stack2)
Pushes the length a.k.a. depth of stack1 onto stack2.
split (stack1, stack2)
Pushes every character of stack1 onto stack2, one by one. The first character of stack1 ends up on top.
sew (stack1, stack2)
Concatenates every entry of stack1, starting from the top, and pushes it onto stack2. If a stack looks as follows,
hamburger |
cheeseburger |
3.74 |
BigMacWHOPPER |
Stack1 |
---|
The string “hamburgercheeseburger3.74BigMacWHOPPER” is pushed to stack2.
eval (stackname)
Unconditionally evaluates an entire stack as if it were its own LayerCake program, starting from the bottom this time.
zeval (stack1, stack2)
Evaluates stack1 if the top of stack2 == 0.
pop (stackname)
Removes the top entry of stack stackname.
peek (stack1, n, stack2)
Pushes the nth entry of stack1 onto stack2, starting from the top.
speek (stack1, nstack, stack2)
The top of stack1 is fed to peek() as stack1, the top of nstack is fed in as n, and stack2 remains the same.
poke (stack1, n, literal)
Replaces the nth entry of stack1 with a literal, starting from the top.
spoke (stack1, nstack, stack2)
The top of stack1 is fed to poke() as stack1, the top of nstack is fed to poke as n, and the top of stack2 is fed to poke as literal.
add (stackname)
Pushes the sum of every entry in stackname to the top of it. Text and NaN are ignored.
mul (stackname)
Pushes the product of every entry in stackname to the top of it. Text and NaN are ignored.
recp (stackname)
Divides 1 by the top of stackname, and pushes the result on top. Text and NaN are skipped.
and (stackname)
ANDs together an entire stack, and pushes the result on top. Text and NaN are ignored, and doubles are rounded down.
or (stackname)
ORs together an entire stack, and pushes the result on top. Text and NaN are ignored, and doubles are rounded down.
xor (stack1, stack2)
Feeds the top of stack1 and the top of stack2 into an XOR gate, and pushes that to the top of stack2. Text and NaN are ignored, and doubles are rounded down.
nand (stack1, stack2)
Feeds the top of stack1 and the top of stack2 into a NAND gate, and pushes that to the top of stack2. Text and NaN are ignored, and doubles are rounded down.
not (stackname)
Bitwise inverts the top of a stack. Text and NaN are ignored, and doubles are rounded down.
Example programs
Truth.lc:
new(exit) lit(exit, “ptr(pt, cont)”) // stacks are alphabetical only lit(exit, “del(Main)”) new(pt) // ptr is a function lit(pt, “Stdout”) // i can use that name but i won’t new(cont) // out of order declarations lit(cont, “0”) // fully interpreted lol new(spam) lit(spam, “lit(cont, 1)”) // fyi you can push ‘numbers’ like this. same as “0”. lit(spam, “ptr(pt, cont)”) lit(spam, “eval(spam)”) lit(Stdin, “xd”) // request input zeval(exit, Stdin) // if input = 0, run exit eval(spam) // we’re still here so run spam instead
Fibonacci.lc:
// self explanatory⬇️ new(fib) lit(fib, 0) lit(fib, 1) // newlines do nothing // this will be passed into ptr() new(pt) // the way it's currently set up, it will say "235813213455..." lit(pt, “Stdout”) // programming challenge: add newlines so it's not all on one line new(loop) lit(loop, “add(fib)”) // add up all of fib lit(loop, “poke(fib, 2, 0)”) // make the 2nd number down 0 ptr(pt, fib) // push top of fib to stdout lit(loop, “eval(loop)”) // jump to itself eval(loop) // start fib