lisp.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  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 16384
  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) * 3083 + 3191) >> 4) & (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 Gc(A, x) {
  139. var C, B = cx;
  140. x = Copy(x, A, A - B), C = cx;
  141. while (C < B) Set(--A, Get(--B));
  142. return cx = A, x;
  143. }
  144. function Copy(x, m, k) {
  145. var r, y, z;
  146. if (x >= m) return x;
  147. r = (y = Cons(Copy(Car(x), m, k), 0)) + k;
  148. for (;;) {
  149. if ((x = Cdr(x)) < m) {
  150. z = Cons(Copy(Car(x), m, k), 0);
  151. Set(y + 1, z + k);
  152. y = z;
  153. } else {
  154. Set(y + 1, x);
  155. break;
  156. }
  157. }
  158. return r;
  159. }
  160. function Assoc(x, y) {
  161. if (!y) Throw(x);
  162. return x == Car(Car(y)) ? Cdr(Car(y)) : Assoc(x, Cdr(y));
  163. }
  164. function Evcon(t, c, a) {
  165. if (c >= 0) Throw(kCond);
  166. if (Eval(Car(Car(c)), a)) {
  167. return Apply(t, Car(Cdr(Car(c))), a);
  168. } else {
  169. return Evcon(t, Cdr(c), a);
  170. }
  171. }
  172. function Bind(x, y, u, a) {
  173. return x ? Cons(Cons(Car(x), Eval(Car(y), u)),
  174. Bind(Cdr(x), Cdr(y), u, a)) : a;
  175. }
  176. function Apply(t, e, a) {
  177. var f, x, b, p, u, l, A;
  178. if (!e) return e;
  179. if (e > 0) return t ? e : Assoc(e, a);
  180. f = Car(e), x = Cdr(e);
  181. if (f == kCond) return Evcon(t, x, a);
  182. if (t) return e;
  183. if (f == kQuote) return Car(x);
  184. if (f == kCons) return Cons(Eval(Car(x), a), Eval(Car(Cdr(x)), a));
  185. if (f == kEq) return Eval(Car(x), a) == Eval(Car(Cdr(x)), a);
  186. if (f == kAtom) return Eval(Car(x), a) >= 0;
  187. if (f == kCar) return Car(Eval(Car(x), a));
  188. if (f == kCdr) return Cdr(Eval(Car(x), a));
  189. t = f;
  190. if (f > 0) f = Assoc(f, a);
  191. p = Car(Cdr(f));
  192. b = Car(Cdr(Cdr(f)));
  193. for (A = cx, u = a;;) {
  194. u = Bind(p, x, u, a);
  195. x = funcall(t, b, u);
  196. if (x < 0 && Car(x) == t) {
  197. x = Gc(A, Cons(u, Cdr(x)));
  198. u = Car(x);
  199. x = Cdr(x);
  200. } else {
  201. return Gc(A, Eval(x, u));
  202. }
  203. }
  204. }
  205. function Eval(e, a) {
  206. return Apply(0, e, a);
  207. }
  208. function Funcall(t, e, a) {
  209. return Apply(t, e, a);
  210. }
  211. function Funtrace(t, e, a) {
  212. var y;
  213. Indent(depth);
  214. Print(t);
  215. Print(e);
  216. PrintChar(Ord('\n'));
  217. depth += 2;
  218. y = Funcall(t, e, a);
  219. depth -= 2;
  220. Indent(depth);
  221. Print(t);
  222. Print(e);
  223. PrintChar(Ord(' '));
  224. PrintChar(0x2192);
  225. PrintChar(Ord(' '));
  226. Print(y);
  227. PrintChar(Ord('\n'));
  228. return y;
  229. }
  230. function Indent(i) {
  231. printf("%010d ", -cx);
  232. for (; i; --i) {
  233. PrintChar(Ord(' '));
  234. }
  235. }
  236. function DumpAlist(a) {
  237. PrintChar(Ord('('));
  238. PrintChar(Ord('\n'));
  239. for (;a ;a = Cdr(a)) {
  240. PrintChar(Ord('('));
  241. Print(Car(Car(a)));
  242. PrintChar(Ord(' '));
  243. PrintChar(Ord('.'));
  244. PrintChar(Ord(' '));
  245. Print(Cdr(Car(a)));
  246. PrintChar(Ord(')'));
  247. PrintChar(Ord('\n'));
  248. }
  249. PrintChar(Ord(')'));
  250. }
  251. function DumpDefines(a) {
  252. if (a) {
  253. DumpDefines(Cdr(a));
  254. PrintChar(Ord('('));
  255. Print(kDefine);
  256. PrintChar(Ord(' '));
  257. Print(Car(Car(a)));
  258. PrintChar(Ord(' '));
  259. PrintChar(Ord('.'));
  260. PrintChar(Ord(' '));
  261. Print(Cdr(Car(a)));
  262. PrintChar(Ord(')'));
  263. PrintChar(Ord('\n'));
  264. }
  265. }
  266. function LoadBuiltins() {
  267. Read();
  268. Read();
  269. kEq = Read();
  270. kCar = Read();
  271. kCdr = Read();
  272. kAtom = Read();
  273. kCond = Read();
  274. kCons = Read();
  275. kQuote = Read();
  276. kDefine = Read();
  277. }
  278. function Crunch(e, B) {
  279. var x, y, i;
  280. if (e >= 0) return e;
  281. x = Crunch(Car(e), B);
  282. y = Crunch(Cdr(e), B);
  283. for (i = B - 2; i >= cx; i -= 2) {
  284. if (x == Car(i) &&
  285. y == Cdr(i)) {
  286. return i - B;
  287. }
  288. }
  289. return Cons(x, y) - B;
  290. }
  291. function Compact(x) {
  292. var C, B = cx, A = 0;
  293. x = Crunch(x, B), C = cx;
  294. while (C < B) Set(--A, Get(--B));
  295. return cx = A, x;
  296. }
  297. function Remove(x, y) {
  298. if (!y) return y;
  299. if (x == Car(Car(y))) return Cdr(y);
  300. return Cons(Car(y), Remove(x, Cdr(y)));
  301. }
  302. function Define(x, a) {
  303. return Compact(Cons(x, Remove(Car(x), a)));
  304. }
  305. //
`
  306. ////////////////////////////////////////////////////////////////////////////////
  307. // ANSI POSIX C Specific Code
  308. Ord(c) {
  309. return c;
  310. }
  311. Throw(x) {
  312. if (fail < 255) ++fail;
  313. longjmp(undefined, ~x);
  314. }
  315. PrintChar(b) {
  316. fputwc(b, stdout);
  317. }
  318. SaveAlist(a) {
  319. }
  320. ReadChar() {
  321. int b, c, t;
  322. static char *freeme;
  323. static char *line = "NIL T EQ CAR CDR ATOM COND CONS QUOTE DEFINE ";
  324. if (line || (line = freeme = bestlineWithHistory("* ", "sectorlisp"))) {
  325. if (*line) {
  326. c = *line++ & 0377;
  327. if (c >= 0300) {
  328. for (b = 0200; c & b; b >>= 1) c ^= b;
  329. while ((*line & 0300) == 0200) {
  330. c <<= 6;
  331. c |= *line++ & 0177;
  332. }
  333. }
  334. } else {
  335. free(freeme);
  336. freeme = 0;
  337. line = 0;
  338. c = '\n';
  339. }
  340. t = dx;
  341. dx = c;
  342. return t;
  343. } else {
  344. exit(fail);
  345. }
  346. }
  347. main(argc, argv)
  348. char *argv[];
  349. {
  350. var x, a, A;
  351. setlocale(LC_ALL, "");
  352. bestlineSetXlatCallback(bestlineUppercase);
  353. funcall = Funcall;
  354. for (x = 1; x < argc; ++x) {
  355. if (argv[x][0] == '-' && argv[x][1] == 't') {
  356. funcall = Funtrace;
  357. } else {
  358. fputs("Usage: ", stderr);
  359. fputs(argv[0], stderr);
  360. fputs(" [-t] <input.lisp >errput.lisp\n", stderr);
  361. exit(1);
  362. }
  363. }
  364. LoadBuiltins();
  365. for (a = 0;;) {
  366. A = cx;
  367. if (!(x = setjmp(undefined))) {
  368. x = Read();
  369. if (x < 0 && Car(x) == kDefine) {
  370. a = Define(Cdr(x), a);
  371. SaveAlist(a);
  372. continue;
  373. }
  374. x = Eval(x, a, 0);
  375. } else {
  376. x = ~x;
  377. PrintChar('?');
  378. }
  379. Print(x);
  380. PrintChar('\n');
  381. Gc(A, 0);
  382. }
  383. }
  384. #if 0
  385. //`
  386. ////////////////////////////////////////////////////////////////////////////////
  387. // JavaScript Specific Code for https://justine.lol/
  388. var a, code, index, output, funcall, M, Null;
  389. var eOutput, eEval, eReset, eLoad, eTrace, ePrograms, eDump;
  390. var eGets, eSets, eMs, eAtoms, eCode, eHeap, eReads, eWrites, eClear;
  391. function Throw(x) {
  392. throw x;
  393. }
  394. function Reset() {
  395. var i;
  396. a = 0;
  397. cx = 0;
  398. cHeap = 0;
  399. cGets = 0;
  400. cSets = 0;
  401. cReads = 0;
  402. cPrints = 0;
  403. Null = 16384;
  404. M = new Array(Null * 2);
  405. // for (i = 0; i < M.length; ++i) {
  406. // M[i] = 0; /* make json smaller */
  407. // }
  408. Load("NIL T EQ CAR CDR ATOM COND CONS QUOTE DEFINE ");
  409. LoadBuiltins()
  410. }
  411. function PrintU16(c) {
  412. output += String.fromCharCode(c);
  413. }
  414. function IsHighSurrogate(c) {
  415. return (0xfc00 & c) == 0xd800;
  416. }
  417. function IsLowSurrogate(c) {
  418. return (0xfc00 & c) == 0xdc00;
  419. }
  420. function GetHighSurrogate(c) {
  421. return ((c - 0x10000) >> 10) + 0xD800;
  422. }
  423. function GetLowSurrogate(c) {
  424. return ((c - 0x10000) & 1023) + 0xDC00;
  425. }
  426. function ComposeUtf16(c, d) {
  427. return ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000;
  428. }
  429. function PrintChar(c) {
  430. if (c < 0x10000) {
  431. PrintU16(c);
  432. } else if (c < 0x110000) {
  433. PrintU16(GetHighSurrogate(c));
  434. PrintU16(GetLowSurrogate(c));
  435. } else {
  436. PrintU16(0xFFFD);
  437. }
  438. }
  439. function Ord(s) {
  440. var c, d;
  441. c = s.charCodeAt(0);
  442. if (IsHighSurrogate(c)) {
  443. if (code.length > 1 && IsLowSurrogate((d = s.charCodeAt(1)))) {
  444. c = ComposeUtf16(c, d);
  445. } else {
  446. c = 0xFFFD;
  447. }
  448. } else if (IsLowSurrogate(c)) {
  449. c = 0xFFFD;
  450. }
  451. return c;
  452. }
  453. function ReadChar() {
  454. var c, d, t;
  455. if (code.length) {
  456. if (index < code.length) {
  457. c = code.charCodeAt(index++);
  458. if (IsHighSurrogate(c)) {
  459. if (index < code.length &&
  460. IsLowSurrogate((d = code.charCodeAt(index)))) {
  461. c = ComposeUtf16(c, d), ++index;
  462. } else {
  463. c = 0xFFFD;
  464. }
  465. } else if (IsLowSurrogate(c)) {
  466. c = 0xFFFD;
  467. }
  468. } else {
  469. code = "";
  470. c = 0;
  471. }
  472. t = dx;
  473. dx = c;
  474. return t;
  475. } else {
  476. Throw(0);
  477. }
  478. }
  479. function Lisp() {
  480. var x, A, d, t;
  481. d = 0;
  482. cGets = 0;
  483. cSets = 0;
  484. cHeap = cx;
  485. cReads = 0;
  486. cPrints = 0;
  487. output = "";
  488. while (dx) {
  489. if (dx <= Ord(' ')) {
  490. ReadChar();
  491. } else {
  492. t = GetMillis();
  493. A = cx;
  494. try {
  495. x = Read();
  496. if (x < 0 && Car(x) == kDefine) {
  497. a = Define(Cdr(x), a);
  498. continue;
  499. }
  500. x = Eval(x, a, 0);
  501. } catch (z) {
  502. PrintChar(Ord('?'));
  503. x = z;
  504. }
  505. Print(x);
  506. PrintChar(Ord('\n'));
  507. Gc(A, 0);
  508. d += GetMillis() - t;
  509. }
  510. }
  511. eOutput.innerText = output;
  512. SaveAlist(a);
  513. SaveOutput();
  514. ReportUsage(d);
  515. }
  516. function Load(s) {
  517. index = 0;
  518. dx = Ord(' ');
  519. code = s + "\n";
  520. }
  521. function OnEval() {
  522. Load(g_editor.getValue());
  523. Lisp();
  524. SetStorage("input", g_editor.getValue());
  525. }
  526. function OnBeforeUnload() {
  527. SetStorage("input", g_editor.getValue());
  528. }
  529. function OnDump() {
  530. var t;
  531. output = "";
  532. t = GetMillis();
  533. DumpDefines(a);
  534. eOutput.innerText = output;
  535. t = GetMillis() - t;
  536. SaveOutput();
  537. ReportUsage(t);
  538. }
  539. function OnReset(e) {
  540. var t;
  541. output = "";
  542. t = GetMillis();
  543. try {
  544. if (!e.shiftKey) DumpDefines(a);
  545. eOutput.innerText = output;
  546. Reset();
  547. } catch (e) {
  548. /* ignored */
  549. }
  550. t = GetMillis() - t;
  551. RemoveStorage("alist");
  552. SaveOutput();
  553. ReportUsage(t);
  554. }
  555. function OnClear() {
  556. output = "";
  557. eOutput.innerText = output;
  558. SaveOutput();
  559. ReportUsage(0);
  560. }
  561. function OnTrace() {
  562. var t;
  563. Load(g_editor.getValue());
  564. t = panic;
  565. depth = 0;
  566. panic = 10000;
  567. funcall = Funtrace;
  568. Lisp();
  569. funcall = Funcall;
  570. panic = t;
  571. }
  572. function OnLoad() {
  573. if (ePrograms.className == "dropdown-content") {
  574. ePrograms.className = "dropdown-content show";
  575. } else {
  576. ePrograms.className = "dropdown-content";
  577. }
  578. }
  579. function OnWindowClick(e) {
  580. if (e.target && !e.target.matches("#load")) {
  581. ePrograms.className = "dropdown-content";
  582. }
  583. }
  584. function OnWindowKeyDown(e) {
  585. if (e.key == "Escape") {
  586. ePrograms.className = "dropdown-content";
  587. }
  588. }
  589. function SaveAlist(a) {
  590. output = "";
  591. DumpAlist(a);
  592. SetStorage("alist", output);
  593. }
  594. function RestoreMachine() {
  595. var v;
  596. if ((v = GetStorage("output"))) {
  597. eOutput.innerText = v;
  598. }
  599. if ((v = GetStorage("input"))) {
  600. g_editor.setValue(v);
  601. }
  602. if ((v = GetStorage("alist"))) {
  603. Reset();
  604. Load(v);
  605. a = Compact(Read());
  606. } else if ((v = JSON.parse(GetStorage("machine")))) {
  607. M = v[0];
  608. a = v[1];
  609. cx = v[2];
  610. cHeap = cx;
  611. }
  612. }
  613. function SaveOutput() {
  614. SetStorage("input", g_editor.getValue());
  615. SetStorage("output", eOutput.innerText);
  616. }
  617. function FormatInt(i) {
  618. return i.toLocaleString();
  619. }
  620. function FormatDuration(d) {
  621. return d ? Math.round(d * 1000) / 1000 : 0;
  622. }
  623. function ReportUsage(ms) {
  624. var i, atom, code, heap;
  625. code = -cx >> 1;
  626. heap = -cHeap >> 1;
  627. for (atom = i = 0; i < Null / 2; ++i) {
  628. if (M[Null + i]) ++atom;
  629. }
  630. if (eGets) eGets.innerText = FormatInt(cGets);
  631. if (eSets) eSets.innerText = FormatInt(cSets);
  632. if (eMs) eMs.innerText = FormatInt(ms);
  633. if (eAtoms) eAtoms.innerText = FormatInt(atom);
  634. if (eCode) eCode.innerText = FormatInt(code);
  635. if (eHeap) eHeap.innerText = FormatInt(heap - code);
  636. if (eReads) eReads.innerText = FormatInt(cReads);
  637. if (ePrints) ePrints.innerText = FormatInt(cPrints);
  638. }
  639. function Discount(f) {
  640. return function() {
  641. var x, g, h, s;
  642. g = cGets;
  643. s = cSets;
  644. h = cHeap;
  645. x = f.apply(this, arguments);
  646. cHeap = h;
  647. cSets = s;
  648. cGets = g;
  649. return x;
  650. };
  651. }
  652. function GetMillis() {
  653. if (typeof performance != "undefined") {
  654. return performance.now();
  655. } else {
  656. return 0;
  657. }
  658. }
  659. function GetStorage(k) {
  660. if (typeof localStorage != "undefined") {
  661. return localStorage.getItem(g_lisp + "." + k);
  662. } else {
  663. return null;
  664. }
  665. }
  666. function RemoveStorage(k) {
  667. if (typeof localStorage != "undefined") {
  668. localStorage.removeItem(g_lisp + "." + k);
  669. }
  670. }
  671. function SetStorage(k, v) {
  672. if (typeof localStorage != "undefined") {
  673. localStorage.setItem(g_lisp + "." + k, v);
  674. }
  675. }
  676. function SetUp() {
  677. funcall = Funcall;
  678. Read = Discount(Read);
  679. Print = Discount(Print);
  680. Define = Discount(Define);
  681. eLoad = document.getElementById("load");
  682. eReset = document.getElementById("reset");
  683. eTrace = document.getElementById("trace");
  684. eOutput = document.getElementById("output");
  685. eEval = document.getElementById("eval");
  686. eClear = document.getElementById("clear");
  687. eDump = document.getElementById("dump");
  688. ePrograms = document.getElementById("programs");
  689. eGets = document.getElementById("cGets");
  690. eSets = document.getElementById("cSets");
  691. eMs = document.getElementById("cMs");
  692. eAtoms = document.getElementById("cAtoms");
  693. eCode = document.getElementById("cCode");
  694. eHeap = document.getElementById("cHeap");
  695. eReads = document.getElementById("cReads");
  696. ePrints = document.getElementById("cPrints");
  697. window.onkeydown = OnWindowKeyDown;
  698. if (window.onbeforeunload) window.onbeforeunload = OnBeforeUnload;
  699. if (ePrograms) window.onclick = OnWindowClick;
  700. if (eLoad) eLoad.onclick = OnLoad;
  701. if (eReset) eReset.onclick = OnReset;
  702. if (eTrace) eTrace.onclick = OnTrace;
  703. if (eEval) eEval.onclick = OnEval;
  704. if (eDump) eDump.onclick = OnDump;
  705. if (eClear) eClear.onclick = OnClear;
  706. }
  707. //
`
  708. #endif
  709. //`