lisp.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. /*bin/echo '#-*- indent-tabs-mode:nil;js-indent-level:2;coding:utf-8 -*-
  2. SectorLISP v2.o (ISC License)
  3. Copyright 2021 Justine Tunney
  4. This file implements SectorLISP as a C / JavaScript polyglot and
  5. includes friendly branch features such as the undefined behavior
  6. exceptions handlers, optimized interning, and global definitions
  7. (aset standard-display-table #x2029 [?¶]) ;; emacs protip '>/dev/null
  8. curl -so bestline.c -z bestline.c https://justine.lol/sectorlisp2/bestline.c
  9. curl -so bestline.h -z bestline.h https://justine.lol/sectorlisp2/bestline.h
  10. [ lisp.js -nt lisp ] && cc -w -xc lisp.js bestline.c -o lisp
  11. exec ./lisp "$@"
  12. exit
  13. */
  14. //
`
  15. #include "bestline.h"
  16. #ifndef __COSMOPOLITAN__
  17. #include <assert.h>
  18. #include <stdio.h>
  19. #include <locale.h>
  20. #include <setjmp.h>
  21. #endif
  22. #define var int
  23. #define function
  24. #define Null 01000000
  25. var M[Null * 2];
  26. var (*funcall)();
  27. jmp_buf undefined;
  28. //`
  29. var ax, cx, dx, depth, panic, fail;
  30. var cHeap, cGets, cSets, cReads, cPrints;
  31. var kEq, kCar, kCdr, kCond, kAtom, kCons, kQuote, kDefine;
  32. function Get(i) {
  33. ++cGets;
  34. return M[Null + i];
  35. }
  36. function Set(i, x) {
  37. ++cSets;
  38. M[Null + i] = x;
  39. }
  40. function Car(x) {
  41. if (x > 0) Throw(List(kCar, x));
  42. return x ? Get(x) : +0;
  43. }
  44. function Cdr(x) {
  45. if (x > 0) Throw(List(kCdr, x));
  46. return x ? Get(x + 1) : -0;
  47. }
  48. function Cons(car, cdr) {
  49. if (cx == -Null) Throw(kCons);
  50. Set(--cx, cdr);
  51. Set(--cx, car);
  52. if (cx < cHeap) cHeap = cx;
  53. return cx;
  54. }
  55. function Probe(h, p) {
  56. return (h + p * p) & (Null / 2 - 1);
  57. }
  58. function Hash(h, x) {
  59. return ((h + x) * 60611 + 20485) & (Null / 2 - 1);
  60. }
  61. function Intern(x, y, h, p) {
  62. if (x == Get(h) && y == Get(h + Null / 2)) return h;
  63. if (Get(h)) return Intern(x, y, Probe(h, p), p + 1);
  64. Set(h, x);
  65. Set(h + Null/2, y);
  66. return h;
  67. }
  68. function ReadAtom() {
  69. var x, y;
  70. ax = y = 0;
  71. do x = ReadChar();
  72. while (x <= Ord(' '));
  73. if (x > Ord(')') && dx > Ord(')')) y = ReadAtom();
  74. return Intern(x, y, (ax = Hash(x, ax)), 1);
  75. }
  76. function ReadList() {
  77. var x, y;
  78. if ((x = Read()) > 0) {
  79. if (Get(x) == Ord(')')) return -0;
  80. if (Get(x) == Ord('.') && !Get(x + 1)) {
  81. x = Read();
  82. y = ReadList();
  83. if (!y) {
  84. return x;
  85. } else {
  86. Throw(y);
  87. }
  88. }
  89. }
  90. return Cons(x, ReadList());
  91. }
  92. function Read() {
  93. var t;
  94. ++cReads;
  95. t = ReadAtom();
  96. if (Get(t) != Ord('(')) return t;
  97. return ReadList();
  98. }
  99. function PrintAtom(x) {
  100. do PrintChar(Get(x));
  101. while ((x = Get(x + Null / 2)));
  102. }
  103. function PrintList(x) {
  104. PrintChar(Ord('('));
  105. if (x < 0) {
  106. Print(Car(x));
  107. while ((x = Cdr(x))) {
  108. if (panic && cPrints > panic) {
  109. PrintChar(Ord(' '));
  110. PrintChar(0x2026);
  111. break;
  112. }
  113. if (x < 0) {
  114. PrintChar(Ord(' '));
  115. Print(Car(x));
  116. } else {
  117. PrintChar(Ord(' '));
  118. PrintChar(Ord('.'));
  119. PrintChar(Ord(' '));
  120. Print(x);
  121. break;
  122. }
  123. }
  124. }
  125. PrintChar(Ord(')'));
  126. }
  127. function Print(x) {
  128. ++cPrints;
  129. if (1./x < 0) {
  130. PrintList(x);
  131. } else {
  132. PrintAtom(x);
  133. }
  134. }
  135. function List(x, y) {
  136. return Cons(x, Cons(y, -0));
  137. }
  138. function Evcon(c, a, t) {
  139. if (c >= 0) Throw(kCond);
  140. if (Eval(Car(Car(c)), a)) {
  141. return Apply(Car(Cdr(Car(c))), a, t);
  142. } else {
  143. return Evcon(Cdr(c), a, t);
  144. }
  145. }
  146. function Assoc(x, y) {
  147. var c, p;
  148. for (c = 3; y < 0; y = M[Null + y + 1], c += 3) {
  149. if (x == M[Null + M[Null + y]]) {
  150. cGets += c;
  151. return M[Null + M[Null + y] + 1];
  152. }
  153. }
  154. Throw(x);
  155. }
  156. function Bind(x, y, u, a) {
  157. while (x) {
  158. a = Cons(Cons(Car(x), Arg1(y, u)), a);
  159. x = Cdr(x);
  160. y = Cdr(y);
  161. }
  162. return a;
  163. }
  164. function Gc(A, x) {
  165. var C, B = cx;
  166. x = Copy(x, A, A - B), C = cx;
  167. while (C < B) Set(--A, Get(--B));
  168. return cx = A, x;
  169. }
  170. function Copy(x, m, k) {
  171. var r, y, z;
  172. if (x >= m) return x;
  173. r = (y = Cons(Copy(Car(x), m, k), 0)) + k;
  174. for (;;) {
  175. if ((x = Cdr(x)) < m) {
  176. z = Cons(Copy(Car(x), m, k), 0);
  177. Set(y + 1, z + k);
  178. y = z;
  179. } else {
  180. Set(y + 1, x);
  181. break;
  182. }
  183. }
  184. return r;
  185. }
  186. function Evlam(e, a, t, f, x) {
  187. var b, p, u, A;
  188. p = Car(Cdr(f));
  189. b = Car(Cdr(Cdr(f)));
  190. for (A = cx, u = a;;) {
  191. u = Bind(p, x, u, a);
  192. x = funcall(b, u, t, a);
  193. if (x < 0 && Car(x) == t) {
  194. x = Gc(A, Cons(u, Cdr(x)));
  195. u = Car(x);
  196. x = Cdr(x);
  197. } else {
  198. return Gc(A, Eval(x, u));
  199. }
  200. }
  201. }
  202. function Apply(e, a, t) {
  203. if (!e) return e;
  204. if (e > 0) return t ? e : Assoc(e, a);
  205. return Evfun(e, a, t, Car(e), Cdr(e));
  206. }
  207. function Evfun(e, a, t, f, x) {
  208. if (f == kCond) return Evcon(x, a, t);
  209. if (t) return e;
  210. if (f == kQuote) return Car(x);
  211. if (f == kCons) return Cons(Arg1(x, a), Arg2(x, a));
  212. if (f == kEq) return Arg1(x, a) == Arg2(x, a);
  213. if (f == kAtom) return Arg1(x, a) >= 0;
  214. if (f == kCar) return Car(Arg1(x, a));
  215. if (f == kCdr) return Cdr(Arg1(x, a));
  216. return Evlam(e, a, f, f > 0 ? Assoc(f, a) : f, x);
  217. }
  218. function Arg1(x, a) {
  219. return Eval(Car(x), a);
  220. }
  221. function Arg2(x, a) {
  222. return Arg1(Cdr(x), a);
  223. }
  224. function Eval(e, a) {
  225. return Apply(e, a, 0);
  226. }
  227. function Trace(b, u, t, a) {
  228. var i, y;
  229. if (t > 0) {
  230. Indent(depth);
  231. PrintChar(Ord('('));
  232. Print(t);
  233. for (i = u; i != a; i = Cdr(i)) {
  234. PrintChar(Ord(' '));
  235. Print(Cdr(Car(i)));
  236. }
  237. PrintChar(Ord(')'));
  238. PrintChar(Ord('\r'));
  239. PrintChar(Ord('\n'));
  240. depth += 2;
  241. }
  242. y = Apply(b, u, t);
  243. if (t > 0) {
  244. depth -= 2;
  245. Indent(depth);
  246. Print(t);
  247. PrintChar(Ord(' '));
  248. PrintChar(0x2192);
  249. PrintChar(Ord(' '));
  250. Print(y);
  251. PrintChar(Ord('\r'));
  252. PrintChar(Ord('\n'));
  253. }
  254. return y;
  255. }
  256. function Indent(i) {
  257. for (; i; --i) {
  258. PrintChar(Ord(' '));
  259. }
  260. }
  261. function DumpAlist(a) {
  262. PrintChar(Ord('('));
  263. PrintChar(Ord('\n'));
  264. for (;a ;a = Cdr(a)) {
  265. PrintChar(Ord('('));
  266. Print(Car(Car(a)));
  267. PrintChar(Ord(' '));
  268. PrintChar(Ord('.'));
  269. PrintChar(Ord(' '));
  270. Print(Cdr(Car(a)));
  271. PrintChar(Ord(')'));
  272. PrintChar(Ord('\n'));
  273. }
  274. PrintChar(Ord(')'));
  275. }
  276. function DumpDefines(a) {
  277. if (a) {
  278. DumpDefines(Cdr(a));
  279. PrintChar(Ord('('));
  280. Print(kDefine);
  281. PrintChar(Ord(' '));
  282. Print(Car(Car(a)));
  283. PrintChar(Ord(' '));
  284. PrintChar(Ord('.'));
  285. PrintChar(Ord(' '));
  286. Print(Cdr(Car(a)));
  287. PrintChar(Ord(')'));
  288. PrintChar(Ord('\n'));
  289. }
  290. }
  291. function LoadBuiltins() {
  292. Read();
  293. Read();
  294. kEq = Read();
  295. kCar = Read();
  296. kCdr = Read();
  297. kAtom = Read();
  298. kCond = Read();
  299. kCons = Read();
  300. kQuote = Read();
  301. kDefine = Read();
  302. }
  303. function Crunch(e, B) {
  304. var x, y, i;
  305. if (e >= 0) return e;
  306. x = Crunch(Car(e), B);
  307. y = Crunch(Cdr(e), B);
  308. for (i = B - 2; i >= cx; i -= 2) {
  309. if (x == Car(i) &&
  310. y == Cdr(i)) {
  311. return i - B;
  312. }
  313. }
  314. return Cons(x, y) - B;
  315. }
  316. function Compact(x) {
  317. var C, B = cx, A = 0;
  318. x = Crunch(x, B), C = cx;
  319. while (C < B) Set(--A, Get(--B));
  320. return cx = A, x;
  321. }
  322. function Remove(x, y) {
  323. if (!y) return y;
  324. if (x == Car(Car(y))) return Cdr(y);
  325. return Cons(Car(y), Remove(x, Cdr(y)));
  326. }
  327. function Define(x, a) {
  328. return Compact(Cons(x, Remove(Car(x), a)));
  329. }
  330. //
