ActionLang

From Esolang
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++;}