Create friendly version

This commit is contained in:
Justine Tunney 2021-11-24 10:03:42 -08:00
parent 17bd5be818
commit 2a00af296b
3 changed files with 76 additions and 25 deletions

30
lisp.c
View file

@ -25,6 +25,7 @@
#include <string.h> #include <string.h>
#include <locale.h> #include <locale.h>
#include <limits.h> #include <limits.h>
#include <setjmp.h>
#endif #endif
/*───────────────────────────────────────────────────────────────────────────│─╗ /*───────────────────────────────────────────────────────────────────────────│─╗
@ -46,6 +47,7 @@
int cx; /* stores negative memory use */ int cx; /* stores negative memory use */
int dx; /* stores lookahead character */ int dx; /* stores lookahead character */
int RAM[0100000]; /* your own ibm7090 */ int RAM[0100000]; /* your own ibm7090 */
jmp_buf undefined;
Intern() { Intern() {
int i, j, x; int i, j, x;
@ -157,10 +159,12 @@ Print(e) {
*/ */
Car(x) { Car(x) {
if (x >= 0) longjmp(undefined, x);
return M[x]; return M[x];
} }
Cdr(x) { Cdr(x) {
if (x >= 0) longjmp(undefined, x);
return M[x + 1]; return M[x + 1];
} }
@ -186,7 +190,7 @@ Pairlis(x, y, a) {
} }
Assoc(x, y) { Assoc(x, y) {
if (!y) return 0; if (y >= 0) longjmp(undefined, x);
if (x == Car(Car(y))) return Cdr(Car(y)); if (x == Car(Car(y))) return Cdr(Car(y));
return Assoc(x, Cdr(y)); return Assoc(x, Cdr(y));
} }
@ -207,14 +211,14 @@ Apply(f, x, a) {
if (f == kAtom) return Car(x) < 0 ? 0 : kT; if (f == kAtom) return Car(x) < 0 ? 0 : 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);
} }
Eval(e, a) { Eval(e, a) {
int A, B, C; int A, B, C;
if (e >= 0) if (!e) return 0;
return Assoc(e, a); if (e > 0) return Assoc(e, a);
if (Car(e) == kQuote) if (Car(e) == kQuote) return Car(Cdr(e));
return Car(Cdr(e));
A = cx; A = cx;
if (Car(e) == kCond) { if (Car(e) == kCond) {
e = Evcon(Cdr(e), a); e = Evcon(Cdr(e), a);
@ -235,12 +239,20 @@ Eval(e, a) {
*/ */
main() { main() {
int i; int x, a = 0;
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
bestlineSetXlatCallback(bestlineUppercase); bestlineSetXlatCallback(bestlineUppercase);
for(i = 0; i < sizeof(S); ++i) M[i] = S[i]; for(x = 0; x < sizeof(S); ++x) M[x] = S[x];
for (;;) { for (;;) {
cx = 0; if (!(x = setjmp(undefined))) {
Print(Eval(Read(), 0)); x = Eval(Read(), a);
if (x < 0) {
a = Cons(x, a);
}
} else {
if (x == 1) x = 0;
PrintChar('?');
}
Print(x);
} }
} }

View file

@ -120,3 +120,15 @@ NIL
((EQ (CAR E) (QUOTE COND)) (EVCON (CDR E) A)) ((EQ (CAR E) (QUOTE COND)) (EVCON (CDR E) A))
((QUOTE T) (APPLY (CAR E) (EVLIS (CDR E) A) A)))) ((QUOTE T) (APPLY (CAR E) (EVLIS (CDR E) A) A))))
((QUOTE T) (APPLY (CAR E) (EVLIS (CDR E) A) A)))))) ((QUOTE T) (APPLY (CAR E) (EVLIS (CDR E) A) A))))))
(CONS (QUOTE NOT)
(QUOTE (LAMBDA (X)
(COND (X (QUOTE F))
((QUOTE T) (QUOTE T))))))
((LAMBDA (X E C)
(CONS (QUOTE LAMBDA) (CONS NIL (CONS (CAR (CDR C)) NIL))))
(QUOTE T)
(QUOTE (LAMBDA (F) (F)))
(QUOTE (COND (X (QUOTE F))
((QUOTE T) (QUOTE T)))))

