/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ │ Permission to use, copy, modify, and/or distribute this software for │ │ any purpose with or without fee is hereby granted, provided that the │ │ above copyright notice and this permission notice appear in all copies. │ │ │ │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "bestline.h" #ifndef __COSMOPOLITAN__ #include #include #include #include #include #include #endif /*───────────────────────────────────────────────────────────────────────────│─╗ │ The LISP Challenge § LISP Machine ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ #define kT 4 #define kQuote 6 #define kAtom 12 #define kCar 17 #define kCdr 21 #define kCons 25 #define kEq 30 #define M (RAM + sizeof(RAM) / sizeof(RAM[0]) / 2) #define S "NIL\0T\0QUOTE\0ATOM\0CAR\0CDR\0CONS\0EQ" int cx; /* stores negative memory use */ int dx; /* stores lookahead character */ int RAM[0100000]; /* your own ibm7090 */ Intern() { int i, j, x; for (i = 0; (x = M[i++]);) { for (j = 0;; ++j) { if (x != RAM[j]) break; if (!x) return i - j - 1; x = M[i++]; } while (x) x = M[i++]; } j = 0; x = --i; while ((M[i++] = RAM[j++])); return x; } GetChar() { int c, t; static char *l, *p; if (l || (l = p = bestlineWithHistory("* ", "sectorlisp"))) { if (*p) { c = *p++ & 255; } else { free(l); l = p = 0; c = '\n'; } t = dx; dx = c; return t; } else { PrintChar('\n'); exit(0); } } PrintChar(b) { fputwc(b, stdout); } GetToken() { int c, i = 0; do if ((c = GetChar()) > ' ') RAM[i++] = c; while (c <= ' ' || (c > ')' && dx > ')')); RAM[i] = 0; return c; } AddList(x) { return Cons(x, GetList()); } GetList() { int c = GetToken(); if (c == ')') return 0; return AddList(GetObject(c)); } GetObject(c) { if (c == '(') return GetList(); return Intern(); } Read() { return GetObject(GetToken()); } PrintAtom(x) { int c; for (;;) { if (!(c = M[x++])) break; PrintChar(c); } } PrintList(x) { PrintChar('('); if (x) { PrintObject(Car(x)); while ((x = Cdr(x))) { if (x < 0) { PrintChar(' '); PrintObject(Car(x)); } else { PrintChar(L'∙'); PrintObject(x); break; } } } PrintChar(')'); } PrintObject(x) { if (1./x < 0) { PrintList(x); } else { PrintAtom(x); } } Print(e) { PrintObject(e); PrintChar('\n'); } /*───────────────────────────────────────────────────────────────────────────│─╗ │ The LISP Challenge § Bootstrap John McCarthy's Metacircular Evaluator ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ Car(x) { return M[x]; } Cdr(x) { return M[x + 1]; } Cons(car, cdr) { M[--cx] = cdr; M[--cx] = car; return cx; } Gc(x, m, k) { return x < m ? Cons(Gc(Car(x), m, k), Gc(Cdr(x), m, k)) + k : x; } Evlis(m, a) { return m ? Cons(Eval(Car(m), a), Evlis(Cdr(m), a)) : 0; } Pairlis(x, y, a) { return x ? Cons(Cons(Car(x), Car(y)), Pairlis(Cdr(x), Cdr(y), a)) : a; } Assoc(x, y) { if (x == Car(Car(y))) return Cdr(Car(y)); return Assoc(x, Cdr(y)); } Evcon(c, a) { if (Eval(Car(Car(c)), a)) { return Eval(Car(Cdr(Car(c))), a); } else { return Evcon(Cdr(c), a); } } Apply(f, x, a) { if (f < 0) return Evcon(Cdr(f), Pairlis(Car(f), x, a)); if (f > kEq) return Apply(Eval(f, a), 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 == kCar) return Car(Car(x)); if (f == kCdr) return Cdr(Car(x)); } Eval(e, a) { int A, B, C; if (!e) return 0; if (e > 0) return Assoc(e, a); if (Car(e) == kQuote) return Car(Cdr(e)); A = cx, e = Apply(Car(e), Evlis(Cdr(e), a), a); B = cx, e = Gc(e, A, A - B); C = cx; while (C < B) M[--A] = M[--B]; cx = A; return e; } /*───────────────────────────────────────────────────────────────────────────│─╗ │ The LISP Challenge § User Interface ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ main() { int i; setlocale(LC_ALL, ""); bestlineSetXlatCallback(bestlineUppercase); for(i = 0; i < sizeof(S); ++i) M[i] = S[i]; for (;;) { cx = 0; Print(Eval(Read(), 0)); } }