JSFiddle - React, Tailwind, and code Playground

by Conor O'Brien

HTML

<h1>Reng v.1.1</h1>
<h2>input</h2>
<textarea id="input"></textarea>
<button id=f>feed input</button>
<h2>code</h2>
<textarea id="code">
</textarea>
<button id=s>set code</button><button id=b>step</button><button id=r>run</button>(<input id=int value=500>ms delay)<button id=q>stop</button>
<div id="dispTable"></div>
<div id="stack"></div>
<hr>
<h2>output</h2>
<div id=o></div>

CSS

@import url(https://fonts.googleapis.com/css?family=Cousine:400,400italic,700,700italic);@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,700,700italic);html,button,input{font-family:"Open Sans",sans-serif;}table{border-collapse:collapse;}td{width:1em;height:1em;border:1px solid #888;padding:5px;text-align:center;}td.cur{background:#edaaaa;}textarea{width:100%;min-height:6em;}#int{width:6ch;}td,textarea,#stack,#o{font-family:"Cousine",monospace;}h1,h2{margin:0;}

JavaScript

/*

#x	push a token char x
=	pop a value N and a token X and sets X to N (redefine)
(...)	push a code block ... to the stack
0...Z	push 0...36
+-*%.	ops ifu (% division, . modulu)
a	print all of stack
e	value equality
g	greater than
l	less than
p	print
~	switch top two
$	drop
:	dup
?	pop N, skip the next char if N is 1
<>^v	directional pointers
|/\	mirrors

*/

function Reng(code){
  this.code = code.split("\n").map(function(e){return e.split("");});
  this.input = [];
  this.input.shift = function(){
  	var a = this[0];
    if(typeof a!=="undefined"){
    	this.splice(0,1);
      return a;
    } else return -1;
  }
  this.pos = {x:0,y:0};
  this.dir = {x:1,y:0};
  this.depth = 1;
  this.mode = 1;
  this.ops = {};
  for(i in Reng.ops){
  	this.ops[i] = Reng.ops[i];
  }
  this.running = true;
  this.buildFunc = "";
  this.parentStacks = [];
  this.stack = [];      // ugh another stack ;_;
  // popping off of empty stack yields 0
  this.stack.pop = function(){
  	var val = this[this.length-1];
    if(typeof val==="undefined") val = 0;
    else this.splice(-1,1);
    return val;
  }
  this.maxLen = this.code.reduce(function(x,y){return Math.max(y.length,x);},"");
  this.code = this.code.map(function(e){while(e.length<this.maxLen)e.push(" ");return e;}.bind(this));
}
Reng.dirChange = function(nx,ny){return function(R){R.dir={x:nx,y:ny}}}
Reng.nullary = function(f){return function(R){R.stack.push(f(R));}}
Reng.nullaryC = function(f){return function(R){R.stack=R.stack.concat(f(R,R.stack.pop()));}}
Reng.dropUse = function(f){return function(R){(f||function(){})(R,R.stack.pop());}}
Reng.binary = function(f){return function(R){var top=R.stack.pop(),sec=R.stack.pop();R.stack.push(f(R,sec,top));}}
Reng.constant = function(v){return function(R){R.stack.push(v);}}
Reng.mode = function(m){return function(R){R.mode=m;}}
Reng.ops = {
  ">":Reng.dirChange(1,0),
  "<":Reng.dirChange(-1,0),
  "^":Reng.dirChange(0,-1),
  "v":Reng.dirChange(0,1),
 ...