mirror of
https://github.com/samsonjs/sectorlisp.git
synced 2026-04-27 14:57:41 +00:00
Make DEFINE more like Scheme
This commit is contained in:
parent
a25d58bddd
commit
f6e8f51307
2 changed files with 178 additions and 85 deletions
218
lisp.js
218
lisp.js
|
|
@ -26,19 +26,24 @@ exit
|
||||||
#define function
|
#define function
|
||||||
#define Null 16384
|
#define Null 16384
|
||||||
var M[Null * 2];
|
var M[Null * 2];
|
||||||
|
var (*funcall)();
|
||||||
jmp_buf undefined;
|
jmp_buf undefined;
|
||||||
//`
|
//`
|
||||||
|
|
||||||
var cx, dx, lo, kT, kEq, kCar, kCdr, kCond, kAtom, kCons, kQuote, kDefine;
|
var cx, dx, depth, panic;
|
||||||
|
var cHeap, cGets, cSets, cPrints;
|
||||||
function Set(i, x) {
|
var kT, kEq, kCar, kCdr, kCond, kAtom, kCons, kQuote, kDefine;
|
||||||
M[Null + i] = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get(i) {
|
function Get(i) {
|
||||||
|
++cGets;
|
||||||
return M[Null + i];
|
return M[Null + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Set(i, x) {
|
||||||
|
++cSets;
|
||||||
|
M[Null + i] = x;
|
||||||
|
}
|
||||||
|
|
||||||
function Car(x) {
|
function Car(x) {
|
||||||
if (x > 0) Throw(List(kCar, x));
|
if (x > 0) Throw(List(kCar, x));
|
||||||
return x ? Get(x) : +0;
|
return x ? Get(x) : +0;
|
||||||
|
|
@ -52,7 +57,7 @@ function Cdr(x) {
|
||||||
function Cons(car, cdr) {
|
function Cons(car, cdr) {
|
||||||
Set(--cx, cdr);
|
Set(--cx, cdr);
|
||||||
Set(--cx, car);
|
Set(--cx, car);
|
||||||
if (cx < lo) lo = cx;
|
if (cx < cHeap) cHeap = cx;
|
||||||
return cx;
|
return cx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,11 +82,6 @@ function ReadAtom(h) {
|
||||||
Hash(h, c) - Hash(0, Ord('N')));
|
Hash(h, c) - Hash(0, Ord('N')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function PrintAtom(x) {
|
|
||||||
do PrintChar(Get(x));
|
|
||||||
while ((x = Get(x + 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function ReadList() {
|
function ReadList() {
|
||||||
var x;
|
var x;
|
||||||
if ((x = Read()) > 0) {
|
if ((x = Read()) > 0) {
|
||||||
|
|
@ -100,17 +100,33 @@ function ReadObject(t) {
|
||||||
return ReadList();
|
return ReadList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Read() {
|
||||||
|
return ReadObject(ReadAtom(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
function PrintAtom(x) {
|
||||||
|
do PrintChar(Get(x));
|
||||||
|
while ((x = Get(x + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
function PrintList(x) {
|
function PrintList(x) {
|
||||||
PrintChar(Ord('('));
|
PrintChar(Ord('('));
|
||||||
if (x < 0) {
|
if (x < 0) {
|
||||||
PrintObject(Car(x));
|
Print(Car(x));
|
||||||
while ((x = Cdr(x))) {
|
while ((x = Cdr(x))) {
|
||||||
|
if (panic && cPrints > panic) {
|
||||||
|
PrintChar(Ord(' '));
|
||||||
|
PrintChar(0x2026);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (x < 0) {
|
if (x < 0) {
|
||||||
PrintChar(Ord(' '));
|
PrintChar(Ord(' '));
|
||||||
PrintObject(Car(x));
|
Print(Car(x));
|
||||||
} else {
|
} else {
|
||||||
PrintChar(0x2219);
|
PrintChar(Ord(' '));
|
||||||
PrintObject(x);
|
PrintChar(Ord('.'));
|
||||||
|
PrintChar(Ord(' '));
|
||||||
|
Print(x);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -118,7 +134,8 @@ function PrintList(x) {
|
||||||
PrintChar(Ord(')'));
|
PrintChar(Ord(')'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function PrintObject(x) {
|
function Print(x) {
|
||||||
|
++cPrints;
|
||||||
if (1./x < 0) {
|
if (1./x < 0) {
|
||||||
PrintList(x);
|
PrintList(x);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -126,13 +143,12 @@ function PrintObject(x) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Print(e) {
|
function List(x, y) {
|
||||||
PrintObject(e);
|
return Cons(x, Cons(y, 0));
|
||||||
PrintChar(Ord('\n'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Read() {
|
function Define(A, x, a) {
|
||||||
return ReadObject(ReadAtom(0));
|
return Gc(A, Cons(x, Remove(Car(x), a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function Remove(x, y) {
|
function Remove(x, y) {
|
||||||
|
|
@ -141,14 +157,6 @@ function Remove(x, y) {
|
||||||
return Cons(Car(y), Remove(x, Cdr(y)));
|
return Cons(Car(y), Remove(x, Cdr(y)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function List(x, y) {
|
|
||||||
return Cons(x, Cons(y, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
function Define(x, y) {
|
|
||||||
return Cons(Cons(x, Read()), Remove(x, y));
|
|
||||||
}
|
|
||||||
|
|
||||||
function Gc(A, x) {
|
function Gc(A, x) {
|
||||||
var C, B = cx;
|
var C, B = cx;
|
||||||
x = Copy(x, A, A - B), C = cx;
|
x = Copy(x, A, A - B), C = cx;
|
||||||
|
|
@ -167,7 +175,6 @@ function Evlis(m, a) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function Pairlis(x, y, a) {
|
function Pairlis(x, y, a) {
|
||||||
if (!!x ^ !!y) Throw(List(x, y));
|
|
||||||
return x ? Cons(Cons(Car(x), Car(y)),
|
return x ? Cons(Cons(Car(x), Car(y)),
|
||||||
Pairlis(Cdr(x), Cdr(y), a)) : a;
|
Pairlis(Cdr(x), Cdr(y), a)) : a;
|
||||||
}
|
}
|
||||||
|
|
@ -184,7 +191,7 @@ function Evcon(c, a) {
|
||||||
} else if (Cdr(c)) {
|
} else if (Cdr(c)) {
|
||||||
return Evcon(Cdr(c), a);
|
return Evcon(Cdr(c), a);
|
||||||
} else {
|
} else {
|
||||||
Throw(c);
|
Throw(Cons(kCond, c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,16 +202,61 @@ function 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));
|
||||||
return Apply(Assoc(f, a), x, a);
|
return funcall(f, Assoc(f, a), x, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Eval(e, a) {
|
function Eval(e, a) {
|
||||||
var A = cx;
|
|
||||||
if (!e) return e;
|
if (!e) return e;
|
||||||
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));
|
||||||
if (Car(e) == kCond) return Gc(A, Evcon(Cdr(e), a));
|
if (Car(e) == kCond) return Evcon(Cdr(e), a);
|
||||||
return Gc(A, Apply(Car(e), Evlis(Cdr(e), a), a));
|
return Apply(Car(e), Evlis(Cdr(e), a), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Funcall(f, l, x, a) {
|
||||||
|
var A = cx;
|
||||||
|
return Gc(A, Apply(l, x, a));
|
||||||
|
}
|
||||||
|
|
||||||
|
function Funtrace(f, l, x, a) {
|
||||||
|
var y, i, A = cx;
|
||||||
|
Indent(depth);
|
||||||
|
Print(f);
|
||||||
|
Print(x);
|
||||||
|
PrintChar(Ord('\n'));
|
||||||
|
depth += 2;
|
||||||
|
y = Funcall(f, l, x, a);
|
||||||
|
depth -= 2;
|
||||||
|
Indent(depth);
|
||||||
|
Print(f);
|
||||||
|
Print(x);
|
||||||
|
PrintChar(Ord(' '));
|
||||||
|
PrintChar(0x2192);
|
||||||
|
PrintChar(Ord(' '));
|
||||||
|
Print(y);
|
||||||
|
PrintChar(Ord('\n'));
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Indent(i) {
|
||||||
|
if (!i) return;
|
||||||
|
PrintChar(Ord(' '));
|
||||||
|
Indent(i - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Dump(a) {
|
||||||
|
if (!a) return;
|
||||||
|
Dump(Cdr(a));
|
||||||
|
PrintChar(Ord('('));
|
||||||
|
Print(kDefine);
|
||||||
|
PrintChar(Ord(' '));
|
||||||
|
Print(Car(Car(a)));
|
||||||
|
PrintChar(Ord(' '));
|
||||||
|
PrintChar(Ord('.'));
|
||||||
|
PrintChar(Ord(' '));
|
||||||
|
Print(Cdr(Car(a)));
|
||||||
|
PrintChar(Ord(')'));
|
||||||
|
PrintChar(Ord('\n'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function LoadBuiltins() {
|
function LoadBuiltins() {
|
||||||
|
|
@ -267,17 +319,24 @@ ReadChar() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
main(argc, argv)
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
var x, a, A;
|
var x, a, A;
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
bestlineSetXlatCallback(bestlineUppercase);
|
bestlineSetXlatCallback(bestlineUppercase);
|
||||||
|
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 't') {
|
||||||
|
funcall = Funtrace;
|
||||||
|
} else {
|
||||||
|
funcall = Funcall;
|
||||||
|
}
|
||||||
LoadBuiltins();
|
LoadBuiltins();
|
||||||
for (a = 0;;) {
|
for (a = 0;;) {
|
||||||
A = cx;
|
A = cx;
|
||||||
if (!(x = setjmp(undefined))) {
|
if (!(x = setjmp(undefined))) {
|
||||||
x = Read();
|
x = Read();
|
||||||
if (x == kDefine) {
|
if (x < 0 && Car(x) == kDefine) {
|
||||||
a = Gc(0, Define(Read(), a));
|
a = Define(0, Cdr(x), a);
|
||||||
SaveMachine(a);
|
SaveMachine(a);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -287,6 +346,7 @@ main() {
|
||||||
PrintChar('?');
|
PrintChar('?');
|
||||||
}
|
}
|
||||||
Print(x);
|
Print(x);
|
||||||
|
PrintChar('\n');
|
||||||
Gc(A, 0);
|
Gc(A, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -296,8 +356,8 @@ main() {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// JavaScript Specific Code for https://justine.lol/
|
// JavaScript Specific Code for https://justine.lol/
|
||||||
|
|
||||||
var a, code, index, output, M, Null;
|
var a, code, index, output, funcall, M, Null;
|
||||||
var eInput, eOutput, eSubmit, eReset, eLoad, ePrograms;
|
var eInput, eOutput, eEval, eReset, eLoad, eTrace, ePrograms;
|
||||||
|
|
||||||
function Throw(x) {
|
function Throw(x) {
|
||||||
throw x;
|
throw x;
|
||||||
|
|
@ -311,7 +371,10 @@ function Reset() {
|
||||||
var i;
|
var i;
|
||||||
a = 0;
|
a = 0;
|
||||||
cx = 0;
|
cx = 0;
|
||||||
lo = 0;
|
cHeap = 0;
|
||||||
|
cGets = 0;
|
||||||
|
cSets = 0;
|
||||||
|
cPrints = 0;
|
||||||
Null = 16384;
|
Null = 16384;
|
||||||
M = new Array(Null * 2);
|
M = new Array(Null * 2);
|
||||||
for (i = 0; i < M.length; ++i) {
|
for (i = 0; i < M.length; ++i) {
|
||||||
|
|
@ -343,8 +406,11 @@ function ReadChar() {
|
||||||
|
|
||||||
function Lisp() {
|
function Lisp() {
|
||||||
var x, A;
|
var x, A;
|
||||||
lo = cx;
|
cGets = 0;
|
||||||
output = '';
|
cSets = 0;
|
||||||
|
cHeap = cx;
|
||||||
|
cPrints = 0;
|
||||||
|
output = "";
|
||||||
while (dx) {
|
while (dx) {
|
||||||
if (dx <= Ord(' ')) {
|
if (dx <= Ord(' ')) {
|
||||||
ReadChar();
|
ReadChar();
|
||||||
|
|
@ -352,8 +418,8 @@ function Lisp() {
|
||||||
A = cx;
|
A = cx;
|
||||||
try {
|
try {
|
||||||
x = Read();
|
x = Read();
|
||||||
if (x == kDefine) {
|
if (x < 0 && Car(x) == kDefine) {
|
||||||
a = Gc(0, Define(Read(), a));
|
a = Define(0, Cdr(x), a);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
x = Eval(x, a);
|
x = Eval(x, a);
|
||||||
|
|
@ -362,6 +428,7 @@ function Lisp() {
|
||||||
x = z;
|
x = z;
|
||||||
}
|
}
|
||||||
Print(x);
|
Print(x);
|
||||||
|
PrintChar(Ord('\n'));
|
||||||
Gc(A, 0);
|
Gc(A, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -377,21 +444,11 @@ function Load(s) {
|
||||||
index = 1;
|
index = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function OnSubmit() {
|
function OnEval() {
|
||||||
Load(eInput.value.toUpperCase());
|
Load(eInput.value.toUpperCase());
|
||||||
Lisp();
|
Lisp();
|
||||||
}
|
}
|
||||||
|
|
||||||
function Dump(a) {
|
|
||||||
if (!a) return;
|
|
||||||
Dump(Cdr(a));
|
|
||||||
output += "DEFINE ";
|
|
||||||
PrintObject(Car(Car(a)));
|
|
||||||
output += " ";
|
|
||||||
PrintObject(Cdr(Car(a)));
|
|
||||||
output += "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
function OnReset() {
|
function OnReset() {
|
||||||
output = "";
|
output = "";
|
||||||
try {
|
try {
|
||||||
|
|
@ -406,6 +463,18 @@ function OnReset() {
|
||||||
ReportUsage();
|
ReportUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function OnTrace() {
|
||||||
|
var t;
|
||||||
|
Load(eInput.value);
|
||||||
|
t = panic;
|
||||||
|
depth = 0;
|
||||||
|
panic = 10000;
|
||||||
|
funcall = Funtrace;
|
||||||
|
Lisp();
|
||||||
|
funcall = Funcall;
|
||||||
|
panic = t;
|
||||||
|
}
|
||||||
|
|
||||||
function OnLoad() {
|
function OnLoad() {
|
||||||
ePrograms.classList.toggle("show");
|
ePrograms.classList.toggle("show");
|
||||||
}
|
}
|
||||||
|
|
@ -431,7 +500,7 @@ function RestoreMachine() {
|
||||||
M = machine[0];
|
M = machine[0];
|
||||||
a = machine[1];
|
a = machine[1];
|
||||||
cx = machine[2];
|
cx = machine[2];
|
||||||
lo = cx;
|
cHeap = cx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -449,25 +518,48 @@ function Number(i) {
|
||||||
function ReportUsage() {
|
function ReportUsage() {
|
||||||
var i, c;
|
var i, c;
|
||||||
for (c = i = 0; i < Null; i += 2) {
|
for (c = i = 0; i < Null; i += 2) {
|
||||||
if (Get(i)) ++c;
|
if (M[Null + i]) ++c;
|
||||||
}
|
}
|
||||||
document.getElementById("usage").innerText =
|
document.getElementById("ops").innerText =
|
||||||
|
Number(cGets) + " gets / " +
|
||||||
|
Number(cSets) + " sets";
|
||||||
|
document.getElementById("mem").innerText =
|
||||||
Number((-cx >> 1) + c) + " / " +
|
Number((-cx >> 1) + c) + " / " +
|
||||||
Number((-lo >> 1) + c) + " / " +
|
Number((-cHeap >> 1) + c) + " / " +
|
||||||
Number(Null) + " doublewords";
|
Number(Null) + " doublewords";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Discount(f) {
|
||||||
|
return function() {
|
||||||
|
var x, g, h, s;
|
||||||
|
g = cGets;
|
||||||
|
s = cSets;
|
||||||
|
h = cHeap;
|
||||||
|
x = f.apply(this, arguments);
|
||||||
|
cHeap = h;
|
||||||
|
cSets = s;
|
||||||
|
cGets = g;
|
||||||
|
return x;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function SetUp() {
|
function SetUp() {
|
||||||
|
funcall = Funcall;
|
||||||
|
Read = Discount(Read);
|
||||||
|
Print = Discount(Print);
|
||||||
|
Define = Discount(Define);
|
||||||
eLoad = document.getElementById("load");
|
eLoad = document.getElementById("load");
|
||||||
eInput = document.getElementById("input");
|
eInput = document.getElementById("input");
|
||||||
eReset = document.getElementById("reset");
|
eReset = document.getElementById("reset");
|
||||||
|
eTrace = document.getElementById("trace");
|
||||||
eOutput = document.getElementById("output");
|
eOutput = document.getElementById("output");
|
||||||
eSubmit = document.getElementById("submit");
|
eEval = document.getElementById("eval");
|
||||||
ePrograms = document.getElementById("programs");
|
ePrograms = document.getElementById("programs");
|
||||||
window.onclick = OnWindowClick;
|
window.onclick = OnWindowClick;
|
||||||
eSubmit.onclick = OnSubmit;
|
|
||||||
eReset.onclick = OnReset;
|
|
||||||
eLoad.onclick = OnLoad;
|
eLoad.onclick = OnLoad;
|
||||||
|
eReset.onclick = OnReset;
|
||||||
|
eTrace.onclick = OnTrace;
|
||||||
|
eEval.onclick = OnEval;
|
||||||
Reset();
|
Reset();
|
||||||
RestoreMachine();
|
RestoreMachine();
|
||||||
ReportUsage();
|
ReportUsage();
|
||||||
|
|
|
||||||
45
sectorlisp.S
45
sectorlisp.S
|
|
@ -34,8 +34,8 @@ kT: .asciz "T" # add %dl,(%si) boot A:\ DL=0
|
||||||
start: ljmp $0x7c00>>4,$begin # cs = 0x7c00 is boot address
|
start: ljmp $0x7c00>>4,$begin # cs = 0x7c00 is boot address
|
||||||
.asciz ""
|
.asciz ""
|
||||||
kDefine:.asciz "DEFINE"
|
kDefine:.asciz "DEFINE"
|
||||||
kQuote: .asciz "QUOTE"
|
|
||||||
kCond: .asciz "COND"
|
kCond: .asciz "COND"
|
||||||
|
kQuote: .asciz "QUOTE"
|
||||||
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
|
||||||
|
|
@ -123,16 +123,14 @@ 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 .RetDx # look xchg ret
|
jne .retDx # look xchg ret
|
||||||
mov $'\n',%al
|
mov $'\n',%al
|
||||||
jmp PutChar
|
jmp PutChar
|
||||||
.RetDx: xchg %dx,%ax
|
|
||||||
ret
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Gc: cmp %dx,%di # Gc(x:di,A:dx,B:si):ax
|
Gc: cmp %dx,%di # Gc(x:di,A:dx,B:si):ax
|
||||||
jb .RetDi # we assume immutable cells
|
jb .retDi # we assume immutable cells
|
||||||
push (%bx,%di) # mark prevents negative gc
|
push (%bx,%di) # mark prevents negative gc
|
||||||
mov (%di),%di
|
mov (%di),%di
|
||||||
call Gc
|
call Gc
|
||||||
|
|
@ -146,7 +144,7 @@ Gc: cmp %dx,%di # Gc(x:di,A:dx,B:si):ax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
Evlis: test %di,%di # Evlis(m:di,a:dx):ax
|
Evlis: test %di,%di # Evlis(m:di,a:dx):ax
|
||||||
jz .RetDi # 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
|
||||||
|
|
@ -160,7 +158,7 @@ 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
|
||||||
.RetDi: xchg %di,%ax
|
.retDi: xchg %di,%ax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
GetList:call GetToken
|
GetList:call GetToken
|
||||||
|
|
@ -178,6 +176,9 @@ GetList:call GetToken
|
||||||
pop %ax
|
pop %ax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.retDx: xchg %dx,%ax
|
||||||
|
ret
|
||||||
|
|
||||||
.resolv:push %si
|
.resolv:push %si
|
||||||
call Eval # do (fn si) → ((λ ...) si)
|
call Eval # do (fn si) → ((λ ...) si)
|
||||||
pop %si
|
pop %si
|
||||||
|
|
@ -189,11 +190,16 @@ Apply: test %ax,%ax # Apply(fn:ax,x:si:a:dx):ax
|
||||||
mov (%di),%di # di = Cadr(fn)
|
mov (%di),%di # di = Cadr(fn)
|
||||||
Pairlis:test %di,%di # Pairlis(x:di,y:si,a:dx):dx
|
Pairlis:test %di,%di # Pairlis(x:di,y:si,a:dx):dx
|
||||||
jz .EvCadr # return if x is nil
|
jz .EvCadr # return if x is nil
|
||||||
|
xor %ax,%ax # FRIENDLY FEATURE
|
||||||
|
test %si,%si # DEFAULT NIL ARGS
|
||||||
|
jz 1f
|
||||||
lodsw # ax = Car(y)
|
lodsw # ax = Car(y)
|
||||||
push (%bx,%di) # push Cdr(x)
|
1: push (%bx,%di) # push Cdr(x)
|
||||||
mov (%di),%di # di = Car(x)
|
mov (%di),%di # di = Car(x)
|
||||||
|
test %si,%si
|
||||||
|
jz 1f
|
||||||
mov (%si),%si # si = Cdr(y)
|
mov (%si),%si # si = Cdr(y)
|
||||||
call Cons # Cons(Car(x),Car(y))
|
1: call Cons # Cons(Car(x),Car(y))
|
||||||
xchg %ax,%di
|
xchg %ax,%di
|
||||||
xchg %dx,%ax
|
xchg %dx,%ax
|
||||||
call Cons # Cons(Cons(Car(x),Car(y)),a)
|
call Cons # Cons(Cons(Car(x),Car(y)),a)
|
||||||
|
|
@ -223,6 +229,10 @@ Pairlis:test %di,%di # Pairlis(x:di,y:si,a:dx):dx
|
||||||
.retF: xor %ax,%ax # ax = nil
|
.retF: xor %ax,%ax # ax = nil
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
Define: xchg %dx,%ax
|
||||||
|
call Cons
|
||||||
|
jmp .retDx
|
||||||
|
|
||||||
Assoc: mov %dx,%si # Assoc(x:ax,y:dx):ax
|
Assoc: mov %dx,%si # Assoc(x:ax,y:dx):ax
|
||||||
1: test %si,%si # FRIENDLY FEATURE
|
1: test %si,%si # FRIENDLY FEATURE
|
||||||
jns Undef # PRINT ?X IF X∉DX
|
jns Undef # PRINT ?X IF X∉DX
|
||||||
|
|
@ -260,6 +270,7 @@ Eval: test %ax,%ax # Eval(e:ax,a:dx):ax
|
||||||
je Car
|
je Car
|
||||||
cmp $kCond,%ax
|
cmp $kCond,%ax
|
||||||
je Evcon # ABC Garbage Collector
|
je Evcon # ABC Garbage Collector
|
||||||
|
jb Define
|
||||||
push %dx # save a
|
push %dx # save a
|
||||||
push %cx # save A
|
push %cx # save A
|
||||||
push %ax
|
push %ax
|
||||||
|
|
@ -288,17 +299,6 @@ Read: call GetToken
|
||||||
call GetObject
|
call GetObject
|
||||||
ret
|
ret
|
||||||
|
|
||||||
Define: call Read # FRIENDLY FEATURE
|
|
||||||
push %ax # DEFINE NAME SEXP
|
|
||||||
call Read
|
|
||||||
pop %di
|
|
||||||
call Cons
|
|
||||||
xchg %ax,%di
|
|
||||||
xchg %bp,%ax
|
|
||||||
call Cons
|
|
||||||
xchg %ax,%bp
|
|
||||||
jmp main
|
|
||||||
|
|
||||||
begin: mov $0x8000,%sp
|
begin: mov $0x8000,%sp
|
||||||
push %cs
|
push %cs
|
||||||
pop %ds
|
pop %ds
|
||||||
|
|
@ -311,10 +311,11 @@ begin: mov $0x8000,%sp
|
||||||
xor %bp,%bp
|
xor %bp,%bp
|
||||||
main: xor %dx,%dx
|
main: xor %dx,%dx
|
||||||
call Read
|
call Read
|
||||||
cmp $kDefine,%ax
|
|
||||||
je Define
|
|
||||||
mov %bp,%dx
|
mov %bp,%dx
|
||||||
call Eval
|
call Eval
|
||||||
|
mov %dx,%bp
|
||||||
|
cmp $kDefine,%ax
|
||||||
|
je main
|
||||||
Catch: xchg %ax,%si
|
Catch: xchg %ax,%si
|
||||||
call PrintObject
|
call PrintObject
|
||||||
mov $'\r',%al
|
mov $'\r',%al
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue