-
Notifications
You must be signed in to change notification settings - Fork 56
Eval
What is stated as undefined in John McCarthy's paper is left as is, period.
(CAR NIL)
... the result is undefined ...
(COND (NIL NIL))
... may never decide what to answer ...
It is the user responsibility to feed valid input to the interpreter. Our sectorlisp is not able to emit errors or check for border cases.
#define ATOM 0
#define CONS 1
#define OBJECT(t, v) (((v)<<1)|(t))
#define VALUE(x) ((x) >> 1)
#define NIL 0
Testing for zero or NULL value in C/C++ yields shorter machine code
test %ax,%ax
jnz ...
than comparing explicitly with the zero value
cmp $0, %ax
jne ...
the compiler generated code to get the value of Cdr(di)
is
Car:
and $-2,%di
mov (%di),%ax
ret
but, as we are now quite sure that we never pass an ATOM
to Car()
or Cdr()
this can be simplified as
Car:
dec %di
mov (%di),%ax
ret
It there a relation to the "content of the decrement register" on an IBM 704 ? Who knows ?
#define ATOM 1
#define CONS 0
...
#define NIL (ATOM | 0)
In this case, every CONS
cell is the address of that cell.
The code becomes quite easy to understand.
Cadr:
mov 2(%di),%di
mov (%di),%ax
ret
Comparing for against the NIL
value is now required.
The code size gain overall is worth the effort.
The code generated by the compiler with -Os
and the realify.sh
wrapper is
not well optimized for size. By manually reordering the evaluation of
the statements we can gain some precious bits. In C/C++, the evaluation order
of the arguments to a function is unspecified, I don't know for LISP.
WORD Bind(WORD v, WORD a, WORD e) { // evlis + pair w/ dot notation
if (v == NIL)
return e;
WORD t1 = Eval(Car(a), e);
WORD t2 = Cons(Car(v), t1);
WORD t3 = Bind(Cdr(v), Cdr(a), e);
return Cons(t2, t3);
}
can be transcribed as
Bind: # Bind(v:di,a:si,e:dx):ax
cmp $NIL,%di
je 1f
push 2(%di) # 1 save Cdr(v)
push 2(%si) # 2 save Cdr(a)
push %dx # 3 save e
push (%di) # 4 save Car(v)
mov (%si),%ax # ax = Car(a)
xchg %dx,%si
call Eval
xchg %ax,%si
pop %di # 4 restore di = Car(v)
call Cons
pop %dx # 3 restore e
pop %si # 2 restore Cdr(a)
pop %di # 1 restore Cdr(v)
push %ax # 5 save
call Bind
xchg %ax,%si
pop %di # 5 restore
jmp Cons
1:xchg %dx,%ax
ret
By searching a way to save more bytes, I found this page: What is the most minimal implementation of Lisp available? where pbewig commented:
The canonical implementation of Lisp is on page 13 of John McCarthy's book; everything else is a library function.
This refers to the LISP 1.5 Programmer's Manual.
This is the source for the new Eval()
function, with some adaptations
like in Assoc()
...
It is possible to run the LISP 1.5 code with the SIMH simulator for the IBM 7094 on your PC.