All pastes #3892155 Raw Edit

TwoFiftyFive.js

public unlisted javascript v1 · immutable
#3892155 ·published 2017-10-19 23:19 UTC
rendered paste body
/*http://esolangs.org/wiki/TwoFiftyFiveUsage:new VM255("program", function(){input}, function(){output}).run();Example usage (Cat program):new VM255("FF02 FFFF FE*FA FA*FE FDFF FF*FC",function(){    var s=prompt("INPUT");    s=(s==null?"":s);    var out=new Array(s.length);    for(var i=0; i<out.length; i++)	out[i]=s.charCodeAt(i);    return out;},function(i){    document.body.innerText+=String.fromCharCode(i);}).run();*/class VM255{	//string, function, function	constructor(program, input, output)	{		this.ram=new Uint8Array(256);		this.stack=[];		this.prog=[]; //filled in lower		//must return an int[] when called		this.input=input;		this.inputBuffer=[];		//must accept a int and output it		this.output=output;		//special values		this.EOF=0x00;		this.IP=0xFF;		this.NAND_A=0xFE;		this.NAND_B=0xFD;		this.NAND_OUT=0xFC;		this.STACK_IO=0xFB;		this.STD_IO=0xFA;		this.RESERVED=[0xF9];		//fill in this.prog		let word="";		for(let c of program)		{			if("0123456789abcdef*".indexOf(c.toLowerCase())!=-1)			{				word+=c.toLowerCase();				//count the number of hex digits in word				let hexCount=0;				for(let h of word)					if("0123456789abcdef".indexOf(h)!=-1)						hexCount++;				if(hexCount==4)				{					//we have a word					//spilt it into bytes					let a="";					let b="";					if(word[0]=='*')					{						a=word.slice(0,3);						b=word.slice(3, word.length);					}					else					{						a=word.slice(0,2);						b=word.slice(2, word.length);					}					//translate them to bytes					let aByte;					let bByte;					if(a[0]=='*')						aByte=new VM255Byte(parseInt(a.slice(1,3),16),true);					else						aByte=new VM255Byte(parseInt(a,16));					if(b[0]=='*')						bByte=new VM255Byte(parseInt(b.slice(1,3),16),true);					else						bByte=new VM255Byte(parseInt(b,16));					//and into a byte pair					let pair=new VM255Word(aByte, bByte);					//put it in the program array					this.prog.push(pair);					if(this.prog.length>256)						throw "ROM Overflow Error";					//reset the word					word="";				}			}		}		if(word.length!=0)			throw "Extraneous Nibbles Error";	}	//RAM manip	getVal(p)	{		if(this.RESERVED.indexOf(p)!=-1)			console.warn("RAM("+p.toString(16).padStart(2, "0")+") is reserved for future extensions.");		switch(p)		{			case this.STACK_IO:				if(this.stack.length>0)					return this.stack.pop();				else					throw "Empty Stack Error";			case this.STD_IO:				//if input buffer is empty, refill it				if(this.inputBuffer.length==0)				{					this.inputBuffer=this.input();					this.inputBuffer.push(this.EOF);				}				return this.inputBuffer.shift();			default:				return this.ram[p];		}	}	setVal(v, p)	{		if(this.RESERVED.indexOf(p)!=-1)			console.warn("RAM("+p.toString(16).padStart(2, "0")+") is reserved for future extensions.");		switch(p)		{			case this.NAND_A:			case this.NAND_B:				this.ram[p]=v;				this.updateNAND();				break;			case this.NAND_OUT:				throw "Read Only Error: RAM("+p.toString(16).padStart(2, "0")+") is reserved for NAND Output, and is read only.";				break;//not needed, but it was bugging me			case this.STACK_IO:				this.stack.push(v);				break;			case this.STD_IO:				this.output(v);				break;			default:				this.ram[p]=v;						}	}	//IP Manip	getIP()	{		return this.getVal(this.IP);	}	setIP(p)	{		this.setVal(p, this.IP);	}	incIP()	{		this.setIP(this.getIP()+1);	}	//NAND gate	updateNAND()	{		this.ram[this.NAND_OUT]=+((this.getVal(this.NAND_A)==0)||(this.getVal(this.NAND_B)==0));		/*		//nand		var foo=~(this.getVal(this.NAND_A)&this.getVal(this.NAND_B));		//refit into 0-255		var bar=((foo%256)+256)%256;		this.ram[this.NAND_OUT]=bar;		*/	}	run()	{		this.ram[this.IP]=0;		while(this.getIP()<this.prog.length)		{			let word=this.prog[this.getIP()];			let val=word.b.getValue(this);			let dest=word.a.getValue(this);			this.setVal(val, dest);			if(dest!=this.IP)				this.incIP();		}	}	reset()	{		for(var i=0; i<256; i++)			this.ram[i]=0;	}}class VM255Byte{	constructor(value, isPointer)	{		//in case undefined		this.isPointer=!!isPointer;		this.setValue(value);	}	//functions	getValue(VM){		if(this.isPointer)			return VM.getVal(this.value);		else			return this.value;	};	setValue(newVal){		//set value, keeping in 0-255 range		this.value=((newVal%256)+256)%256;	};}class VM255Word{	//a and b are both bytes	constructor(a, b)	{		this.a=a;		this.b=b;	}}