|
@@ -24,12 +24,12 @@ exit
|
|
#endif
|
|
#endif
|
|
#define var int
|
|
#define var int
|
|
#define function
|
|
#define function
|
|
-#define Null 0100000
|
|
|
|
|
|
+#define Null 16384
|
|
var M[Null * 2];
|
|
var M[Null * 2];
|
|
jmp_buf undefined;
|
|
jmp_buf undefined;
|
|
//`
|
|
//`
|
|
|
|
|
|
-var cx, dx, kT, kEq, kCar, kCdr, kCond, kAtom, kCons, kQuote, kDefine;
|
|
|
|
|
|
+var cx, dx, lo, kT, kEq, kCar, kCdr, kCond, kAtom, kCons, kQuote, kDefine;
|
|
|
|
|
|
function Set(i, x) {
|
|
function Set(i, x) {
|
|
M[Null + i] = x;
|
|
M[Null + i] = x;
|
|
@@ -58,6 +58,7 @@ function Cdr(x) {
|
|
function Cons(car, cdr) {
|
|
function Cons(car, cdr) {
|
|
Set(--cx, cdr);
|
|
Set(--cx, cdr);
|
|
Set(--cx, car);
|
|
Set(--cx, car);
|
|
|
|
+ if (cx < lo) lo = cx;
|
|
return cx;
|
|
return cx;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -137,17 +138,21 @@ function Read() {
|
|
return ReadObject(ReadAtom(0));
|
|
return ReadObject(ReadAtom(0));
|
|
}
|
|
}
|
|
|
|
|
|
-function Define(a) {
|
|
|
|
- var x = Read();
|
|
|
|
- return Cons(Cons(x, Read()), a);
|
|
|
|
|
|
+function Remove(x, y) {
|
|
|
|
+ if (!y) return y;
|
|
|
|
+ if (x == Car(Car(y))) return Cdr(y);
|
|
|
|
+ return Cons(Car(y), Remove(x, Cdr(y)));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function Define(x, y) {
|
|
|
|
+ return Cons(Cons(x, Read()), Remove(x, y));
|
|
}
|
|
}
|
|
|
|
|
|
function Gc(A, x) {
|
|
function Gc(A, x) {
|
|
var C, B = cx;
|
|
var C, B = cx;
|
|
x = Copy(x, A, A - B), C = cx;
|
|
x = Copy(x, A, A - B), C = cx;
|
|
while (C < B) Set(--A, Get(--B));
|
|
while (C < B) Set(--A, Get(--B));
|
|
- cx = A;
|
|
|
|
- return x;
|
|
|
|
|
|
+ return cx = A, x;
|
|
}
|
|
}
|
|
|
|
|
|
function Copy(x, m, k) {
|
|
function Copy(x, m, k) {
|
|
@@ -196,12 +201,8 @@ function Eval(e, a) {
|
|
if (!e) return e;
|
|
if (!e) return e;
|
|
if (e > 0) return Assoc(e, a);
|
|
if (e > 0) return Assoc(e, a);
|
|
if (Car(e) == kQuote) return Car(Cdr(e));
|
|
if (Car(e) == kQuote) return Car(Cdr(e));
|
|
- if (Car(e) == kCond) {
|
|
|
|
- e = Evcon(Cdr(e), a);
|
|
|
|
- } else {
|
|
|
|
- e = Apply(Car(e), Evlis(Cdr(e), a), a);
|
|
|
|
- }
|
|
|
|
- return Gc(A, e);
|
|
|
|
|
|
+ if (Car(e) == kCond) return Gc(A, Evcon(Cdr(e), a));
|
|
|
|
+ return Gc(A, Apply(Car(e), Evlis(Cdr(e), a), a));
|
|
}
|
|
}
|
|
|
|
|
|
function LoadBuiltins() {
|
|
function LoadBuiltins() {
|
|
@@ -233,6 +234,9 @@ PrintChar(b) {
|
|
fputwc(b, stdout);
|
|
fputwc(b, stdout);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+SaveMachine(a) {
|
|
|
|
+}
|
|
|
|
+
|
|
ReadChar() {
|
|
ReadChar() {
|
|
int b, c, t;
|
|
int b, c, t;
|
|
static char *freeme;
|
|
static char *freeme;
|
|
@@ -271,7 +275,8 @@ main() {
|
|
if (!(x = setjmp(undefined))) {
|
|
if (!(x = setjmp(undefined))) {
|
|
x = Read();
|
|
x = Read();
|
|
if (x == kDefine) {
|
|
if (x == kDefine) {
|
|
- a = Gc(A, Define(a));
|
|
|
|
|
|
+ a = Gc(0, Define(Read(), a));
|
|
|
|
+ SaveMachine(a);
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
x = Eval(x, a);
|
|
x = Eval(x, a);
|
|
@@ -289,8 +294,8 @@ main() {
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// JavaScript Specific Code for https://justine.lol/
|
|
// JavaScript Specific Code for https://justine.lol/
|
|
|
|
|
|
-var a, code, index, M, Null;
|
|
|
|
-var eInput, eOutput, eSubmit, eClear, eLoad, ePrograms;
|
|
|
|
|
|
+var a, code, index, output, M, Null;
|
|
|
|
+var eInput, eOutput, eSubmit, eReset, eLoad, ePrograms;
|
|
|
|
|
|
function Throw(x) {
|
|
function Throw(x) {
|
|
throw x;
|
|
throw x;
|
|
@@ -300,9 +305,22 @@ function Ord(s) {
|
|
return s.charCodeAt(0);
|
|
return s.charCodeAt(0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+function Reset() {
|
|
|
|
+ var i;
|
|
|
|
+ a = 0;
|
|
|
|
+ cx = 0;
|
|
|
|
+ lo = 0;
|
|
|
|
+ Null = 16384;
|
|
|
|
+ M = new Array(Null * 2);
|
|
|
|
+ for (i = 0; i < M.length; ++i) {
|
|
|
|
+ M[i] = 0; /* make json smaller */
|
|
|
|
+ }
|
|
|
|
+ Load("NIL T EQ CAR CDR ATOM COND CONS QUOTE DEFINE ");
|
|
|
|
+ LoadBuiltins()
|
|
|
|
+}
|
|
|
|
+
|
|
function PrintChar(c) {
|
|
function PrintChar(c) {
|
|
- eOutput.innerText += String.fromCharCode(c);
|
|
|
|
- SaveOutput();
|
|
|
|
|
|
+ output += String.fromCharCode(c);
|
|
}
|
|
}
|
|
|
|
|
|
function ReadChar() {
|
|
function ReadChar() {
|
|
@@ -323,6 +341,8 @@ function ReadChar() {
|
|
|
|
|
|
function Lisp() {
|
|
function Lisp() {
|
|
var x, A;
|
|
var x, A;
|
|
|
|
+ lo = cx;
|
|
|
|
+ output = '';
|
|
while (dx) {
|
|
while (dx) {
|
|
if (dx <= Ord(' ')) {
|
|
if (dx <= Ord(' ')) {
|
|
ReadChar();
|
|
ReadChar();
|
|
@@ -331,7 +351,7 @@ function Lisp() {
|
|
try {
|
|
try {
|
|
x = Read();
|
|
x = Read();
|
|
if (x == kDefine) {
|
|
if (x == kDefine) {
|
|
- a = Gc(A, Define(a));
|
|
|
|
|
|
+ a = Gc(0, Define(Read(), a));
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
x = Eval(x, a);
|
|
x = Eval(x, a);
|
|
@@ -343,6 +363,10 @@ function Lisp() {
|
|
Gc(A, 0);
|
|
Gc(A, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ eOutput.innerText = output;
|
|
|
|
+ SaveMachine(a);
|
|
|
|
+ SaveOutput();
|
|
|
|
+ ReportUsage();
|
|
}
|
|
}
|
|
|
|
|
|
function Load(s) {
|
|
function Load(s) {
|
|
@@ -352,13 +376,28 @@ function Load(s) {
|
|
}
|
|
}
|
|
|
|
|
|
function OnSubmit() {
|
|
function OnSubmit() {
|
|
- Load(eInput.value);
|
|
|
|
|
|
+ Load(eInput.value.toUpperCase());
|
|
Lisp();
|
|
Lisp();
|
|
}
|
|
}
|
|
|
|
|
|
-function OnClear() {
|
|
|
|
- eOutput.innerText = "";
|
|
|
|
|
|
+function Dump(a) {
|
|
|
|
+ if (!a) return;
|
|
|
|
+ Dump(Cdr(a));
|
|
|
|
+ output += "DEFINE ";
|
|
|
|
+ PrintObject(Car(Car(a)));
|
|
|
|
+ output += " ";
|
|
|
|
+ PrintObject(Cdr(Car(a)));
|
|
|
|
+ output += "\n";
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function OnReset() {
|
|
|
|
+ output = "";
|
|
|
|
+ Dump(a);
|
|
|
|
+ eOutput.innerText = output;
|
|
|
|
+ Reset();
|
|
|
|
+ localStorage.removeItem("sectorlisp.machine");
|
|
SaveOutput();
|
|
SaveOutput();
|
|
|
|
+ ReportUsage();
|
|
}
|
|
}
|
|
|
|
|
|
function OnLoad() {
|
|
function OnLoad() {
|
|
@@ -366,33 +405,65 @@ function OnLoad() {
|
|
}
|
|
}
|
|
|
|
|
|
function OnWindowClick(event) {
|
|
function OnWindowClick(event) {
|
|
- if (!event.target.matches('#load')) {
|
|
|
|
|
|
+ if (!event.target.matches("#load")) {
|
|
ePrograms.classList.remove("show");
|
|
ePrograms.classList.remove("show");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+function SaveMachine(a) {
|
|
|
|
+ var machine;
|
|
|
|
+ if (typeof localStorage != "undefined") {
|
|
|
|
+ machine = [M, a, cx];
|
|
|
|
+ localStorage.setItem("sectorlisp.machine", JSON.stringify(machine));
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function RestoreMachine() {
|
|
|
|
+ var machine;
|
|
|
|
+ if (typeof localStorage != "undefined" &&
|
|
|
|
+ (machine = JSON.parse(localStorage.getItem("sectorlisp.machine")))) {
|
|
|
|
+ M = machine[0];
|
|
|
|
+ a = machine[1];
|
|
|
|
+ cx = machine[2];
|
|
|
|
+ lo = cx;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
function SaveOutput() {
|
|
function SaveOutput() {
|
|
- if (typeof localStorage != 'undefined') {
|
|
|
|
- localStorage.setItem('output', eOutput.innerText);
|
|
|
|
|
|
+ if (typeof localStorage != "undefined") {
|
|
|
|
+ localStorage.setItem("input", document.getElementById("input").value);
|
|
|
|
+ localStorage.setItem("output", eOutput.innerText);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+function Number(i) {
|
|
|
|
+ return i.toLocaleString();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function ReportUsage() {
|
|
|
|
+ var i, c;
|
|
|
|
+ for (c = i = 0; i < Null; i += 2) {
|
|
|
|
+ if (Get(i)) ++c;
|
|
|
|
+ }
|
|
|
|
+ document.getElementById("usage").innerText =
|
|
|
|
+ Number((-cx >> 1) + c) + " / " +
|
|
|
|
+ Number((-lo >> 1) + c) + " / " +
|
|
|
|
+ Number(Null) + " doublewords";
|
|
|
|
+}
|
|
|
|
+
|
|
function SetUp() {
|
|
function SetUp() {
|
|
- a = 0;
|
|
|
|
- cx = 0;
|
|
|
|
- Null = 0100000;
|
|
|
|
- M = new Array(Null * 2);
|
|
|
|
- Load("NIL T EQ CAR CDR ATOM COND CONS QUOTE DEFINE ");
|
|
|
|
- LoadBuiltins()
|
|
|
|
- eLoad = document.getElementById('load');
|
|
|
|
- eInput = document.getElementById('input');
|
|
|
|
- eClear = document.getElementById('clear');
|
|
|
|
- eOutput = document.getElementById('output');
|
|
|
|
- eSubmit = document.getElementById('submit');
|
|
|
|
|
|
+ Reset();
|
|
|
|
+ RestoreMachine();
|
|
|
|
+ ReportUsage();
|
|
|
|
+ eLoad = document.getElementById("load");
|
|
|
|
+ eInput = document.getElementById("input");
|
|
|
|
+ eReset = document.getElementById("reset");
|
|
|
|
+ eOutput = document.getElementById("output");
|
|
|
|
+ eSubmit = document.getElementById("submit");
|
|
ePrograms = document.getElementById("programs");
|
|
ePrograms = document.getElementById("programs");
|
|
window.onclick = OnWindowClick;
|
|
window.onclick = OnWindowClick;
|
|
eSubmit.onclick = OnSubmit;
|
|
eSubmit.onclick = OnSubmit;
|
|
- eClear.onclick = OnClear;
|
|
|
|
|
|
+ eReset.onclick = OnReset;
|
|
eLoad.onclick = OnLoad;
|
|
eLoad.onclick = OnLoad;
|
|
}
|
|
}
|
|
|
|
|