UNPKG

js-forth

Version:

An implementation of [Forth](https://en.wikipedia.org/wiki/Forth_(programming_language)) in Javascript

156 lines (128 loc) 4.32 kB
var Long = require("long"); function Output(f) { f._output = ""; f.defjs("cr", function cr() { f._output += "\n"; }); f.defjs(".", function dot() { var value; var top = f.stack.pop(); if (typeof top === "undefined") value = "undefined"; else if (top === null) value = "null"; else value = top.toString(f._base()); // Output numbers in current base f._output += value + " "; }); f.defjs(".r", function dotR() { var value; var width = f.stack.pop(); var top = f.stack.pop(); if (typeof top === "undefined") value = "undefined"; else if (top === null) value = "null"; else value = top.toString(f._base()); // Output numbers in current base while (value.length < width) { value = " " + value; } f._output += value + " "; }); f.defjs("emit", function emit() { var value = f.stack.pop(); if (typeof value === "number") f._output += String.fromCharCode(value); else f._output += value; }); f.defjs("type", function type() { var length = f.stack.pop(); var address = f.stack.pop(); for (var i = 0; i < length; i++) { var value = f._getAddress(address + i); if (typeof value === "number") { f._output += String.fromCharCode(value); } else f._output += value; } }); // Numeric output var numericOutputStart = f.dataSpace.length; var numericOutput = ""; f.dataSpace.length += 128; f.defjs("<#", function initialiseNumericOutput() { numericOutput = ""; }); f.defjs("hold", function hold() { var value = f.stack.pop(); if (typeof value === "number") value = String.fromCharCode(value); numericOutput += value; }); f.defjs("#>", function finishNumericOutput() { f.stack.pop(); f.stack.pop(); for (var i = 0; i < numericOutput.length; i++) { f.dataSpace[numericOutputStart + i] = numericOutput[numericOutput.length - i - 1]; } f.stack.push(numericOutputStart); f.stack.push(numericOutput.length); }); f.defjs("sign", function sign() { if (f.stack.pop() < 0) numericOutput += "-"; }); f.defjs("#", function writeNextNumericOutput() { var bigPart = f.stack.pop(); var smallPart = f.stack.pop(); var value = new Long(smallPart, bigPart, true); var base = Long.fromInt(f._base()); numericOutput += value.mod(base).toString(base).toUpperCase(); value = value.div(base); f.stack.push(value.smallPart); f.stack.push(value.bigPart); }); f.defjs("#S", function writeAllNumericOutput() { var bigPart = f.stack.pop(); var smallPart = f.stack.pop(); var value = new Long(smallPart, bigPart, true); var base = Long.fromInt(f._base()); if (value.compare(Long.ZERO)) { while (value.compare(Long.ZERO)) { numericOutput += value.mod(base).toString(base).toUpperCase(); value = value.div(base); } } else { numericOutput += "0"; } f.stack.push(0); f.stack.push(0); }); f.defjs(">number", function toNumber() { var base = Long.fromInt(f._base()); var length = f.stack.pop(); var address = f.stack.pop(); var bigPart = f.stack.pop(); var smallPart = f.stack.pop(); var value = new Long(smallPart, bigPart, true); var unconverted = length; for (var i = 0; i < length; i++) { var next = parseInt(String.fromCharCode(f._getAddress(address)), base); if (isNaN(next)) { break; } else { address++; unconverted--; value = value.mul(base).add(Long.fromInt(next)); } } f.stack.push(value.low); f.stack.push(value.high); f.stack.push(address); f.stack.push(unconverted); }); return f; } module.exports = Output;