Make improvements

This commit is contained in:
Justine Tunney 2021-12-11 11:59:16 -08:00
parent 3eb0db0a7a
commit a25d58bddd
3 changed files with 71 additions and 66 deletions

View file

@ -3,6 +3,7 @@ CFLAGS = -w -g
CLEANFILES = \ CLEANFILES = \
lisp \ lisp \
lisp.o \ lisp.o \
lisp.o \
bestline.o \ bestline.o \
sectorlisp.o \ sectorlisp.o \
sectorlisp.bin \ sectorlisp.bin \
@ -19,7 +20,7 @@ all: lisp \
brainfuck.bin.dbg brainfuck.bin.dbg
.PHONY: clean .PHONY: clean
clean:; $(RM) lisp lisp.o bestline.o sectorlisp.o sectorlisp.bin sectorlisp.bin.dbg clean:; $(RM) $(CLEANFILES)
lisp: lisp.o bestline.o lisp: lisp.o bestline.o
lisp.o: lisp.js bestline.h lisp.o: lisp.js bestline.h

31
lisp.js
View file

@ -40,19 +40,13 @@ function Get(i) {
} }
function Car(x) { function Car(x) {
if (x < 0) { if (x > 0) Throw(List(kCar, x));
return Get(x); return x ? Get(x) : +0;
} else {
Throw(List(kCar, x));
}
} }
function Cdr(x) { function Cdr(x) {
if (x < 0) { if (x > 0) Throw(List(kCdr, x));
return Get(x + 1); return x ? Get(x + 1) : -0;
} else {
Throw(List(kCdr, x));
}
} }
function Cons(car, cdr) { function Cons(car, cdr) {
@ -88,14 +82,17 @@ function PrintAtom(x) {
while ((x = Get(x + 1))); while ((x = Get(x + 1)));
} }
function AddList(x) {
return Cons(x, ReadList());
}
function ReadList() { function ReadList() {
var t = ReadAtom(0); var x;
if (Get(t) == Ord(')')) return -0; if ((x = Read()) > 0) {
return AddList(ReadObject(t)); if (Get(x) == Ord(')')) return -0;
if (Get(x) == Ord('.') && !Get(x + 1)) {
x = Read();
ReadList();
return x;
}
}
return Cons(x, ReadList());
} }
function ReadObject(t) { function ReadObject(t) {

View file

@ -19,8 +19,13 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
// LISP meta-circular evaluator in a MBR // LISP meta-circular evaluator in a MBR
// Compatible with the original hardware // Compatible with the original hardware
// This is the friendly extended version
// This adds (FOO . BAR) support to Read
// It print errors on undefined behavior
// It can also DEFINE persistent binding
.code16 .code16
.globl _start .globl _start
@ -31,11 +36,11 @@ start: ljmp $0x7c00>>4,$begin # cs = 0x7c00 is boot address
kDefine:.asciz "DEFINE" kDefine:.asciz "DEFINE"
kQuote: .asciz "QUOTE" kQuote: .asciz "QUOTE"
kCond: .asciz "COND" kCond: .asciz "COND"
kAtom: .asciz "ATOM" # ordering matters
kCar: .asciz "CAR" # ordering matters kCar: .asciz "CAR" # ordering matters
kCdr: .asciz "CDR" # ordering matters 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" # ordering matters
kAtom: .asciz "ATOM" # needs to be last
GetToken: # GetToken():al GetToken: # GetToken():al
mov %cx,%di mov %cx,%di
@ -45,8 +50,6 @@ GetToken: # GetToken():al
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
je 4f
cmp $' ',%al cmp $' ',%al
jbe 1b jbe 1b
cmp $')',%al cmp $')',%al
@ -56,8 +59,6 @@ GetToken: # GetToken():al
3: mov %bh,(%di) # bh is zero 3: mov %bh,(%di) # bh is zero
xchg %si,%ax xchg %si,%ax
ret ret
4: dec %di
jmp 2b
.PrintList: .PrintList:
mov $'(',%al mov $'(',%al
@ -122,16 +123,30 @@ PutChar:mov $0x0e,%ah # prints CP-437
int $0x10 # vidya service int $0x10 # vidya service
pop %bp # scroll up bug pop %bp # scroll up bug
cmp $'\r',%al # don't clobber cmp $'\r',%al # don't clobber
jne 1f # look xchg ret jne .RetDx # look xchg ret
mov $'\n',%al mov $'\n',%al
jmp PutChar jmp PutChar
1: xchg %dx,%ax .RetDx: xchg %dx,%ax
ret ret
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Gc: cmp %dx,%di # Gc(x:di,A:dx,B:si):ax
jb .RetDi # we assume immutable cells
push (%bx,%di) # mark prevents negative gc
mov (%di),%di
call Gc
pop %di
push %ax
call Gc
pop %di
call Cons
sub %si,%ax # ax -= C - B
add %dx,%ax
ret
Evlis: test %di,%di # Evlis(m:di,a:dx):ax Evlis: test %di,%di # Evlis(m:di,a:dx):ax
jz 1f # jump if nil jz .RetDi # jump if nil
push (%bx,%di) # save 1 Cdr(m) push (%bx,%di) # save 1 Cdr(m)
mov (%di),%ax mov (%di),%ax
call Eval call Eval
@ -145,36 +160,27 @@ Cons: xchg %di,%cx # Cons(m:di,a:ax):ax
mov %cx,(%di) # must preserve si mov %cx,(%di) # must preserve si
mov %ax,(%bx,%di) mov %ax,(%bx,%di)
lea 4(%di),%cx lea 4(%di),%cx
1: xchg %di,%ax .RetDi: xchg %di,%ax
ret
Gc: cmp %dx,%di # Gc(x:di,A:dx,B:si):ax
jb 1b # we assume immutable cells
push (%bx,%di) # mark prevents negative gc
mov (%di),%di
call Gc
pop %di
push %ax
call Gc
pop %di
call Cons
sub %si,%ax # ax -= C - B
add %dx,%ax
ret ret
GetList:call GetToken GetList:call GetToken
cmp $')',%al cmp $')',%al
je .retF je .retF
cmp $'.',%al # FRIENDLY FEATURE
je 1f # CONS DOT LITERAL
call GetObject call GetObject
push %ax # popped by xCons push %ax # popped by xCons
call GetList call GetList
jmp xCons jmp xCons
1: call Read
push %ax
call GetList
pop %ax
ret
.dflt1: push %si # save x .resolv:push %si
call Eval call Eval # do (fn si) ((λ ...) si)
pop %si # restore x pop %si
# jmp Apply
Apply: test %ax,%ax # Apply(fn:ax,x:si:a:dx):ax Apply: test %ax,%ax # Apply(fn:ax,x:si:a:dx):ax
jns .switch # jump if atom jns .switch # jump if atom
xchg %ax,%di # di = fn xchg %ax,%di # di = fn
@ -194,31 +200,32 @@ Pairlis:test %di,%di # Pairlis(x:di,y:si,a:dx):dx
xchg %ax,%dx # a = new list xchg %ax,%dx # a = new list
pop %di # grab Cdr(x) pop %di # grab Cdr(x)
jmp Pairlis jmp Pairlis
.switch:cmp $kEq,%ax # eq is last builtin atom .switch:cmp $kAtom,%ax # eq is last builtin atom
ja .dflt1 # ah is zero if not above ja .resolv # ah is zero if not above
mov (%si),%di # di = Car(x) mov (%si),%di # di = Car(x)
je .ifAtom
cmp $kCons,%ax
jae .ifCons
test %di,%di # FRIENDLY FEATURE
jns .retF # CAR/CDR(NIL)NIL
.ifCar: cmp $kCar,%al .ifCar: cmp $kCar,%al
je Car je Car
.ifCdr: cmp $kCdr,%al .ifCdr: jmp Cdr
je Cdr .ifCons:mov (%bx,%si),%si # si = Cdr(x)
.ifAtom:cmp $kAtom,%al
jne .ifCons
test %di,%di # test if atom
jns .retT
.retF: xor %ax,%ax # ax = nil
ret
.ifCons:cmp $kCons,%al
mov (%bx,%si),%si # si = Cdr(x)
lodsw # si = Cadr(x) lodsw # si = Cadr(x)
je Cons je Cons
.isEq: xor %di,%ax # we know for certain it's eq .isEq: xor %di,%ax # we know for certain it's eq
jne .retF jne .retF
.retT: mov $kT,%al .retT: mov $kT,%al
ret ret
.ifAtom:test %di,%di # test if atom
jns .retT
.retF: xor %ax,%ax # ax = nil
ret
Assoc: mov %dx,%si # Assoc(x:ax,y:dx):ax Assoc: mov %dx,%si # Assoc(x:ax,y:dx):ax
1: test %si,%si 1: test %si,%si # FRIENDLY FEATURE
jns Undef jns Undef # PRINT ?X IF XDX
mov (%si),%di mov (%si),%di
mov (%bx,%si),%si mov (%bx,%si),%si
scasw scasw
@ -228,7 +235,7 @@ Cadr: mov (%bx,%di),%di # contents of decrement register
.byte 0x3C # cmp §scasw,%al (nop next byte) .byte 0x3C # cmp §scasw,%al (nop next byte)
Cdr: scasw # increments our data index by 2 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 ret
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
@ -281,8 +288,8 @@ Read: call GetToken
call GetObject call GetObject
ret ret
Define: call Read Define: call Read # FRIENDLY FEATURE
push %ax push %ax # DEFINE NAME SEXP
call Read call Read
pop %di pop %di
call Cons call Cons