(original) (raw)
!*********************************************************************** !* !* LISP for EMAS !* !* Edinburgh Regional Computing Centre !* !* Updated by R.D. Eager University of Kent MCMLXXXII !* !*********************************************************************** ! ! !*********************************************************************** !* !* Constants !* !*********************************************************************** ! %constantinteger no = 0, yes = 1 %constantinteger setup = 1,instream = 2,outstream = 3 %constantinteger ssdatafiletype = 4; ! Subsystem file type %constantinteger marker = m'LISP'; ! Marker at the front of LISP machine files %constantinteger default line length = 80 ! For formatting output %constantinteger maxlevel = 15 %constantinteger long base = 256 %constantinteger long tail = 511 %constantinteger name base = 512 %constantinteger name tail = 2047 %constantinteger stack base = 1024 %constantinteger stack tail = 2047 %constantinteger short base = 2048 %constantinteger short tail = 4095 %constantinteger list base = 4096 %constantinteger list tail = x'7fff' %constantinteger atom base = 256 %constantinteger char base = 1919 %constantinteger zero base = 3072 %constantinteger pname max = 8191 %constantinteger t = 2003 %constantinteger percent = 1956 %constantinteger nil = 512 %constantinteger quote = 513 %constantinteger label = 514 %constantinteger lambda = 515 %constantinteger apval = 516 %constantinteger subr = 517 %constantinteger fsubr = 518 %constantinteger expr = 519 %constantinteger fexpr = 520 %constantinteger exit = 521 %constantinteger evln = x'8000'!522 %constantinteger stars = 523 %constantinteger error = 0 %constantinteger error1 = 1 %constantinteger error2 = 2 %constantinteger error3 = 3 %constantinteger escape = x'88',eof = x'89' %constantbyteintegerarray mask(apval:fexpr) = 3, 4!2, 2, 4!1, 1 %constantbyteintegerarray code(0:127) = %c x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'80', eof, x'80', x'80', x'80', x'80', x'80', x'80', x'80', x'21', x'22', x'23',escape, x'25', x'26', x'84', x'81', x'83', x'2a', x'2b', x'2c', x'2d', x'82',escape, x'30', x'31', x'32', x'33', x'34', x'35', x'36', x'37', x'38', x'39', x'3a', x'3b', x'3c', x'3d', x'3e', x'3f', x'84', x'41', x'42', x'43', x'44', x'45', x'46', x'47', x'48', x'49', x'4a', x'4b', x'4c', x'4d', x'4e', x'4f', x'50', x'51', x'52', x'53', x'54', x'55', x'56', x'57', x'58', x'59', x'5a', x'85', x'5c', x'87', x'5e', x'5f', x'60', x'61', x'62', x'63', x'64', x'65', x'66', x'67', x'68', x'69', x'6a', x'6b', x'6c', x'6d', x'6e', x'6f', x'70', x'71', x'72', x'73', x'74', x'75', x'76', x'77', x'78', x'79', x'7a', x'7b', x'7c', x'7d', x'7e', x'7f' %constantstring(1) snl = " " %constantstring(1)%array charx(0:7) = %c " ", "(", ".", ")", "'", "[", " ", "]" ! ! !*********************************************************************** !* !* Record and array formats !* !*********************************************************************** ! %recordformat atom cell(%halfinteger bind,prop,func,%byteinteger form, %stringname pname) %recordformat lisp cell(%halfinteger car,cdr) %recordformat lispinfo(%integer dataend,datastart,filesize,filetype, sum,datetime,format,records,marker,const, long head,pname space,pname base,pname head,name, name head,stack,global,list,list head,list count, line length) %recordformat rf(%integer conad,filetype,datastart,dataend) %recordformat stack frame(%halfinteger back,bind,link) ! %ownintegerarrayformat constf(long base:long tail) %ownrecord(stack frame)%arrayformat stackf(stack base:stack tail) %ownrecord(lisp cell)%arrayformat listf(0:list tail) %ownrecord(atom cell)%arrayformat namef(name base:name tail) %ownbyteintegerarrayformat pnamef(0:pname max) ! ! !*********************************************************************** !* !* Subsystem references !* !*********************************************************************** ! %systemroutinespec connect(%string(31) file,%integer mode,hole, prot,%record(rf)%name r,%integername flag) %systemroutinespec define(%integer chan,%string(31) iden, %integername afd,flag) %systemstringfunctionspec failuremessage(%integer mess) %systemstringfunctionspec itos(%integer n) %systemroutinespec outfile(%string(31) file,%integer size,hole, prot,%integername conad,flag) %externalroutinespec prompt(%string(255) s) %systemroutinespec setfname(%string(63) s) %externalroutinespec set return code(%integer i) ! ! !*********************************************************************** !* !* Own variables !* !*********************************************************************** ! %owninteger auxp; ! Auxiliary stack pointer %owninteger errval,infile,outf %owninteger char,reset,front,pname tail,progflag,local,nillist %ownintegername list count,list head,long head,pname head,global,name head %ownintegername line length %ownstring(255) pmpt,plabel,line,clause,pspaces %ownintegerarrayname const %ownrecord(lispinfo)%name lispfile %ownrecord(atom cell)%arrayname name %ownrecord(lisp cell)%arrayname list %ownrecord(stack frame)%arrayname stack %ownintegerarray auxs(0:1023); ! Auxiliary stack %ownbyteintegerarray blanks(0:255) = ' '(*) %ownstring(5) errors = "Error" ! ! !*********************************************************************** !* !* Forward references !* !*********************************************************************** ! %integerfunctionspec eval(%integer form) %integerfunctionspec func(%record(atom cell)%name atom,%integer args) %routinespec loop(%string(255) pmpt,%integer term) ! ! !*********************************************************************** !* !* Miscellaneous routines !* !*********************************************************************** ! %integerfunction push(%integer index) ! Adds the item 'index' to the auxiliary stack, yielding 'index' as the ! result. auxs(auxp) = index auxp = auxp + 1 %result = index %end; ! of push ! !----------------------------------------------------------------------- ! %integerfunction pop(%integer index) ! Removes an item from the auxiliary stack, yielding that item as its ! result. auxp = auxp - 1 %result = index %end; ! of pop ! !----------------------------------------------------------------------- ! %stringfunction pname(%integer index) ! Yields the printable form of the atom described by 'index'. %if index >= long base %then %start %if index >= name base %then %start %result = itos(index-zero base) %if index >= short base %result = tostring(index-char base) %if index >= char base %result = name(index)_p name %finish %else %result = itos(const(index)) %finish %else %result = errors %end; ! of pname ! !----------------------------------------------------------------------- ! %string(255)%function pack(%integer index) %integer car %string(255) packed ! packed = "" %while index >= list base %cycle; ! cdr down the list car = list(index)_car index = list(index)_cdr %if car >= list base %then packed <- packed.pack(car) %else %c packed <- packed.pname(car) %repeat packed <- packed.pname(index) %unless index = nil %result = packed %end; ! of pack ! !----------------------------------------------------------------------- ! %integerfunction numberp(%integername value) ! Performs the LISP function 'numberp', on the item described by ! 'value'. value = const(value) %and %result = t %if long base <= value <= long tail value = value - zero base %and %result = t %if short base <= value <= short tail %result = nil %end; ! of numberp ! !----------------------------------------------------------------------- ! %integerfunction equal(%integer arg1,arg2) ! Performs the LISP function 'equal' on the two items described by ! 'arg1' and 'arg2'. %if arg1 = arg2 %or (numberp(arg1) = t = numberp(arg2) %and %c arg1 = arg2) %or(arg1 >= list base %and arg2 >= list base %and %c equal(list(arg1)_car,list(arg2)_car) = t %and %c equal(list(arg1)_cdr,list(arg2)_cdr) = t) %then %result = t %result = nil %end; ! of equal ! !----------------------------------------------------------------------- ! %integerfunction mnumb(%integer value) ! Allocates storage for a number (if necessary), and yields its value as ! the result. %integer index ! %result = value + zero base %if -1024 <= value <= 1023 %unless long base <= long head <= long tail %then %start printstring(snl."Atom error: No more room for long constants".snl) %result = error %finish index = long base %while index # long head %cycle %result = index %if const(index) = value index = index + 1 %repeat long head = long head + 1 const(index) = value %result = index %end; ! of mnumb ! !----------------------------------------------------------------------- ! %integerfunction matom(%string(255) pname) ! Allocates storage for the name 'pname', and yields its index as the ! result. Uses an existing copy if it is already in the name table. %integer index %record(atom cell)%name atom ! %if length(pname) = 1 %then %start %result = char base + (charno(pname,1) & x'7f') %finish %for index = name base,1,name head - 1 %cycle %result = index %if pname = name(index)_pname %repeat %unless name head < char base %and %c pname head + length(pname) + 1 < pname tail %then %start printstring(snl."Atom error: No more space for names".snl) %result = error %finish atom == name(name head) atom_pname == string(pname head) pname head = pname head + length(pname) + 1 atom_pname = pname index = name head name head = name head + 1 %result = index %end; ! of matom ! !----------------------------------------------------------------------- ! %integerfunction ratom ! Reads and allocates space for an atom, after classifying it. Yields ! the index of the item read. %integer type,sign,value,tsign %string(255) pname ! type = 0 value = 0 sign = +1 tsign = +1 pname = "" %cycle %if char & x'80' # 0 %then %start; ! Separator %if pname # "" %then %start; ! Terminator %result = matom(pname) %if type < 2 ! Symbolic atom %result = mnumb(value); ! Numeric atom %finish value = char & x'7f' char = x'80' %and %result = value %if char # x'80' ! Break character %finish %else %start; ! Normal character %if 0 <= type <= 2 %then %start; ! Possibly numeric %if '0' <= char <= '9' %then %start ! Yes for now type = 2 %if sign = -1 %then %start value = -value sign = +1 %finish value = value*10 + (char-'0')*tsign %finish %else %start; ! Possibly signed %if type = 0 %and (char = '+' %or char = '-') %then %start type = 1 %if char = '-' %then %start sign = -1 tsign = -1 %finish %finish %else type = -1; ! Not numeric %finish %finish pname <- pname.tostring(char); ! Always symbolic %finish %cycle readch(char); ! Next symbol char = code(char & x'7f') selectinput(0) %if char = eof %repeat %until char # eof readch(char) %and type = -1 %if char = escape %repeat %end; ! of ratom ! !----------------------------------------------------------------------- ! %routine printchars(%string(255) phrase) %integer adjustment ! phrase <- plabel.phrase %and plabel = "" %if plabel # "" %if phrase = "" %then %start %if length(line) + length(clause) < line length %then %start printstring(line.clause.snl) %finish %else printstring(line.snl.pspaces.clause.snl) line = "" clause = "" %finish %if length(pspaces)+length(clause)+length(phrase) >= line length %then %start adjustment = length(pspaces) - length(phrase) %if adjustment < 0 %then %start printstring(line.snl) %if line # "" printstring(pspaces.clause.snl) line = "" clause = "" %finish %else length(pspaces) = adjustment %finish clause = clause.phrase; ! Append phrase %end; ! of printchars ! !----------------------------------------------------------------------- ! %routine print(%integer index) %integer level,clevel,adjustment,i %byteinteger r flag,c count,r count,line 1 %integerarray line pos(0:maxlevel) ! ! %string(255)%function padding %integer index,count ! %if level < maxlevel + 1 %then index = level %else index = maxlevel count = line pos(index) - length(plabel) count = line length %if count > line length count = 0 %if count < 0 blanks(0) = count %result = string(addr(blanks(0))) %end; ! of padding ! ! %routine lparen %integer i ! %if level <= maxlevel %and line pos(level) = 0 %then %start line pos(level) = length(line) + length(clause) %finish c count = 10 %if 50 < length(line) > line pos(level) %or %c length(clause) > 30 %or (length(clause) > 20 %and length(line) > 20) %if r flag > 0 %or c count >= 10 %then %start ! Start of new phrase %if length(line) + length(clause) > line length %or %c length(line) - length(pspaces) > 25 %or c count >= 2 %then %start ! ! Adjust the position of the left parenthesis at this level ! %if level > clevel %then %start adjustment = length(line) - length(pspaces) %for i = clevel + 1,1,level %cycle line pos(i) = line pos(i) - adjustment %repeat %finish printstring(line.snl) %if line # "" line = pspaces.clause line 1 = 0 %finish %else line = line.clause c count = r count clause = "" clevel = level pspaces = padding %finish level = level + 1 %if line 1 = 0 r flag = 0 r count = 0 print chars("(") %end; ! of lparen ! ! %routine rparen print chars(")") line pos(level) = 0 %if 0 < level <= maxlevel level = level - 1 %if level > 0 r flag = 1 rcount = rcount + 1 %end; ! of rparen ! !----------------------------------------------------------------------- ! %routine print sexp(%integer index) ! Prints out the S-expression described by 'index'. This may be a list ! cell (and therefore something fairly complex) or it may just be an ! atom. %integer car,cdr %record(lisp cell)%name cell ! %if index >= list base %then %start; ! List cell cell == list(index) car = cell_car cdr = cell_cdr; ! Map onto cell lparen print sexp(car); ! Start of list %if cdr >= list base %then %start %cycle; ! Print tail index = cdr cell == list(index) car = cell_car cdr = cell_cdr print chars(" ") %if plabel = "" ! Print space %exit %if cdr < list base; ! End of list %if car = nil %then %start; ! Print empty list lparen print chars(" ") rparen %finish %else print sexp(car); ! Print car %repeat print sexp(car) %finish printchars(" . ") %and printchars(pname(cdr)) %and rflag = 0 %if cdr # nil r paren; ! Close list %finish %else %start; ! Atom %if r flag = 1 %then %start r flag = 2 plabel <- pname(index)." " %finish %else %start print chars(pname(index)) r flag = 0 %finish %finish %end; ! of print sexp ! ! line 1 = 1 r flag = 0 c count = 0 r count = 0 pspaces = "" level = 0 clevel = 0 line pos(0) = 4; ! Initial indentation line pos(i) = 0 %for i = 1,1,maxlevel print sexp(index) %end; ! of print ! !----------------------------------------------------------------------- ! %routine mark(%integer index) ! Marks the chain of cells headed by 'index', by adding bit x'8000'. ! Used by the garbage collector. %halfintegername car ! %while index >= list base %and list(index)_car >= 0 %cycle car == list(index)_car index = list(index)_cdr car <- car!x'8000' mark(car & x'7fff') %if car & x'7fff' >= list base %repeat %end; ! of mark ! !----------------------------------------------------------------------- ! %routine garbage collect %record(lisp cell)%name cell %integer i ! mark(name(i)_prop) %for i = name base,1,name head - 1 mark(name(i)_prop) %for i = char base,1,name tail mark(stack(i)_bind) %for i = stack base,1,front mark(stack(i)_bind) %for i = global,1,stack tail %if auxp > 0 %then %start mark(auxs(i)) %for i = 0,1,auxp - 1 %finish list count = 0 list head = 0 %for i = list base,1,list tail %cycle cell == list(i) %if cell_car < 0 %then cell_car <- cell_car & x'7fff' %else %start list count = list count + 1 cell_car = list head list head = i %finish %repeat %end; ! of garbage collect ! !----------------------------------------------------------------------- ! %integerfunction cons(%integer car,cdr) ! Performs the LISP function 'cons' on the items described by 'car' and ! 'cdr'. Yields the index of the cell constructed. %integer index,dummy %record(lisp cell)%name cell ! %if list count <= 100 %or list head < list base %then %start dummy = push(car); ! Ensure these lists are not garbage collected dummy = push(cdr) auxp = auxp + 2 garbage collect auxp = auxp - 2 %if list count <= 1000 %then %start printstring(snl."Lisp note: Less than 1000 free cells remaining - free something".snl) loop("Free:",percent) %finish %finish %if list head < list base %then %start printstring(snl."Lisp error: No more free space left".snl) %result = error %finish list count = list count - 1 index = list head cell == list(index) list head = cell_car cell_car = car cell_cdr = cdr %result = index %end; ! of cons ! !----------------------------------------------------------------------- ! %integerfunction reverse(%integer curr) %integer last %record(lisp cell)%name cell ! last = nil %while curr >= list base %cycle cell == list(curr) last = cons(cell_car,last) curr = cell_cdr %repeat %result = last %end; ! of reverse ! !----------------------------------------------------------------------- ! %integerfunction read sexp(%string(255) pmpt) %integerfunctionspec cell(%integer car) %integerfunctionspec head %integerfunctionspec tail %integer colapse ! ! %integerfunction cell(%integer car) %integer cdr ! %if car >= atom base %then %start; ! Head not in error auxs(auxp) = car auxp = auxp + 1 cdr = tail auxp = auxp - 1 %result = cons(car,cdr) %if cdr >= atom base ! Tail not in error %finish %result = error %end; ! of cell ! ! %integerfunction head %integer temp,res %switch sw(0:3) ! temp = ratom %result = temp %if temp >= atom base; ! Atom -> sw(temp & 3); ! Handle by case ! sw(0): ! " %result = cons(quote,cons(head,nil)) ! sw(1): ! '(' or '[' res = tail colapse = no %if temp >= 4; ! '[' %result = res ! sw(2): sw(3): ! '.' or ')' printstring(snl."Read error: S-expression begins with a ".charx(temp).snl) %result = error %end; ! of head ! ! %integerfunction tail %integer temp,res %switch sw(0:3) ! %result = nil %if colapse = yes; ! Collapse back to '[' temp = ratom; ! Separator %result = cell(temp) %if temp >= atom base ! Atom -> sw(temp & 3); ! Handle by case ! sw(0): %result = cell(cons(quote,cons(head,nil))) ! sw(1): ! '(' or '[' res = tail colapse = no %if temp >= 4; ! '[' %result = cell(res) ! sw(2): ! '.' temp = head %result = temp %if tail = nil printstring(snl."Read error: Dotted pair not enclosed in brackets".snl) %result = error ! sw(3): ! ')' or ']' colapse = yes %if temp >= 4 %result = nil %end; ! of tail ! ! colapse = no prompt(pmpt) %result = head %end; ! of read sexp ! !----------------------------------------------------------------------- ! %routine loop(%string(255) pmpt,%integer term) %integer value ! %cycle reset = 0 value = eval(read sexp(pmpt)) %exit %if value = term print(value) %and print chars("") %unless reset # 0 %repeat %end; ! of loop ! !----------------------------------------------------------------------- ! %integerfunction pcons(%integer car,cdr) auxp = auxp - 1 %result = cons(car,cdr) %end; ! of pcons ! !----------------------------------------------------------------------- ! %routine xprint(%string(255) mess,%integer form) %string(255) save ! save = line line = mess print(form) print chars("") line = save %end; ! of xprint ! !----------------------------------------------------------------------- ! %routine bind(%integer symb,entry,bind) %record(atom cell)%name atom %record(stack frame)%name frame ! %unless name base <= symb < list base %then %start printstring(snl."Bind error: Element of name list not an atom, element = ") xprint("",symb) %return %finish %if name(symb)_form = 3 %then %start xprint(snl."Bind error: Name list entry has constant binding, name=",symb) %return %finish %unless global > front %then %start printstring(snl."Bind error: Stack overflow".snl) %return %finish frame == stack(entry) atom == name(symb) %unless bind >= atom base %then %start printstring(snl."Bind error: Unassigned argument ") xprint("",symb) bind = error %finish frame_bind = bind frame_back = symb frame_link = atom_bind atom_bind = entry %end; ! of bind ! !----------------------------------------------------------------------- ! %routine bindlist(%integername names,args) %record(lisp cell)%name cell,argc ! stack(front)_link = local stack(front)_back = 0 local = front front = front + 1 %while names >= list base %cycle cell == list(names) argc == list(args) bind(cell_car,front,argc_car) front = front + 1 names = cell_cdr args = argc_cdr %repeat %end; ! of bindlist ! !----------------------------------------------------------------------- ! %integerfunction unbind(%integer result) %record(stack frame)%name frame ! %while front > local %cycle front = front - 1 frame == stack(front) name(frame_back)_bind = frame_link %if frame_back > 0 %repeat front = local local = stack(front)_link %result = result %end; ! of unbind ! !----------------------------------------------------------------------- ! %integerfunction prog(%integer names,body) %integer proglist,result %record(lisp cell)%name cell ! bindlist(names,nillist) progflag = progflag + 4; ! In prog proglist = body %while body >= list base %cycle; ! Evaluate body cell == list(body) %if cell_car >= list base %then %start ! Not a plabel result = eval(cell_car); ! So evaluate %if progflag & 3 # 0 %then %start;! Return or go %if progflag & 1 # 0 %then %start ! Return progflag = progflag & (\3) - 4 %result = unbind(result) %finish cell == list(proglist) progflag = progflag & (\3) %while cell_car # result %cycle; ! Scan for label %if cell_cdr < list base %then %start progflag = progflag - 4 %result = unbind(error); ! Not found %finish cell == list(cell_cdr) %repeat %finish %finish body = cell_cdr %repeat progflag = progflag - 4 %result = unbind(result); ! Fell through %end; ! of prog ! !----------------------------------------------------------------------- ! %integerfunction evlist(%integer args) %record(lisp cell)%name cell ! %result = args %unless args >= list base cell == list(args) %result = pcons(push(eval(cell_car)),evlist(cell_cdr)) %end; ! of evlist ! !----------------------------------------------------------------------- ! %integerfunction apply(%integer function,args) %integer car,cadr,caddr %record(lisp cell)%name cell ! %if function >= list base %then %start cell == list(function) car = cell_car cell == list(cell_cdr) cadr = cell_car cell == list(cell_cdr) caddr = cell_car %if car = label %then %start bind(cadr,front,caddr) front = front + 1 %result = apply(caddr,args) %finish %if car = lambda %then %start bindlist(cadr,args) bind(cadr,front,args) %and front = front + 1 %if cadr # nil %result = unbind(eval(caddr)) %finish %result = apply(eval(function),args) %finish %if name base <= function <= name tail %then %start %result = func(name(function),args) %finish %result = error %end; ! of apply ! !----------------------------------------------------------------------- ! %integerfunction put(%integer atom,bind,prop) %integer id %halfintegername hole %record(lisp cell)%name prop cell,bind cell ! %unless name base <= atom <= name tail %and name base <= prop <= name tail %then %start %result = error3 %finish hole == name(atom)_prop %cycle; ! Search property list hole = cons(prop,cons(bind,nil)) %and %exit %if hole < list base ! Not on list prop cell == list(hole) bind cell == list(prop cell_cdr) bind cell_car = bind %and %exit %if prop cell_car = prop ! Property found hole == bind cell_cdr; ! Try next entry %repeat %if apval <= prop <= fexpr %then %start;! Function definition name(atom)_form = mask(prop) %if subr <= prop <= fsubr %then %start id = bind %result = error3 %unless numberp(id) = t name(atom)_func = id %finish %else name(atom)_func = bind %finish %result = bind %end; ! of put ! !----------------------------------------------------------------------- ! %integerfunction func(%record(atom cell)%name atom,%integer args) ! Interprets a function call. EXPRs and FEXPRs are interpreted by ! calling 'apply'. SUBRs and FSUBRs are interpreted in the 'func()' ! switch below. %integer arg1,arg2,arg3,symb,afd,flag %string(80) line %halfintegername hole %record(lisp cell)%name cell %record(stack frame)%name frame %switch type(0:3) %switch func(0:86) ! -> type(atom_form & 3) ! type(3): ! Apval type(0): ! No function definition on property list %result = error2 %unless atom_bind < global ! Nor on alist front = front + 1 args = evlist(args) front = front - 1 %result = apply(stack(atom_bind)_bind,args) ! type(1): ! Expr or Fexpr %result = apply(atom_func,args) ! type(2): ! Subr or Fsubr cell == list(args); arg1 = cell_car cell == list(cell_cdr); arg2 = cell_car cell == list(cell_cdr); arg3 = cell_car ! -> func(atom_func) ! func(0): ! Quote %result = arg1 ! func(1): ! Car %result = list(arg1)_car ! func(2): ! Cdr %result = list(arg1)_cdr ! func(3): ! Caar %result = list(list(arg1)_car)_car ! func(4): ! Cadr %result = list(list(arg1)_cdr)_car ! func(5): ! Cdar %result = list(list(arg1)_car)_cdr ! func(6): ! Cddr %result = list(list(arg1)_cdr)_cdr ! func(7): ! Cons %result = cons(arg1,arg2) ! func(8): ! List %result = args ! func(9): ! Cond %while args >= list base %cycle cell == list(list(args)_car) arg1 = eval(cell_car) %if arg1 # nil %then %start %while cell_cdr >= list base %cycle cell == list(cell_cdr) arg1 = eval(cell_car) %repeat %result = arg1 %finish args = list(args)_cdr %repeat %result = nil ! func(10): ! And %while args >= list base %cycle cell == list(args) %result = nil %unless eval(cell_car) # nil args = cell_cdr %repeat %result = t ! func(11): ! Or %while args >= list base %cycle cell == list(args) %result = t %if eval(cell_car) # nil args = cell_cdr %repeat %result = nil ! func(12): ! Null %if arg1 = nil %then %result = t %else %result = nil ! func(13): ! Atom %if atom base <= arg1 < list base %then %result = t %else %result = nil ! func(14): ! Numberp %result = numberp(arg1) ! func(56): ! Evenp %if numberp(arg1) = t %and (arg1 & 1) = 0 %then %result = t %result = nil ! func(55): ! Onep arg1 = arg1 - 1 ! func(15): ! Zerop %if arg1 = zero base %then %result = t %else %result = nil ! func(16): ! Eq %if arg1 = arg2 %then %result = t %else %result = nil ! func(17): ! Equal %result = equal(arg1,arg2) ! func(18): ! Lessp %if numberp(arg1) = t = numberp(arg2) %and arg1 < arg2 %then %result = t %else %c %result = nil ! func(19): ! Greaterp %if numberp(arg1) = t = numberp(arg2) %and arg1 > arg2 %then %result = t %else %c %result = nil ! func(20): ! Memb/Memq %while arg2 >= list base %cycle cell == list(arg2) %result = t %if arg1 = cell_car arg2 = cell_cdr %repeat %result = nil ! func(21): ! Member %while arg2 >= list base %cycle cell == list(arg2) %result = t %if equal(arg1,cell_car) = t arg2 = cell_cdr %repeat %result = nil ! func(22): ! Assoc %while arg2 >= list base %cycle cell == list(arg2) %result = cell_car %if equal(arg1,list(cell_car)_car) = t arg2 = cell_cdr %repeat %result = nil ! func(23): ! Plus arg1 = 0 %while args >= list base %cycle cell == list(args) arg2 = cell_car %if numberp(arg2) = t %then arg1 = arg1 + arg2 %else %result = error3 args = cell_cdr %repeat %result = mnumb(arg1) ! func(24): ! Difference %unless numberp(arg1) = t %then %result = error3 %while args >= list base %cycle cell == list(args) arg2 = cell_car %if numberp(arg2) = t %then arg1 = arg1 - arg2 %else %result = error3 args = cell_cdr %repeat %result = mnumb(arg1) ! func(25): ! Times arg1 = 1 %while args >= list base %cycle cell == list(args) arg2 = cell_car %if numberp(arg2) = t %then arg1 = arg1 * arg2 %else %result = error3 args = cell_cdr %repeat %result = mnumb(arg1) ! func(26): ! Quotient %unless numberp(arg1) = t %then %result = error3 %while args >= list base %cycle cell == list(args) arg2 = cell_cdr %if numberp(arg2) = t %then arg1 = arg1//arg2 %else %result = error3 args = cell_cdr %repeat %result = mnumb(arg1) ! func(27): ! Add1 %if numberp(arg1) = t %then %result = mnumb(arg1 + 1) %result = error3 ! func(28): ! Sub1 %if numberp(arg1) = t %then %result = mnumb(arg1 - 1) %result = error3 ! func(29): ! Abs %if numberp(arg1) = t %then %result = mnumb(imod(arg1)) %result = error3 ! func(30): ! Selectq arg1 = eval(arg1) args = list(args)_cdr %cycle arg3 = args args = list(arg3)_cdr %exit %if args < list base cell == list(list(arg3)_car) arg2 = cell_car arg3 = cell_cdr %while arg2 >= list base %cycle cell == list(arg2) -> exit %if cell_car = arg1 arg2 = cell_cdr %repeat %exit %if arg2 = arg1 %repeat ! exit: %while arg3 >= list base %cycle cell == list(arg3) arg1 = eval(cell_car) arg3 = cell_cdr %repeat %result = arg1 ! func(31): ! Put %result = put(arg1,arg3,arg2) ! func(32): ! Prop %result = error3 %unless name base <= arg1 <= name tail %result = name(arg1)_prop ! func(33): ! Rem/Remprop %result = error3 %unless %c name base <= arg1 <= name tail %and name base <= arg2 <= name tail atom == name(arg1) hole == atom_prop %while hole >= list base %cycle cell == list(hole) %if cell_car = arg2 %then %start cell == list(cell_cdr) atom_form = 0 %if cell_car = atom_func hole = cell_cdr %result = t %finish hole == list(cell_cdr)_cdr %repeat %result = nil ! func(34): ! Get %result = error3 %unless %c name base <= arg1 <= name tail %and name base <= arg2 <= name tail args = name(arg1)_prop %while args >= list base %cycle cell == list(args) %result = list(cell_cdr)_car %if cell_car = arg2 args = list(cell_cdr)_cdr %repeat %result = nil ! func(35): ! Put/Putprop/Defprop %result = put(arg1,arg2,arg3) ! func(36): ! Eval %result = eval(arg1) ! func(37): ! Evlis %result = evlist(args) ! func(38): ! Apply %result = apply(arg1,arg2) ! func(39): ! Errset arg1 = cons(eval(arg1),nil) arg1 = errval %and reset = 0 %if reset = 2 %result = arg1 ! func(40): ! Rplaca %result = error3 %if arg1 < list base list(arg1)_car = arg2 %result = arg2 ! func(41): ! Rplacd %result = error3 %if arg1 < list base list(arg1)_cdr = arg2 %result = arg2 ! func(42): ! Nconc %result = arg2 %if arg1 = nil %result = error3 %unless arg1 >= list base args = arg1; ! Remember 'a' arg1 = list(arg1)_cdr %while list(arg1)_cdr >= list base ! Cdr down 'a' list(arg1)_cdr = arg2 %result = args ! func(43): ! Minusp %if numberp(arg1) = t %and arg1 < 0 %then %result = t %result = nil ! func(44): ! Setq arg2 = eval(arg2) ! func(45): ! Set %result = error3 %unless name base <= arg1 <= name tail arg3 = name(arg1)_bind %if arg3 < stack tail %then %start stack(arg3)_bind = arg2 %finish %else %start global = global - 1 bind(arg1,global,arg2) %finish %result = arg2 ! func(46): ! Explode %result = error3 %unless atom base <= arg1 < list base line = pname(arg1) arg2 = nil %for arg1 = addr(line) + length(line),-1,addr(line) + 1 %cycle symb = byteinteger(arg1) %if '0' <= symb <= '9' %then symb = zero base + symb - '0' %else %c symb = char base + symb arg2 = cons(symb,arg2) %repeat %result = arg2 ! func(47): ! Implode %result = matom(pack(arg1)) ! func(48): ! Prog2 %result = arg2 ! func(49): ! Progn %while args >= list base %cycle cell == list(args) arg1 = eval(cell_car) args = cell_cdr %repeat %result = arg1 ! func(50): ! Prog %result = prog(arg1,list(args)_cdr) ! func(51): ! Minus %if numberp(arg1) = t %then %result = mnumb(-arg1) %result = error3 ! func(52): ! Return progflag = progflag!1 %result = arg1 ! func(53): ! Go progflag = progflag!2 %result = arg1 ! func(54): ! Reverse %result = reverse(arg1) ! func(60): ! Prompt %result = error3 %unless name base <= arg1 <= name tail pmpt = pname(arg1) %result = arg1 ! func(61): ! Readch %if atom base <= arg1 < list base %then prompt(pname(arg1)) %else prompt(pmpt) readch(symb) %if '0' <= symb <= '9' %then %result = mnumb(symb - '0') %else %c %result = matom(tostring(symb)) ! func(62): ! Read %result = read sexp(pname(arg1)) %if atom base <= arg1 < list base %result = read sexp(pmpt) ! func(63): ! Princ print(arg1) %result = arg1 ! func(64): ! Print print(arg1) print chars("") %result = arg1 ! func(65): ! Terpri print chars("") arg1 = nil %unless arg1 >= atom base %result = arg1 ! func(66): ! Inunit selectinput(arg1) %and %result = mnumb(arg1) %if numberp(arg1) = t %result = error3 ! func(67): ! Outunit selectoutput(arg1) %and %result = mnumb(arg1) %if numberp(arg1) = t %result = error3 ! func(68): ! Input %result = error3 %unless name base <= arg1 <= name tail selectinput(0) closestream(instream) arg2 = infile infile = arg1 define(instream,name(infile)_pname,afd,flag) selectinput(instream) %result = arg2 ! func(69): ! Output %result = error3 %unless name base <= arg1 <= name tail selectoutput(0) closestream(outstream) arg2 = outf outf = arg1 define(outstream,name(outf)_pname,afd,flag) selectoutput(outstream) %result = arg2 ! func(70): ! Trace %result = error3 %unless name base <= arg1 <= name tail atom == name(arg1) atom_form = atom_form!8 %result = arg1 ! func(71): ! Untrace %result = error3 %unless name base <= arg1 <= name tail atom == name(arg1) atom_form = atom_form & (\8) %result = arg1 ! func(72): ! Break %result = error3 %unless name base <= arg1 <= name tail name(arg1)_form = name(arg1)_form!16 %result = arg1 ! func(73): ! Unbreak %result = error3 %unless name base <= arg1 <= name tail name(arg1)_form = name(arg1)_form & (\16) %result = arg1 ! func(74): ! $Delete %result = error3 %unless name base <= arg1 <= name tail atom == name(arg1) atom_bind = stack tail atom_prop = nil atom_func = 0 atom_form = 0 %result = arg1 ! func(75): ! Peek %if numberp(arg1) = t %and front - arg1 > stack base %then %c arg1 = front - arg1 %else arg1 = stack base %if front # arg1 %then %start %for arg1 = front - 1,-1,arg1 %cycle frame == stack(arg1) line <- pname(frame_back & x'fff')." " length(line) = 9 %if frame_back & x'8000' # 0 %then line = line."* " %else line = line."= " xprint(line,frame_bind) %repeat %finish %result = stars ! func(76): ! Linelength %result = error3 %unless zerobase + 40 <= arg1 <= zerobase + 255 line length = arg1 - zerobase %result = arg1 ! func(77): ! Garb garbage collect %result = mnumb(list count) ! func(78): ! Reset pmpt = "Read:" reset = 1 errval = nil %result = percent ! func(79): ! Err errval = arg1 reset = 2 %result = percent ! func(80): ! Oblist arg2 = nil %for arg1 = name head - 1,-1,name base %cycle arg2 = cons(arg1,arg2) %repeat %result = arg2 ! func(81): ! Alist arg2 = nil arg3 = nil %for arg1 = stack base,1,front - 1 %cycle frame == stack(arg1) arg2 = cons(cons(frame_back,frame_bind),arg2) %if %c name base <= frame_back <= name tail %repeat %for arg1 = stack tail - 1,-1,global %cycle frame == stack(arg1) arg3 = cons(cons(frame_back,frame_bind),arg3) %repeat %result = cons(arg2,arg3) ! func(82): ! Ascii %result = error3 %unless numberp(arg1) = t %and 0 <= arg1 <= 127 %result = matom(tostring(arg1)) ! func(83): ! Max %unless numberp(arg1) = t %then %result = error3 %while args >= list base %cycle cell == list(args) arg2 = cell_car %unless numberp(arg2) = t %then %result = error3 arg1 = arg2 %if arg1 < arg2 args = cell_cdr %repeat %result = mnumb(arg1) ! func(84): ! Min %unless numberp(arg1) = t %then %result = error3 %while args >= list base %cycle cell == list(args) arg2 = cell_car %unless numberp(arg2) = t %then %result = error3 arg1 = arg2 %if arg2 < arg1 args = cell_cdr %repeat %result = mnumb(arg1) ! func(85): ! Sqrt %unless numberp(arg1) = t %then %result = error3 %result = int(sqrt(arg1)) ! func(86): ! Expt %unless numberp(arg1) = t = numberp(arg2) %then %result = error3 %result = mnumb(arg1****arg2) %end; ! of func ! !----------------------------------------------------------------------- ! %integerfunction trace(%string(255) mess,%integer form) xprint(mess,form) %result = form %end; ! of trace ! !----------------------------------------------------------------------- ! %integerfunction eval(%integer form) %integer car,cdr %record(lisp cell)%name cell %record(atom cell)%name atom %record(stack frame)%name frame ! ! %integerfunction break(%integer result) %integer sexp %switch error(0:3) ! %result = result %if result >= atom base %or reset # 0 selectinput(0) selectoutput(0) xprint("Eval error: ",form) ! -> error(result) ! error(1): printstring(" Atom is not bound to a value".snl) -> error(0) ! error(2): xprint(" Function not defined: ",car) -> error(0) ! error(3): xprint(" Argument not of the correct form in ",cdr) ! error(0): loop(" %:",percent) %result = percent %if reset # 0 sexp = read sexp("Eval:") sexp = form %if sexp = percent %result = eval(sexp) %end; ! of break ! ! ** Body of eval ** ! %result = percent %if reset # 0 frame == stack(front) frame_back <- evln frame_bind = form %if form >= list base %then %start; ! Form is a list cell == list(form) car = cell_car cdr = cell_cdr %if name base <= car <= name tail %then %start atom == name(car) %if atom_form & 4 # 0 %then %start ! Evaluate tail if EXPR or SUBR front = front + 1 cdr = evlist(cdr) front = front - 1 %finish form = push(form) frame_back <- car!x'8000' frame_bind = cdr %if atom_form & 16 # 0 %then %start selectinput(0) selectoutput(0) xprint("Lisp Break: ",form) front = front + 1 loop(" %:",percent) front = front - 1 %finish %if atom_form & 8 # 0 %then %start ! Name being traced %result = pop(break(trace("<--- ".pname(car)." ",func(atom, trace("---> ".pname(car)." ",cdr))))) %finish %result = pop(break(func(atom,cdr))) ! Form of Apply %finish front = front + 1 cdr = evlist(cdr) front = front - 1 %result = break(apply(car,cdr)); ! Function is a list %finish %if name base <= form <= name tail %then %start atom == name(form) %result = atom_func %if atom_form & x'7' = 3 ! Apval %result = break(stack(atom_bind)_bind) ! Return binding %finish %result = form; ! Constant %end; ! of eval ! !----------------------------------------------------------------------- ! %routine initlisp %integer i,sexp %record(atom cell)%name atom %record(lisp cell)%name cell %record(stack frame)%name frame ! %for i = name base,1,name tail %cycle atom == name(i) atom_bind = stack tail atom_prop = nil atom_func = 0 atom_form = 0 atom_pname == errors %repeat selectinput(setup) reset = 0 sexp = ratom %for i = nil,1,stars; ! Read in known atoms %for i = 0,1,list base - 1 %cycle cell == list(i) cell_car = error3 cell_cdr = error3 %repeat list head = list base list count = list tail - list head list(i)_car = i + 1 %for i = list base,1,list tail - 1 list(list tail) = 0 sexp = put(ratom,ratom,ratom) %until sexp = nil ! Initialise from INITLISP stack(front)_bind = error frame == stack(global) frame_link = global frame_bind = error1 auxs(auxp) = error sexp = eval(read sexp("")) %until sexp = nil selectinput(0) %end; ! of initlisp ! ! !*********************************************************************** !* !* L I S P !* !*********************************************************************** ! %externalroutine lisp(%string(255) parms) %integer flag,conad,initmode,i,fixup %string(255) work %record(rf) rr %byteintegerarrayname pname space %record(atom cell)%name atom ! local = stack base front = stack base auxp = 0 pmpt = "Read:" char = x'80'; ! Arbitrary separator to start ! %if parms -> work.("/").parms %and work = "" %then %start %if parms = "" %then parms = "T#LSPMACH" outfile(parms,196608,0,0,conad,flag) -> err %if flag # 0 initmode = yes %finish %else %start initmode = no connect(parms,3,0,0,rr,flag) -> err %if flag # 0 conad = rr_conad %finish ! ! lispfile == record(conad); ! LISP machine store ! %if initmode = yes %then %start lispfile_dataend = lispfile_filesize lispfile_filetype = ssdatafiletype lispfile_format = 3; ! Un-structured lispfile_marker = marker lispfile_const = x'1000' lispfile_long head = long base lispfile_pname space = lispfile_const + 4*(long tail-long base+1) lispfile_pname base = lispfile_pname space lispfile_pname head = lispfile_pname base lispfile_name = x'4000' lispfile_name head = name base lispfile_stack = x'A000' lispfile_global = stack tail lispfile_list = x'10000' lispfile_line length = default line length %finish %else %start %if lispfile_marker # marker %then %start ! Not a LISP machine file flag = 311; ! Corrupt file setfname(parms) -> err %finish %finish ! ! Map variables onto machine file ! const == array(conad+lispfile_const,constf) long head == lispfile_long head pname space == array(conad+lispfile_pname space,pnamef) pname head == lispfile_pname head pname tail = addr(pname space(pname max)) name == array(conad+lispfile_name,namef) name head == lispfile_name head global == lispfile_global line length == lispfile_line length ! ! Relocate 'pname' addresses. ! fixup = addr(pname space(0)) - lispfile_pname base lispfile_pname base = lispfile_pname base + fixup lispfile_pname head = lispfile_pname head + fixup %for i = name base,1,name head - 1 %cycle atom == name(i) atom_pname == string(addr(atom_pname)+fixup) atom_bind = stack tail %unless global <= atom_bind <= stack tail %repeat ! %for i = char base,1,name tail %cycle atom == name(i) atom_bind = stack tail %unless global <= atom_bind <= stack tail %repeat ! list == array(conad+lispfile_list,listf) list head == lispfile_list head list count == lispfile_list count stack == array(conad + lispfile_stack,stackf) ! pspaces = "" plabel = "" line = "" clause = "" progflag = 0 flag = 0 %if initmode = yes %then initlisp nillist = cons(nil,nil) list(nillist)_cdr = push(nillist) infile = matom(".IN") outf = matom(".OUT") ! loop("Lisp:",exit) set return code(0) %stop ! err: selectoutput(0) printstring(snl."LISP fails -".failuremessage(flag)) set return code(flag) %stop %end; ! of lisp %endoffile