|
@@ -18,6 +18,7 @@ exit
|
|
|
//
`
|
|
|
#include "bestline.h"
|
|
|
#ifndef __COSMOPOLITAN__
|
|
|
+#include <assert.h>
|
|
|
#include <stdio.h>
|
|
|
#include <locale.h>
|
|
|
#include <setjmp.h>
|
|
@@ -30,9 +31,9 @@ var (*funcall)();
|
|
|
jmp_buf undefined;
|
|
|
//`
|
|
|
|
|
|
-var cx, dx, depth, panic;
|
|
|
-var cHeap, cGets, cSets, cPrints;
|
|
|
-var kT, kEq, kCar, kCdr, kCond, kAtom, kCons, kQuote, kDefine;
|
|
|
+var ax, cx, dx, depth, panic, fail;
|
|
|
+var cHeap, cGets, cSets, cReads, cPrints;
|
|
|
+var kEq, kCar, kCdr, kCond, kAtom, kCons, kQuote, kDefine;
|
|
|
|
|
|
function Get(i) {
|
|
|
++cGets;
|
|
@@ -61,52 +62,59 @@ function Cons(car, cdr) {
|
|
|
return cx;
|
|
|
}
|
|
|
|
|
|
-function Hash(h, c) {
|
|
|
- return h + c * 2;
|
|
|
+function Probe(h, p) {
|
|
|
+ return (h + p * p) & (Null / 2 - 1);
|
|
|
}
|
|
|
|
|
|
-function Intern(x, y, i) {
|
|
|
- i &= Null - 1;
|
|
|
- if (x == Get(i) && y == Get(i + 1)) return i;
|
|
|
- if (Get(i)) return Intern(x, y, i + 2);
|
|
|
- Set(i, x);
|
|
|
- Set(i + 1, y);
|
|
|
- return i;
|
|
|
+function Hash(h, x) {
|
|
|
+ return (((h + x) * 3083 + 3191) >> 4) & (Null / 2 - 1);
|
|
|
}
|
|
|
|
|
|
-function ReadAtom(h) {
|
|
|
- var c = ReadChar();
|
|
|
- if (c <= Ord(' ')) return ReadAtom(h);
|
|
|
- return Intern(c, c > Ord(')') && dx > Ord(')') ?
|
|
|
- ReadAtom(Hash(h, c)) : 0,
|
|
|
- Hash(h, c) - Hash(0, Ord('N')));
|
|
|
+function Intern(x, y, h, p) {
|
|
|
+ if (x == Get(h) && y == Get(h + Null / 2)) return h;
|
|
|
+ if (Get(h)) return Intern(x, y, Probe(h, p), p + 1);
|
|
|
+ Set(h, x);
|
|
|
+ Set(h + Null/2, y);
|
|
|
+ return h;
|
|
|
+}
|
|
|
+
|
|
|
+function ReadAtom() {
|
|
|
+ var x, y;
|
|
|
+ ax = y = 0;
|
|
|
+ do x = ReadChar();
|
|
|
+ while (x <= Ord(' '));
|
|
|
+ if (x > Ord(')') && dx > Ord(')')) y = ReadAtom();
|
|
|
+ return Intern(x, y, (ax = Hash(x, ax)), 1);
|
|
|
}
|
|
|
|
|
|
function ReadList() {
|
|
|
- var x;
|
|
|
+ var x, y;
|
|
|
if ((x = Read()) > 0) {
|
|
|
if (Get(x) == Ord(')')) return -0;
|
|
|
if (Get(x) == Ord('.') && !Get(x + 1)) {
|
|
|
x = Read();
|
|
|
- ReadList();
|
|
|
- return x;
|
|
|
+ y = ReadList();
|
|
|
+ if (!y) {
|
|
|
+ return x;
|
|
|
+ } else {
|
|
|
+ Throw(y);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
return Cons(x, ReadList());
|
|
|
}
|
|
|
|
|
|
-function ReadObject(t) {
|
|
|
+function Read() {
|
|
|
+ var t;
|
|
|
+ ++cReads;
|
|
|
+ t = ReadAtom();
|
|
|
if (Get(t) != Ord('(')) return t;
|
|
|
return ReadList();
|
|
|
}
|
|
|
|
|
|
-function Read() {
|
|
|
- return ReadObject(ReadAtom(0));
|
|
|
-}
|
|
|
-
|
|
|
function PrintAtom(x) {
|
|
|
do PrintChar(Get(x));
|
|
|
- while ((x = Get(x + 1)));
|
|
|
+ while ((x = Get(x + Null / 2)));
|
|
|
}
|
|
|
|
|
|
function PrintList(x) {
|
|
@@ -144,17 +152,7 @@ function Print(x) {
|
|
|
}
|
|
|
|
|
|
function List(x, y) {
|
|
|
- return Cons(x, Cons(y, 0));
|
|
|
-}
|
|
|
-
|
|
|
-function Define(A, x, a) {
|
|
|
- return Gc(A, Cons(x, Remove(Car(x), 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)));
|
|
|
+ return Cons(x, Cons(y, -0));
|
|
|
}
|
|
|
|
|
|
function Gc(A, x) {
|
|
@@ -164,6 +162,19 @@ function Gc(A, x) {
|
|
|
return cx = A, x;
|
|
|
}
|
|
|
|
|
|
+function Evcon(c, a) {
|
|
|
+ if (c >= 0) Throw(kCond);
|
|
|
+ if (Eval(Car(Car(c)), a)) {
|
|
|
+ return Eval(Car(Cdr(Car(c))), a);
|
|
|
+ } else {
|
|
|
+ return Evcon(Cdr(c), a);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function Peel(x, a) {
|
|
|
+ return a && x == Car(Car(a)) ? Cdr(a) : a;
|
|
|
+}
|
|
|
+
|
|
|
function Copy(x, m, k) {
|
|
|
return x < m ? Cons(Copy(Car(x), m, k),
|
|
|
Copy(Cdr(x), m, k)) + k : x;
|
|
@@ -176,33 +187,23 @@ function Evlis(m, a) {
|
|
|
|
|
|
function Pairlis(x, y, a) {
|
|
|
return x ? Cons(Cons(Car(x), Car(y)),
|
|
|
- Pairlis(Cdr(x), Cdr(y), a)) : a;
|
|
|
+ Pairlis(Cdr(x), Cdr(y),
|
|
|
+ Peel(Car(x), a))) : a;
|
|
|
}
|
|
|
|
|
|
function Assoc(x, y) {
|
|
|
- if (y >= 0) Throw(x);
|
|
|
- if (x == Car(Car(y))) return Cdr(Car(y));
|
|
|
- return Assoc(x, Cdr(y));
|
|
|
-}
|
|
|
-
|
|
|
-function Evcon(c, a) {
|
|
|
- if (Eval(Car(Car(c)), a)) {
|
|
|
- return Eval(Car(Cdr(Car(c))), a);
|
|
|
- } else if (Cdr(c)) {
|
|
|
- return Evcon(Cdr(c), a);
|
|
|
- } else {
|
|
|
- Throw(Cons(kCond, c));
|
|
|
- }
|
|
|
+ if (!y) Throw(x);
|
|
|
+ return x == Car(Car(y)) ? Cdr(Car(y)) : Assoc(x, Cdr(y));
|
|
|
}
|
|
|
|
|
|
function Apply(f, x, a) {
|
|
|
if (f < 0) return Eval(Car(Cdr(Cdr(f))), Pairlis(Car(Cdr(f)), x, a));
|
|
|
- if (f == kEq) return Car(x) == Car(Cdr(x)) ? kT : 0;
|
|
|
if (f == kCons) return Cons(Car(x), Car(Cdr(x)));
|
|
|
- if (f == kAtom) return Car(x) < 0 ? 0 : kT;
|
|
|
+ if (f == kEq) return Car(x) == Car(Cdr(x));
|
|
|
+ if (f == kAtom) return Car(x) >= 0;
|
|
|
if (f == kCar) return Car(Car(x));
|
|
|
if (f == kCdr) return Cdr(Car(x));
|
|
|
- return funcall(f, Assoc(f, a), x, a);
|
|
|
+ return funcall(cx, f, Assoc(f, a), x, a);
|
|
|
}
|
|
|
|
|
|
function Eval(e, a) {
|
|
@@ -213,19 +214,18 @@ function Eval(e, a) {
|
|
|
return Apply(Car(e), Evlis(Cdr(e), a), a);
|
|
|
}
|
|
|
|
|
|
-function Funcall(f, l, x, a) {
|
|
|
- var A = cx;
|
|
|
+function Funcall(A, f, l, x, a) {
|
|
|
return Gc(A, Apply(l, x, a));
|
|
|
}
|
|
|
|
|
|
-function Funtrace(f, l, x, a) {
|
|
|
- var y, i, A = cx;
|
|
|
+function Funtrace(A, f, l, x, a) {
|
|
|
+ var y;
|
|
|
Indent(depth);
|
|
|
Print(f);
|
|
|
Print(x);
|
|
|
PrintChar(Ord('\n'));
|
|
|
depth += 2;
|
|
|
- y = Funcall(f, l, x, a);
|
|
|
+ y = Funcall(cx, f, l, x, a);
|
|
|
depth -= 2;
|
|
|
Indent(depth);
|
|
|
Print(f);
|
|
@@ -245,9 +245,25 @@ function Indent(i) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-function Dump(a) {
|
|
|
+function DumpAlist(a) {
|
|
|
+ PrintChar(Ord('('));
|
|
|
+ PrintChar(Ord('\n'));
|
|
|
+ for (;a ;a = Cdr(a)) {
|
|
|
+ PrintChar(Ord('('));
|
|
|
+ Print(Car(Car(a)));
|
|
|
+ PrintChar(Ord(' '));
|
|
|
+ PrintChar(Ord('.'));
|
|
|
+ PrintChar(Ord(' '));
|
|
|
+ Print(Cdr(Car(a)));
|
|
|
+ PrintChar(Ord(')'));
|
|
|
+ PrintChar(Ord('\n'));
|
|
|
+ }
|
|
|
+ PrintChar(Ord(')'));
|
|
|
+}
|
|
|
+
|
|
|
+function DumpDefines(a) {
|
|
|
if (a) {
|
|
|
- Dump(Cdr(a));
|
|
|
+ DumpDefines(Cdr(a));
|
|
|
PrintChar(Ord('('));
|
|
|
Print(kDefine);
|
|
|
PrintChar(Ord(' '));
|
|
@@ -262,16 +278,47 @@ function Dump(a) {
|
|
|
}
|
|
|
|
|
|
function LoadBuiltins() {
|
|
|
- ReadAtom(0);
|
|
|
- kT = ReadAtom(0);
|
|
|
- kEq = ReadAtom(0);
|
|
|
- kCar = ReadAtom(0);
|
|
|
- kCdr = ReadAtom(0);
|
|
|
- kAtom = ReadAtom(0);
|
|
|
- kCond = ReadAtom(0);
|
|
|
- kCons = ReadAtom(0);
|
|
|
- kQuote = ReadAtom(0);
|
|
|
- kDefine = ReadAtom(0);
|
|
|
+ Read();
|
|
|
+ Read();
|
|
|
+ kEq = Read();
|
|
|
+ kCar = Read();
|
|
|
+ kCdr = Read();
|
|
|
+ kAtom = Read();
|
|
|
+ kCond = Read();
|
|
|
+ kCons = Read();
|
|
|
+ kQuote = Read();
|
|
|
+ kDefine = Read();
|
|
|
+}
|
|
|
+
|
|
|
+function Crunch(e, B) {
|
|
|
+ var x, y, i;
|
|
|
+ if (e >= 0) return e;
|
|
|
+ x = Crunch(Car(e), B);
|
|
|
+ y = Crunch(Cdr(e), B);
|
|
|
+ for (i = B - 2; i >= cx; i -= 2) {
|
|
|
+ if (x == Car(i) &&
|
|
|
+ y == Cdr(i)) {
|
|
|
+ return i - B;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return Cons(x, y) - B;
|
|
|
+}
|
|
|
+
|
|
|
+function Compact(x) {
|
|
|
+ var C, B = cx, A = 0;
|
|
|
+ x = Crunch(x, B), C = cx;
|
|
|
+ while (C < B) Set(--A, Get(--B));
|
|
|
+ return cx = A, x;
|
|
|
+}
|
|
|
+
|
|
|
+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, a) {
|
|
|
+ return Compact(Cons(x, Remove(Car(x), a)));
|
|
|
}
|
|
|
|
|
|
//
`
|
|
@@ -283,6 +330,7 @@ Ord(c) {
|
|
|
}
|
|
|
|
|
|
Throw(x) {
|
|
|
+ if (fail < 255) ++fail;
|
|
|
longjmp(undefined, ~x);
|
|
|
}
|
|
|
|
|
@@ -290,7 +338,7 @@ PrintChar(b) {
|
|
|
fputwc(b, stdout);
|
|
|
}
|
|
|
|
|
|
-SaveMachine(a) {
|
|
|
+SaveAlist(a) {
|
|
|
}
|
|
|
|
|
|
ReadChar() {
|
|
@@ -317,7 +365,7 @@ ReadChar() {
|
|
|
dx = c;
|
|
|
return t;
|
|
|
} else {
|
|
|
- exit(0);
|
|
|
+ exit(fail);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -344,8 +392,8 @@ main(argc, argv)
|
|
|
if (!(x = setjmp(undefined))) {
|
|
|
x = Read();
|
|
|
if (x < 0 && Car(x) == kDefine) {
|
|
|
- a = Define(0, Cdr(x), a);
|
|
|
- SaveMachine(a);
|
|
|
+ a = Define(Cdr(x), a);
|
|
|
+ SaveAlist(a);
|
|
|
continue;
|
|
|
}
|
|
|
x = Eval(x, a);
|
|
@@ -365,16 +413,13 @@ main(argc, argv)
|
|
|
// JavaScript Specific Code for https://justine.lol/
|
|
|
|
|
|
var a, code, index, output, funcall, M, Null;
|
|
|
-var eInput, eOutput, eEval, eReset, eLoad, eTrace, ePrograms;
|
|
|
+var eOutput, eEval, eReset, eLoad, eTrace, ePrograms, eDump;
|
|
|
+var eGets, eSets, eMs, eAtoms, eCode, eHeap, eReads, eWrites, eClear;
|
|
|
|
|
|
function Throw(x) {
|
|
|
throw x;
|
|
|
}
|
|
|
|
|
|
-function Ord(s) {
|
|
|
- return s.charCodeAt(0);
|
|
|
-}
|
|
|
-
|
|
|
function Reset() {
|
|
|
var i;
|
|
|
a = 0;
|
|
@@ -382,66 +427,116 @@ function Reset() {
|
|
|
cHeap = 0;
|
|
|
cGets = 0;
|
|
|
cSets = 0;
|
|
|
+ cReads = 0;
|
|
|
cPrints = 0;
|
|
|
Null = 16384;
|
|
|
M = new Array(Null * 2);
|
|
|
- for (i = 0; i < M.length; ++i) {
|
|
|
- M[i] = 0; /* make json smaller */
|
|
|
- }
|
|
|
+ // 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 PrintU16(c) {
|
|
|
output += String.fromCharCode(c);
|
|
|
}
|
|
|
|
|
|
+function IsHighSurrogate(c) {
|
|
|
+ return (0xfc00 & c) == 0xd800;
|
|
|
+}
|
|
|
+
|
|
|
+function IsLowSurrogate(c) {
|
|
|
+ return (0xfc00 & c) == 0xdc00;
|
|
|
+}
|
|
|
+
|
|
|
+function GetHighSurrogate(c) {
|
|
|
+ return ((c - 0x10000) >> 10) + 0xD800;
|
|
|
+}
|
|
|
+
|
|
|
+function GetLowSurrogate(c) {
|
|
|
+ return ((c - 0x10000) & 1023) + 0xDC00;
|
|
|
+}
|
|
|
+
|
|
|
+function ComposeUtf16(c, d) {
|
|
|
+ return ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000;
|
|
|
+}
|
|
|
+
|
|
|
+function PrintChar(c) {
|
|
|
+ if (c < 0x10000) {
|
|
|
+ PrintU16(c);
|
|
|
+ } else if (c < 0x110000) {
|
|
|
+ PrintU16(GetHighSurrogate(c));
|
|
|
+ PrintU16(GetLowSurrogate(c));
|
|
|
+ } else {
|
|
|
+ PrintU16(0xFFFD);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function Ord(s) {
|
|
|
+ var c, d;
|
|
|
+ c = s.charCodeAt(0);
|
|
|
+ if (IsHighSurrogate(c)) {
|
|
|
+ if (code.length > 1 && IsLowSurrogate((d = s.charCodeAt(1)))) {
|
|
|
+ c = ComposeUtf16(c, d);
|
|
|
+ } else {
|
|
|
+ c = 0xFFFD;
|
|
|
+ }
|
|
|
+ } else if (IsLowSurrogate(c)) {
|
|
|
+ c = 0xFFFD;
|
|
|
+ }
|
|
|
+ return c;
|
|
|
+}
|
|
|
+
|
|
|
function ReadChar() {
|
|
|
- var ax;
|
|
|
+ var c, d, t;
|
|
|
if (code.length) {
|
|
|
- ax = dx;
|
|
|
if (index < code.length) {
|
|
|
- dx = code.charCodeAt(index++);
|
|
|
+ c = code.charCodeAt(index++);
|
|
|
+ if (IsHighSurrogate(c)) {
|
|
|
+ if (index < code.length &&
|
|
|
+ IsLowSurrogate((d = code.charCodeAt(index)))) {
|
|
|
+ c = ComposeUtf16(c, d), ++index;
|
|
|
+ } else {
|
|
|
+ c = 0xFFFD;
|
|
|
+ }
|
|
|
+ } else if (IsLowSurrogate(c)) {
|
|
|
+ c = 0xFFFD;
|
|
|
+ }
|
|
|
} else {
|
|
|
code = "";
|
|
|
- dx = 0;
|
|
|
+ c = 0;
|
|
|
}
|
|
|
- return ax;
|
|
|
+ t = dx;
|
|
|
+ dx = c;
|
|
|
+ return t;
|
|
|
} else {
|
|
|
Throw(0);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-function GetMillis() {
|
|
|
- if (typeof performance != "undefined") {
|
|
|
- return performance.now();
|
|
|
- } else {
|
|
|
- return 0;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
function Lisp() {
|
|
|
var x, A, d, t;
|
|
|
d = 0;
|
|
|
cGets = 0;
|
|
|
cSets = 0;
|
|
|
cHeap = cx;
|
|
|
+ cReads = 0;
|
|
|
cPrints = 0;
|
|
|
output = "";
|
|
|
while (dx) {
|
|
|
if (dx <= Ord(' ')) {
|
|
|
ReadChar();
|
|
|
} else {
|
|
|
+ t = GetMillis();
|
|
|
A = cx;
|
|
|
try {
|
|
|
x = Read();
|
|
|
if (x < 0 && Car(x) == kDefine) {
|
|
|
- a = Define(0, Cdr(x), a);
|
|
|
+ a = Define(Cdr(x), a);
|
|
|
continue;
|
|
|
}
|
|
|
- t = GetMillis();
|
|
|
x = Eval(x, a);
|
|
|
- d += GetMillis() - t;
|
|
|
} catch (z) {
|
|
|
PrintChar(Ord('?'));
|
|
|
x = z;
|
|
@@ -449,45 +544,69 @@ function Lisp() {
|
|
|
Print(x);
|
|
|
PrintChar(Ord('\n'));
|
|
|
Gc(A, 0);
|
|
|
+ d += GetMillis() - t;
|
|
|
}
|
|
|
}
|
|
|
eOutput.innerText = output;
|
|
|
- SaveMachine(a);
|
|
|
+ SaveAlist(a);
|
|
|
SaveOutput();
|
|
|
ReportUsage(d);
|
|
|
}
|
|
|
|
|
|
function Load(s) {
|
|
|
+ index = 0;
|
|
|
+ dx = Ord(' ');
|
|
|
code = s + "\n";
|
|
|
- dx = Ord(s);
|
|
|
- index = 1;
|
|
|
}
|
|
|
|
|
|
function OnEval() {
|
|
|
- Load(eInput.value.toUpperCase());
|
|
|
+ Load(g_editor.getValue());
|
|
|
Lisp();
|
|
|
+ SetStorage("input", g_editor.getValue());
|
|
|
+}
|
|
|
+
|
|
|
+function OnBeforeUnload() {
|
|
|
+ SetStorage("input", g_editor.getValue());
|
|
|
+}
|
|
|
+
|
|
|
+function OnDump() {
|
|
|
+ var t;
|
|
|
+ output = "";
|
|
|
+ t = GetMillis();
|
|
|
+ DumpDefines(a);
|
|
|
+ eOutput.innerText = output;
|
|
|
+ t = GetMillis() - t;
|
|
|
+ SaveOutput();
|
|
|
+ ReportUsage(t);
|
|
|
}
|
|
|
|
|
|
-function OnReset() {
|
|
|
+function OnReset(e) {
|
|
|
var t;
|
|
|
output = "";
|
|
|
t = GetMillis();
|
|
|
try {
|
|
|
- Dump(a);
|
|
|
+ if (!e.shiftKey) DumpDefines(a);
|
|
|
eOutput.innerText = output;
|
|
|
Reset();
|
|
|
} catch (e) {
|
|
|
/* ignored */
|
|
|
}
|
|
|
t = GetMillis() - t;
|
|
|
- localStorage.removeItem("sectorlisp.machine");
|
|
|
+ RemoveStorage("alist");
|
|
|
SaveOutput();
|
|
|
ReportUsage(t);
|
|
|
}
|
|
|
|
|
|
+function OnClear() {
|
|
|
+ output = "";
|
|
|
+ eOutput.innerText = output;
|
|
|
+ SaveOutput();
|
|
|
+ ReportUsage(0);
|
|
|
+}
|
|
|
+
|
|
|
function OnTrace() {
|
|
|
var t;
|
|
|
- Load(eInput.value);
|
|
|
+ Load(g_editor.getValue());
|
|
|
t = panic;
|
|
|
depth = 0;
|
|
|
panic = 10000;
|
|
@@ -498,39 +617,54 @@ function OnTrace() {
|
|
|
}
|
|
|
|
|
|
function OnLoad() {
|
|
|
- ePrograms.classList.toggle("show");
|
|
|
+ if (ePrograms.className == "dropdown-content") {
|
|
|
+ ePrograms.className = "dropdown-content show";
|
|
|
+ } else {
|
|
|
+ ePrograms.className = "dropdown-content";
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-function OnWindowClick(event) {
|
|
|
- if (!event.target.matches("#load")) {
|
|
|
- ePrograms.classList.remove("show");
|
|
|
+function OnWindowClick(e) {
|
|
|
+ if (e.target && !e.target.matches("#load")) {
|
|
|
+ ePrograms.className = "dropdown-content";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-function SaveMachine(a) {
|
|
|
- var machine;
|
|
|
- if (typeof localStorage != "undefined") {
|
|
|
- machine = [M, a, cx];
|
|
|
- localStorage.setItem("sectorlisp.machine", JSON.stringify(machine));
|
|
|
+function OnWindowKeyDown(e) {
|
|
|
+ if (e.key == "Escape") {
|
|
|
+ ePrograms.className = "dropdown-content";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+function SaveAlist(a) {
|
|
|
+ output = "";
|
|
|
+ DumpAlist(a);
|
|
|
+ SetStorage("alist", output);
|
|
|
+}
|
|
|
+
|
|
|
function RestoreMachine() {
|
|
|
- var machine;
|
|
|
- if (typeof localStorage != "undefined" &&
|
|
|
- (machine = JSON.parse(localStorage.getItem("sectorlisp.machine")))) {
|
|
|
- M = machine[0];
|
|
|
- a = machine[1];
|
|
|
- cx = machine[2];
|
|
|
+ var v;
|
|
|
+ if ((v = GetStorage("output"))) {
|
|
|
+ eOutput.innerText = v;
|
|
|
+ }
|
|
|
+ if ((v = GetStorage("input"))) {
|
|
|
+ g_editor.setValue(v);
|
|
|
+ }
|
|
|
+ if ((v = GetStorage("alist"))) {
|
|
|
+ Reset();
|
|
|
+ Load(v);
|
|
|
+ a = Compact(Read());
|
|
|
+ } else if ((v = JSON.parse(GetStorage("machine")))) {
|
|
|
+ M = v[0];
|
|
|
+ a = v[1];
|
|
|
+ cx = v[2];
|
|
|
cHeap = cx;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function SaveOutput() {
|
|
|
- if (typeof localStorage != "undefined") {
|
|
|
- localStorage.setItem("input", document.getElementById("input").value);
|
|
|
- localStorage.setItem("output", eOutput.innerText);
|
|
|
- }
|
|
|
+ SetStorage("input", g_editor.getValue());
|
|
|
+ SetStorage("output", eOutput.innerText);
|
|
|
}
|
|
|
|
|
|
function FormatInt(i) {
|
|
@@ -541,19 +675,21 @@ function FormatDuration(d) {
|
|
|
return d ? Math.round(d * 1000) / 1000 : 0;
|
|
|
}
|
|
|
|
|
|
-function ReportUsage(d) {
|
|
|
- var i, c, s;
|
|
|
- for (c = i = 0; i < Null; i += 2) {
|
|
|
- if (M[Null + i]) ++c;
|
|
|
+function ReportUsage(ms) {
|
|
|
+ var i, atom, code, heap;
|
|
|
+ code = -cx >> 1;
|
|
|
+ heap = -cHeap >> 1;
|
|
|
+ for (atom = i = 0; i < Null / 2; ++i) {
|
|
|
+ if (M[Null + i]) ++atom;
|
|
|
}
|
|
|
- document.getElementById("ops").innerText =
|
|
|
- FormatInt(cGets) + " gets / " +
|
|
|
- FormatInt(cSets) + " sets / " +
|
|
|
- FormatDuration(d) + " ms";
|
|
|
- document.getElementById("mem").innerText =
|
|
|
- FormatInt((-cx >> 1) + c) + " / " +
|
|
|
- FormatInt((-cHeap >> 1) + c) + " / " +
|
|
|
- FormatInt(Null) + " doublewords";
|
|
|
+ if (eGets) eGets.innerText = FormatInt(cGets);
|
|
|
+ if (eSets) eSets.innerText = FormatInt(cSets);
|
|
|
+ if (eMs) eMs.innerText = FormatInt(ms);
|
|
|
+ if (eAtoms) eAtoms.innerText = FormatInt(atom);
|
|
|
+ if (eCode) eCode.innerText = FormatInt(code);
|
|
|
+ if (eHeap) eHeap.innerText = FormatInt(heap - code);
|
|
|
+ if (eReads) eReads.innerText = FormatInt(cReads);
|
|
|
+ if (ePrints) ePrints.innerText = FormatInt(cPrints);
|
|
|
}
|
|
|
|
|
|
function Discount(f) {
|
|
@@ -570,30 +706,66 @@ function Discount(f) {
|
|
|
};
|
|
|
}
|
|
|
|
|
|
+function GetMillis() {
|
|
|
+ if (typeof performance != "undefined") {
|
|
|
+ return performance.now();
|
|
|
+ } else {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function GetStorage(k) {
|
|
|
+ if (typeof localStorage != "undefined") {
|
|
|
+ return localStorage.getItem(g_lisp + "." + k);
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function RemoveStorage(k) {
|
|
|
+ if (typeof localStorage != "undefined") {
|
|
|
+ localStorage.removeItem(g_lisp + "." + k);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function SetStorage(k, v) {
|
|
|
+ if (typeof localStorage != "undefined") {
|
|
|
+ localStorage.setItem(g_lisp + "." + k, v);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
function SetUp() {
|
|
|
funcall = Funcall;
|
|
|
Read = Discount(Read);
|
|
|
Print = Discount(Print);
|
|
|
Define = Discount(Define);
|
|
|
eLoad = document.getElementById("load");
|
|
|
- eInput = document.getElementById("input");
|
|
|
eReset = document.getElementById("reset");
|
|
|
eTrace = document.getElementById("trace");
|
|
|
eOutput = document.getElementById("output");
|
|
|
eEval = document.getElementById("eval");
|
|
|
+ eClear = document.getElementById("clear");
|
|
|
+ eDump = document.getElementById("dump");
|
|
|
ePrograms = document.getElementById("programs");
|
|
|
- window.onclick = OnWindowClick;
|
|
|
- eLoad.onclick = OnLoad;
|
|
|
- eReset.onclick = OnReset;
|
|
|
- eTrace.onclick = OnTrace;
|
|
|
- eEval.onclick = OnEval;
|
|
|
- Reset();
|
|
|
- RestoreMachine();
|
|
|
- ReportUsage();
|
|
|
+ eGets = document.getElementById("cGets");
|
|
|
+ eSets = document.getElementById("cSets");
|
|
|
+ eMs = document.getElementById("cMs");
|
|
|
+ eAtoms = document.getElementById("cAtoms");
|
|
|
+ eCode = document.getElementById("cCode");
|
|
|
+ eHeap = document.getElementById("cHeap");
|
|
|
+ eReads = document.getElementById("cReads");
|
|
|
+ ePrints = document.getElementById("cPrints");
|
|
|
+ window.onkeydown = OnWindowKeyDown;
|
|
|
+ if (window.onbeforeunload) window.onbeforeunload = OnBeforeUnload;
|
|
|
+ if (ePrograms) window.onclick = OnWindowClick;
|
|
|
+ if (eLoad) eLoad.onclick = OnLoad;
|
|
|
+ if (eReset) eReset.onclick = OnReset;
|
|
|
+ if (eTrace) eTrace.onclick = OnTrace;
|
|
|
+ if (eEval) eEval.onclick = OnEval;
|
|
|
+ if (eDump) eDump.onclick = OnDump;
|
|
|
+ if (eClear) eClear.onclick = OnClear;
|
|
|
}
|
|
|
|
|
|
-SetUp();
|
|
|
-
|
|
|
//
`
|
|
|
#endif
|
|
|
//`
|