mirror of
https://github.com/samsonjs/sectorlisp.git
synced 2026-04-27 14:57:41 +00:00
Experiment with friendlier branch
This commit is contained in:
parent
2a00af296b
commit
626f71b9a3
3 changed files with 149 additions and 155 deletions
3
Makefile
3
Makefile
|
|
@ -1,5 +1,4 @@
|
||||||
CFLAGS = -w -Os
|
CFLAGS = -w -g
|
||||||
LDFLAGS = -s
|
|
||||||
|
|
||||||
CLEANFILES = \
|
CLEANFILES = \
|
||||||
lisp \
|
lisp \
|
||||||
|
|
|
||||||
273
lisp.c
273
lisp.c
|
|
@ -28,121 +28,78 @@
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
|
||||||
│ The LISP Challenge § LISP Machine ─╬─│┼
|
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
|
||||||
|
|
||||||
#define kT 4
|
|
||||||
#define kQuote 6
|
|
||||||
#define kCond 12
|
|
||||||
#define kAtom 17
|
|
||||||
#define kCar 22
|
|
||||||
#define kCdr 26
|
|
||||||
#define kCons 30
|
|
||||||
#define kEq 35
|
|
||||||
|
|
||||||
#define M (RAM + sizeof(RAM) / sizeof(RAM[0]) / 2)
|
|
||||||
#define S "NIL\0T\0QUOTE\0COND\0ATOM\0CAR\0CDR\0CONS\0EQ"
|
|
||||||
|
|
||||||
int cx; /* stores negative memory use */
|
|
||||||
int dx; /* stores lookahead character */
|
|
||||||
int RAM[0100000]; /* your own ibm7090 */
|
|
||||||
jmp_buf undefined;
|
jmp_buf undefined;
|
||||||
|
int cx, dx, M[0100000];
|
||||||
|
int Null = sizeof(M) / sizeof(M[0]) / 2;
|
||||||
|
char *line = "NIL T CAR CDR ATOM COND CONS QUOTE EQ ";
|
||||||
|
int kT, kEq, kNil, kCar, kCdr, kCond, kAtom, kCons, kQuote;
|
||||||
|
|
||||||
Intern() {
|
Get(i) {
|
||||||
int i, j, x;
|
return M[Null + i];
|
||||||
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() {
|
Set(i, x) {
|
||||||
int c, t;
|
M[Null + i] = x;
|
||||||
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() {
|
Read() {
|
||||||
return GetObject(GetToken());
|
return ReadObject(ReadAtom(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
Intern(x, y, i) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadAtom(i) {
|
||||||
|
int c = ReadChar();
|
||||||
|
if (c <= ' ') return ReadAtom(i);
|
||||||
|
return Intern(c, c > ')' && dx > ')' ? ReadAtom(0) : 0, i + c * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddList(x) {
|
||||||
|
return Cons(x, ReadList());
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadList() {
|
||||||
|
int t = ReadAtom(0);
|
||||||
|
if (Get(t) == ')') return kNil;
|
||||||
|
return AddList(ReadObject(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadObject(t) {
|
||||||
|
if (Get(t) != '(') return t;
|
||||||
|
return ReadList();
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAtom(x) {
|
PrintAtom(x) {
|
||||||
int c;
|
do PrintChar(Get(x));
|
||||||
for (;;) {
|
while ((x = Get(x + 1)));
|
||||||
if (!(c = M[x++])) break;
|
|
||||||
PrintChar(c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintList(x) {
|
PrintList(x) {
|
||||||
PrintChar('(');
|
PrintChar('(');
|
||||||
PrintObject(Car(x));
|
if (x < 0) {
|
||||||
while ((x = Cdr(x))) {
|
PrintObject(Car(x));
|
||||||
if (x < 0) {
|
while ((x = Cdr(x)) != kNil) {
|
||||||
PrintChar(' ');
|
if (x < 0) {
|
||||||
PrintObject(Car(x));
|
PrintChar(' ');
|
||||||
} else {
|
PrintObject(Car(x));
|
||||||
PrintChar(L'∙');
|
} else {
|
||||||
PrintObject(x);
|
PrintChar(L'∙');
|
||||||
break;
|
PrintObject(x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintChar(')');
|
PrintChar(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintObject(x) {
|
PrintObject(x) {
|
||||||
if (x < 0) {
|
if (1./x < 0) {
|
||||||
PrintList(x);
|
PrintList(x);
|
||||||
} else {
|
} else {
|
||||||
PrintAtom(x);
|
PrintAtom(x);
|
||||||
|
|
@ -154,39 +111,49 @@ Print(e) {
|
||||||
PrintChar('\n');
|
PrintChar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
|
||||||
│ The LISP Challenge § Bootstrap John McCarthy's Metacircular Evaluator ─╬─│┼
|
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
|
||||||
|
|
||||||
Car(x) {
|
Car(x) {
|
||||||
if (x >= 0) longjmp(undefined, x);
|
if (x < 0) {
|
||||||
return M[x];
|
return Get(x);
|
||||||
|
} else {
|
||||||
|
longjmp(undefined, x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Cdr(x) {
|
Cdr(x) {
|
||||||
if (x >= 0) longjmp(undefined, x);
|
if (x < 0) {
|
||||||
return M[x + 1];
|
return Get(x + 1);
|
||||||
|
} else {
|
||||||
|
longjmp(undefined, x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Cons(car, cdr) {
|
Cons(car, cdr) {
|
||||||
M[--cx] = cdr;
|
Set(--cx, cdr);
|
||||||
M[--cx] = car;
|
Set(--cx, car);
|
||||||
return cx;
|
return cx;
|
||||||
}
|
}
|
||||||
|
|
||||||
Gc(x, m, k) {
|
Gc(A, x) {
|
||||||
return x < m ? Cons(Gc(Car(x), m, k),
|
int C, B = cx;
|
||||||
Gc(Cdr(x), m, k)) + k : x;
|
x = Copy(x, A, A - B), C = cx;
|
||||||
|
while (C < B) Set(--A, Get(--B));
|
||||||
|
cx = A;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy(x, m, k) {
|
||||||
|
return x < m ? Cons(Copy(Car(x), m, k),
|
||||||
|
Copy(Cdr(x), m, k)) + k : x;
|
||||||
}
|
}
|
||||||
|
|
||||||
Evlis(m, a) {
|
Evlis(m, a) {
|
||||||
return m ? Cons(Eval(Car(m), a),
|
return m != kNil ? Cons(Eval(Car(m), a),
|
||||||
Evlis(Cdr(m), a)) : 0;
|
Evlis(Cdr(m), a)) : kNil;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pairlis(x, y, a) {
|
Pairlis(x, y, a) {
|
||||||
return x ? Cons(Cons(Car(x), Car(y)),
|
return x != kNil ? Cons(Cons(Car(x), Car(y)),
|
||||||
Pairlis(Cdr(x), Cdr(y), a)) : a;
|
Pairlis(Cdr(x), Cdr(y), a)) : a;
|
||||||
}
|
}
|
||||||
|
|
||||||
Assoc(x, y) {
|
Assoc(x, y) {
|
||||||
|
|
@ -196,63 +163,93 @@ Assoc(x, y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Evcon(c, a) {
|
Evcon(c, a) {
|
||||||
if (Eval(Car(Car(c)), a)) {
|
if (Eval(Car(Car(c)), a) != kNil) {
|
||||||
return Eval(Car(Cdr(Car(c))), a);
|
return Eval(Car(Cdr(Car(c))), a);
|
||||||
} else {
|
} else if (Cdr(c) != kNil) {
|
||||||
return Evcon(Cdr(c), a);
|
return Evcon(Cdr(c), a);
|
||||||
|
} else {
|
||||||
|
longjmp(undefined, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Apply(f, x, a) {
|
Apply(f, x, a) {
|
||||||
if (f < 0) return Eval(Car(Cdr(Cdr(f))), Pairlis(Car(Cdr(f)), x, a));
|
if (f < 0) return Eval(Car(Cdr(Cdr(f))), Pairlis(Car(Cdr(f)), x, a));
|
||||||
if (f > kEq) return Apply(Eval(f, a), x, a);
|
if (f == kEq) return Car(x) == Car(Cdr(x)) ? kT : kNil;
|
||||||
if (f == kEq) return Car(x) == Car(Cdr(x)) ? kT : 0;
|
|
||||||
if (f == kCons) return Cons(Car(x), Car(Cdr(x)));
|
if (f == kCons) return Cons(Car(x), Car(Cdr(x)));
|
||||||
if (f == kAtom) return Car(x) < 0 ? 0 : kT;
|
if (f == kAtom) return Car(x) < 0 ? kNil : kT;
|
||||||
if (f == kCar) return Car(Car(x));
|
if (f == kCar) return Car(Car(x));
|
||||||
if (f == kCdr) return Cdr(Car(x));
|
if (f == kCdr) return Cdr(Car(x));
|
||||||
longjmp(undefined, f);
|
return Apply(Assoc(f, a), x, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
Eval(e, a) {
|
Eval(e, a) {
|
||||||
int A, B, C;
|
int A = cx;
|
||||||
if (!e) return 0;
|
if (e == kNil) return kNil;
|
||||||
if (e > 0) return Assoc(e, a);
|
if (e >= 0) return Assoc(e, a);
|
||||||
if (Car(e) == kQuote) return Car(Cdr(e));
|
if (Car(e) == kQuote) return Car(Cdr(e));
|
||||||
A = cx;
|
|
||||||
if (Car(e) == kCond) {
|
if (Car(e) == kCond) {
|
||||||
e = Evcon(Cdr(e), a);
|
e = Evcon(Cdr(e), a);
|
||||||
} else {
|
} else {
|
||||||
e = Apply(Car(e), Evlis(Cdr(e), a), a);
|
e = Apply(Car(e), Evlis(Cdr(e), a), a);
|
||||||
}
|
}
|
||||||
B = cx;
|
return Gc(A, e);
|
||||||
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() {
|
main() {
|
||||||
int x, a = 0;
|
int x, a;
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
bestlineSetXlatCallback(bestlineUppercase);
|
bestlineSetXlatCallback(bestlineUppercase);
|
||||||
for(x = 0; x < sizeof(S); ++x) M[x] = S[x];
|
kNil = ReadAtom(0);
|
||||||
for (;;) {
|
kT = ReadAtom(0);
|
||||||
|
kCar = ReadAtom(0);
|
||||||
|
kCdr = ReadAtom(0);
|
||||||
|
kAtom = ReadAtom(0);
|
||||||
|
kCond = ReadAtom(0);
|
||||||
|
kCons = ReadAtom(0);
|
||||||
|
kQuote = ReadAtom(0);
|
||||||
|
kEq = ReadAtom(0);
|
||||||
|
for (a = kNil;;) {
|
||||||
if (!(x = setjmp(undefined))) {
|
if (!(x = setjmp(undefined))) {
|
||||||
x = Eval(Read(), a);
|
x = Read();
|
||||||
|
x = Eval(x, a);
|
||||||
if (x < 0) {
|
if (x < 0) {
|
||||||
a = Cons(x, a);
|
a = Cons(x, a);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (x == 1) x = 0;
|
|
||||||
PrintChar('?');
|
PrintChar('?');
|
||||||
}
|
}
|
||||||
Print(x);
|
Print(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintChar(b) {
|
||||||
|
fputwc(b, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadChar() {
|
||||||
|
int b, c, t;
|
||||||
|
static char *freeme;
|
||||||
|
if (line || (line = freeme = bestlineWithHistory("* ", "sectorlisp"))) {
|
||||||
|
if (*line) {
|
||||||
|
c = *line++ & 0377;
|
||||||
|
if (c >= 0300) {
|
||||||
|
for (b = 0200; c & b; b >>= 1) c ^= b;
|
||||||
|
while ((*line & 0300) == 0200) {
|
||||||
|
c <<= 6;
|
||||||
|
c |= *line++ & 0177;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
free(freeme);
|
||||||
|
freeme = 0;
|
||||||
|
line = 0;
|
||||||
|
c = '\n';
|
||||||
|
}
|
||||||
|
t = dx;
|
||||||
|
dx = c;
|
||||||
|
return t;
|
||||||
|
} else {
|
||||||
|
PrintChar('\n');
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
28
sectorlisp.S
28
sectorlisp.S
|
|
@ -23,12 +23,13 @@
|
||||||
// Compatible with the original hardware
|
// Compatible with the original hardware
|
||||||
|
|
||||||
.code16
|
.code16
|
||||||
.set save,-10
|
.set save,-2-2
|
||||||
.set look,start+2
|
.set look,start+5-2
|
||||||
.globl _start
|
.globl _start
|
||||||
_start: .asciz "NIL" # dec %si ; dec %cx ; dec %sp
|
_start: .asciz "NIL" # dec %si ; dec %cx ; dec %sp
|
||||||
kT: .asciz "T" # add %dl,(%si) boot A:\ DL=0
|
kT: .asciz "T" # add %dl,(%si) boot A:\ DL=0
|
||||||
start: ljmp $0x7c00>>4,$begin # cs = 0x7c00 is boot address
|
start: mov $0x8000,%sp # this should be safe we hope
|
||||||
|
ljmp $0x7c00>>4,$begin # cs = 0x7c00 is boot address
|
||||||
.asciz ""
|
.asciz ""
|
||||||
kQuote: .asciz "QUOTE"
|
kQuote: .asciz "QUOTE"
|
||||||
kCond: .asciz "COND"
|
kCond: .asciz "COND"
|
||||||
|
|
@ -38,20 +39,17 @@ kCdr: .asciz "CDR" # ordering matters
|
||||||
kCons: .asciz "CONS" # ordering matters
|
kCons: .asciz "CONS" # ordering matters
|
||||||
kEq: .asciz "EQ" # needs to be last
|
kEq: .asciz "EQ" # needs to be last
|
||||||
|
|
||||||
begin: mov $2,%bx
|
begin: push %cs # that means ss = ds = es = cs
|
||||||
mov $0x8000,%cx
|
|
||||||
main: cli
|
|
||||||
push %cs # that means ss = ds = es = cs
|
|
||||||
pop %ds # noting ljmp set cs to 0x7c00
|
pop %ds # noting ljmp set cs to 0x7c00
|
||||||
push %cs # that's the bios load address
|
push %cs # that's the bios load address
|
||||||
pop %es # therefore NULL points to NUL
|
pop %es # therefore NULL points to NUL
|
||||||
push %cs # terminated NIL string above!
|
push %cs # terminated NIL string above!
|
||||||
pop %ss # errata exists but don't care
|
pop %ss # errata exists but don't care
|
||||||
xor %sp,%sp # use highest address as stack
|
mov $2,%bx
|
||||||
sti
|
mov %sp,%cx
|
||||||
call GetToken
|
main: call GetToken
|
||||||
call GetObject
|
call GetObject
|
||||||
mov %dx,save
|
mov %dx,save(%bx)
|
||||||
call Eval
|
call Eval
|
||||||
test %ax,%ax
|
test %ax,%ax
|
||||||
jns Print
|
jns Print
|
||||||
|
|
@ -69,7 +67,7 @@ Print: xchg %ax,%si
|
||||||
|
|
||||||
GetToken: # GetToken():al
|
GetToken: # GetToken():al
|
||||||
mov %cx,%di
|
mov %cx,%di
|
||||||
1: mov look,%al
|
1: mov look(%bx),%al
|
||||||
cmp $' ',%al
|
cmp $' ',%al
|
||||||
jbe 2f
|
jbe 2f
|
||||||
stosb
|
stosb
|
||||||
|
|
@ -79,12 +77,12 @@ GetToken: # GetToken():al
|
||||||
jne 4f
|
jne 4f
|
||||||
dec %di
|
dec %di
|
||||||
jmp 2b
|
jmp 2b
|
||||||
4: xchg %ax,look
|
4: xchg %ax,look(%bx)
|
||||||
cmp $' ',%al
|
cmp $' ',%al
|
||||||
jbe 1b
|
jbe 1b
|
||||||
cmp $')',%al
|
cmp $')',%al
|
||||||
jbe 3f
|
jbe 3f
|
||||||
cmpb $')',look
|
cmpb $')',look(%bx)
|
||||||
ja 1b
|
ja 1b
|
||||||
3: mov %bh,(%di) # bh is zero
|
3: mov %bh,(%di) # bh is zero
|
||||||
xchg %si,%ax
|
xchg %si,%ax
|
||||||
|
|
@ -147,7 +145,7 @@ Undef: push %ax
|
||||||
mov $'?',%al
|
mov $'?',%al
|
||||||
call PutChar
|
call PutChar
|
||||||
pop %ax
|
pop %ax
|
||||||
mov save,%dx
|
mov save(%bx),%dx
|
||||||
jmp Print
|
jmp Print
|
||||||
|
|
||||||
GetChar:xor %ax,%ax # GetChar→al:dl
|
GetChar:xor %ax,%ax # GetChar→al:dl
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue