UNPKG

js-forth

Version:

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

116 lines (98 loc) 3.65 kB
var Forth = require("../kernel/forth.js"); function Repl() { var forth = Forth(); function loadForth(file) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { forth.run(xmlhttp.responseText, onForthOutput); } }; xmlhttp.open("GET", file, true); xmlhttp.send(); } loadForth("forth/forth.fth"); var inputHistory = [""]; var historyCount = 0; var historySelection = 0; function useHistory(selection) { var inputNode = document.getElementById("input"); if (inputNode.value !== inputHistory[historySelection]) { historySelection = historyCount - 1; inputHistory[historyCount] = inputNode.value; } else { historySelection = Math.min(Math.max(selection, 0), inputHistory.length - 1); } inputNode.value = inputHistory[historySelection]; inputNode.selectionStart = inputNode.value.length; } function updateHistory(input) { // Remove duplicates for (var i = inputHistory.length - 1; i >= 0; i--) { if (inputHistory[i] === input) { inputHistory.splice(i, 1); historyCount--; } } inputHistory[historyCount] = input; historyCount = inputHistory.length; historySelection = inputHistory.length; inputHistory.push(""); } function createReplNode(icon, text, className) { if (!text) return; var textNode = document.createElement("textarea"); textNode.className = className; textNode.readOnly = true; textNode.cols = 80; textNode.value = icon + " " + text; var replNode = document.createElement("div"); replNode.appendChild(textNode); var outputNode = document.getElementById("output"); outputNode.appendChild(replNode); setTimeout(function() { textNode.style.height = textNode.scrollHeight + "px"; outputNode.scrollTop = outputNode.scrollHeight - outputNode.clientHeight; }, 0); } function onForthOutput(error, output) { createReplNode("\u2190", output, "forth-output"); if (error) { createReplNode("X", error, "error"); } showStack(); } function runforth() { var inputNode = document.getElementById("input"); var input = inputNode.value.trim(); if (input) { updateHistory(input); createReplNode("\u2192", input, "user-output"); inputNode.value = ""; forth.run(input, onForthOutput); } } function showStack() { var stack = forth.stack; var stackNode = document.getElementById("stack"); // Clear stack while (stackNode.firstChild) stackNode.removeChild(stackNode.firstChild); for (var i = 1; i <= stack.length(); i++) { var element = document.createElement("span"); element.className = "stack-element"; element.textContent = String(stack.peek(i)); stackNode.appendChild(element); } } return { interpret: function(event) { if (event.keyCode == 13 && !event.shiftKey) runforth(); else if (event.keyCode == 80 && event.ctrlKey) useHistory(historySelection - 1); else if (event.keyCode == 78 && event.ctrlKey) useHistory(historySelection + 1); } }; } global.repl = Repl();