View file

@ -23,6 +23,8 @@
// Compatible with the original hardware // Compatible with the original hardware
.code16 .code16
.set save,-10
.set look,start+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
@ -36,37 +38,53 @@ 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: push %cs # that means ss = ds = es = cs begin: mov $2,%bx
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 xor %sp,%sp # use highest address as stack
mov $2,%bx sti
main: mov $0x8000,%cx # dl (g_look) is zero or cr
call GetToken call GetToken
call GetObject call GetObject
mov %dx,save
call Eval call Eval
xchg %ax,%si test %ax,%ax
jns Print
push %ax
xchg %ax,%di
xchg %dx,%ax
call Cons
xchg %ax,%dx
pop %ax
Print: xchg %ax,%si
call PrintObject call PrintObject
mov $'\r',%al mov $'\r',%al
call PutChar call PutChar
jmp main jmp main
GetToken: # GetToken():al, dl is g_look GetToken: # GetToken():al
mov %cx,%di mov %cx,%di
1: mov %dl,%al 1: mov look,%al
cmp $' ',%al cmp $' ',%al
jbe 2f jbe 2f
stosb stosb
xchg %ax,%si xchg %ax,%si
2: call GetChar # exchanges dx and ax 2: call GetChar # exchanges dx and ax
cmp $'\b',%al
jne 4f
dec %di
jmp 2b
4: xchg %ax,look
cmp $' ',%al cmp $' ',%al
jbe 1b jbe 1b
cmp $')',%al cmp $')',%al
jbe 3f jbe 3f
cmp $')',%dl # dl = g_look cmpb $')',look
ja 1b ja 1b
3: mov %bh,(%di) # bh is zero 3: mov %bh,(%di) # bh is zero
xchg %si,%ax xchg %si,%ax
@ -123,14 +141,21 @@ Intern: push %cx # Intern(cx,di): ax
jmp 1b jmp 1b
2: rep movsb # memcpy(di,si,cx) 2: rep movsb # memcpy(di,si,cx)
9: pop %cx 9: pop %cx
ret 3: ret
Undef: push %ax
mov $'?',%al
call PutChar
pop %ax
mov save,%dx
jmp Print
GetChar:xor %ax,%ax # GetCharal:dl GetChar:xor %ax,%ax # GetCharal:dl
int $0x16 # get keystroke int $0x16 # get keystroke
PutChar:mov $0x0e,%ah # prints CP-437 PutChar:mov $0x0e,%ah # prints CP-437
int $0x10 # vidya service int $0x10 # vidya service
cmp $'\r',%al # don't clobber cmp $'\r',%al # don't clobber
jne 1f # look xchg ret jne 3b # look xchg ret
mov $'\n',%al mov $'\n',%al
jmp PutChar jmp PutChar
@ -183,6 +208,15 @@ Gc: cmp %dx,%di # Gc(x:di,A:dx,B:si):ax
add %dx,%ax add %dx,%ax
ret ret
Assoc: mov %dx,%si # Assoc(x:ax,y:dx):ax
1: test %si,%si
jns Undef
mov (%si),%di
mov (%bx,%si),%si
scasw
jne 1b
jmp Car
GetList:call GetToken GetList:call GetToken
cmp $')',%al cmp $')',%al
je .retF je .retF
@ -234,13 +268,6 @@ Cdr: scasw # increments our data index by 2
Car: mov (%di),%ax # contents of address register!! Car: mov (%di),%ax # contents of address register!!
2: ret 2: ret
Assoc: mov %dx,%si # Assoc(x:ax,y:dx):ax
1: mov (%si),%di
mov (%bx,%si),%si
scasw
jne 1b
jmp Car
1: mov (%bx,%di),%di # di = Cdr(c) 1: mov (%bx,%di),%di # di = Cdr(c)
Evcon: push %di # save c Evcon: push %di # save c
mov (%di),%si # di = Car(c) mov (%di),%si # di = Car(c)