lisp.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
  2. │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
  3. ╞══════════════════════════════════════════════════════════════════════════════╡
  4. │ Copyright 2020 Justine Alexandra Roberts Tunney │
  5. │ │
  6. │ Permission to use, copy, modify, and/or distribute this software for │
  7. │ any purpose with or without fee is hereby granted, provided that the │
  8. │ above copyright notice and this permission notice appear in all copies. │
  9. │ │
  10. │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
  11. │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
  12. │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
  13. │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
  14. │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
  15. │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
  16. │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
  17. │ PERFORMANCE OF THIS SOFTWARE. │
  18. ╚─────────────────────────────────────────────────────────────────────────────*/
  19. #include "bestline.h"
  20. #ifndef __COSMOPOLITAN__
  21. #include <stdio.h>
  22. #include <locale.h>
  23. #include <setjmp.h>
  24. #endif
  25. #define var int
  26. #define function
  27. #define Null 0100000
  28. var M[Null * 2];
  29. jmp_buf undefined;
  30. var cx, dx, kT, kEq, kCar, kCdr, kCond, kAtom, kCons, kQuote;
  31. function Set(i, x) {
  32. M[Null + i] = x;
  33. }
  34. function Get(i) {
  35. return M[Null + i];
  36. }
  37. function Hash(h, c) {
  38. return h + c * 2;
  39. }
  40. function Intern(x, y, i) {
  41. i &= Null - 1;
  42. if (x == Get(i) && y == Get(i + 1)) return i;
  43. if (Get(i)) return Intern(x, y, i + 2);
  44. Set(i, x);
  45. Set(i + 1, y);
  46. return i;
  47. }
  48. function ReadAtom(h) {
  49. var c = ReadChar();
  50. if (c <= 32) return ReadAtom(h);
  51. return Intern(c, c > 41 && dx > 41 ?
  52. ReadAtom(Hash(h, c)) : 0,
  53. Hash(h, c) - Hash(0, 78));
  54. }
  55. function PrintAtom(x) {
  56. do PrintChar(Get(x));
  57. while ((x = Get(x + 1)));
  58. }
  59. function AddList(x) {
  60. return Cons(x, ReadList());
  61. }
  62. function ReadList() {
  63. var t = ReadAtom(0);
  64. if (Get(t) == 41) return 0;
  65. return AddList(ReadObject(t));
  66. }
  67. function ReadObject(t) {
  68. if (Get(t) != 40) return t;
  69. return ReadList();
  70. }
  71. function PrintList(x) {
  72. PrintChar(40);
  73. if (x < 0) {
  74. PrintObject(Car(x));
  75. while ((x = Cdr(x))) {
  76. if (x < 0) {
  77. PrintChar(32);
  78. PrintObject(Car(x));
  79. } else {
  80. PrintChar(8729);
  81. PrintObject(x);
  82. break;
  83. }
  84. }
  85. }
  86. PrintChar(41);
  87. }
  88. function PrintObject(x) {
  89. if (1./x < 0) {
  90. PrintList(x);
  91. } else {
  92. PrintAtom(x);
  93. }
  94. }
  95. function Print(e) {
  96. PrintObject(e);
  97. PrintChar(10);
  98. }
  99. function Read() {
  100. return ReadObject(ReadAtom(0));
  101. }
  102. function Car(x) {
  103. if (x < 0) {
  104. return Get(x);
  105. } else {
  106. Throw(x);
  107. }
  108. }
  109. function Cdr(x) {
  110. if (x < 0) {
  111. return Get(x + 1);
  112. } else {
  113. Throw(x);
  114. }
  115. }
  116. function Cons(car, cdr) {
  117. Set(--cx, cdr);
  118. Set(--cx, car);
  119. return cx;
  120. }
  121. function Gc(A, x) {
  122. var C, B = cx;
  123. x = Copy(x, A, A - B), C = cx;
  124. while (C < B) Set(--A, Get(--B));
  125. cx = A;
  126. return x;
  127. }
  128. function Copy(x, m, k) {
  129. return x < m ? Cons(Copy(Car(x), m, k),
  130. Copy(Cdr(x), m, k)) + k : x;
  131. }
  132. function Evlis(m, a) {
  133. return m ? Cons(Eval(Car(m), a),
  134. Evlis(Cdr(m), a)) : 0;
  135. }
  136. function Pairlis(x, y, a) {
  137. return x ? Cons(Cons(Car(x), Car(y)),
  138. Pairlis(Cdr(x), Cdr(y), a)) : a;
  139. }
  140. function Assoc(x, y) {
  141. if (y >= 0) Throw(x);
  142. if (x == Car(Car(y))) return Cdr(Car(y));
  143. return Assoc(x, Cdr(y));
  144. }
  145. function Evcon(c, a) {
  146. if (Eval(Car(Car(c)), a)) {
  147. return Eval(Car(Cdr(Car(c))), a);
  148. } else if (Cdr(c)) {
  149. return Evcon(Cdr(c), a);
  150. } else {
  151. Throw(c);
  152. }
  153. }
  154. function Apply(f, x, a) {
  155. if (f < 0) return Eval(Car(Cdr(Cdr(f))), Pairlis(Car(Cdr(f)), x, a));
  156. if (f == kEq) return Car(x) == Car(Cdr(x)) ? kT : 0;
  157. if (f == kCons) return Cons(Car(x), Car(Cdr(x)));
  158. if (f == kAtom) return Car(x) < 0 ? 0 : kT;
  159. if (f == kCar) return Car(Car(x));
  160. if (f == kCdr) return Cdr(Car(x));
  161. return Apply(Assoc(f, a), x, a);
  162. }
  163. function Eval(e, a) {
  164. var A = cx;
  165. if (!e) return 0;
  166. if (e > 0) return Assoc(e, a);
  167. if (Car(e) == kQuote) return Car(Cdr(e));
  168. if (Car(e) == kCond) {
  169. e = Evcon(Cdr(e), a);
  170. } else {
  171. e = Apply(Car(e), Evlis(Cdr(e), a), a);
  172. }
  173. return Gc(A, e);
  174. }
  175. function Lisp() {
  176. var x, a;
  177. ReadAtom(0);
  178. kT = ReadAtom(0);
  179. kCar = ReadAtom(0);
  180. kCdr = ReadAtom(0);
  181. kAtom = ReadAtom(0);
  182. kCond = ReadAtom(0);
  183. kCons = ReadAtom(0);
  184. kQuote = ReadAtom(0);
  185. kEq = ReadAtom(0);
  186. for (a = 0;;) {
  187. if (!(x = setjmp(undefined))) {
  188. x = Read();
  189. x = Eval(x, a);
  190. if (x < 0) {
  191. a = Cons(x, a);
  192. }
  193. } else {
  194. PrintChar(63);
  195. }
  196. Print(x);
  197. }
  198. }
  199. Throw(x) {
  200. longjmp(undefined, x);
  201. }
  202. PrintChar(b) {
  203. fputwc(b, stdout);
  204. }
  205. ReadChar() {
  206. int b, c, t;
  207. static char *freeme;
  208. static char *line = "NIL T CAR CDR ATOM COND CONS QUOTE EQ ";
  209. if (line || (line = freeme = bestlineWithHistory("* ", "sectorlisp"))) {
  210. if (*line) {
  211. c = *line++ & 0377;
  212. if (c >= 0300) {
  213. for (b = 0200; c & b; b >>= 1) c ^= b;
  214. while ((*line & 0300) == 0200) {
  215. c <<= 6;
  216. c |= *line++ & 0177;
  217. }
  218. }
  219. } else {
  220. free(freeme);
  221. freeme = 0;
  222. line = 0;
  223. c = 10;
  224. }
  225. t = dx;
  226. dx = c;
  227. return t;
  228. } else {
  229. PrintChar(10);
  230. exit(0);
  231. }
  232. }
  233. main() {
  234. setlocale(LC_ALL, "");
  235. bestlineSetXlatCallback(bestlineUppercase);
  236. Lisp();
  237. }