pas0.save 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761
  1. #padtwv (* PreProcessor Version - Run through Filter *)
  2. #p (* PERQ version *)
  3. #a (* Apollo Version *)
  4. #d (* DEC-20 Version *)
  5. #t (* Terak Version *)
  6. #w (* Wicat Version *)
  7. #v (* VAX version *)
  8. (*********************************************************************
  9. PASCAL BASED MINI-LISP
  10. File: PAS0.PAS - PASCAL/LISP KERNEL
  11. ChangeHistory:
  12. 9 Dec 81, RO: Remove apollo specific I/O.
  13. 1 Dec 81 RO: I/O fixes for wicat & fixnum bug
  14. 14 Nov 81, MLG:add some PERQ updates from Voelker
  15. 28 Oct 81, RO: GENSYM & fixnum gc
  16. All RIGHTS RESERVED
  17. COPYRIGHT (C) - 1981 - M. L. Griss and R. Ottenheimer
  18. Computer Science Department
  19. University of Utah
  20. Do Not distribute with out written consent of M. L. Griss
  21. ********************************************************************)
  22. #t (*$S+*) (* swapping mode *)
  23. #t (*$G+*) (* goto is legal *)
  24. #adtvw PROGRAM pas0 ; (* (input*,output) *)
  25. #p PROGRAM pas0 (input,output, symin, finput,foutput);
  26. (************************************************************)
  27. (* support routines for a "lisp" machine. uses a register *)
  28. (* model with a stack for holding frames. stack also used *)
  29. (* to hold compiler generated constants. *)
  30. (* written by: *)
  31. (* william f. galway, martin l. griss *)
  32. (* ralph ottenheimer *)
  33. (* append pas1...pasn at end *)
  34. (* -------------------------------------------------------- *)
  35. (* symin is input channel one--used to initialize "symbol *)
  36. (* table". input is input channel two--standard input. *)
  37. (* output is output channel one--the standard output. *)
  38. (* finput is file input channel three. *)
  39. (* foutput is file output channel four. *)
  40. (************************************************************)
  41. #a (* Apollo System include files *)
  42. #a %include '/sys/ins/base.ins.pas';
  43. #a %include '/sys/ins/base_transition.ins.pas';
  44. #a %include '/sys/ins/streams.ins.pas';
  45. #a %include '/sys/ins/pgm.ins.pas';
  46. #p imports Stream from Stream;
  47. #p imports system from system;
  48. #p imports io_others from io_others;
  49. #p imports io_unit from io_unit;
  50. (************************************************************)
  51. CONST
  52. #aptv (* for terak, perq, Apollo, vax *)
  53. #aptvw sp = ' ';
  54. #aptvw ht = 9; (* ascii codes *)
  55. #aptvw lf = 10;
  56. #aptvw cr = 13;
  57. #aptvw nul = 0;
  58. #d eos = nul; (* terminator character for strings. *)
  59. #t (* use eos=chr(nul) *)
  60. #av eos=chr(nul) ;
  61. #pw eos = chr(0); (* KLUDGE: null string *)
  62. #adtwpv inchns = 3; (* number of input channels. *)
  63. #adtwpv outchns = 2; (* number of output channels. *)
  64. begin_comment = '%';
  65. (* Initial symbols, needed in Kernel *)
  66. xtoktype = 129; (* slot in idspace for toktype. *)
  67. xbstack = 130; (* Bstack Pointer *)
  68. xthrowing = 131; (* If throw mode *)
  69. xinitform = 132; (* for restart *)
  70. xraise = 133; (* for RAISE of lc in ids *)
  71. Xinput = 134; (* For Open *)
  72. Xoutput = 135; (* For Open *)
  73. chartype = 3; (* various token types *)
  74. inttype = 1;
  75. idtype = 2;
  76. max_gsym = 4; (* number of digits in gen'd id. *)
  77. #dt shift_const = 8192; (* tags and info are packed into an integer *)
  78. #av shift_const = 4096;
  79. #p (* no shift const *)
  80. #w (* no shift const *)
  81. (* assumed to be at least 16 bits long. low order 13 bits *)
  82. (* are the info, top 3 are the tag. *)
  83. #dt int_offset = 4096; (* small integers are stored 0..8191 *)
  84. #av int_offset = 2048; (* small integers are stored -2048..2047 *)
  85. #pw int_offset = 32767; (* PERQ and WICAT items are records *)
  86. #dt (* instead of -4096..4095 because it will pack smaller *)
  87. #dt (* under ucsd pascal. *)
  88. (* the various tags - can't use a defined scalar type *)
  89. (* because of the lack of convertion functions. *)
  90. inttag = 0; (* info is an integer *)
  91. chartag = 1; (* info is a character code *)
  92. pairtag = 2; (* info points to pair *)
  93. idtag = 3; (* info points to identifier *)
  94. codetag = 4; (* info is index into a case statement *)
  95. (* that calls appropriate function. *)
  96. errtag = 5; (* info is an error code - see below. *)
  97. fixtag = 6; (* info points to a full word (or *)
  98. (* longer) integer. *)
  99. flotag = 7; (* info points to a float number. *)
  100. (* error codes. corresponding to tag = errtag. *)
  101. noprspace = 1; (* no more "pair space"--can't cons. *)
  102. notpair = 2; (* a pair operation attempted on a non-pair. *)
  103. noidspace = 3; (* no more free identifiers *)
  104. undefined = 4; (* used to mark undefined function cells (etc?) *)
  105. noint = 5; (* no free integer space after garbage collection *)
  106. notid = 6;
  107. (* data space sizes *)
  108. #adwv maxpair = 10000; (* max number of pairs allowed. *)
  109. #p maxpair = 3700; (* max number of pairs allowed. *)
  110. #t maxpair = 1000; (* max number of pairs allowed *)
  111. #t maxident = 400; (* max number of identifiers *)
  112. #adpwv maxident = 800; (* max number of identifiers *)
  113. #adpwv maxstrsp = 4500; (* size of string (literal) storage space. *)
  114. #t maxstrsp = 2000; (* size of string (literal) storage space. *)
  115. maxintsp = 200; (* max number of long integers allowed *)
  116. #t maxflosp = 2; (* max number of floating numbers allowed *)
  117. #adpwv maxflosp = 50; (* max number of floating numbers allowed *)
  118. hidmax = 50; (* number of hash values for identifiers *)
  119. maxgcstk = 100; (* size of garbage collection stack. *)
  120. stksize = 500; (* stack size *)
  121. maxreg = 15; (* number of registers in lisp machine. *)
  122. eofcode = 26; (* magic character code for eof, ascii for *)
  123. (* cntrl-z. kludge, see note in xrdtok. *)
  124. choffset = 1; (* add choffset to ascii code to get address *)
  125. (* in id space for corresponding identifier. *)
  126. nillnk = 0; (* when integers are used as pointers. *)
  127. end_flag = maxint; (* marks end of fixnum space *)
  128. (************************************************************)
  129. TYPE
  130. #w regblk_type:array[0..16] of longint;
  131. #d onechar = ascii; (* for DEC *)
  132. #aptvw onechar = char; (* for terak,perq,Apollo,Wicat*)
  133. #a real= integer32; (* Kludge, no reals yet *)
  134. #p FileName= String; (* For PERQ FileName *)
  135. #atwv FileName=Packed ARRAY[0..8] of onechar;
  136. #d FileName=Packed ARRAY[1..9] of onechar;
  137. (* note we allow zero for id_ptr, allowing a "nil" link. *)
  138. stringp = 1..maxstrsp; (* pointer into string space. *)
  139. id_ptr = 0..maxident; (* pointer into id space. *)
  140. #adtv itemref = integer;
  141. #pw itemref = RECORD
  142. #pw tag:integer;
  143. #pw info:integer;
  144. #pw END;
  145. itemtype = 0..7; (* the tags *)
  146. pair = PACKED RECORD
  147. prcar: itemref;
  148. prcdr: itemref;
  149. (* OLD markflag:boolean , but wastes space *)
  150. END;
  151. #aw ascfile = text;
  152. #dptv ascfile = PACKED FILE OF onechar;
  153. #d textfile =PACKED FILE of char;
  154. #a (* No PASCAL file I/O yet *)
  155. ident = PACKED RECORD (* identifier *)
  156. idname: stringp;
  157. val: itemref; (* value *)
  158. plist: itemref; (* property list *)
  159. funcell: itemref; (* function cell *)
  160. idhlink: id_ptr; (* hash link *)
  161. END;
  162. #dptvw longint = integer;
  163. #a longint = integer; (* Should be integer32 ? *)
  164. (************************************************************)
  165. VAR
  166. (* global information *)
  167. nilref, trueref, tmpref: itemref;
  168. (* refers to identifiers "nil", "t", and a temp to get around bug in. *)
  169. (* apollo & wicat pascal *)
  170. initphase: integer; (* Start up *)
  171. #adpvw r: ARRAY[1..maxreg] OF itemref;
  172. #t r: ARRAY[0..maxreg] OF itemref; (* cuts code size down *)
  173. rxx,ryy: itemref;
  174. #tw CHARCNT: INTEGER; (* input buffer & pointer *)
  175. #tw LINE: STRING;
  176. (* "st" is the stack pointer into "stk". it counts the number of *)
  177. (* items on the stack, so it runs from zero while the stack starts *)
  178. (* at one. *)
  179. st: 0..stksize;
  180. stk: ARRAY[1..stksize] OF itemref;
  181. (* pair space *)
  182. prspace: PACKED ARRAY[1..maxpair] OF pair; (* all pairs stored here. *)
  183. freepair: integer; (* pointer to next free pair in prspace. *)
  184. (* identifier space *)
  185. idhead: ARRAY[0..hidmax] OF id_ptr;
  186. idspace: PACKED ARRAY[1..maxident] OF ident;
  187. freeident: integer;
  188. g_sym: ARRAY[1..max_gsym] OF onechar;
  189. (* string space *)
  190. strspace: PACKED ARRAY[1..maxstrsp] OF onechar;
  191. freestr: stringp;
  192. (* large integer space *)
  193. intspace: ARRAY[1..maxintsp] OF longint; (* use long int on terak *)
  194. freeint: 1..maxintsp;
  195. (* floating point number space *)
  196. flospace: ARRAY[1..maxflosp] OF real;
  197. freefloat: 1..maxflosp;
  198. (* i/o channels *)
  199. #p (* files declared on header *)
  200. #adptvw symin: ascfile;
  201. #adptvw finput : ascfile;
  202. #aptvw foutput: ascfile;
  203. #d foutput: textfile;
  204. #d input: ascfile;
  205. #a IoStatus:Integer32;
  206. inchnl: 1..inchns; (* current input channel number *)
  207. outchnl: 1..outchns; (* current output channel number *)
  208. (* "current character" for each input channel. *)
  209. (* may want to include more than one character at some later date *)
  210. (* (for more lookahead). *)
  211. ichrbuf: ARRAY[1..inchns] OF onechar;
  212. (* for collecting statistics. *)
  213. gccount: integer; (* counts garbage collections *)
  214. (* counts from last garbage collection. *)
  215. consknt: integer; (* number of times "cons" called *)
  216. (* ........ Everything nested inside CATCH *)
  217. #w procedure _setjmp(var regblk:regblk_type);external;
  218. #w procedure _long_jump(var regblk:regblk_type);external;
  219. Procedure Xcatch; (* ----------- Outermost Procedure ----------- *)
  220. #adv LABEL 9999;
  221. #w (* need to use special ASM68 procedures for Wicat *)
  222. var catch_stk:0..stksize;
  223. catch_Bstk:itemref;
  224. #w Catch_regs:regblk_type;
  225. #t Procedure xeval;
  226. #t Forward;
  227. PROCEDURE xread;
  228. FORWARD;
  229. PROCEDURE xprint;
  230. FORWARD;
  231. PROCEDURE xunbindto;
  232. FORWARD;
  233. PROCEDURE xeval;
  234. FORWARD;
  235. Procedure Xthrow;
  236. begin (* throw value *)
  237. idspace[Xthrowing].val := trueref;
  238. #dav goto 9999
  239. #w _long_jump(Catch_regs);
  240. #tp exit(xeval)
  241. end (* throw *);
  242. #p (* Special handlers *)
  243. #p Handler CtlC; (* ------- handle runaway aborts ------- *)
  244. #p begin
  245. #p write('^C');
  246. #p IOKeyClear;
  247. #p IObeep;
  248. #p if initphase > 1 then Xthrow;
  249. #p end;
  250. (********************************************************)
  251. (* *)
  252. (* item selectors & constructors *)
  253. (* *)
  254. (********************************************************)
  255. #a (* use some SHIFTS ? *)
  256. FUNCTION tag_of(item: itemref): itemtype;
  257. #t VAR gettag: PACKED RECORD
  258. #t CASE boolean OF
  259. #t TRUE: (i: itemref);
  260. #t FALSE: (info: 0..8191;
  261. #t tag: 0..7)
  262. #t END;
  263. BEGIN (* tag_of *)
  264. #t gettag.i := item;
  265. #t tag_of := gettag.tag
  266. #adv tag_of := item DIV shift_const;
  267. #pw tag_of := item.tag;
  268. END;
  269. (* tag_of *)
  270. FUNCTION info_of(item: itemref): integer;
  271. #t VAR getinfo: PACKED RECORD
  272. #t CASE boolean OF
  273. #t TRUE: (i: itemref);
  274. #t FALSE: (info: 0..8191;
  275. #t tag: 0..7)
  276. #t END;
  277. BEGIN (* info_of *)
  278. #t getinfo.i := item;
  279. #t if getinfo.tag = inttag then
  280. #t info_of := getinfo.info - int_offset
  281. #t else info_of := getinfo.info
  282. #adv IF item DIV shift_const = inttag THEN
  283. #adv info_of := item MOD shift_const - int_offset
  284. #adv ELSE
  285. #adv info_of := item MOD shift_const
  286. #pw info_of := item.info
  287. END;
  288. (* info_of *)
  289. FUNCTION xnull(item: itemref): boolean;
  290. BEGIN
  291. xnull := (tag_of(item) = tag_of(nilref)) AND
  292. (info_of(item) = info_of(nilref))
  293. END;
  294. PROCEDURE mkitem(tag: itemtype; info: longint; VAR item: itemref);
  295. (* do range checking on info. ints run from -4096 to +4095 *)
  296. (* everything else runs from 0 to 8191. ints & chars *)
  297. (* contain their info, all others points into an *)
  298. (* appropriate space. *)
  299. PROCEDURE mkfixint;
  300. VAR nextfree: integer;
  301. PROCEDURE gc_int;
  302. VAR i: integer;
  303. mark_flag: PACKED ARRAY[1..maxintsp] OF boolean;
  304. PROCEDURE mark(u: itemref);
  305. BEGIN (* Mark *)
  306. IF tag_of(u) = pairtag THEN
  307. BEGIN
  308. mark(prspace[info_of(u)].prcar);
  309. mark(prspace[info_of(u)].prcdr)
  310. END
  311. ELSE IF tag_of(u) = fixtag THEN
  312. mark_flag[info_of(u)] := true
  313. END (* Mark *);
  314. BEGIN (* Gc_int *)
  315. writeln('*** Gc int');
  316. FOR i := 1 TO maxintsp do (* clear mark flags *)
  317. mark_flag[i] := false;
  318. FOR i := 1 TO st DO (* mark from the stack *)
  319. Mark(stk[i]);
  320. FOR i := 1 TO maxident DO (* mark from the symbol table *)
  321. BEGIN
  322. Mark(idspace[i].val);
  323. Mark(idspace[i].plist);
  324. Mark(idspace[i].funcell) (* probably NOT necessary *)
  325. END;
  326. (* reconstruct free list *)
  327. FOR i := 1 TO maxintsp - 1 DO
  328. IF NOT mark_flag[i] THEN
  329. BEGIN
  330. intspace[i] := freeint;
  331. freeint := i
  332. END
  333. END (* Gc_int *);
  334. BEGIN (* mkfixint *)
  335. IF intspace[freeint] = end_flag THEN
  336. gc_int; (* garbage collect intspace *)
  337. IF intspace[freeint] <> end_flag THEN
  338. BEGIN (* convert to fixnum *)
  339. tag := fixtag;
  340. nextfree := intspace[freeint];
  341. intspace[freeint] := info;
  342. info := freeint; (* since we want the pointer *)
  343. freeint := nextfree
  344. END
  345. ELSE
  346. BEGIN mkitem(errtag,noint, r[1]);
  347. writeln('***** Integer space exhausted')
  348. END
  349. END;
  350. (* mkfixint *)
  351. BEGIN (* mkitem *)
  352. IF tag = inttag THEN
  353. #pw BEGIN
  354. IF (info < -int_offset) OR (info > int_offset - 1) THEN mkfixint
  355. #adtv ELSE info := info + int_offset (* info was in range so add offset *)
  356. #pw END
  357. ELSE IF tag = fixtag THEN mkfixint
  358. ELSE IF info < 0 THEN
  359. BEGIN
  360. writeln('*****MKITEM: BAD NEG');
  361. #d break(output);
  362. #dtv halt;
  363. #p exit(pas0);
  364. #a pgm_$exit;
  365. END;
  366. (* nothing special to do for other types *)
  367. (* pack tag and info into 16-bit item. *)
  368. #adtv item := tag * shift_const + info
  369. #pw item.tag := tag;
  370. #pw item.info := info
  371. END;
  372. (* mkitem *)
  373. PROCEDURE mkerr(info: longint; VAR item: itemref);
  374. Begin
  375. mkitem(errtag,info,item);
  376. End;
  377. PROCEDURE set_info(VAR item: itemref; newinfo: longint);
  378. BEGIN (* set_info *)
  379. mkitem(tag_of(item), newinfo, item)
  380. END;
  381. (* set_info *)
  382. PROCEDURE set_tag(VAR item: itemref; newtag: itemtype);
  383. BEGIN (* set_tag *)
  384. mkitem(newtag, info_of(item), item)
  385. END;
  386. (* set_tag *)
  387. PROCEDURE mkident(id: integer; reg: integer);
  388. (* make identifier "id" in register "reg" *)
  389. BEGIN (* mkident *)
  390. mkitem(idtag, id, r[reg]);
  391. END;
  392. (* mkident *)
  393. PROCEDURE mkint(int: longint; reg: integer);
  394. BEGIN (* mkint *)
  395. mkitem(inttag, int, r[reg]);
  396. END;
  397. (* mkint *)
  398. PROCEDURE mkpair(pr: integer; reg: integer);
  399. BEGIN (* mkpair *)
  400. mkitem(pairtag, pr, r[reg])
  401. END;
  402. (* mkpair *)
  403. PROCEDURE int_val(item: itemref; VAR number: longint);
  404. (* returns integer value of item (int or fixnum). *)
  405. (* must return 'number' in var parameter instead *)
  406. (* of function value since long integers are not *)
  407. (* a legal function type in ucsd pascal. *)
  408. BEGIN (* int_val *)
  409. IF tag_of(item) = inttag THEN
  410. number := info_of(item)
  411. ELSE IF tag_of(item) = fixtag THEN
  412. number := intspace[info_of(item)]
  413. ELSE writeln('***** ILLEGAL DATA TYPE FOR NUMERIC OPERATION')
  414. (* halt or fatal error *)
  415. END;
  416. (* int_val *)
  417. (********************************************************)
  418. (* *)
  419. (* stack allocation *)
  420. (* *)
  421. (********************************************************)
  422. PROCEDURE alloc(n: integer);
  423. BEGIN
  424. IF n + st <= stksize THEN
  425. st := n+st
  426. ELSE
  427. BEGIN
  428. writeln('*****LISP STACK OVERFLOW');
  429. writeln(' TRIED TO ALLOCATE ',n);
  430. writeln(' CURRENT STACK TOP IS ',st);
  431. #d break(output);
  432. END;
  433. END;
  434. PROCEDURE dealloc(n: integer);
  435. BEGIN
  436. IF st - n >= 0 THEN
  437. st := st - n
  438. ELSE
  439. writeln('*****LISP STACK UNDERFLOW');
  440. END;
  441. (* optimized allocs *)
  442. PROCEDURE alloc1;
  443. BEGIN alloc(1) END;
  444. PROCEDURE dealloc1;
  445. BEGIN dealloc(1) END;
  446. PROCEDURE alloc2;
  447. BEGIN alloc(2) END;
  448. PROCEDURE dealloc2;
  449. BEGIN dealloc(2) END;
  450. PROCEDURE alloc3;
  451. BEGIN alloc(3) END;
  452. PROCEDURE dealloc3;
  453. BEGIN dealloc(3) END;
  454. (********************************************************)
  455. (* *)
  456. (* support for register model *)
  457. (* *)
  458. (********************************************************)
  459. PROCEDURE load(reg: integer; sloc: integer);
  460. BEGIN
  461. IF sloc < 0 THEN r[reg] := r[-sloc]
  462. ELSE r[reg] := stk[st-sloc];
  463. (* will, fix for load (pos,pos) *)
  464. END;
  465. PROCEDURE store(reg: integer; sloc: integer);
  466. BEGIN
  467. stk[st-sloc] := r[reg];
  468. END;
  469. (* optimized load/store. *)
  470. PROCEDURE load10;
  471. BEGIN
  472. load(1,0);
  473. END;
  474. PROCEDURE store10;
  475. BEGIN
  476. store(1,0);
  477. END;
  478. PROCEDURE storenil(sloc: integer);
  479. BEGIN
  480. stk[st-sloc] := nilref;
  481. END;
  482. (* Other primitives ?? *)
  483. (********************************************************)
  484. (* *)
  485. (* identifier lookup & entry *)
  486. (* *)
  487. (********************************************************)
  488. function nmhash(nm: stringp): integer;
  489. CONST
  490. hashc = 256;
  491. VAR
  492. i,tmp: integer;
  493. BEGIN
  494. tmp := 0;
  495. i := 1; (* get hash code from first three chars of string. *)
  496. WHILE (i <= 3) AND (strspace[nm+i] <> eos) DO
  497. BEGIN
  498. tmp := ord(strspace[nm+i]) + hashc*tmp;
  499. i := i + 1;
  500. END;
  501. nmhash := abs(tmp) MOD hidmax; (* abs because mod is screwy. *)
  502. END;
  503. FUNCTION eqstr(s1,s2: stringp): boolean;
  504. BEGIN
  505. WHILE (strspace[s1] = strspace[s2]) AND (strspace[s1] <> eos) DO
  506. BEGIN
  507. s1 := s1 + 1;
  508. s2 := s2 + 1;
  509. END;
  510. eqstr := (strspace[s1] = strspace[s2]);
  511. END;
  512. PROCEDURE nmlookup(nm: stringp; VAR found: boolean; VAR hash: integer;
  513. VAR loc: itemref);
  514. (* lookup a name in "identifier space". *)
  515. (* "hash" returns the hash value for the name. *)
  516. (* "loc" returns the location in the space for the (possibly new) *)
  517. (* identifier. *)
  518. BEGIN
  519. hash := nmhash(nm);
  520. mkitem(idtag, idhead[hash], loc);
  521. (* default is identifier, but may be "error". *)
  522. (* start at appropriate hash chain. *)
  523. found := false;
  524. WHILE (info_of(loc) <> nillnk) AND (NOT found) DO
  525. BEGIN
  526. found := eqstr(nm, idspace[info_of(loc)].idname);
  527. IF NOT found THEN
  528. set_info(loc, idspace[info_of(loc)].idhlink);
  529. (* next id in chain *)
  530. END;
  531. IF NOT found THEN (* find spot for new identifier *)
  532. BEGIN
  533. IF freeident=nillnk THEN (* no more free identifiers. *)
  534. mkerr( noidspace, loc)
  535. ELSE
  536. BEGIN
  537. set_info(loc, freeident);
  538. freeident := idspace[freeident].idhlink;
  539. END;
  540. END;
  541. END;
  542. PROCEDURE putnm(nm: stringp; VAR z: itemref; VAR found: boolean);
  543. (* put a new name into identifier space, or return old location *)
  544. (* if it's already there. *)
  545. VAR
  546. tmp: ident;
  547. hash: integer;
  548. BEGIN
  549. nmlookup(nm, found, hash, z);
  550. IF (NOT found) AND (tag_of(z) = idtag) THEN
  551. BEGIN
  552. tmp.idname := nm;
  553. tmp.idhlink := idhead[hash]; (* put new ident at head of chain *)
  554. tmp.val := nilref; (* initialize value and property list *)
  555. tmp.plist := nilref;
  556. tmp.funcell := nilref; (* also, the function cell *)
  557. idhead[hash] := info_of(z);
  558. idspace[info_of(z)] := tmp;
  559. END;
  560. END;
  561. PROCEDURE xfaststat;
  562. (* give quick summary of statistics gathered *)
  563. BEGIN
  564. writeln('CONSES:',consknt);
  565. writeln('ST :',st);
  566. #d break(output)
  567. END;
  568. (********************************************************)
  569. (* *)
  570. (* the garbage collector *)
  571. (* *)
  572. (********************************************************)
  573. PROCEDURE xgcollect;
  574. VAR
  575. i: integer;
  576. markedk: integer; (* counts the number of pairs marked *)
  577. freedk: integer; (* counts the number of pairs freed. *)
  578. gcstkp: 0..maxgcstk; (* note the garbage collection stack *)
  579. mxgcstk: 0..maxgcstk; (* is local to this procedure. *)
  580. gcstk: ARRAY[1..maxgcstk] OF integer;
  581. markflag: PACKED ARRAY[1..maxpair] OF boolean;
  582. (* used not to have array here *)
  583. PROCEDURE pushref(pr: itemref);
  584. (* push the address of an unmarked pair, if that's what it is. *)
  585. BEGIN
  586. IF tag_of(pr) = pairtag THEN
  587. IF NOT markflag[info_of(pr)] THEN (* was .markflag *)
  588. BEGIN
  589. IF gcstkp < maxgcstk THEN
  590. BEGIN
  591. gcstkp := gcstkp + 1;
  592. gcstk[gcstkp] := info_of(pr);
  593. IF gcstkp > mxgcstk THEN
  594. mxgcstk := gcstkp;
  595. END
  596. ELSE
  597. BEGIN
  598. writeln('*****GARBAGE STACK OVERFLOW');
  599. #dtv halt;
  600. #p exit(pas0);
  601. #a pgm_$exit;
  602. END;
  603. END;
  604. END;
  605. PROCEDURE mark;
  606. (* "recursively" mark pairs referred to from gcstk. gcstk is used to *)
  607. (* simulate recursion. *)
  608. VAR
  609. prloc: integer;
  610. BEGIN
  611. WHILE gcstkp > 0 DO
  612. BEGIN
  613. prloc := gcstk[gcstkp];
  614. gcstkp := gcstkp - 1;
  615. markflag[prloc] := true;
  616. (* OLD prspace[prloc].markflag := true; *)
  617. pushref(prspace[prloc].prcdr);
  618. pushref(prspace[prloc].prcar); (* trace the car first. *)
  619. END;
  620. END;
  621. BEGIN (* xgcollect *)
  622. writeln('***GARBAGE COLLECTOR CALLED');
  623. #d break(output);
  624. gccount := gccount + 1; (* count garbage collections. *)
  625. xfaststat; (* give summary of statistics collected *)
  626. consknt := 0; (* clear out the cons counter *)
  627. gcstkp := 0; (* initialize the garbage stack pointer. *)
  628. mxgcstk := 0; (* keeps track of max stack depth. *)
  629. (* clear markflags *)
  630. FOR i := 1 TO maxpair DO markflag[i] := false;
  631. (* OLD: wasnt needed *)
  632. (* mark things from the "computation" stack. *)
  633. FOR i := 1 TO st DO
  634. BEGIN
  635. pushref(stk[i]);
  636. mark;
  637. END;
  638. (* mark things from identifier space. *)
  639. FOR i := 1 TO maxident DO
  640. BEGIN
  641. pushref(idspace[i].val);
  642. mark;
  643. pushref(idspace[i].plist);
  644. mark;
  645. pushref(idspace[i].funcell);
  646. mark;
  647. END;
  648. (* reconstruct free list by adding things to the head. *)
  649. freedk := 0;
  650. markedk := 0;
  651. FOR i:= 1 TO maxpair - 1 DO
  652. BEGIN
  653. IF markflag[i] THEN
  654. (* OLD: IF prspace[i].markflag THEN *)
  655. BEGIN
  656. markedk := markedk + 1;
  657. markflag[i] := false
  658. (* OLD: prspace[i].markflag := false *)
  659. END
  660. ELSE
  661. BEGIN
  662. prspace[i].prcar := nilref;
  663. mkitem(pairtag, freepair, prspace[i].prcdr);
  664. freepair := i;
  665. freedk := freedk + 1
  666. END
  667. END;
  668. writeln(freedk,' PAIRS FREED.');
  669. writeln(markedk,' PAIRS IN USE.');
  670. writeln('MAX GC STACK WAS ',mxgcstk);
  671. #d break(output);
  672. END;
  673. (* xgcollect *)
  674. (********************************************************)
  675. (* *)
  676. (* lisp primitives *)
  677. (* *)
  678. (********************************************************)
  679. (* return r[1].r[2] in r[1] *)
  680. PROCEDURE xcons;
  681. VAR p: integer;
  682. BEGIN
  683. (* push args onto stack, in case we need to garbage collect the *)
  684. (* references will be detected. *)
  685. alloc(2);
  686. stk[st] := r[1];
  687. stk[st-1] := r[2];
  688. IF xNull(prspace[freepair].prcdr) THEN xgcollect;
  689. p := freepair;
  690. freepair := info_of(prspace[p].prcdr);
  691. prspace[p].prcar := stk[st];
  692. prspace[p].prcdr := stk[st - 1];
  693. mkpair(p, 1); (* leave r[1] pointing at new pair. *)
  694. consknt := consknt + 1;
  695. dealloc(2);
  696. END;
  697. PROCEDURE xncons;
  698. BEGIN r[2] := nilref;
  699. xcons;
  700. END;
  701. PROCEDURE xxcons;
  702. BEGIN rxx := r[1];
  703. r[1] := r[2];
  704. r[2] := rxx;
  705. xcons;
  706. END;
  707. (* return car of r[1] in r[1] *)
  708. PROCEDURE xcar;
  709. BEGIN
  710. IF tag_of(r[1]) = pairtag THEN
  711. r[1] := prspace[info_of(r[1])].prcar
  712. ELSE
  713. mkerr( notpair, r[1]);
  714. END;
  715. PROCEDURE xcdr;
  716. BEGIN
  717. IF tag_of(r[1]) = pairtag THEN
  718. r[1] := prspace[info_of(r[1])].prcdr
  719. ELSE
  720. mkerr( notpair, r[1]);
  721. END;
  722. PROCEDURE xrplaca;
  723. BEGIN
  724. IF tag_of(r[1]) = pairtag THEN
  725. prspace[info_of(r[1])].prcar:=r[2]
  726. ELSE
  727. mkerr( notpair, r[1]);
  728. END;
  729. PROCEDURE xrplacd;
  730. BEGIN
  731. IF tag_of(r[1]) = pairtag THEN
  732. prspace[info_of(r[1])].prcdr :=r[2]
  733. ELSE
  734. mkerr( notpair, r[1]);
  735. END;
  736. (* anyreg car and cdr *)
  737. PROCEDURE anycar(a: itemref; VAR b: itemref);
  738. BEGIN
  739. IF tag_of(a) = pairtag THEN
  740. b := prspace[info_of(a)].prcar
  741. ELSE
  742. mkerr( notpair, b);
  743. END;
  744. PROCEDURE anycdr(a: itemref; VAR b: itemref);
  745. BEGIN
  746. IF tag_of(a) = pairtag THEN
  747. b := prspace[info_of(a)].prcdr
  748. ELSE
  749. mkerr( notpair, b);
  750. END;
  751. (********************************************************)
  752. (* *)
  753. (* compress & explode *)
  754. (* *)
  755. (********************************************************)
  756. PROCEDURE compress; (* returns new id from list of chars *)
  757. VAR i: stringp;
  758. clist, c: itemref;
  759. found: boolean;
  760. int: integer;
  761. FUNCTION is_int(i: stringp; VAR int: longint): boolean;
  762. VAR negative, could_be: boolean;
  763. BEGIN (* is_int *)
  764. int := 0;
  765. could_be := true;
  766. negative := strspace[i] = '-';
  767. IF negative OR (strspace[i] = '+') THEN i := i + 1;
  768. WHILE could_be AND (strspace[i] <> eos) DO
  769. BEGIN
  770. IF (strspace[i] >= '0') AND (strspace[i] <= '9') THEN
  771. int := int * 10 + (ord(strspace[i]) - ord('0'))
  772. ELSE could_be := false;
  773. i := i + 1
  774. END;
  775. IF negative THEN int := -int;
  776. is_int := could_be
  777. END (* is_int *);
  778. BEGIN (* compress *)
  779. clist := r[1]; (* list of chars *)
  780. i := freestr; (* point to possible new string *)
  781. WHILE (i < maxstrsp) AND NOT xNull(clist) DO
  782. BEGIN
  783. IF tag_of(clist) = PAIRTAG THEN
  784. BEGIN
  785. c := prspace[info_of(clist)].prcar;
  786. clist := prspace[info_of(clist)].prcdr;
  787. IF tag_of(c) = IDTAG THEN
  788. IF (info_of(c) > choffset) AND
  789. (info_of(c) < choffset + 128) THEN
  790. BEGIN
  791. strspace[i] := chr(info_of(c) - choffset);
  792. i := i + 1
  793. END
  794. ELSE
  795. writeln('*****COMPRESS: LIST ID NOT SINGLE CHAR')
  796. ELSE
  797. writeln('*****COMPRESS: LIST ITEM NOT ID');
  798. END
  799. ELSE
  800. writeln('*****COMPRESS: ITEM NOT LIST')
  801. END (* WHILE *);
  802. strspace[i] := eos; (* terminate string *)
  803. IF (i >= maxstrsp) THEN
  804. writeln('*****STRING SPACE EXHAUSTED')
  805. ELSE IF is_int(freestr, int) THEN
  806. mkint(int, 1)
  807. ELSE (* look the name up, return itemref for it *)
  808. BEGIN
  809. putnm(freestr, r[1], found);
  810. IF NOT found THEN
  811. freestr := i + 1;
  812. END
  813. END (* compress *);
  814. PROCEDURE explode; (* returns list of chars from id or int *)
  815. FUNCTION id_explode(i: stringp): itemref;
  816. BEGIN (* id_explode *)
  817. IF strspace[i] = eos THEN id_explode := nilref
  818. ELSE
  819. BEGIN
  820. r[2] := id_explode(i + 1);
  821. mkident(ord(strspace[i]) + choffset, 1);
  822. xcons;
  823. id_explode := r[1]
  824. END
  825. END (* id_explode *);
  826. FUNCTION int_explode(i: integer): itemref;
  827. VAR negative: boolean;
  828. BEGIN (* int_explode *)
  829. r[1] := nilref;
  830. IF i < 0 THEN
  831. BEGIN negative := true;
  832. i := -i
  833. END
  834. ELSE negative := false;
  835. WHILE i > 0 DO
  836. BEGIN
  837. r[2] := r[1];
  838. mkident(i MOD 10 + ord('0') + choffset, 1);
  839. xcons;
  840. i := i DIV 10
  841. END;
  842. IF negative THEN
  843. BEGIN
  844. r[2] := r[1];
  845. mkident(ord('-') + choffset, 1);
  846. xcons
  847. END;
  848. int_explode := r[1]
  849. END (* int_explode *);
  850. BEGIN (* explode *)
  851. IF tag_of(r[1]) = IDTAG THEN
  852. r[1] := id_explode(idspace[info_of(r[1])].idname)
  853. ELSE IF tag_of(r[1]) = INTTAG THEN
  854. r[1] := int_explode(info_of(r[1]))
  855. ELSE IF tag_of(r[1]) = FIXTAG THEN
  856. r[1] := int_explode(intspace[info_of(r[1])])
  857. ELSE
  858. writeln('***** EXPLODE: ARG BAD TYPE')
  859. END (* explode *);
  860. PROCEDURE gensym;
  861. VAR i: integer;
  862. PROCEDURE kick(i: integer); (* increments gsym digit *)
  863. BEGIN (* Kick *)
  864. IF (g_sym[i] = '9') THEN
  865. BEGIN
  866. g_sym[i] := '0';
  867. IF (i < max_gsym) THEN kick(i + 1) (* otherwise wrap around *)
  868. END
  869. ELSE g_sym[i] := succ(g_sym[i])
  870. END (* Kick *);
  871. BEGIN (* gensym *)
  872. r[1] := nilref;
  873. FOR i := 1 TO max_gsym DO
  874. BEGIN
  875. r[2] := r[1];
  876. mkident(ord(g_sym[i]) + choffset, 1);
  877. xcons
  878. END;
  879. r[2] := r[1];
  880. mkident(ord('G') + choffset, 1);
  881. xcons;
  882. compress;
  883. Kick(1);
  884. END; (* gensym *)
  885. (********************************************************)
  886. (* *)
  887. (* i/o primitives *)
  888. (* *)
  889. (********************************************************)
  890. PROCEDURE xopen; (* Simple OPEN, but see NPAS0 *)
  891. var s1: FileName;
  892. i,j : integer;
  893. #p (* catch some I/O errors *)
  894. #p handler ResetError(name: PathName);
  895. #p begin
  896. #p writeln('**** Could not open file - ',name,' for read');
  897. #p exit(xopen);
  898. #p end;
  899. #p handler RewriteError(name: PathName);
  900. #p begin
  901. #p writeln('**** Could not open file - ',name,' for write');
  902. #p exit(xopen);
  903. #p end;
  904. begin
  905. IF tag_of(r[1]) = IDTAG THEN
  906. begin
  907. i := idspace[info_of(r[1])].idname;
  908. #p s1[0] := chr(255); (* set length *)
  909. #d s1:=' ';
  910. j:= 0;
  911. WHILE (i <= maxstrsp) AND (strspace[i] <> eos)
  912. #d AND (j <9 )
  913. do
  914. begin
  915. j:= j + 1;
  916. s1[j] := strspace[i];
  917. i:= i + 1;
  918. end;
  919. #p s1[0]:= chr(j); (* set Actual Length *)
  920. IF tag_of(r[2]) = IDTAG THEN
  921. BEGIN
  922. If info_of(r[2])= Xinput then
  923. begin
  924. #p reset(finput,s1);
  925. #d reset(finput,s1,0,0,'DSK ');
  926. mkint(3,1) end
  927. else if info_of(r[2])= Xoutput then
  928. begin
  929. #p rewrite(foutput,s1);
  930. #d rewrite(foutput,s1,0,0,'DSK ');
  931. mkint(2,1) end
  932. else
  933. begin writeln('**** OPEN: ARG2 NOT INPUT/OUTPUT');
  934. mkerr(notid,r[1])
  935. end
  936. end else writeln('**** OPEN: ARG2 BAD TYPE')
  937. end else writeln('**** OPEN: ARG1 BAD TYPE');
  938. end;
  939. procedure xclose;
  940. begin
  941. case info_of(r[1]) of
  942. 1: ;
  943. #d 2: break(output);
  944. #a 3: close(finput);
  945. #d 3: ;
  946. #ap 4: close(foutput);
  947. #d 4: break(foutput);
  948. end;
  949. end;
  950. PROCEDURE xrds;
  951. (* Select channel for input *)
  952. VAR tmp: longint;
  953. BEGIN
  954. tmp:=inchnl;
  955. inchnl := info_of(r[1]);
  956. mkint(tmp,1)
  957. END;
  958. PROCEDURE Xwrs;
  959. (* Select channel for output *)
  960. VAR tmp:longint;
  961. BEGIN
  962. tmp:=outchnl;
  963. outchnl := info_of(r[1]);
  964. mkint(tmp,1)
  965. END;
  966. PROCEDURE xterpri;
  967. (* need to change for multiple output channels. *)
  968. BEGIN
  969. CASE outchnl OF
  970. #p 1: writeln(' ');
  971. #d 1: begin writeln(output); break(output); end;
  972. #dp 2: begin writeln(foutput,' '); break(foutput); end;
  973. #awtv 1: writeln(output);
  974. #wtv 2: writeln(foutput);
  975. END (* CASE *)
  976. END;
  977. #adv FUNCTION Int_field(I:integer):Integer;
  978. #adv Begin
  979. #adv Int_field:=2+trunc(log(abs(I)));
  980. #adv END;
  981. PROCEDURE XwriteInt(I:integer);
  982. BEGIN
  983. #adptw CASE outchnl OF
  984. #p 1: write(' ', I:0);
  985. #dv 1: If I=0 then Write('0') else write(I:Int_field(I) );
  986. #atw 1: write(i);
  987. #p 2: write(foutput,' ', I:0);
  988. #dv 2: If I=0 then Write(foutput,'0') else write(foutput,I:Int_field(I) );
  989. #atw 2: write(foutput, i);
  990. #adptw END (* CASE *)
  991. END (* XwriteInt *);
  992. PROCEDURE Xwritereal(R:real);
  993. BEGIN
  994. #adtpw CASE outchnl OF
  995. #p 1: write(' real Bug ', trunc(R));
  996. #adtvw 1: write(output,R);
  997. #p 2: write(foutput,' real Bug ', trunc(R));
  998. #dtvw 2: write(foutput,R);
  999. #adtpw END (* CASE *)
  1000. END;
  1001. PROCEDURE XwriteChar(C:onechar);
  1002. BEGIN
  1003. #adptw CASE outchnl OF
  1004. #p 1: write(' ', C);
  1005. #adtvw 1: write(C);
  1006. #p 2: write(foutput,' ', C);
  1007. #adtvw 2: write(foutput,C);
  1008. #adptw END (* CASE *)
  1009. END;
  1010. PROCEDURE xwrtok;
  1011. (* doesn't expand escaped characters in identifier names *)
  1012. VAR i: integer;
  1013. BEGIN
  1014. IF tag_of(r[1]) = inttag THEN XwriteInt(info_of(R[1]))
  1015. ELSE IF tag_of(r[1]) = fixtag THEN XwriteInt(intspace[info_of(R[1])])
  1016. ELSE IF tag_of(r[1]) = flotag THEN XwriteReal(flospace[info_of(r[1])])
  1017. ELSE IF tag_of(r[1]) = idtag THEN
  1018. BEGIN
  1019. i := idspace[info_of(r[1])].idname;
  1020. WHILE (i <= maxstrsp) AND (strspace[i] <> eos) DO
  1021. BEGIN
  1022. XwriteChar(strspace[i]);
  1023. i:= i + 1;
  1024. END;
  1025. END
  1026. ELSE IF tag_of(r[1]) = chartag THEN
  1027. XwriteChar(chr(info_of(r[1]) - choffset))
  1028. ELSE IF tag_of(r[1]) = errtag THEN
  1029. Begin XwriteChar(' ');
  1030. XwriteChar('*'); XwriteChar('*'); XwriteChar('*');
  1031. XwriteChar(' '); XwriteChar('#'); XwriteChar(' ');
  1032. XwriteInt(info_of(r[1])); Xterpri;
  1033. End
  1034. ELSE IF tag_of(r[1]) = codetag THEN
  1035. Begin XwriteChar(' '); XwriteChar('#'); XwriteChar('#');
  1036. XwriteInt(info_of(r[1]));
  1037. End
  1038. ELSE
  1039. Begin
  1040. XwriteChar(' '); XwriteChar('?'); XwriteChar(' ');
  1041. XwriteInt(tag_of(r[1]));
  1042. XwriteChar(' '); XwriteChar('/'); XwriteChar(' ');
  1043. XwriteInt(info_of(r[1]));
  1044. XwriteChar(' '); XwriteChar('?'); XwriteChar(' ');
  1045. End;
  1046. #d break(output);
  1047. END;
  1048. PROCEDURE rdchnl(chnlnum: integer; VAR ch: onechar);
  1049. BEGIN
  1050. IF (chnlnum < 1) OR (chnlnum > inchns) THEN
  1051. writeln('*****BAD INPUT CHANNEL FOR RDCHNL',chnlnum)
  1052. ELSE
  1053. CASE chnlnum OF
  1054. 1: BEGIN
  1055. #adptvw ch := symin^; (* a little strange, but avoids *)
  1056. #adptvw get(symin); (* initialization problems *)
  1057. #adptvw ichrbuf[inchnl] := symin^; (* Peek ahead *)
  1058. END;
  1059. 2: BEGIN
  1060. #tw IF charcnt > Length(line) THEN
  1061. #tw BEGIN
  1062. #tw charcnt := 1;
  1063. #tw Readln(line)
  1064. #tw END;
  1065. #tw ch := line[charcnt];
  1066. #tw IF Length(line) > charcnt THEN
  1067. #tw ichrbuf[inchnl] := line[charcnt + 1]
  1068. #tw ELSE ichrbuf[inchnl] := sp;
  1069. #tw charcnt := charcnt + 1
  1070. #adpv ch := input^;
  1071. #adpv get(input);
  1072. #adpv ichrbuf[inchnl] := input^;
  1073. END;
  1074. #dp 3: begin
  1075. #dp ch := finput^;
  1076. #dp get(finput);
  1077. #dp ichrbuf[inchnl] := finput^;
  1078. #dp END;
  1079. END;
  1080. (* case *)
  1081. END;
  1082. (* rdchnl *)
  1083. FUNCTION eofchnl: boolean;
  1084. BEGIN
  1085. #adptvw CASE inchnl OF
  1086. #adptvw 1: eofchnl := eof(symin);
  1087. #adptvw 2: eofchnl := eof(input);
  1088. #adptvw 3: eofchnl := eof(finput);
  1089. #adptvw END;
  1090. END;
  1091. FUNCTION eol: boolean;
  1092. BEGIN
  1093. CASE inchnl OF
  1094. 1: eol := eoln(symin);
  1095. 2: eol := eoln(input);
  1096. 3: eol := eoln(finput);
  1097. END;
  1098. END;
  1099. (********************************************************)
  1100. (* *)
  1101. (* token scanner *)
  1102. (* *)
  1103. (********************************************************)
  1104. PROCEDURE xrdtok;
  1105. LABEL 1;
  1106. VAR
  1107. ch,ch1,ChangedCh: onechar;
  1108. i: integer;
  1109. anint: longint;
  1110. moreid: boolean;
  1111. found: boolean;
  1112. negflag: integer;
  1113. FUNCTION digit(ch: onechar): boolean;
  1114. BEGIN
  1115. digit := ( '0' <= ch ) AND ( ch <= '9');
  1116. END;
  1117. FUNCTION escalpha(VAR ch: onechar): boolean;
  1118. (* test for alphabetic or escaped character. *)
  1119. (* note side effect in ChangedCh. *)
  1120. BEGIN
  1121. ChangedCh := Ch;
  1122. IF ( 'A' <= ch ) AND ( ch <= 'Z') THEN
  1123. escalpha := true
  1124. ELSE IF ( ord('A')+32 <= ord(ch)) AND ( ord(ch) <= ord('Z')+32) THEN
  1125. BEGIN
  1126. IF NOT xNull(idspace[xraise].val) THEN
  1127. Changedch := chr(ord(ch)-32);
  1128. escalpha := true; (* lower case alphabetics *)
  1129. END
  1130. ELSE IF ch='!' THEN
  1131. BEGIN
  1132. rdchnl(inchnl,ch);
  1133. ChangedCh:=Ch;
  1134. escalpha := true;
  1135. END
  1136. ELSE
  1137. escalpha := false;
  1138. END;
  1139. FUNCTION alphanum(VAR ch: onechar): boolean;
  1140. (* test if escalfa or digit *)
  1141. VAR b: boolean;
  1142. BEGIN
  1143. ChangedCh:=Ch;
  1144. b := digit(ch);
  1145. IF NOT b THEN b := escalpha(ch);
  1146. alphanum := b;
  1147. END;
  1148. FUNCTION whitesp(ch: onechar): boolean;
  1149. #d BEGIN
  1150. #d (* may want a faster test *)
  1151. #d whitesp := (ch = sp) OR (ch = cr) OR (ch = lf) OR (ch = ht)
  1152. #d OR (ch = nul); (* null?? *)
  1153. #aptvw VAR ascode:integer;
  1154. #aptvw BEGIN
  1155. #aptvw ascode:=ord(ch);
  1156. #aptvw WHITESP := (CH = SP) OR (ascode = CR) OR (ascode = LF)
  1157. #aptvw OR (ascode = ht) or (ascode = nul); (* null?? *)
  1158. END;
  1159. (* reads fixnums...need to read flonums too *)
  1160. BEGIN (* xrdtok *)
  1161. 1:
  1162. IF NOT eofchnl THEN
  1163. REPEAT (* skip leading white space. *)
  1164. rdchnl(inchnl,ch)
  1165. UNTIL (NOT whitesp(ch)) OR eofchnl;
  1166. IF eofchnl THEN
  1167. mkitem(chartag, eofcode + choffset, r[1])
  1168. (* should really return !$eof!$ *)
  1169. ELSE
  1170. BEGIN
  1171. IF digit(ch) or (ch = '-') THEN
  1172. set_tag(r[1], inttag)
  1173. ELSE IF escalpha(ch) THEN
  1174. set_tag(r[1], idtag)
  1175. ELSE
  1176. set_tag(r[1], chartag);
  1177. CASE tag_of(r[1]) OF
  1178. chartag: BEGIN
  1179. if ch = begin_comment then
  1180. BEGIN
  1181. While not eol do rdchnl(inchnl,ch);
  1182. rdchnl(inchnl, ch);
  1183. GOTO 1
  1184. END;
  1185. set_tag(r[1], idtag);
  1186. mkitem(inttag, chartype, tmpref);
  1187. idspace[xtoktype].val := tmpref;
  1188. set_info(r[1], ord(ch) + choffset);
  1189. END;
  1190. inttag: BEGIN
  1191. mkitem(inttag, inttype, tmpref;
  1192. idspace[xtoktype].val :=tmpref;
  1193. negflag := 1;
  1194. if ch = '-' then
  1195. begin anint := 0; negflag :=-1 end
  1196. else anint := ord(ch) - ord('0');
  1197. WHILE digit(ichrbuf[inchnl]) DO
  1198. BEGIN
  1199. rdchnl(inchnl,ch);
  1200. anint := 10 * anint + (ord(ch) - ord('0'))
  1201. END;
  1202. anint := negflag * anint;
  1203. set_info(r[1], anint)
  1204. END;
  1205. idtag: BEGIN
  1206. mkitem(inttag, idtype, tmpref);
  1207. idspace[xtoktype].val:=tmpref;
  1208. i := freestr; (* point to possible new string *)
  1209. moreid := true;
  1210. WHILE (i < maxstrsp) AND moreid DO
  1211. BEGIN
  1212. strspace[i] := ChangedCh; (* May have Case Change, etc *)
  1213. i:= i + 1;
  1214. moreid :=alphanum(ichrbuf[inchnl]); (* PEEK ahead char *)
  1215. IF moreid THEN rdchnl(inchnl,ch) (* Advance readch *)
  1216. END;
  1217. strspace[i] := eos; (* terminate string *)
  1218. IF (i >= maxstrsp) THEN
  1219. writeln('*****STRING SPACE EXHAUSTED')
  1220. ELSE (* look the name up, return itemref for it *)
  1221. BEGIN
  1222. putnm(freestr, r[1], found);
  1223. IF NOT found THEN
  1224. freestr := i + 1;
  1225. END;
  1226. END;
  1227. (* of case idtag *)
  1228. END;
  1229. (* of case *)
  1230. END;
  1231. END;
  1232. (* xrdtok *)
  1233. (* for DEBUG *)
  1234. (********************************************************)
  1235. (* *)
  1236. (* initialization *)
  1237. (* *)
  1238. (********************************************************)
  1239. PROCEDURE init;
  1240. (* initialization procedure depends on *)
  1241. (* ability to load stack with constants *)
  1242. (* from a file. *)
  1243. VAR
  1244. strptr: stringp;
  1245. #dptvw nam: PACKED ARRAY[1..3] OF onechar;
  1246. #a nam: PACKED ARRAY[1..4] OF onechar; (* SPL bug for Apollo *)
  1247. (* holds 'nil', other strings? *)
  1248. i, n: integer;
  1249. idref: itemref;
  1250. found: boolean;
  1251. #aptv (* init is divided into two parts so it can compile on terak *)
  1252. PROCEDURE init1;
  1253. BEGIN
  1254. #tw CHARCNT := 1;
  1255. #tw LINE := '';
  1256. (* initialize top of stack *)
  1257. st := 0;
  1258. freefloat := 1;
  1259. (* initialize fixnum free list *)
  1260. FOR freeint := 1 TO maxintsp - 1 DO
  1261. intspace[freeint] := freeint + 1;
  1262. intspace[maxintsp] := end_flag;
  1263. freeint := 1;
  1264. (* define nilref - the id, nil, is defined a little later. *)
  1265. freeident := 1;
  1266. mkitem(idtag, freeident, nilref);
  1267. (* initialize pair space. *)
  1268. FOR i := 1 TO maxpair - 1 DO (* initialize free list. *)
  1269. BEGIN
  1270. (* OLD: prspace[i].MarkFlag := false; *)
  1271. prspace[i].prcar := nilref; (* just for fun *)
  1272. mkitem(pairtag, i + 1, prspace[i].prcdr);
  1273. END;
  1274. prspace[maxpair].prcar := nilref;
  1275. prspace[maxpair].prcdr := nilref; (* end flag *)
  1276. freepair := 1; (* point to first free pair *)
  1277. (* initialize identifier space and string space. *)
  1278. freestr := 1;
  1279. FOR i := 0 TO hidmax - 1 DO
  1280. idhead[i] := nillnk;
  1281. FOR i := 1 TO maxident DO
  1282. BEGIN
  1283. IF i < maxident THEN
  1284. idspace[i].idhlink := i + 1
  1285. ELSE (* nil to mark the final identifier in the table. *)
  1286. idspace[i].idhlink := nillnk;
  1287. (* set function cells to undefined *)
  1288. mkerr( undefined, tmpref);
  1289. idspace[i].funcell :=tmpref;
  1290. idspace[i].val :=tmpref;
  1291. idspace[i].plist :=tmpref;
  1292. END;
  1293. (* nil must be the first identifier in the table--id #1 *)
  1294. (* must fill in fields by hand for nilref.*)
  1295. (* putnm can handle any later additions. *)
  1296. nam := 'NIL';
  1297. strptr := freestr;
  1298. FOR i := 1 TO 3 DO
  1299. BEGIN
  1300. strspace[strptr] := nam[i];
  1301. strptr:= strptr + 1;
  1302. END;
  1303. strspace[strptr] := eos;
  1304. putnm(freestr, nilref, found);
  1305. IF NOT found THEN
  1306. freestr := strptr + 1;
  1307. (* make the single character ascii identifiers, except nul(=eos). *)
  1308. FOR i := 1 TO 127 DO
  1309. BEGIN
  1310. strspace[freestr] := chr(i);
  1311. strspace[freestr + 1] := eos;
  1312. putnm(freestr, idref, found);
  1313. IF NOT found THEN
  1314. freestr := freestr + 2;
  1315. IF i = ord('T') THEN
  1316. trueref := idref;
  1317. (* returns location for 't. *)
  1318. END;
  1319. (* init gensym id list *)
  1320. FOR i := 1 TO max_gsym DO g_sym[i] := '0';
  1321. (* clear the counters *)
  1322. idspace[xraise].val := trueref;
  1323. gccount := 0;
  1324. consknt := 0;
  1325. END;
  1326. (* init1 *)
  1327. PROCEDURE init2;
  1328. BEGIN
  1329. (* load "symbol table" with identifiers, constants, and functions. *)
  1330. inchnl := 1; (* select symbol input file. *)
  1331. outchnl := 1; (* select symbol OUTPUT file. *)
  1332. #p reset(symin,'paslsp.ini');
  1333. #p reset(input);
  1334. #p rewrite(output);
  1335. #w reset(symin, "paslsp.ini");
  1336. #t reset(symin,'#5:poly.data');
  1337. #d reset(symin,'paslspini',0,0,'DSK ');
  1338. #d reset(input,'tty ',0,0,'TTY ');
  1339. #d rewrite(output,'tty ',0,0,'TTY ');
  1340. #a open(symin,'paslsp.ini','old',iostatus);
  1341. #a reset(symin);
  1342. #a for i:=1 to inchns do
  1343. #a BEGIN;
  1344. #a ichrbuf[i]:=' ';
  1345. #a END;
  1346. xrdtok; (* get count of identifiers. *)
  1347. IF tag_of(r[1]) <> inttag THEN
  1348. writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED AT START');
  1349. n := info_of(r[1]);
  1350. FOR i := 1 TO n DO
  1351. xrdtok;
  1352. (* reading token magically loads it into id space. *)
  1353. xrdtok; (* look for zero terminator. *)
  1354. IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
  1355. writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER IDENTIFIERS');
  1356. xrdtok; (* count of constants *)
  1357. IF tag_of(r[1]) <> inttag THEN
  1358. writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED BEFORE CONSTANTS');
  1359. n := info_of(r[1]);
  1360. alloc(n); (* space for constants on the stack *)
  1361. FOR i := 1 TO n DO
  1362. BEGIN
  1363. xread;
  1364. stk[i] := r[1];
  1365. END;
  1366. xrdtok;
  1367. IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
  1368. writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER CONSTANTS');
  1369. xrdtok; (* count of functions. *)
  1370. IF tag_of(r[1]) <> inttag THEN
  1371. writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED BEFORE FUNCTIONS');
  1372. n := info_of(r[1]);
  1373. FOR i := 1 TO n DO
  1374. (* for each function *)
  1375. (* store associated code *)
  1376. BEGIN
  1377. xrdtok;
  1378. mkitem(codetag, i, tmpref);
  1379. idspace[info_of(r[1])].funcell :=tmpref;
  1380. END;
  1381. xrdtok;
  1382. IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
  1383. writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER FUNCTIONS');
  1384. END;
  1385. (* init2 *)
  1386. PROCEDURE dumpids;
  1387. VAR i, p: integer;
  1388. BEGIN
  1389. FOR i := 1 TO freeident - 1 DO
  1390. BEGIN
  1391. p := idspace[i].idname;
  1392. write('id #', i:5, ' at', p:5, ': ');
  1393. WHILE strspace[p] <> eos DO
  1394. BEGIN
  1395. write(strspace[p]);
  1396. p := p + 1
  1397. END;
  1398. write('. Function code: ');
  1399. writeln(INFO_OF(idspace[i].funcell));
  1400. END
  1401. END;
  1402. BEGIN (* init *)
  1403. init1;
  1404. init2;
  1405. END;
  1406. (* init *)
  1407. (********************************************************)
  1408. (* *)
  1409. (* arithmetic functions *)
  1410. (* *)
  1411. (********************************************************)
  1412. PROCEDURE xadd1;
  1413. VAR i: longint;
  1414. BEGIN
  1415. int_val(r[1], i);
  1416. mkint(i + 1, 1)
  1417. END;
  1418. PROCEDURE xdifference;
  1419. VAR i1, i2: longint;
  1420. BEGIN
  1421. int_val(r[1], i1);
  1422. int_val(r[2], i2);
  1423. mkint(i1 - i2, 1)
  1424. END;
  1425. PROCEDURE xdivide; (* returns dotted pair (quotient . remainder). *)
  1426. VAR quot, rem: integer;
  1427. i1, i2: longint;
  1428. BEGIN
  1429. int_val(r[1], i1);
  1430. int_val(r[2], i2);
  1431. mkint(i1 DIV i2, 1);
  1432. mkint(i1 MOD i2, 2);
  1433. xcons
  1434. END;
  1435. PROCEDURE xgreaterp;
  1436. VAR i1, i2: longint;
  1437. BEGIN
  1438. int_val(r[1], i1);
  1439. int_val(r[2], i2);
  1440. IF i1 > i2 THEN
  1441. r[1] := trueref
  1442. ELSE
  1443. r[1] := nilref;
  1444. END;
  1445. PROCEDURE xlessp;
  1446. VAR i1, i2: longint;
  1447. BEGIN
  1448. int_val(r[1], i1);
  1449. int_val(r[2], i2);
  1450. IF i1 < i2 THEN
  1451. r[1] := trueref
  1452. ELSE
  1453. r[1] := nilref;
  1454. END;
  1455. PROCEDURE xminus;
  1456. VAR i: longint;
  1457. BEGIN
  1458. int_val(r[1], i);
  1459. mkint(-i, 1)
  1460. END;
  1461. PROCEDURE xplus2;
  1462. VAR i1, i2: longint;
  1463. BEGIN
  1464. int_val(r[1], i1);
  1465. int_val(r[2], i2);
  1466. mkint(i1 + i2, 1)
  1467. END;
  1468. PROCEDURE xquotient;
  1469. VAR i1, i2: longint;
  1470. BEGIN
  1471. int_val(r[1], i1);
  1472. int_val(r[2], i2);
  1473. mkint(i1 DIV i2, 1)
  1474. END;
  1475. PROCEDURE xremainder;
  1476. VAR i1, i2: longint;
  1477. BEGIN
  1478. int_val(r[1], i1);
  1479. int_val(r[2], i2);
  1480. mkint(i1 MOD i2, 1)
  1481. END;
  1482. PROCEDURE xtimes2;
  1483. VAR i1, i2: longint;
  1484. BEGIN
  1485. int_val(r[1], i1);
  1486. int_val(r[2], i2);
  1487. mkint(i1 * i2, 1)
  1488. END;
  1489. (* xtimes2 *)
  1490. (********************************************************)
  1491. (* *)
  1492. (* support for eval *)
  1493. (* *)
  1494. (********************************************************)
  1495. PROCEDURE execute(code: integer);
  1496. FORWARD;
  1497. (* Xapply(fn,arglist)-- "fn" is an operation code. *)
  1498. PROCEDURE xxapply;
  1499. VAR
  1500. i: integer;
  1501. code: integer;
  1502. tmp: itemref;
  1503. tmpreg: ARRAY[1..maxreg] OF itemref;
  1504. BEGIN
  1505. code := info_of(r[1]);
  1506. r[1] := r[2];
  1507. i := 1;
  1508. (* spread the arguments *)
  1509. WHILE NOT xNull(r[1]) AND (i <= maxreg) DO
  1510. BEGIN
  1511. tmp := r[1];
  1512. xcar;
  1513. tmpreg[i] := r[1];
  1514. i := i + 1;
  1515. r[1] := tmp;
  1516. xcdr;
  1517. END;
  1518. WHILE i > 1 DO
  1519. BEGIN
  1520. i := i - 1;
  1521. r[i] := tmpreg[i];
  1522. END;
  1523. execute(code);
  1524. END;
  1525. (* rest of pas1...pasn follow , pasn Closes definition of Catch *)