ActionLang
Jump to navigation
Jump to search
ActionLang is a 2-dimensional esolang invented by User:None1.
Introduction
Though it is a 2-dimensional esolang, it's quite different from other 2-dimensional esolangs in these ways:
- It's commands are words, not characters.
- Every word can also store an integer.
- Like many 1D esolangs, the IP has only 1 direction: right.
Programs
Programs are lines of words (commands). Words in one line are separated by commas. Whitespaces except for line feeds are ignored. Every line must have the same number of commands. This esolang is sensitive.
Memory
- There's an integer stack, which is initially empty. Popping from an empty stack returns 0.
- All integers are unbounded and signed.
- Each command also has an integer, called return value. It's nothing initially. The return value of a command and the command itself are independent because the former is mutable (but can only be changed by returning), while the latter isn't. However, after a command finishes, it may return a value which will be stored in it's return value.
Commands
- input/read: Reads a(n) integer/character and pushes it (Unicode value for character) into stack. Returns the value read.
- output/write: Prints the stack top as integer/character and pops it, returns nothing.
- duplicate: Duplicate stack top, returns nothing.
- add/subtract/multiply/divide/modulus: Pop a. Pop b. Calculate b+a/b-a/b×a/b÷a/b%a. Pushes and returns the result.
- up/down/left/right: Find the closest non-nothing return value in that direction, pushes and returns it. If there's no such return value, returns and pushes nothing.
- jump: Pop a. Pop b. If a is nonzero, jumps to line b (1-indexed).
- number: Pushes that number into the stack and returns it.
- discard: Pop stack and discards the popped value.
- halt: Self-explanatory.
- nop: NOP.
Examples
Cat
read,write,1,1,jump
Truth Machine
1,input,nop duplicate,nop,output 2,up,jump
Hello, World!
72,write,101,write,108,write,left,write,111,write,44,write 32,write,87,write,111,write,114,write,108,write,100,write 33,write,10,write,nop,nop,nop,nop,nop,nop
Interpreter
With the "random" unofficial command: pushes a random number from [0,1e100).
Also, there are some aliases for commands. EOF returns -1.
//"只要你敢造,我就敢实现" (if you created, then I'll implement it.)
code=
[[],
['1','input','nop'],
['duplicate','nop','output'],
['2','up','jump'], //input code here
]
input='0' //input input here
h=1;l=0;stack=[];ip=0;R=q=>BigInt(Math.floor(Math.random()*q))
next=_=>ip>=input.length?-1n:BigInt(input.codePointAt(ip++));
q=function(){let c=0n,u=1n,z=next();while(z<48n||z>57n){if(z==45n)u=-u;z=next();}
while(z>=48n&&z<=57n){c=10n*c+z-48n;z=next();}ip--;return c*u;}
code=code.map(b=>b.map(c=>[c,null]));
while(h<code.length){switch(code[h][l][0]){
case'input':stack.push(code[h][l][1]=q());break;
case'output':process.stdout.write(''+stack.pop());code[h][l][1]=null;break;
case'read':
case'getchar':stack.push(code[h][l][1]=next());break;
case'write':
case'putchar':process.stdout.write(String.fromCodePoint(+(""+stack.pop())));code[h][l][1]=null;break;
case'jump':
case'jmp':C=stack.pop();L=stack.pop();if(C)h=L,l=-1;break;
case'nop':
case'APLWSI':break;
case'duplicate':
case'dup':stack.push(stack[stack.length-1]);code[h][l][1]=null;break;
case'halt':process.exit();
case'discard':stack.pop();code[h][l][1]=null;break; //I assume that discard don't store the value
case'discard-store':
case'dst':code[h][l][1]=stack.pop();break; //so I made up a command that stores it
case'add':C=stack.pop();stack.push(stack.pop()+C);break;
case'substract':
case'sub':C=stack.pop();stack.push(stack.pop()-C);break;
case'multiply':
case'mul':C=stack.pop();stack.push(stack.pop()*C);break;
case'divide':
case'div':C=stack.pop();stack.push(stack.pop()/C);break;
case'modulus':
case'modulo':
case'mod':C=stack.pop();stack.push(stack.pop()%C);break;
case'up':C=null;for(let j=h-1;j;j--)if(C===null)C=code[j][l][1];if(C!==null)stack.push(C);code[h][l][1]=C;break;
case'down':C=null;for(let j=h+1;j<code.length;j++)if(C===null)C=code[j][l][1];if(C!==null)stack.push(C);code[h][l][1]=C;break;
case'left':C=null;for(let j=l-1;j;j--)if(C===null)C=code[h][j][1];if(C!==null)stack.push(C);code[h][l][1]=C;break;
case'right':C=null;for(let j=l+1;j<code[h].length;j--)if(C===null)C=code[h][j][1];if(C!==null)stack.push(C);code[h][l][1]=C;break;
case'random':
case'rand':stack.push(code[h][l][1]=R(1e10)*10n**90n+R(1e15)*10n**75n+R(1e15)*10n**45n+R(1e15)*10n**60n+R(1e15)*10n**30n+R(1e15)*10n**15n+R(1e15));break;
default:stack.push(code[h][l][1]=+code[h][l][0]||(_=>{throw"invalid number"})())
}if(++l>=code[h].length)l=0,h++;}