`
  331. ////////////////////////////////////////////////////////////////////////////////
  332. // ANSI POSIX C Specific Code
  333. Ord(c) {
  334. return c;
  335. }
  336. Throw(x) {
  337. if (fail < 255) ++fail;
  338. longjmp(undefined, ~x);
  339. }
  340. PrintChar(b) {
  341. fputwc(b, stdout);
  342. }
  343. SaveAlist(a) {
  344. }
  345. ReadChar() {
  346. int b, c, t;
  347. static char *freeme;
  348. static char *line = "NIL T EQ CAR CDR ATOM COND CONS QUOTE DEFINE ";
  349. if (line || (line = freeme = bestlineWithHistory("* ", "sectorlisp"))) {
  350. if (*line) {
  351. c = *line++ & 0377;
  352. if (c >= 0300) {
  353. for (b = 0200; c & b; b >>= 1) c ^= b;
  354. while ((*line & 0300) == 0200) {
  355. c <<= 6;
  356. c |= *line++ & 0177;
  357. }
  358. }
  359. } else {
  360. free(freeme);
  361. freeme = 0;
  362. line = 0;
  363. c = '\n';
  364. }
  365. t = dx;
  366. dx = c;
  367. return t;
  368. } else {
  369. exit(fail);
  370. }
  371. }
  372. main(argc, argv)
  373. char *argv[];
  374. {
  375. var x, a, A;
  376. setlocale(LC_ALL, "");
  377. bestlineSetXlatCallback(bestlineUppercase);
  378. funcall = Apply;
  379. for (x = 1; x < argc; ++x) {
  380. if (argv[x][0] == '-' && argv[x][1] == 't') {
  381. funcall = Trace;
  382. } else {
  383. fputs("Usage: ", stderr);
  384. fputs(argv[0], stderr);
  385. fputs(" [-t] <input.lisp >errput.lisp\n", stderr);
  386. exit(1);
  387. }
  388. }
  389. LoadBuiltins();
  390. for (a = 0;;) {
  391. A = cx;
  392. if (!(x = setjmp(undefined))) {
  393. x = Read();
  394. if (x < 0 && Car(x) == kDefine) {
  395. a = Define(Cdr(x), a);
  396. SaveAlist(a);
  397. continue;
  398. }
  399. x = Eval(x, a, 0);
  400. } else {
  401. x = ~x;
  402. PrintChar('?');
  403. }
  404. Print(x);
  405. PrintChar('\n');
  406. Gc(A, 0);
  407. }
  408. }
  409. #if 0
  410. //`
  411. ////////////////////////////////////////////////////////////////////////////////
  412. // JavaScript Specific Code for https://justine.lol/
  413. var a, code, index, output, funcall, M, Null;
  414. var eOutput, eEval, eReset, eLoad, eTrace, ePrograms, eDump;
  415. var eGets, eSets, eMs, eAtoms, eCode, eHeap, eReads, eWrites, eClear;
  416. function Throw(x) {
  417. throw x;
  418. }
  419. function Reset() {
  420. var i;
  421. a = 0;
  422. cx = 0;
  423. cHeap = 0;
  424. cGets = 0;
  425. cSets = 0;
  426. cReads = 0;
  427. cPrints = 0;
  428. Null = 16384;
  429. M = new Array(Null * 2);
  430. // for (i = 0; i < M.length; ++i) {
  431. // M[i] = 0; /* make json smaller */
  432. // }
  433. Load("NIL T EQ CAR CDR ATOM COND CONS QUOTE DEFINE ");
  434. LoadBuiltins()
  435. }
  436. function PrintU16(c) {
  437. output += String.fromCharCode(c);
  438. }
  439. function IsHighSurrogate(c) {
  440. return (0xfc00 & c) == 0xd800;
  441. }
  442. function IsLowSurrogate(c) {
  443. return (0xfc00 & c) == 0xdc00;
  444. }
  445. function GetHighSurrogate(c) {
  446. return ((c - 0x10000) >> 10) + 0xD800;
  447. }
  448. function GetLowSurrogate(c) {
  449. return ((c - 0x10000) & 1023) + 0xDC00;
  450. }
  451. function ComposeUtf16(c, d) {
  452. return ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000;
  453. }
  454. function PrintChar(c) {
  455. if (c < 0x10000) {
  456. PrintU16(c);
  457. } else if (c < 0x110000) {
  458. PrintU16(GetHighSurrogate(c));
  459. PrintU16(GetLowSurrogate(c));
  460. } else {
  461. PrintU16(0xFFFD);
  462. }
  463. }
  464. function Ord(s) {
  465. var c, d;
  466. c = s.charCodeAt(0);
  467. if (IsHighSurrogate(c)) {
  468. if (code.length > 1 && IsLowSurrogate((d = s.charCodeAt(1)))) {
  469. c = ComposeUtf16(c, d);
  470. } else {
  471. c = 0xFFFD;
  472. }
  473. } else if (IsLowSurrogate(c)) {
  474. c = 0xFFFD;
  475. }
  476. return c;
  477. }
  478. function ReadChar() {
  479. var c, d, t;
  480. if (code.length) {
  481. if (index < code.length) {
  482. c = code.charCodeAt(index++);
  483. if (IsHighSurrogate(c)) {
  484. if (index < code.length &&
  485. IsLowSurrogate((d = code.charCodeAt(index)))) {
  486. c = ComposeUtf16(c, d), ++index;
  487. } else {
  488. c = 0xFFFD;
  489. }
  490. } else if (IsLowSurrogate(c)) {
  491. c = 0xFFFD;
  492. }
  493. } else {
  494. code = "";
  495. c = 0;
  496. }
  497. t = dx;
  498. dx = c;
  499. return t;
  500. } else {
  501. Throw(0);
  502. }
  503. }
  504. function Lisp() {
  505. var x, A, d, t;
  506. d = 0;
  507. cGets = 0;
  508. cSets = 0;
  509. cHeap = cx;
  510. cReads = 0;
  511. cPrints = 0;
  512. output = "";
  513. while (dx) {
  514. if (dx <= Ord(' ')) {
  515. ReadChar();
  516. } else {
  517. t = GetMillis();
  518. A = cx;
  519. try {
  520. x = Read();
  521. if (x < 0 && Car(x) == kDefine) {
  522. a = Define(Cdr(x), a);
  523. continue;
  524. }
  525. x = Eval(x, a, 0);
  526. } catch (z) {
  527. PrintChar(Ord('?'));
  528. x = z;
  529. }
  530. Print(x);
  531. PrintChar(Ord('\n'));
  532. Gc(A, 0);
  533. d += GetMillis() - t;
  534. }
  535. }
  536. eOutput.innerText = output;
  537. SaveAlist(a);
  538. SaveOutput();
  539. ReportUsage(d);
  540. }
  541. function Load(s) {
  542. index = 0;
  543. dx = Ord(' ');
  544. code = s + "\n";
  545. }
  546. function OnEval() {
  547. Load(g_editor.getValue());
  548. Lisp();
  549. SetStorage("input", g_editor.getValue());
  550. }
  551. function OnBeforeUnload() {
  552. SetStorage("input", g_editor.getValue());
  553. }
  554. function OnDump() {
  555. var t;
  556. output = "";
  557. t = GetMillis();
  558. DumpDefines(a);
  559. eOutput.innerText = output;
  560. t = GetMillis() - t;
  561. SaveOutput();
  562. ReportUsage(t);
  563. }
  564. function OnReset(e) {
  565. var t;
  566. output = "";
  567. t = GetMillis();
  568. try {
  569. if (!e.shiftKey) DumpDefines(a);
  570. eOutput.innerText = output;
  571. Reset();
  572. } catch (e) {
  573. /* ignored */
  574. }
  575. t = GetMillis() - t;
  576. RemoveStorage("alist");
  577. SaveOutput();
  578. ReportUsage(t);
  579. }
  580. function OnClear() {
  581. output = "";
  582. eOutput.innerText = output;
  583. SaveOutput();
  584. ReportUsage(0);
  585. }
  586. function OnTrace() {
  587. var t;
  588. Load(g_editor.getValue());
  589. t = panic;
  590. depth = 0;
  591. panic = 10000;
  592. funcall = Trace;
  593. Lisp();
  594. funcall = Apply;
  595. panic = t;
  596. }
  597. function OnLoad() {
  598. if (ePrograms.className == "dropdown-content") {
  599. ePrograms.className = "dropdown-content show";
  600. } else {
  601. ePrograms.className = "dropdown-content";
  602. }
  603. }
  604. function OnWindowClick(e) {
  605. if (e.target && !e.target.matches("#load")) {
  606. ePrograms.className = "dropdown-content";
  607. }
  608. }
  609. function OnWindowKeyDown(e) {
  610. if (e.key == "Escape") {
  611. ePrograms.className = "dropdown-content";
  612. }
  613. }
  614. function SaveAlist(a) {
  615. output = "";
  616. DumpAlist(a);
  617. SetStorage("alist", output);
  618. }
  619. function RestoreMachine() {
  620. var v;
  621. if ((v = GetStorage("output"))) {
  622. eOutput.innerText = v;
  623. }
  624. if ((v = GetStorage("input"))) {
  625. g_editor.setValue(v);
  626. }
  627. if ((v = GetStorage("alist"))) {
  628. Reset();
  629. Load(v);
  630. a = Compact(Read());
  631. } else if ((v = JSON.parse(GetStorage("machine")))) {
  632. M = v[0];
  633. a = v[1];
  634. cx = v[2];
  635. cHeap = cx;
  636. }
  637. }
  638. function SaveOutput() {
  639. SetStorage("input", g_editor.getValue());
  640. SetStorage("output", eOutput.innerText);
  641. }
  642. function FormatInt(i) {
  643. return i.toLocaleString();
  644. }
  645. function FormatDuration(d) {
  646. return d ? Math.round(d * 1000) / 1000 : 0;
  647. }
  648. function ReportUsage(ms) {
  649. var i, atom, code, heap;
  650. code = -cx >> 1;
  651. heap = -cHeap >> 1;
  652. for (atom = i = 0; i < Null / 2; ++i) {
  653. if (M[Null + i]) ++atom;
  654. }
  655. if (eGets) eGets.innerText = FormatInt(cGets);
  656. if (eSets) eSets.innerText = FormatInt(cSets);
  657. if (eMs) eMs.innerText = FormatInt(ms);
  658. if (eAtoms) eAtoms.innerText = FormatInt(atom);
  659. if (eCode) eCode.innerText = FormatInt(code);
  660. if (eHeap) eHeap.innerText = FormatInt(heap - code);
  661. if (eReads) eReads.innerText = FormatInt(cReads);
  662. if (ePrints) ePrints.innerText = FormatInt(cPrints);
  663. }
  664. function Discount(f) {
  665. return function() {
  666. var x, g, h, s;
  667. g = cGets;
  668. s = cSets;
  669. h = cHeap;
  670. x = f.apply(this, arguments);
  671. cHeap = h;
  672. cSets = s;
  673. cGets = g;
  674. return x;
  675. };
  676. }
  677. function GetMillis() {
  678. if (typeof performance != "undefined") {
  679. return performance.now();
  680. } else {
  681. return 0;
  682. }
  683. }
  684. function GetStorage(k) {
  685. if (typeof localStorage != "undefined") {
  686. return localStorage.getItem(g_lisp + "." + k);
  687. } else {
  688. return null;
  689. }
  690. }
  691. function RemoveStorage(k) {
  692. if (typeof localStorage != "undefined") {
  693. localStorage.removeItem(g_lisp + "." + k);
  694. }
  695. }
  696. function SetStorage(k, v) {
  697. if (typeof localStorage != "undefined") {
  698. localStorage.setItem(g_lisp + "." + k, v);
  699. }
  700. }
  701. function SetUp() {
  702. funcall = Apply;
  703. Read = Discount(Read);
  704. Print = Discount(Print);
  705. Define = Discount(Define);
  706. eLoad = document.getElementById("load");
  707. eReset = document.getElementById("reset");
  708. eTrace = document.getElementById("trace");
  709. eOutput = document.getElementById("output");
  710. eEval = document.getElementById("eval");
  711. eClear = document.getElementById("clear");
  712. eDump = document.getElementById("dump");
  713. ePrograms = document.getElementById("programs");
  714. eGets = document.getElementById("cGets");
  715. eSets = document.getElementById("cSets");
  716. eMs = document.getElementById("cMs");
  717. eAtoms = document.getElementById("cAtoms");
  718. eCode = document.getElementById("cCode");
  719. eHeap = document.getElementById("cHeap");
  720. eReads = document.getElementById("cReads");
  721. ePrints = document.getElementById("cPrints");
  722. window.onkeydown = OnWindowKeyDown;
  723. if (window.onbeforeunload) window.onbeforeunload = OnBeforeUnload;
  724. if (ePrograms) window.onclick = OnWindowClick;
  725. if (eLoad) eLoad.onclick = OnLoad;
  726. if (eReset) eReset.onclick = OnReset;
  727. if (eTrace) eTrace.onclick = OnTrace;
  728. if (eEval) eEval.onclick = OnEval;
  729. if (eDump) eDump.onclick = OnDump;
  730. if (eClear) eClear.onclick = OnClear;
  731. }
  732. //
`
  733. #endif
  734. //`