retroforth/source/interfaces/alternates/retro12.html
crc af7454ee80 Build for 64bit with make clean; make CFLAGS="-O2 -DBIT64"
FossilOrigin-Name: d4fa66ba7fd57ca5095f4f6ac40bc8c20c948f6c8a52635a6156b3525f9703b3
2019-09-23 15:11:56 +00:00

610 lines
13 KiB
HTML

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>RETRO FORTH</title>
<style type="text/css">
*::-webkit-scrollbar {
width: 0.5em;
}
*::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
}
*::-webkit-scrollbar-thumb {
background-color: #333333;
outline: 1px solid slategrey;
}
body {
background: #212121;
color: #ababab;
font-size: 22pt;
font-family: monospace;
height:100%;
margin:0;
padding:0;
}
.left, .mid, .right {
float: left;
height: 100vp;
overflow: auto; overflow-x:hidden;
height:100%;
}
.left, .mid {
width: 40%;
}
.mid {
background: #1A1A1A;
}
.right {
width: 20%;
}
textarea, iframe {
width:100%;
height:100%;
box-sizing: border-box; /* For IE and modern versions of Chrome */
-moz-box-sizing: border-box; /* For Firefox */
-webkit-box-sizing: border-box; /* For Safari */
background: #212121;
color: #ababab;
font-size: 22pt;
border: 0px;
}
button {
background: #121212;
color: orange;
border: 1px solid orange;
font-size: 22pt;
}
</style>
<body onLoad='loadproject()'>
<div class='left'>
<textarea id='input' onchange='saveproject()'>
</textarea>
</div>
<div class='mid'>
<div style='float: right; margin-right: 10px;'>
<button onclick='cls()'>Clear</button>
<button onclick='go()'>Go</button>
</div>
<div>
<xmp id='console'>
</xmp>
</div>
</div>
<div class='right'>
<iframe src='http://forth.works:9999'></iframe>
</div>
</body>
<script>
/* Nga ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Copyright (c) 2008 - 2018, Charles Childers
Copyright (c) 2009 - 2010, Luke Parrish
Copyright (c) 2010, Marc Simpson
Copyright (c) 2010, Jay Skeer
Copyright (c) 2011, Kenneth Keating
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
var IMAGE_SIZE = 524288 * 4; /* Amount of simulated RAM */
var DATA_DEPTH = 8192; /* Depth of data stack */
var ADDRESS_DEPTH = 32768; /* Depth of the stacks */
function Stack(size) {
this.sp = 0;
this.data = new Array(size);
this.push = function(n) {
this.sp++;
this.data[this.sp] = n;
}
this.pop = function() {
return this.data[this.sp--];
}
this.depth = function() {
return this.sp;
}
this.tos = function() {
return this.data[this.sp];
}
this.nos = function() {
return this.data[this.sp - 1];
}
this.dup = function() {
this.push(this.tos());
}
this.drop = function() {
this.sp--;
}
this.swap = function() {
var a = this.nos();
this.data[this.sp - 1] = this.tos();
this.data[this.sp] = a;
}
this.inc = function() {
this.data[this.sp]++;
}
this.dec = function() {
this.data[this.sp]--;
}
this.reset = function() {
this.sp = 0;
}
}
function Opcodes() {
this.NOP = 0;
this.LIT = 1;
this.DUP = 2;
this.DROP = 3;
this.SWAP = 4;
this.PUSH = 5;
this.POP = 6;
this.JUMP = 7;
this.CALL = 8;
this.CCALL = 9;
this.RETURN = 10;
this.EQ = 11;
this.NEQ = 12;
this.LT = 13;
this.GT = 14;
this.FETCH = 15;
this.STORE = 16;
this.ADD = 17;
this.SUB = 18;
this.MUL = 19;
this.DIVMOD = 20;
this.AND = 21;
this.OR = 22;
this.XOR = 23;
this.SHIFT = 24;
this.ZERO_EXIT = 25;
this.END = 26;
this.IE = 27;
this.IQ = 28;
this.II = 29;
}
var ip = 0;
var data = new Stack(DATA_DEPTH);
var address = new Stack(ADDRESS_DEPTH);
var image = new Array(IMAGE_SIZE);
var vm = new Opcodes();
var instructions = new Array(vm.II + 1);
function rxPrepareVM() {
ip = 0;
data.reset();
address.reset();
}
instructions[vm.NOP] = function() {}
instructions[vm.LIT] = function() {
ip++;
data.push(image[ip]);
}
instructions[vm.DUP] = function() {
data.dup();
}
instructions[vm.DROP] = function() {
data.drop();
}
instructions[vm.SWAP] = function() {
data.swap();
}
instructions[vm.PUSH] = function() {
address.push(data.pop());
}
instructions[vm.POP] = function() {
data.push(address.pop())
}
instructions[vm.JUMP] = function() {
ip = data.pop() - 1;
}
instructions[vm.CALL] = function() {
address.push(ip);
ip = data.pop() - 1;
}
instructions[vm.CCALL] = function() {
var a, b;
a = data.pop();
b = data.pop();
if (b != 0) {
address.push(ip);
ip = a - 1;
}
}
instructions[vm.RETURN] = function() {
ip = address.pop();
}
instructions[vm.EQ] = function() {
var a, b;
a = data.pop();
b = data.pop();
if (b == a)
data.push(-1);
else
data.push(0);
}
instructions[vm.NEQ] = function() {
var a, b;
a = data.pop();
b = data.pop();
if (b != a)
data.push(-1);
else
data.push(0);
}
instructions[vm.LT] = function() {
var a, b;
a = data.pop();
b = data.pop();
if (b < a)
data.push(-1);
else
data.push(0);
}
instructions[vm.GT] = function() {
var a, b;
a = data.pop();
b = data.pop();
if (b > a)
data.push(-1);
else
data.push(0);
}
instructions[vm.FETCH] = function() {
x = data.pop();
if (x == -1)
data.push(data.sp);
else if (x == -2)
data.push(address.sp);
else if (x == -3)
data.push(IMAGE_SIZE);
else if (x == -4)
data.push(-2147483648);
else if (x == -5)
data.push(2147483647);
else
data.push(image[x]);
}
instructions[vm.STORE] = function() {
image[data.tos()] = data.nos();
data.drop();
data.drop();
}
instructions[vm.ADD] = function() {
var x = data.pop();
var y = data.pop();
data.push(x + y);
}
instructions[vm.SUB] = function() {
var x = data.pop();
var y = data.pop();
data.push(y - x);
}
instructions[vm.MUL] = function() {
var x = data.pop();
var y = data.pop();
data.push(y * x);
}
instructions[vm.DIVMOD] = function() {
var b = data.pop();
var a = data.pop();
if (b == 0) {
ip = 0;
data.sp = 0;
address.sp = 0;
} else {
var x = Math.abs(b);
var y = Math.abs(a);
var q = Math.floor(y / x);
var r = y % x;
if (a < 0 && b < 0)
r = r * -1;
if (a > 0 && b < 0)
q = q * -1;
if (a < 0 && b > 0) {
r = r * -1;
q = q * -1;
}
data.push(r);
data.push(q);
}
}
instructions[vm.AND] = function() {
var x = data.pop();
var y = data.pop();
data.push(x & y);
}
instructions[vm.OR] = function() {
var x = data.pop();
var y = data.pop();
data.push(x | y);
}
instructions[vm.XOR] = function() {
var x = data.pop();
var y = data.pop();
data.push(x ^ y);
}
instructions[vm.SHIFT] = function() {
var x = data.pop();
var y = data.pop();
if (x < 0)
data.push(y << (x * -1));
else
data.push(y >>= x);
}
instructions[vm.ZERO_EXIT] = function() {
if (data.tos() == 0) {
data.drop();
ip = address.pop();
}
}
instructions[vm.END] = function() {
ip = IMAGE_SIZE;
}
instructions[vm.IE] = function() {
data.push(1);
}
instructions[vm.IQ] = function() {
data.drop();
data.push(0);
data.push(0);
}
instructions[vm.II] = function() {
data.pop();
var s = String.fromCharCode(data.pop());
document.getElementById('console').innerHTML += s;
}
window.addEventListener('load', function(e) {
rxPrepareVM();
}, false);
function processOpcode(opcode) {
if (opcode != 0) {
instructions[opcode]();
checkStack();
}
}
function validatePackedOpcodes(opcode) {
var raw = opcode;
var current;
var valid = -1;
var i = 0;
while (i < 4) {
current = raw & 0xFF;
if (!current >= 0 && current <= 29)
valid = 0;
raw = raw >> 8;
i++;
}
}
function ngaProcessPackedOpcodes(opcode) {
var raw = opcode;
ops = new Array(3);
ops[0] = raw & (255);
raw = raw >> 8;
ops[1] = raw & (255);
raw = raw >> 8;
ops[2] = raw & (255);
raw = raw >> 8;
ops[3] = raw & (255);
processOpcode(ops[0]);
processOpcode(ops[1]);
processOpcode(ops[2]);
processOpcode(ops[3]);
}
var ngaImage = [
<<<IMAGE>>>
];
/* Nga - Retro - JavaScript Interface ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Copyright (c) 2008 - 2018, Charles Childers
Copyright (c) 2009 - 2010, Luke Parrish
Copyright (c) 2010, Marc Simpson
Copyright (c) 2010, Jay Skeer
Copyright (c) 2011, Kenneth Keating
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
function loadInitialImage() {
image = ngaImage.slice();
}
function execute(offset) {
var opcode;
address.sp = 1;
ip = offset;
var notfound = d_xt_for("err:notfound");
while (ip < IMAGE_SIZE) {
opcode = image[ip];
if (ip == notfound) {
document.getElementById('console').value +=
"err:notfound : " + string_extract(1471) + "\n";
}
if (validatePackedOpcodes(opcode) != 0) {
ngaProcessPackedOpcodes(opcode);
} else {
alert("Invalid instruction!");
alert("At " + ip + ", opcode " + opcode);
}
if (address.sp == 0)
ip = IMAGE_SIZE;
ip++;
}
}
function checkStack() {
var depth = data.depth();
var adepth = address.depth();
var flag = 0;
if (depth < 0 || adepth < 0) {
flag = -1;
}
if (depth > DATA_DEPTH || adepth > DATA_DEPTH) {
flag = -1;
}
if (flag == -1) {
ip = 0;
data.sp = 0;
address.sp = 0;
}
}
function string_inject(str, buffer) {
var m = str.length;
var i = 0;
while (m > 0) {
image[buffer + i] = str[i].charCodeAt(0);
image[buffer + i + 1] = 0;
m--;
i++;
}
}
function string_extract(at) {
string_data = "";
var starting = at;
var i = 0;
while (image[starting] != 0)
string_data += String.fromCharCode(image[starting++]);
return string_data;
}
function d_link(dt) {
return dt + 0;
}
function d_xt(dt) {
return dt + 1;
}
function d_class(dt) {
return dt + 2;
}
function d_name(dt) {
return dt + 3;
}
function d_count_entries() {
var c = 0;
var i = image[2];
while (image[i] != 0) {
c++;
i = image[i];
}
return c;
}
function d_lookup(name) {
var dt = 0;
var i = image[2];
var dname;
while (image[i] != 0 && i != 0) {
dname = string_extract(d_name(i));
if (dname == name) {
dt = i;
i = 0;
} else {
i = image[i];
}
}
return dt;
}
function d_xt_for(name) {
return image[d_xt(d_lookup(name))];
}
function d_class_for(name) {
return image[d_class(d_lookup(name))];
}
function evaluate(s) {
if (s.length == 0)
return;
var i = d_xt_for("interpret");
string_inject(s, 1471);
data.push(1471);
execute(i);
}
function cls() {
document.getElementById('console').innerHTML = "";
}
function unu(src) {
raw = src.split("\n");
var i = raw.length;
var lines = new Array();
var j = 0;
var code = 0;
while (j < i) {
if (code == 1 && raw[j] == "~~~") {
code = 0;
} else if (code == 0 && raw[j] == "~~~") {
code = 1;
} else if (code == 1) {
lines.push(raw[j]);
}
j++;
}
return lines.join(" ");
}
function go() {
rxPrepareVM();
loadInitialImage();
document.getElementById("console").innerHTML = "";
src = document.getElementById("input").value;
tokens = unu(src).match(/\S+/g);
var i = tokens.length;
var j = 0;
while (j < i) {
evaluate(tokens[j]);
j++;
}
s = "";
i = data.depth();
j = 1;
while (j <= i) {
s = s + data.data[j] + " ";
j++;
}
document.getElementById("console").innerHTML += "\n" + s;
}
function saveproject() {
src = document.getElementById("input").value;
console.log('saving ' + src);
localStorage.setItem("Snapshot", src);
}
function loadproject() {
src = localStorage.getItem("Snapshot");
document.getElementById("input").value = src;
}
</script>
</html>
<!--
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
-->