Overview
Comment:Add Reduce 3.0 to the historical section of the archive, and some more
files relating to version sof PSL from the early 1980s. Thanks are due to
Paul McJones and Nelson Beebe for these, as well as to all the original
authors.

git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/historical@5328 2bfe0521-f11c-4a00-b80e-6202646ff360

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | master | trunk
Files: files | file ages | folders
SHA3-256: 3519b83598db4fc5c71c95732a12b7b59160f5067f1494bc22937e5b438065f9
User & Date: arthurcnorman@users.sourceforge.net on 2020-04-21 19:40:01
Other Links: manifest | tags
Context
2021-03-01
00:11:36
Updating .gitignore check-in: 3f9ee8c811 user: jeff@gridfinity.com tags: master, trunk
2020-04-21
19:40:01
Add Reduce 3.0 to the historical section of the archive, and some more
files relating to version sof PSL from the early 1980s. Thanks are due to
Paul McJones and Nelson Beebe for these, as well as to all the original
authors.

git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/historical@5328 2bfe0521-f11c-4a00-b80e-6202646ff360 check-in: 3519b83598 user: arthurcnorman@users.sourceforge.net tags: master, trunk

2019-02-28
18:01:26
Commit two tar.gz files with PSL sources and binaries for "old" architectures.
Courtesy of Winfried Neun (ZIB Berlin).

git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/historical@4918 2bfe0521-f11c-4a00-b80e-6202646ff360 check-in: 1d536d6d33 user: schoepf@users.sourceforge.net tags: master, trunk

Changes

Added CONTRIBUTORS version [7f84b98c0f].









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
The historical files here represents copies of earlier versions of
Reduce and PSL with (at present) the oldes ones being from the early 1980s.
They are in general unaltered from the original archives that they were
recovered from, and a consequence of that is that some have restrictive
rights messages embedded which represented their status at that time.
Tony Hearn and Martin Griss as lead copyright holders were senty an enquiry:
> Would you grant permission for me to make these public as part of the
> above-mentioned web site (which Im expecting will eventually be
> formally accessioned into the Computer History Museum digital
> repository? Thanks very much.

Tony Hearn replied:
> Fine with me.

Martin Griss replied:
> I have no objections to their release with an appropriate note, but its
> important to know that several files were written or updated by
> multiple students at Utah and by several staff at HP Laboratories; many
> of these folks have most likely retired.
>
> So, I am not sure if we need to contact them for permission. Perhaps
> they at least need to be listed as contributors. As far as I can
> tell/recall, only some of the files have copyright notices that request
> my permission for release - I assume (or intended -:) these notice on
> the "main" files apply to all subsidiary files, both hand written and
> generated.
>
> We will need certainly to add some sort of caveat/disclosure that says
> these files are provided for historical interest only, and there is no
> implied warrantee of fitness or correctness for use, nor may they be
> used for any commercial pupose..

Please note that last paragraph that these files are made availanle to
record the historical trail of the Reduce project and the contributors -
both those named within the filea and others deserve thanks and credit.

For later copies of Reduce Tony Hearn arranged that contributors completed
paperwork to confirm that they were willing to have their code distributed
as part of Reduce. For PSL at some stage control and support was organised
through HP Labs, and a modest while after Reduce became an open source
project they confirmed that they were happy for their code to be included
as part of the open source version. It is probable that the rights that they
acquired in order to be able to develop and exploit PSL means that their
release of the code covers almost all of the versions here. See the HP
disclaimer in the PSL section of the main current version of the code.

The bibliography in the file doc/manual/bibl.bib lists many of those who
contributed to Reduce.

                                                          ACN April 2020

 

Added perq-pascal-lisp-project/CONTRIBUTORS version [7f84b98c0f].









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
The historical files here represents copies of earlier versions of
Reduce and PSL with (at present) the oldes ones being from the early 1980s.
They are in general unaltered from the original archives that they were
recovered from, and a consequence of that is that some have restrictive
rights messages embedded which represented their status at that time.
Tony Hearn and Martin Griss as lead copyright holders were senty an enquiry:
> Would you grant permission for me to make these public as part of the
> above-mentioned web site (which Im expecting will eventually be
> formally accessioned into the Computer History Museum digital
> repository? Thanks very much.

Tony Hearn replied:
> Fine with me.

Martin Griss replied:
> I have no objections to their release with an appropriate note, but its
> important to know that several files were written or updated by
> multiple students at Utah and by several staff at HP Laboratories; many
> of these folks have most likely retired.
>
> So, I am not sure if we need to contact them for permission. Perhaps
> they at least need to be listed as contributors. As far as I can
> tell/recall, only some of the files have copyright notices that request
> my permission for release - I assume (or intended -:) these notice on
> the "main" files apply to all subsidiary files, both hand written and
> generated.
>
> We will need certainly to add some sort of caveat/disclosure that says
> these files are provided for historical interest only, and there is no
> implied warrantee of fitness or correctness for use, nor may they be
> used for any commercial pupose..

Please note that last paragraph that these files are made availanle to
record the historical trail of the Reduce project and the contributors -
both those named within the filea and others deserve thanks and credit.

For later copies of Reduce Tony Hearn arranged that contributors completed
paperwork to confirm that they were willing to have their code distributed
as part of Reduce. For PSL at some stage control and support was organised
through HP Labs, and a modest while after Reduce became an open source
project they confirmed that they were happy for their code to be included
as part of the open source version. It is probable that the rights that they
acquired in order to be able to develop and exploit PSL means that their
release of the code covers almost all of the versions here. See the HP
disclaimer in the PSL section of the main current version of the code.

The bibliography in the file doc/manual/bibl.bib lists many of those who
contributed to Reduce.

                                                          ACN April 2020

 

Added perq-pascal-lisp-project/[teco].output version [c35b8bf16a].





























































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
@Device(lpt)
@style(justification yes)
@style(spacing 1)
@use(Bibliography "<griss.docs>mtlisp.bib")
@make(article)
@modify(enumerate,numbered=<@a. @,@i. >, spread 1)
@modify(appendix,numbered=<APPENDIX @A: >)
@modify(itemize,spread 1)
@modify(description,leftmargin +2.0 inch,indent -2.0 inch)
@define(up,use text,capitalized on,  break off)
@define(mac,use text, underline off,  break off)
@define(LISPmac,use text, underline alphanumerics,  break off)
@pageheading(Left  "Utah Symbolic Computation Group",
             Right "December 1981", 
             Line "Operating Note 60"
            )
@set(page=1)
@newpage()
@begin(titlepage)
@begin(titlebox)
@b(A PASCAL Based Standard LISP for the Apollo Domain)
@center[
by

M. L. Griss and R. Ottenheimer

Department of Computer Science
University of Utah
Salt Lake City, Utah 84112

@b(Preliminary  Version)

Last Revision: @value(date)]

@end(titlebox)
@begin(abstract)
This report describes an interim implementation of Standard LISP for the
Apollo DOMAIN. This LISP is based upon the Standard LISP report, and a newly
developing Portable Standard LISP.  This interim implementation is designed
to explore LISP implementations in PASCAL on the Apollo DOMAIN and similar 
machines.
The system consists of a kernel, handcoded in PASCAL, with the rest of the
system written in LISP and compiled to PASCAL.
@End(abstract)
@begin(Researchcredit)
Work supported in part by the National Science Foundation
under Grant No. MCS80-07034.
@end(Researchcredit)
@end(titlepage)
@pageheading(Left "Apollo Pascal LISP",Center "@value(date)",
             Right "@value(Page)"
            )
@set(page=1)
@newpage
@section(Introduction)
In this preliminary report, we describe an implementation of Standard LISP
in PASCAL, PASLSP. Versions of PASLSP have been run on a number of
machines, ranging from an LSI-11 based TERAK to Apollo and PERQ. This report
concentrates on the Apollo DOMAIN implementation. This report is to be read in
conjunction with the Standard LISP report@cite(Marti79); we will
highlight the differences from the functions documented in the Standard
LISP, describe the implementation strategy, and discuss future work.

PASLSP is based on a series of small and medium sized LISP interpreters
that have been developed at the University of Utah to explore LISP
implementations in higher level languages. Each of these LISP systems
consists of a small kernel handcoded in some language, with the rest of the
system written in LISP and compiled to the target language.  We have used
FORTRAN, PASCAL and assembly language as targets. The PASLSP series use
PASCAL for the kernel, and have a LISP to PASCAL compiler for the rest of
the system. 

Recent work has concentrated on reducing the size of the hand-coded kernel,
and extending the compiler to handle systems level constructs. This has
resulted in a new Portable Standard LISP, PSL, running on the DEC-20 and
VAX-11/750@cite(Benson81,Griss81). An implementation of PSL for MC68000 is
underway. The PSL system is a modern, efficient LISP, written entirely in
itself; it uses an efficient LISP to machine code compiler to produce the
kernel, and then the rest of LISP is loaded. In the future we hope to
produce a complete PSL targeted at a higher level languages, such as
PASCAL, C or ADA, and this will replace the current PASLSP.

@subsection(History of PASLSP)
The system now called PASLSP was originally developed (by M. Griss and W.
Galway), as a small LISP like kernel to support a small computer algebra
system on an LSI-11 TERAK; this was to be used as an answer analysis module
within a CAI system@cite(Brandt81), written entirely in PASCAL. It was
decided to hand-code a very small kernel, and compile additional functions
written in LISP (LISP support functions, parser and
simplifier) to PASCAL,
using a modified Portable LISP compiler@cite(griss79). This version (call
it V0) did not even have user defined functions, since space on the TERAK
was at a premium.

About June 1981, PASLSP came to the attention of a number people evaluating
Apollo's and PERQ's, and it was suggested that we enhance V0 PASLSP for
this purpose. During the space of a few days,  features taken
from the Standard LISP Report and newly developing
PSL files were added to
produce  PASLSP-V1, running on a DEC-20 and Terak. This
was a fairly complete LISP (including Catch and Throw), but lacked a few
features (OPEN, CLOSE, RDS, WRS, PROG, GO, RETURN, COMPRESS, EXPLODE,
Vectors and Strings, etc.).  V1 PASLSP was adapted to a PERQ, VAX and
Apollo by Paul Milazo of Schlumberge in the space of a few weeks (we did
not have a PERQ or Apollo at that time).

We subsequently obtained a PERQ and an Apollo, and recent work has been
aimed at producing an enhanced PASLSP for these machines, maintaining all
versions in one set of source files.  The current system, PASLSP-V2, is
produced from a single PASCAL kernel and set of LISP support files; the
machine specific features are handled by a simple Source Code
Conditionalizer, changing the definition of certain constants and data
types. Only a few features of the Standard LISP report are missing,
and there are a number of additions.

@subsection(Acknowledgement)

We would like to acknowledge the contributions and support of
Eric Benson, Dick Brandt, Will Galway,   and Paul Milazo.

@section(Features of PASLSP and relation to Standard LISP)
PASLSP as far as possible provides all the functions mentioned
in the attached Standard LISP Report (note the hand-written
comments added to this appendix); some of the functions are simply
stubs, so that a Standard LISP Test-file can be run without major
modification.

PASLSP-V2  does not implement the following features of Standard LISP:
@begin(enumeration,spread 0)
VECTORS (only a simple garbage collector is used).

String space is not garbage collected.

Integers are limited in size (INTs and FIXNUMs, no BIGNUMs).

FLOATING Point is not implemented.

IDs can not be REMOB'ed or INTERN'd.

Only 3 Input Channels and 2 Output Channels are available to OPEN,
RDS, WRS, and CLOSE. Thus file input statements can not be nested
very deeply in files.

Line, Page and Character counting (POSN, LPOSN, etc) are not implemented.
@end(enumeration)

PASLSP-V2 provides some extensions over Standard LISP:
@begin(enumerate,spread 0)
(CATCH form) and (THROW form) and the tagged versions: (TCATCH tag form)
and (TTHROW tag form) are used to implement error and errorset, 
and higher level control functions.

Implicit PROGN in COND, and LAMBDA expressions.

(WHILE pred action-1 action-2 ... action-n).

(DSKIN 'filename)
@end(enumerate)

PASLSP-V2 has not been extensively tested, and there may still be a number
of bugs. While some effort has been spent in adjusting PASLSP to the Apollo
DOMAIN, it is clear that the various heap sizes are not yet optimal. 
See appendix A for current list of functions, and appendix B for a copy
of the Standard LISP Report annotated to reflect the current status of 
PASLSP.

@section(Using PASLSP on the Apollo DOMAIN)
	Initializing the system from the floppy looks like this:
@begin(verbatim)
Create a directory (call it pl):
	crd /pl
Mount the floppy:
	mtvol f 1 /f
Copy the files of interest:
	cpt /f/pascallisp /pl

    The files copied will be: paslsp (executable file)
                              paslsp.ini (initialization file)
                              paslsp.tst (a test file)
@end(verbatim)

Run paslsp as you would any other file.  If you
get an error it is most likely because the paslsp.ini file couldn't be found.
If this happens, locate paslsp.ini and try again.  If it still hangs,
try calling Ralph Ottenheimer at (801) 355-0226 or M. Griss at (801) 581-6542.


Previously prepared files of LISP (e.g., library procedures)
can be input by
using the function "DSKIN".  For Example,
@begin(verbatim)
(DSKIN 'Paslsptst)
(DSKIN '!/p!/foo!.sl)
@end
would load the paslsp test file.  Paslsp test is adapted from an extensive
test of Standard LISP (avoiding features not yet implemented).  This is a
good excercise, try it. [Note that the filename must be given as an ID,
and that special characters should be prefaced by an "escape character",
! . This is  also the case for filenames in OPEN.]


  Paslsp is "case-sensitive" with regard to identifiers.  All of the
kernel procedures have upper-case identifiers associated with them.  This
means that ordinarily the expression (dskin 'paslsptst) would not be
recognized since "dskin" is in lowercase.  However, there is a global flag
!*RAISE which if true will convert all lower-case typin to upper-case.
This Apollo DOMAIN paslsp implementation sets !*RAISE to T as a default by
having (SETQ !*RAISE T) in the paslsp.ini file.  You may put any special
initialization code you like at the end of paslsp.ini as indicated by the
comments in the file.
Toggling would be accomplished by typing the following lisp-expressions:
@begin(verbatim)
	(SETQ !*RAISE T)
	(SETQ !*RAISE NIL)
@end(verbatim)

	Any Apollo DOMAIN filename (25 characters maximum)is allowable
 as a paslsp filename.
Remember to prefix all special characters with an exclamation-mark: "!". 
Special characters include all non-alphanumerics. For example: fof!.ksjd
!*RAISE goforit!! paslsp!.test .
@section(Implementation of PASLSP)
@subsection(Building PASLSP)
PASLSP is built in the following steps:

@u(Kernel files), PAS0.PRE, and trailer file (main program) PASN.PRE
are run through a filter program to produce PAS0.PAS and PASN.PAS,
tailored to the Apollo DOMAIN (appropriate Include files, Consts, etc).
This kernel provides the Basic I/O (Token reading and printing),
handcoded storage allocator and garbage collector, lowlevel arithmetic
primitives, lowlevel calls (via Case statement) from LISP to kernel, etc.

@u(Rest of LISP), currently files PAS1.RED, PAS2.RED and PAS3.RED are
compiled to PASCAL using a version of the Portable LISP Compiler
(PLC)@cite(griss79). During compilation, a Symbol Table file, PASn.SYM is
read in and written out. These files record (for "incremental" compilation)
the names and ID table locations of each ID encountered, so that the compiler
can refer to an ID by its offset in the ID table. LISP constants are also
recorded in the PASn.SYM files. PAS0.SYM is modified by hand as the kernel
is changed.  

The compilation model used is that of a Register Machine: Arguments to LISP
functions are passed in registers (a PASCAL array), and the result returned
in Register 1. Space is allocated on a software stack (not the PASCAL
recursion stack), for any temporaries or save arguments required. Short
functions usually do not require any stack. The reason for this choice was
the existence of the PLC (targeted at comventional machines), and the fact
that inline access to the register array compiles quite well, while a
"PUSH/POP" stack would be much less efficient.

@u(Initialization). 
After the PAS0.PAS,..PASN.PAS are produced,
the symbol table file (pas3.sym) is converted into a file
PASLSP.INI, which contains the names of all ID's, the LISP constants
used, and also ID's for all kernel functions that should be known to the
user LISP level. Also produced is a file, EXEC.PAS, that contains a case
statement associating each user callable kernel function with an integer.
The PAS0.PAS ... PASN.PAS and EXEC.PAS are compiled and linked into an
executable .RUN file. When this file is executed, PASLSP.INI is read in:
each id is read and stored in the appropriate location in the symbol-table,
the kernal function names have the associated Case index put into
a function cell, and the LISP s-expressions are READ in. Finally,
some s-expressions will be executed (with care, the user can add his own
expressions, including requests to (DSKIN 'library), etc.
@subsection(Internal data structures)
[To be written, see the PAS0.PRE files regarding data-types,
function calling conventions, etc]
      itemref = RECORD
                tag: integer;  (* Small integer denoting the type.   *)
                info: integer; (* Either the item or a pointer to it *)
                               (* depending upon the type.           *)
                END;

      pair = PACKED RECORD
                      prcar: itemref;
                      prcdr: itemref;
                  END;

    ident = PACKED RECORD           (* identifier *)
                       idname: stringp;
                       val: itemref;       (* value *)
                       plist: itemref;     (* property list *)
                       funcell: itemref;   (* function cell *)
                       idhlink: id_ptr;    (* hash link *)
                   END;

@subsection(Adding user functions to the kernel)
[To be written, describe format of EXEC.PAS, PASLSP.INI and major functions
that are needed to add new Arithmetic extensions,
or more complex operations].

@Section(Future work on PASLSP)
PASLSP V2 is based on a fairly old model of a portable LISP, and
has been used mainly to explore the capbilities of PASCAL as a
target language. In particular, V2 PASCAL is not yet powerful enough to
run the PLC compiler  itself;
instead, the PLC is run on our PSL system on the DEC-20. In order for the
full benefits of PASLSP (or PSL) to be realized, the user should be able to
compile his own LISP modules into PASCAL and link them with the kernel.
In order to make the system even more adapatable, we would like to write
even less of the kernel in PASCAL by hand. This goal has lead us to the
development of PSL. 

@subsection(Goals of the Utah PSL Project)

The goal of the PSL project is to produce an efficient and transportable
Standard LISP system that may be used to:
@begin(enumeration)
Experimentally  explore
a variety of LISP implementation issues (storage management, binding,
environments, etc.).

Effectively support the REDUCE computer algebra system@cite(hearn73)
on a number of machines.

Provide the same, uniform, modern LISP programming environment on all of
the machines that we use (DEC-20, VAX/750, PDP-11/45, PERQ, and Apollo), of
the power and complexity of UCI-LISP, FranzLISP or MACLISP, with some
extensions and enhancements derived from LISP Machine LISP or CommonLISP.
@end(enumeration)

The approach we have been using is to write the @b(entire) LISP system in
Standard LISP (with extensions for dealing with 
machine words and operations), and to bootstrap it to the desired target
machine
in two steps:
@begin(enumeration)
Cross compile an appropriate kernel to the assembly language of the
target machine;

Once the kernel is running, use a resident compiler and loader, or
fast-loader, to build the rest of the system.
@end(enumeration)

 The PASLSP system, and other early implementations, have the problem that
the implementation language (PASCAL) is a distinct language from LISP, so
that communication between "system" code and "LISP" code was difficult.  We
have incorporated all of the good features of the earlier work into a new
efficient LISP-like systems language, SYSLISP, recoded all useful modules
into SYSLISP, and proceeded from there.  SYSLISP currently produces
targeted assembly code; earlier verisions were targeted at high-level
languages such as FORTRAN, PASCAL, C or ADA.  The goal is a portability
strategy that leads to an efficient enough system for a production quality,
yet portable system. We currently think of the extensions to Standard LISP
as having two levels: the SYSLISP level, dealing with words and bytes and
machine operations, enabling us to write essentially all of the kernel in
Standard LISP; and, the STDLISP level, incorporating all of the features
that make Standard LISP into a modern LISP, PSL.  SYSLISP and LISP are both
compiled by an improved version of the Portable Standard LISP Compiler. The
SYSLISP mode of the PSL compiler does compile-time folding of constants,
and more comprehensive register allocation than the previous LISP-only
version of the compiler.

The current state of PSL is fully described in an "overview" document
obtainable from the authors @cite(griss81e).  Currently PSL runs on the
DEC-20 under TOPS-20, and on the DEC VAX-11/750 under Unix.  We are now
concentrating on the MC68000 PSL for the Apollo. All of the code-generators
and assembler support is complete, and a number of large files have been
compiled from LISP to assembly code, and correctly assembled and executed
on the Apollo, testing basic I/O and arithmetic. We are now in the process
of writing the PSL support code (small functions in LAP), and testing that
various decisions about register and memory usage are correct. Based on the
development history on the VAX, we are about 1-2 months away from a
preliminary PSL on the Apollo.
@section(References)
@Bibliography

Added perq-pascal-lisp-project/apollo-paslsp.aux version [6215f4ba3d].

















>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
@Comment{AUXFILE of APOLLO-PASLSP.MSS.35 by Scribe 3C(1250) on 26 February 1982 at 14:47}
@AuxCitation{BENSON81$=(1;;)}
@AuxCitation{BRANDT81$=(2;;)}
@AuxCitation{GRISS79$=(3;;)}
@AuxCitation{GRISS81$=(4;;)}
@AuxCitation{GRISS81E$=(5;;)}
@AuxCitation{HEARN73$=(6;;)}
@AuxCitation{MARTI79$=(7;;)}

Added perq-pascal-lisp-project/apollo-paslsp.err version [507cbceb11].











>
>
>
>
>
1
2
3
4
5
@Comment{ErrLog of APOLLO-PASLSP.MSS.35 by Scribe 3C(1250) on 26 February 1982 at 14:47}

Error in text found while processing the manuscript.
APOLLO-PASLSP.MSS.35 line 239:    notpair = 2;      (* a pair operation attempted on a non-pair.*)
Line too wide; lost ")".

Added perq-pascal-lisp-project/apollo-paslsp.lpt version [5a2f0fef1c].

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
Utah Symbolic Computation Group                     December 1981
Operating Note 60









       A PASCAL Based Standard LISP for the Apollo Domain        A PASCAL Based Standard LISP for the Apollo Domain        A PASCAL Based Standard LISP for the Apollo Domain


                               by

                 M. L. Griss and R. Ottenheimer

                 Department of Computer Science
                       University of Utah
                   Salt Lake City, Utah 84112

                      Preliminary  Version                       Preliminary  Version                       Preliminary  Version

                 Last Revision: 26 February 1982










                            ABSTRACT                             ABSTRACT                             ABSTRACT


This  report describes an interim implementation of Standard LISP
for the Apollo DOMAIN. This LISP is based upon the Standard  LISP
report,  and  a  newly  developing  Portable Standard LISP.  This
interim   implementation   is   designed    to    explore    LISP
implementations  in  PASCAL  on  the  Apollo  DOMAIN  and similar
machines.  The system consists of a kernel, handcoded in  PASCAL,
with  the  rest  of  the  system  written in LISP and compiled to
PASCAL.





Work supported in part by the National Science  Foundation  under
Grant No. MCS80-07034. Apollo Pascal LISP      26 February 1982                        1


1. Introduction 1. Introduction 1. Introduction

  In  this  preliminary  report, we describe an implementation of
Standard LISP in PASCAL, PASLSP. Versions of PASLSP have been run
on a number of machines, ranging from an LSI-11  based  TERAK  to
Apollo  and  PERQ.  This report concentrates on the Apollo DOMAIN
implementation. This report is to be read in conjunction with the
Standard LISP report [7]; we will highlight the differences  from
the  functions  documented  in  the  Standard  LISP, describe the
implementation strategy, and discuss future work.


  PASLSP is based on a series of  small  and  medium  sized  LISP
interpreters  that  have been developed at the University of Utah
to explore LISP implementations in higher level  languages.  Each
of  these  LISP  systems  consists of a small kernel handcoded in
some language, with the rest of the system written  in  LISP  and
compiled  to  the  target language.  We have used FORTRAN, PASCAL
and assembly language as targets. The PASLSP  series  use  PASCAL
for  the  kernel, and have a LISP to PASCAL compiler for the rest
of the system.


  Recent work has  concentrated  on  reducing  the  size  of  the
hand-coded  kernel,  and extending the compiler to handle systems
level constructs. This has resulted in a  new  Portable  Standard
LISP,  PSL,  running  on  the  DEC-20  and  VAX-11/750 [1, 4]. An
implementation of PSL for MC68000 is underway. The PSL system  is
a  modern, efficient LISP, written entirely in itself; it uses an
efficient LISP to machine code compiler to  produce  the  kernel,
and  then  the  rest  of LISP is loaded. In the future we hope to
produce a complete PSL targeted at a higher level languages, such
as PASCAL, C or ADA, and this will replace the current PASLSP.


1.1. History of PASLSP 1.1. History of PASLSP 1.1. History of PASLSP

  The system now  called  PASLSP  was  originally  developed  (by
M. Griss and W. Galway), as a small LISP like kernel to support a
small  computer algebra system on an LSI-11 TERAK; this was to be
used as an  answer  analysis  module  within  a  CAI  system [2],
written  entirely  in  PASCAL. It was decided to hand-code a very
small kernel, and compile additional functions  written  in  LISP
(LISP  support functions, parser and simplifier) to PASCAL, using
a modified Portable LISP compiler [3]. This version (call it  V0)
did  not  even  have  user  defined functions, since space on the
TERAK was at a premium.


  About June 1981, PASLSP came  to  the  attention  of  a  number
people  evaluating Apollo's and PERQ's, and it was suggested that
we enhance V0 PASLSP for this purpose. During the space of a  few Apollo Pascal LISP      26 February 1982                        2


days,  features  taken  from  the  Standard LISP Report and newly
developing PSL files were added to produce PASLSP-V1, running  on
a  DEC-20  and  Terak. This was a fairly complete LISP (including
Catch and Throw), but lacked a few features  (OPEN,  CLOSE,  RDS,
WRS,  PROG,  GO,  RETURN, COMPRESS, EXPLODE, Vectors and Strings,
etc.).  V1 PASLSP was adapted to a PERQ, VAX and Apollo  by  Paul
Milazo  of  Schlumberge  in  the space of a few weeks (we did not
have a PERQ or Apollo at that time).


  We subsequently obtained a PERQ and an Apollo, and recent  work
has  been  aimed  at  producing  an  enhanced  PASLSP  for  these
machines, maintaining all versions in one set  of  source  files.
The  current  system, PASLSP-V2, is produced from a single PASCAL
kernel and set  of  LISP  support  files;  the  machine  specific
features  are  handled  by  a simple Source Code Conditionalizer,
changing the definition of certain constants and data types. Only
a few features of the Standard LISP report are missing, and there
are a number of additions.


1.2. Acknowledgement 1.2. Acknowledgement 1.2. Acknowledgement

  We would like to acknowledge the contributions and  support  of
Eric Benson, Dick Brandt, Will Galway, and Paul Milazo.



2. Features of PASLSP and relation to Standard LISP 2. Features of PASLSP and relation to Standard LISP 2. Features of PASLSP and relation to Standard LISP

  PASLSP  as far as possible provides all the functions mentioned
in the attached  Standard  LISP  Report  (note  the  hand-written
comments  added  to  this  appendix);  some  of the functions are
simply stubs, so that  a  Standard  LISP  Test-file  can  be  run
without major modification.


  PASLSP-V2 does not implement the following features of Standard
LISP:


   a. VECTORS (only a simple garbage collector is used).
   b. Strings  are  implemented  as identifiers (not garbage
      collected).
   c. Integers are limited in size  (INTs  and  FIXNUMs,  no
      BIGNUMs).
   d. FLOATING Point is not implemented.
   e. IDs can not be REMOB'ed or INTERN'd.
   f. Only  3  Input  Channels  and  2  Output  Channels are
      available to OPEN, RDS,  WRS,  and  CLOSE.  Thus  file
      input  statements  can  not  be  nested very deeply in
      files. Apollo Pascal LISP      26 February 1982                        3


   g. Line,  Page  and Character counting (POSN, LPOSN, etc)
      are not implemented.


  PASLSP-V2 provides some extensions over Standard LISP:


   a. (CATCH form) and (THROW form) and the tagged versions:
      (TCATCH tag form) and (TTHROW tag form)  are  used  to
      implement error and errorset, and higher level control
      functions.
   b. Implicit PROGN in COND, and LAMBDA expressions.
   c. (WHILE pred action-1 action-2 ... action-n).
   d. (DSKIN 'filename) or (DSKIN "filename")


  PASLSP-V2  has not been extensively tested, and there may still
be a number  of  bugs.  While  some  effort  has  been  spent  in
adjusting  PASLSP  to  the  Apollo  DOMAIN,  it is clear that the
various heap sizes are not yet  optimal.    See  appendix  A  for
current  list  of  functions,  and  appendix  B for a copy of the
Standard LISP Report annotated to reflect the current  status  of
PASLSP.



3. Using PASLSP on the Apollo DOMAIN 3. Using PASLSP on the Apollo DOMAIN 3. Using PASLSP on the Apollo DOMAIN

  Initializing the system from the floppy looks like this:


Create a directory (call it pl):
        crd /pl
Mount the floppy:
        mtvol f 1 /f
Copy the files of interest:
        cpt /f/pascallisp /pl

    The files copied will be: paslsp (executable file)
                              paslsp.ini (initialization file)
                              paslsp.tst (a test file)


  Run paslsp as you would any other file.  If you get an error it
is most likely because the paslsp.ini file couldn't be found.  If
this  happens,  locate  paslsp.ini  and  try  again.  If it still
hangs,  try  calling  Ralph  Ottenheimer  at  (801)  355-0226  or
M. Griss at (801) 581-6542.


  Previously  prepared  files  of LISP (e.g., library procedures)
can be input by using the function "DSKIN".  For Example, Apollo Pascal LISP      26 February 1982                        4


(DSKIN 'Paslsp!.tst) or (DSKIN "Paslsp.tst")


would  load the paslsp test file. The PASLSP test is adapted from
an extensive test of Standard LISP  (avoiding  features  not  yet
implemented).    This  is a good excercise, try it. [Note that if
the filename is given as an ID, that special characters should be
prefaced by an "escape character", ! . This is also the case  for
filenames  in  OPEN.  Alternately the string form may be used, in
that case special characters need not be escaped.]


  Paslsp is "case-sensitive" with regard to identifiers.  All  of
the kernel procedures have upper-case identifiers associated with
them.      This  means  that  ordinarily  the  expression  (dskin
'paslsp!.tst)  would  not  be  recognized  since  "dskin"  is  in
lowercase.  However, there is a global flag !*RAISE which if true
will  convert  all  lower-case  typin to upper-case.  This Apollo
DOMAIN paslsp implementation sets !*RAISE to T as  a  default  by
having  (SETQ !*RAISE T) in the paslsp.ini file.  You may put any
special initialization code you like at the end of paslsp.ini  as
indicated  by  the  comments  in  the  file.    Toggling would be
accomplished by typing the following lisp-expressions:


        (ON !*RAISE)     equivalent to  (SETQ !*RAISE T)
        (OFF !*RAISE)    equivalent to  (SETQ !*RAISE NIL)


  Any Apollo DOMAIN filename (60 characters maximum)is  allowable
as  a paslsp filename.  Remember to prefix all special characters
with an exclamation-mark: "!".  Special  characters  include  all
non-alphanumerics.  For  example:  !*RAISE goforit!! paslsp!.test
!/login!/smith!/foo!.sl .


  If the global !*ECHO is not NIL (default is NIL), input will be
echoed  to  the  selected  output  channel.    It  is   sometimes
convienient to put:


        (SETQ !*ECHO T)


at the beginning of a file to be read by DSKIN, and:


        (SETQ !*ECHO NIL)


at the end.  This will echo the file to the screen (or to a file)
as it is read. Apollo Pascal LISP      26 February 1982                        5


  Certain low level errors do not display any explanatory message
but  instead display a numeric code (such as *** # 2), below is a
summary of these codes and their meanings:


  (* error codes.  corresponding to tag = errtag. *)
  noprspace = 1;    (* no more "pair space"--can't cons. *)
  notpair = 2;      (* a pair operation attempted on a non-pair.*
  noidspace = 3;    (* no more free identifiers *)
  undefined = 4;    (* used to mark undefined function cells *)
  noint = 5;        (* no free integer space after gc. *)
  notid = 6;        (* id was expected *)



4. Implementation of PASLSP 4. Implementation of PASLSP 4. Implementation of PASLSP


4.1. Building PASLSP 4.1. Building PASLSP 4.1. Building PASLSP

  PASLSP is built in the following steps:


  ______  _____   Kernel  files,  PAS0.PRE,  and  trailer  file  (main   program)
PASN.PRE are run through a filter program to produce PAS0.PAS and
PASN.PAS,  tailored  to  the  Apollo  DOMAIN (appropriate Include
files, Consts, etc).  This kernel provides the Basic  I/O  (Token
reading  and  printing),  handcoded storage allocator and garbage
collector, lowlevel arithmetic primitives,  lowlevel  calls  (via
Case statement) from LISP to kernel, etc.


  ____  __  ____   Rest  of  LISP, currently files PAS1.RED, PAS2.RED and PAS3.RED
are compiled to PASCAL using  a  version  of  the  Portable  LISP
Compiler  (PLC) [3].  During  compilation,  a  Symbol Table file,
PASn.SYM is read in and written  out.  These  files  record  (for
"incremental"  compilation)  the  names and ID table locations of
each ID encountered, so that the compiler can refer to an  ID  by
its  offset  in the ID table. LISP constants are also recorded in
the PASn.SYM files. PAS0.SYM is modified by hand as the kernel is
changed.


  The compilation model used  is  that  of  a  Register  Machine:
Arguments  to  LISP  functions  are passed in registers (a PASCAL
array), and the result returned in Register 1. Space is allocated
on a software stack (not the PASCAL  recursion  stack),  for  any
temporaries  or  save arguments required. Short functions usually
do not require any stack. The reason  for  this  choice  was  the
existence of the PLC (targeted at comventional machines), and the
fact  that  inline  access  to  the register array compiles quite
well, while a "PUSH/POP" stack would be much less efficient. Apollo Pascal LISP      26 February 1982                        6


  ______________   Initialization.    After  the PAS0.PAS,..PASN.PAS are produced,
the symbol  table  file  (pas3.sym)  is  converted  into  a  file
PASLSP.INI,  which  contains  the  names  of  all  ID's, the LISP
constants used, and also  ID's  for  all  kernel  functions  that
should  be known to the user LISP level. Also produced is a file,
EXEC.PAS, that contains a case statement  associating  each  user
callable  kernel  function  with  an  integer.   The PAS0.PAS ...
PASN.PAS and EXEC.PAS are compiled and linked into an  executable
file. When this file is executed, PASLSP.INI is read in:  each id
is   read   and   stored  in  the  appropriate  location  in  the
symbol-table, the kernel function names have the associated  Case
index  put  into  a function cell, and the LISP s-expressions are
READ in. Finally, some s-expressions will be executed (with care,
the user can add  his  own  expressions,  including  requests  to
(DSKIN 'library), etc.


4.2. Internal data structures 4.2. Internal data structures 4.2. Internal data structures

  The  data  spaces  (or  heaps)  in  PASLSP  are  divided into 4
sections: the pair space, id space (the oblist), string space and
large integer (fixnum) space.  These are all arrays of objects of
the appropriate type (see declarations below).    The  system  is
fully  tagged,  that is, every LISP item has associated with it a
tag field which denotes the type of the item and an 'info'  field
which  either  points  to  the  item  in an array (in the case of
pairs, identifiers and  fixnums),  or  contains  the  information
itself   (in  the  case  of  inums,  character  codes  and  error
conditions). The info field of a code pointer contains the  index
into  a case staement (see procedure 'execute') by means of which
any LISP callable function may be invoked.


itemref = RECORD
           tag:  integer;   (* Small integer denoting  type.   *)
           info: integer;   (* Item or a pointer to it         *)
                            (* depending upon the type.        *)
          END;

   pair = PACKED RECORD
            prcar: itemref;
            prcdr: itemref;
          END;

  ident = PACKED RECORD           (* identifier *)
            idname: stringp;
               val: itemref; (* value *)
             plist: itemref; (* property list *)
           funcell: itemref; (* function cell *)
           idhlink: id_ptr;  (* hash link *)
                   END; Apollo Pascal LISP      26 February 1982                        7


4.3. Adding user functions to the kernel 4.3. Adding user functions to the kernel 4.3. Adding user functions to the kernel

  It  is  fairly  easy  to  add handcoded Pascal functions to the
kernel so that  they  can  be  called  from  LISP.  For  example,
consider  adding  the  function  SQR(x), that squares its integer
argument.  Since SQR is already the name of  an  existing  PASCAL
function, we will call it "Xsqr" in PASCAL, and SQR in LISP.


  The  function  Xsqr  has  to take its argument from R[1], check
that it is an intege, square the information part, and  retag  as
integer:


PROCEDURE Xsqr;
    VAR i1 : longint;

    BEGIN
    int_val(r[1], i1);  (* Test type and extract Info *)
    mkint(i1 * i1, 1)   (* Square, retag, and put in R[1] *)
    END;


  Now  procedure  Xsqr  needs be to be installed into the EXECUTE
table, so that it can be found as the N'th code item. The  number
of  defined procedures will have to be increased by 1 in the 3'rd
line of  procedure  EXECUTE,  (currently  201  defined),  and  an
additional case added:


202:    Xsqr;


  Note  also  that  this  table  gives the Internal names of each
available procedure, should one of  these  be  required  in  your
handcoded  procedure.    Finally,  the Identifier SQR needs to be
associated with case 202 in PASLSP.INI.  Note that PASLAP.INI has
3 tables of objects, each prefixed by a count and terminated by a
0. The first is the Random ID table, consisting of  special  ID's
used  for  messages  etc.  The  second  block is for S-expression
constants, which get  loaded  into  the  base  of  the  stack  as
Globals.  The next batch are the names of LISP callable functions
in the order  corresponding  to  the  EXECUTE  procedure.  Simply
modify  the  count  form 201 to 202 (or whatever), and add SQR at
the end, just before the 0.


  In general, look for  a  sample  procedure  in  the  kernel  if
possible,  or  in  the  compiled part (although these are hard to
follow), and adapt to the specific needs. Note  the  use  of  the
ALLOC(n)  and  DEALLOC(n)  procedures  to  allocate  a  block  of
temporaries on the stack.  These  should  be  used,  rather  than Apollo Pascal LISP      26 February 1982                        8


PASCAL  VAR's, since the garbage collector may need to trace from
one of the saved objects.



5. Future work on PASLSP 5. Future work on PASLSP 5. Future work on PASLSP

  PASLSP V2 is based on a fairly old model of  a  portable  LISP,
and  has been used mainly to explore the capbilities of PASCAL as
a target language. In particular, V2 PASCAL is not  yet  powerful
enough to run the PLC compiler itself; instead, the PLC is run on
our  PSL  system on the DEC-20. In order for the full benefits of
PASLSP (or PSL) to be  realized,  the  user  should  be  able  to
compile  his  own LISP modules into PASCAL and link them with the
kernel.  In order to make the system  even  more  adapatable,  we
would  like  to  write even less of the kernel in PASCAL by hand.
This goal has lead us to the development of PSL.


5.1. Goals of the Utah PSL Project 5.1. Goals of the Utah PSL Project 5.1. Goals of the Utah PSL Project

  The goal of the PSL project is  to  produce  an  efficient  and
transportable Standard LISP system that may be used to:


   a. Experimentally    explore    a    variety    of   LISP
      implementation issues  (storage  management,  binding,
      environments, etc.).

   b. Effectively   support   the  REDUCE  computer  algebra
      system [6] on a number of machines.

   c. Provide the same,  uniform,  modern  LISP  programming
      environment  on  all  of  the  machines  that  we  use
      (DEC-20, VAX/750, PDP-11/45, PERQ, and Apollo), of the
      power  and  complexity  of  UCI-LISP,   FranzLISP   or
      MACLISP, with some extensions and enhancements derived
      from LISP Machine LISP or CommonLISP.


                                                      entire                                                       entire   The  approach  we  have  been using is to write the entire LISP
system in PSL (using LISP extensions  for  dealing  with  machine
words  and operations), and to bootstrap it to the desired target
machine in two steps:


   a. Cross compile an appropriate kernel  to  the  assembly
      language of the target machine;

   b. Once  the  kernel  is running, use a resident compiler
      and loader, or fast-loader, to build the rest  of  the
      system. Apollo Pascal LISP      26 February 1982                        9


  The  PASLSP  system,  and other early implementations, have the
problem that the implementation language (PASCAL) is  a  distinct
language  from  LISP, so that communication between "system" code
and "LISP" code was difficult.  We have incorporated all  of  the
good  features of the earlier work into a new efficient LISP-like
systems  language,  SYSLISP,  recoded  all  useful  modules  into
SYSLISP,  and  proceeded  from there.  SYSLISP currently produces
targeted  assembly  code;  earlier  verisions  were  targeted  at
high-level languages such as FORTRAN, PASCAL, C or ADA.  The goal
is  a  portability  strategy  that  leads  to an efficient enough
system  for  a  production  quality,  yet  portable  system.   We
currently  think of the extensions to Standard LISP as having two
levels: the SYSLISP level,  dealing  with  words  and  bytes  and
machine  operations,  enabling us to write essentially all of the
kernel in Standard LISP; and, the LISP level,  incorporating  all
of  the features that make PSL into a modern LISP.  Both modes of
PSL are compiled by an improved version of the Portable  Standard
LISP  Compiler.  The  SYSLISP  mode  of  the  PSL  compiler  does
compile-time  folding  of  constants,  and   more   comprehensive
register  allocation  than  the previous LISP-only version of the
compiler.


  The current state of PSL is fully described  in  an  "overview"
document  obtainable from the authors [5].  Currently PSL runs on
the DEC-20 under TOPS-20, and on the DEC VAX-11/750  under  Unix.
We  are  now concentrating on the MC68000 PSL for the Apollo. All
of the code-generators and assembler support is complete,  and  a
number  of  large  files have been compiled from LISP to assembly
code, and correctly assembled and executed on the Apollo, testing
basic I/O and arithmetic. We are now in the  process  of  writing
the  PSL  support code (small functions in LAP), and testing that
various decisions about register and memory  usage  are  correct.
Based  on  the  development  history on the VAX, we are about 1-2
months away from a preliminary PSL on the Apollo.



6. References 6. References 6. References

[1]   Benson, E. and Griss, M. L.
      _______  _ ________ ____ _____ _______ ______________       SYSLISP: A portable LISP based systems implementation
         ________          language.
      Utah Symbolic Computation Group, Report UCP-81, University
         of Utah, February, 1981.

[2]   Brandt, R. C. and Knapp, B. H.
      The University of Utah Video Computer Authoring System.
         ___________ __ ___ _________ __ ________ __________       In Proceedings of the Symposium on Learning Technology,
         pages 18-23.  Orlando, Florida, Feb, 1981. Apollo Pascal LISP      26 February 1982                       10


[3]   Griss, M. L.; Kessler, R. R.; and Maguire, G. Q. Jr.
      TLISP - A Portable LISP Implemented in P-code.
         ___________ __ _______ __       In Proceedings of EUROSAM 79, pages 490-502.  ACM, June,
         1979.

[4]   Griss, M. L. and Morrison, B.
      ___ ________ ________ ____ _____ ______       The Portable Standard LISP Users Manual.
      Utah Symbolic Computation Group,  TR-10, University of
         Utah, March, 1981.

[5]   Griss, M. L.
      ________ ________ ____  _ _____ ________       Portable Standard LISP: A Brief Overview.
      Utah Symbolic Computation Group, Operating Note 58,
         University of Utah, October, 1981.

[6]   Hearn, A. C.
      ______ _ _____ ______       REDUCE 2 Users Manual.
      Utah Symbolic Computation Group UCP-19, University of Utah,
         1973.

[7]   Marti, J. B., et al.
      Standard LISP Report.
      _______ _______       SIGPLAN Notices 14(10):48-68, October, 1979.



APPENDIX A:  A List of Current PASLSP Functions and Globals APPENDIX A:  A List of Current PASLSP Functions and Globals APPENDIX A:  A List of Current PASLSP Functions and Globals


____ ________ __________ ___ ________ ____ ______ Lisp Callable Functions, see Standard LISP Report
!*FIRST!-PROCEDURE      The top loop LISP reader
ABS
ADD1
AND
APPEND
APPLY
APPLY1                  (APPLY f (LIST u))
ASSOC
ATOM
ATSOC
CAAAAR
CAAADR
CAAAR
CAADAR
CAADDR
CAADR
CAAR
CADAAR
CADADR
CADAR
CADDAR
CADDDR Apollo Pascal LISP      26 February 1982                       11


CADDR
CADR
CAR
CATCH
CDAAAR
CDAADR
CDAAR
CDADAR
CDADDR
CDADR
CDAR
CDDAAR
CDDADR
CDDAR
CDDDAR
CDDDDR
CDDDR
CDDR
CDR
CLOSE
CODEP
COMPRESS
COND
CONS
CONSTANTP
DE
DEFLIST
DELATQ          (DELATQ 'X alist) deletes (X . any) from alist
DELETE
DELQ             Efficient DELETE (using EQ)
DF
DIFFERENCE
DIGIT
DIVIDE
DM
DN
DSKIN           (DSKIN file-id)
EOFP            (EOFP channel)
EQ
EQCAR
EQN
EQUAL
ERROR
ERRORSET
ERRPRT           Prints message with *'s
EVAL
EVLAM            Evaluates a LAMBDA expression
EVLIS
EXPAND
EXPLODE
EXPT
FASTSTAT        Prints RECLAIM message Apollo Pascal LISP      26 February 1982                       12


FIX
FIXP
FLAG
FLAG1           (FLAG (LIST x) y)
FLAGP
FLOAT
FLOATP
FLUID
FLUIDP
FUNCELL         Accesses function cell
FUNCTION
GENSYM
GET
GETD
GETV
GLOBAL
GLOBALP
GO
GREATERP
IDP
INTERN
LBIND1          Binds a single ID in LAMBDA
LBINDN
LENGTH
LESSP
LIST2           For efficent LIST compilation
LIST3
LIST4
LIST5
LITER
MAP
MAPC
MAPCAN
MAPCAR
MAPCON
MAPLIST
MAX
MAX2
MEMBER
MEMQ
MIN
MIN2
MINUS
MINUSP
MKVECT
MSGPRT
NCONC
NCONS
NOT
NULL
NUMBERP
ONEP Apollo Pascal LISP      26 February 1982                       13


OPEN
OR
ORDERP
P!.N                    Evaluates Implicit PROGNs
PAIR
PAIRP
PBIND1                  PROG binding
PBINDN
PLIST                   Access full property list
PLUS
PLUS2
PRIN1
PRIN2
PRIN2T
PRIN2TL
PRINC
PRINT
PROG
PROG2
PROGG0131
PROGN
PUT
PUTC
PUTD
PUTL
PUTV
QUOTIENT
RDEVPR          A read-eval-print loop
RDS
RDTOK
READ
READCH
RECLAIM
REMAINDER
REMD
REMFLAG
REMFLAG1
REMOB
REMPROP
RETURN
REV
REVERSE
REVX
RLIST
RPLACA
RPLACD
SASSOC
SET
SETFUNCELL
SETPLIST
SETVALUE
STRINGP         Equivalent to IDP Apollo Pascal LISP      26 February 1982                       14


SUB1
SUBLIS
SUBST
TCATCH
TERPRI
THROW
TIMES
TIMES2
TOKEN
TTHROW
UNBIND1
UNBINDN
UNBINDTO
UNFLUID
UPBV
VALUE
VECTORP
WHILE
WRS
WRTOK
XAPPLY
XCONS
ZEROP
___________ _______ Interesting Globals
!*RAISE         Raise lower case typing to upper case if not NIL
!*ECHO          Selected input to selected output if not NIL.
BSTK!*          Holds old values of rebound IDS
EMSG!*          Error message in most recent call on ERROR
ENUM!*          Error number in most recent call on ERROR.
INITFORM!*      First Expression EVAL'ed
THROWING!*      Indicates if throwing
THROWTAG!*      Indicates TAG in TTHROW
TOK!*           Holds last token scanned
TOKTYPE         Indicates type of token scanned:
                        1: integer
                        2: id
                        3: character Apollo Pascal LISP      26 February 1982                        i


                        Table of Contents                         Table of Contents                         Table of Contents

1. Introduction                                                 1
     1.1. History of PASLSP                                     1
     1.2. Acknowledgement                                       2
2. Features of PASLSP and relation to Standard LISP             2
3. Using PASLSP on the Apollo DOMAIN                            3
4. Implementation of PASLSP                                     5
     4.1. Building PASLSP                                       5
     4.2. Internal data structures                              6
     4.3. Adding user functions to the kernel                   7
5. Future work on PASLSP                                        8
     5.1. Goals of the Utah PSL Project                         8
6. References                                                   9
APPENDIX A:  A List of Current PASLSP Functions and Globals    10

Added perq-pascal-lisp-project/apollo-paslsp.mss version [960b88068d].























































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
@Device(lpt)
@style(justification yes)
@style(spacing 1)
@use(Bibliography "<griss.docs>mtlisp.bib")
@make(article)
@modify(enumerate,numbered=<@a. @,@i. >, spread 1)
@modify(appendix,numbered=<APPENDIX @A: >)
@modify(itemize,spread 1)
@modify(description,leftmargin +2.0 inch,indent -2.0 inch)
@define(up,use text,capitalized on,  break off)
@define(mac,use text, underline off,  break off)
@define(LISPmac,use text, underline alphanumerics,  break off)
@pageheading(Left  "Utah Symbolic Computation Group",
             Right "December 1981", 
             Line "Operating Note 60"
            )
@set(page=1)
@newpage()
@begin(titlepage)
@begin(titlebox)
@b(A PASCAL Based Standard LISP for the Apollo Domain)
@center[
by

M. L. Griss and R. Ottenheimer

Department of Computer Science
University of Utah
Salt Lake City, Utah 84112

@b(Preliminary  Version)

Last Revision: @value(date)]

@end(titlebox)
@begin(abstract)
This report describes an interim implementation of Standard LISP for the
Apollo DOMAIN. This LISP is based upon the Standard LISP report, and a
newly developing Portable Standard LISP.  This interim implementation is
designed to explore LISP implementations in PASCAL on the Apollo DOMAIN and
similar machines.  The system consists of a kernel, handcoded in PASCAL,
with the rest of the system written in LISP and compiled to PASCAL.
@End(abstract)
@begin(Researchcredit)
Work supported in part by the National Science Foundation
under Grant No. MCS80-07034.
@end(Researchcredit)
@end(titlepage)
@pageheading(Left "Apollo Pascal LISP",Center "@value(date)",
             Right "@value(Page)"
            )
@set(page=1)
@newpage
@section(Introduction)
In this preliminary report, we describe an implementation of Standard LISP
in PASCAL, PASLSP. Versions of PASLSP have been run on a number of
machines, ranging from an LSI-11 based TERAK to Apollo and PERQ. This report
concentrates on the Apollo DOMAIN implementation. This report is to be read in
conjunction with the Standard LISP report@cite(Marti79); we will
highlight the differences from the functions documented in the Standard
LISP, describe the implementation strategy, and discuss future work.

PASLSP is based on a series of small and medium sized LISP interpreters
that have been developed at the University of Utah to explore LISP
implementations in higher level languages. Each of these LISP systems
consists of a small kernel handcoded in some language, with the rest of the
system written in LISP and compiled to the target language.  We have used
FORTRAN, PASCAL and assembly language as targets. The PASLSP series use
PASCAL for the kernel, and have a LISP to PASCAL compiler for the rest of
the system. 

Recent work has concentrated on reducing the size of the hand-coded kernel,
and extending the compiler to handle systems level constructs. This has
resulted in a new Portable Standard LISP, PSL, running on the DEC-20 and
VAX-11/750@cite(Benson81,Griss81). An implementation of PSL for MC68000 is
underway. The PSL system is a modern, efficient LISP, written entirely in
itself; it uses an efficient LISP to machine code compiler to produce the
kernel, and then the rest of LISP is loaded. In the future we hope to
produce a complete PSL targeted at a higher level languages, such as
PASCAL, C or ADA, and this will replace the current PASLSP.

@subsection(History of PASLSP)
The system now called PASLSP was originally developed (by M. Griss and W.
Galway), as a small LISP like kernel to support a small computer algebra
system on an LSI-11 TERAK; this was to be used as an answer analysis module
within a CAI system@cite(Brandt81), written entirely in PASCAL. It was
decided to hand-code a very small kernel, and compile additional functions
written in LISP (LISP support functions, parser and
simplifier) to PASCAL,
using a modified Portable LISP compiler@cite(griss79). This version (call
it V0) did not even have user defined functions, since space on the TERAK
was at a premium.

About June 1981, PASLSP came to the attention of a number people evaluating
Apollo's and PERQ's, and it was suggested that we enhance V0 PASLSP for
this purpose. During the space of a few days, features taken from the
Standard LISP Report and newly developing PSL files were added to produce
PASLSP-V1, running on a DEC-20 and Terak. This was a fairly complete LISP
(including Catch and Throw), but lacked a few features (OPEN, CLOSE, RDS,
WRS, PROG, GO, RETURN, COMPRESS, EXPLODE, Vectors and Strings, etc.).  V1
PASLSP was adapted to a PERQ, VAX and Apollo by Paul Milazo of Schlumberge
in the space of a few weeks (we did not have a PERQ or Apollo at that
time).

We subsequently obtained a PERQ and an Apollo, and recent work has been
aimed at producing an enhanced PASLSP for these machines, maintaining all
versions in one set of source files.  The current system, PASLSP-V2, is
produced from a single PASCAL kernel and set of LISP support files; the
machine specific features are handled by a simple Source Code
Conditionalizer, changing the definition of certain constants and data
types. Only a few features of the Standard LISP report are missing,
and there are a number of additions.

@subsection(Acknowledgement)

We would like to acknowledge the contributions and support of
Eric Benson, Dick Brandt, Will Galway,   and Paul Milazo.

@section(Features of PASLSP and relation to Standard LISP)
PASLSP as far as possible provides all the functions mentioned
in the attached Standard LISP Report (note the hand-written
comments added to this appendix); some of the functions are simply
stubs, so that a Standard LISP Test-file can be run without major
modification.

PASLSP-V2  does not implement the following features of Standard LISP:
@begin(enumeration,spread 0)
VECTORS (only a simple garbage collector is used).

Strings are implemented as identifiers (not garbage collected).

Integers are limited in size (INTs and FIXNUMs, no BIGNUMs).

FLOATING Point is not implemented.

IDs can not be REMOB'ed or INTERN'd.

Only 3 Input Channels and 2 Output Channels are available to OPEN,
RDS, WRS, and CLOSE. Thus file input statements can not be nested
very deeply in files.

Line, Page and Character counting (POSN, LPOSN, etc) are not implemented.
@end(enumeration)

PASLSP-V2 provides some extensions over Standard LISP:
@begin(enumerate,spread 0)
(CATCH form) and (THROW form) and the tagged versions: (TCATCH tag form)
and (TTHROW tag form) are used to implement error and errorset, 
and higher level control functions.

Implicit PROGN in COND, and LAMBDA expressions.

(WHILE pred action-1 action-2 ... action-n).

(DSKIN 'filename) or (DSKIN "filename")
@end(enumerate)

PASLSP-V2 has not been extensively tested, and there may still be a number
of bugs. While some effort has been spent in adjusting PASLSP to the Apollo
DOMAIN, it is clear that the various heap sizes are not yet optimal. 
See appendix A for current list of functions, and appendix B for a copy
of the Standard LISP Report annotated to reflect the current status of 
PASLSP.

@section(Using PASLSP on the Apollo DOMAIN)
	Initializing the system from the floppy looks like this:
@begin(verbatim)
Create a directory (call it pl):
	crd /pl
Mount the floppy:
	mtvol f 1 /f
Copy the files of interest:
	cpt /f/pascallisp /pl

    The files copied will be: paslsp (executable file)
                              paslsp.ini (initialization file)
                              paslsp.tst (a test file)
@end(verbatim)

Run paslsp as you would any other file.  If you
get an error it is most likely because the paslsp.ini file couldn't be found.
If this happens, locate paslsp.ini and try again.  If it still hangs,
try calling Ralph Ottenheimer at (801) 355-0226 or M. Griss at (801) 581-6542.


Previously prepared files of LISP (e.g., library procedures)
can be input by
using the function "DSKIN".  For Example,
@begin(verbatim)
(DSKIN 'Paslsp!.tst) or (DSKIN "Paslsp.tst")
@end
would load the paslsp test file. The PASLSP test is adapted from an extensive
test of Standard LISP (avoiding features not yet implemented).  This is a
good excercise, try it. [Note that if the filename is given as an ID,
that special characters should be prefaced by an "escape character",
! . This is  also the case for filenames in OPEN.  Alternately the string
form may be used, in that case special characters need not be escaped.]

  Paslsp is "case-sensitive" with regard to identifiers.  All of the
kernel procedures have upper-case identifiers associated with them.  This
means that ordinarily the expression (dskin 'paslsp!.tst) would not be
recognized since "dskin" is in lowercase.  However, there is a global flag
!*RAISE which if true will convert all lower-case typin to upper-case.
This Apollo DOMAIN paslsp implementation sets !*RAISE to T as a default by
having (SETQ !*RAISE T) in the paslsp.ini file.  You may put any special
initialization code you like at the end of paslsp.ini as indicated by the
comments in the file.
Toggling would be accomplished by typing the following lisp-expressions:
@begin(verbatim)
	(ON !*RAISE)     equivalent to  (SETQ !*RAISE T)
        (OFF !*RAISE)    equivalent to  (SETQ !*RAISE NIL)
@end(verbatim)

	Any Apollo DOMAIN filename (60 characters maximum)is allowable
 as a paslsp filename.
Remember to prefix all special characters with an exclamation-mark: "!". 
Special characters include all non-alphanumerics. For example: !*RAISE
 goforit!! paslsp!.test !/login!/smith!/foo!.sl .

If the global !*ECHO is not NIL (default is NIL), input will be echoed to
the selected output channel.  It is sometimes convienient to put:
@begin(verbatim)
        (SETQ !*ECHO T)
@end(verbatim)
at the beginning of a file to be read by DSKIN, and:
@begin(verbatim)
        (SETQ !*ECHO NIL)
@end(verbatim)
at the end.  This will echo the file to the screen (or to a file) as it is
read. 

Certain low level errors do not display any explanatory message but
instead display a numeric code (such as *** # 2), below is a summary of these
codes and their meanings:

@begin(verbatim)
  (* error codes.  corresponding to tag = errtag. *)
  noprspace = 1;    (* no more "pair space"--can't cons. *)
  notpair = 2;      (* a pair operation attempted on non-pair.*)
  noidspace = 3;    (* no more free identifiers *)
  undefined = 4;    (* used to mark undefined function cells *)
  noint = 5;        (* no free integer space after gc. *)
  notid = 6;        (* id was expected *)
@end(verbatim)


@section(Implementation of PASLSP)
@subsection(Building PASLSP)
PASLSP is built in the following steps:

@u(Kernel files), PAS0.PRE, and trailer file (main program) PASN.PRE
are run through a filter program to produce PAS0.PAS and PASN.PAS,
tailored to the Apollo DOMAIN (appropriate Include files, Consts, etc).
This kernel provides the Basic I/O (Token reading and printing),
handcoded storage allocator and garbage collector, lowlevel arithmetic
primitives, lowlevel calls (via Case statement) from LISP to kernel, etc.

@u(Rest of LISP), currently files PAS1.RED, PAS2.RED and PAS3.RED are
compiled to PASCAL using a version of the Portable LISP Compiler
(PLC)@cite(griss79). During compilation, a Symbol Table file, PASn.SYM is
read in and written out. These files record (for "incremental" compilation)
the names and ID table locations of each ID encountered, so that the compiler
can refer to an ID by its offset in the ID table. LISP constants are also
recorded in the PASn.SYM files. PAS0.SYM is modified by hand as the kernel
is changed.  

The compilation model used is that of a Register Machine: Arguments to LISP
functions are passed in registers (a PASCAL array), and the result returned
in Register 1. Space is allocated on a software stack (not the PASCAL
recursion stack), for any temporaries or save arguments required. Short
functions usually do not require any stack. The reason for this choice was
the existence of the PLC (targeted at comventional machines), and the fact
that inline access to the register array compiles quite well, while a
"PUSH/POP" stack would be much less efficient.

@u(Initialization). 
After the PAS0.PAS,..PASN.PAS are produced,
the symbol table file (pas3.sym) is converted into a file
PASLSP.INI, which contains the names of all ID's, the LISP constants
used, and also ID's for all kernel functions that should be known to the
user LISP level. Also produced is a file, EXEC.PAS, that contains a case
statement associating each user callable kernel function with an integer.
The PAS0.PAS ... PASN.PAS and EXEC.PAS are compiled and linked into an
executable file. When this file is executed, PASLSP.INI is read in:
each id is read and stored in the appropriate location in the symbol-table,
the kernel function names have the associated Case index put into
a function cell, and the LISP s-expressions are READ in. Finally,
some s-expressions will be executed (with care, the user can add his own
expressions, including requests to (DSKIN 'library), etc.
@subsection(Internal data structures)
The data spaces (or heaps) in PASLSP are divided into 4 sections: the
pair space, id space (the oblist), string space and large integer
(fixnum) space.  These are all arrays of objects of the appropriate type
(see declarations below).  The system is fully tagged, that is, every LISP
item has associated with it a tag field which denotes the type of the item 
and an 'info' field which either points to the item in an array (in the
case of pairs, identifiers and fixnums), or contains the information 
itself (in the case of inums, character codes and error conditions). The
info field of a code pointer contains the index into a case staement (see
procedure 'execute') by means of which any LISP callable function may be
invoked.

@begin(verbatim,leftmargin 0)
itemref = RECORD
           tag:  integer;   (* Small integer denoting  type.   *)
           info: integer;   (* Item or a pointer to it         *)
                            (* depending upon the type.        *)
          END;

   pair = PACKED RECORD
            prcar: itemref;
            prcdr: itemref;
          END;

  ident = PACKED RECORD           (* identifier *)
            idname: stringp;
               val: itemref; (* value *)
             plist: itemref; (* property list *)
           funcell: itemref; (* function cell *)
           idhlink: id_ptr;  (* hash link *)
                   END;
@end(verbatim)
@subsection(Adding user functions to the kernel)
It is fairly easy to add handcoded Pascal functions to
the kernel so that they can be called from LISP. For example,
consider adding the function SQR(x), that squares its integer argument.
Since SQR is already the name of an existing PASCAL function, we will
call it "Xsqr" in PASCAL, and SQR in LISP.

The function Xsqr has to take its argument from R[1], check that it is an intege, square the information part, and retag as integer:
@begin(verbatim)
PROCEDURE Xsqr;
    VAR i1 : longint;

    BEGIN
    int_val(r[1], i1);  (* Test type and extract Info *)
    mkint(i1 * i1, 1)   (* Square, retag, and put in R[1] *)
    END;
@end(verbatim)

Now procedure Xsqr needs be to be installed into the EXECUTE table, so that
it can be found as the N'th code item. The number of defined procedures
will have to be increased by 1 in the 3'rd line of procedure EXECUTE,
(currently 201 defined), and an additional case added:
@begin(verbatim)
202:    Xsqr;
@end(verbatim)

Note also that this table gives the Internal names of each available
procedure, should one of these be required in your handcoded procedure.
Finally, the Identifier SQR needs to be associated with case 202 in
PASLSP.INI.  Note that PASLAP.INI has 3 tables of objects, each prefixed by
a count and terminated by a 0. The first is the Random ID table, consisting
of special ID's used for messages etc. The second block is for S-expression
constants, which get loaded into the base of the stack as Globals. The
next batch are the names of LISP callable functions in the order
corresponding to the EXECUTE procedure. Simply modify the count form
201 to 202 (or whatever), and add SQR at the end, just before the 0.

In general, look for a sample procedure in the kernel if possible,
or in the compiled part (although these are hard to follow), and adapt
to the specific needs. Note the use of the ALLOC(n) and DEALLOC(n)
procedures to allocate a block of temporaries on the stack.
These should be used, rather than PASCAL VAR's, since the garbage collector
may need to trace from one of the saved objects.
@Section(Future work on PASLSP)
PASLSP V2 is based on a fairly old model of a portable LISP, and
has been used mainly to explore the capbilities of PASCAL as a
target language. In particular, V2 PASCAL is not yet powerful enough to
run the PLC compiler  itself;
instead, the PLC is run on our PSL system on the DEC-20. In order for the
full benefits of PASLSP (or PSL) to be realized, the user should be able to
compile his own LISP modules into PASCAL and link them with the kernel.
In order to make the system even more adapatable, we would like to write
even less of the kernel in PASCAL by hand. This goal has lead us to the
development of PSL. 

@subsection(Goals of the Utah PSL Project)

The goal of the PSL project is to produce an efficient and transportable
Standard LISP system that may be used to:
@begin(enumeration)
Experimentally  explore
a variety of LISP implementation issues (storage management, binding,
environments, etc.).

Effectively support the REDUCE computer algebra system@cite(hearn73)
on a number of machines.

Provide the same, uniform, modern LISP programming environment on all of
the machines that we use (DEC-20, VAX/750, PDP-11/45, PERQ, and Apollo), of
the power and complexity of UCI-LISP, FranzLISP or MACLISP, with some
extensions and enhancements derived from LISP Machine LISP or CommonLISP.
@end(enumeration)

The approach we have been using is to write the @b(entire) LISP system in
PSL (using LISP extensions for dealing with 
machine words and operations), and to bootstrap it to the desired target
machine
in two steps:
@begin(enumeration)
Cross compile an appropriate kernel to the assembly language of the
target machine;

Once the kernel is running, use a resident compiler and loader, or
fast-loader, to build the rest of the system.
@end(enumeration)

 The PASLSP system, and other early implementations, have the problem that
the implementation language (PASCAL) is a distinct language from LISP, so
that communication between "system" code and "LISP" code was difficult.  We
have incorporated all of the good features of the earlier work into a new
efficient LISP-like systems language, SYSLISP, recoded all useful modules
into SYSLISP, and proceeded from there.  SYSLISP currently produces
targeted assembly code; earlier verisions were targeted at high-level
languages such as FORTRAN, PASCAL, C or ADA.  The goal is a portability
strategy that leads to an efficient enough system for a production quality,
yet portable system. We currently think of the extensions to Standard LISP
as having two levels: the SYSLISP level, dealing with words and bytes and
machine operations, enabling us to write essentially all of the kernel in
Standard LISP; and, the LISP level, incorporating all of the features that
make PSL into a modern LISP.  Both modes of PSL are compiled by an improved
version of the Portable Standard LISP Compiler. The SYSLISP mode of the PSL
compiler does compile-time folding of constants, and more comprehensive
register allocation than the previous LISP-only version of the compiler.

The current state of PSL is fully described in an "overview" document
obtainable from the authors @cite(griss81e).  Currently PSL runs on the
DEC-20 under TOPS-20, and on the DEC VAX-11/750 under Unix.  We are now
concentrating on the MC68000 PSL for the Apollo. All of the code-generators
and assembler support is complete, and a number of large files have been
compiled from LISP to assembly code, and correctly assembled and executed
on the Apollo, testing basic I/O and arithmetic. We are now in the process
of writing the PSL support code (small functions in LAP), and testing that
various decisions about register and memory usage are correct. Based on the
development history on the VAX, we are about 1-2 months away from a
preliminary PSL on the Apollo.
@section(References)
@Bibliography
@appendix(A List of Current PASLSP Functions and Globals)
@begin(verbatim,leftmargin 0)
@include(Appendix-A.table)
@end(verbatim)

Added perq-pascal-lisp-project/apollo-paslsp.otl version [e310cc6bc0].







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Comment{OUTLINE of APOLLO-PASLSP.MSS.35 by Scribe 3C(1250) on 26 February 1982 at 14:47}
1. Introduction                                           1 APOLLO-PASLSP.MSS.35 line 54
  1.1. History of PASLSP                                  1 APOLLO-PASLSP.MSS.35 line 82
  1.2. Acknowledgement                                    2 APOLLO-PASLSP.MSS.35 line 114
2. Features of PASLSP and relation to Standard LISP       2 APOLLO-PASLSP.MSS.35 line 119
3. Using PASLSP on the Apollo DOMAIN                      3 APOLLO-PASLSP.MSS.35 line 165
4. Implementation of PASLSP                               5 APOLLO-PASLSP.MSS.35 line 248
  4.1. Building PASLSP                                    5 APOLLO-PASLSP.MSS.35 line 249
  4.2. Internal data structures                           6 APOLLO-PASLSP.MSS.35 line 291
  4.3. Adding user functions to the kernel                7 APOLLO-PASLSP.MSS.35 line 324
5. Future work on PASLSP                                  8 APOLLO-PASLSP.MSS.35 line 367
  5.1. Goals of the Utah PSL Project                      8 APOLLO-PASLSP.MSS.35 line 379
6. References                                             9 APOLLO-PASLSP.MSS.35 line 439
APPENDIX A:  A List of Current PASLSP Functions and Glo  10 APOLLO-PASLSP.MSS.35 line 441
 Table of Contents                                        1 -SCRIBE-SCRATCH-.25-4-1.100025 line 3
	Alphabetic Listing of Cross-Reference Tags and Labels

Tag or Label Name                    Page   Label Value  Source file Location
-----------------------------------------------------------------------------

Added perq-pascal-lisp-project/appendix-a.table version [fc4fc16be9].

















































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
@u[Lisp Callable Functions, see Standard LISP Report]
!*FIRST!-PROCEDURE	The top loop LISP reader
ABS
ADD1
AND
APPEND
APPLY
APPLY1                  (APPLY f (LIST u))
ASSOC
ATOM
ATSOC
CAAAAR
CAAADR
CAAAR
CAADAR
CAADDR
CAADR
CAAR
CADAAR
CADADR
CADAR
CADDAR
CADDDR
CADDR
CADR
CAR
CATCH
CDAAAR
CDAADR
CDAAR
CDADAR
CDADDR
CDADR
CDAR
CDDAAR
CDDADR
CDDAR
CDDDAR
CDDDDR
CDDDR
CDDR
CDR
CLOSE
CODEP
COMPRESS
COND
CONS
CONSTANTP
DE
DEFLIST
DELATQ 		(DELATQ 'X alist) deletes (X . any) from alist
DELETE
DELQ             Efficient DELETE (using EQ)
DF
DIFFERENCE
DIGIT
DIVIDE
DM
DN
DSKIN		(DSKIN file-id)
EOFP            (EOFP channel)
EQ
EQCAR
EQN
EQUAL
ERROR
ERRORSET
ERRPRT           Prints message with *'s
EVAL
EVLAM            Evaluates a LAMBDA expression
EVLIS
EXPAND
EXPLODE
EXPT
FASTSTAT 	Prints RECLAIM message
FIX
FIXP
FLAG
FLAG1	        (FLAG (LIST x) y)
FLAGP
FLOAT
FLOATP
FLUID
FLUIDP
FUNCELL	        Accesses function cell
FUNCTION
GENSYM
GET
GETD
GETV
GLOBAL
GLOBALP
GO
GREATERP
IDP
INTERN
LBIND1		Binds a single ID in LAMBDA
LBINDN
LENGTH
LESSP
LIST2	        For efficent LIST compilation
LIST3
LIST4
LIST5
LITER
MAP
MAPC
MAPCAN
MAPCAR
MAPCON
MAPLIST
MAX
MAX2
MEMBER
MEMQ
MIN
MIN2
MINUS
MINUSP
MKVECT
MSGPRT
NCONC
NCONS
NOT
NULL
NUMBERP
ONEP
OPEN
OR
ORDERP
P!.N			Evaluates Implicit PROGNs
PAIR
PAIRP
PBIND1			PROG binding
PBINDN
PLIST			Access full property list
PLUS
PLUS2
PRIN1
PRIN2
PRIN2T
PRIN2TL
PRINC
PRINT
PROG
PROG2
PROGG0131
PROGN
PUT
PUTC
PUTD
PUTL
PUTV
QUOTIENT
RDEVPR			A read-eval-print loop
RDS
RDTOK
READ
READCH
RECLAIM
REMAINDER
REMD
REMFLAG
REMFLAG1
REMOB
REMPROP
RETURN
REV
REVERSE
REVX
RLIST
RPLACA
RPLACD
SASSOC
SET
SETFUNCELL
SETPLIST
SETVALUE
STRINGP		Equivalent to IDP
SUB1
SUBLIS
SUBST
TCATCH
TERPRI
THROW
TIMES
TIMES2
TOKEN
TTHROW
UNBIND1
UNBINDN
UNBINDTO
UNFLUID
UPBV
VALUE
VECTORP
WHILE
WRS
WRTOK
XAPPLY
XCONS
ZEROP
@u[Interesting Globals]
!*RAISE		Raise lower case typing to upper case if not NIL
!*ECHO          Selected input to selected output if not NIL.
BSTK!*		Holds old values of rebound IDS
EMSG!*		Error message in most recent call on ERROR
ENUM!*		Error number in most recent call on ERROR.
INITFORM!*      First Expression EVAL'ed
THROWING!*	Indicates if throwing
THROWTAG!*      Indicates TAG in TTHROW
TOK!*		Holds last token scanned
TOKTYPE		Indicates type of token scanned:
			1: integer
			2: id
			3: character

Added perq-pascal-lisp-project/componly.bld version [555d07e63d].













>
>
>
>
>
>
1
2
3
4
5
6
pascal
s:PL20.rel
S:PL20.lst
S:PL20.PAS/debug
load S:PL20.REL
save S:PL20.EXE

Added perq-pascal-lisp-project/delete.pas version [f4ac3aa94f].

































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
forward;
(* !(!*ENTRY DELETE EXPR !2!) *)
(*  EXPR DELETE *)
procedure PAS227;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPC G!0!0!9!9 !2 PAIRTAG!) *)
      IF tag_of(R[2]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*JUMP G!0!1!0!1!) *)
      GOTO 102;
(* !(!*LBL G!0!0!9!9!) *)
100: 
(* !(!*LOAD !2 !(CAR !2!)!) *)
   ANYcar(R[2],R[2]);
(* !(!*LINK EQUAL EXPR !2!) *)
     PAS226;
(* !(!*JUMPNIL G!0!1!0!0!) *)
      IF R[1] = nilref THEN GOTO 101;
(* !(!*LOAD !1 !(CDR !-!1!)!) *)
   ANYcdr(stk[st-1],R[1]);
(* !(!*JUMP G!0!1!0!1!) *)
      GOTO 102;
(* !(!*LBL G!0!1!0!0!) *)
101: 
(* !(!*LOAD !2 !(CDR !-!1!)!) *)
   ANYcdr(stk[st-1],R[2]);
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK DELETE EXPR !2!) *)
     PAS227;
(* !(!*LOAD !2 !(CAR !-!1!)!) *)
   ANYcar(stk[st-1],R[2]);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*LBL G!0!1!0!1!) *)
102: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
procedure PAS228;
forward;
(* !(!*ENTRY DELQ EXPR !2!) *)
(*  EXPR DELQ *)
procedure PAS228;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*STORE !2 !0!) *)
      store(2,0);
(* !(!*JUMPC G!0!1!0!5 !2 PAIRTAG!) *)
      IF tag_of(R[2]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*JUMP G!0!1!0!7!) *)
      GOTO 102;
(* !(!*LBL G!0!1!0!5!) *)
100: 
(* !(!*JUMPN G!0!1!0!6 !(CAR !2!)!) *)
   ANYcar(R[2],RXX);
      IF R[1] <> RXX THEN GOTO 101;
(* !(!*LOAD !1 !(CDR !2!)!) *)
   ANYcdr(R[2],R[1]);
(* !(!*JUMP G!0!1!0!7!) *)
      GOTO 102;
(* !(!*LBL G!0!1!0!6!) *)
101: 
(* !(!*LOAD !2 !(CDR !2!)!) *)
   ANYcdr(R[2],R[2]);
(* !(!*LINK DELQ EXPR !2!) *)
     PAS228;
(* !(!*LOAD !2 !(CAR !-!1!)!) *)
   ANYcar(stk[st-1],R[2]);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*LBL G!0!1!0!7!) *)
102: 
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;

Added perq-pascal-lisp-project/draft version [5f78cf2721].













>
>
>
>
>
>
1
2
3
4
5
6
Subject: PASLSP TEST
To: GRISS
cc: CAI.OTTENHEIMER

(DSKIN "PASLSP.TST") croaks on the 20 also, ends up with inf. recursion.

Added perq-pascal-lisp-project/exec.pas version [c3841c4d21].

cannot compute difference between binary files

Added perq-pascal-lisp-project/lspfns.pas version [2044c66832].























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
function caar(x: any): any;
    begin
    caar := car(car(x))
    end;

function cadr(x: any): any;
    begin
    cadr := car(cdr(x))
    end;

function cdar(x: any): any;
    begin
    cdar := car(cdr(x))
    end;

function cddr(x: any): any;
    begin
    cddr := cdr(cdr(x))
    end;

function prin2(x: any): any;
    begin
    end;

function rev(l1: any): any;
    begin
    end;

function notnull(x: any): any;
    begin 
    notnull := x
    end;

function list2(r1, r2: any): any;
    begin
    list2 := cons(r1, ncons(r2))
    end;

function list3(r1, r2, r3: any): any;
    begin
    list3 := cons(r1, list2(r2, r3))
    end;

function list4(r1, r2, r3, r4: any): any;
    begin
    list4 := cons(r1, list3(r2, r3, r4))
    end;

function list5(r1, r2, r3, r4, r5: any): any;
    begin
    list5 := cons(r1, list4(r2, r3, r4, r5))
    end;

function reverse(u: any): any;
    begin
    reverse := rev(u)
    end;

function append(u, v: any): any;
    function append1: any;
        begin
	junk := setq(u, reverse(u));
	while truep(pairp(u)) do
	    begin
	    junk := setq(v, cons(car(u), v));
	    junk := setq(u, cdr(u))	(* a hard case *)
	    end;
	append := v	(* goto also needed? *)
	end;

    begin
    append := append1;
    end;

	(* procedures to support get & put. *)
function memq(u, v: any): any;
    begin
    if truep(xnot(pairp(v))) then memq := v
    else if truep(eq(u, car(v))) then memq := v
    else memq := memq(u, cdr(v))
    end;

function atsoc(u, v: any): any;
    begin
    if truep(xnot(pairp(v))) then atsoc := v
    else if truep(xnot(pairp(v))) or truep(xnot(eq(u, caar(v)))) then
	atsoc := atsoc(u, cdr(v))
    else atsoc := car(v)
    end;

function delq(u, v: any): any;
    begin
    if truep(xnot(pairp(v))) then delq := v
    else if truep(eq(u, car(v))) then delq := cdr(v)
    else delq := cons(car(v), delq(u, cdr(v)))
    end;

function delatq(u, v: any): any;
    begin
    if truep(xnot(pairp(v))) then delatq := v
    else if truep(xnot(pairp(car(v)))) or truep(xnot(eq(u, caar(v)))) then
	delatq := cons(car(v), delatq(u, cdr(v)))
    else delatq := cdr(v)
    end;

function get(u, v:any): any;
    begin
    if truep(xnot(idp(u))) then get := xnil
    else if truep(pairp(setq(u, atsoc(v, plist(u))))) then get := cdr(u)
    else get := xnil
    end;

function put(u, v, ww: any): any;
    function put1: any;
        label 1;
        var l: any;
	begin
	if truep(xnot(idp(u))) then
	    begin
	    put1 := ww;
	    goto 1
	    end;
	junk := setq(l, plist(u));
	if truep(atsoc(v, l)) then junk := delatq(v, l);
	if truep(notnull(ww)) then junk := setq(l, cons(cons(v, ww), l));
	junk := setplist(u, l);
	begin
	put1 := ww;
	goto 1
	end;
	1:
	end;

    begin
    put := put1
    end;

function remprop(u, v: any): any;
    begin
    remprop := put(u, v, xnil)
    end;

function eqcar(u, v: any): any;
    begin
    if truep(pairp(u)) then
	if truep(eq(car(u), v)) then eqcar := t
	else eqcar := xnil
    end;

function null(u: any): any;
    begin
    null := eq(u, xnil)
    end;

function equal(x, y: any): any;
    begin
    if truep(atom(x)) then
	if truep(atom(y)) then
	    equal := eq(x, y)
	else equal := xnil
    else if truep(atom(y)) then equal := xnil
    else if truep(equal(car(x), car(y))) then
	if truep(equal(cdr(x), cdr(y))) then equal := t
	else equal := xnil
    else equal := xnil
    end;

function read;
    begin
    end;

Added perq-pascal-lisp-project/lspker.pas version [75f18e93af].











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
(* include following two lines for terak *)
(*  [$s+] *) (* swapping mode to manage this large file *)
(*  [$g+] *) (* goto is legal *)

PROGRAM Paslsp(symin, input, output);

    (************************************************************)
    (* this file contains global data declarations and          *)
    (* function definitions to support a sub-standard lisp      *)
    (* system.  it is used with a compiler which compiles lisp  *)
    (* to pascal source code. this file is divided into the     *)
    (* following sections:                                      *)
    (*     1. constant, type & global variable declarations.    *)
    (*     2. lisp item selectors & constructors - these are    *)
    (*        the functions which know about the internal       *)
    (*        (pascal) representation of lisp data primitives.  *)
    (*        currently these are: integers (-4096..4095),      *)
    (*        characters, dotted pairs, identifiers,            *)
    (*        code pointers, error conditions, large integers & *)
    (*        floating point numbers (most hooks exist).        *)
    (*     3. stack allocation - variables local to a function  *)
    (*        are kept on a stack.                              *)
    (*     4. the garbage collector.                            *)
    (*     5. identifier lookup & entry - symbol table          *)
    (*        management.                                       *)
    (*     6. standard lisp functions - pascal implementations  *)
    (*        taking lisp items as arguments and returning a    *)
    (*        lisp item. more standard lisp functions are found *)
    (*        in lspfns.red.                                    *)
    (*     7. i/o primitives (not callable from lisp functions).*)
    (*     8. a lisp callable token scanner.                    *)
    (*     9. initialization.                                   *)
    (*    10. apply                                             *)
    (************************************************************)
    (* symin is input channel one--used to initialize "symbol   *)
    (* table".  input is input channel two--standard input.     *)
    (* output is output channel one--the standard output.       *)
    (************************************************************)
    (* written by martin l. griss, william f. galway and        *)
    (* ralph ottenheimer.                                       *)
    (* last changed 16 june 1981                                *)
    (************************************************************)

CONST

    (* constants relating to input / output *)
    sp = ' ';
    nul = 0;          (* ascii codes *)
    ht = 9;
    lf = 10;
    cr = 13;

    inchns = 2;       (* number of input channels.  *)
    outchns = 1;      (* number of output channels. *)
    eofcode = 26;     (* magic character code for eof, ascii for *)
    (*                   cntrl-z.   kludge, see note in rdtok.  *)
    choffset = 1;     (* add choffset to ascii code to get address  *)
    (*                   in id space for corresponding identifier.  *)
    eos = nul;        (* terminator character for strings. *)

    (* constants relating to the token scanner *)
    toktype  =  129; (* slot in idspace for toktype. *)
    chartype  =  3;   (* various token types *)
    inttype  =  1;
    idtype  =  2;

    (* constants relating to lisp data types and their representations. *)
    shift_const = 8192; (* tags and info are packed into an integer *)
    (* assumed to be at least 16 bits long.  low order 13 bits  *)
    (* are the info, top 3 are the tag.                         *)
    int_offset = 4096;  (* small integers are stored 0..8191    *)
    (* instead of -4096..4095 because it will pack smaller      *)
    (* under ucsd pascal.                                       *)
    end_flag = -1;  (* marks end of fixnum free list. *)

    (* the various tags - can't use a defined scalar type *)
    (* because of the lack of convertion functions.       *)
    inttag = 0;    (* info is an integer                  *)
    chartag = 1;   (* info is a character code            *)
    pairtag = 2;   (* info points to pair                 *)
    idtag = 3;     (* info points to identifier           *)
    codetag = 4;   (* info is index into a case statement *)
    (*                that calls appropriate function.    *)
    errtag = 5;    (* info is an error code - see below.  *)
    fixtag = 6;    (* info points to a full word (or      *)
    (*                longer) integer.                    *)
    flotag = 7;    (* info points to a float number.      *)

    (* error codes.  corresponding to tag = errtag.  *)
    noprspace = 1;    (* no more "pair space"--can't cons. *)
    notpair = 2;      (* a pair operation attempted on a non-pair. *)
    noidspace = 3;    (* no more free identifiers *)
    undefined = 4;    (* used to mark undefined function cells (etc?) *)

    (* constants relating to data space *)
    maxpair = 2500;   (* max number of pairs allowed. *)
    maxident = 400;   (* max number of identifiers *)
    maxstrsp = 2000;  (* size of string (literal) storage space. *)
    maxintsp = 50;    (* max number of long integers allowed *)
    maxflosp = 2;     (* max number of floating numbers allowed *)
    maxgcstk = 100;   (* size of garbage collection stack.    *)
    stksize = 500;    (* stack size *)

    (* constants relating to the symbol table. *)
    hidmax = 50;      (* number of hash values for identifiers *)
    nillnk = 0;       (* when integers are used as pointers.  *)


TYPE
    onechar = char;

    (* note we allow zero for id_ptr, allowing a "nil" link. *)
    stringp = 1..maxstrsp;        (* pointer into string space. *)
    id_ptr = 0..maxident;         (* pointer into id space. *)

    any = integer;  (* your basic lisp item *)
    itemtype = 0..7;    (* the tags *)


    pair = PACKED RECORD
		      prcar: any;
		      prcdr: any;
		      markflg: boolean;        (* for garbage collection   *)
		  END;


    ascfile = PACKED FILE OF onechar;

    ident = PACKED RECORD           (* identifier *)
		       idname: stringp;
		       val: any;       (* value *)
		       plist: any;     (* property list *)
		       funcell: any;   (* function cell *)
		       idhlink: id_ptr;    (* hash link *)
		   END;
    longint = integer;  (* use integer[n] on terak *)

VAR
    (* global information *)
    xnil, t: any;    (* refers to identifiers "nil", and "t". *)
    junk: any;     (* global to hold uneeded function results *)
    old_binds: any;	(* saved fluid bindings *)

    (* "st" is the stack pointer into "stk".  it counts the number of  *)
    (* items on the stack, so it runs from zero while the stack starts *)
    (* at one.                                                         *)
    st: 0..stksize;
    stk: ARRAY[1..stksize] OF any;

    (* pair space *)
    prspace: PACKED ARRAY[1..maxpair] OF pair; (* all pairs stored here. *)
    freepair: integer;          (* pointer to next free pair in prspace. *)

    (* identifier space *)
    idhead: ARRAY[0..hidmax] OF id_ptr;
    idspace: PACKED ARRAY[1..maxident] OF ident;
    freeident: integer;

    (* string space *)
    strspace: PACKED ARRAY[1..maxstrsp] OF onechar;
    freestr: stringp;

    (* large integer space *)
    intspace: ARRAY[1..maxintsp] OF longint;
    freeint: 1..maxintsp;

    (* floating point number space *)
    flospace: ARRAY[1..maxflosp] OF real;
    freefloat: 1..maxflosp;

    (* i/o channels *)
    symin: ascfile;
    input: ascfile; (* comment out for terak. *)

    inchnl: 1..inchns;      (* current input channel number  *)
    outchnl: 1..outchns;    (* current output channel number *)

    (* "current character" for each input channel.                    *)
    (* may want to include more than one character at some later date *)
    (* (for more lookahead).                                          *)
    ichrbuf: ARRAY[1..inchns] OF onechar;

    (* for collecting statistics. *)
    gccount: integer;           (* counts garbage collections *)
    (* counts from last garbage collection. *)
    consknt: integer;           (* number of times "cons" called *)
    pairknt: integer;           (* number of pairs created *)


    (********************************************************)
    (*                                                      *)
    (*             item selectors & constructors            *)
    (*                                                      *)
    (********************************************************)

FUNCTION Truep(predicate: any): boolean;
    BEGIN (* truep *)
    Truep := predicate <> xnil
    END  (* truep *);

FUNCTION Falsep(predicate: any): boolean;
    BEGIN (* Falsep *)
    Falsep := predicate = xnil
    END (* Falsep *);

FUNCTION Tag_of(item: any): itemtype;
    BEGIN (* tag_of *)
    Tag_of := item DIV shift_const;
    END;
    (* tag_of *)

FUNCTION Info_of(item: any): integer;
    BEGIN (* info_of *)
    IF item DIV shift_const = inttag THEN
	Info_of := item MOD shift_const - int_offset
    ELSE
	Info_of := item MOD shift_const
    END;
    (* info_of *)

FUNCTION Mkitem(tag: itemtype; info: longint): any;
    (* do range checking on info. ints run from -4096 to +4095 *)
    (* everything else runs from 0 to 8191. ints & chars       *)
    (* contain their info, all others points into an           *)
    (* appropriate space.                                      *)

    BEGIN (* mkitem *)
    IF info < 0 THEN        (* this check probably not necessary *)
	Writeln('*****MKITEM: BAD NEG');

    (* pack tag and info into 16-bit item.   *)
    Mkitem := tag * shift_const + info
    END    (* mkitem *);


PROCEDURE Set_info(VAR item: any; newinfo: longint);
    BEGIN (* set_info *)
    item := Mkitem(Tag_of(item), newinfo)
    END;
    (* set_info *)

PROCEDURE Set_tag(VAR item: any; newtag: itemtype);
    BEGIN (* set_tag *)
    item := Mkitem(newtag, Info_of(item))
    END;
    (* set_tag *)

FUNCTION Mkident(id: integer): any;
    BEGIN       (* mkident *)
    Mkident := Mkitem(idtag, id);
    END;
    (* mkident *)

FUNCTION Car(u: any): any; FORWARD;
FUNCTION Cdr(u: any): any; FORWARD;
FUNCTION Pairp(item: any): any; FORWARD;

FUNCTION Mkfixint(fixint: longint): any;
    VAR p: integer;

    PROCEDURE Gc_int;       (* Garbage collect large integer space. *)
	VAR i: integer;
	    mark_flag: PACKED ARRAY[1..maxintsp] OF boolean;

	PROCEDURE Mark(u: any);
	    BEGIN (* mark *)
	    IF Truep(Pairp(u)) THEN
		BEGIN
		Mark(Car(u));
		Mark(Cdr(u))
		END
	    ELSE IF Tag_of(u) = fixtag THEN
		mark_flag[Info_of(u)] := true
	    END; (* mark *)

	BEGIN (* gc_int *)
	FOR i := 1 TO maxintsp DO       (* clear mark flags *)
	    mark_flag[i] := false;

	FOR i := 1 TO st DO             (* mark from the stack *)
	    Mark(stk[i]);

	FOR i := 1 TO maxident DO       (* mark from the symbol table *)
	    BEGIN
	    Mark(idspace[i].val);
	    Mark(idspace[i].plist);
	    Mark(idspace[i].funcell)
	    END;

	(* reconstruct free list *)
	FOR i := 1 TO maxintsp - 1 DO
	    IF NOT mark_flag[i] THEN
		BEGIN
		intspace[i] := freeint;
		freeint := i
		END
	END; (* gc_int *)


    BEGIN (* mkfixint *)
    IF intspace[freeint] = end_flag THEN Gc_int;
    IF intspace[freeint] <> end_flag THEN     (* convert to fixnum *)
	BEGIN
	p := freeint;
	freeint := intspace[freeint];
	Mkfixint := Mkitem(fixtag, p);
	intspace[p] := fixint
	END
    ELSE Writeln('*****FIXNUM SPACE EXHAUSTED')
    END  (* mkfixint *);

FUNCTION Mkint(int: longint): any;
    BEGIN       (* mkint *)
    IF (int < -int_offset) OR (int > int_offset - 1) THEN
	Mkint := Mkfixint(int)
    ELSE
	Mkint := Mkitem(inttag, int + int_offset)
	(* int was in range so add offset *)
    END    (* mkint *);

FUNCTION Mkpair(pr: integer): any;
    BEGIN (* mkpair *)
    Mkpair := Mkitem(pairtag, pr)
    END;
    (* mkpair *)

PROCEDURE Int_val(item: any; VAR number: longint);
    (* returns integer value of item (int or fixnum). *)
    (* must return 'number' in var parameter instead  *)
    (* of function value since long integers are not  *)
    (* a legal function type in ucsd pascal.          *)
    BEGIN (* int_val *)
    IF Tag_of(item) = inttag THEN
	number := Info_of(item)
    ELSE IF Tag_of(item) = fixtag THEN
	number := intspace[Info_of(item)]
    ELSE Writeln('***** ILLEGAL DATA TYPE FOR NUMERIC OPERATION')
    END    (* int_val *);


    (********************************************************)
    (*                                                      *)
    (*                  stack allocation                    *)
    (*                                                      *)
    (********************************************************)

PROCEDURE Alloc(n: integer);
    BEGIN
    IF n + st <= stksize THEN
	st := n+st
    ELSE
	BEGIN
	Writeln('*****LISP STACK OVERFLOW');
	Writeln('     TRIED TO ALLOCATE ',n);
	Writeln('     CURRENT STACK TOP IS ',st);
	END;
    END;

PROCEDURE Dealloc(n: integer);
    BEGIN
    IF st - n >= 0 THEN
	st := st - n
    ELSE
	Writeln('*****LISP STACK UNDERFLOW');
    END;

    (* optimized allocs *)

PROCEDURE Alloc1;
    BEGIN Alloc(1) END;

PROCEDURE Dealloc1;
    BEGIN Dealloc(1) END;

PROCEDURE Alloc2;
    BEGIN Alloc(2) END;

PROCEDURE Dealloc2;
    BEGIN Dealloc(2) END;

PROCEDURE Alloc3;
    BEGIN Alloc(3) END;

PROCEDURE Dealloc3;
    BEGIN Dealloc(3) END;


    (********************************************************)
    (*                                                      *)
    (*              the garbage collector                   *)
    (*                                                      *)
    (********************************************************)

PROCEDURE Faststat;
    (* give quick summary of statistics gathered *)
    BEGIN
    Writeln('CONSES:',consknt);
    Writeln('PAIRS :',pairknt);
    Writeln('CONSES/PAIRS: ',consknt/pairknt);
    Writeln('ST    :',st);
    END;


PROCEDURE Gcollect;
    VAR
	i: integer;
	markedk: integer;   (* counts the number of pairs marked *)
	freedk: integer;    (* counts the number of pairs freed. *)
	gcstkp: 0..maxgcstk; (* note the garbage collection stack   *)
	mxgcstk: 0..maxgcstk;           (* is local to this procedure. *)
	gcstk: ARRAY[1..maxgcstk] OF integer;

    PROCEDURE Pushref(pr: any);
	(* push the address of an unmarked pair, if that's what it is. *)
	BEGIN
	IF Tag_of(pr) = pairtag THEN
	    IF NOT prspace[Info_of(pr)].markflg THEN
		BEGIN
		IF gcstkp < maxgcstk THEN
		    BEGIN
		    gcstkp := gcstkp + 1;
		    gcstk[gcstkp] := Info_of(pr);
		    IF gcstkp > mxgcstk THEN
			mxgcstk := gcstkp;
		    END
		ELSE
		    Writeln('*****GARBAGE STACK OVERFLOW');
		(* fatal error *)
		END;
	END;

    PROCEDURE Mark;
	(* "recursively" mark pairs referred to from gcstk. gcstk is used to *)
	(* simulate recursion.                                               *)
	VAR
	    prloc: integer;
	BEGIN
	WHILE gcstkp > 0 DO
	    BEGIN
	    prloc := gcstk[gcstkp];
	    gcstkp := gcstkp - 1;
	    prspace[prloc].markflg := true;
	    Pushref(prspace[prloc].prcdr);
	    Pushref(prspace[prloc].prcar);  (* trace the car first. *)
	    END;
	END;

    BEGIN       (* gcollect *)
    Writeln('***GARBAGE COLLECTOR CALLED');
    gccount := gccount + 1;          (* count garbage collections. *)
    Faststat;   (* give summary of statistics collected *)
    consknt := 0;       (* clear out the cons/pair counters *)
    pairknt := 0;
    gcstkp := 0;                    (* initialize the garbage stack pointer. *)
    mxgcstk := 0;                   (* keeps track of max stack depth. *)

    (* mark things from the "computation" stack. *)
    FOR i := 1 TO st DO
	BEGIN
	Pushref(stk[i]);
	Mark;
	END;
    (* mark things from identifier space. *)
    FOR i := 1 TO maxident DO
	BEGIN
	Pushref(idspace[i].val);
	Mark;
	Pushref(idspace[i].plist);
	Mark;
	Pushref(idspace[i].funcell);
	Mark;
	END;

    (* reconstruct free list by adding things to the head. *)
    freedk := 0;
    markedk := 0;
    FOR i:= 1 TO maxpair - 1 DO
	BEGIN
	IF prspace[i].markflg THEN
	    BEGIN
	    markedk := markedk + 1;
	    prspace[i].markflg := false
	    END
	ELSE
	    BEGIN
	    prspace[i].prcar := xnil;
	    prspace[i].prcdr := Mkitem(pairtag, freepair);
	    freepair := i;
	    freedk := freedk + 1
	    END
	END (* for *);
    Writeln(freedk,' PAIRS FREED.');
    Writeln(markedk,' PAIRS IN USE.');
    Writeln('MAX GC STACK WAS ',mxgcstk);
    END    (* gcollect *);


    (********************************************************)
    (*                                                      *)
    (*              identifier lookup & entry               *)
    (*                                                      *)
    (********************************************************)

FUNCTION Nmhash(nm: stringp): integer;
    CONST
	hashc = 256;
    VAR
	i,tmp: integer;
    BEGIN
    tmp := 0;
    i := 1;     (* get hash code from first three chars of string. *)
    WHILE (i <= 3) AND (strspace[nm+i] <> Chr(eos)) DO
	BEGIN
	tmp := Ord(strspace[nm+i]) + hashc*tmp;
	i := i + 1;
	END;
    Nmhash := Abs(tmp) MOD hidmax;      (* abs because mod is screwy. *)
    END;

FUNCTION Eqstr(s1,s2: stringp): boolean;
    BEGIN
    WHILE (strspace[s1] = strspace[s2]) AND (strspace[s1] <> Chr(eos)) DO
	BEGIN
	s1 := s1 + 1;
	s2 := s2 + 1;
	END;
    Eqstr := (strspace[s1] = strspace[s2]);
    END;

PROCEDURE Nmlookup(nm: stringp; VAR found: boolean; VAR hash: integer;
		   VAR loc: any);
    (* lookup a name in "identifier space".                                 *)
    (* "hash" returns the hash value for the name.                          *)
    (* "loc" returns the location in the space for the (possibly new)       *)
    (* identifier.                                                          *)
    BEGIN
    hash := Nmhash(nm);
    loc := Mkitem(idtag, idhead[hash]);
    (* default is identifier, but may be "error". *)
    (* start at appropriate hash chain. *)

    found := false;
    WHILE (Info_of(loc) <> nillnk) AND (NOT found) DO
	BEGIN
	found := Eqstr(nm, idspace[Info_of(loc)].idname);
	IF NOT found THEN
	    Set_info(loc, idspace[Info_of(loc)].idhlink);
	(* next id in chain *)
	END;
    IF NOT found THEN               (* find spot for new identifier *)
	BEGIN
	IF freeident=nillnk THEN    (* no more free identifiers. *)
	    loc := Mkitem(errtag, noidspace)
	ELSE
	    BEGIN
	    Set_info(loc, freeident);
	    freeident := idspace[freeident].idhlink;
	    END;
	END;
    END;

PROCEDURE Putnm(nm: stringp; VAR z: any; VAR found: boolean);
    (* put a new name into identifier space, or return old location *)
    (* if it's already there.                                       *)
    VAR
	tmp: ident;
	hash: integer;
    BEGIN
    Nmlookup(nm, found, hash, z);
    IF (NOT found) AND (Tag_of(z) = idtag) THEN
	BEGIN
	tmp.idname := nm;
	tmp.idhlink := idhead[hash];   (* put new ident at head of chain     *)
	tmp.val := xnil;             (* initialize value and property list *)
	tmp.plist := xnil;
	tmp.funcell := xnil;         (* also, the function cell *)
	idhead[hash] := Info_of(z);
	idspace[Info_of(z)] := tmp;
	END;
    END;

    (********************************************************)
    (*                                                      *)
    (*               standard lisp functions                *)
    (*                                                      *)
    (********************************************************)

    (* the following standard lisp functions appear in *)
    (* lspfns.red: reverse, append, memq, atsoc, get,  *)
    (* put, remprop, eq, null, equal, error, errorset, *)
    (* abs, idp, numberp, atom, minusp, eval, apply,   *)
    (* evlis, prin1, print, prin2t, list2 ... list5.   *)

FUNCTION Setq(VAR u: any; v: any): any;
    BEGIN   (* setq *)
    (* should check to make sure u not t or nil. *)
    u := v;
    Setq := v
    END  (* setq *);

FUNCTION Atom(item : any): any;
    BEGIN       (* atom *)
    IF Tag_of(item) <> pairtag THEN Atom := t
    ELSE Atom := xnil
    END (* atom *);

FUNCTION Codep(item: any): any;
    BEGIN       (* codep *)
    IF Tag_of(item) = codetag THEN Codep := t
    ELSE Codep := xnil
    END (* codep *);

FUNCTION Idp(item: any): any;
    BEGIN       (* idp *)
    IF Tag_of(item) = idtag THEN Idp := t
    ELSE Idp := xnil
    END (* idp *);

FUNCTION Pairp(*item: any): any*);
    BEGIN (* pairp *)
    IF Tag_of(item) = pairtag THEN Pairp := t
    ELSE Pairp := xnil
    END (* pairp *);

FUNCTION Constantp(item: any): any;
    BEGIN       (* constantp *)
    IF NOT((Pairp(item) = t) OR (Idp(item) = t)) THEN
	Constantp := t
    ELSE Constantp := xnil
    END (* constantp *);

FUNCTION Eq(u, v: any): any;
    BEGIN       (* eq *)
    IF u = v THEN Eq := t
    ELSE Eq := xnil
    END (* eq *);

FUNCTION Eqn(u, v: any): any;
    VAR i, j: longint;

    BEGIN       (* eqn *)
    Int_val(u, i);
    Int_val(v, j);
    IF i = j THEN Eqn := t
    ELSE Eqn := xnil
    END (* eqn *);

FUNCTION Fixp(item: any): any;
    BEGIN       (* fixp *)
    IF (Tag_of(item) = inttag) OR (Tag_of(item) = fixtag) THEN
	Fixp := t
    ELSE Fixp := xnil
    END (* fixp *);

FUNCTION Floatp(item: any): any;
    BEGIN       (* floatp *)
    IF Tag_of(item) = flotag THEN Floatp := t
    ELSE Floatp := xnil
    END (* floatp *);

FUNCTION Numberp(item: any): any;
    BEGIN       (* numberp *)
    Numberp := Fixp(item)   (* will have to fix for floats *)
    END (* numberp *);

FUNCTION Cons(u, v: any): any;
    VAR p: integer;

    BEGIN   (* cons *)
    (* push args onto stack, in case we need to garbage collect the *)
    (* references will be detected.                                 *)
    Alloc(2);
    stk[st] := u;
    stk[st-1] := v;

    IF prspace[freepair].prcdr = xnil THEN Gcollect;

    p := freepair;
    freepair := Info_of(prspace[p].prcdr);
    prspace[p].prcar := u;
    prspace[p].prcdr := v;
    Cons := Mkpair(p);       (* return new pair. *)

    consknt := consknt + 1;
    Dealloc(2);
    END     (* cons *);

FUNCTION Ncons(u: any): any;
    BEGIN
    Ncons := Cons(u, xnil)
    END;

FUNCTION Xcons(u, v: any): any;
    BEGIN
    Xcons := Cons(v, u)
    END;

FUNCTION Car(*u: any): any*);
    BEGIN
    IF Tag_of(u) = pairtag THEN
	Car := prspace[Info_of(u)].prcar
    ELSE
	Car := Mkitem(errtag, notpair);
    END;

FUNCTION Cdr(*u: any): any*);
    BEGIN
    IF Tag_of(u) = pairtag THEN
	Cdr := prspace[Info_of(u)].prcdr
    ELSE
	Cdr := Mkitem(errtag, notpair);
    END;


    (* fluid binding *)
FUNCTION Push_bind(bind: any): any;
    BEGIN	(* push_bind *)
    old_binds := cons(bind, old_binds);
    push_bind := xnil
    END	(* push_bind *);

FUNCTION Lam_bind(alist: any): any;
    VAR bind: any;

    BEGIN (* lam_bind *)
    WHILE Truep(Pairp(alist)) DO
	BEGIN
	bind := Car(alist);
	alist := Cdr(alist);
	push_bind(bind);
	setvalue(Car(bind), Cdr(bind))
	END;
    Lam_bind := xnil
    END  (* lam_bind *);

FUNCTION Prog_bind(id: any): any;
    BEGIN (* prog_bind *)
    Prog_bind := Lam_bind(cons(id, xnil))
    END (* prog_bind *);

FUNCTION Unbind(id: any): any;
    BEGIN (* unbind *)
    setvalue(id, cdr(atsoc(id, old_binds)))
    Unbind := xnil
    END (* unbind *);

    (* arithmetic functions *)
FUNCTION Add1(i: any): any;
    VAR j: longint;

    BEGIN
    Int_val(i, j);
    Add1 := Mkint(j + 1)
    END;

FUNCTION Difference(i, j: any): any;
    VAR i1, i2: longint;

    BEGIN
    Int_val(i, i1);
    Int_val(j, i2);
    Difference := Mkint(i1 - i2)
    END;

FUNCTION Divide(i, j: any): any;
    (* returns dotted pair (quotient . remainder). *)
    VAR i1, i2: longint;

    BEGIN
    Int_val(i, i1);
    Int_val(j, i2);
    IF i2 = 0 THEN Writeln('***** ATTEMPT TO DIVIDE BY 0 IN DIVIDE');
    Divide := Cons(Mkint(i1 DIV i2), Mkint(i1 MOD i2))
    END;

FUNCTION Greaterp(i, j: any): any;
    VAR i1, i2: longint;

    BEGIN
    Int_val(i, i1);
    Int_val(j, i2);

    IF i1 > i2 THEN
	Greaterp := t
    ELSE
	Greaterp := xnil;
    END;

FUNCTION Lessp(i, j: any): any;
    VAR i1, i2: longint;

    BEGIN
    Int_val(i, i1);
    Int_val(j, i2);

    IF i1 < i2 THEN
	Lessp := t
    ELSE
	Lessp := xnil;
    END;

FUNCTION Minus(i: any): any;
    VAR j: longint;

    BEGIN
    Int_val(i, j);
    Minus := Mkint(-j)
    END;

FUNCTION Plus2(i, j: any): any;
    VAR i1, i2: longint;

    BEGIN
    Int_val(i, i1);
    Int_val(j, i2);
    Plus2 := Mkint(i1 + i2)
    END;

FUNCTION Quotient(i, j: any): any;
    VAR i1, i2: longint;

    BEGIN
    Int_val(i, i1);
    Int_val(j, i2);
    IF i2 = 0 THEN Writeln('***** ATTEMPT TO DIVIDE BY 0 IN QUOTIENT');
    Quotient := Mkint(i1 DIV i2)
    END;

FUNCTION Remainder(i, j: any): any;
    VAR i1, i2: longint;

    BEGIN
    Int_val(i, i1);
    Int_val(j, i2);
    IF i2 = 0 THEN Writeln('***** ATTEMPT TO DIVIDE BY 0 IN REMAINDER');
    Remainder := Mkint(i1 MOD i2)
    END;

FUNCTION Times2(i, j: any): any;
    VAR i1, i2: longint;

    BEGIN
    Int_val(i, i1);
    Int_val(j, i2);
    Times2 := Mkint(i1 * i2)
    END;
    (* times2 *)

    (* symbol table support *)
FUNCTION Value(u: any): any;
    BEGIN   (* value *)
    Value := idspace[Info_of(u)].val
    END     (* value *);

FUNCTION Plist(u: any): any;
    BEGIN   (* plist *)
    Plist := idspace[Info_of(u)].plist
    END     (* plist *);

FUNCTION Funcell(u: any): any;
    BEGIN   (* funcell *)
    Funcell := idspace[Info_of(u)].funcell
    END     (* funcell *);

FUNCTION Setplist(u, v: any): any;
    BEGIN (* setplist *)
    END (* setplist *);

    (* also need setvalue, setfuncell, setplist. *)

FUNCTION Xnot(u: any): any;
    BEGIN (* xnot *)
    Xnot := Eq(u, xnil)
    END (* xnot *);


    (********************************************************)
    (*                                                      *)
    (*                    i/o primitives                    *)
    (*                                                      *)
    (********************************************************)


PROCEDURE Terpri;
    (* need to change for multiple output channels.  *)
    BEGIN
    Writeln(output);
    END;


PROCEDURE Wrtok(u: any);
    (* doesn't expand escaped characters in identifier names *)
    VAR i: integer;
    BEGIN
    IF Tag_of(u) = inttag THEN
	IF Info_of(u) = 0 THEN
	    Write('0')
	ELSE
	    Write(Info_of(u): 2+Trunc(Log(Abs(Info_of(u)))))

    ELSE IF Tag_of(u) = fixtag THEN
	Write(intspace[Info_of(u)])

    ELSE IF Tag_of(u) = flotag THEN
	Write(flospace[Info_of(u)])

    ELSE IF Tag_of(u) = idtag THEN
	BEGIN
	i := idspace[Info_of(u)].idname;
	WHILE (i <= maxstrsp) AND (strspace[i] <> Chr(eos)) DO
	    BEGIN
	    Write(strspace[i]);
	    i:= i + 1;
	    END;
	END

    ELSE IF Tag_of(u) = chartag THEN
	Write(Chr(Info_of(u) - choffset))

    ELSE
	Writeln('WRTOK GIVEN ',Tag_of(u), Info_of(u));
    END;


PROCEDURE Rdchnl(chnlnum: integer; VAR ch: onechar);
    BEGIN
    IF (chnlnum < 1) OR (chnlnum > inchns) THEN
	Writeln('*****BAD INPUT CHANNEL FOR RDCHNL')
    ELSE
	CASE chnlnum OF
	    1:  BEGIN
		ch := symin^;  (* a little strange, but avoids  *)
		Get(symin);              (* initialization problems *)
		ichrbuf[inchnl] := symin^;
		END;

	    2:  BEGIN
		ch := input^;
		Get(input);
		ichrbuf[inchnl] := input^;
		END;
		END;
    (* case *)
    END;
    (* rdchnl *)

FUNCTION Eofchnl(chnlnum: integer): boolean;
    BEGIN
    IF (chnlnum < 1) OR (chnlnum > inchns) THEN
	Writeln('*****BAD INPUT CHANNEL FOR EOFCHNL')
    ELSE
	CASE chnlnum OF
	    1:  Eofchnl := Eof(symin);
	    2:  Eofchnl := Eof(input);
		END;
    END;

    (********************************************************)
    (*                                                      *)
    (*                   token scanner                      *)
    (*                                                      *)
    (********************************************************)

FUNCTION Rdtok: any;
    VAR
	ch: onechar;
	i: integer;
	anint: longint;
	moreid: boolean;
	found: boolean;
	token: any; (* the token read *)

    FUNCTION Digit(ch: onechar): boolean;
	BEGIN
	Digit := ( '0' <= ch ) AND ( ch <= '9')
	END;

    FUNCTION Escalpha(VAR ch: onechar): boolean;
	(* test for alphabetic or escaped character.  *)
	(* note possible side effect.                 *)
	BEGIN   (* escalpha *)
	IF ( 'A' <= ch ) AND ( ch <= 'Z') THEN
	    Escalpha := true
	ELSE IF ( Ord('A')+32 <= Ord(ch)) AND ( Ord(ch) <= Ord('Z')+32) THEN
	    Escalpha := true    (* lower case alphabetics *)
	ELSE IF ch='!' THEN
	    BEGIN
	    Rdchnl(inchnl,ch);
	    Escalpha := true;
	    END
	ELSE
	    Escalpha := false;
	END     (* escalpha *);

    FUNCTION Alphanum(VAR ch: onechar): boolean;
	(* test if escalfa or digit *)
	VAR b: boolean;
	BEGIN
	b := Digit(ch);
	IF NOT b THEN b := Escalpha(ch);
	Alphanum := b;
	END;

    FUNCTION Whitesp(ch: onechar): boolean;
	BEGIN
	(* may want a faster test *)
	Whitesp := (ch = sp) OR (Ord(ch) = cr) OR (Ord(ch) = lf)
	OR (Ord(ch) = ht) OR (Ord(ch) = nul)
	END;


	(* reads fixnums...need to read flonums too *)
    BEGIN       (* rdtok *)
    IF NOT Eofchnl(inchnl) THEN
	REPEAT                          (* skip leading white space. *)
	    Rdchnl(inchnl,ch)
	UNTIL (NOT Whitesp(ch)) OR Eofchnl(inchnl);
    IF Eofchnl(inchnl) THEN
	token := Mkitem(chartag, eofcode + choffset)
	(* should really return !$eof!$  *)

    ELSE
	BEGIN
	token := xnil;        (* init to something *)

	IF Digit(ch) THEN
	    Set_tag(token, inttag)
	ELSE IF Escalpha(ch) THEN
	    Set_tag(token, idtag)
	ELSE
	    Set_tag(token, chartag);

	CASE Tag_of(token) OF
	    chartag:  BEGIN
		Set_tag(token, idtag);
		idspace[toktype].val := Mkitem(inttag, chartype);
		Set_info(token, Ord(ch) + choffset);
		END;
	    inttag:   BEGIN
		idspace[toktype].val := Mkitem(inttag, inttype);
		anint := Ord(ch) - Ord('0');
		WHILE Digit(ichrbuf[inchnl]) DO
		    BEGIN
		    Rdchnl(inchnl,ch);
		    anint := 10 * anint + (Ord(ch) - Ord('0'))
		    END;
		Set_info(token, anint)
		END;

	    idtag:    BEGIN
		idspace[toktype].val := Mkitem(inttag, idtype);
		i := freestr; (* point to possible new string *)
		moreid := true;
		WHILE (i < maxstrsp) AND moreid DO
		    BEGIN
		    strspace[i] := ch;
		    i := i + 1;
		    moreid := Alphanum(ichrbuf[inchnl]);
		    IF moreid THEN
			Rdchnl(inchnl,ch);
		    END;
		strspace[i] := Chr(eos);   (* terminate string *)
		IF (i >= maxstrsp) THEN
		    Writeln('*****STRING SPACE EXHAUSTED')
		ELSE  (* look the name up, return item for it *)
		    BEGIN
		    Putnm(freestr, token, found);
		    IF NOT found THEN
			freestr := i + 1;
		    END;
		END;
		(* of case idtag *)
	END;
	(* of case *)
	END;
    Rdtok := token
    END;
    (* rdtok *)

    (********************************************************)
    (*                                                      *)
    (*                    initialization                    *)
    (*                                                      *)
    (********************************************************)

FUNCTION Read: any;    FORWARD;

PROCEDURE Init;
    (* initialization procedure depends on  *)
    (* ability to load stack with constants *)
    (* from a file.                         *)
    VAR
	strptr: stringp;
	nam: PACKED ARRAY[1..3] OF onechar;
	(* holds 'nil', other strings? *)
	i, n: integer;
	idref: any;
	found: boolean;

	(* init is divided into two parts so it can compile on terak *)
    PROCEDURE Init1;
	BEGIN
	(* initialize top of stack *)
	st := 0;

	freefloat := 1;

	(* define nil - the id, nil, is defined a little later. *)
	freeident := 1;
	xnil := Mkitem(idtag, freeident);

	(* initialize pair space. *)
	FOR i := 1 TO maxpair - 1 DO      (* initialize free list. *)
	    BEGIN
	    prspace[i].markflg := false;        (* redundant? *)
	    prspace[i].prcar := xnil;         (* just for fun *)
	    prspace[i].prcdr := Mkitem(pairtag, i + 1)
	    END;
	prspace[maxpair].prcar := xnil;
	prspace[maxpair].prcdr := xnil;       (* end flag *)
	freepair := 1;                  (* point to first free pair *)


	(* initialize identifier space and string space. *)
	freestr := 1;
	FOR i := 0 TO hidmax - 1 DO
	    idhead[i] := nillnk;
	FOR i := 1 TO maxident DO
	    BEGIN
	    IF i < maxident THEN
		idspace[i].idhlink := i + 1
	    ELSE    (* nil to mark the final identifier in the table. *)
		idspace[i].idhlink := nillnk;
	    (* set function cells to undefined *)
	    idspace[i].funcell := Mkitem(errtag, undefined)
	    END;

	(* nil must be the first identifier in the table--id #1 *)
	(* must fill in fields by hand for nil.*)
	(* putnm can handle any later additions.  *)
	nam := 'NIL';
	strptr := freestr;
	FOR i := 1 TO 3 DO
	    BEGIN
	    strspace[strptr] := nam[i];
	    strptr:= strptr + 1;
	    END;
	strspace[strptr] := Chr(eos);
	Putnm(freestr, xnil, found);
	IF NOT found THEN
	    freestr := strptr + 1;

	(* make the single character ascii identifiers, except nul(=eos). *)
	FOR i := 1 TO 127  DO
	    BEGIN
	    strspace[freestr] := Chr(i);
	    strspace[freestr + 1] := Chr(eos);
	    Putnm(freestr, idref, found);
	    IF NOT found THEN
		freestr := freestr + 2;
	    IF i = Ord('T') THEN
		t := idref;
	    (* returns location for 't. *)
	    END;

	(* init fixnum free list. *)
	FOR i := 1 TO maxintsp - 1 DO
	    intspace[i] := i + 1;
	intspace[maxintsp] := end_flag;
	freeint := 1;


	(* clear the counters *)
	gccount := 0;
	consknt := 0;
	pairknt := 0;
	END     (* init1 *);


    PROCEDURE Init2;
	VAR token: any;

	BEGIN
	(* load "symbol table" with identifiers, constants, and functions.  *)
	inchnl := 1;        (* select symbol input file. *)
	(* reset(symin,'#5:poly.data'); *) (* for terak *)


	token := Rdtok;     (* get count of identifiers. *)
	IF Tag_of(token) <> inttag THEN
	    Writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED AT START');
	n := Info_of(token);
	FOR i := 1 TO n DO
	    token := Rdtok;
	(* reading token magically loads it into id space. *)
	token := Rdtok;         (* look for zero terminator. *)
	IF (Tag_of(token) <> inttag) OR (Info_of(token) <> 0) THEN
	    Writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER IDENTIFIERS');

	token := Rdtok;         (* count of constants  *)
	IF Tag_of(token) <> inttag THEN
	    Writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED BEFORE CONSTANTS');
	n := Info_of(token);
	Alloc(n);       (* space for constants on the stack *)
	FOR i := 1 TO n DO
	    stk[i] := Read;
	token := Rdtok;
	IF (Tag_of(token) <> inttag) OR (Info_of(token) <> 0) THEN
	    Writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER CONSTANTS');


	token := Rdtok;     (* count of functions. *)
	IF Tag_of(token) <> inttag THEN
	    Writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED BEFORE FUNCTIONS');
	n := Info_of(token);
	FOR i := 1 TO n DO
	    (* for each function *)
	    (* store associated code *)
	    idspace[Rdtok].funcell := Mkitem(codetag, i);
	token := Rdtok;
	IF (Tag_of(token) <> inttag) OR (Info_of(token) <> 0) THEN
	    Writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER FUNCTIONS');

	inchnl := 2;        (* select standard input. *)
	END     (* init2 *);

    BEGIN       (* init *)
    Init1;
    Init2;
    END    (* init *);


    (********************************************************)
    (*                                                      *)
    (*                        apply                         *)
    (*                                                      *)
    (********************************************************)

FUNCTION Apply(fn, arglist: any): any;
    VAR arg1, arg2, arg3, arg4, arg5: any;
	numargs: integer;

    BEGIN (* apply *)
    IF Tag_of(fn) <> codetag THEN
	Writeln('*****APPLY: UNDEFINED FUNCTION.')
    ELSE
	BEGIN   (* spread the arguments *)
	numargs := 0;
	WHILE Truep(Pairp(arglist)) DO
	    BEGIN
	    numargs := numargs + 1;
	    CASE numargs OF
		1: arg1 := Car(arglist);
		2: arg2 := Car(arglist);
		3: arg3 := Car(arglist);
		4: arg4 := Car(arglist);
		5: arg5 := Car(arglist);
		6: Writeln('APPLY: TOO MANY ARGS SUPPLIED.')
		END (* case *);
	    arglist := Cdr(arglist)
	    END (* while *)
	END (* if *);

    CASE Info_of(fn) OF
	1: Apply := Atom(arg1);
	END (* case *)
    END (* apply *);
    (*??* Missing closing point at end of program. *??*)
(*??* Missing closing point at end of program. *??*)

Added perq-pascal-lisp-project/pas0.perq version [2651cb233d].



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505

 (* PreProcessor Version - Run  through Filter *)
      (* PERQ version *)
(*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                     
% 		PASCAL BASED MINI-LISP
%
% File: 	PAS0.PAS - PASCAL/LISP KERNEL
% ChangeDate: 	11:00pm Monday, 28 September 1981
% By: 		Ralph Ottenheimer big -> fix, END comment FOR #pta
%		COMPRESS & EXPLODE
% 
% 	    All RIGHTS RESERVED
%           COPYRIGHT (C) - 1981 - M. L. GRISS
%           Computer Science Department
%           University of Utah
%
%           Do Not distribute with out written consent of M. L. Griss
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*)


    PROGRAM pas0 (input,output, symin,finput,foutput);
    (************************************************************)
    (* support routines for a "lisp" machine.  uses a register  *)
    (* model with a stack for holding frames.  stack also used  *)
    (* to hold compiler generated constants.                    *)
    (* written by william f. galway and martin l. griss         *)
    (* modified by ralph ottenheimer may 81                     *)
    (* append pas1...pasn at  end                               *)
    (* -------------------------------------------------------- *)
    (* symin is input channel one--used to initialize "symbol   *)
    (* table".  input is input channel two--standard input.     *)
    (* output is output channel one--the standard output.       *)
    (* finput is file input channel three.                      *)
    (* foutput is file output channel four.                      *)
    (************************************************************)


imports Stream from Stream;
imports system from system;
imports io_others from io_others;
imports io_unit from io_unit;


CONST
    (* for terak, perq, Apollo, vax  *)
 sp = ' '; 
 ht = 9;          (* ascii codes *)
 lf = 10;
 cr = 13; 
 nul = 0;

   eos = chr(0);        (* KLUDGE: null string *)
    inchns = 3;       (* number of input channels.  *)
    outchns = 4;      (* number of output channels. *)
    begin_comment = '%';

(* Initial symbols, needed in Kernel *)
    xtoktype  =  129; (* slot in idspace for toktype. *)
    xbstack   = 130;  (* Bstack Pointer *)
    xthrowing = 131;  (* If throw mode *)
    xinitform = 132;  (* for restart *)
    xraise    = 133;  (* for RAISE of lc in ids *)

    chartype  =  3;   (* various token types *)
    inttype  =  1;
    idtype  =  2;

   (* no shift const *)
    (* assumed to be at least 16 bits long.  low order 13 bits  *)
    (* are the info, top 3 are the tag.                         *)
     int_offset = 32767; (* PERQ item is record *   )

    (* the various tags - can't use a defined scalar type *)
    (* because of the lack of convertion functions.       *)
    inttag = 0;    (* info is an integer                  *)
    chartag = 1;   (* info is a character code            *)
    pairtag = 2;   (* info points to pair                 *)
    idtag = 3;     (* info points to identifier           *)
    codetag = 4;   (* info is index into a case statement *)
    (*                that calls appropriate function.    *)
    errtag = 5;    (* info is an error code - see below.  *)
    fixtag = 6;    (* info points to a full word (or      *)
    (*                longer) integer.                    *)
    flotag = 7;    (* info points to a float number.      *)

    (* error codes.  corresponding to tag = errtag.  *)
    noprspace = 1;    (* no more "pair space"--can't cons. *)
    notpair = 2;      (* a pair operation attempted on a non-pair. *)
    noidspace = 3;    (* no more free identifiers *)
    undefined = 4;    (* used to mark undefined function cells (etc?) *)

    maxpair = 3700;   (* max number of pairs allowed. *)
    maxident = 800;   (* max number of identifiers *)
    maxstrsp = 4500;  (* size of string (literal) storage space. *)
    maxintsp = 200;   (* max number of long integers allowed *)
     maxflosp = 50;     (* max number of floating numbers allowed *)

    hidmax = 50;      (* number of hash values for identifiers *)
    maxgcstk = 100;   (* size of garbage collection stack.    *)
    stksize = 500;    (* stack size *)
    maxreg = 15;      (* number of registers in lisp machine. *)

    eofcode = 26;     (* magic character code for eof, ascii for *)
    (*  cntrl-z.  kludge, see note in xrdtok.  *)
    choffset = 1;     (* add choffset to ascii code to get address  *)
    (* in id space for corresponding identifier.  *)
    nillnk = 0;       (* when integers are used as pointers.  *)


TYPE
    onechar = char;     (* for terak,perq,Apollo*)

    (* note we allow zero for id_ptr, allowing a "nil" link. *)

    stringp = 1..maxstrsp;        (* pointer into string space. *)
    id_ptr = 0..maxident;            (* pointer into id space. *)

       itemref = RECORD
	           tag:integer;
                 info:integer;
                 END;
    itemtype = 0..7;    (* the tags *)


    pair = PACKED RECORD
		      prcar: itemref;
		      prcdr: itemref;
	(* OLD        markflag:boolean , but wastes space *)
		  END;


   ascfile = PACKED FILE OF onechar;

    ident = PACKED RECORD           (* identifier *)
		       idname: stringp;
		       val: itemref;       (* value *)
		       plist: itemref;     (* property list *)
		       funcell: itemref;   (* function cell *)
		       idhlink: id_ptr;    (* hash link *)
		   END;
    longint = integer;
VAR
    (* global information *)
    nilref,trueref: itemref;    (* refers to identifiers "nil", and "t". *)
    initphase: integer;                (* Start up *)
    r: ARRAY[1..maxreg] OF itemref;
    rxx,ryy: itemref;



    (* "st" is the stack pointer into "stk".  it counts the number of  *)
    (* items on the stack, so it runs from zero while the stack starts *)
    (* at one.                                                         *)
    st: 0..stksize;
    stk: ARRAY[1..stksize] OF itemref;

    (* pair space *)
    prspace: PACKED ARRAY[1..maxpair] OF pair; (* all pairs stored here. *)
    freepair: integer;          (* pointer to next free pair in prspace. *)

    (* identifier space *)
    idhead: ARRAY[0..hidmax] OF id_ptr;
    idspace: PACKED ARRAY[1..maxident] OF ident;
    freeident: integer;

    (* string space *)
    strspace: PACKED ARRAY[1..maxstrsp] OF onechar;
    freestr: stringp;

    (* large integer space *)
    intspace: ARRAY[1..maxintsp] OF longint;    (* use long int on terak *)
    freeint: 1..maxintsp;

    (* floating point number space *)
    flospace: ARRAY[1..maxflosp] OF real;
    freefloat: 1..maxflosp;

    (* i/o channels *)
  (* files declared on header *)
    symin : ascfile;
    finput : ascfile;
    foutput : ascfile;
    inchnl: 1..inchns;      (* current input channel number  *)
    outchnl: 1..outchns;    (* current output channel number *)

    (* "current character" for each input channel.                    *)
    (* may want to include more than one character at some later date *)
    (* (for more lookahead).                                          *)
    ichrbuf: ARRAY[1..inchns] OF onechar;

    (* for collecting statistics. *)
    gccount: integer;           (* counts garbage collections *)
    (* counts from last garbage collection. *)
    consknt: integer;           (* number of times "cons" called *)



(* ........ Everything nested inside CATCH *)

Procedure Xcatch;  (* ----------- Outermost Procedure ----------- *)
 var catch_stk:0..stksize;
     catch_Bstk:itemref;

PROCEDURE xread;
    FORWARD;

PROCEDURE xprint;
    FORWARD;

PROCEDURE xunbindto;
    FORWARD;

PROCEDURE xeval;
    FORWARD;

 Procedure Xthrow;
    begin (* throw value *)
        idspace[Xthrowing].val := trueref;
      exit(xeval)
    end (* throw *);
    
 Handler CtlC;  (* ------- handle runaway aborts ------- *)
 
 begin
    write('^C');
    IOKeyClear;
    IObeep;
    if initphase > 1 then Xthrow;
 end;

    (********************************************************)
    (*                                                      *)
    (*             item selectors & constructors            *)
    (*                                                      *)
    (********************************************************)


FUNCTION tag_of(item: itemref): itemtype;

    BEGIN (* tag_of *)
       tag_of := item.tag;
    END;
    (* tag_of *)

FUNCTION info_of(item: itemref): integer;

 BEGIN (* info_of *)
      info_of := item.info
    END;
    (* info_of *)

PROCEDURE mkitem(tag: itemtype; info: longint; VAR item: itemref);
    (* do range checking on info. ints run from -4096 to +4095 *)
    (* everything else runs from 0 to 8191. ints & chars       *)
    (* contain their info, all others points into an           *)
    (* appropriate space.                                      *)

    PROCEDURE mkfixint;
	BEGIN (* mkfixint *)
	IF freeint < maxintsp THEN     (* convert to fixnum *)
	    BEGIN
	    tag := fixtag;
	    intspace[freeint] := info;
	    info := freeint;        (* since we want the pointer *)
	    freeint := freeint + 1;
	    END
	ELSE BEGIN
                 writeln('*****FIXNUM SPACE EXHAUSTED');
                 (* should do gc *)
		 exit(pas0);
             END;
	END;
	(* mkfixint *)


    BEGIN (* mkitem *)
    IF tag = inttag THEN
      BEGIN
	IF (info < -int_offset) OR (info > int_offset - 1) THEN mkfixint
 	END
    ELSE IF tag = fixtag THEN mkfixint

	 ELSE IF info < 0 THEN
		  BEGIN
		  writeln('*****MKITEM: BAD NEG');
                exit(pas0);
		  END;
    (* nothing special to do for other types *)

    (* pack tag and info into 16-bit item.   *)
       item.tag := tag;
       item.info := info
    END;
    (* mkitem *)

PROCEDURE set_info(VAR item: itemref; newinfo: longint);
    BEGIN (* set_info *)
    mkitem(tag_of(item), newinfo, item)
    END;
    (* set_info *)

PROCEDURE set_tag(VAR item: itemref; newtag: itemtype);
    BEGIN (* set_tag *)
    mkitem(newtag, info_of(item), item)
    END;
    (* set_tag *)

PROCEDURE mkident(id: integer; reg: integer);
    (* make identifier "id" in register "reg" *)
    BEGIN       (* mkident *)
    mkitem(idtag, id, r[reg]);
    END;
    (* mkident *)

PROCEDURE mkint(int: longint; reg: integer);
    BEGIN       (* mkint *)
    mkitem(inttag, int, r[reg]);
    END;
    (* mkint *)

PROCEDURE mkpair(pr: integer; reg: integer);
    BEGIN (* mkpair *)
    mkitem(pairtag, pr, r[reg])
    END;
    (* mkpair *)

PROCEDURE int_val(item: itemref; VAR number: longint);
    (* returns integer value of item (int or fixnum). *)
    (* must return 'number' in var parameter instead  *)
    (* of function value since long integers are not  *)
    (* a legal function type in ucsd pascal.          *)
    BEGIN (* int_val *)
    IF tag_of(item) = inttag THEN
	number := info_of(item)
    ELSE IF tag_of(item) = fixtag THEN
	     number := intspace[info_of(item)]
  ELSE writeln('***** ILLEGAL DATA TYPE FOR NUMERIC OPERATION')
	(* halt or fatal error *)
    END;
    (* int_val *)


    (********************************************************)
    (*                                                      *)
    (*                  stack allocation                    *)
    (*                                                      *)
    (********************************************************)

PROCEDURE alloc(n: integer);
    BEGIN
    IF n + st <= stksize THEN
	st := n+st
    ELSE
	BEGIN
   writeln('*****LISP STACK OVERFLOW');
	writeln('     TRIED TO ALLOCATE ',n);
	writeln('     CURRENT STACK TOP IS ',st);
	END;
    END;

PROCEDURE dealloc(n: integer);
    BEGIN
    IF st - n >= 0 THEN
	st := st - n
    ELSE
	writeln('*****LISP STACK UNDERFLOW');
    END;

    (* optimized allocs *)

PROCEDURE alloc1;
    BEGIN alloc(1) END;

PROCEDURE dealloc1;
    BEGIN dealloc(1) END;

PROCEDURE alloc2;
    BEGIN alloc(2) END;

PROCEDURE dealloc2;
    BEGIN dealloc(2) END;

PROCEDURE alloc3;
    BEGIN alloc(3) END;

PROCEDURE dealloc3;
    BEGIN dealloc(3) END;


    (********************************************************)
    (*                                                      *)
    (*              support for register model              *)
    (*                                                      *)
    (********************************************************)

PROCEDURE load(reg: integer; sloc: integer);
    BEGIN
    IF sloc < 0 THEN r[reg] := r[-sloc]
    ELSE  r[reg] := stk[st-sloc];
    (* will, fix for load (pos,pos) *)
    END;

PROCEDURE store(reg: integer; sloc: integer);
    BEGIN
    stk[st-sloc] := r[reg];
    END;

    (* optimized load/store. *)
PROCEDURE load10;
    BEGIN
    load(1,0);
    END;

PROCEDURE store10;
    BEGIN
    store(1,0);
    END;

PROCEDURE storenil(sloc: integer);
    BEGIN
    stk[st-sloc] := nilref;
    END;

(* Other primitives ?? *)

    (********************************************************)
    (*                                                      *)
    (*              identifier lookup & entry               *)
    (*                                                      *)
    (********************************************************)

function nmhash(nm: stringp): integer;
    CONST
	hashc = 256;
    VAR
	i,tmp: integer;
    BEGIN
    tmp := 0;
    i := 1;     (* get hash code from first three chars of string. *)
    WHILE (i <= 3) AND (strspace[nm+i] <> eos) DO
	BEGIN
	tmp := ord(strspace[nm+i]) + hashc*tmp;
	i := i + 1;
	END;
    nmhash := abs(tmp) MOD hidmax;      (* abs because mod is screwy. *)
    END;

FUNCTION eqstr(s1,s2: stringp): boolean;
    BEGIN
    WHILE (strspace[s1] = strspace[s2]) AND (strspace[s1] <> eos) DO
	BEGIN
	s1 := s1 + 1;
	s2 := s2 + 1;
	END;
    eqstr := (strspace[s1] = strspace[s2]);
    END;

PROCEDURE nmlookup(nm: stringp; VAR found: boolean; VAR hash: integer;
		   VAR loc: itemref);
    (* lookup a name in "identifier space".                                 *)
    (* "hash" returns the hash value for the name.                          *)
    (* "loc" returns the location in the space for the (possibly new)       *)
    (* identifier.                                                          *)
    BEGIN
    hash := nmhash(nm);
    mkitem(idtag, idhead[hash], loc);
    (* default is identifier, but may be "error". *)
    (* start at appropriate hash chain. *)

    found := false;
    WHILE (info_of(loc) <> nillnk) AND (NOT found) DO
	BEGIN
	found := eqstr(nm, idspace[info_of(loc)].idname);
	IF NOT found THEN
	    set_info(loc, idspace[info_of(loc)].idhlink);
	(* next id in chain *)
	END;
    IF NOT found THEN               (* find spot for new identifier *)
	BEGIN
	IF freeident=nillnk THEN    (* no more free identifiers. *)
	    mkitem(errtag, noidspace, loc)
	ELSE
	    BEGIN
	    set_info(loc, freeident);
	    freeident := idspace[freeident].idhlink;
	    END;
	END;
    END;

PROCEDURE putnm(nm: stringp; VAR z: itemref; VAR found: boolean);
    (* put a new name into identifier space, or return old location *)
    (* if it's already there.                                       *)
    VAR
	tmp: ident;
	hash: integer;
    BEGIN
    nmlookup(nm, found, hash, z);
    IF (NOT found) AND (tag_of(z) = idtag) THEN
	BEGIN
	tmp.idname := nm;
	tmp.idhlink := idhead[hash];   (* put new ident at head of chain     *)
	tmp.val := nilref;             (* initialize value and property list *)
	tmp.plist := nilref;
	tmp.funcell := nilref;         (* also, the function cell *)
	idhead[hash] := info_of(z);
	idspace[info_of(z)] := tmp;
	END;
    END;

PROCEDURE xfaststat;
    (* give quick summary of statistics gathered *)
    BEGIN
    writeln('CONSES:',consknt);
    writeln('ST    :',st);
    END;


    (********************************************************)
    (*                                                      *)
    (*              the garbage collector                   *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xgcollect;
    VAR
	i: integer;
	markedk: integer;   (* counts the number of pairs marked *)
	freedk: integer;    (* counts the number of pairs freed. *)
	gcstkp: 0..maxgcstk; (* note the garbage collection stack   *)
	mxgcstk: 0..maxgcstk;           (* is local to this procedure. *)
	gcstk: ARRAY[1..maxgcstk] OF integer;
        markflag: PACKED ARRAY[1..maxpair] OF boolean;
(* used not to have array here *)
        
    PROCEDURE pushref(pr: itemref);
	(* push the address of an unmarked pair, if that's what it is. *)
	BEGIN
	IF tag_of(pr) = pairtag THEN
	    IF NOT markflag[info_of(pr)] THEN  (* was .markflag *)
		BEGIN
		IF gcstkp < maxgcstk THEN
		    BEGIN
		    gcstkp := gcstkp + 1;
		    gcstk[gcstkp] := info_of(pr);
		    IF gcstkp > mxgcstk THEN
			mxgcstk := gcstkp;
		    END
		ELSE
		    BEGIN
		    writeln('*****GARBAGE STACK OVERFLOW');
                  exit(pas0);
		    END;
		END;
	END;

    PROCEDURE mark;
	(* "recursively" mark pairs referred to from gcstk. gcstk is used to *)
	(* simulate recursion.                                               *)
	VAR
	    prloc: integer;
	BEGIN
	WHILE gcstkp > 0 DO
	    BEGIN
	    prloc := gcstk[gcstkp];
	    gcstkp := gcstkp - 1;
            markflag[prloc] := true;
(* OLD      prspace[prloc].markflag := true;  *)
	    pushref(prspace[prloc].prcdr);
	    pushref(prspace[prloc].prcar);  (* trace the car first. *)
	    END;
	END;

    BEGIN       (* xgcollect *)
    writeln('***GARBAGE COLLECTOR CALLED');
    gccount := gccount + 1;          (* count garbage collections. *)
    xfaststat;   (* give summary of statistics collected *)
    consknt := 0;       (* clear out the cons counter *)
    gcstkp := 0;        (* initialize the garbage stack pointer. *)
    mxgcstk := 0;       (* keeps track of max stack depth. *)

    (* clear markflags *)
    FOR i := 1 TO maxpair DO markflag[i] := false;
    (* OLD: wasnt needed *)
    (* mark things from the "computation" stack. *)
    FOR i := 1 TO st DO
	BEGIN
	pushref(stk[i]);
	mark;
	END;
    (* mark things from identifier space. *)
    FOR i := 1 TO maxident DO
	BEGIN
	pushref(idspace[i].val);
	mark;
	pushref(idspace[i].plist);
	mark;
	pushref(idspace[i].funcell);
	mark;
	END;

    (* reconstruct free list by adding things to the head. *)
    freedk := 0;
    markedk := 0;
    FOR i:= 1 TO maxpair - 1 DO
	BEGIN
	IF markflag[i] THEN
	(* OLD:	IF prspace[i].markflag THEN  *)
	    BEGIN
	    markedk := markedk + 1;
	    markflag[i] := false
	    (* OLD: prspace[i].markflag := false *)
	    END
	ELSE
	    BEGIN
	    prspace[i].prcar := nilref;
	    mkitem(pairtag, freepair, prspace[i].prcdr);
	    freepair := i;
	    freedk := freedk + 1
	    END
	END;
    writeln(freedk,' PAIRS FREED.');
    writeln(markedk,' PAIRS IN USE.');
    writeln('MAX GC STACK WAS ',mxgcstk);
    END;
    (* xgcollect *)

    (********************************************************)
    (*                                                      *)
    (*                  lisp primitives                     *)
    (*                                                      *)
    (********************************************************)

    (* return r[1].r[2] in r[1] *)
PROCEDURE xcons;
    VAR p: integer;

    BEGIN
    (* push args onto stack, in case we need to garbage collect the *)
    (* references will be detected.                                 *)
    alloc(2);
    stk[st] := r[1];
    stk[st-1] := r[2];

    IF prspace[freepair].prcdr = nilref THEN xgcollect;

    p := freepair;
    freepair := info_of(prspace[p].prcdr);
    prspace[p].prcar := stk[st];
    prspace[p].prcdr := stk[st - 1];
    mkpair(p, 1);       (* leave r[1] pointing at new pair. *)

    consknt := consknt + 1;
    dealloc(2);
    END;

PROCEDURE xncons;
    BEGIN r[2] := nilref;
    xcons;
    END;

PROCEDURE xxcons;
    BEGIN rxx := r[1];
    r[1] := r[2];
    r[2] := rxx;
    xcons;
    END;

    (* return car of r[1] in r[1] *)
PROCEDURE xcar;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
	r[1] := prspace[info_of(r[1])].prcar
    ELSE
	mkitem(errtag, notpair, r[1]);
    END;

PROCEDURE xcdr;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
	r[1] := prspace[info_of(r[1])].prcdr
    ELSE
	mkitem(errtag, notpair, r[1]);
    END;

PROCEDURE xrplaca;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
	prspace[info_of(r[1])].prcar:=r[2]
    ELSE
	mkitem(errtag, notpair, r[1]);
    END;

PROCEDURE xrplacd;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
	prspace[info_of(r[1])].prcdr :=r[2]
    ELSE
	mkitem(errtag, notpair, r[1]);
    END;

    (* anyreg car and cdr *)
PROCEDURE anycar(VAR a, b: itemref);
    BEGIN
    IF tag_of(a) = pairtag THEN
	b := prspace[info_of(a)].prcar
    ELSE
	mkitem(errtag, notpair, b);
    END;

PROCEDURE anycdr(VAR a, b: itemref);
    BEGIN
    IF tag_of(a) = pairtag THEN
	b := prspace[info_of(a)].prcdr
    ELSE
	mkitem(errtag, notpair, b);
    END;


    (********************************************************)
    (*                                                      *)
    (*              compress & explode                      *)
    (*                                                      *)
    (********************************************************)
PROCEDURE compress;     (* returns new id from list of chars *)
      VAR i: stringp;
          clist, c: itemref;
          found: boolean;
          int: integer;

    FUNCTION is_int(i: stringp; VAR int: longint): boolean;
        VAR negative, could_be: boolean;

        BEGIN   (* is_int *)
        int := 0;
        could_be := true;
        negative := strspace[i] = '-';
        IF negative OR (strspace[i] = '+') THEN i := i + 1;

        WHILE could_be AND (strspace[i] <> eos) DO
            BEGIN
            IF (strspace[i] >= '0') AND (strspace[i] <= '9') THEN
                 int := int * 10 + (ord(strspace[i]) - ord('0'))
            ELSE could_be := false;
            i := i + 1
            END;

        IF negative THEN int := -int;
        is_int := could_be
        END     (* is_int *);

    BEGIN     (* compress *)
    clist := r[1];        (* list of chars *)
    i := freestr; (* point to possible new string *)

    WHILE (i < maxstrsp) AND (clist <> nilref) DO
        BEGIN
        IF tag_of(clist) = PAIRTAG THEN
            BEGIN
            c := prspace[info_of(clist)].prcar;
            clist := prspace[info_of(clist)].prcdr;
            IF tag_of(c) = IDTAG THEN
                IF (info_of(c) > choffset) AND
                   (info_of(c) < choffset + 128) THEN 
                    BEGIN 
                    strspace[i] := chr(info_of(c) - choffset);
                    i := i + 1
                    END
                ELSE 
               writeln('*****COMPRESS: LIST ID NOT SINGLE CHAR')
            ELSE 
           writeln('*****COMPRESS: LIST ITEM NOT ID');
            END 
        ELSE 
       writeln('*****COMPRESS: ITEM NOT LIST')
        END (* WHILE *);

    strspace[i] := eos;   (* terminate string *)

    IF (i >= maxstrsp) THEN
	writeln('*****STRING SPACE EXHAUSTED')
    ELSE IF is_int(freestr, int) THEN
         mkint(int, 1)
    ELSE (* look the name up, return itemref for it *)
        BEGIN
        putnm(freestr, r[1], found);
	IF NOT found THEN
	    freestr := i + 1;
	END
    END       (* compress *);

PROCEDURE explode;      (* returns list of chars from id or int *)
      
      FUNCTION id_explode(i: stringp): itemref;
          BEGIN (* id_explode *)
          IF strspace[i] = eos THEN id_explode := nilref
          ELSE 
              BEGIN
              r[2] := id_explode(i + 1);
              mkident(ord(strspace[i]) + choffset, 1);
              xcons;
              id_explode := r[1]
              END
          END   (* id_explode *);

     FUNCTION int_explode(i: integer): itemref;
          VAR negative: boolean;

          BEGIN (* int_explode *)
          r[1] := nilref;
          IF i < 0 THEN
              BEGIN negative := true;
              i := -i
              END
          ELSE negative := false;

          WHILE i > 0 DO
              BEGIN
              r[2] := r[1];
              mkident(i MOD 10 + ord('0') + choffset, 1);
              xcons;
              i := i DIV 10
              END;

          IF negative THEN
              BEGIN 
              r[2] := r[1];
              mkident(ord('-') + choffset, 1);
              xcons
              END;
          int_explode := r[1]
          END (* int_explode *);

      BEGIN     (* explode *)
      IF tag_of(r[1]) = IDTAG THEN 
          r[1] := id_explode(idspace[info_of(r[1])].idname)
      ELSE IF tag_of(r[1]) = INTTAG THEN 
          r[1] := int_explode(info_of(r[1]))
      ELSE IF tag_of(r[1]) = FIXTAG THEN
          r[1] := int_explode(intspace[info_of(r[1])])
      ELSE 
     writeln('***** EXPLODE: ARG BAD TYPE')
      END       (* explode *);


    (********************************************************)
    (*                                                      *)
    (*                    i/o primitives                    *)
    (*                                                      *)
    (********************************************************)

procedure xopen;

var s1: string; i,j : integer;

  handler ResetError(name: PathName);
  begin
    writeln('**** Could not open file -  ',name,' for read');
    exit(xopen);
  end;

  handler RewriteError(name: PathName);
  begin
    writeln('**** Could not open file -  ',name,' for write');
    exit(xopen);
  end;
  
begin
      IF tag_of(r[1]) = IDTAG THEN 
      begin
        i := idspace[info_of(r[1])].idname;
        s1[0] := chr(255);
        j:= 0;
        WHILE (i <= maxstrsp) AND (strspace[i] <> eos) do
        begin
          j:= j + 1;
          s1[j] := strspace[i];
          i:= i + 1;
        end;
        s1[0]:= chr(j);
        
        IF tag_of(r[2]) = IDTAG THEN 
         case  strspace[idspace[info_of(r[2])].idname] of
         'i', 'I': begin reset(finput,s1); mkint(3,1) end;
         'o', 'O': begin rewrite(foutput,s1); mkint(4,1) end;
         otherwise: writeln('**** OPEN: ARG2 NOT INPUT/OUTPUT');
         end  else writeln('**** OPEN: ARG2 BAD TYPE')
     end else writeln('**** OPEN: ARG1 BAD TYPE');
end;

procedure xclose;

begin
  case info_of(r[1]) of
  1,2: ;
  3: close(finput);
  4: close(foutput);
  end;
end;

PROCEDURE xrds;
  (* Select channel for input *)
  VAR tmp:longint;
    BEGIN
        tmp:=inchnl;
        inchnl := info_of(r[1]);
         mkint(tmp,1)
    END;

PROCEDURE xwrs;
  (* Select channel for output *)
  VAR tmp:longint;
    BEGIN
        tmp:=outchnl;
        outchnl := info_of(r[1]);
        mkint(tmp,1)
    END;

PROCEDURE xterpri;
(* need to change for multiple output channels.  *)
    BEGIN
     case outchnl of
     1: writeln(' ');

     2: writeln(foutput,' ')
     end;
   END;


PROCEDURE xwrtok;
    (* doesn't expand escaped characters in identifier names *)
    VAR
      temp_real: real; (* KLUDGE: for bug *)
	i: integer;
    BEGIN
      case outchnl of
      1: BEGIN
    IF tag_of(r[1]) = inttag THEN
	BEGIN
	IF info_of(r[1]) = 0 THEN
	    write('0')
	ELSE
	    write('  ', info_of(r[1]):0);
	END

    ELSE IF tag_of(r[1]) = fixtag THEN
	     write(intspace[info_of(r[1])])

	 ELSE IF tag_of(r[1]) = flotag THEN
                BEGIN temp_real:= flospace[info_of(r[1])];
                  write( '* Real number bug *', trunc (temp_real))
                END
	      ELSE IF tag_of(r[1]) = idtag THEN
		       BEGIN
		       i := idspace[info_of(r[1])].idname;
		       WHILE (i <= maxstrsp) AND (strspace[i] <> eos) DO
			   BEGIN
			   write(strspace[i]);
			   i:= i + 1;
			   END;
		       END

		   ELSE IF tag_of(r[1]) = chartag THEN
		    write(chr(info_of(r[1]) - choffset))

		   ELSE IF tag_of(r[1]) = errtag THEN
		         writeln(' *** Error # ', '  ',info_of(r[1]):0)
		   ELSE IF tag_of(r[1]) = codetag THEN
			   write(' ## ','  ', info_of(r[1]):0)

		   ELSE  write(' ? ','  ' ,tag_of(r[1]):0,' /  ' ,info_of(r[1]):0,' ? ');
    END;
    
    4: BEGIN
    IF tag_of(r[1]) = inttag THEN
	BEGIN
	IF info_of(r[1]) = 0 THEN
	    write(foutput,'0')
	ELSE
	    write(foutput,'  ', info_of(r[1]):0);
	END

    ELSE IF tag_of(r[1]) = fixtag THEN
	     write(foutput,intspace[info_of(r[1])])

	 ELSE IF tag_of(r[1]) = flotag THEN
                BEGIN temp_real:= flospace[info_of(r[1])];
                  write(foutput, '* Real number bug *', trunc (temp_real))
                END
	      ELSE IF tag_of(r[1]) = idtag THEN
		       BEGIN
		       i := idspace[info_of(r[1])].idname;
		       WHILE (i <= maxstrsp) AND (strspace[i] <> eos) DO
			   BEGIN
			   write(foutput,strspace[i]);
			   i:= i + 1;
			   END;
		       END

		   ELSE IF tag_of(r[1]) = chartag THEN
		    write(foutput,chr(info_of(r[1]) - choffset))

		   ELSE IF tag_of(r[1]) = errtag THEN
		         writeln(foutput,' *** Error # ', '  ',info_of(r[1]):0)
		   ELSE IF tag_of(r[1]) = codetag THEN
			   write(foutput,' ## ','  ', info_of(r[1]):0)

		   ELSE  write(foutput,' ? ','  ' ,tag_of(r[1]):0,' /  ' ,info_of(r[1]):0,' ? ');
    END;
    END; (*case*)
  end; (*wrtoken*)
  
  
PROCEDURE rdchnl(chnlnum: integer; VAR ch: onechar);
    BEGIN
    IF (chnlnum < 1) OR (chnlnum > inchns) THEN
	writeln('*****BAD INPUT CHANNEL FOR RDCHNL',chnlnum)
    ELSE
	CASE chnlnum OF
	    1:  BEGIN
	    ch := symin^;  (* a little strange, but avoids  *)
	    get(symin);              (* initialization problems *)
	    ichrbuf[inchnl] := symin^; (* Peek ahead *)
	    END;

	    2:  BEGIN
	    ch := input^;
	    get(input);
	    ichrbuf[inchnl] := input^;
	    END;

	    3:  BEGIN
	    ch := finput^;
	    get(finput);
	    ichrbuf[inchnl] := finput^;
	    END;

    END;
    (* case *)
    END;
    (* rdchnl *)

FUNCTION eofchnl: boolean;
    BEGIN
	CASE inchnl OF
	    1:  eofchnl := eof(symin);
	    2:  eofchnl := eof(input);
	    3:  eofchnl := eof(finput);
	    END;
    END;


 FUNCTION eol: boolean;
    BEGIN
	CASE inchnl OF
	    1:  eol := eoln(symin);
	    2:  eol := eoln(input);
	    3:  eol := eoln(finput);
	    END;
    END;

    (********************************************************)
    (*                                                      *)
    (*                   token scanner                      *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xrdtok;
LABEL 1;

    VAR
	ch,ch1,ChangedCh: onechar;
	i: integer;
	anint: longint;
	moreid: boolean;
	found: boolean;

    FUNCTION digit(ch: onechar): boolean;
	BEGIN
	digit := ( '0' <= ch ) AND ( ch <= '9');
	END;


    FUNCTION escalpha(VAR ch: onechar): boolean;
	(* test for alphabetic or escaped character.                 *)
	(* note side effect in ChangedCh.                                *)
	BEGIN
        ChangedCh := Ch;
	IF ( 'A' <= ch ) AND ( ch <= 'Z') THEN
	    escalpha := true
	ELSE IF ( ord('A')+32 <= ord(ch)) AND ( ord(ch) <= ord('Z')+32) THEN
               BEGIN
                 IF idspace[xraise].val=trueref
                  THEN Changedch := chr(ord(ch)-32);
		 escalpha := true;    (* lower case alphabetics *)
               END
	     ELSE IF ch='!' THEN
		      BEGIN
		      rdchnl(inchnl,ch);
                      ChangedCh:=Ch;
                      escalpha := true;
		      END
		  ELSE
		      escalpha := false;
	END;

    FUNCTION alphanum(VAR ch: onechar): boolean;
	(* test if escalfa or digit *)
	VAR b: boolean;
	BEGIN
        ChangedCh:=Ch;
	b := digit(ch);
	IF NOT b THEN b := escalpha(ch);
	alphanum := b;
	END;

    FUNCTION whitesp(ch: onechar): boolean;
    VAR ascode:integer
    BEGIN
        ascode:=ord(ch);
        WHITESP := (CH = SP) OR (ascode = CR) OR (ascode = LF)
	 OR (ascode = ht) or (ascode = nul);        (* null?? *)
    END; 

	(* reads fixnums...need to read flonums too *)

    var negflag : integer;
    BEGIN       (* xrdtok *)
1:
    IF NOT eofchnl THEN
        REPEAT                          (* skip leading white space. *)
            rdchnl(inchnl,ch)
        UNTIL (NOT whitesp(ch)) OR eofchnl;
    IF eofchnl THEN
        mkitem(chartag, eofcode + choffset, r[1])
        (* should really return !$eof!$  *)
    ELSE
        BEGIN
        IF digit(ch) or  (ch = '-') THEN
            set_tag(r[1], inttag)
        ELSE IF escalpha(ch) THEN
                 set_tag(r[1], idtag)
             ELSE
                 set_tag(r[1], chartag);

        CASE tag_of(r[1]) OF
            chartag:  BEGIN
                  if ch = begin_comment then
                      BEGIN
                      while not eol do rdchnl(inchnl, ch);
                      (*REPEAT rdchnl(inchnl, ch)*) 
                      (*UNTIL eol;        (of selected input *)
                      rdchnl(inchnl, ch);
                      GOTO 1
                      END;
                  set_tag(r[1], idtag);
                  mkitem(inttag, chartype, idspace[xtoktype].val);
                  set_info(r[1], ord(ch) + choffset);
                  END;
            inttag:   BEGIN
                 mkitem(inttag, inttype, idspace[xtoktype].val);
                 negflag := 1;
                 if ch = '-' then 
                     begin
                       anint := 0;
                       negflag := -1
                     end  else
                     anint := ord(ch) - ord('0');
                 WHILE digit(ichrbuf[inchnl]) DO
                     BEGIN
                     rdchnl(inchnl,ch);
                     anint := 10 * anint + (ord(ch) - ord('0'))
                     END;
                 anint := anint * negflag;
                 set_info(r[1], anint)
                 END;
            idtag:    BEGIN
                mkitem(inttag, idtype, idspace[xtoktype].val);
                i := freestr; (* point to possible new string *)
                moreid := true;
                WHILE (i < maxstrsp) AND moreid DO
                    BEGIN
                    strspace[i] := ChangedCh; (* May have Case Change, etc *)
                    i:= i + 1;
                    moreid :=alphanum(ichrbuf[inchnl]);  (* PEEK ahead char *)
                    IF moreid THEN rdchnl(inchnl,ch) (* Advance readch *)
                    END;
                strspace[i] := eos;   (* terminate string *)
                IF (i >= maxstrsp) THEN
                    writeln('*****STRING SPACE EXHAUSTED')
                ELSE  (* look the name up, return itemref for it *)
                    BEGIN
                    putnm(freestr, r[1], found);
                    IF NOT found THEN
                        freestr := i + 1;
                    END;
                END;
                (* of case idtag *)
            END;
        (* of case *)
        END;
    END;
    (* xrdtok *)
    (* for DEBUG *)
    (********************************************************)
    (*                                                      *)
    (*                    initialization                    *)
    (*                                                      *)
    (********************************************************)


PROCEDURE init;
    (* initialization procedure depends on  *)
    (* ability to load stack with constants *)
    (* from a file.                         *)
    VAR
	strptr: stringp;
	nam: PACKED ARRAY[1..3] OF onechar;
	(* holds 'nil', other strings? *)
	i, n: integer;
	idref: itemref;
	found: boolean;

	(* init is divided into two parts so it can compile on terak *)
    PROCEDURE init1;
	BEGIN

	(* initialize top of stack *)
	st := 0;

	freefloat := 1;
	freeint := 1;

	(* define nilref - the id, nil, is defined a little later. *)
	freeident := 1;
	mkitem(idtag, freeident, nilref);

	(* initialize pair space. *)
	FOR i := 1 TO maxpair - 1 DO      (* initialize free list. *)
	    BEGIN
          (* OLD: prspace[i].MarkFlag := false; *)
	    prspace[i].prcar := nilref;         (* just for fun *)
	    mkitem(pairtag, i + 1, prspace[i].prcdr);
	    END;
	prspace[maxpair].prcar := nilref;
	prspace[maxpair].prcdr := nilref;       (* end flag *)
	freepair := 1;                  (* point to first free pair *)


	(* initialize identifier space and string space. *)
	freestr := 1;
	FOR i := 0 TO hidmax - 1 DO
	    idhead[i] := nillnk;
	FOR i := 1 TO maxident DO
	    BEGIN
	    IF i < maxident THEN
		idspace[i].idhlink := i + 1
	    ELSE    (* nil to mark the final identifier in the table. *)
		idspace[i].idhlink := nillnk;
	    (* set function cells to undefined *)
	    mkitem(errtag, undefined, idspace[i].funcell);
	    mkitem(errtag, undefined, idspace[i].val);
	    mkitem(errtag, undefined, idspace[i].plist);
	    
	    END;

	(* nil must be the first identifier in the table--id #1 *)
	(* must fill in fields by hand for nilref.*)
	(* putnm can handle any later additions.  *)
	nam := 'NIL';
	strptr := freestr;
	FOR i := 1 TO 3 DO
	    BEGIN
	    strspace[strptr] := nam[i];
	    strptr:= strptr + 1;
	    END;
	strspace[strptr] := eos;
        putnm(freestr, nilref, found);
	IF NOT found THEN
	    freestr := strptr + 1;

	(* make the single character ascii identifiers, except nul(=eos). *)
	FOR i := 1 TO 127  DO
	    BEGIN
	    strspace[freestr] := chr(i);
	    strspace[freestr + 1] := eos;
	    putnm(freestr, idref, found);
	    IF NOT found THEN
		freestr := freestr + 2;
	    IF i = ord('T') THEN
		trueref := idref;
	    (* returns location for 't. *)
	    END;

	(* clear the counters *)
        idspace[xraise].val := trueref;
	gccount := 0;
	consknt := 0;
	END;
	(* init1 *)

    PROCEDURE init2;
	BEGIN
	(* load "symbol table" with identifiers, constants, and functions.  *)
	inchnl := 1;        (* select symbol input file. *)
	outchnl := 1;        (* select standard output file. *)
	reset(symin,'paslsp.ini');
	reset(input);
	rewrite(output);
	xrdtok;     (* get count of identifiers. *)
	IF tag_of(r[1]) <> inttag THEN
	    writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED AT START');
	n := info_of(r[1]);
	FOR i := 1 TO n DO
	    xrdtok;
	(* reading token magically loads it into id space. *)
	xrdtok;         (* look for zero terminator. *)
	IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
	    writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER IDENTIFIERS');

	xrdtok;         (* count of constants  *)
	IF tag_of(r[1]) <> inttag THEN
    writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED BEFORE CONSTANTS');
	n := info_of(r[1]);
	alloc(n);       (* space for constants on the stack *)
	FOR i := 1 TO n DO
	    BEGIN
	    xread;
	    stk[i] := r[1];
	    END;
	xrdtok;
	IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
    writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER CONSTANTS');

	xrdtok;     (* count of functions. *)
	IF tag_of(r[1]) <> inttag THEN
	   writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED BEFORE FUNCTIONS');
	n := info_of(r[1]);
	FOR i := 1 TO n DO
	    (* for each function *)
	    (* store associated code *)
	    BEGIN
	    xrdtok;
	    mkitem(codetag, i, idspace[info_of(r[1])].funcell);
	    END;
	xrdtok;
	IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
    writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER FUNCTIONS');

	END;
	(* init2 *)
    BEGIN       (* init *)
    init1;
    init2;
    END;
    (* init *)

    (********************************************************)
    (*                                                      *)
    (*                 arithmetic functions                 *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xadd1;
    VAR i: longint;

    BEGIN
    int_val(r[1], i);
    mkint(i + 1, 1)
    END;

PROCEDURE xdifference;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 - i2, 1)
    END;

PROCEDURE xdivide;      (* returns dotted pair (quotient . remainder). *)
    VAR quot, rem: integer;
	i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);

    mkint(i1 DIV i2, 1);
    mkint(i1 MOD i2, 2);
    xcons
    END;

PROCEDURE xgreaterp;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);

    IF i1 > i2 THEN
	r[1] := trueref
    ELSE
	r[1] := nilref;
    END;

PROCEDURE xlessp;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);

    IF i1 < i2 THEN
	r[1] := trueref
    ELSE
	r[1] := nilref;
    END;

PROCEDURE xminus;
    VAR i: longint;

    BEGIN
    int_val(r[1], i);
    mkint(-i, 1)
    END;

PROCEDURE xplus2;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 + i2, 1)
    END;

PROCEDURE xquotient;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 DIV i2, 1)
    END;

PROCEDURE xremainder;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 MOD i2, 1)
    END;

PROCEDURE xtimes2;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 * i2, 1)
    END;
    (* xtimes2 *)


    (********************************************************)
    (*                                                      *)
    (*                    support for eval                  *)
    (*                                                      *)
    (********************************************************)


PROCEDURE execute(code: integer);
    FORWARD;

    (* Xapply(fn,arglist)-- "fn" is an operation code. *)
PROCEDURE xxapply;
    VAR
	i: integer;
	code: integer;
	tmp: itemref;
	tmpreg: ARRAY[1..maxreg] OF itemref;
    BEGIN
    code := info_of(r[1]);
    r[1] := r[2];
    i := 1;
    (* spread the arguments  *)
    WHILE (r[1] <> nilref) AND (i <= maxreg) DO
	BEGIN
	tmp := r[1];
	xcar;
	tmpreg[i] := r[1];
	i := i + 1;
	r[1] := tmp;
	xcdr;
	END;
    WHILE i > 1 DO
	BEGIN
	i := i - 1;
	r[i] := tmpreg[i];
	END;
    execute(code);
    END;

Added perq-pascal-lisp-project/pas0.pre version [3176d56a5a].























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
#padtwv (* PreProcessor Version - Run  through Filter *)
#p      (* PERQ version *)
#a      (* Apollo Version *)
#d      (* DEC-20 Version *)
#t      (* Terak Version *)
#w      (* Wicat Version *)
#v      (* VAX version *)
(*********************************************************************
                                    
                PASCAL BASED MINI-LISP

 File:  PAS0.PAS - PASCAL/LISP KERNEL
 ChangeHistory:
    3 Mar 82  RO: Apollo version finished, some changes for WICAT
   16 Feb 82  RO: Implement !*ECHO
   11 Feb 82  RO: Allow string as alias for identifier
    8 Feb 82  RO: Fix GC bug & clean up for apollo
   19 Jan 82  RO: Change I/O channel assginments
   29 Dec 81  RO: File I/O for apollo & wicat
   23 Dec 81  RO: More changes for Apollo & Wicat
    9 Dec 81, RO: Remove apollo specific I/O.
    1 Dec 81  RO: I/O fixes for wicat & fixnum bug
   14 Nov 81, MLG:add some PERQ updates from Voelker
   28 Oct 81, RO: GENSYM & fixnum gc
 
   All RIGHTS RESERVED
   COPYRIGHT (C) - 1981 - M. L. Griss and R. Ottenheimer
   Computer Science Department
           University of Utah

           Do Not distribute with out written consent of M. L. Griss

********************************************************************)

#t (*$S+*) (* swapping mode *)
#t (*$G+*) (* goto is legal *)

#adtvw PROGRAM pas0 ; (* (input*,output) *)
#p    PROGRAM pas0 (input,output, symin, finput,foutput);
    (************************************************************)
    (* support routines for a "lisp" machine.  uses a register  *)
    (* model with a stack for holding frames.  stack also used  *)
    (* to hold compiler generated constants.                    *)
    (* written by:                                              *)
    (*      william f. galway, martin l. griss                  *)
    (*      ralph ottenheimer                                   *)
    (* append pas1...pasn at  end                               *)
    (* -------------------------------------------------------- *)

    (* I/O channel assignments:
     1: symin, used to init symbol table
     2: stdin,
     3: stdout,
     4: finput,
     5: foutput.
    *)

    (************************************************************)
#a (* Apollo System include files *)
#a %include '/sys/ins/base.ins.pas';
#a %include '/sys/ins/pgm.ins.pas';


#p imports Stream from Stream;
#p imports system from system;
#p imports io_others from io_others;
#p imports io_unit from io_unit;

    (************************************************************)

CONST
#aptv    (* for terak, perq, Apollo, vax  *)
#aptvw sp = ' '; 
#aptvw ht = 9;          (* ascii codes *)
#aptvw lf = 10;
#aptvw cr = 13; 
#aptvw nul = 0;

#d    eos = nul;      (* terminator character for strings. *)
#t    (* use eos=chr(nul)  *)
#av  eos=chr(nul) ;
#pw  eos = chr(0);        (* KLUDGE: null string *)
#adtwpv   inchns = 5;       (* number of input channels.  *)
#adtwpv   outchns = 5;      (* number of output channels. *)
    begin_comment = '%';

(* Initial symbols, needed in Kernel *)
    xtoktype  = 129;  (* slot in idspace for toktype. *)
    xbstack   = 130;  (* Bstack Pointer *)
    xthrowing = 131;  (* If throw mode *)
    xinitform = 132;  (* for restart *)
    xraise    = 133;  (* for RAISE of lc in ids *)
    Xinput    = 134;  (* For Open *)
    Xoutput   = 135;  (* For Open *)
    xQuote    = 138;  (* For quoting ids in pascal code. *)
    xEcho     = 136;  (* raw input is echoed if not NIL. *)
    chartype  =  3;   (* various token types *)
    inttype  =  1;
    idtype  =  2;

    max_gsym = 4;       (* number of digits in gen'd id. *)

#dt  shift_const = 8192; (* tags and info are packed into an integer *)
#a   (* no shift const *)
#p   (* no shift const *)
#w   (* no shift const *)
#dt  (* assumed to be at least 16 bits long.  low order 13 bits  *)
#dt  (* are the info, top 3 are the tag.                         *)
#dt    int_offset = 4096;  (* small integers are stored 0..8191    *)
#dt (* instead of -4096..4095 because it will pack smaller      *)
#dt (* under ucsd pascal.                                       *)
#apw     int_offset = 32767; (* Apollo, PERQ and WICAT items are records *)

    (* the various tags - can't use a defined scalar type *)
    (* because of the lack of convertion functions.       *)
    inttag = 0;    (* info is an integer                  *)
    chartag = 1;   (* info is a character code            *)
    pairtag = 2;   (* info points to pair                 *)
    idtag = 3;     (* info points to identifier           *)
    codetag = 4;   (* info is index into a case statement *)
    (*                that calls appropriate function.    *)
    errtag = 5;    (* info is an error code - see below.  *)
    fixtag = 6;    (* info points to a full word (or      *)
    (*                longer) integer.                    *)
    strtag = 7;    (* info points to a string.            *)

    (* error codes.  corresponding to tag = errtag.  *)
    noprspace = 1;    (* no more "pair space"--can't cons. *)
    notpair = 2;      (* a pair operation attempted on a non-pair. *)
    noidspace = 3;    (* no more free identifiers *)
    undefined = 4;    (* used to mark undefined function cells (etc?) *)
    noint = 5;        (* no free integer space after garbage collection *)
    notid = 6;

     (* data space sizes *)
(* remember pointers to these things are inums, sometimes quite small *)
#av      maxpair = 10000;  (* max number of pairs allowed. *)
#dpw     maxpair = 3700;   (* max number of pairs allowed. *)
#t       maxpair = 1000;   (* max number of pairs allowed *)
#tw      maxident = 400;   (* max number of identifiers *)
#adpv    maxident = 800;   (* max number of identifiers *)
#adpv    maxstrsp = 4000;  (* size of string (literal) storage space. *)
                           (* beware - string pointers are inums. *)
#tw      maxstrsp = 2000;  (* size of string (literal) storage space. *)
#adpv    maxintsp = 200;   (* max number of long integers allowed *) 
#tw      maxintsp = 2;   (* max number of long integers allowed *)

    hidmax = 50;      (* number of hash values for identifiers *)
    maxgcstk = 100;   (* size of garbage collection stack.    *)
    stksize = 500;    (* stack size *)
    maxreg = 15;      (* number of registers in lisp machine. *)

    eofcode = 26;     (* magic character code for eof, ascii for *)
    (*  cntrl-z.  kludge, see note in xrdtok.  *)
    choffset = 1;     (* add choffset to ascii code to get address  *)
    (* in id space for corresponding identifier.  *)
    nillnk = 0;       (* when integers are used as pointers.  *)
#dptw end_flag = maxint;  (* marks end of fixnum space *)
#a    end_flag = -2147483648;  (* marks end of fixnum space *)

    (************************************************************)

TYPE
#w   regblk_type = array[0..16] of longint;
#d   onechar = ascii;     (* for DEC *)
#aptvw    onechar = char;     (* for terak,perq,Apollo,Wicat*)
#awv FileName=Packed ARRAY[0..59] of onechar;
#p   FileName: string;
#t   FileName: string[60];
#d   FileName=Packed ARRAY[1..9] of onechar;

    (* note we allow zero for id_ptr, allowing a "nil" link. *)
    stringp = 1..maxstrsp;        (* pointer into string space. *)
    id_ptr = 0..maxident;            (* pointer into id space. *)

#dtv    itemref = integer;
#apw      itemref = RECORD
#apw                tag:integer;
#apw                info:integer;
#apw                END;
    itemtype = 0..7;    (* the tags *)


    pair = PACKED RECORD
                      prcar: itemref;
                      prcdr: itemref;
                  END;


#aw       ascfile = text;
#dptv    ascfile = PACKED FILE OF onechar;
#d       textfile =PACKED FILE of char;

    ident = PACKED RECORD           (* identifier *)
                       idname: stringp;
                       val: itemref;       (* value *)
                       plist: itemref;     (* property list *)
                       funcell: itemref;   (* function cell *)
                       idhlink: id_ptr;    (* hash link *)
                   END;
#dptvw   longint = integer;
#a       longint = integer32;

    (************************************************************)

VAR
    (* global information *)
    nilref, trueref, tmpref: itemref; 
    (* refers to identifiers "nil", "t", and a temp to get around bug in. *)
    (* apollo & wicat pascal *)
    initphase: integer;                (* Start up *)
#adpvw r: ARRAY[1..maxreg] OF itemref;
#t     r: ARRAY[0..maxreg] OF itemref;  (* cuts code size down *)
    rxx,ryy: itemref;

#t  CHARCNT: INTEGER;   (* input buffer & pointer *)
#t  LINE: STRING;

    (* "st" is the stack pointer into "stk".  it counts the number of  *)
    (* items on the stack, so it runs from zero while the stack starts *)
    (* at one.                                                         *)
    st: 0..stksize;
    stk: ARRAY[1..stksize] OF itemref;

    (* pair space *)
    prspace: PACKED ARRAY[1..maxpair] OF pair; (* all pairs stored here. *)
    freepair: integer;          (* pointer to next free pair in prspace. *)

    (* identifier space *)
    idhead: ARRAY[0..hidmax] OF id_ptr;
    idspace: PACKED ARRAY[1..maxident] OF ident;
    freeident: integer;
    g_sym: ARRAY[1..max_gsym] OF onechar;

    (* string space *)
    strspace: PACKED ARRAY[1..maxstrsp] OF onechar;
    freestr: stringp;

    (* large integer space *)
    intspace: ARRAY[1..maxintsp] OF longint;
    freeint: 1..maxintsp;


    (* i/o channels *)
#p  (* files declared on header *)
#adptvw    symin: ascfile;
#adptvw    finput : ascfile;
#aptvw    foutput: ascfile;
#d       foutput: textfile;
#d  input: ascfile;
#a  IoStatus:Integer32;
    inchnl: 1..inchns;      (* current input channel number  *)
    outchnl: 1..outchns;    (* current output channel number *)

    (* "current character" for each input channel.                    *)
    (* may want to include more than one character at some later date *)
    (* (for more lookahead).                                          *)
    ichrbuf: ARRAY[1..inchns] OF onechar;

    (* for collecting statistics. *)
    gccount: integer;           (* counts garbage collections *)
    (* counts from last garbage collection. *)
    consknt: integer;           (* number of times "cons" called *)



(* ........ Everything nested inside CATCH *)

#w procedure _setjmp(var regblk:regblk_type);external;
#w procedure _long_jump(var regblk:regblk_type);external;

Procedure Xcatch;  (* ----------- Outermost Procedure ----------- *)
#adv LABEL 9999;
#w  (* need to use special ASM68 procedures for Wicat *)
 var catch_stk:0..stksize;
     catch_Bstk:itemref;
#w   Catch_regs:regblk_type;

PROCEDURE xread;
    FORWARD;

PROCEDURE xprint;
    FORWARD;

PROCEDURE xunbindto;
    FORWARD;

PROCEDURE xeval;
    FORWARD;

 Procedure Xthrow;
    begin (* throw value *)
        idspace[Xthrowing].val := trueref;
#dav     goto 9999
#w       _long_jump(Catch_regs);
#tp      exit(xeval)
    end (* throw *);
#p (* Special handlers *)
#p Handler CtlC;  (* ------- handle runaway aborts ------- *)

#p begin
#p    write('^C');
#p    IOKeyClear;
#p    IObeep;
#p    if initphase > 1 then Xthrow;
#p end;

    (********************************************************)
    (*                                                      *)
    (*             item selectors & constructors            *)
    (*                                                      *)
    (********************************************************)

#a (* use some SHIFTS ? *)

FUNCTION tag_of(item: itemref): itemtype;
#t       VAR gettag: PACKED RECORD
#t                   CASE boolean OF
#t                   TRUE: (i: itemref);
#t                   FALSE: (info: 0..8191;
#t                           tag: 0..7)
#t               END;

    BEGIN (* tag_of *)
#t    gettag.i := item;
#t    tag_of := gettag.tag
#dv   tag_of := item DIV shift_const;
#apw  tag_of := item.tag;
    END;
    (* tag_of *)

FUNCTION info_of(item: itemref): integer;
#t       VAR getinfo: PACKED RECORD
#t                   CASE boolean OF
#t                   TRUE: (i: itemref);
#t                   FALSE: (info: 0..8191;
#t                           tag: 0..7)
#t               END;

 BEGIN (* info_of *)
#t    getinfo.i := item;
#t    if getinfo.tag = inttag then
#t        info_of := getinfo.info - int_offset
#t    else info_of := getinfo.info
#dv  IF item DIV shift_const = inttag THEN
#dv      info_of := item MOD shift_const - int_offset
#dv  ELSE
#dv      info_of := item MOD shift_const
#apw   info_of := item.info
    END;
    (* info_of *)

FUNCTION xnull(item: itemref): boolean;
    BEGIN
    xnull := (tag_of(item) = tag_of(nilref)) AND 
             (info_of(item) = info_of(nilref))
    END;


PROCEDURE mkitem(tag: itemtype; info: longint; VAR item: itemref);
    (* do range checking on info. ints run from -4096 to +4095 *)
    (* everything else runs from 0 to 8191. ints & chars       *)
    (* contain their info, all others points into an           *)
    (* appropriate space.                                      *)

    PROCEDURE mkfixint;
        VAR nextfree: integer;

        PROCEDURE gc_int;
            VAR i: integer;
            mark_flag: PACKED ARRAY[1..maxintsp] OF boolean;


            PROCEDURE mark(u: itemref);
                BEGIN (* Mark *)
                IF tag_of(u) = pairtag THEN
                    BEGIN
                    mark(prspace[info_of(u)].prcar);
                    mark(prspace[info_of(u)].prcdr)
                    END
                ELSE IF tag_of(u) = fixtag THEN
                    mark_flag[info_of(u)] := true
                END (* Mark *);

            BEGIN (* Gc_int *)
            writeln('*** Gc int');
            FOR i := 1 TO maxintsp do   (* clear mark flags *)
                mark_flag[i] := false;

            FOR i := 1 TO st DO             (* mark from the stack *)
                Mark(stk[i]);

            FOR i := 1 TO maxident DO       (* mark from the symbol table *)
                BEGIN
                Mark(idspace[i].val);
                Mark(idspace[i].plist);
                Mark(idspace[i].funcell)        (* probably NOT necessary *)
                END;

            (* reconstruct free list *)
            FOR i := 1 TO maxintsp - 1 DO
                IF NOT mark_flag[i] THEN
                    BEGIN
                    intspace[i] := freeint;
                    freeint := i
                    END
            END (* Gc_int *);

        BEGIN (* mkfixint *)
        IF info = end_flag THEN (* user can't use magic number *)
                BEGIN info := 0;
                writeln('*****Mkfixint: Info too large')
                END;
        IF intspace[freeint] = end_flag THEN 
            gc_int;    (* garbage collect intspace *)

        IF intspace[freeint] <> end_flag THEN 
            BEGIN    (* convert to fixnum *)
            tag := fixtag;
            nextfree := intspace[freeint];
            intspace[freeint] := info;
            info := freeint;        (* since we want the pointer *)
            freeint := nextfree
            END
        ELSE
            BEGIN mkitem(errtag, noint, r[1]);
            writeln('***** Integer space exhausted')
            END
        END;
        (* mkfixint *)


    BEGIN (* mkitem *)
    IF tag = inttag THEN
#apw     BEGIN
        IF (info < -int_offset) OR (info > int_offset - 1) THEN mkfixint
#dtv   ELSE info := info + int_offset    (* info was in range so add offset *)
#apw     END
    ELSE IF tag = fixtag THEN mkfixint

         ELSE IF info < 0 THEN
                  BEGIN
                  writeln('*****Mkitem: bad neg');
#d                break(output); 
#dtv              halt;
#p                exit(pas0);
#a                pgm_$exit;
                  END;
    (* nothing special to do for other types *)

#dtv     (* pack tag and info into 16-bit item.   *)
#dtv     item := tag * shift_const + info
#apw     item.tag := tag;
#apw     item.info := info
    END;
    (* mkitem *)

PROCEDURE mkerr(info: longint; VAR item: itemref);
 Begin
     mkitem(errtag,info,item);
 End;


PROCEDURE set_info(VAR item: itemref; newinfo: longint);
    BEGIN (* set_info *)
    mkitem(tag_of(item), newinfo, item)
    END;
    (* set_info *)

PROCEDURE set_tag(VAR item: itemref; newtag: itemtype);
    BEGIN (* set_tag *)
    mkitem(newtag, info_of(item), item)
    END;
    (* set_tag *)

PROCEDURE mkident(id: integer; reg: integer);
    (* make identifier "id" in register "reg" *)
    BEGIN       (* mkident *)
    mkitem(idtag, id, r[reg]);
    END;
    (* mkident *)

PROCEDURE mkint(int: longint; reg: integer);
    BEGIN       (* mkint *)
    mkitem(inttag, int, r[reg]);
    END;
    (* mkint *)

PROCEDURE mkpair(pr: integer; reg: integer);
    BEGIN (* mkpair *)
    mkitem(pairtag, pr, r[reg])
    END;
    (* mkpair *)

PROCEDURE int_val(item: itemref; VAR number: longint);
    (* returns integer value of item (int or fixnum). *)
    (* must return 'number' in var parameter instead  *)
    (* of function value since long integers are not  *)
    (* a legal function type in ucsd pascal.          *)
    BEGIN (* int_val *)
    IF tag_of(item) = inttag THEN
        number := info_of(item)
    ELSE IF tag_of(item) = fixtag THEN
             number := intspace[info_of(item)]
    ELSE writeln(tag_of(item), ' *****Illegal data type for numeric operation')
        (* halt or fatal error *)
    END;
    (* int_val *)


    (********************************************************)
    (*                                                      *)
    (*                  stack allocation                    *)
    (*                                                      *)
    (********************************************************)

PROCEDURE alloc(n: integer);
    BEGIN
    IF n + st <= stksize THEN
        st := n+st
    ELSE
        BEGIN
        writeln('*****LISP stack overflow');
        writeln('     tried to allocate ',n);
        writeln('     current stack top is ',st);
#d      break(output);
        END;
    END;

PROCEDURE dealloc(n: integer);
    BEGIN
    IF st - n >= 0 THEN
        st := st - n
    ELSE
        writeln('*****Lisp stack underflow');
    END;

    (* optimized allocs *)

PROCEDURE alloc1;
    BEGIN alloc(1) END;

PROCEDURE dealloc1;
    BEGIN dealloc(1) END;

PROCEDURE alloc2;
    BEGIN alloc(2) END;

PROCEDURE dealloc2;
    BEGIN dealloc(2) END;

PROCEDURE alloc3;
    BEGIN alloc(3) END;

PROCEDURE dealloc3;
    BEGIN dealloc(3) END;


    (********************************************************)
    (*                                                      *)
    (*              support for register model              *)
    (*                                                      *)
    (********************************************************)

PROCEDURE load(reg: integer; sloc: integer);
    BEGIN
    IF sloc < 0 THEN r[reg] := r[-sloc]
    ELSE  r[reg] := stk[st-sloc];
    (* will, fix for load (pos,pos) *)
    END;

PROCEDURE store(reg: integer; sloc: integer);
    BEGIN
    stk[st-sloc] := r[reg];
    END;

    (* optimized load/store. *)
PROCEDURE load10;
    BEGIN
    load(1,0);
    END;

PROCEDURE store10;
    BEGIN
    store(1,0);
    END;

PROCEDURE storenil(sloc: integer);
    BEGIN
    stk[st-sloc] := nilref;
    END;


    (********************************************************)
    (*                                                      *)
    (*              identifier lookup & entry               *)
    (*                                                      *)
    (********************************************************)

function nmhash(nm: stringp): integer;
    CONST
        hashc = 256;
    VAR
        i,tmp: integer;
    BEGIN
    tmp := 0;
    i := 1;     (* get hash code from first three chars of string. *)
    WHILE (i <= 3) AND (strspace[nm+i] <> eos) DO
        BEGIN
        tmp := ord(strspace[nm+i]) + hashc*tmp;
        i := i + 1;
        END;
    nmhash := abs(tmp) MOD hidmax;      (* abs because mod is screwy. *)
    END;

FUNCTION eqstr(s1,s2: stringp): boolean;
    BEGIN
    WHILE (strspace[s1] = strspace[s2]) AND (strspace[s1] <> eos) DO
        BEGIN
        s1 := s1 + 1;
        s2 := s2 + 1;
        END;
    eqstr := (strspace[s1] = strspace[s2]);
    END;

PROCEDURE nmlookup(nm: stringp; VAR found: boolean; VAR hash: integer;
                   VAR loc: itemref);
    (* lookup a name in "identifier space".                                 *)
    (* "hash" returns the hash value for the name.                          *)
    (* "loc" returns the location in the space for the (possibly new)       *)
    (* identifier.                                                          *)
    BEGIN
    hash := nmhash(nm);
    mkitem(idtag, idhead[hash], loc);
    (* default is identifier, but may be "error". *)
    (* start at appropriate hash chain. *)

    found := false;
    WHILE (info_of(loc) <> nillnk) AND (NOT found) DO
        BEGIN
        found := eqstr(nm, idspace[info_of(loc)].idname);
        IF NOT found THEN
            set_info(loc, idspace[info_of(loc)].idhlink);
        (* next id in chain *)
        END;
    IF NOT found THEN               (* find spot for new identifier *)
        BEGIN
        IF freeident=nillnk THEN    (* no more free identifiers. *)
            BEGIN
            mkerr(noidspace, loc);
            writeln('*****Identifer space exhausted')
            END
        ELSE
            BEGIN
            set_info(loc, freeident);
            freeident := idspace[freeident].idhlink;
            END;
        END;
    END;

PROCEDURE putnm(nm: stringp; VAR z: itemref; VAR found: boolean);
    (* put a new name into identifier space, or return old location *)
    (* if it's already there.                                       *)
    VAR
        tmp: ident;
        hash: integer;
    BEGIN
    nmlookup(nm, found, hash, z);
    IF (NOT found) AND (tag_of(z) = idtag) THEN
        BEGIN
        tmp.idname := nm;
        tmp.idhlink := idhead[hash];   (* put new ident at head of chain     *)
        tmp.val := nilref;             (* initialize value and property list *)
        tmp.plist := nilref;
        tmp.funcell := nilref;         (* also, the function cell *)
        idhead[hash] := info_of(z);
        idspace[info_of(z)] := tmp;
        END;
    END;


    (********************************************************)
    (*                                                      *)
    (*              the garbage collector                   *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xfaststat;
    (* give quick summary of statistics gathered *)
    BEGIN
#dw       writeln('Next free pair:   ', freepair, ' out of ', maxpair);
#dw       writeln('Next free fixnum: ', freeint, ' out of ', maxintsp);
#dw       writeln('Next free string: ', freestr, ' out of ', maxstrsp);
          writeln('Next free id loc: ', freeident, ' out of ', maxident);
          writeln('Pair space reclaimed ', gccount, ' times');
          writeln('Conses since last reclaim:',consknt);
          writeln('Stack top is:',st);
#d       break(output)
    END;


PROCEDURE xgcollect;
    VAR
        i: integer;
        markedk: integer;   (* counts the number of pairs marked *)
        freedk: integer;    (* counts the number of pairs freed. *)
        gcstkp: 0..maxgcstk; (* note the garbage collection stack   *)
        mxgcstk: 0..maxgcstk;           (* is local to this procedure. *)
        gcstk: ARRAY[1..maxgcstk] OF integer;
        markflag: PACKED ARRAY[1..maxpair] OF boolean;
        
    PROCEDURE pushref(pr: itemref);
        (* push the address of an unmarked pair, if that's what it is. *)
        BEGIN
        IF tag_of(pr) = pairtag THEN
            IF NOT markflag[info_of(pr)] THEN  (* was .markflag *)
                BEGIN
                IF gcstkp < maxgcstk THEN
                    BEGIN
                    gcstkp := gcstkp + 1;
                    gcstk[gcstkp] := info_of(pr);
                    IF gcstkp > mxgcstk THEN
                        mxgcstk := gcstkp;
                    END
                ELSE
                    BEGIN
                    writeln('*****Garbage stack overflow');
#dtv                halt;
#p                  exit(pas0);
#a                pgm_$exit;
                    END;
                END;
        END;

    PROCEDURE mark;
        (* "recursively" mark pairs referred to from gcstk. gcstk is used to *)
        (* simulate recursion.                                               *)
        VAR
            prloc: integer;
        BEGIN
        WHILE gcstkp > 0 DO
            BEGIN
            prloc := gcstk[gcstkp];
            gcstkp := gcstkp - 1;
            markflag[prloc] := true;
            pushref(prspace[prloc].prcdr);
            pushref(prspace[prloc].prcar);  (* trace the car first. *)
            END;
        END;

    BEGIN       (* xgcollect *)
    writeln;
    writeln('***Garbage collector called');
#d  break(output);
    gccount := gccount + 1;          (* count garbage collections. *)
    xfaststat;   (* give summary of statistics collected *)
    consknt := 0;       (* clear out the cons counter *)
    gcstkp := 0;        (* initialize the garbage stack pointer. *)
    mxgcstk := 0;       (* keeps track of max stack depth. *)

    (* clear markflags *)
    FOR i := 1 TO maxpair DO markflag[i] := false;
    (* mark things from the "computation" stack. *)
    FOR i := 1 TO st DO
        BEGIN
        pushref(stk[i]);
        mark;
        END;
    (* mark things from identifier space. *)
    FOR i := 1 TO maxident DO
        BEGIN
        pushref(idspace[i].val);
        mark;
        pushref(idspace[i].plist);
        mark;
        pushref(idspace[i].funcell);
        mark;
        END;

    (* reconstruct free list by adding things to the head. *)
    freedk := 0;
    markedk := 0;
    FOR i:= 1 TO maxpair - 1 DO
        BEGIN
        IF markflag[i] THEN
            BEGIN
            markedk := markedk + 1;
            markflag[i] := false
            END
        ELSE
            BEGIN
            prspace[i].prcar := nilref;
            mkitem(pairtag, freepair, prspace[i].prcdr);
            freepair := i;
            freedk := freedk + 1
            END
        END;
    writeln(freedk,' pairs freed.');
    writeln(markedk,' pairs in use.');
    writeln('Max gc stack was ',mxgcstk);
#d  break(output);
    mkint(gccount, 1) (* return number of garbage collections *)
    END;
    (* xgcollect *)

    (********************************************************)
    (*                                                      *)
    (*                  lisp primitives                     *)
    (*                                                      *)
    (********************************************************)

    (* return r[1].r[2] in r[1] *)
PROCEDURE xcons;
    VAR p: integer;

    BEGIN
    (* push args onto stack, in case we need to garbage collect the *)
    (* references will be detected.                                 *)
    alloc(2);
    stk[st] := r[1];
    stk[st-1] := r[2];

    IF xNull(prspace[freepair].prcdr) THEN xgcollect;

    p := freepair;
    freepair := info_of(prspace[p].prcdr);
    prspace[p].prcar := stk[st];
    prspace[p].prcdr := stk[st - 1];
    mkpair(p, 1);       (* leave r[1] pointing at new pair. *)

    consknt := consknt + 1;
    dealloc(2);
    END;

PROCEDURE xncons;
    BEGIN r[2] := nilref;
    xcons;
    END;

PROCEDURE xxcons;
    BEGIN rxx := r[1];
    r[1] := r[2];
    r[2] := rxx;
    xcons;
    END;
(* Makes things too big for Apollo ...
PROCEDURE xWrtok;       FORWARD;

PROCEDURE err_not_pair(VAR u: itemref);
    BEGIN
    write('*****Pair operation attempted on '); xwrtok; writeln;
    mkerr(notpair, u);
    END;
*)

    (* return car of r[1] in r[1] *)
PROCEDURE xcar;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
        r[1] := prspace[info_of(r[1])].prcar
    ELSE
        mkerr(notpair, r[1]);
    END;

PROCEDURE xcdr;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
        r[1] := prspace[info_of(r[1])].prcdr
    ELSE
        mkerr(notpair, r[1]);
    END;

PROCEDURE xrplaca;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
        prspace[info_of(r[1])].prcar:=r[2]
    ELSE
        mkerr(notpair, r[1]);
    END;

PROCEDURE xrplacd;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
        prspace[info_of(r[1])].prcdr :=r[2]
    ELSE
        mkerr(notpair, r[1]);
    END;

    (* anyreg car and cdr *)
PROCEDURE anycar(a: itemref; VAR b: itemref);
    BEGIN
    IF tag_of(a) = pairtag THEN
        b := prspace[info_of(a)].prcar
    ELSE
        mkerr(notpair, b);
    END;

PROCEDURE anycdr(a: itemref; VAR b: itemref);
    BEGIN
    IF tag_of(a) = pairtag THEN
        b := prspace[info_of(a)].prcdr
    ELSE
        mkerr(notpair, b);
    END;


    (********************************************************)
    (*                                                      *)
    (*              compress & explode                      *)
    (*                                                      *)
    (********************************************************)

PROCEDURE compress;     (* returns new id from list of chars *)
      VAR i: stringp;
          clist, c: itemref;
          found: boolean;
          int: longint;

    FUNCTION is_int(i: stringp; VAR int: longint): boolean;
        VAR negative, could_be: boolean;

        BEGIN   (* is_int *)
        int := 0;
        could_be := true;
        negative := strspace[i] = '-';
        IF negative OR (strspace[i] = '+') THEN i := i + 1;

        WHILE could_be AND (strspace[i] <> eos) DO
            BEGIN
            IF (strspace[i] >= '0') AND (strspace[i] <= '9') THEN
                 int := int * 10 + (ord(strspace[i]) - ord('0'))
            ELSE could_be := false;
            i := i + 1
            END;

        IF negative THEN int := -int;
        is_int := could_be
        END     (* is_int *);

    BEGIN     (* compress *)
    clist := r[1];        (* list of chars *)
    i := freestr; (* point to possible new string *)

    WHILE (i < maxstrsp) AND NOT xNull(clist) DO
        BEGIN
        IF tag_of(clist) = PAIRTAG THEN
            BEGIN
            c := prspace[info_of(clist)].prcar;
            clist := prspace[info_of(clist)].prcdr;
            IF tag_of(c) = IDTAG THEN
                IF (info_of(c) > choffset) AND
                   (info_of(c) < choffset + 128) THEN 
                    BEGIN 
                    strspace[i] := chr(info_of(c) - choffset);
                    i := i + 1
                    END
                ELSE 
                    writeln('*****Compress: list item not single char')
            ELSE 
                writeln('*****Compress: list item not ID');
            END 
        ELSE 
            writeln('*****Compress: item not list')
        END (* WHILE *);

    strspace[i] := eos;   (* terminate string *)

    IF (i >= maxstrsp) THEN
        writeln('*****String space exhausted')
    ELSE IF is_int(freestr, int) THEN
         mkint(int, 1)
    ELSE (* look the name up, return itemref for it *)
        BEGIN
        putnm(freestr, r[1], found);
        IF NOT found THEN
            freestr := i + 1;
        END
    END       (* compress *);

PROCEDURE explode;      (* returns list of chars from id or int *)
      
      FUNCTION id_explode(i: stringp): itemref;
          BEGIN (* id_explode *)
          IF strspace[i] = eos THEN id_explode := nilref
          ELSE 
              BEGIN
              r[2] := id_explode(i + 1);
              mkident(ord(strspace[i]) + choffset, 1);
              xcons;
              id_explode := r[1]
              END
          END   (* id_explode *);

     FUNCTION int_explode(i: longint): itemref;
          VAR negative: boolean;

          BEGIN (* int_explode *)
          r[1] := nilref;
          IF i < 0 THEN
              BEGIN negative := true;
              i := -i
              END
          ELSE negative := false;

          WHILE i > 0 DO
              BEGIN
              r[2] := r[1];
              mkident(i MOD 10 + ord('0') + choffset, 1);
              xcons;
              i := i DIV 10
              END;

          IF negative THEN
              BEGIN 
              r[2] := r[1];
              mkident(ord('-') + choffset, 1);
              xcons
              END;
          int_explode := r[1]
          END (* int_explode *);

      BEGIN     (* explode *)
      IF tag_of(r[1]) = IDTAG THEN 
          r[1] := id_explode(idspace[info_of(r[1])].idname)
      ELSE IF tag_of(r[1]) = INTTAG THEN 
          r[1] := int_explode(info_of(r[1]))
      ELSE IF tag_of(r[1]) = FIXTAG THEN
          r[1] := int_explode(intspace[info_of(r[1])])
      ELSE IF tag_of(r[1]) = CODETAG THEN
          r[1] := int_explode(info_of(r[1]))
      ELSE 
          writeln('***** EXPLODE: Arg bad type')
      END       (* explode *);

PROCEDURE gensym;
    VAR i: integer;

    PROCEDURE kick(i: integer);     (* increments gsym digit *)
        BEGIN (* Kick *)
        IF (g_sym[i] = '9') THEN 
            BEGIN
            g_sym[i] := '0';
            IF (i < max_gsym) THEN kick(i + 1)  (* otherwise wrap around *)
            END
        ELSE g_sym[i] := succ(g_sym[i])
        
        END (* Kick *);

    BEGIN (* gensym *)
    r[1] := nilref;

    FOR i := 1 TO max_gsym DO
        BEGIN
        r[2] := r[1];
        mkident(ord(g_sym[i]) + choffset, 1);
        xcons
        END;
    r[2] := r[1];
    mkident(ord('G') + choffset, 1);
    xcons;
    compress;

    Kick(1);
    END; (* gensym *)


    (********************************************************)
    (*                                                      *)
    (*                    i/o primitives                    *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xopen;   (* Simple OPEN, but see NPAS0 *)

var s1: FileName;
    i,j : integer;
#a  io_status: integer32;
#p (* catch some I/O errors *)
#p  handler ResetError(name: PathName);
#p  begin
#p    writeln('**** Could not open file -  ',name,' for read');
#p    exit(xopen);
#p  end;

#p  handler RewriteError(name: PathName);
#p  begin
#p    writeln('**** Could not open file -  ',name,' for write');
#p    exit(xopen);
#p  end;
  
begin
      IF tag_of(r[1]) = IDTAG THEN 
      begin
        i := idspace[info_of(r[1])].idname;
#p      s1[0] := chr(255);  (* set length *)
#d     s1:='         ';
#w     s1:="                    ";
#aptv  s1:='                                                            ';
#adpvw j:= 0;
#t     j := 1;

        WHILE (i <= maxstrsp) AND (strspace[i] <> eos) 
#d             AND (j <9 )
          do
        begin
#d      IF strspace[i] <> '.' THEN (* ignore dots in 20 file names. *)
#d      BEGIN
#d        j:= j + 1;
          s1[j] := strspace[i];
#d        END;
#aptvw    j:= j + 1;
          i:= i + 1;
        end;
#p      s1[0]:= chr(j);  (* set Actual Length *)
       
        IF tag_of(r[2]) = IDTAG THEN 
          BEGIN
           If info_of(r[2])= Xinput then
             begin 
#t              close(finput);
#twp            reset(finput, s1);
#d              reset(finput,s1,0,0,'DSK   '); 
#a              close(finput);
#a              open(finput, s1, 'old', io_status);
#a              IF io_status = 0 THEN 
#a                  BEGIN 
#a                  reset(finput);
                    mkint(4,1)
#a                  END
#a              ELSE BEGIN writeln('***** OPEN: Could not open ', s1);
#a                   r[1] := nilref END
             end

           else if info_of(r[2])= Xoutput then
             begin 
#t           close(foutput);
#twp         rewrite(foutput, s1);
#d           rewrite(foutput,s1,0,0,'DSK   '); 
#a           close(foutput);
#a           open(foutput, s1, 'new', io_status);
#a              IF io_status = 0 THEN 
#a                  BEGIN 
#a                  rewrite(foutput);
                    mkint(5,1) 
#a                  END
#a              ELSE BEGIN writeln('***** OPEN: Could not open ', s1);
#a                   r[1] := nilref
#a                   END 
             END
           ELSE
             BEGIN writeln('***** Open: arg2 not INPUT/OUTPUT');
                   mkerr(notid,r[1])
             END
         END  ELSE writeln('***** Open: arg2 bad type')
     END ELSE writeln('***** Open: arg1 bad type');
END;

PROCEDURE xclose;
begin
  case info_of(r[1]) of
        1: ;
        2: ;
        3: ;
#w      4: ;
#w      5: ;
#apt    4: close(finput);
#apt    5: close(foutput);
#d      4: break(finput);
#d      5: break(foutput);
  end;
end;

PROCEDURE xrds;
  (* Select channel for input *)        
  VAR tmp: longint;
    BEGIN
        tmp:=inchnl;
        inchnl := info_of(r[1]);
        mkint(tmp,1)
    END;

PROCEDURE Xwrs;
  (* Select channel for output *)
  VAR tmp:longint;
    BEGIN
        tmp:=outchnl;
        outchnl := info_of(r[1]);
        mkint(tmp,1)
    END;

PROCEDURE xterpri;
    BEGIN
    CASE outchnl OF
#p     3: writeln(' ');
#d     3: begin writeln(output); break(output); end;
#dp    5: begin writeln(foutput,' '); break(foutput); end;
#atw   3: writeln(output);
#atw   5: writeln(foutput);
    END (* CASE *)
    END;

 FUNCTION Int_field(I: longint): Integer;
     VAR width: integer;
         n: longint;
     BEGIN
     width := 1;
     n := 10;
     IF i < 0 THEN width := width + 1; (* For minus sign *)
     i := abs(i);
     WHILE (i >= n) AND (width < 10) DO
         BEGIN width := width + 1;
         n := n * 10
         END;
     int_field := width
     END;

PROCEDURE XwriteInt(I:integer);
    BEGIN
        CASE outchnl OF
        3: write(i: int_field(i));
        5: write(foutput, i: int_field(i));
        END     (* CASE *)
    END  (* XwriteInt *);

PROCEDURE XwriteChar(C:onechar);
    BEGIN
#adptw CASE outchnl OF
#p         3: write('  ', C);
#adtvw     3: write(C);
#p         5: write(foutput,'  ', C);
#adtvw     5: write(foutput,C);
#adptw     END        (* CASE *)
    END;

PROCEDURE xwrtok;
    (* doesn't expand escaped characters in identifier names *)
  VAR  i: integer;
  BEGIN
   IF tag_of(r[1]) = inttag THEN  XwriteInt(info_of(R[1]))
    ELSE IF tag_of(r[1]) = fixtag THEN XwriteInt(intspace[info_of(R[1])])
    ELSE IF tag_of(r[1]) = idtag THEN
         BEGIN
           i := idspace[info_of(r[1])].idname;
           WHILE (i <= maxstrsp) AND (strspace[i] <> eos) DO
                    BEGIN
                    XwriteChar(strspace[i]);
                    i:= i + 1;
                    END;
         END
(*
    ELSE IF tag_of(r[1]) = strtag THEN
        BEGIN xWriteChar('"');
        i := info_of(r[1]);
        WHILE (i <= maxstrsp) AND (strspace[i] <> eos) DO
            BEGIN
            XwriteChar(strspace[i]);
            i := i + 1;
            END;
        xWriteChar('"')
        END
*)

    ELSE IF tag_of(r[1]) = chartag THEN
           XwriteChar(chr(info_of(r[1]) - choffset))
    ELSE IF tag_of(r[1]) = errtag THEN
      Begin XwriteChar(' ');
         XwriteChar('*'); XwriteChar('*'); XwriteChar('*');
         XwriteChar(' '); XwriteChar('#'); XwriteChar(' ');
            XwriteInt(info_of(r[1]));   Xterpri;
      End
    ELSE IF tag_of(r[1]) = codetag THEN
         Begin XwriteChar(' '); XwriteChar('#'); XwriteChar('#');
               XwriteInt(info_of(r[1]));
         End
    ELSE
         Begin
         XwriteChar(' '); XwriteChar('?'); XwriteChar(' ');
            XwriteInt(tag_of(r[1]));
         XwriteChar(' '); XwriteChar('/'); XwriteChar(' ');
            XwriteInt(info_of(r[1]));
         XwriteChar(' '); XwriteChar('?'); XwriteChar(' ');
         End;
#d   break(output);  
    END;

#aptvw FUNCTION eol: boolean;
#aptvw    BEGIN
#aptvw    CASE inchnl OF
#aptvw       1:  eol := eoln(symin);
#aptvw       2:  eol := eoln(input);
#aptvw       4:  eol := eoln(finput);
#aptvw        END;
#aptvw    END;

PROCEDURE rdchnl(chnlnum: integer; VAR ch: onechar);
    BEGIN
    IF (chnlnum < 1) OR (chnlnum > inchns) THEN
     writeln('*****Bad input channel for RDCHNL', chnlnum)
    ELSE
        CASE chnlnum OF
            1:  BEGIN
            ch := symin^;  (* a little strange, but avoids  *)
            get(symin);              (* initialization problems *)
            ichrbuf[inchnl] := symin^; (* Peek ahead *)
            END;

            2:  BEGIN
#t             IF charcnt > Length(line) THEN
#t                 BEGIN
#t                 charcnt := 1;
#t                 Readln(line)
#t                 END;
#t             ch := line[charcnt];
#t             IF Length(line) > charcnt THEN
#t                 ichrbuf[inchnl] := line[charcnt + 1]
#t             ELSE ichrbuf[inchnl] := sp;
#t             charcnt := charcnt + 1
#adpvw      ch := input^;
#adpvw      get(input);
#adpvw      ichrbuf[inchnl] := input^;
            END;
         4:  begin
             ch := finput^;
             get(finput);
             ichrbuf[inchnl] := finput^;
            END;
            END;
    (* case *)
    IF idspace[xEcho].val <> nilref THEN
#aptvw  IF eol THEN BEGIN xWriteChar(ch); xTerpri END ELSE xWriteChar(ch);
#d            xWriteChar(ch);
    END;
    (* rdchnl *)

FUNCTION eofchnl: boolean;
    BEGIN
#adptvw  CASE inchnl OF
#adptvw      1:  eofchnl := eof(symin);
#adptvw      2:  eofchnl := eof(input);
#adptvw      4:  eofchnl := eof(finput);
#adptvw      END;
    END;


    (********************************************************)
    (*                                                      *)
    (*                   token scanner                      *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xrdtok;
LABEL 1;

    VAR
        ch,ch1,ChangedCh: onechar;
        i: integer;
        anint: longint;
        moreid: boolean;
        found: boolean;
        negflag: integer;

    FUNCTION digit(ch: onechar): boolean;
        BEGIN
        digit := ( '0' <= ch ) AND ( ch <= '9');
        END;


    FUNCTION escalpha(VAR ch: onechar): boolean;
        (* test for alphabetic or escaped character. *)
        (* note side effect in ChangedCh.            *)
        BEGIN
        ChangedCh := Ch;
        IF ( 'A' <= ch ) AND ( ch <= 'Z') THEN
            escalpha := true
        ELSE IF ( ord('A')+32 <= ord(ch)) AND ( ord(ch) <= ord('Z')+32) THEN
               BEGIN
                 IF NOT xNull(idspace[xraise].val) THEN
                     Changedch := chr(ord(ch)-32);
                 escalpha := true;    (* lower case alphabetics *)
               END
             ELSE IF ch='!' THEN
                      BEGIN
                      rdchnl(inchnl,ch);
                      ChangedCh:=Ch;
                      escalpha := true;
                      END
                  ELSE
                      escalpha := false;
        END;

    FUNCTION alphanum(VAR ch: onechar): boolean;
        (* test if escalfa or digit *)
        VAR b: boolean;
        BEGIN
        ChangedCh:=Ch;
        b := digit(ch);
        IF NOT b THEN b := escalpha(ch);
        alphanum := b;
        END;

    FUNCTION whitesp(ch: onechar): boolean;
#d     BEGIN
#d      (* may want a faster test *)
#d      whitesp := (ch = sp) OR (ch = cr) OR (ch = lf) OR (ch = ht)
#d      OR (ch = nul);       (* null?? *)
#aptvw    VAR ascode:integer;
#aptvw    BEGIN
#aptvw        ascode:=ord(ch);
#aptvw        WHITESP := (CH = SP) OR (ascode = CR) OR (ascode = LF)
#aptvw    OR (ascode = ht) or (ascode = nul);        (* null?? *)
    END; 

    BEGIN       (* xrdtok *)
1:
    IF NOT eofchnl THEN
        REPEAT                          (* skip leading white space. *)
            rdchnl(inchnl,ch)
        UNTIL (NOT whitesp(ch)) OR eofchnl;
    IF eofchnl THEN
        mkitem(chartag, eofcode + choffset, r[1])
        (* should really return !$eof!$  *)
    ELSE
        BEGIN
        IF digit(ch) or (ch = '-') THEN
            set_tag(r[1], inttag)
        ELSE IF ch = '"' THEN set_tag(r[1], strtag)
        ELSE IF escalpha(ch) THEN
                 set_tag(r[1], idtag)
             ELSE
                 set_tag(r[1], chartag);

        CASE tag_of(r[1]) OF
            chartag:  BEGIN
                  if ch = begin_comment then
                      BEGIN
#d                    While (ch <> cr) do rdchnl(inchnl,ch);
#aptvw                While not eol do rdchnl(inchnl,ch);
                      rdchnl(inchnl, ch);
                      GOTO 1
                      END;
                  set_tag(r[1], idtag);
                  mkitem(inttag, chartype, tmpref);
                  idspace[xtoktype].val := tmpref;
                  set_info(r[1], ord(ch) + choffset);
                  END;
            inttag:   BEGIN
                 mkitem(inttag, inttype, tmpref);
                 idspace[xtoktype].val :=tmpref;
                 negflag := 1;
                 if ch = '-' then
                 begin anint := 0; negflag :=-1 end
                     else anint := ord(ch) - ord('0');
                 WHILE digit(ichrbuf[inchnl]) DO
                     BEGIN
                     rdchnl(inchnl,ch);
                     anint := 10 * anint + (ord(ch) - ord('0'))
                     END;
                 anint := negflag * anint;
                 set_info(r[1], anint)
                 END;
            idtag:    BEGIN
                mkitem(inttag, idtype, tmpref);
                idspace[xtoktype].val:=tmpref;
                i := freestr; (* point to possible new string *)
                moreid := true;
                WHILE (i < maxstrsp) AND moreid DO
                    BEGIN
                    strspace[i] := ChangedCh;
                    (* May have Case Change, etc *)
                    i:= i + 1;
                    moreid :=alphanum(ichrbuf[inchnl]);  (* PEEK ahead char *)
                    IF moreid THEN rdchnl(inchnl,ch) (* Advance readch *)
                    END;
                strspace[i] := eos;   (* terminate string *)
                IF (i >= maxstrsp) THEN
                   writeln('*****String space exhausted')
                ELSE  (* look the name up, return itemref for it *)
                    BEGIN
                    putnm(freestr, r[1], found);
                    IF NOT found THEN
                        freestr := i + 1;
                    END;
                END   (* of case idtag *);
                strtag: BEGIN
                        (* an alias for quoted identifier - special *)
                        (* characters need not be escaped.   *)
                        mkitem(inttag, idtype, tmpref);
                        idspace[xtoktype].val:=tmpref;
                        i := freestr;
                        rdchnl(inchnl, ch); (* scan past " *)
                        WHILE (ch <> '"') AND (i < maxstrsp) DO
                            BEGIN
                            strspace[i] := ch;
                            i := i + 1;
                            rdchnl(inchnl, ch);
                            END;
#adw                    strspace[i] := eos;
#ptv                    strspace[i] := chr(eos);
                        i := i + 1;
                        IF ch <> '"' THEN
                            writeln('***** String space exhausted')
                        ELSE  (* look the name up, return itemref for it *)
                            BEGIN
                            putnm(freestr, r[1], found);
                            set_tag(r[1], idtag);
			    (* must have the form ('QUOTE . id . NIL) *)
                            (* to give the effect of a quoted id.     *)
                            r[2] := nilref;
                            xcons;
                            r[2] := r[1];
                            mkident(xQuote, 1);
                            xcons;
                            IF NOT found THEN
                                freestr := i;
                            END;
                        END (* OF CASE strtag *);
            END (* of case *);
        END;
    END (* xrdtok *);

    (********************************************************)
    (*                                                      *)
    (*                    initialization                    *)
    (*                                                      *)
    (********************************************************)


PROCEDURE init;
    (* initialization procedure depends on  *)
    (* ability to load stack with constants *)
    (* from a file.                         *)
    VAR
        strptr: stringp;
#dptvw  nam: PACKED ARRAY[1..3] OF onechar;
#a      nam: PACKED ARRAY[1..4] OF onechar; (* SPL bug for Apollo *)
        (* holds 'nil', other strings? *)
        i, n: integer;
        idref: itemref;
        found: boolean;

#aptv   (* init is divided into two parts so it can compile on terak *)
    PROCEDURE init1;
        BEGIN
#t      CHARCNT := 1;
#t      LINE := '';
#t      eos := chr(nul);

        (* initialize top of stack *)
        st := 0;

        (* initialize fixnum free list *)
        FOR freeint := 1 TO maxintsp - 1 DO 
            intspace[freeint] := freeint + 1;
        intspace[maxintsp] := end_flag;
        freeint := 1;

        (* define nilref - the id, nil, is defined a little later. *)
        freeident := 1;
        mkitem(idtag, freeident, nilref);

        (* initialize pair space. *)
        FOR i := 1 TO maxpair - 1 DO      (* initialize free list. *)
            BEGIN
            prspace[i].prcar := nilref;         (* just for fun *)
            mkitem(pairtag, i + 1, prspace[i].prcdr);
            END;
        prspace[maxpair].prcar := nilref;
        prspace[maxpair].prcdr := nilref;       (* end flag *)
        freepair := 1;                  (* point to first free pair *)


        (* initialize identifier space and string space. *)
        freestr := 1;
        FOR i := 0 TO hidmax - 1 DO
            idhead[i] := nillnk;
        FOR i := 1 TO maxident DO
            BEGIN
            IF i < maxident THEN
                idspace[i].idhlink := i + 1
            ELSE    (* nil to mark the final identifier in the table. *)
                idspace[i].idhlink := nillnk;
            (* set function cells to undefined *)
            mkerr(undefined, tmpref);
            idspace[i].funcell :=tmpref;
            idspace[i].val :=tmpref;
            idspace[i].plist :=tmpref;
            END;

        (* nil must be the first identifier in the table--id #1 *)
        (* must fill in fields by hand for nilref.*)
        (* putnm can handle any later additions.  *)
        nam := 'NIL';
        strptr := freestr;
        FOR i := 1 TO 3 DO
            BEGIN
            strspace[strptr] := nam[i];
            strptr:= strptr + 1;
            END;
        strspace[strptr] := eos;
        putnm(freestr, nilref, found);
        IF NOT found THEN
            freestr := strptr + 1;

        (* make the single character ascii identifiers, except nul(=eos). *)
        FOR i := 1 TO 127  DO
            BEGIN
            strspace[freestr] := chr(i);
            strspace[freestr + 1] := eos;
            putnm(freestr, idref, found);
            IF NOT found THEN
                freestr := freestr + 2;
            IF i = ord('T') THEN
                BEGIN 
                trueref := idref;    (* returns location for 't. *)
                idspace[info_of(idref)].val := trueref (* Set T to T *)
                END
            END;

        
        (* init gensym id list *)
        FOR i := 1 TO max_gsym DO g_sym[i] := '0';

        (* clear the counters *)
        idspace[xraise].val := trueref; (* gets undone when !*RAISE is read *)
        idspace[xEcho].val := nilref;  (* prevent echo until !*ECHO is read *)
        gccount := 0;
        consknt := 0;
        END;
        (* init1 *)

    PROCEDURE init2;
        BEGIN
        (* load "symbol table" with identifiers, constants, and functions.  *)
        inchnl := 1;        (* select symbol input file. *)
        outchnl := 3;        (* select output file. *)
#p      reset(symin,'paslsp.ini');
#p      reset(input);
#p      rewrite(output);
#w      reset(symin, "paslsp.ini");
#t      reset(symin,'#5:lspini.text');
#d      reset(symin,'paslspini',0,0,'DSK   ');
#d      reset(input,'tty      ',0,0,'TTY   ');
#d      rewrite(output,'tty      ',0,0,'TTY   ');
#a      open(symin,'paslsp.ini','old',iostatus);
#a      reset(symin);
#a      for i:=1 to inchns do
#a         ichrbuf[i]:=' ';
        xrdtok;     (* get count of identifiers. *)
        IF tag_of(r[1]) <> inttag THEN
           writeln('*****Bad symbol table, integer expected at start');
        n := info_of(r[1]);
        FOR i := 1 TO n DO
            xrdtok;
        (* reading token magically loads it into id space. *)
        xrdtok;         (* look for zero terminator. *)
        IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
          writeln('*****Bad symbol table, zero expected after identifiers');

        xrdtok;         (* count of constants  *)
        IF tag_of(r[1]) <> inttag THEN
           writeln('*****Bad symbol table, integer expected before constants');
        n := info_of(r[1]);
        alloc(n);       (* space for constants on the stack *)
        FOR i := 1 TO n DO
            BEGIN
            xread;
            stk[i] := r[1];
            END;
        xrdtok;
        IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
         writeln('*****Bad symbol table, zero expected after constants');
        xrdtok;     (* count of functions. *)
        IF tag_of(r[1]) <> inttag THEN
           writeln('*****Bad symbol table, integer expected before functions');
        n := info_of(r[1]);
        FOR i := 1 TO n DO
            (* for each function *)
            (* store associated code *)
            BEGIN
            xrdtok;
            mkitem(codetag, i, tmpref);
            idspace[info_of(r[1])].funcell :=tmpref;
            END;
        xrdtok;
        IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
         writeln('*****Bad symbol table, zero expected after functions');
        END;
        (* init2 *)

(*
PROCEDURE dumpids;
    VAR i, p: integer;

    BEGIN
    FOR i := 1 TO freeident - 1 DO
        BEGIN
        p := idspace[i].idname;
        write('id #', i:5, ' at', p:5, ': ');
        WHILE strspace[p] <> eos DO
            BEGIN 
            write(strspace[p]);
            p := p + 1
            END;
        write('.  Function code: ');
        writeln(INFO_OF(idspace[i].funcell)); 
        END
    END;
*)

    BEGIN       (* init *)
    init1;
    init2;
    END;
    (* init *)

    (********************************************************)
    (*                                                      *)
    (*                 arithmetic functions                 *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xadd1;
    VAR i: longint;

    BEGIN
    int_val(r[1], i);
    mkint(i + 1, 1)
    END;

PROCEDURE xdifference;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 - i2, 1)
    END;

PROCEDURE xdivide;      (* returns dotted pair (quotient . remainder). *)
    VAR quot, rem: integer;
        i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    IF i2 = 0 THEN writeln('*****Attempt to divide by 0 in DIVIDE')
    ELSE BEGIN mkint(i1 DIV i2, 1);
         mkint(i1 MOD i2, 2);
         END;
    xcons
    END;

PROCEDURE xgreaterp;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);

    IF i1 > i2 THEN
        r[1] := trueref
    ELSE
        r[1] := nilref;
    END;

PROCEDURE xlessp;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);

    IF i1 < i2 THEN
        r[1] := trueref
    ELSE
        r[1] := nilref;
    END;

PROCEDURE xminus;
    VAR i: longint;

    BEGIN
    int_val(r[1], i);
    mkint(-i, 1)
    END;

PROCEDURE xplus2;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 + i2, 1)
    END;

PROCEDURE xquotient;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    IF i2 = 0 THEN writeln('*****Attempt to divide by 0 in QUOTIENT')
    ELSE mkint(i1 DIV i2, 1)
    END;

PROCEDURE xremainder;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    IF i2 = 0 THEN writeln('*****Attempt to divide by 0 in REMAINDER')
    ELSE mkint(i1 MOD i2, 1)
    END;

PROCEDURE xtimes2;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 * i2, 1)
    END;
    (* xtimes2 *)


    (********************************************************)
    (*                                                      *)
    (*                    support for eval                  *)
    (*                                                      *)
    (********************************************************)


PROCEDURE execute(code: integer);
    FORWARD;

    (* Xapply(fn,arglist)-- "fn" is an operation code. *)
PROCEDURE xxapply;
    VAR
        i: integer;
        code: integer;
        tmp: itemref;
        tmpreg: ARRAY[1..maxreg] OF itemref;
    BEGIN
    code := info_of(r[1]);
    r[1] := r[2];
    i := 1;
    (* spread the arguments  *)
    WHILE NOT xNull(r[1]) AND (i <= maxreg) DO
        BEGIN
        tmp := r[1];
        xcar;
        tmpreg[i] := r[1];
        i := i + 1;
        r[1] := tmp;
        xcdr;
        END;
    WHILE i > 1 DO
        BEGIN
        i := i - 1;
        r[i] := tmpreg[i];
        END;
    execute(code);
    END;

    (*  rest of pas1...pasn follow , pasn Closes definition of Catch *)

Added perq-pascal-lisp-project/pas0.save version [32c96d71fe].

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
#padtwv (* PreProcessor Version - Run  through Filter *)
#p      (* PERQ version *)
#a      (* Apollo Version *)
#d      (* DEC-20 Version *)
#t      (* Terak Version *)
#w      (* Wicat Version *)
#v      (* VAX version *)
(*********************************************************************
                                    
                PASCAL BASED MINI-LISP

 File:  PAS0.PAS - PASCAL/LISP KERNEL
 ChangeHistory:
    9 Dec 81, RO: Remove apollo specific I/O.
    1 Dec 81  RO: I/O fixes for wicat & fixnum bug
   14 Nov 81, MLG:add some PERQ updates from Voelker
   28 Oct 81, RO: GENSYM & fixnum gc
 
   All RIGHTS RESERVED
   COPYRIGHT (C) - 1981 - M. L. Griss and R. Ottenheimer
   Computer Science Department
           University of Utah

           Do Not distribute with out written consent of M. L. Griss

********************************************************************)

#t (*$S+*) (* swapping mode *)
#t (*$G+*) (* goto is legal *)

#adtvw PROGRAM pas0 ; (* (input*,output) *)
#p    PROGRAM pas0 (input,output, symin, finput,foutput);
    (************************************************************)
    (* support routines for a "lisp" machine.  uses a register  *)
    (* model with a stack for holding frames.  stack also used  *)
    (* to hold compiler generated constants.                    *)
    (* written by:                                              *)
    (*      william f. galway, martin l. griss                  *)
    (*      ralph ottenheimer                                   *)
    (* append pas1...pasn at  end                               *)
    (* -------------------------------------------------------- *)
    (* symin is input channel one--used to initialize "symbol   *)
    (* table".  input is input channel two--standard input.     *)
    (* output is output channel one--the standard output.       *)
    (* finput is file input channel three.                      *)
    (* foutput is file output channel four.                     *)
    (************************************************************)
#a (* Apollo System include files *)
#a %include '/sys/ins/base.ins.pas';
#a %include '/sys/ins/base_transition.ins.pas';
#a %include '/sys/ins/streams.ins.pas';
#a %include '/sys/ins/pgm.ins.pas';


#p imports Stream from Stream;
#p imports system from system;
#p imports io_others from io_others;
#p imports io_unit from io_unit;

    (************************************************************)

CONST
#aptv    (* for terak, perq, Apollo, vax  *)
#aptvw sp = ' '; 
#aptvw ht = 9;          (* ascii codes *)
#aptvw lf = 10;
#aptvw cr = 13; 
#aptvw nul = 0;

#d    eos = nul;      (* terminator character for strings. *)
#t    (* use eos=chr(nul)  *)
#av  eos=chr(nul) ;
#pw  eos = chr(0);        (* KLUDGE: null string *)
#adtwpv   inchns = 3;       (* number of input channels.  *)
#adtwpv   outchns = 2;      (* number of output channels. *)
    begin_comment = '%';

(* Initial symbols, needed in Kernel *)
    xtoktype  = 129;  (* slot in idspace for toktype. *)
    xbstack   = 130;  (* Bstack Pointer *)
    xthrowing = 131;  (* If throw mode *)
    xinitform = 132;  (* for restart *)
    xraise    = 133;  (* for RAISE of lc in ids *)
    Xinput    = 134;  (* For Open *)
    Xoutput   = 135;  (* For Open *)
    chartype  =  3;   (* various token types *)
    inttype  =  1;
    idtype  =  2;

    max_gsym = 4;       (* number of digits in gen'd id. *)

#dt  shift_const = 8192; (* tags and info are packed into an integer *)
#av shift_const = 4096;
#p   (* no shift const *)
#w   (* no shift const *)
    (* assumed to be at least 16 bits long.  low order 13 bits  *)
    (* are the info, top 3 are the tag.                         *)
#dt    int_offset = 4096;  (* small integers are stored 0..8191    *)
#av    int_offset = 2048;  (* small integers are stored -2048..2047 *)
#pw     int_offset = 32767; (* PERQ and WICAT items are records *)
#dt (* instead of -4096..4095 because it will pack smaller      *)
#dt (* under ucsd pascal.                                       *)

    (* the various tags - can't use a defined scalar type *)
    (* because of the lack of convertion functions.       *)
    inttag = 0;    (* info is an integer                  *)
    chartag = 1;   (* info is a character code            *)
    pairtag = 2;   (* info points to pair                 *)
    idtag = 3;     (* info points to identifier           *)
    codetag = 4;   (* info is index into a case statement *)
    (*                that calls appropriate function.    *)
    errtag = 5;    (* info is an error code - see below.  *)
    fixtag = 6;    (* info points to a full word (or      *)
    (*                longer) integer.                    *)
    flotag = 7;    (* info points to a float number.      *)

    (* error codes.  corresponding to tag = errtag.  *)
    noprspace = 1;    (* no more "pair space"--can't cons. *)
    notpair = 2;      (* a pair operation attempted on a non-pair. *)
    noidspace = 3;    (* no more free identifiers *)
    undefined = 4;    (* used to mark undefined function cells (etc?) *)
    noint = 5;        (* no free integer space after garbage collection *)
    notid = 6;

     (* data space sizes *)
#adwv    maxpair = 10000;  (* max number of pairs allowed. *)
#p       maxpair = 3700;   (* max number of pairs allowed. *)
#t       maxpair = 1000;   (* max number of pairs allowed *)
#t       maxident = 400;   (* max number of identifiers *)
#adpwv   maxident = 800;   (* max number of identifiers *)
#adpwv   maxstrsp = 4500;  (* size of string (literal) storage space. *)
#t      maxstrsp = 2000;  (* size of string (literal) storage space. *)
    maxintsp = 200;   (* max number of long integers allowed *)
#t  maxflosp = 2;     (* max number of floating numbers allowed *)
#adpwv maxflosp = 50; (* max number of floating numbers allowed *)

    hidmax = 50;      (* number of hash values for identifiers *)
    maxgcstk = 100;   (* size of garbage collection stack.    *)
    stksize = 500;    (* stack size *)
    maxreg = 15;      (* number of registers in lisp machine. *)

    eofcode = 26;     (* magic character code for eof, ascii for *)
    (*  cntrl-z.  kludge, see note in xrdtok.  *)
    choffset = 1;     (* add choffset to ascii code to get address  *)
    (* in id space for corresponding identifier.  *)
    nillnk = 0;       (* when integers are used as pointers.  *)
    end_flag = maxint;  (* marks end of fixnum space *)

    (************************************************************)

TYPE
#w   regblk_type:array[0..16] of longint;
#d   onechar = ascii;     (* for DEC *)
#aptvw    onechar = char;     (* for terak,perq,Apollo,Wicat*)
#a   real= integer32;        (* Kludge, no reals yet *)
#p   FileName= String;       (* For PERQ FileName *)
#atwv FileName=Packed ARRAY[0..8] of onechar;
#d    FileName=Packed ARRAY[1..9] of onechar;
    (* note we allow zero for id_ptr, allowing a "nil" link. *)

    stringp = 1..maxstrsp;        (* pointer into string space. *)
    id_ptr = 0..maxident;            (* pointer into id space. *)

#adtv    itemref = integer;
#pw      itemref = RECORD
#pw                tag:integer;
#pw                info:integer;
#pw                END;
    itemtype = 0..7;    (* the tags *)


    pair = PACKED RECORD
                      prcar: itemref;
                      prcdr: itemref;
        (* OLD        markflag:boolean , but wastes space *)
                  END;


#aw       ascfile = text;
#dptv    ascfile = PACKED FILE OF onechar;
#d       textfile =PACKED FILE of char;
#a      (* No PASCAL file I/O yet *)

    ident = PACKED RECORD           (* identifier *)
                       idname: stringp;
                       val: itemref;       (* value *)
                       plist: itemref;     (* property list *)
                       funcell: itemref;   (* function cell *)
                       idhlink: id_ptr;    (* hash link *)
                   END;
#dptvw   longint = integer;
#a       longint = integer; (* Should be integer32  ? *)

    (************************************************************)

VAR
    (* global information *)
    nilref, trueref, tmpref: itemref; 
    (* refers to identifiers "nil", "t", and a temp to get around bug in. *)
    (* apollo & wicat pascal *)
    initphase: integer;                (* Start up *)
#adpvw r: ARRAY[1..maxreg] OF itemref;
#t     r: ARRAY[0..maxreg] OF itemref;  (* cuts code size down *)
    rxx,ryy: itemref;

#tw  CHARCNT: INTEGER;   (* input buffer & pointer *)
#tw  LINE: STRING;

    (* "st" is the stack pointer into "stk".  it counts the number of  *)
    (* items on the stack, so it runs from zero while the stack starts *)
    (* at one.                                                         *)
    st: 0..stksize;
    stk: ARRAY[1..stksize] OF itemref;

    (* pair space *)
    prspace: PACKED ARRAY[1..maxpair] OF pair; (* all pairs stored here. *)
    freepair: integer;          (* pointer to next free pair in prspace. *)

    (* identifier space *)
    idhead: ARRAY[0..hidmax] OF id_ptr;
    idspace: PACKED ARRAY[1..maxident] OF ident;
    freeident: integer;
    g_sym: ARRAY[1..max_gsym] OF onechar;

    (* string space *)
    strspace: PACKED ARRAY[1..maxstrsp] OF onechar;
    freestr: stringp;

    (* large integer space *)
    intspace: ARRAY[1..maxintsp] OF longint;    (* use long int on terak *)
    freeint: 1..maxintsp;

    (* floating point number space *)
    flospace: ARRAY[1..maxflosp] OF real;
    freefloat: 1..maxflosp;

    (* i/o channels *)
#p  (* files declared on header *)
#adptvw    symin: ascfile;
#adptvw    finput : ascfile;
#aptvw    foutput: ascfile;
#d       foutput: textfile;
#d  input: ascfile;
#a  IoStatus:Integer32;
    inchnl: 1..inchns;      (* current input channel number  *)
    outchnl: 1..outchns;    (* current output channel number *)

    (* "current character" for each input channel.                    *)
    (* may want to include more than one character at some later date *)
    (* (for more lookahead).                                          *)
    ichrbuf: ARRAY[1..inchns] OF onechar;

    (* for collecting statistics. *)
    gccount: integer;           (* counts garbage collections *)
    (* counts from last garbage collection. *)
    consknt: integer;           (* number of times "cons" called *)



(* ........ Everything nested inside CATCH *)

#w procedure _setjmp(var regblk:regblk_type);external;
#w procedure _long_jump(var regblk:regblk_type);external;

Procedure Xcatch;  (* ----------- Outermost Procedure ----------- *)
#adv LABEL 9999;
#w  (* need to use special ASM68 procedures for Wicat *)
 var catch_stk:0..stksize;
     catch_Bstk:itemref;
#w   Catch_regs:regblk_type;

#t Procedure xeval;
#t  Forward;
PROCEDURE xread;
    FORWARD;

PROCEDURE xprint;
    FORWARD;

PROCEDURE xunbindto;
    FORWARD;

PROCEDURE xeval;
    FORWARD;

 Procedure Xthrow;
    begin (* throw value *)
        idspace[Xthrowing].val := trueref;
#dav     goto 9999
#w       _long_jump(Catch_regs);
#tp      exit(xeval)
    end (* throw *);
#p (* Special handlers *)
#p Handler CtlC;  (* ------- handle runaway aborts ------- *)

#p begin
#p    write('^C');
#p    IOKeyClear;
#p    IObeep;
#p    if initphase > 1 then Xthrow;
#p end;

    (********************************************************)
    (*                                                      *)
    (*             item selectors & constructors            *)
    (*                                                      *)
    (********************************************************)

#a (* use some SHIFTS ? *)

FUNCTION tag_of(item: itemref): itemtype;
#t       VAR gettag: PACKED RECORD
#t                   CASE boolean OF
#t                   TRUE: (i: itemref);
#t                   FALSE: (info: 0..8191;
#t                           tag: 0..7)
#t               END;

    BEGIN (* tag_of *)
#t    gettag.i := item;
#t    tag_of := gettag.tag
#adv    tag_of := item DIV shift_const;
#pw       tag_of := item.tag;
    END;
    (* tag_of *)

FUNCTION info_of(item: itemref): integer;
#t       VAR getinfo: PACKED RECORD
#t                   CASE boolean OF
#t                   TRUE: (i: itemref);
#t                   FALSE: (info: 0..8191;
#t                           tag: 0..7)
#t               END;

 BEGIN (* info_of *)
#t    getinfo.i := item;
#t    if getinfo.tag = inttag then
#t        info_of := getinfo.info - int_offset
#t    else info_of := getinfo.info
#adv  IF item DIV shift_const = inttag THEN
#adv      info_of := item MOD shift_const - int_offset
#adv  ELSE
#adv      info_of := item MOD shift_const
#pw   info_of := item.info
    END;
    (* info_of *)

FUNCTION xnull(item: itemref): boolean;
    BEGIN
    xnull := (tag_of(item) = tag_of(nilref)) AND 
             (info_of(item) = info_of(nilref))
    END;


PROCEDURE mkitem(tag: itemtype; info: longint; VAR item: itemref);
    (* do range checking on info. ints run from -4096 to +4095 *)
    (* everything else runs from 0 to 8191. ints & chars       *)
    (* contain their info, all others points into an           *)
    (* appropriate space.                                      *)

    PROCEDURE mkfixint;
        VAR nextfree: integer;

        PROCEDURE gc_int;
            VAR i: integer;
            mark_flag: PACKED ARRAY[1..maxintsp] OF boolean;


            PROCEDURE mark(u: itemref);
                BEGIN (* Mark *)
                IF tag_of(u) = pairtag THEN
                    BEGIN
                    mark(prspace[info_of(u)].prcar);
                    mark(prspace[info_of(u)].prcdr)
                    END
                ELSE IF tag_of(u) = fixtag THEN
                    mark_flag[info_of(u)] := true
                END (* Mark *);

            BEGIN (* Gc_int *)
            writeln('*** Gc int');
            FOR i := 1 TO maxintsp do   (* clear mark flags *)
                mark_flag[i] := false;

            FOR i := 1 TO st DO             (* mark from the stack *)
                Mark(stk[i]);

            FOR i := 1 TO maxident DO       (* mark from the symbol table *)
                BEGIN
                Mark(idspace[i].val);
                Mark(idspace[i].plist);
                Mark(idspace[i].funcell)        (* probably NOT necessary *)
                END;

            (* reconstruct free list *)
            FOR i := 1 TO maxintsp - 1 DO
                IF NOT mark_flag[i] THEN
                    BEGIN
                    intspace[i] := freeint;
                    freeint := i
                    END
            END (* Gc_int *);

        BEGIN (* mkfixint *)
        IF intspace[freeint] = end_flag THEN 
            gc_int;    (* garbage collect intspace *)

        IF intspace[freeint] <> end_flag THEN 
            BEGIN    (* convert to fixnum *)
            tag := fixtag;
            nextfree := intspace[freeint];
            intspace[freeint] := info;
            info := freeint;        (* since we want the pointer *)
            freeint := nextfree
            END
        ELSE
            BEGIN mkitem(errtag,noint, r[1]);
            writeln('***** Integer space exhausted')
            END
        END;
        (* mkfixint *)


    BEGIN (* mkitem *)
    IF tag = inttag THEN
#pw     BEGIN
        IF (info < -int_offset) OR (info > int_offset - 1) THEN mkfixint
#adtv   ELSE info := info + int_offset    (* info was in range so add offset *)
#pw     END
    ELSE IF tag = fixtag THEN mkfixint

         ELSE IF info < 0 THEN
                  BEGIN
                  writeln('*****MKITEM: BAD NEG');
#d                break(output); 
#dtv              halt;
#p                exit(pas0);
#a                pgm_$exit;
                  END;
    (* nothing special to do for other types *)

    (* pack tag and info into 16-bit item.   *)
#adtv    item := tag * shift_const + info
#pw      item.tag := tag;
#pw      item.info := info
    END;
    (* mkitem *)

PROCEDURE mkerr(info: longint; VAR item: itemref);
 Begin
     mkitem(errtag,info,item);
 End;


PROCEDURE set_info(VAR item: itemref; newinfo: longint);
    BEGIN (* set_info *)
    mkitem(tag_of(item), newinfo, item)
    END;
    (* set_info *)

PROCEDURE set_tag(VAR item: itemref; newtag: itemtype);
    BEGIN (* set_tag *)
    mkitem(newtag, info_of(item), item)
    END;
    (* set_tag *)

PROCEDURE mkident(id: integer; reg: integer);
    (* make identifier "id" in register "reg" *)
    BEGIN       (* mkident *)
    mkitem(idtag, id, r[reg]);
    END;
    (* mkident *)

PROCEDURE mkint(int: longint; reg: integer);
    BEGIN       (* mkint *)
    mkitem(inttag, int, r[reg]);
    END;
    (* mkint *)

PROCEDURE mkpair(pr: integer; reg: integer);
    BEGIN (* mkpair *)
    mkitem(pairtag, pr, r[reg])
    END;
    (* mkpair *)

PROCEDURE int_val(item: itemref; VAR number: longint);
    (* returns integer value of item (int or fixnum). *)
    (* must return 'number' in var parameter instead  *)
    (* of function value since long integers are not  *)
    (* a legal function type in ucsd pascal.          *)
    BEGIN (* int_val *)
    IF tag_of(item) = inttag THEN
        number := info_of(item)
    ELSE IF tag_of(item) = fixtag THEN
             number := intspace[info_of(item)]
    ELSE writeln('***** ILLEGAL DATA TYPE FOR NUMERIC OPERATION')
        (* halt or fatal error *)
    END;
    (* int_val *)


    (********************************************************)
    (*                                                      *)
    (*                  stack allocation                    *)
    (*                                                      *)
    (********************************************************)

PROCEDURE alloc(n: integer);
    BEGIN
    IF n + st <= stksize THEN
        st := n+st
    ELSE
        BEGIN
        writeln('*****LISP STACK OVERFLOW');
        writeln('     TRIED TO ALLOCATE ',n);
        writeln('     CURRENT STACK TOP IS ',st);
#d      break(output);
        END;
    END;

PROCEDURE dealloc(n: integer);
    BEGIN
    IF st - n >= 0 THEN
        st := st - n
    ELSE
        writeln('*****LISP STACK UNDERFLOW');
    END;

    (* optimized allocs *)

PROCEDURE alloc1;
    BEGIN alloc(1) END;

PROCEDURE dealloc1;
    BEGIN dealloc(1) END;

PROCEDURE alloc2;
    BEGIN alloc(2) END;

PROCEDURE dealloc2;
    BEGIN dealloc(2) END;

PROCEDURE alloc3;
    BEGIN alloc(3) END;

PROCEDURE dealloc3;
    BEGIN dealloc(3) END;


    (********************************************************)
    (*                                                      *)
    (*              support for register model              *)
    (*                                                      *)
    (********************************************************)

PROCEDURE load(reg: integer; sloc: integer);
    BEGIN
    IF sloc < 0 THEN r[reg] := r[-sloc]
    ELSE  r[reg] := stk[st-sloc];
    (* will, fix for load (pos,pos) *)
    END;

PROCEDURE store(reg: integer; sloc: integer);
    BEGIN
    stk[st-sloc] := r[reg];
    END;

    (* optimized load/store. *)
PROCEDURE load10;
    BEGIN
    load(1,0);
    END;

PROCEDURE store10;
    BEGIN
    store(1,0);
    END;

PROCEDURE storenil(sloc: integer);
    BEGIN
    stk[st-sloc] := nilref;
    END;

(* Other primitives ?? *)

    (********************************************************)
    (*                                                      *)
    (*              identifier lookup & entry               *)
    (*                                                      *)
    (********************************************************)

function nmhash(nm: stringp): integer;
    CONST
        hashc = 256;
    VAR
        i,tmp: integer;
    BEGIN
    tmp := 0;
    i := 1;     (* get hash code from first three chars of string. *)
    WHILE (i <= 3) AND (strspace[nm+i] <> eos) DO
        BEGIN
        tmp := ord(strspace[nm+i]) + hashc*tmp;
        i := i + 1;
        END;
    nmhash := abs(tmp) MOD hidmax;      (* abs because mod is screwy. *)
    END;

FUNCTION eqstr(s1,s2: stringp): boolean;
    BEGIN
    WHILE (strspace[s1] = strspace[s2]) AND (strspace[s1] <> eos) DO
        BEGIN
        s1 := s1 + 1;
        s2 := s2 + 1;
        END;
    eqstr := (strspace[s1] = strspace[s2]);
    END;

PROCEDURE nmlookup(nm: stringp; VAR found: boolean; VAR hash: integer;
                   VAR loc: itemref);
    (* lookup a name in "identifier space".                                 *)
    (* "hash" returns the hash value for the name.                          *)
    (* "loc" returns the location in the space for the (possibly new)       *)
    (* identifier.                                                          *)
    BEGIN
    hash := nmhash(nm);
    mkitem(idtag, idhead[hash], loc);
    (* default is identifier, but may be "error". *)
    (* start at appropriate hash chain. *)

    found := false;
    WHILE (info_of(loc) <> nillnk) AND (NOT found) DO
        BEGIN
        found := eqstr(nm, idspace[info_of(loc)].idname);
        IF NOT found THEN
            set_info(loc, idspace[info_of(loc)].idhlink);
        (* next id in chain *)
        END;
    IF NOT found THEN               (* find spot for new identifier *)
        BEGIN
        IF freeident=nillnk THEN    (* no more free identifiers. *)
            mkerr( noidspace, loc)
        ELSE
            BEGIN
            set_info(loc, freeident);
            freeident := idspace[freeident].idhlink;
            END;
        END;
    END;

PROCEDURE putnm(nm: stringp; VAR z: itemref; VAR found: boolean);
    (* put a new name into identifier space, or return old location *)
    (* if it's already there.                                       *)
    VAR
        tmp: ident;
        hash: integer;
    BEGIN
    nmlookup(nm, found, hash, z);
    IF (NOT found) AND (tag_of(z) = idtag) THEN
        BEGIN
        tmp.idname := nm;
        tmp.idhlink := idhead[hash];   (* put new ident at head of chain     *)
        tmp.val := nilref;             (* initialize value and property list *)
        tmp.plist := nilref;
        tmp.funcell := nilref;         (* also, the function cell *)
        idhead[hash] := info_of(z);
        idspace[info_of(z)] := tmp;
        END;
    END;

PROCEDURE xfaststat;
    (* give quick summary of statistics gathered *)
    BEGIN
          writeln('CONSES:',consknt);
          writeln('ST    :',st);
#d       break(output)
    END;


    (********************************************************)
    (*                                                      *)
    (*              the garbage collector                   *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xgcollect;
    VAR
        i: integer;
        markedk: integer;   (* counts the number of pairs marked *)
        freedk: integer;    (* counts the number of pairs freed. *)
        gcstkp: 0..maxgcstk; (* note the garbage collection stack   *)
        mxgcstk: 0..maxgcstk;           (* is local to this procedure. *)
        gcstk: ARRAY[1..maxgcstk] OF integer;
        markflag: PACKED ARRAY[1..maxpair] OF boolean;
(* used not to have array here *)
        
    PROCEDURE pushref(pr: itemref);
        (* push the address of an unmarked pair, if that's what it is. *)
        BEGIN
        IF tag_of(pr) = pairtag THEN
            IF NOT markflag[info_of(pr)] THEN  (* was .markflag *)
                BEGIN
                IF gcstkp < maxgcstk THEN
                    BEGIN
                    gcstkp := gcstkp + 1;
                    gcstk[gcstkp] := info_of(pr);
                    IF gcstkp > mxgcstk THEN
                        mxgcstk := gcstkp;
                    END
                ELSE
                    BEGIN
                    writeln('*****GARBAGE STACK OVERFLOW');
#dtv                halt;
#p                  exit(pas0);
#a                pgm_$exit;
                    END;
                END;
        END;

    PROCEDURE mark;
        (* "recursively" mark pairs referred to from gcstk. gcstk is used to *)
        (* simulate recursion.                                               *)
        VAR
            prloc: integer;
        BEGIN
        WHILE gcstkp > 0 DO
            BEGIN
            prloc := gcstk[gcstkp];
            gcstkp := gcstkp - 1;
            markflag[prloc] := true;
(* OLD      prspace[prloc].markflag := true;  *)
            pushref(prspace[prloc].prcdr);
            pushref(prspace[prloc].prcar);  (* trace the car first. *)
            END;
        END;

    BEGIN       (* xgcollect *)
    writeln('***GARBAGE COLLECTOR CALLED');
#d  break(output);
    gccount := gccount + 1;          (* count garbage collections. *)
    xfaststat;   (* give summary of statistics collected *)
    consknt := 0;       (* clear out the cons counter *)
    gcstkp := 0;        (* initialize the garbage stack pointer. *)
    mxgcstk := 0;       (* keeps track of max stack depth. *)

    (* clear markflags *)
    FOR i := 1 TO maxpair DO markflag[i] := false;
    (* OLD: wasnt needed *)
    (* mark things from the "computation" stack. *)
    FOR i := 1 TO st DO
        BEGIN
        pushref(stk[i]);
        mark;
        END;
    (* mark things from identifier space. *)
    FOR i := 1 TO maxident DO
        BEGIN
        pushref(idspace[i].val);
        mark;
        pushref(idspace[i].plist);
        mark;
        pushref(idspace[i].funcell);
        mark;
        END;

    (* reconstruct free list by adding things to the head. *)
    freedk := 0;
    markedk := 0;
    FOR i:= 1 TO maxpair - 1 DO
        BEGIN
        IF markflag[i] THEN
        (* OLD: IF prspace[i].markflag THEN  *)
            BEGIN
            markedk := markedk + 1;
            markflag[i] := false
            (* OLD: prspace[i].markflag := false *)
            END
        ELSE
            BEGIN
            prspace[i].prcar := nilref;
            mkitem(pairtag, freepair, prspace[i].prcdr);
            freepair := i;
            freedk := freedk + 1
            END
        END;
    writeln(freedk,' PAIRS FREED.');
    writeln(markedk,' PAIRS IN USE.');
    writeln('MAX GC STACK WAS ',mxgcstk);
#d  break(output);
    END;
    (* xgcollect *)

    (********************************************************)
    (*                                                      *)
    (*                  lisp primitives                     *)
    (*                                                      *)
    (********************************************************)

    (* return r[1].r[2] in r[1] *)
PROCEDURE xcons;
    VAR p: integer;

    BEGIN
    (* push args onto stack, in case we need to garbage collect the *)
    (* references will be detected.                                 *)
    alloc(2);
    stk[st] := r[1];
    stk[st-1] := r[2];

    IF xNull(prspace[freepair].prcdr) THEN xgcollect;

    p := freepair;
    freepair := info_of(prspace[p].prcdr);
    prspace[p].prcar := stk[st];
    prspace[p].prcdr := stk[st - 1];
    mkpair(p, 1);       (* leave r[1] pointing at new pair. *)

    consknt := consknt + 1;
    dealloc(2);
    END;

PROCEDURE xncons;
    BEGIN r[2] := nilref;
    xcons;
    END;

PROCEDURE xxcons;
    BEGIN rxx := r[1];
    r[1] := r[2];
    r[2] := rxx;
    xcons;
    END;

    (* return car of r[1] in r[1] *)
PROCEDURE xcar;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
        r[1] := prspace[info_of(r[1])].prcar
    ELSE
        mkerr( notpair, r[1]);
    END;

PROCEDURE xcdr;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
        r[1] := prspace[info_of(r[1])].prcdr
    ELSE
        mkerr( notpair, r[1]);
    END;

PROCEDURE xrplaca;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
        prspace[info_of(r[1])].prcar:=r[2]
    ELSE
        mkerr( notpair, r[1]);
    END;

PROCEDURE xrplacd;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
        prspace[info_of(r[1])].prcdr :=r[2]
    ELSE
        mkerr( notpair, r[1]);
    END;

    (* anyreg car and cdr *)
PROCEDURE anycar(a: itemref; VAR b: itemref);
    BEGIN
    IF tag_of(a) = pairtag THEN
        b := prspace[info_of(a)].prcar
    ELSE
        mkerr( notpair, b);
    END;

PROCEDURE anycdr(a: itemref; VAR b: itemref);
    BEGIN
    IF tag_of(a) = pairtag THEN
        b := prspace[info_of(a)].prcdr
    ELSE
        mkerr( notpair, b);
    END;


    (********************************************************)
    (*                                                      *)
    (*              compress & explode                      *)
    (*                                                      *)
    (********************************************************)

PROCEDURE compress;     (* returns new id from list of chars *)
      VAR i: stringp;
          clist, c: itemref;
          found: boolean;
          int: integer;

    FUNCTION is_int(i: stringp; VAR int: longint): boolean;
        VAR negative, could_be: boolean;

        BEGIN   (* is_int *)
        int := 0;
        could_be := true;
        negative := strspace[i] = '-';
        IF negative OR (strspace[i] = '+') THEN i := i + 1;

        WHILE could_be AND (strspace[i] <> eos) DO
            BEGIN
            IF (strspace[i] >= '0') AND (strspace[i] <= '9') THEN
                 int := int * 10 + (ord(strspace[i]) - ord('0'))
            ELSE could_be := false;
            i := i + 1
            END;

        IF negative THEN int := -int;
        is_int := could_be
        END     (* is_int *);

    BEGIN     (* compress *)
    clist := r[1];        (* list of chars *)
    i := freestr; (* point to possible new string *)

    WHILE (i < maxstrsp) AND NOT xNull(clist) DO
        BEGIN
        IF tag_of(clist) = PAIRTAG THEN
            BEGIN
            c := prspace[info_of(clist)].prcar;
            clist := prspace[info_of(clist)].prcdr;
            IF tag_of(c) = IDTAG THEN
                IF (info_of(c) > choffset) AND
                   (info_of(c) < choffset + 128) THEN 
                    BEGIN 
                    strspace[i] := chr(info_of(c) - choffset);
                    i := i + 1
                    END
                ELSE 
                    writeln('*****COMPRESS: LIST ID NOT SINGLE CHAR')
            ELSE 
                writeln('*****COMPRESS: LIST ITEM NOT ID');
            END 
        ELSE 
            writeln('*****COMPRESS: ITEM NOT LIST')
        END (* WHILE *);

    strspace[i] := eos;   (* terminate string *)

    IF (i >= maxstrsp) THEN
        writeln('*****STRING SPACE EXHAUSTED')
    ELSE IF is_int(freestr, int) THEN
         mkint(int, 1)
    ELSE (* look the name up, return itemref for it *)
        BEGIN
        putnm(freestr, r[1], found);
        IF NOT found THEN
            freestr := i + 1;
        END
    END       (* compress *);

PROCEDURE explode;      (* returns list of chars from id or int *)
      
      FUNCTION id_explode(i: stringp): itemref;
          BEGIN (* id_explode *)
          IF strspace[i] = eos THEN id_explode := nilref
          ELSE 
              BEGIN
              r[2] := id_explode(i + 1);
              mkident(ord(strspace[i]) + choffset, 1);
              xcons;
              id_explode := r[1]
              END
          END   (* id_explode *);

     FUNCTION int_explode(i: integer): itemref;
          VAR negative: boolean;

          BEGIN (* int_explode *)
          r[1] := nilref;
          IF i < 0 THEN
              BEGIN negative := true;
              i := -i
              END
          ELSE negative := false;

          WHILE i > 0 DO
              BEGIN
              r[2] := r[1];
              mkident(i MOD 10 + ord('0') + choffset, 1);
              xcons;
              i := i DIV 10
              END;

          IF negative THEN
              BEGIN 
              r[2] := r[1];
              mkident(ord('-') + choffset, 1);
              xcons
              END;
          int_explode := r[1]
          END (* int_explode *);

      BEGIN     (* explode *)
      IF tag_of(r[1]) = IDTAG THEN 
          r[1] := id_explode(idspace[info_of(r[1])].idname)
      ELSE IF tag_of(r[1]) = INTTAG THEN 
          r[1] := int_explode(info_of(r[1]))
      ELSE IF tag_of(r[1]) = FIXTAG THEN
          r[1] := int_explode(intspace[info_of(r[1])])
      ELSE 
          writeln('***** EXPLODE: ARG BAD TYPE')
      END       (* explode *);

PROCEDURE gensym;
    VAR i: integer;

    PROCEDURE kick(i: integer);     (* increments gsym digit *)
        BEGIN (* Kick *)
        IF (g_sym[i] = '9') THEN 
            BEGIN
            g_sym[i] := '0';
            IF (i < max_gsym) THEN kick(i + 1)  (* otherwise wrap around *)
            END
        ELSE g_sym[i] := succ(g_sym[i])
        
        END (* Kick *);

    BEGIN (* gensym *)
    r[1] := nilref;

    FOR i := 1 TO max_gsym DO
        BEGIN
        r[2] := r[1];
        mkident(ord(g_sym[i]) + choffset, 1);
        xcons
        END;
    r[2] := r[1];
    mkident(ord('G') + choffset, 1);
    xcons;
    compress;

    Kick(1);
    END; (* gensym *)


    (********************************************************)
    (*                                                      *)
    (*                    i/o primitives                    *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xopen;   (* Simple OPEN, but see NPAS0 *)

var s1: FileName;
    i,j : integer;
#p (* catch some I/O errors *)
#p  handler ResetError(name: PathName);
#p  begin
#p    writeln('**** Could not open file -  ',name,' for read');
#p    exit(xopen);
#p  end;

#p  handler RewriteError(name: PathName);
#p  begin
#p    writeln('**** Could not open file -  ',name,' for write');
#p    exit(xopen);
#p  end;
  
begin
      IF tag_of(r[1]) = IDTAG THEN 
      begin
        i := idspace[info_of(r[1])].idname;
#p      s1[0] := chr(255);  (* set length *)
#d      s1:='         ';
        j:= 0;
        WHILE (i <= maxstrsp) AND (strspace[i] <> eos) 
#d             AND (j <9 )
          do
        begin
          j:= j + 1;
          s1[j] := strspace[i];
          i:= i + 1;
        end;
#p      s1[0]:= chr(j);  (* set Actual Length *)
       
        IF tag_of(r[2]) = IDTAG THEN 
          BEGIN
           If info_of(r[2])= Xinput then
             begin 
#p              reset(finput,s1); 
#d              reset(finput,s1,0,0,'DSK   '); 
           mkint(3,1) end
           else if info_of(r[2])= Xoutput then
             begin 
#p           rewrite(foutput,s1); 
#d           rewrite(foutput,s1,0,0,'DSK   '); 
                 mkint(2,1) end
           else
             begin writeln('**** OPEN: ARG2 NOT INPUT/OUTPUT');
                   mkerr(notid,r[1])
             end
         end  else writeln('**** OPEN: ARG2 BAD TYPE')
     end else writeln('**** OPEN: ARG1 BAD TYPE');
end;

procedure xclose;

begin
  case info_of(r[1]) of
  1: ;
#d  2: break(output);
#a  3: close(finput);
#d  3: ;
#ap 4: close(foutput);
#d  4: break(foutput);
  end;
end;

PROCEDURE xrds;
  (* Select channel for input *)        
  VAR tmp: longint;
    BEGIN
        tmp:=inchnl;
        inchnl := info_of(r[1]);
        mkint(tmp,1)
    END;

PROCEDURE Xwrs;
  (* Select channel for output *)
  VAR tmp:longint;
    BEGIN
        tmp:=outchnl;
        outchnl := info_of(r[1]);
        mkint(tmp,1)
    END;

PROCEDURE xterpri;
(* need to change for multiple output channels.  *)
    BEGIN
    CASE outchnl OF
#p 1: writeln(' ');
#d 1: begin writeln(output); break(output); end;
#dp 2: begin writeln(foutput,' '); break(foutput); end;
#awtv 1: writeln(output);
#wtv 2: writeln(foutput);
    END (* CASE *)
    END;

#adv FUNCTION Int_field(I:integer):Integer;
#adv  Begin
#adv  Int_field:=2+trunc(log(abs(I)));
#adv  END;

PROCEDURE XwriteInt(I:integer);
    BEGIN
#adptw CASE outchnl OF
#p      1: write('  ', I:0);
#dv     1: If I=0 then Write('0') else write(I:Int_field(I) );
#atw    1: write(i);
#p      2: write(foutput,'  ', I:0);
#dv     2: If I=0 then Write(foutput,'0') else write(foutput,I:Int_field(I) );
#atw    2: write(foutput, i);
#adptw   END     (* CASE *)
    END  (* XwriteInt *);

PROCEDURE Xwritereal(R:real);
    BEGIN
#adtpw CASE outchnl OF
#p     1: write(' real Bug ', trunc(R));
#adtvw 1:  write(output,R);
#p     2: write(foutput,' real Bug ', trunc(R));
#dtvw 2:  write(foutput,R);
#adtpw END        (* CASE *)
    END;

PROCEDURE XwriteChar(C:onechar);
    BEGIN
#adptw CASE outchnl OF
#p         1: write('  ', C);
#adtvw     1: write(C);
#p         2: write(foutput,'  ', C);
#adtvw     2: write(foutput,C);
#adptw     END        (* CASE *)
    END;

PROCEDURE xwrtok;
    (* doesn't expand escaped characters in identifier names *)
  VAR  i: integer;
  BEGIN
   IF tag_of(r[1]) = inttag THEN  XwriteInt(info_of(R[1]))
    ELSE IF tag_of(r[1]) = fixtag THEN XwriteInt(intspace[info_of(R[1])])
    ELSE IF tag_of(r[1]) = flotag THEN XwriteReal(flospace[info_of(r[1])])
    ELSE IF tag_of(r[1]) = idtag THEN
         BEGIN
           i := idspace[info_of(r[1])].idname;
           WHILE (i <= maxstrsp) AND (strspace[i] <> eos) DO
                    BEGIN
                    XwriteChar(strspace[i]);
                    i:= i + 1;
                    END;
                END
    ELSE IF tag_of(r[1]) = chartag THEN
           XwriteChar(chr(info_of(r[1]) - choffset))
    ELSE IF tag_of(r[1]) = errtag THEN
      Begin XwriteChar(' ');
         XwriteChar('*'); XwriteChar('*'); XwriteChar('*');
         XwriteChar(' '); XwriteChar('#'); XwriteChar(' ');
            XwriteInt(info_of(r[1]));   Xterpri;
      End
    ELSE IF tag_of(r[1]) = codetag THEN
         Begin XwriteChar(' '); XwriteChar('#'); XwriteChar('#');
               XwriteInt(info_of(r[1]));
         End
    ELSE
         Begin
         XwriteChar(' '); XwriteChar('?'); XwriteChar(' ');
            XwriteInt(tag_of(r[1]));
         XwriteChar(' '); XwriteChar('/'); XwriteChar(' ');
            XwriteInt(info_of(r[1]));
         XwriteChar(' '); XwriteChar('?'); XwriteChar(' ');
         End;
#d   break(output);  
    END;

PROCEDURE rdchnl(chnlnum: integer; VAR ch: onechar);
    BEGIN
    IF (chnlnum < 1) OR (chnlnum > inchns) THEN
     writeln('*****BAD INPUT CHANNEL FOR RDCHNL',chnlnum)
    ELSE
        CASE chnlnum OF
            1:  BEGIN
#adptvw      ch := symin^;  (* a little strange, but avoids  *)
#adptvw      get(symin);              (* initialization problems *)
#adptvw      ichrbuf[inchnl] := symin^; (* Peek ahead *)
            END;

            2:  BEGIN
#tw             IF charcnt > Length(line) THEN
#tw                 BEGIN
#tw                 charcnt := 1;
#tw                 Readln(line)
#tw                 END;
#tw             ch := line[charcnt];
#tw             IF Length(line) > charcnt THEN
#tw                 ichrbuf[inchnl] := line[charcnt + 1]
#tw             ELSE ichrbuf[inchnl] := sp;
#tw             charcnt := charcnt + 1
#adpv        ch := input^;
#adpv        get(input);
#adpv        ichrbuf[inchnl] := input^;
            END;
#dp      3:  begin
#dp          ch := finput^;
#dp          get(finput);
#dp          ichrbuf[inchnl] := finput^;
#dp         END;
            END;
    (* case *)
    END;
    (* rdchnl *)

FUNCTION eofchnl: boolean;
    BEGIN
#adptvw  CASE inchnl OF
#adptvw      1:  eofchnl := eof(symin);
#adptvw      2:  eofchnl := eof(input);
#adptvw      3:  eofchnl := eof(finput);
#adptvw      END;
    END;

 FUNCTION eol: boolean;
    BEGIN
    CASE inchnl OF
        1:  eol := eoln(symin);
        2:  eol := eoln(input);
        3:  eol := eoln(finput);
        END;
    END;

    (********************************************************)
    (*                                                      *)
    (*                   token scanner                      *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xrdtok;
LABEL 1;

    VAR
        ch,ch1,ChangedCh: onechar;
        i: integer;
        anint: longint;
        moreid: boolean;
        found: boolean;
        negflag: integer;

    FUNCTION digit(ch: onechar): boolean;
        BEGIN
        digit := ( '0' <= ch ) AND ( ch <= '9');
        END;


    FUNCTION escalpha(VAR ch: onechar): boolean;
        (* test for alphabetic or escaped character.                 *)
        (* note side effect in ChangedCh.                                *)
        BEGIN
        ChangedCh := Ch;
        IF ( 'A' <= ch ) AND ( ch <= 'Z') THEN
            escalpha := true
        ELSE IF ( ord('A')+32 <= ord(ch)) AND ( ord(ch) <= ord('Z')+32) THEN
               BEGIN
                 IF NOT xNull(idspace[xraise].val) THEN
                     Changedch := chr(ord(ch)-32);
                 escalpha := true;    (* lower case alphabetics *)
               END
             ELSE IF ch='!' THEN
                      BEGIN
                      rdchnl(inchnl,ch);
                      ChangedCh:=Ch;
                      escalpha := true;
                      END
                  ELSE
                      escalpha := false;
        END;

    FUNCTION alphanum(VAR ch: onechar): boolean;
        (* test if escalfa or digit *)
        VAR b: boolean;
        BEGIN
        ChangedCh:=Ch;
        b := digit(ch);
        IF NOT b THEN b := escalpha(ch);
        alphanum := b;
        END;

    FUNCTION whitesp(ch: onechar): boolean;
#d     BEGIN
#d      (* may want a faster test *)
#d      whitesp := (ch = sp) OR (ch = cr) OR (ch = lf) OR (ch = ht)
#d      OR (ch = nul);       (* null?? *)
#aptvw    VAR ascode:integer;
#aptvw    BEGIN
#aptvw        ascode:=ord(ch);
#aptvw        WHITESP := (CH = SP) OR (ascode = CR) OR (ascode = LF)
#aptvw    OR (ascode = ht) or (ascode = nul);        (* null?? *)
    END; 

        (* reads fixnums...need to read flonums too *)
    BEGIN       (* xrdtok *)
1:
    IF NOT eofchnl THEN
        REPEAT                          (* skip leading white space. *)
            rdchnl(inchnl,ch)
        UNTIL (NOT whitesp(ch)) OR eofchnl;
    IF eofchnl THEN
        mkitem(chartag, eofcode + choffset, r[1])
        (* should really return !$eof!$  *)
    ELSE
        BEGIN
        IF digit(ch) or (ch = '-') THEN
            set_tag(r[1], inttag)
        ELSE IF escalpha(ch) THEN
                 set_tag(r[1], idtag)
             ELSE
                 set_tag(r[1], chartag);

        CASE tag_of(r[1]) OF
            chartag:  BEGIN
                  if ch = begin_comment then
                      BEGIN
                      While not eol do rdchnl(inchnl,ch);
                      rdchnl(inchnl, ch);
                      GOTO 1
                      END;
                  set_tag(r[1], idtag);
                  mkitem(inttag, chartype, tmpref);
                  idspace[xtoktype].val := tmpref;
                  set_info(r[1], ord(ch) + choffset);
                  END;
            inttag:   BEGIN
                 mkitem(inttag, inttype, tmpref;
                idspace[xtoktype].val :=tmpref;
                 negflag := 1;
                 if ch = '-' then
            begin anint := 0; negflag :=-1 end
                     else anint := ord(ch) - ord('0');
                 WHILE digit(ichrbuf[inchnl]) DO
                     BEGIN
                     rdchnl(inchnl,ch);
                     anint := 10 * anint + (ord(ch) - ord('0'))
                     END;
                 anint := negflag * anint;
                 set_info(r[1], anint)
                 END;
            idtag:    BEGIN
                mkitem(inttag, idtype, tmpref);
                idspace[xtoktype].val:=tmpref;
                i := freestr; (* point to possible new string *)
                moreid := true;
                WHILE (i < maxstrsp) AND moreid DO
                    BEGIN
                    strspace[i] := ChangedCh; (* May have Case Change, etc *)
                    i:= i + 1;
                    moreid :=alphanum(ichrbuf[inchnl]);  (* PEEK ahead char *)
                    IF moreid THEN rdchnl(inchnl,ch) (* Advance readch *)
                    END;
                strspace[i] := eos;   (* terminate string *)
                IF (i >= maxstrsp) THEN
                   writeln('*****STRING SPACE EXHAUSTED')
                ELSE  (* look the name up, return itemref for it *)
                    BEGIN
                    putnm(freestr, r[1], found);
                    IF NOT found THEN
                        freestr := i + 1;
                    END;
                END;
                (* of case idtag *)
            END;
        (* of case *)
        END;
    END;
    (* xrdtok *)
    (* for DEBUG *)
    (********************************************************)
    (*                                                      *)
    (*                    initialization                    *)
    (*                                                      *)
    (********************************************************)


PROCEDURE init;
    (* initialization procedure depends on  *)
    (* ability to load stack with constants *)
    (* from a file.                         *)
    VAR
        strptr: stringp;
#dptvw  nam: PACKED ARRAY[1..3] OF onechar;
#a      nam: PACKED ARRAY[1..4] OF onechar; (* SPL bug for Apollo *)
        (* holds 'nil', other strings? *)
        i, n: integer;
        idref: itemref;
        found: boolean;

#aptv   (* init is divided into two parts so it can compile on terak *)
    PROCEDURE init1;
        BEGIN
#tw      CHARCNT := 1;
#tw      LINE := '';

        (* initialize top of stack *)
        st := 0;

        freefloat := 1;
        (* initialize fixnum free list *)
        FOR freeint := 1 TO maxintsp - 1 DO 
            intspace[freeint] := freeint + 1;
        intspace[maxintsp] := end_flag;
        freeint := 1;

        (* define nilref - the id, nil, is defined a little later. *)
        freeident := 1;
        mkitem(idtag, freeident, nilref);

        (* initialize pair space. *)
        FOR i := 1 TO maxpair - 1 DO      (* initialize free list. *)
            BEGIN
          (* OLD: prspace[i].MarkFlag := false; *)
            prspace[i].prcar := nilref;         (* just for fun *)
            mkitem(pairtag, i + 1, prspace[i].prcdr);
            END;
        prspace[maxpair].prcar := nilref;
        prspace[maxpair].prcdr := nilref;       (* end flag *)
        freepair := 1;                  (* point to first free pair *)


        (* initialize identifier space and string space. *)
        freestr := 1;
        FOR i := 0 TO hidmax - 1 DO
            idhead[i] := nillnk;
        FOR i := 1 TO maxident DO
            BEGIN
            IF i < maxident THEN
                idspace[i].idhlink := i + 1
            ELSE    (* nil to mark the final identifier in the table. *)
                idspace[i].idhlink := nillnk;
            (* set function cells to undefined *)
            mkerr( undefined, tmpref);
            idspace[i].funcell :=tmpref;
            idspace[i].val :=tmpref;
            idspace[i].plist :=tmpref;
            END;

        (* nil must be the first identifier in the table--id #1 *)
        (* must fill in fields by hand for nilref.*)
        (* putnm can handle any later additions.  *)
        nam := 'NIL';
        strptr := freestr;
        FOR i := 1 TO 3 DO
            BEGIN
            strspace[strptr] := nam[i];
            strptr:= strptr + 1;
            END;
        strspace[strptr] := eos;
        putnm(freestr, nilref, found);
        IF NOT found THEN
            freestr := strptr + 1;

        (* make the single character ascii identifiers, except nul(=eos). *)
        FOR i := 1 TO 127  DO
            BEGIN
            strspace[freestr] := chr(i);
            strspace[freestr + 1] := eos;
            putnm(freestr, idref, found);
            IF NOT found THEN
                freestr := freestr + 2;
            IF i = ord('T') THEN
                trueref := idref;
            (* returns location for 't. *)
            END;

        (* init gensym id list *)
        FOR i := 1 TO max_gsym DO g_sym[i] := '0';

        (* clear the counters *)
        idspace[xraise].val := trueref;
        gccount := 0;
        consknt := 0;
        END;
        (* init1 *)

    PROCEDURE init2;
        BEGIN
        (* load "symbol table" with identifiers, constants, and functions.  *)
        inchnl := 1;        (* select symbol input file. *)
        outchnl := 1;        (* select symbol OUTPUT file. *)
#p      reset(symin,'paslsp.ini');
#p      reset(input);
#p      rewrite(output);
#w      reset(symin, "paslsp.ini");
#t      reset(symin,'#5:poly.data');
#d      reset(symin,'paslspini',0,0,'DSK   ');
#d      reset(input,'tty      ',0,0,'TTY   ');
#d      rewrite(output,'tty      ',0,0,'TTY   ');
#a      open(symin,'paslsp.ini','old',iostatus);
#a      reset(symin);
#a      for i:=1 to inchns do
#a       BEGIN;
#a         ichrbuf[i]:=' ';
#a       END;
        xrdtok;     (* get count of identifiers. *)
        IF tag_of(r[1]) <> inttag THEN
           writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED AT START');
        n := info_of(r[1]);
        FOR i := 1 TO n DO
            xrdtok;
        (* reading token magically loads it into id space. *)
        xrdtok;         (* look for zero terminator. *)
        IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
          writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER IDENTIFIERS');

        xrdtok;         (* count of constants  *)
        IF tag_of(r[1]) <> inttag THEN
           writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED BEFORE CONSTANTS');
        n := info_of(r[1]);
        alloc(n);       (* space for constants on the stack *)
        FOR i := 1 TO n DO
            BEGIN
            xread;
            stk[i] := r[1];
            END;
        xrdtok;
        IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
         writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER CONSTANTS');
        xrdtok;     (* count of functions. *)
        IF tag_of(r[1]) <> inttag THEN
           writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED BEFORE FUNCTIONS');
        n := info_of(r[1]);
        FOR i := 1 TO n DO
            (* for each function *)
            (* store associated code *)
            BEGIN
            xrdtok;
            mkitem(codetag, i, tmpref);
            idspace[info_of(r[1])].funcell :=tmpref;
            END;
        xrdtok;
        IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
         writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER FUNCTIONS');
        END;
        (* init2 *)

PROCEDURE dumpids;
    VAR i, p: integer;

    BEGIN
    FOR i := 1 TO freeident - 1 DO
        BEGIN
        p := idspace[i].idname;
        write('id #', i:5, ' at', p:5, ': ');
        WHILE strspace[p] <> eos DO
            BEGIN 
            write(strspace[p]);
            p := p + 1
            END;
        write('.  Function code: ');
        writeln(INFO_OF(idspace[i].funcell)); 
        END
    END;

    BEGIN       (* init *)
    init1;
    init2;
    END;
    (* init *)

    (********************************************************)
    (*                                                      *)
    (*                 arithmetic functions                 *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xadd1;
    VAR i: longint;

    BEGIN
    int_val(r[1], i);
    mkint(i + 1, 1)
    END;

PROCEDURE xdifference;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 - i2, 1)
    END;

PROCEDURE xdivide;      (* returns dotted pair (quotient . remainder). *)
    VAR quot, rem: integer;
        i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);

    mkint(i1 DIV i2, 1);
    mkint(i1 MOD i2, 2);
    xcons
    END;

PROCEDURE xgreaterp;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);

    IF i1 > i2 THEN
        r[1] := trueref
    ELSE
        r[1] := nilref;
    END;

PROCEDURE xlessp;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);

    IF i1 < i2 THEN
        r[1] := trueref
    ELSE
        r[1] := nilref;
    END;

PROCEDURE xminus;
    VAR i: longint;

    BEGIN
    int_val(r[1], i);
    mkint(-i, 1)
    END;

PROCEDURE xplus2;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 + i2, 1)
    END;

PROCEDURE xquotient;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 DIV i2, 1)
    END;

PROCEDURE xremainder;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 MOD i2, 1)
    END;

PROCEDURE xtimes2;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 * i2, 1)
    END;
    (* xtimes2 *)


    (********************************************************)
    (*                                                      *)
    (*                    support for eval                  *)
    (*                                                      *)
    (********************************************************)


PROCEDURE execute(code: integer);
    FORWARD;

    (* Xapply(fn,arglist)-- "fn" is an operation code. *)
PROCEDURE xxapply;
    VAR
        i: integer;
        code: integer;
        tmp: itemref;
        tmpreg: ARRAY[1..maxreg] OF itemref;
    BEGIN
    code := info_of(r[1]);
    r[1] := r[2];
    i := 1;
    (* spread the arguments  *)
    WHILE NOT xNull(r[1]) AND (i <= maxreg) DO
        BEGIN
        tmp := r[1];
        xcar;
        tmpreg[i] := r[1];
        i := i + 1;
        r[1] := tmp;
        xcdr;
        END;
    WHILE i > 1 DO
        BEGIN
        i := i - 1;
        r[i] := tmpreg[i];
        END;
    execute(code);
    END;

    (*  rest of pas1...pasn follow , pasn Closes definition of Catch *)

Added perq-pascal-lisp-project/pas0.sym version [efa6eea900].















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
PAS0IDS := '((TOKTYPE . 129)
             (BSTK!* . 130)
             (THROWING!* . 131)
             (INITFORM!* . 132)
             (!*RAISE    . 133)
	     (INPUT      . 134)
             (OUTPUT     . 135)
             (!*ECHO     . 137)
            )$
PAS0CSTS := '()$
PAS0LITS := '()$

% Functions that initial system is expected to know about.
% (Arranged in alphabetical order.)
PAS0FNS:='(
(!*FIRST!-PROCEDURE . FIRSTP)
	(ADD1 . XADD1)
	(XAPPLY . XXAPPLY)
	(CAR . XCAR)
        (CATCH . XCATCH)
	(CDR . XCDR)
	(CODEP . XCODEP)
	(COMPRESS . COMPRESS)
	(CONS . XCONS)
        (CLOSE . XCLOSE)
	(DIFFERENCE . XDIFFERENCE)
	(DIVIDE . XDIVIDE)
        (EVAL . XEVAL)
	(EXPLODE . EXPLODE)
	(FASTSTAT . XFASTSTAT)
	(GENSYM . GENSYM)
	(GREATERP . XGREATERP)
	(LESSP . XLESSP)
	(MINUS . XMINUS)
	(NCONS . XNCONS)
        (OPEN . XOPEN)
	(PLUS2 . XPLUS2)
        (PRINT . XPRINT)
	(QUOTIENT . XQUOTIENT)
	(RDTOK . XRDTOK)
        (RDS   . XRDS)
	(READ . XREAD)
	(RECLAIM . XGCOLLECT)
	(REMAINDER . XREMAINDER)
	(RPLACA . XRPLACA)
	(RPLACD . XRPLACD)
	(TERPRI . XTERPRI)
	(TIMES2 . XTIMES2)
        (THROW  . XTHROW)
        (UNBINDTO . XUNBINDTO)
	(WRTOK . XWRTOK)
        (WRS .   XWRS)
	(XCONS . XXCONS)
	)
$

Added perq-pascal-lisp-project/pas1.bld version [d97bc1bd46].



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
DEF s: <SCRATCH>
DEF DSK: DSK:,SYS:
DEF SYS: DSK:,SYS:
pas:PASCMP
OFF SYSLISP$
OFF MSG$
OFF NOUUO$
ON DOMOVE$
ON NOFIXFRM;
ON MACECHO$		%OFF cuts down size of output file.
PUT('CAR,'ANYREG,'T)$
PUT('CDR,'ANYREG,'T)$

IN PAS0.SYM$		% Pre Symbol Table
OUT PAS1.PAS$
DRT1('PAS1,PAS0IDS,PAS0CSTS,PAS0LITS,PAS0FNS)$
IN PAS1.RED$
DRT2()$
SHUT PAS1.PAS$

OUT PAS1.SYM$		% Post SYMBOL Table
DUMPSYMS('PAS1)$
SHUT PAS1.SYM$

OUT PAS1.SLI$	 % Sexpressions and declarations
DRT3()$
SHUT PAS1.SLI$
QUIT$

Added perq-pascal-lisp-project/pas1.pas version [fd17de7681].

cannot compute difference between binary files

Added perq-pascal-lisp-project/pas1.red version [6adb70eef6].















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                     
% 		PASCAL BASED MINI-LISP
%
% File: 	PAS1.RED - Basic I/O Functions
% ChangeDate: 	10:48pm  Wednesday, 15 July 1981
% By: 		M. L. Griss
%       	Change to add Features for Schlumberger Demo
% 
% 	    All RIGHTS RESERVED
%           COPYRIGHT (C) - 1981 - M. L. GRISS
%           Computer Science Department
%           University of Utah
%
%           Do Not distribute with out written consent of M. L. Griss
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Additional Support procedures for optimized code;

SYMBOLIC PROCEDURE CAAR(X);
 CAR CAR X;

SYMBOLIC PROCEDURE CADR X;
 CAR CDR X;

SYMBOLIC PROCEDURE CDAR X;
 CDR CAR X;

SYMBOLIC PROCEDURE CDDR X;
 CDR CDR X;

% All Friendly CxxxR's

SYMBOLIC PROCEDURE CAAAAR X; CAR CAR CAR CAR X;

SYMBOLIC PROCEDURE CAAADR X; CAR CAR CAR CDR X;

SYMBOLIC PROCEDURE CAADAR X; CAR CAR CDR CAR X;

SYMBOLIC PROCEDURE CAADDR X; CAR CAR CDR CDR X;

SYMBOLIC PROCEDURE CADAAR X; CAR CDR CAR CAR X;

SYMBOLIC PROCEDURE CADADR X; CAR CDR CAR CDR X;

SYMBOLIC PROCEDURE CADDAR X; CAR CDR CDR CAR X;

SYMBOLIC PROCEDURE CADDDR X; CAR CDR CDR CDR X;

SYMBOLIC PROCEDURE CDAAAR X; CDR CAR CAR CAR X;

SYMBOLIC PROCEDURE CDAADR X; CDR CAR CAR CDR X;

SYMBOLIC PROCEDURE CDADAR X; CDR CAR CDR CAR X;

SYMBOLIC PROCEDURE CDADDR X; CDR CAR CDR CDR X;

SYMBOLIC PROCEDURE CDDAAR X; CDR CDR CAR CAR X;

SYMBOLIC PROCEDURE CDDADR X; CDR CDR CAR CDR X;

SYMBOLIC PROCEDURE CDDDAR X; CDR CDR CDR CAR X;

SYMBOLIC PROCEDURE CDDDDR X; CDR CDR CDR CDR X;

SYMBOLIC PROCEDURE CAAAR X; CAR CAR CAR X;

SYMBOLIC PROCEDURE CAADR X; CAR CAR CDR X;

SYMBOLIC PROCEDURE CADAR X; CAR CDR CAR X;

SYMBOLIC PROCEDURE CADDR X; CAR CDR CDR X;

SYMBOLIC PROCEDURE CDAAR X; CDR CAR CAR X;

SYMBOLIC PROCEDURE CDADR X; CDR CAR CDR X;

SYMBOLIC PROCEDURE CDDAR X; CDR CDR CAR X;

SYMBOLIC PROCEDURE CDDDR X; CDR CDR CDR X;

symbolic procedure prin2(x);
    begin
        if pairp(x) then
        <<  wrtok( '!( );
            while pairp(x) do
            <<  prin2 car(x);
                x := cdr x;
		if not eq(x,NIL) then wrtok('! ); % A space.
            >>;
            if not eq(x,NIL) then
            <<  wrtok( '!.!  ); %Period followed by space.
                prin2(x);
            >>;
            wrtok( '!) );
        >>
        else
            wrtok(x);
    end;

symbolic procedure revx(l1,l2);
   % Non-destructive reverser, adds reverse of l1 to front of l2.
    begin
        while pairp(l1) do
        <<  l2 := (car l1).l2;
            l1 := cdr l1;
        >>;
        if not null (l1) then l2 := l1 . l2;
        return l2;
    end;

symbolic procedure rev(l1);
     revx(l1,NIL);

% EOF code is Ascii Z plus an offset of 1,  much too obscure!.
symbolic procedure eofp(x);
     if atom(x) and (!*inf(x) eq 27) then 'T else 'NIL;

symbolic procedure read();
    begin scalar itm,ii;
        itm := rdtok(); 
	if not(toktype eq 3) or eofp(itm)  then return(itm); % Over cautious;
        if (itm eq '!( ) 
            then return rlist()
        else if (itm eq '!' )         % Treat quote mark as QUOTE.
	    then return <<ii := read();
			  if eofp(ii) then ii
			   else ('QUOTE . ii . NIL)>>
        else return itm;
    end;

symbolic procedure rlist();
% Non destructive READ of S-expr, including ".".
    begin scalar itm,lst,done,last;
        itm := read();
        if eofp(itm) then return itm;
	done := NIL;
        while not done do
	    if itm eq '!) and toktype eq 3 
                  then done :='T
              else if itm = '!. and toktype eq 3 
	          then <<done:='T; last:= car rlist()>>  %CAR cures bug? WFG
              else
	          <<lst := itm.lst; itm := read()>>;
% ???   if pairp last then last:=car last>>;
     	if eofp(itm) then return itm;
        return revx(lst,last);
    end;

END$

Added perq-pascal-lisp-project/pas1.sli version [5b899bf610].



>
1
% Initialization LISP for module: PAS1

Added perq-pascal-lisp-project/pas1.sym version [9d9c249db1].

cannot compute difference between binary files

Added perq-pascal-lisp-project/pas2.bld version [06d1a89250].























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
DEF s: <SCRATCH>
DEF DSK: DSK:,SYS:
DEF SYS: DSK:,SYS:
pas:PASCMP
OFF SYSLISP$
OFF MSG$
OFF NOUUO$
OFF DOMOVE$             % Can't have BOTH DOMOVE and FXFRM
OFF NOFIXFRM;		% Reduce ALLOCS
ON MACECHO$		%OFF Cuts down size of output file.
REMPROP('W,'STAT);
REMPROP('PLIST,'STAT);

IN PAS1.SYM$
% Perhaps the following lines should really be in POLY.RED, but they
% don't work correctly inside body of text being compiled.
PUT('CAR,'ANYREG,'T)$
PUT('CDR,'ANYREG,'T)$
PUT('VALUE,'OPENCOD,'("        R[1] := idspace[info_of(R[1])].val;"));
PUT('PLIST,'OPENCOD,'("        R[1] := idspace[Info_of(r[1])].plist;"));
PUT('FUNCELL,'OPENCOD,'("        R[1] := idspace[Info_of(r[1])].funcell;"));
PUT('SETVALUE,'OPENCOD,'("       idspace[Info_of(r[1])].val := R[2];"));
PUT('SETPLIST,'OPENCOD,'("        idspace[Info_of(r[1])].plist := R[2];"));
PUT('SETFUNCELL,'OPENCOD,'("        idspace[Info_of(r[1])].funcell := R[2];"));
PUT('CHAR2ID,'OPENCOD,'("     set_tag(R[1], idtag);"));
PUT('CODEP, 'OPENCOD, '("     tag_of(r[1]) = codetag;"));

OUT PAS2.PAS$
DRT1('PAS2,PAS1IDS,PAS1CSTS,PAS1LITS,PAS1FNS)$
IN PAS2.RED$

DRT2()$
SHUT PAS2.PAS$

OUT PAS2.SYM$
DUMPSYMS('PAS2)$
SHUT PAS2.SYM$

OUT PAS2.SLI$
DRT3()$			% S-expressions and Declarations
SHUT PAS2.SLI$

QUIT$

Added perq-pascal-lisp-project/pas2.pas version [9d209a1c1c].









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
(* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  PASCAL Based MINI-LISP/ compilation: V1
   Special Schlumberger Demo 
   All RIGHTS RESERVED
   COPYRIGHT (C) - 1981 - M. L. GRISS
      Computer Science Department
           University of Utah
 
 Do Not distribute with out written consent of M. L. Griss
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *)
(* !(!*ENTRY PAIRP EXPR !1!) *)
(*  EXPR PAIRP *)
procedure PAS21;
label
      101,
      100;
begin
(* !(!*ALLOC !0!) *)
(* !(!*JUMPNC G!0!0!0!5 !1 PAIRTAG!) *)
      IF tag_of(R[1]) <> PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE T!)!) *)
      R[1] := trueref;
(* !(!*JUMP G!0!0!0!6!) *)
      GOTO 101;
(* !(!*LBL G!0!0!0!5!) *)
100: 
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*LBL G!0!0!0!6!) *)
101: 
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
procedure PAS22;
forward;
(* !(!*ENTRY NOT EXPR !1!) *)
(*  EXPR NOT *)
procedure PAS23;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LOAD !2 !(QUOTE NIL!)!) *)
      R[2] := nilref;
(* !(!*LINK EQ EXPR !2!) *)
     PAS22;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY CODEP EXPR !1!) *)
(*  EXPR CODEP *)
procedure XCODEP;
label
      101,
      100;
begin
(* !(!*ALLOC !0!) *)
(* !(!*JUMPNC G!0!0!1!0 !1 CODETAG!) *)
      IF tag_of(R[1]) <> CODETAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE T!)!) *)
      R[1] := trueref;
(* !(!*JUMP G!0!0!1!1!) *)
      GOTO 101;
(* !(!*LBL G!0!0!1!0!) *)
100: 
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*LBL G!0!0!1!1!) *)
101: 
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
procedure PAS24;
forward;
procedure PAS25;
forward;
(* !(!*ENTRY CONSTANTP EXPR !1!) *)
(*  EXPR CONSTANTP *)
procedure PAS26;
label
      100;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LINK PAIRP EXPR !1!) *)
     PAS21;
(* !(!*JUMPT G!0!0!1!3!) *)
      IF R[1] <> nilref THEN GOTO 100;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK IDP EXPR !1!) *)
     PAS24;
(* !(!*LBL G!0!0!1!3!) *)
100: 
(* !(!*LINK NULL EXPR !1!) *)
     PAS25;
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY EQN EXPR !2!) *)
(*  EXPR EQN *)
procedure PAS27;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LINK EQ EXPR !2!) *)
     PAS22;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY LIST!2 EXPR !2!) *)
(*  EXPR LIST2 *)
procedure PAS28;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*LINK NCONS EXPR !1!) *)
     XNCONS;
(* !(!*LOAD !2 !0!) *)
      load(2,0);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY LIST!3 EXPR !3!) *)
(*  EXPR LIST3 *)
procedure PAS29;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*LOAD !2 !3!) *)
      R[2] := R[3];
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK LIST!2 EXPR !2!) *)
     PAS28;
(* !(!*LOAD !2 !0!) *)
      load(2,0);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY LIST!4 EXPR !4!) *)
(*  EXPR LIST4 *)
procedure PAS210;
begin
(* !(!*ALLOC !3!) *)
    alloc3;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*STORE !3 !-!2!) *)
      store(3,2);
(* !(!*LOAD !3 !4!) *)
      R[3] := R[4];
(* !(!*LOAD !2 !-!2!) *)
      load(2,2);
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK LIST!3 EXPR !3!) *)
     PAS29;
(* !(!*LOAD !2 !0!) *)
      load(2,0);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*DEALLOC !3!) *)
      dealloc3;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY LIST!5 EXPR !5!) *)
(*  EXPR LIST5 *)
procedure PAS211;
begin
(* !(!*ALLOC !4!) *)
    alloc(4);
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*STORE !3 !-!2!) *)
      store(3,2);
(* !(!*STORE !4 !-!3!) *)
      store(4,3);
(* !(!*LOAD !4 !5!) *)
      R[4] := R[5];
(* !(!*LOAD !3 !-!3!) *)
      load(3,3);
(* !(!*LOAD !2 !-!2!) *)
      load(2,2);
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK LIST!4 EXPR !4!) *)
     PAS210;
(* !(!*LOAD !2 !0!) *)
      load(2,0);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*DEALLOC !4!) *)
      dealloc(4);
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY REVERSE EXPR !1!) *)
(*  EXPR REVERSE *)
procedure PAS212;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LINK REV EXPR !1!) *)
     PAS131;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY APPEND EXPR !2!) *)
(*  EXPR APPEND *)
procedure PAS213;
label
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*LINK REVERSE EXPR !1!) *)
     PAS212;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LBL G!0!0!2!9!) *)
100: 
(* !(!*JUMPNC G!0!0!2!8 !1 PAIRTAG!) *)
      IF tag_of(R[1]) <> PAIRTAG THEN GOTO 101;
(* !(!*LOAD !2 !-!1!) *)
      load(2,1);
(* !(!*LOAD !1 !(CAR !1!)!) *)
   XCAR;
(* !(!*LINK CONS EXPR !2!) *)
     XCONS;
(* !(!*STORE !1 !-!1!) *)
      store(1,1);
(* !(!*LOAD !1 !(CDR !0!)!) *)
   ANYcdr(stk[st],R[1]);
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*JUMP G!0!0!2!9!) *)
      GOTO 100;
(* !(!*LBL G!0!0!2!8!) *)
101: 
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
procedure PAS214;
forward;
(* !(!*ENTRY MEMBER EXPR !2!) *)
(*  EXPR MEMBER *)
procedure PAS214;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LOAD !3 !1!) *)
      R[3] := R[1];
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*JUMPT G!0!0!3!4!) *)
      IF R[1] <> nilref THEN GOTO 100;
(* !(!*LOAD !1 !3!) *)
      R[1] := R[3];
(* !(!*JUMP G!0!0!3!6!) *)
      GOTO 102;
(* !(!*LBL G!0!0!3!4!) *)
100: 
(* !(!*LOAD !1 !3!) *)
      R[1] := R[3];
(* !(!*JUMPN G!0!0!3!5 !(CAR !2!)!) *)
   ANYcar(R[2],RXX);
      IF R[1] <> RXX THEN GOTO 101;
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*JUMP G!0!0!3!6!) *)
      GOTO 102;
(* !(!*LBL G!0!0!3!5!) *)
101: 
(* !(!*LOAD !2 !(CDR !2!)!) *)
   ANYcdr(R[2],R[2]);
(* !(!*LINK MEMBER EXPR !2!) *)
     PAS214;
(* !(!*LBL G!0!0!3!6!) *)
102: 
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
procedure PAS215;
forward;
procedure PAS216;
forward;
(* !(!*ENTRY PAIR EXPR !2!) *)
(*  EXPR PAIR *)
procedure PAS216;
label
      103,
      102,
      101,
      100;
begin
(* !(!*ALLOC !3!) *)
    alloc3;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPNIL G!0!0!3!9!) *)
      IF R[1] = nilref THEN GOTO 100;
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*JUMPT G!0!0!4!0!) *)
      IF R[1] <> nilref THEN GOTO 102;
(* !(!*LBL G!0!0!3!9!) *)
100: 
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*JUMPT G!0!0!4!4!) *)
      IF R[1] <> nilref THEN GOTO 101;
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*JUMPNIL G!0!0!4!5!) *)
      IF R[1] = nilref THEN GOTO 103;
(* !(!*LBL G!0!0!4!4!) *)
101: 
(* !(!*LOAD !2 !(QUOTE PAIR!)!) *)
      mkident(139,2);
(* !(!*LOAD !1 !(QUOTE !0!)!) *)
      mkint(0,1);
(* !(!*LINK ERROR EXPR !2!) *)
     PAS215;
(* !(!*LBL G!0!0!4!0!) *)
102: 
(* !(!*LOAD !2 !(CAR !1!)!) *)
   ANYcar(R[1],R[2]);
(* !(!*LOAD !1 !(CAR !0!)!) *)
   ANYcar(stk[st],R[1]);
(* !(!*LINK CONS EXPR !2!) *)
     XCONS;
(* !(!*STORE !1 !-!2!) *)
      store(1,2);
(* !(!*LOAD !2 !(CDR !-!1!)!) *)
   ANYcdr(stk[st-1],R[2]);
(* !(!*LOAD !1 !(CDR !0!)!) *)
   ANYcdr(stk[st],R[1]);
(* !(!*LINK PAIR EXPR !2!) *)
     PAS216;
(* !(!*LOAD !2 !-!2!) *)
      load(2,2);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*LBL G!0!0!4!5!) *)
103: 
(* !(!*DEALLOC !3!) *)
      dealloc3;
(* !(!*EXIT!) *)
end;
procedure PAS217;
forward;
procedure PAS218;
forward;
(* !(!*ENTRY SASSOC EXPR !3!) *)
(*  EXPR SASSOC *)
procedure PAS218;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !3!) *)
    alloc3;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*STORE !3 !-!2!) *)
      store(3,2);
(* !(!*JUMPC G!0!0!4!8 !2 PAIRTAG!) *)
      IF tag_of(R[2]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !2 !(QUOTE !(NIL!)!)!) *)
      R[2] := stk[1];
(* !(!*LOAD !1 !3!) *)
      R[1] := R[3];
(* !(!*LINK APPLY EXPR !2!) *)
     PAS217;
(* !(!*JUMP G!0!0!5!0!) *)
      GOTO 102;
(* !(!*LBL G!0!0!4!8!) *)
100: 
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*LINK CAAR EXPR !1!) *)
     PAS11;
(* !(!*JUMPN G!0!0!4!9 !0!) *)
      IF R[1] <> stk[st] THEN GOTO 101;
(* !(!*LOAD !1 !(CAR !-!1!)!) *)
   ANYcar(stk[st-1],R[1]);
(* !(!*JUMP G!0!0!5!0!) *)
      GOTO 102;
(* !(!*LBL G!0!0!4!9!) *)
101: 
(* !(!*LOAD !3 !-!2!) *)
      load(3,2);
(* !(!*LOAD !2 !(CDR !-!1!)!) *)
   ANYcdr(stk[st-1],R[2]);
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK SASSOC EXPR !3!) *)
     PAS218;
(* !(!*LBL G!0!0!5!0!) *)
102: 
(* !(!*DEALLOC !3!) *)
      dealloc3;
(* !(!*EXIT!) *)
end;
procedure PAS219;
forward;
procedure PAS220;
forward;
(* !(!*ENTRY SUBLIS EXPR !2!) *)
(*  EXPR SUBLIS *)
procedure PAS220;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !3!) *)
    alloc3;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPC G!0!0!5!3 !1 PAIRTAG!) *)
      IF tag_of(R[1]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*JUMP G!0!0!5!4!) *)
      GOTO 102;
(* !(!*LBL G!0!0!5!3!) *)
100: 
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK ASSOC EXPR !2!) *)
     PAS219;
(* !(!*JUMPNIL G!0!0!5!7!) *)
      IF R[1] = nilref THEN GOTO 101;
(* !(!*LOAD !1 !(CDR !1!)!) *)
   XCDR;
(* !(!*JUMP G!0!0!5!4!) *)
      GOTO 102;
(* !(!*LBL G!0!0!5!7!) *)
101: 
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*JUMPC G!0!0!5!4 !1 ATOM!) *)
      IF tag_of(R[1]) <> PAIRTAG THEN GOTO 102;
(* !(!*LOAD !2 !(CAR !1!)!) *)
   ANYcar(R[1],R[2]);
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK SUBLIS EXPR !2!) *)
     PAS220;
(* !(!*STORE !1 !-!2!) *)
      store(1,2);
(* !(!*LOAD !2 !(CDR !-!1!)!) *)
   ANYcdr(stk[st-1],R[2]);
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK SUBLIS EXPR !2!) *)
     PAS220;
(* !(!*LOAD !2 !-!2!) *)
      load(2,2);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*LBL G!0!0!5!4!) *)
102: 
(* !(!*DEALLOC !3!) *)
      dealloc3;
(* !(!*EXIT!) *)
end;
procedure PAS221;
forward;
(* !(!*ENTRY SUBST EXPR !3!) *)
(*  EXPR SUBST *)
procedure PAS221;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !4!) *)
    alloc(4);
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*JUMPNIL G!0!0!6!8!) *)
      IF R[1] = nilref THEN GOTO 102;
(* !(!*JUMPN G!0!0!6!6 !3!) *)
      IF R[1] <> R[3] THEN GOTO 100;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*JUMP G!0!0!6!8!) *)
      GOTO 102;
(* !(!*LBL G!0!0!6!6!) *)
100: 
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*STORE !3 !-!2!) *)
      store(3,2);
(* !(!*JUMPNC G!0!0!6!7 !3 ATOM!) *)
      IF tag_of(R[3]) = PAIRTAG THEN GOTO 101;
(* !(!*LOAD !1 !3!) *)
      R[1] := R[3];
(* !(!*JUMP G!0!0!6!8!) *)
      GOTO 102;
(* !(!*LBL G!0!0!6!7!) *)
101: 
(* !(!*LOAD !3 !(CAR !3!)!) *)
   ANYcar(R[3],R[3]);
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK SUBST EXPR !3!) *)
     PAS221;
(* !(!*STORE !1 !-!3!) *)
      store(1,3);
(* !(!*LOAD !3 !(CDR !-!2!)!) *)
   ANYcdr(stk[st-2],R[3]);
(* !(!*LOAD !2 !-!1!) *)
      load(2,1);
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK SUBST EXPR !3!) *)
     PAS221;
(* !(!*LOAD !2 !-!3!) *)
      load(2,3);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*LBL G!0!0!6!8!) *)
102: 
(* !(!*DEALLOC !4!) *)
      dealloc(4);
(* !(!*EXIT!) *)
end;
procedure PAS222;
forward;
(* !(!*ENTRY MEMQ EXPR !2!) *)
(*  EXPR MEMQ *)
procedure PAS222;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !0!) *)
(* !(!*JUMPNC G!0!0!7!6 !2 PAIRTAG!) *)
      IF tag_of(R[2]) <> PAIRTAG THEN GOTO 100;
(* !(!*JUMPN G!0!0!7!4 !(CAR !2!)!) *)
   ANYcar(R[2],RXX);
      IF R[1] <> RXX THEN GOTO 101;
(* !(!*LBL G!0!0!7!6!) *)
100: 
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*JUMP G!0!0!7!5!) *)
      GOTO 102;
(* !(!*LBL G!0!0!7!4!) *)
101: 
(* !(!*LOAD !2 !(CDR !2!)!) *)
   ANYcdr(R[2],R[2]);
(* !(!*LINK MEMQ EXPR !2!) *)
     PAS222;
(* !(!*LBL G!0!0!7!5!) *)
102: 
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
procedure PAS223;
forward;
(* !(!*ENTRY ATSOC EXPR !2!) *)
(*  EXPR ATSOC *)
procedure PAS223;
label
      103,
      102,
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPC G!0!0!7!9 !2 PAIRTAG!) *)
      IF tag_of(R[2]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*JUMP G!0!0!8!2!) *)
      GOTO 103;
(* !(!*LBL G!0!0!7!9!) *)
100: 
(* !(!*LOAD !1 !(CAR !2!)!) *)
   ANYcar(R[2],R[1]);
(* !(!*JUMPNC G!0!0!8!1 !1 PAIRTAG!) *)
      IF tag_of(R[1]) <> PAIRTAG THEN GOTO 101;
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*LINK CAAR EXPR !1!) *)
     PAS11;
(* !(!*JUMPE G!0!0!8!0 !0!) *)
      IF R[1]=stk[st] THEN GOTO 102;
(* !(!*LBL G!0!0!8!1!) *)
101: 
(* !(!*LOAD !2 !(CDR !-!1!)!) *)
   ANYcdr(stk[st-1],R[2]);
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK ATSOC EXPR !2!) *)
     PAS223;
(* !(!*JUMP G!0!0!8!2!) *)
      GOTO 103;
(* !(!*LBL G!0!0!8!0!) *)
102: 
(* !(!*LOAD !1 !(CAR !-!1!)!) *)
   ANYcar(stk[st-1],R[1]);
(* !(!*LBL G!0!0!8!2!) *)
103: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY ASSOC EXPR !2!) *)
(*  EXPR ASSOC *)
procedure PAS219;
label
      103,
      102,
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPC G!0!0!8!5 !2 PAIRTAG!) *)
      IF tag_of(R[2]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*JUMP G!0!0!8!9!) *)
      GOTO 103;
(* !(!*LBL G!0!0!8!5!) *)
100: 
(* !(!*LOAD !1 !(CAR !2!)!) *)
   ANYcar(R[2],R[1]);
(* !(!*JUMPNC G!0!0!8!6 !1 ATOM!) *)
      IF tag_of(R[1]) = PAIRTAG THEN GOTO 101;
(* !(!*LOAD !2 !(QUOTE ASSOC!)!) *)
      mkident(140,2);
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK LIST!2 EXPR !2!) *)
     PAS28;
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !(QUOTE !1!0!0!)!) *)
      mkint(100,1);
(* !(!*LINK ERROR EXPR !2!) *)
     PAS215;
(* !(!*LBL G!0!0!8!6!) *)
101: 
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*LINK CAAR EXPR !1!) *)
     PAS11;
(* !(!*JUMPN G!0!0!8!8 !0!) *)
      IF R[1] <> stk[st] THEN GOTO 102;
(* !(!*LOAD !1 !(CAR !-!1!)!) *)
   ANYcar(stk[st-1],R[1]);
(* !(!*JUMP G!0!0!8!9!) *)
      GOTO 103;
(* !(!*LBL G!0!0!8!8!) *)
102: 
(* !(!*LOAD !2 !(CDR !-!1!)!) *)
   ANYcdr(stk[st-1],R[2]);
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK ASSOC EXPR !2!) *)
     PAS219;
(* !(!*LBL G!0!0!8!9!) *)
103: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
procedure PAS224;
forward;
procedure PAS225;
forward;
(* !(!*ENTRY DEFLIST EXPR !2!) *)
(*  EXPR DEFLIST *)
procedure PAS225;
label
      101,
      100;
begin
(* !(!*ALLOC !3!) *)
    alloc3;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPC G!0!0!9!2 !1 PAIRTAG!) *)
      IF tag_of(R[1]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*JUMP G!0!0!9!3!) *)
      GOTO 101;
(* !(!*LBL G!0!0!9!2!) *)
100: 
(* !(!*LINK CAAR EXPR !1!) *)
     PAS11;
(* !(!*LOAD !3 !(CAR !(CDR !(CAR !0!)!)!)!) *)
   ANYcar(stk[st],R[3]);
   ANYcdr(R[3],R[3]);
   ANYcar(R[3],R[3]);
(* !(!*LOAD !2 !-!1!) *)
      load(2,1);
(* !(!*LINK PUT EXPR !3!) *)
     PAS224;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK CAAR EXPR !1!) *)
     PAS11;
(* !(!*STORE !1 !-!2!) *)
      store(1,2);
(* !(!*LOAD !2 !-!1!) *)
      load(2,1);
(* !(!*LOAD !1 !(CDR !0!)!) *)
   ANYcdr(stk[st],R[1]);
(* !(!*LINK DEFLIST EXPR !2!) *)
     PAS225;
(* !(!*LOAD !2 !-!2!) *)
      load(2,2);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*LBL G!0!0!9!3!) *)
101: 
(* !(!*DEALLOC !3!) *)
      dealloc3;
(* !(!*EXIT!) *)
end;
procedure PAS226;
forward;
procedure PAS227;
forward;
(* !(!*ENTRY DELETE EXPR !2!) *)
(*  EXPR DELETE *)
procedure PAS227;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPC G!0!0!9!9 !2 PAIRTAG!) *)
      IF tag_of(R[2]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*JUMP G!0!1!0!1!) *)
      GOTO 102;
(* !(!*LBL G!0!0!9!9!) *)
100: 
(* !(!*LOAD !2 !(CAR !2!)!) *)
   ANYcar(R[2],R[2]);
(* !(!*LINK EQUAL EXPR !2!) *)
     PAS226;
(* !(!*JUMPNIL G!0!1!0!0!) *)
      IF R[1] = nilref THEN GOTO 101;
(* !(!*LOAD !1 !(CDR !-!1!)!) *)
   ANYcdr(stk[st-1],R[1]);
(* !(!*JUMP G!0!1!0!1!) *)
      GOTO 102;
(* !(!*LBL G!0!1!0!0!) *)
101: 
(* !(!*LOAD !2 !(CDR !-!1!)!) *)
   ANYcdr(stk[st-1],R[2]);
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK DELETE EXPR !2!) *)
     PAS227;
(* !(!*LOAD !2 !(CAR !-!1!)!) *)
   ANYcar(stk[st-1],R[2]);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*LBL G!0!1!0!1!) *)
102: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
procedure PAS228;
forward;
(* !(!*ENTRY DELQ EXPR !2!) *)
(*  EXPR DELQ *)
procedure PAS228;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*STORE !2 !0!) *)
      store(2,0);
(* !(!*JUMPC G!0!1!0!5 !2 PAIRTAG!) *)
      IF tag_of(R[2]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*JUMP G!0!1!0!7!) *)
      GOTO 102;
(* !(!*LBL G!0!1!0!5!) *)
100: 
(* !(!*JUMPN G!0!1!0!6 !(CAR !2!)!) *)
   ANYcar(R[2],RXX);
      IF R[1] <> RXX THEN GOTO 101;
(* !(!*LOAD !1 !(CDR !2!)!) *)
   ANYcdr(R[2],R[1]);
(* !(!*JUMP G!0!1!0!7!) *)
      GOTO 102;
(* !(!*LBL G!0!1!0!6!) *)
101: 
(* !(!*LOAD !2 !(CDR !2!)!) *)
   ANYcdr(R[2],R[2]);
(* !(!*LINK DELQ EXPR !2!) *)
     PAS228;
(* !(!*LOAD !2 !(CAR !-!1!)!) *)
   ANYcar(stk[st-1],R[2]);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*LBL G!0!1!0!7!) *)
102: 
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;
procedure PAS229;
forward;
(* !(!*ENTRY DELATQ EXPR !2!) *)
(*  EXPR DELATQ *)
procedure PAS229;
label
      103,
      102,
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPC G!0!1!1!1 !2 PAIRTAG!) *)
      IF tag_of(R[2]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*JUMP G!0!1!1!5!) *)
      GOTO 103;
(* !(!*LBL G!0!1!1!1!) *)
100: 
(* !(!*LOAD !1 !(CAR !2!)!) *)
   ANYcar(R[2],R[1]);
(* !(!*JUMPNC G!0!1!1!3 !1 PAIRTAG!) *)
      IF tag_of(R[1]) <> PAIRTAG THEN GOTO 101;
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*LINK CAAR EXPR !1!) *)
     PAS11;
(* !(!*JUMPE G!0!1!1!2 !0!) *)
      IF R[1]=stk[st] THEN GOTO 102;
(* !(!*LBL G!0!1!1!3!) *)
101: 
(* !(!*LOAD !2 !(CDR !-!1!)!) *)
   ANYcdr(stk[st-1],R[2]);
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK DELATQ EXPR !2!) *)
     PAS229;
(* !(!*LOAD !2 !(CAR !-!1!)!) *)
   ANYcar(stk[st-1],R[2]);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*JUMP G!0!1!1!5!) *)
      GOTO 103;
(* !(!*LBL G!0!1!1!2!) *)
102: 
(* !(!*LOAD !1 !(CDR !-!1!)!) *)
   ANYcdr(stk[st-1],R[1]);
(* !(!*LBL G!0!1!1!5!) *)
103: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY GET EXPR !2!) *)
(*  EXPR GET *)
procedure PAS230;
label
      101,
      100;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*STORE !2 !0!) *)
      store(2,0);
(* !(!*JUMPNC G!0!1!1!9 !1 IDTAG!) *)
      IF tag_of(R[1]) <> IDTAG THEN GOTO 100;
(* !(!*LINK PLIST EXPR !1!) *)
        R[1] := IDSPACE[INFO_OF(R[1])].PLIST;
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK ATSOC EXPR !2!) *)
     PAS223;
(* !(!*JUMPNC G!0!1!1!9 !1 PAIRTAG!) *)
      IF tag_of(R[1]) <> PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(CDR !1!)!) *)
   XCDR;
(* !(!*JUMP G!0!1!2!1!) *)
      GOTO 101;
(* !(!*LBL G!0!1!1!9!) *)
100: 
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*LBL G!0!1!2!1!) *)
101: 
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY PUT EXPR !3!) *)
(*  EXPR PUT *)
procedure PAS224;
label
      103,
      102,
      101,
      100;
begin
(* !(!*ALLOC !4!) *)
    alloc(4);
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*STORE !3 !-!2!) *)
      store(3,2);
(* !(!*JUMPC G!0!1!2!6 !1 IDTAG!) *)
      IF tag_of(R[1]) = IDTAG THEN GOTO 100;
(* !(!*LOAD !1 !3!) *)
      R[1] := R[3];
(* !(!*JUMP G!0!1!2!4!) *)
      GOTO 103;
(* !(!*LBL G!0!1!2!6!) *)
100: 
(* !(!*LINK PLIST EXPR !1!) *)
        R[1] := IDSPACE[INFO_OF(R[1])].PLIST;
(* !(!*STORE !1 !-!3!) *)
      store(1,3);
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK ATSOC EXPR !2!) *)
     PAS223;
(* !(!*JUMPNIL G!0!1!2!8!) *)
      IF R[1] = nilref THEN GOTO 101;
(* !(!*LOAD !2 !-!3!) *)
      load(2,3);
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK DELATQ EXPR !2!) *)
     PAS229;
(* !(!*STORE !1 !-!3!) *)
      store(1,3);
(* !(!*LBL G!0!1!2!8!) *)
101: 
(* !(!*LOAD !1 !-!2!) *)
      load(1,2);
(* !(!*JUMPNIL G!0!1!3!0!) *)
      IF R[1] = nilref THEN GOTO 102;
(* !(!*LOAD !2 !-!1!) *)
      load(2,1);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*LOAD !2 !-!3!) *)
      load(2,3);
(* !(!*LINK CONS EXPR !2!) *)
     XCONS;
(* !(!*STORE !1 !-!3!) *)
      store(1,3);
(* !(!*LBL G!0!1!3!0!) *)
102: 
(* !(!*LOAD !2 !-!3!) *)
      load(2,3);
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK SETPLIST EXPR !2!) *)
        IDSPACE[INFO_OF(R[1])].PLIST := R[2];
(* !(!*LOAD !1 !-!2!) *)
      load(1,2);
(* !(!*LBL G!0!1!2!4!) *)
103: 
(* !(!*DEALLOC !4!) *)
      dealloc(4);
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY REMPROP EXPR !2!) *)
(*  EXPR REMPROP *)
procedure PAS231;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LOAD !3 !(QUOTE NIL!)!) *)
      R[3] := nilref;
(* !(!*LINK PUT EXPR !3!) *)
     PAS224;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
procedure PAS232;
forward;
(* !(!*ENTRY LENGTH EXPR !1!) *)
(*  EXPR LENGTH *)
procedure PAS232;
label
      101,
      100;
begin
(* !(!*ALLOC !0!) *)
(* !(!*JUMPC G!0!1!3!5 !1 PAIRTAG!) *)
      IF tag_of(R[1]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE !0!)!) *)
      mkint(0,1);
(* !(!*JUMP G!0!1!3!6!) *)
      GOTO 101;
(* !(!*LBL G!0!1!3!5!) *)
100: 
(* !(!*LOAD !1 !(CDR !1!)!) *)
   XCDR;
(* !(!*LINK LENGTH EXPR !1!) *)
     PAS232;
(* !(!*LINK ADD!1 EXPR !1!) *)
     XADD1;
(* !(!*LBL G!0!1!3!6!) *)
101: 
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY ERRPRT EXPR !1!) *)
(*  EXPR ERRPRT *)
procedure PAS233;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LOAD !1 !(QUOTE !*!*!*!*! !)!) *)
      mkident(141,1);
(* !(!*LINK PRIN!2 EXPR !1!) *)
     PAS129;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK PRINT EXPR !1!) *)
     XPRINT;
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY MSGPRT EXPR !1!) *)
(*  EXPR MSGPRT *)
procedure PAS234;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LOAD !1 !(QUOTE !*!*!*! !)!) *)
      mkident(142,1);
(* !(!*LINK PRIN!2 EXPR !1!) *)
     PAS129;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK PRINT EXPR !1!) *)
     XPRINT;
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY FLAGP EXPR !2!) *)
(*  EXPR FLAGP *)
procedure PAS235;
label
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*LINK IDP EXPR !1!) *)
     PAS24;
(* !(!*JUMPNIL G!0!1!4!1!) *)
      IF R[1] = nilref THEN GOTO 100;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK PLIST EXPR !1!) *)
        R[1] := IDSPACE[INFO_OF(R[1])].PLIST;
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK MEMQ EXPR !2!) *)
     PAS222;
(* !(!*LBL G!0!1!4!1!) *)
100: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
procedure PAS236;
forward;
procedure PAS237;
forward;
(* !(!*ENTRY FLAG EXPR !2!) *)
(*  EXPR FLAG *)
procedure PAS237;
label
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPC G!0!1!4!5 !1 PAIRTAG!) *)
      IF tag_of(R[1]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*JUMP G!0!1!4!6!) *)
      GOTO 101;
(* !(!*LBL G!0!1!4!5!) *)
100: 
(* !(!*LOAD !1 !(CAR !1!)!) *)
   XCAR;
(* !(!*LINK FLAG!1 EXPR !2!) *)
     PAS236;
(* !(!*LOAD !2 !-!1!) *)
      load(2,1);
(* !(!*LOAD !1 !(CDR !0!)!) *)
   ANYcdr(stk[st],R[1]);
(* !(!*LINK FLAG EXPR !2!) *)
     PAS237;
(* !(!*LBL G!0!1!4!6!) *)
101: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY FLAG!1 EXPR !2!) *)
(*  EXPR FLAG1 *)
procedure PAS236;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPNC G!0!1!5!5 !1 IDTAG!) *)
      IF tag_of(R[1]) <> IDTAG THEN GOTO 100;
(* !(!*LINK PLIST EXPR !1!) *)
        R[1] := IDSPACE[INFO_OF(R[1])].PLIST;
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK MEMQ EXPR !2!) *)
     PAS222;
(* !(!*JUMPNIL G!0!1!5!0!) *)
      IF R[1] = nilref THEN GOTO 101;
(* !(!*LBL G!0!1!5!5!) *)
100: 
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*JUMP G!0!1!5!2!) *)
      GOTO 102;
(* !(!*LBL G!0!1!5!0!) *)
101: 
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK PLIST EXPR !1!) *)
        R[1] := IDSPACE[INFO_OF(R[1])].PLIST;
(* !(!*LOAD !2 !-!1!) *)
      load(2,1);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK SETPLIST EXPR !2!) *)
        IDSPACE[INFO_OF(R[1])].PLIST := R[2];
(* !(!*LBL G!0!1!5!2!) *)
102: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
procedure PAS238;
forward;
procedure PAS239;
forward;
(* !(!*ENTRY REMFLAG EXPR !2!) *)
(*  EXPR REMFLAG *)
procedure PAS239;
label
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPC G!0!1!5!8 !1 PAIRTAG!) *)
      IF tag_of(R[1]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*JUMP G!0!1!5!9!) *)
      GOTO 101;
(* !(!*LBL G!0!1!5!8!) *)
100: 
(* !(!*LOAD !1 !(CAR !1!)!) *)
   XCAR;
(* !(!*LINK REMFLAG!1 EXPR !2!) *)
     PAS238;
(* !(!*LOAD !2 !-!1!) *)
      load(2,1);
(* !(!*LOAD !1 !(CDR !0!)!) *)
   ANYcdr(stk[st],R[1]);
(* !(!*LINK REMFLAG EXPR !2!) *)
     PAS239;
(* !(!*LBL G!0!1!5!9!) *)
101: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY REMFLAG!1 EXPR !2!) *)
(*  EXPR REMFLAG1 *)
procedure PAS238;
label
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPC G!0!1!6!2 !1 IDTAG!) *)
      IF tag_of(R[1]) = IDTAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*JUMP G!0!1!6!5!) *)
      GOTO 101;
(* !(!*LBL G!0!1!6!2!) *)
100: 
(* !(!*LINK PLIST EXPR !1!) *)
        R[1] := IDSPACE[INFO_OF(R[1])].PLIST;
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK MEMQ EXPR !2!) *)
     PAS222;
(* !(!*JUMPNIL G!0!1!6!5!) *)
      IF R[1] = nilref THEN GOTO 101;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK PLIST EXPR !1!) *)
        R[1] := IDSPACE[INFO_OF(R[1])].PLIST;
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK DELQ EXPR !2!) *)
     PAS228;
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK SETPLIST EXPR !2!) *)
        IDSPACE[INFO_OF(R[1])].PLIST := R[2];
(* !(!*LBL G!0!1!6!5!) *)
101: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY EQ EXPR !2!) *)
(*  EXPR EQ *)
procedure PAS22;
label
      101,
      100;
begin
(* !(!*ALLOC !0!) *)
(* !(!*JUMPN G!0!1!7!0 !2!) *)
      IF R[1] <> R[2] THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE T!)!) *)
      R[1] := trueref;
(* !(!*JUMP G!0!1!7!1!) *)
      GOTO 101;
(* !(!*LBL G!0!1!7!0!) *)
100: 
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*LBL G!0!1!7!1!) *)
101: 
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY EQCAR EXPR !2!) *)
(*  EXPR EQCAR *)
procedure PAS240;
label
      101,
      100;
begin
(* !(!*ALLOC !0!) *)
(* !(!*JUMPNC G!0!1!7!4 !1 PAIRTAG!) *)
      IF tag_of(R[1]) <> PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(CAR !1!)!) *)
   XCAR;
(* !(!*JUMPN G!0!1!7!4 !2!) *)
      IF R[1] <> R[2] THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE T!)!) *)
      R[1] := trueref;
(* !(!*JUMP G!0!1!7!3!) *)
      GOTO 101;
(* !(!*LBL G!0!1!7!4!) *)
100: 
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*LBL G!0!1!7!3!) *)
101: 
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY NULL EXPR !1!) *)
(*  EXPR NULL *)
procedure PAS25;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LOAD !2 !(QUOTE NIL!)!) *)
      R[2] := nilref;
(* !(!*LINK EQ EXPR !2!) *)
     PAS22;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY PLIST EXPR !1!) *)
(*  EXPR PLIST *)
procedure PAS241;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LINK PLIST EXPR !1!) *)
        R[1] := IDSPACE[INFO_OF(R[1])].PLIST;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY VALUE EXPR !1!) *)
(*  EXPR VALUE *)
procedure PAS242;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LINK VALUE EXPR !1!) *)
        R[1] := IDSPACE[INFO_OF(R[1])].VAL;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY FUNCELL EXPR !1!) *)
(*  EXPR FUNCELL *)
procedure PAS243;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LINK FUNCELL EXPR !1!) *)
        R[1] := IDSPACE[INFO_OF(R[1])].FUNCELL;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY SETPLIST EXPR !2!) *)
(*  EXPR SETPLIST *)
procedure PAS244;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LINK SETPLIST EXPR !2!) *)
        IDSPACE[INFO_OF(R[1])].PLIST := R[2];
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY SETVALUE EXPR !2!) *)
(*  EXPR SETVALUE *)
procedure PAS245;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LINK SETVALUE EXPR !2!) *)
       IDSPACE[INFO_OF(R[1])].VAL := R[2];
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY SETFUNCELL EXPR !2!) *)
(*  EXPR SETFUNCELL *)
procedure PAS246;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LINK SETFUNCELL EXPR !2!) *)
        IDSPACE[INFO_OF(R[1])].FUNCELL := R[2];
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY ORDERP EXPR !2!) *)
(*  EXPR ORDERP *)
procedure PAS247;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*LINK !*INF EXPR !1!) *)
      mkitem(INTTAG,info_of(R[1]),R[1]);
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK !*INF EXPR !1!) *)
      mkitem(INTTAG,info_of(R[1]),R[1]);
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK GREATERP EXPR !2!) *)
     XGREATERP;
(* !(!*LINK NULL EXPR !1!) *)
     PAS25;
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY TOKEN EXPR !0!) *)
(*  EXPR TOKEN *)
procedure PAS248;
label
      100;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LINK RDTOK EXPR !0!) *)
     XRDTOK;
(* !(!*STORE !1 !(FLUID TOK!*!)!) *)
      idspace[143].val := R[1];
(* !(!*JUMPNC G!0!1!9!1 !1 CHARTAG!) *)
      IF tag_of(R[1]) <> CHARTAG THEN GOTO 100;
(* !(!*LINK CHAR!2ID EXPR !1!) *)
     SET_TAG(R[1], IDTAG);
(* !(!*STORE !1 !(FLUID TOK!*!)!) *)
      idspace[143].val := R[1];
(* !(!*LBL G!0!1!9!1!) *)
100: 
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY EQUAL EXPR !2!) *)
(*  EXPR EQUAL *)
procedure PAS226;
label
      103,
      102,
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPNC G!0!1!9!6 !1 ATOM!) *)
      IF tag_of(R[1]) = PAIRTAG THEN GOTO 100;
(* !(!*JUMPNC G!0!2!0!3 !2 ATOM!) *)
      IF tag_of(R[2]) = PAIRTAG THEN GOTO 101;
(* !(!*LINK EQ EXPR !2!) *)
     PAS22;
(* !(!*JUMP G!0!2!0!1!) *)
      GOTO 103;
(* !(!*LBL G!0!1!9!6!) *)
100: 
(* !(!*JUMPNC G!0!2!0!0 !2 ATOM!) *)
      IF tag_of(R[2]) = PAIRTAG THEN GOTO 102;
(* !(!*LBL G!0!2!0!3!) *)
101: 
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*JUMP G!0!2!0!1!) *)
      GOTO 103;
(* !(!*LBL G!0!2!0!0!) *)
102: 
(* !(!*LOAD !2 !(CAR !2!)!) *)
   ANYcar(R[2],R[2]);
(* !(!*LOAD !1 !(CAR !1!)!) *)
   XCAR;
(* !(!*LINK EQUAL EXPR !2!) *)
     PAS226;
(* !(!*JUMPNIL G!0!2!0!1!) *)
      IF R[1] = nilref THEN GOTO 103;
(* !(!*LOAD !2 !(CDR !-!1!)!) *)
   ANYcdr(stk[st-1],R[2]);
(* !(!*LOAD !1 !(CDR !0!)!) *)
   ANYcdr(stk[st],R[1]);
(* !(!*LINK EQUAL EXPR !2!) *)
     PAS226;
(* !(!*LBL G!0!2!0!1!) *)
103: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY ERROR EXPR !2!) *)
(*  EXPR ERROR *)
procedure PAS215;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*LOAD !3 !2!) *)
      R[3] := R[2];
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !(QUOTE !*!*!*!*! ERROR! !)!) *)
      mkident(144,1);
(* !(!*LINK LIST!3 EXPR !3!) *)
     PAS29;
(* !(!*LINK PRINT EXPR !1!) *)
     XPRINT;
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*STORE !1 !(FLUID EMSG!*!)!) *)
      idspace[145].val := R[1];
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*STORE !1 !(FLUID ENUM!*!)!) *)
      idspace[146].val := R[1];
(* !(!*LINK THROW EXPR !1!) *)
     XTHROW;
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY ERRORSET EXPR !3!) *)
(*  EXPR ERRORSET *)
procedure PAS249;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE NIL !(FLUID THROWING!*!)!) *)
      idspace[131].val := nilref;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*LINK CATCH EXPR !1!) *)
     XCATCH;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LOAD !1 !(FLUID THROWING!*!)!) *)
      R[1] := idspace[131].val;
(* !(!*JUMPT G!0!2!0!9!) *)
      IF R[1] <> nilref THEN GOTO 100;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK NCONS EXPR !1!) *)
     XNCONS;
(* !(!*JUMP G!0!2!0!7!) *)
      GOTO 102;
(* !(!*LBL G!0!2!0!9!) *)
100: 
(* !(!*STORE NIL !(FLUID THROWING!*!)!) *)
      idspace[131].val := nilref;
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*JUMPNIL G!0!2!1!2!) *)
      IF R[1] = nilref THEN GOTO 101;
(* !(!*LOAD !3 !(FLUID EMSG!*!)!) *)
      R[3] := idspace[145].val;
(* !(!*LOAD !2 !(FLUID ENUM!*!)!) *)
      R[2] := idspace[146].val;
(* !(!*LOAD !1 !(QUOTE !*!*!*!*!)!) *)
      mkident(147,1);
(* !(!*LINK LIST!3 EXPR !3!) *)
     PAS29;
(* !(!*LINK PRINT EXPR !1!) *)
     XPRINT;
(* !(!*LBL G!0!2!1!2!) *)
101: 
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LBL G!0!2!0!7!) *)
102: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
procedure PAS250;
forward;
(* !(!*ENTRY FIXP EXPR !1!) *)
(*  EXPR FIXP *)
procedure PAS251;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LINK NUMBERP EXPR !1!) *)
     PAS250;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
procedure PAS252;
forward;
(* !(!*ENTRY ABS EXPR !1!) *)
(*  EXPR ABS *)
procedure PAS253;
label
      101,
      100;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LINK MINUSP EXPR !1!) *)
     PAS252;
(* !(!*JUMPNIL G!0!2!1!7!) *)
      IF R[1] = nilref THEN GOTO 100;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK MINUS EXPR !1!) *)
     XMINUS;
(* !(!*JUMP G!0!2!1!8!) *)
      GOTO 101;
(* !(!*LBL G!0!2!1!7!) *)
100: 
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LBL G!0!2!1!8!) *)
101: 
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY SUB!1 EXPR !1!) *)
(*  EXPR SUB1 *)
procedure PAS254;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LOAD !2 !(QUOTE !-!1!)!) *)
      mkint(-1,2);
(* !(!*LINK PLUS!2 EXPR !2!) *)
     XPLUS2;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY ZEROP EXPR !1!) *)
(*  EXPR ZEROP *)
procedure PAS255;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LOAD !2 !(QUOTE !0!)!) *)
      mkint(0,2);
(* !(!*LINK EQ EXPR !2!) *)
     PAS22;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY ONEP EXPR !1!) *)
(*  EXPR ONEP *)
procedure PAS256;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LOAD !2 !(QUOTE !1!)!) *)
      mkint(1,2);
(* !(!*LINK EQ EXPR !2!) *)
     PAS22;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY IDP EXPR !1!) *)
(*  EXPR IDP *)
procedure PAS24;
label
      101,
      100;
begin
(* !(!*ALLOC !0!) *)
(* !(!*JUMPNC G!0!2!2!4 !1 IDTAG!) *)
      IF tag_of(R[1]) <> IDTAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE T!)!) *)
      R[1] := trueref;
(* !(!*JUMP G!0!2!2!5!) *)
      GOTO 101;
(* !(!*LBL G!0!2!2!4!) *)
100: 
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*LBL G!0!2!2!5!) *)
101: 
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
procedure PAS257;
forward;
(* !(!*ENTRY EXPT EXPR !2!) *)
(*  EXPR EXPT *)
procedure PAS257;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*JUMPN G!0!2!2!8 !(QUOTE !0!)!) *)
      mkitem(INTTAG,0,RXX);
      IF R[1] <> RXX THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE !1!)!) *)
      mkint(1,1);
(* !(!*JUMP G!0!2!3!0!) *)
      GOTO 102;
(* !(!*LBL G!0!2!2!8!) *)
100: 
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*LINK MINUSP EXPR !1!) *)
     PAS252;
(* !(!*JUMPNIL G!0!2!2!9!) *)
      IF R[1] = nilref THEN GOTO 101;
(* !(!*LOAD !1 !(QUOTE !0!)!) *)
      mkint(0,1);
(* !(!*JUMP G!0!2!3!0!) *)
      GOTO 102;
(* !(!*LBL G!0!2!2!9!) *)
101: 
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK SUB!1 EXPR !1!) *)
     PAS254;
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK EXPT EXPR !2!) *)
     PAS257;
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK TIMES!2 EXPR !2!) *)
     XTIMES2;
(* !(!*LBL G!0!2!3!0!) *)
102: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY FIX EXPR !1!) *)
(*  EXPR FIX *)
procedure PAS258;
begin
(* !(!*ALLOC !0!) *)
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY FLOAT EXPR !1!) *)
(*  EXPR FLOAT *)
procedure PAS259;
begin
(* !(!*ALLOC !0!) *)
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
procedure PAS260;
forward;
(* !(!*ENTRY MAX MACRO !1!) *)
(*  MACRO MAX *)
procedure PAS261;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LOAD !2 !(QUOTE MAX!2!)!) *)
      mkident(148,2);
(* !(!*LOAD !1 !(CDR !1!)!) *)
   XCDR;
(* !(!*LINK EXPAND EXPR !2!) *)
     PAS260;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY MIN MACRO !1!) *)
(*  MACRO MIN *)
procedure PAS262;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LOAD !2 !(QUOTE MIN!2!)!) *)
      mkident(149,2);
(* !(!*LOAD !1 !(CDR !1!)!) *)
   XCDR;
(* !(!*LINK EXPAND EXPR !2!) *)
     PAS260;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY PLUS MACRO !1!) *)
(*  MACRO PLUS *)
procedure PAS263;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LOAD !2 !(QUOTE PLUS!2!)!) *)
      mkident(150,2);
(* !(!*LOAD !1 !(CDR !1!)!) *)
   XCDR;
(* !(!*LINK EXPAND EXPR !2!) *)
     PAS260;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY TIMES MACRO !1!) *)
(*  MACRO TIMES *)
procedure PAS264;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LOAD !2 !(QUOTE TIMES!2!)!) *)
      mkident(151,2);
(* !(!*LOAD !1 !(CDR !1!)!) *)
   XCDR;
(* !(!*LINK EXPAND EXPR !2!) *)
     PAS260;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY MAX!2 EXPR !2!) *)
(*  EXPR MAX2 *)
procedure PAS265;
label
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*LINK GREATERP EXPR !2!) *)
     XGREATERP;
(* !(!*JUMPNIL G!0!2!4!1!) *)
      IF R[1] = nilref THEN GOTO 100;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*JUMP G!0!2!4!2!) *)
      GOTO 101;
(* !(!*LBL G!0!2!4!1!) *)
100: 
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LBL G!0!2!4!2!) *)
101: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY MIN!2 EXPR !2!) *)
(*  EXPR MIN2 *)
procedure PAS266;
label
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*LINK LESSP EXPR !2!) *)
     XLESSP;
(* !(!*JUMPNIL G!0!2!4!5!) *)
      IF R[1] = nilref THEN GOTO 100;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*JUMP G!0!2!4!6!) *)
      GOTO 101;
(* !(!*LBL G!0!2!4!5!) *)
100: 
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LBL G!0!2!4!6!) *)
101: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY FUNCTION FEXPR !1!) *)
(*  FEXPR FUNCTION *)
procedure PAS267;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LOAD !1 !(CAR !1!)!) *)
   XCAR;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY EXPAND EXPR !2!) *)
(*  EXPR EXPAND *)
procedure PAS260;
label
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LOAD !1 !(CDR !1!)!) *)
   XCDR;
(* !(!*JUMPT G!0!2!5!0!) *)
      IF R[1] <> nilref THEN GOTO 100;
(* !(!*LOAD !1 !(CAR !0!)!) *)
   ANYcar(stk[st],R[1]);
(* !(!*JUMP G!0!2!5!1!) *)
      GOTO 101;
(* !(!*LBL G!0!2!5!0!) *)
100: 
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*LINK EXPAND EXPR !2!) *)
     PAS260;
(* !(!*LOAD !3 !1!) *)
      R[3] := R[1];
(* !(!*LOAD !2 !(CAR !0!)!) *)
   ANYcar(stk[st],R[2]);
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LINK LIST!3 EXPR !3!) *)
     PAS29;
(* !(!*LBL G!0!2!5!1!) *)
101: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY NUMBERP EXPR !1!) *)
(*  EXPR NUMBERP *)
procedure PAS250;
label
      101,
      100;
begin
(* !(!*ALLOC !0!) *)
(* !(!*JUMPNC G!0!2!5!5 !1 NUMTAG!) *)
      IF not((tag_of(R[1]) = INTTAG)
       or (tag_of(R[1]) = FIXTAG)) THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE T!)!) *)
      R[1] := trueref;
(* !(!*JUMP G!0!2!5!6!) *)
      GOTO 101;
(* !(!*LBL G!0!2!5!5!) *)
100: 
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*LBL G!0!2!5!6!) *)
101: 
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY ATOM EXPR !1!) *)
(*  EXPR ATOM *)
procedure PAS268;
label
      101,
      100;
begin
(* !(!*ALLOC !0!) *)
(* !(!*JUMPNC G!0!2!5!9 !1 ATOM!) *)
      IF tag_of(R[1]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE T!)!) *)
      R[1] := trueref;
(* !(!*JUMP G!0!2!6!0!) *)
      GOTO 101;
(* !(!*LBL G!0!2!5!9!) *)
100: 
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*LBL G!0!2!6!0!) *)
101: 
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY MINUSP EXPR !1!) *)
(*  EXPR MINUSP *)
procedure PAS252;
label
      101,
      100;
begin
(* !(!*ALLOC !0!) *)
(* !(!*JUMPNC G!0!2!6!3 !1 NUMTAG!) *)
      IF not((tag_of(R[1]) = INTTAG)
       or (tag_of(R[1]) = FIXTAG)) THEN GOTO 100;
(* !(!*LOAD !2 !(QUOTE !-!1!)!) *)
      mkint(-1,2);
(* !(!*LINK GREATERP EXPR !2!) *)
     XGREATERP;
(* !(!*JUMPT G!0!2!6!3!) *)
      IF R[1] <> nilref THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE T!)!) *)
      R[1] := trueref;
(* !(!*JUMP G!0!2!6!5!) *)
      GOTO 101;
(* !(!*LBL G!0!2!6!3!) *)
100: 
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*LBL G!0!2!6!5!) *)
101: 
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY SET EXPR !2!) *)
(*  EXPR SET *)
procedure PAS269;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPNC G!0!2!6!9 !1 IDTAG!) *)
      IF tag_of(R[1]) <> IDTAG THEN GOTO 100;
(* !(!*JUMPE G!0!2!6!9 !(QUOTE T!)!) *)
      IF R[1]=trueref THEN GOTO 100;
(* !(!*JUMPN G!0!2!6!8 !(QUOTE NIL!)!) *)
      IF R[1] <> nilref THEN GOTO 101;
(* !(!*LBL G!0!2!6!9!) *)
100: 
(* !(!*LOAD !1 !2!) *)
      R[1] := R[2];
(* !(!*LINK NCONS EXPR !1!) *)
     XNCONS;
(* !(!*LOAD !2 !0!) *)
      load(2,0);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*LOAD !2 !(QUOTE SET!)!) *)
      mkident(152,2);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*JUMP G!0!2!7!2!) *)
      GOTO 102;
(* !(!*LBL G!0!2!6!8!) *)
101: 
(* !(!*LINK SETVALUE EXPR !2!) *)
       IDSPACE[INFO_OF(R[1])].VAL := R[2];
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*LBL G!0!2!7!2!) *)
102: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY PRINC EXPR !1!) *)
(*  EXPR PRINC *)
procedure PAS270;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LINK PRIN!2 EXPR !1!) *)
     PAS129;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY PRIN!1 EXPR !1!) *)
(*  EXPR PRIN1 *)
procedure PAS271;
begin
(* !(!*ALLOC !0!) *)
(* !(!*LINK PRIN!2 EXPR !1!) *)
     PAS129;
(* !(!*DEALLOC !0!) *)
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY PRINT EXPR !1!) *)
(*  EXPR PRINT *)
procedure XPRINT;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LINK PRIN!1 EXPR !1!) *)
     PAS271;
(* !(!*LINK TERPRI EXPR !0!) *)
     XTERPRI;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY PRIN!2T EXPR !1!) *)
(*  EXPR PRIN2T *)
procedure PAS272;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LINK PRIN!2 EXPR !1!) *)
     PAS129;
(* !(!*LINK TERPRI EXPR !0!) *)
     XTERPRI;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY LBIND!1 EXPR !2!) *)
(*  EXPR LBIND1 *)
procedure PAS273;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*LINK VALUE EXPR !1!) *)
        R[1] := IDSPACE[INFO_OF(R[1])].VAL;
(* !(!*LOAD !2 !0!) *)
      load(2,0);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*LOAD !2 !(FLUID BSTK!*!)!) *)
      R[2] := idspace[130].val;
(* !(!*LINK CONS EXPR !2!) *)
     XCONS;
(* !(!*STORE !1 !(FLUID BSTK!*!)!) *)
      idspace[130].val := R[1];
(* !(!*LOAD !2 !-!1!) *)
      load(2,1);
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK SETVALUE EXPR !2!) *)
       IDSPACE[INFO_OF(R[1])].VAL := R[2];
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY PBIND!1 EXPR !1!) *)
(*  EXPR PBIND1 *)
procedure PAS274;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LINK VALUE EXPR !1!) *)
        R[1] := IDSPACE[INFO_OF(R[1])].VAL;
(* !(!*LOAD !2 !0!) *)
      load(2,0);
(* !(!*LINK XCONS EXPR !2!) *)
     XXCONS;
(* !(!*LOAD !2 !(FLUID BSTK!*!)!) *)
      R[2] := idspace[130].val;
(* !(!*LINK CONS EXPR !2!) *)
     XCONS;
(* !(!*STORE !1 !(FLUID BSTK!*!)!) *)
      idspace[130].val := R[1];
(* !(!*LOAD !2 !(QUOTE NIL!)!) *)
      R[2] := nilref;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK SETVALUE EXPR !2!) *)
       IDSPACE[INFO_OF(R[1])].VAL := R[2];
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY UNBIND!1 EXPR !0!) *)
(*  EXPR UNBIND1 *)
procedure PAS275;
label
      100;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*LOAD !1 !(FLUID BSTK!*!)!) *)
      R[1] := idspace[130].val;
(* !(!*JUMPC G!0!2!8!9 !1 PAIRTAG!) *)
      IF tag_of(R[1]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !2 !(QUOTE BNDUNDERFLOW!)!) *)
      mkident(153,2);
(* !(!*LOAD !1 !(QUOTE !9!9!)!) *)
      mkint(99,1);
(* !(!*LINK ERROR EXPR !2!) *)
     PAS215;
(* !(!*LBL G!0!2!8!9!) *)
100: 
(* !(!*LINK CAAR EXPR !1!) *)
     PAS11;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LOAD !1 !(FLUID BSTK!*!)!) *)
      R[1] := idspace[130].val;
(* !(!*LINK CDAR EXPR !1!) *)
     PAS13;
(* !(!*LOAD !2 !1!) *)
      R[2] := R[1];
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK SETVALUE EXPR !2!) *)
       IDSPACE[INFO_OF(R[1])].VAL := R[2];
(* !(!*LOAD !1 !(CDR !(FLUID BSTK!*!)!)!) *)
   ANYcdr(idspace[130].val,R[1]);
(* !(!*STORE !1 !(FLUID BSTK!*!)!) *)
      idspace[130].val := R[1];
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY UNBINDN EXPR !1!) *)
(*  EXPR UNBINDN *)
procedure PAS276;
label
      101,
      100;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LBL G!0!2!9!3!) *)
100: 
(* !(!*LOAD !2 !(QUOTE !0!)!) *)
      mkint(0,2);
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK GREATERP EXPR !2!) *)
     XGREATERP;
(* !(!*JUMPNIL G!0!2!9!2!) *)
      IF R[1] = nilref THEN GOTO 101;
(* !(!*LINK UNBIND!1 EXPR !0!) *)
     PAS275;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*LINK SUB!1 EXPR !1!) *)
     PAS254;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*JUMP G!0!2!9!3!) *)
      GOTO 100;
(* !(!*LBL G!0!2!9!2!) *)
101: 
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY UNBINDTO EXPR !2!) *)
(*  EXPR UNBINDTO *)
procedure XUNBINDTO;
label
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*LBL G!0!2!9!9!) *)
100: 
(* !(!*LOAD !1 !(FLUID BSTK!*!)!) *)
      R[1] := idspace[130].val;
(* !(!*JUMPNC G!0!3!0!2 !1 PAIRTAG!) *)
      IF tag_of(R[1]) <> PAIRTAG THEN GOTO 101;
(* !(!*JUMPE G!0!3!0!2 !-!1!) *)
      IF R[1]=stk[st-1] THEN GOTO 101;
(* !(!*LINK UNBIND!1 EXPR !0!) *)
     PAS275;
(* !(!*JUMP G!0!2!9!9!) *)
      GOTO 100;
(* !(!*LBL G!0!3!0!2!) *)
101: 
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*LOAD !1 !0!) *)
      load10;
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
procedure PAS277;
forward;
procedure PAS278;
forward;
(* !(!*ENTRY EVLAM EXPR !2!) *)
(*  EXPR EVLAM *)
procedure PAS279;
label
      101,
      100;
begin
(* !(!*ALLOC !3!) *)
    alloc3;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*JUMPNC G!0!3!0!7 !1 PAIRTAG!) *)
      IF tag_of(R[1]) <> PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(CAR !1!)!) *)
   XCAR;
(* !(!*JUMPE G!0!3!0!6 !(QUOTE LAMBDA!)!) *)
      mkitem(IDTAG,154,RXX);
      IF R[1]=RXX THEN GOTO 101;
(* !(!*LBL G!0!3!0!7!) *)
100: 
(* !(!*LOAD !2 !(QUOTE NOT! DEFINED!)!) *)
      mkident(155,2);
(* !(!*LOAD !1 !(QUOTE !9!9!)!) *)
      mkint(99,1);
(* !(!*LINK ERROR EXPR !2!) *)
     PAS215;
(* !(!*LBL G!0!3!0!6!) *)
101: 
(* !(!*LOAD !1 !(CDR !0!)!) *)
   ANYcdr(stk[st],R[1]);
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*LOAD !1 !(CAR !1!)!) *)
   XCAR;
(* !(!*STORE !1 !-!2!) *)
      store(1,2);
(* !(!*LINK LBINDN EXPR !2!) *)
     PAS277;
(* !(!*LOAD !1 !(CDR !0!)!) *)
   ANYcdr(stk[st],R[1]);
(* !(!*LINK P!.N EXPR !1!) *)
     PAS278;
(* !(!*STORE !1 !-!1!) *)
      store(1,1);
(* !(!*LOAD !1 !-!2!) *)
      load(1,2);
(* !(!*LINK LENGTH EXPR !1!) *)
     PAS232;
(* !(!*LINK UNBINDN EXPR !1!) *)
     PAS276;
(* !(!*LOAD !1 !-!1!) *)
      load(1,1);
(* !(!*DEALLOC !3!) *)
      dealloc3;
(* !(!*EXIT!) *)
end;
procedure PAS280;
forward;
(* !(!*ENTRY LBINDN EXPR !2!) *)
(*  EXPR LBINDN *)
procedure PAS277;
label
      102,
      101,
      100;
begin
(* !(!*ALLOC !2!) *)
    alloc2;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*STORE !2 !-!1!) *)
      store(2,1);
(* !(!*JUMPC G!0!3!1!2 !1 PAIRTAG!) *)
      IF tag_of(R[1]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*JUMP G!0!3!1!4!) *)
      GOTO 102;
(* !(!*LBL G!0!3!1!2!) *)
100: 
(* !(!*JUMPC G!0!3!1!3 !2 PAIRTAG!) *)
      IF tag_of(R[2]) = PAIRTAG THEN GOTO 101;
(* !(!*LINK PBINDN EXPR !1!) *)
     PAS280;
(* !(!*JUMP G!0!3!1!4!) *)
      GOTO 102;
(* !(!*LBL G!0!3!1!3!) *)
101: 
(* !(!*LOAD !2 !(CAR !2!)!) *)
   ANYcar(R[2],R[2]);
(* !(!*LOAD !1 !(CAR !1!)!) *)
   XCAR;
(* !(!*LINK LBIND!1 EXPR !2!) *)
     PAS273;
(* !(!*LOAD !2 !(CDR !-!1!)!) *)
   ANYcdr(stk[st-1],R[2]);
(* !(!*LOAD !1 !(CDR !0!)!) *)
   ANYcdr(stk[st],R[1]);
(* !(!*LINK LBINDN EXPR !2!) *)
     PAS277;
(* !(!*LBL G!0!3!1!4!) *)
102: 
(* !(!*DEALLOC !2!) *)
      dealloc2;
(* !(!*EXIT!) *)
end;
(* !(!*ENTRY PBINDN EXPR !1!) *)
(*  EXPR PBINDN *)
procedure PAS280;
label
      101,
      100;
begin
(* !(!*ALLOC !1!) *)
    alloc1;
(* !(!*STORE !1 !0!) *)
      store10;
(* !(!*JUMPC G!0!3!1!7 !1 PAIRTAG!) *)
      IF tag_of(R[1]) = PAIRTAG THEN GOTO 100;
(* !(!*LOAD !1 !(QUOTE NIL!)!) *)
      R[1] := nilref;
(* !(!*JUMP G!0!3!1!8!) *)
      GOTO 101;
(* !(!*LBL G!0!3!1!7!) *)
100: 
(* !(!*LOAD !1 !(CAR !1!)!) *)
   XCAR;
(* !(!*LINK PBIND!1 EXPR !1!) *)
     PAS274;
(* !(!*LOAD !1 !(CDR !0!)!) *)
   ANYcdr(stk[st],R[1]);
(* !(!*LINK PBINDN EXPR !1!) *)
     PAS280;
(* !(!*LBL G!0!3!1!8!) *)
101: 
(* !(!*DEALLOC !1!) *)
      dealloc1;
(* !(!*EXIT!) *)
end;

Added perq-pascal-lisp-project/pas2.red version [9633c0402a].























































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                     
% 		PASCAL BASED MINI-LISP
%
% File: 	PAS2.RED - Basic LISP Functions
% ChangeDate: 	10:42pm  Wednesday, 15 July 1981
% By: 		M. L. Griss
%       	Change to add Features for Schlumberger Demo
% 
% 	    All RIGHTS RESERVED
%           COPYRIGHT (C) - 1981 - M. L. GRISS
%           Computer Science Department
%           University of Utah
%
%           Do Not distribute with out written consent of M. L. Griss
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

SYMBOLIC PROCEDURE PAIRP X;
  IF PAIRP X THEN T ELSE NIL;

SMACRO PROCEDURE NOTNULL(X);	%For readability.
  X;

SYMBOLIC PROCEDURE NOT X; 
 X EQ NIL;

SYMBOLIC PROCEDURE CODEP X; 
  IF CODEP X THEN T ELSE NIL;

SYMBOLIC PROCEDURE CONSTANTP X; 
   NULL (PAIRP X OR IDP X);

SYMBOLIC PROCEDURE EQN(A,B); 
   A EQ B;

%.  List entries (+ CONS, NCONS, XCONS)

SYMBOLIC PROCEDURE LIST2(R1,R2);
 R1 . NCONS R2;

SYMBOLIC PROCEDURE LIST3(R1,R2,R3);
 R1 .  LIST2(R2,R3);

SYMBOLIC PROCEDURE LIST4(R1,R2,R3,R4);
 R1 .  LIST3(R2,R3,R4);

SYMBOLIC PROCEDURE LIST5(R1,R2,R3,R4,R5);
 R1 .  LIST4(R2,R3,R4,R5);

SYMBOLIC PROCEDURE REVERSE U;
 REV U;

SYMBOLIC PROCEDURE APPEND(U,V);
 BEGIN  U:=REVERSE U;
        WHILE PAIRP U DO <<V :=CAR U . V; U:=CDR U>>;
	RETURN V
 END;

%. procedures to support GET and PUT, FLAG, etc.


SYMBOLIC PROCEDURE MEMBER(A,B); 
   IF NULL B THEN A ELSE IF A EQ CAR B THEN B ELSE A MEMBER CDR B;

SYMBOLIC PROCEDURE PAIR(U,V); 
   IF U AND V THEN (CAR U . CAR V) . PAIR(CDR U,CDR V)
    ELSE IF U OR V THEN ERROR(0,'PAIR)
    ELSE NIL;

SYMBOLIC PROCEDURE SASSOC(U,V,FN); 
   IF NOT PAIRP V THEN APPLY(FN,'(NIL))
    ELSE IF U EQ CAAR V THEN CAR V
    ELSE SASSOC(U,CDR V,FN);

SYMBOLIC PROCEDURE SUBLIS(X,Y); 
   IF NOT PAIRP X THEN Y
    ELSE BEGIN SCALAR U; 
            U := ASSOC(Y,X); 
            RETURN IF U THEN CDR U
                    ELSE IF ATOM Y THEN Y
                    ELSE SUBLIS(X,CAR Y) . SUBLIS(X,CDR Y)
         END;

SYMBOLIC PROCEDURE SUBST(U,V,W); 
   IF NULL V THEN NIL
    ELSE IF V EQ W THEN U
    ELSE IF ATOM W THEN W
    ELSE SUBST(U,V,CAR W) . SUBST(U,V,CDR W);

SYMBOLIC PROCEDURE MEMQ(U,V);
 IF NOT PAIRP V THEN V
  ELSE IF U EQ CAR V THEN V ELSE MEMQ(U,CDR V);

SYMBOLIC PROCEDURE ATSOC(U,V);
 IF NOT PAIRP V THEN V
  ELSE IF (NOT PAIRP CAR V)
	 OR NOT(U EQ CAAR V) THEN ATSOC(U,CDR V)
  ELSE CAR V;

SYMBOLIC PROCEDURE ASSOC(U,V); 
   IF NOT PAIRP V THEN NIL
    ELSE IF ATOM CAR V THEN ERROR(100,LIST(V,'ASSOC))
    ELSE IF U EQ CAAR V THEN CAR V
    ELSE ASSOC(U,CDR V);

SYMBOLIC PROCEDURE DEFLIST(U,IND); 
   IF NOT PAIRP U THEN NIL
    ELSE (<<PUT(CAAR U,IND,CADAR U); CAAR U>>) . DEFLIST(CDR U,IND);

SYMBOLIC PROCEDURE DELETE(U,V); 
   IF NOT PAIRP V THEN NIL 
    ELSE IF U=CAR V THEN CDR V 
    ELSE CAR V . DELETE(U,CDR V);

SYMBOLIC PROCEDURE DELQ(U,V);
   IF NOT PAIRP V THEN V
    ELSE IF U EQ CAR V THEN CDR V
    ELSE CAR V . DELQ(U,CDR V); % Recopy

SYMBOLIC PROCEDURE DELATQ(U,V);
 IF NOT PAIRP V THEN V
  ELSE IF (NOT PAIRP CAR V)
	 OR NOT(U EQ CAAR V) THEN (CAR V . DELATQ(U,CDR V))
  ELSE CDR V;

SYMBOLIC PROCEDURE GET(U,V);
 IF NOT IDP U THEN NIL
 ELSE IF PAIRP (U:=ATSOC(V,PLIST U)) THEN CDR U ELSE NIL;

SYMBOLIC PROCEDURE PUT(U,V,WW);
 BEGIN SCALAR L;
	IF NOT IDP U THEN RETURN WW;
	L:=PLIST U;
	IF ATSOC(V,L) THEN L:=DELATQ(V,L);
	IF NOTNULL WW THEN L:=(V . WW) . L;
	SETPLIST(U,L);
	RETURN WW;
 END;

SYMBOLIC PROCEDURE REMPROP(U,V);
   PUT(U,V,NIL);


SYMBOLIC PROCEDURE LENGTH L;
 IF NOT PAIRP L THEN 0
  ELSE 1+LENGTH CDR L;

SYMBOLIC PROCEDURE ERRPRT L;
 <<PRIN2 '!*!*!*!*! ; PRINT L>>;

SYMBOLIC PROCEDURE MSGPRT L;
 <<PRIN2 '!*!*!*! ; PRINT L>>;

SYMBOLIC PROCEDURE FLAGP(NAM,FLG);
 IDP NAM AND FLG MEMQ PLIST NAM;

SYMBOLIC PROCEDURE FLAG(NAML,FLG);
 IF NOT PAIRP NAML THEN NIL
  ELSE <<FLAG1(CAR NAML,FLG); FLAG(CDR NAML,FLG)>>;

SYMBOLIC PROCEDURE FLAG1(NAM,FLG);
 IF NOT IDP NAM THEN NIL
  ELSE IF FLG MEMQ PLIST NAM THEN NIL
  ELSE SETPLIST(NAM, FLG . PLIST(NAM));

SYMBOLIC PROCEDURE REMFLAG(NAML,FLG);
 IF NOT PAIRP NAML THEN NIL
  ELSE <<REMFLAG1(CAR NAMl,FLG); REMFLAG(CDR NAML,FLG)>>;

SYMBOLIC PROCEDURE REMFLAG1(NAM,FLG);
 IF NOT IDP NAM THEN NIL
  ELSE IF NOT(FLG MEMQ PLIST NAM)THEN NIL
  ELSE SETPLIST(NAM,DELQ(FLG, PLIST(NAM)));

% Interpreter entries for some important OPEN-coded functions;

SYMBOLIC PROCEDURE EQ(U,V);
 IF U EQ V THEN T ELSE NIL; % Careful, only bool-test opencoded

SYMBOLIC PROCEDURE EQCAR(U,V);
 IF  PAIRP  U THEN IF(CAR U EQ V) THEN T ELSE NIL;

SYMBOLIC PROCEDURE NULL U;
 U EQ NIL;

SYMBOLIC PROCEDURE PLIST U;
 PLIST U;

SYMBOLIC PROCEDURE VALUE U;
 VALUE U;

SYMBOLIC PROCEDURE FUNCELL U;
 FUNCELL U;

SYMBOLIC PROCEDURE SETPLIST(U,V);
 SETPLIST(U,V);

SYMBOLIC PROCEDURE SETVALUE(U,V);
 SETVALUE(U,V);

SYMBOLIC PROCEDURE SETFUNCELL(U,V);
 SETFUNCELL(U,V);

%.  Support for ALGebra

SYMBOLIC PROCEDURE ORDERP(X,Y); %.  Compare ID orders
 !*INF(X) <= !*INF(Y);

SYMBOLIC PROCEDURE TOKEN;	%. Renaming
 BEGIN TOK!*:=RDTOK();
       IF CHARP TOK!* THEN TOK!*:=CHAR2ID TOK!*;
       RETURN TOK!*;
 END;

% Can get confused if user changes from non-hashed to hashed cons.

SYMBOLIC PROCEDURE EQUAL(X,Y);
 IF ATOM(X) THEN IF ATOM(Y) THEN X EQ Y ELSE NIL
 ELSE IF ATOM(Y) THEN NIL ELSE EQUAL(CAR X, CAR Y) AND EQUAL(CDR X, CDR Y);

%--------- CATCH/THROW and ERROR handler ---------------

SYMBOLIC PROCEDURE ERROR(X,Y);
 <<PRINT LIST('!*!*!*!*! ERROR! ,X,Y);
   EMSG!* := Y; ENUM!* := X;
   THROW X>>;

SYMBOLIC PROCEDURE ERRORSET(FORM,MSGP,TRACEP);
 BEGIN SCALAR VAL;
   THROWING!* :=NIL;
   VAL:=CATCH FORM;
   IF NOT THROWING!* THEN RETURN LIST VAL;
   THROWING!*:=NIL;
   IF MSGP THEN PRINT LIST('!*!*!*!*,ENUM!*,EMSG!*);
   RETURN VAL
 END;

% More ARITHMETIC
SYMBOLIC PROCEDURE FIXP X; NUMBERP X;

SYMBOLIC PROCEDURE ABS X;
 IF X < 0 THEN (-X) ELSE X;

SYMBOLIC PROCEDURE SUB1 X;
 PLUS2(X,MINUS 1);

SYMBOLIC PROCEDURE ZEROP X;
  X=0;

SYMBOLIC PROCEDURE ONEP X;
  X=1;

SYMBOLIC PROCEDURE IDP X;
 IF IDP X THEN T ELSE NIL;
SYMBOLIC PROCEDURE EXPT(A,B); 
   IF B EQ 0 THEN 1 
    ELSE IF B <0 THEN 0            % Error ?
    ELSE TIMES2(A,A**SUB1 B);

SYMBOLIC PROCEDURE FIX X; X;

SYMBOLIC PROCEDURE FLOAT X; X;
% Should BE MACROS, check problem?

SYMBOLIC MACRO PROCEDURE MAX X; EXPAND(CDR X,'MAX2);

SYMBOLIC MACRO PROCEDURE MIN X; EXPAND(CDR X,'MIN2);

SYMBOLIC MACRO PROCEDURE PLUS X; EXPAND(CDR X,'PLUS2);

SYMBOLIC MACRO PROCEDURE TIMES X;  EXPAND(CDR X,'TIMES2);

SYMBOLIC PROCEDURE MAX2(A,B); IF A>B THEN A ELSE B;

SYMBOLIC PROCEDURE MIN2(A,B); IF A<B THEN A ELSE B;

SYMBOLIC FEXPR PROCEDURE FUNCTION X; CAR X;

SYMBOLIC PROCEDURE EXPAND(L,FN); 
   IF NULL CDR L THEN CAR L ELSE LIST(FN,CAR L,EXPAND(CDR L,FN));

SYMBOLIC PROCEDURE NUMBERP X;
 IF NUMBERP X THEN T ELSE NIL;

SYMBOLIC PROCEDURE ATOM X;
 IF ATOM X THEN T ELSE NIL;

SYMBOLIC PROCEDURE MINUSP X;
 IF NUMBERP X AND X <=(-1) THEN T ELSE NIL;

SYMBOLIC PROCEDURE SET(A,B);
 IF (NOT IDP(A)) OR (A EQ 'T) OR (A EQ 'NIL) THEN
  ('SET .  A . B . NIL) % Error value
  ELSE <<SETVALUE(A,B); B>>;

SYMBOLIC PROCEDURE PRINC X; 
   PRIN2 X;

SYMBOLIC PROCEDURE PRIN1 X;
   PRIN2 X;

SYMBOLIC PROCEDURE PRINT X;
 <<PRIN1 X; TERPRI(); X>>;

SYMBOLIC PROCEDURE PRIN2T X;
  <<PRIN2 X; TERPRI(); X>>;

%. a) Simple Binding for LAMBDA eval
%     Later convert to bstack in PAS0, will need GC hooks

FLUID '(BSTK!*);	% The Binding stack, list of (id . oval)
			% For Special cell model
SYMBOLIC PROCEDURE LBIND1(IDNAME,NVAL); %. For LAMBDA
 <<BSTK!*:=(IDNAME . VALUE(IDNAME)) . BSTK!*;
   SETVALUE(IDNAME,NVAL)>>;

SYMBOLIC PROCEDURE PBIND1(IDNAME);	%. Prog Bind 1 id
 <<BSTK!*:=(IDNAME . VALUE(IDNAME)) . BSTK!*;
   SETVALUE(IDNAME,'NIL)>>;

SYMBOLIC PROCEDURE UNBIND1;		%. Unbind 1 item
  IF PAIRP BSTK!* THEN <<SETVALUE(CAAR BSTK!*,CDAR BSTK!*);
                         BSTK!*:=CDR BSTK!*>>
   ELSE ERROR(99,'BNDUNDERFLOW);

SYMBOLIC PROCEDURE UNBINDN N;		%. Unbind N items
  WHILE N>0 DO <<UNBIND1(); N:=N-1>>;

SYMBOLIC PROCEDURE UNBINDTO(RETVAL,OLDSTK); %. Unbind to CATCH-mark
  <<WHILE PAIRP BSTK!* AND NOT(BSTK!* EQ OLDSTK)
      DO UNBIND1();
    RETVAL>>;

% b) Simple LAMBDA evaluator

SYMBOLIC PROCEDURE EVLAM(LAM,ARGS);	%. Will PAD args NILs
  BEGIN SCALAR VARS,BOD;
	IF NOT (PAIRP LAM AND CAR LAM EQ 'LAMBDA) 
	  THEN RETURN ERROR(99,'Not! defined);
	LAM:=CDR LAM;
	VARS:=CAR LAM; 
	LBINDN(VARS,ARGS);	% Set up BSTK!*
	BOD:=P!.N CDR LAM;	% and do PROGN eval
	UNBINDN LENGTH VARS;	% restore BSTK!*
        RETURN BOD
   END;

SYMBOLIC PROCEDURE LBINDN(VARS,ARGS); %. Bind each element of VARS to ARGS
  IF NOT PAIRP VARS THEN NIL
   ELSE IF NOT PAIRP ARGS THEN PBINDN VARS % rest to NIL
   ELSE <<LBIND1(CAR VARS,CAR ARGS);
          LBINDN(CDR VARS,CDR ARGS)>>;


SYMBOLIC PROCEDURE PBINDN VARS; 	%. Bind each element of VARS to NIL
  IF NOT PAIRP VARS THEN NIL
   ELSE <<PBIND1 CAR VARS;
          PBINDN CDR VARS>>;


END$

Added perq-pascal-lisp-project/pas2.sli version [a63e4bc9d8].

cannot compute difference between binary files

Added perq-pascal-lisp-project/pas2.sym version [fa214de8c2].

cannot compute difference between binary files

Added perq-pascal-lisp-project/pas3.bld version [aa3281dd59].

















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
DEF s: <SCRATCH>
DEF DSK: DSK:,SYS:
DEF SYS: DSK:,SYS:
pas:PASCMP
OFF SYSLISP$
OFF MSG$
OFF NOUUO$
OFF DOMOVE$             % Can't have BOTH DOMOVE and FXFRM
OFF NOFIXFRM;		% Reduce ALLOCS
ON MACECHO$		%OFF Cuts down size of output file.

% passer fixups

REMPROP('W,'STAT);
REMPROP('PLIST,'STAT);
PUT(QUOTE SETQ,QUOTE UNARY,QUOTE SETQ)$	% Permit FEXPR definitions
PUT(QUOTE AND,QUOTE UNARY,QUOTE AND)$
PUT(QUOTE OR,QUOTE UNARY,QUOTE OR)$

IN PAS2.SYM$
% Perhaps the following lines should really be in POLY.RED, but they
% don't work correctly inside body of text being compiled.
PUT('CAR,'ANYREG,'T)$
PUT('CDR,'ANYREG,'T)$
PUT('VALUE,'OPENCOD,'("        R[1] := idspace[info_of(R[1])].val;"));
PUT('PLIST,'OPENCOD,'("        R[1] := idspace[Info_of(r[1])].plist;"));
PUT('FUNCELL,'OPENCOD,'("        R[1] := idspace[Info_of(r[1])].funcell;"));
PUT('SETVALUE,'OPENCOD,'("       idspace[Info_of(r[1])].val := R[2];"));
PUT('SETPLIST,'OPENCOD,'("        idspace[Info_of(r[1])].plist := R[2];"));
PUT('SETFUNCELL,'OPENCOD,'("        idspace[Info_of(r[1])].funcell := R[2];"));
PUT('CHAR2ID,'OPENCOD,'("     set_tag(R[1], idtag);"));
PUT('CODEP, 'OPENCOD, '("     tag_of(r[1]) = codetag;"));

OUT PAS3.PAS$
DRT1('PAS3,PAS2IDS,PAS2CSTS,PAS2LITS,PAS2FNS)$
IN PAS3.RED$
DRT2()$
SHUT PAS3.PAS$

OUT PAS3.SYM$
DUMPSYMS('PAS3)$
SHUT PAS3.SYM$

OUT PAS3.SLI$
DRT3()$
SHUT PAS3.SLI$

OUT EXEC.PAS$
DMPFLST()$		% Construct EXECUTE table
SHUT EXEC.PAS$

OUT PAS3.INI$
DUMPINI()$
SHUT PAS3.INI$
QUIT$

Added perq-pascal-lisp-project/pas3.ini version [2e35c871bd].

cannot compute difference between binary files

Added perq-pascal-lisp-project/pas3.pas version [24344a2ccf].

cannot compute difference between binary files

Added perq-pascal-lisp-project/pas3.red version [c974fb7893].































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                     
% 		PASCAL BASED MINI-LISP
%
% File: 	PAS3.RED - Basic LISP Functions
% ChangeDate: 	10:48pm  Wednesday, 15 July 1981
% By: 		M. L. Griss
%       	Change to add Features for Schlumberger Demo
% 
% 	    All RIGHTS RESERVED
%           COPYRIGHT (C) - 1981 - M. L. GRISS
%           Computer Science Department
%           University of Utah
%
%           Do Not distribute with out written consent of M. L. Griss
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%. Tagged TCATCH and TTHROW In terms of CATCH and THROW

SYMBOLIC PROCEDURE TCATCH(TG,FORM);
 BEGIN SCALAR VAL;
     THROWING!* := NIL;
     VAL:=CATCH(FORM);
     IF NULL TG OR NULL THROWING!* THEN RETURN VAL;	% CatchALL
     IF THROWTAG!* EQ TG THEN RETURN VAL;
     THROW VAL;
 END;

SYMBOLIC PROCEDURE TTHROW(TG,VAL);
 <<THROWING!* := 'T;
   THROWTAG!* := TG;
   THROW VAL>>;

SYMBOLIC PROCEDURE GETD NAM;		%. Return (type.code) if func
  BEGIN SCALAR TY,V;
	IF NOT IDP NAM THEN RETURN NIL;
	TY:=GET(NAM,'TYPE);
	V:=FUNCELL NAM;
	IF NULL TY AND V THEN TY:='EXPR;
        IF V THEN RETURN (TY . V) ELSE RETURN NIL;
  END;

SYMBOLIC PROCEDURE PUTD(NAM,TY,BOD);	%. Make function entry
 IF FLAGP(NAM, 'LOSE) THEN
 <<  ERRPRT LIST(NAM,'not,'flagged,'LOSE); NAM >>
 ELSE BEGIN
	IF GETD(NAM) THEN MSGPRT LIST('Function,NAM,'redefined);
	IF (CODEP BOD OR EQCAR(BOD,'LAMBDA)
          AND TY MEMQ '(EXPR FEXPR NEXPR MACRO) )
 	 THEN <<IF TY EQ 'EXPR THEN TY:=NIL;
                PUT(NAM,'TYPE,TY);
	        SETFUNCELL(NAM,BOD)>>
          ELSE RETURN ERROR(99,LIST(NAM,'Cant,'be,'defined));
	RETURN NAM;
 END;

SYMBOLIC PROCEDURE REMD NAM;		%. Remove function defn
 BEGIN SCALAR PR;
	IF (PR:=GETD NAM) THEN <<SETFUNCELL(NAM,NIL);
				 REMPROP(NAM,'TYPE)>>;
	RETURN PR;
 END;


%. Convenient definitions

SYMBOLIC PROCEDURE PUTL(L,IND,VAL);
 IF NOT PAIRP L THEN NIL
  ELSE <<PUT(CAR L,IND,VAL);
         PUTL(CDR L,IND,VAL)>>;

SYMBOLIC FEXPR PROCEDURE DE L;
   PUTD(CAR L,'EXPR,'LAMBDA . CDR L);

SYMBOLIC FEXPR PROCEDURE DF L;
   PUTD(CAR L,'FEXPR,'LAMBDA . CDR L);

SYMBOLIC FEXPR PROCEDURE DN L;
   PUTD(CAR L,'NEXPR,'LAMBDA . CDR L);

SYMBOLIC FEXPR PROCEDURE DM L;
   PUTD(CAR L,'MACRO,'LAMBDA . CDR L);

%. d) Improved EVAL, with LAMBDA, FEXPR, etc

SYMBOLIC PROCEDURE EVAL(X);
 BEGIN SCALAR FN,A,TY;
 L:IF IDP(X) THEN RETURN VALUE(X)
    ELSE IF NOT PAIRP(X) OR (FN := CAR X) EQ 'LAMBDA THEN
	RETURN X;
    A := CDR X;                         % Arguments
    IF FN EQ 'QUOTE THEN		%Important special Fexprs
	RETURN CAR(A);
    IF FN EQ 'SETQ THEN RETURN SET(CAR A,EVAL CADR A);
    IF IDP FN AND (TY := GET(FN, 'TYPE)) THEN 
     <<IF TY EQ 'FEXPR THEN
           RETURN APPLY1(FN,A);   % No Spread, No EVAL
       IF TY EQ 'NEXPR THEN
        RETURN APPLY1(FN,EVLIS A); % No Spread, EVAL
       IF TY EQ 'MACRO               % Reval full form
          THEN  <<X := APPLY1(FN,X);  GOTO L >> >>;
       A := EVLIS A;
       IF FN EQ 'LIST THEN RETURN A;
       RETURN APPLY(FN,A);
END;

SYMBOLIC PROCEDURE APPLY1(FN,A);
 APPLY(FN, A . NIL);

SYMBOLIC PROCEDURE APPLY(FN,A);
 BEGIN SCALAR EFN;
    EFN := FUNCELL FN;
    IF CODEP EFN THEN RETURN XAPPLY(EFN,A); % Spread args and EXECUTE
    RETURN EVLAM(EFN,A);
END;

SYMBOLIC PROCEDURE EVLIS(L);
IF NOT PAIRP L THEN EVAL L
 ELSE EVAL(CAR L) . EVLIS(CDR L);

%. Some standard FEXPRS and MACROS

SYMBOLIC FEXPR PROCEDURE PROGN ARGS;	%. Evaluate a LIST
  P!.N ARGS;

SYMBOLIC PROCEDURE PROG2(A,B); B;

SYMBOLIC PROCEDURE P!.N ARGS;		%. EVALS elems of list and returns last
BEGIN SCALAR ANS;
   WHILE PAIRP ARGS DO <<ANS := EVAL CAR ARGS; ARGS:=CDR ARGS>>;
  RETURN ANS
END;

%.===== Section 3.7 =====	Program Feature functions

% All this stuff should be rewritten to use the same binding mechanism as
% compiled code, and obey the same constraints on placement of GO/RETURN
% as compiled code.

SYMBOLIC FEXPR PROCEDURE RETURN E;	%. Return From Current PROG
<< P!.P := NIL;
   TTHROW('!$PROG!$,P!.N E) >>;

SYMBOLIC FEXPR PROCEDURE GO E;		%. Go to label in Current PROG
BEGIN SCALAR L;
  E := CAR E;
  REPEAT <<
    WHILE NOT IDP E DO
      ERROR(1100,LIST(E,'Not,'Label));
    L := ATSOC(E,P!.G);
    IF ATOM L THEN
      ERROR(1101,LIST(E,'Not,'a,'label))>>
  UNTIL PAIRP L;
  P!.P := CDR L;
  TTHROW('!$PROG!$,NIL)
END;

SYMBOLIC FEXPR PROCEDURE PROG E;	%. Program feature interpreter
%  P!.P is Next SEXPR to EVAL
BEGIN SCALAR TG,X,V,NVALS,SAVEP,SAVEG;
  SAVEP:=P!.P;
  SAVEG:=P!.G;	% Note FLUIDS not yet working compiled
  NVALS :=LENGTH CAR E;
  PBINDN CAR E;	% Bind each to NIL, putting old value on BSTACK
  P!.P := CDR E; 
% The code body
  X := P!.P;
  P!.G := NIL;
  FOR EACH U ON P!.P DO
    IF IDP CAR U THEN
  P!.G := U . P!.G;
  THROWING!* := NIL;
  TG := '!$PROG!$;
  WHILE P!.P AND TG EQ '!$PROG!$ DO <<
    X := CAR P!.P;
    P!.P := CDR P!.P;
    IF NOT IDP X THEN <<
      X := TCATCH(NIL,X);
      IF THROWING!* THEN
	<<TG := THROWTAG!*; V:=X>>  >> >>;
% UNBIND Even if thrown through
  UNBINDN NVALS;
  P!.P := SAVEP;
  P!.G := SAVEG;
  IF NOT(TG EQ '!$PROG!$) THEN
    TTHROW(TG,V)
  ELSE
    RETURN V
END;


SYMBOLIC FEXPR PROCEDURE WHILE ARGS;	%. Simple WHILE LOOP
% Will do (WHILE bool s1 .. sn)
  BEGIN SCALAR BOOL;
	IF NOT PAIRP ARGS THEN RETURN NIL;
	BOOL:=CAR ARGS;
 L1:	IF NULL EVAL BOOL THEN RETURN NIL;
	P!.N CDR ARGS;
	GOTO L1
 END;


SYMBOLIC FEXPR PROCEDURE AND(X);	%. Xis list of actions
   BEGIN 
     IF NOT PAIRP X THEN RETURN(T);
 L:  IF NULL CDR(X) THEN RETURN(EVAL(CAR X))
      ELSE IF NULL EVAL(CAR X) THEN RETURN(NIL)
      ELSE << X:=CDR X; GOTO L >>
 END;

%/// Add also IF ?

SYMBOLIC FEXPR PROCEDURE COND(E);		%. Conditional eval
   BEGIN SCALAR PR,Y;
 L:  IF NOT PAIRP E THEN RETURN NIL;
     PR:=CAR E; E:=CDR E;
     IF PAIRP PR THEN Y:=CAR PR ELSE Y:=PR;
     IF NULL (Y:=EVAL(Y)) THEN GOTO L;
     IF NULL PAIRP PR OR NULL CDR PR THEN RETURN(Y);
     RETURN P!.N(CDR PR)
   END;

SYMBOLIC FEXPR PROCEDURE  OR(X);	%. Or of action list
   BEGIN SCALAR Y;
 L: IF NOT PAIRP X THEN RETURN(NIL)
     ELSE IF(Y:=EVAL(CAR X)) THEN RETURN(Y)
     ELSE << X:=CDR X;GOTO L >>
 END;

%.===== Section 3.12 =====	MAP composite functions

SYMBOLIC PROCEDURE MAP(X,FN); 		%. Apply FN to each cdr x
   WHILE X DO <<APPLY1(FN,X); X := CDR X>>;

SYMBOLIC PROCEDURE MAPC(X,FN); 		%. Apply FN to each car x
   WHILE X DO <<APPLY1(FN,CAR X); X := CDR X>>;

SYMBOLIC PROCEDURE MAPCAN(X,FN); 	%. Append FN car x
   IF ATOM X THEN NIL ELSE NCONC(APPLY1(FN,CAR X),MAPCAN(CDR X,FN));

SYMBOLIC PROCEDURE MAPCAR(X,FN); 	%. Collect FN car x
   IF ATOM X THEN NIL ELSE APPLY1(FN,CAR X) . MAPCAR(CDR X,FN);

SYMBOLIC PROCEDURE MAPCON(X,FN); 	%. Append FN cdr x
   IF ATOM X THEN NIL ELSE NCONC(APPLY1(FN,X),MAPCON(CDR X,FN));

SYMBOLIC PROCEDURE MAPLIST(X,FN); 	%. Collect FN cdr x
   IF ATOM X THEN NIL ELSE APPLY1(FN,X) . MAPLIST(CDR X,FN);

SYMBOLIC PROCEDURE NCONC(U,V); 		%. Tack V onto end U
   BEGIN SCALAR W; 
      IF ATOM U THEN RETURN V; 
      W := U; 
      WHILE PAIRP CDR W DO W := CDR W; 
      RPLACD(W,V); 
      RETURN U
   END;

%... This procedure drives a simple read/eval/print top loop.

SYMBOLIC PROCEDURE PUTC(X,Y,Z);
  PUT(X,Y,Z);

SYMBOLIC PROCEDURE FLUID L;
  L;

SYMBOLIC PROCEDURE PRIN2TL L;
 IF NOT PAIRP L THEN TERPRI()
  ELSE <<PRIN2 CAR L; PRIN2 '! ; PRIN2TL CDR L>>;
% ... Missing functions to complete Standard LISP set
% ... some dummies developed for PERQ, modified to better use PASLSP


SYMBOLIC PROCEDURE FLOATP X; NIL;

SYMBOLIC PROCEDURE STRINGP X; IDP X;

SYMBOLIC PROCEDURE VECTORP X; NIL;

SYMBOLIC PROCEDURE FLUIDP X; NIL;

SYMBOLIC PROCEDURE INTERN X; X;

SYMBOLIC PROCEDURE REMOB X; NIL;

SYMBOLIC PROCEDURE GLOBAL X; 
   WHILE X DO <<FLAG(X,'GLOBAL); X := CDR X>>;

SYMBOLIC PROCEDURE GLOBALP X; 
   FLAGP(X,'GLOBAL);

SYMBOLIC PROCEDURE UNFLUID X; 
   NIL;


% No vectors yet

SYMBOLIC PROCEDURE GETV(A,B); NIL;

SYMBOLIC PROCEDURE MKVECT X; NIL;

SYMBOLIC PROCEDURE PUTV(A,B,C); NIL;

SYMBOLIC PROCEDURE UPBV X; NIL;

SYMBOLIC PROCEDURE DIGIT X; NIL;

SYMBOLIC PROCEDURE LITER X; NIL;
 
SYMBOLIC PROCEDURE READCH X; NIL;  %/ Needs Interp Mod
 
SYMBOLIC PROCEDURE RDEVPR;
 WHILE T DO PRINT EVAL READ();

SYMBOLIC PROCEDURE DSKIN(FILE);
 BEGIN SCALAR TMP;
   TMP := RDS OPEN(FILE, 'INPUT);
   WHILE NULL EOFP PRINT EVAL READ() DO NIL; %Use RDEVPR ?
   CLOSE RDS TMP;
 END;

SYMBOLIC PROCEDURE !*FIRST!-PROCEDURE;
BEGIN SCALAR X, EOFFLG, OUT;
    PRIN2TL '(Pascal  LISP  V2 !- 15 Feb 1982);
    PRIN2TL '(Copyright (c) 1981 U UTAH);
    PRIN2TL '(All  Rights  Reserved);
    NEXPRS:='(LIST);
    PUTL(NEXPRS,'TYPE,'NEXPR);
    PROCS:='(EXPR FEXPR NEXPR MACRO);
    EOFFLG := NIL;
    % Continue reading Init-File on channel 1;
    WHILE NOT EOFFLG DO
    <<  X := READ();
        EOFFLG := EOFP(X);
	IF NOT EOFFLG THEN
	    EVAL X
    >>;
    RDS(2); % Switch to USER input, THE TTY
    EOFFLG := NIL;
    WHILE NOT EOFFLG DO
      <<OUT := WRS 3; PRIN2 '!>; WRS OUT; % Prompt, OUT holds channel #
        X := READ();
        IF EQCAR(X,'QUIT) THEN EOFFLG := 'T ELSE EOFFLG := EOFP(X);
	IF NOT EOFFLG THEN
	  PRIN2T(CATCH X)
      >>;
    PRIN2T LIST('EXITING,'Top,'Loop);
END;

END;

Added perq-pascal-lisp-project/pas3.sli version [526dcaeccc].

cannot compute difference between binary files

Added perq-pascal-lisp-project/pas3.sym version [ebdc7c9092].

cannot compute difference between binary files

Added perq-pascal-lisp-project/pasasm.pat version [387a720058].





















































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
%Patterns for Lisp to Pascal compilation.  
% Taken from  FORTRAN version
%"system" lisp to Fortran work: "SYSASM.PAT".
%
%Version of 4:23pm  Monday, 13 October 1980.

LISP$ OFF ECHO$ OFF RAISE$

OFF COMP;
ON SYSLISP;

% Very optimized with inline consts, etc.

RULEBLOCK (PAS2,

'(!*ENTRY &1 &2 &3)->
  (BEGIN
	NALLOC:=0;
	W "(*  ",&2," ",&1," *)"$
	W "procedure ",MAPFUN &1,";"$
	DCLRLABELS();		%Declare the labels generated for this routine.
	W "begin";
  RETURN T END),

% Exit VS end of procedure?  Works now since we suppress !*LINKE.
'(!*EXIT)->	
  (BEGIN
	W "end;";
  RETURN T END),

'(!*ALLOC 0)->		T,

'(!*ALLOC 1)->
  (BEGIN
	W "    alloc1;" $
	NALLOC:=1;
  RETURN T END),

'(!*ALLOC 2)->
  (BEGIN
	W "    alloc2;" $
	NALLOC:=2;
  RETURN T END),

'(!*ALLOC 3)->
  (BEGIN
	W "    alloc3;" $
	NALLOC:=3;
  RETURN T END),

'(!*ALLOC &1)->
  (BEGIN
	W "    alloc(",&1,");" $
	NALLOC:=&1;
  RETURN T END),

'(!*DEALLOC 0)->
	<<NALLOC:=0;T>>,

'(!*DEALLOC 1)->
	<<NALLOC:=0;
	  W "      dealloc1;" $
	  T>>,

'(!*DEALLOC 2)->
	<<NALLOC:=0;
	  W "      dealloc2;" $
	T>>,

'(!*DEALLOC 3)->
	<<NALLOC:=0;
	  W "      dealloc3;" $
	T>>,

'(!*DEALLOC &1)->
	<<NALLOC:=0;
	IF &1 NEQ 0 THEN W "      dealloc(",&1,");" $
	T>>,

'(!*LINK &1 &2 &3)->		
  (BEGIN SCALAR X$
	IF X:=GET(&1,'OPENCOD) THEN
	<<% Has OPENCOD form, no retadr needed
	    WLST X$
	    RETURN T$
	>>
	ELSE
	<<
	    W "     ",MAPFUN &1,";";	% simply invoke as proc;
	    RETURN T$
	>>$
 END),

% Suppress LINKE by using ON NOLINKE;
%'(!*LINKE &1 &2 &3 &4)->  NOTHING!

'(!*LOAD 1 0)->
	<<W "      load10;";
	  T>>,

'(!*LOAD &1 &2)->
	(BEGIN SCALAR Y;
	IF &1 NEQ &2 THEN Y:=LOADIT(&1,&2)$   %LOADIT may emit some code.
	IF (REGNAM &1) NEQ Y THEN
	    IF NUMBERP(&1) AND NUMBERP(&2) AND (&2 <= 0) THEN
		W "      load(", &1 , "," , -&2 , ");"
	    ELSE
		W "      ",REGNAM &1," := ",Y,";" $
	RETURN T END),

'(!*MOVE &1 &2) -> % Need to FIX so RXX not used as much.  If no YY then
  (BEGIN SCALAR V1,V2;
	IF &1 EQ &2 THEN RETURN T$
	IF(V1:=EASYSTORE(&1)) THEN
          RETURN <<STOREIT('XX,&2,V1);T>>$
        V2:=LOADIT('XX,&2);
        V1:=LOADIT('YY,&1);
	W "       ",V1," := ",V2,";"$
   RETURN T END),

%**********   Delete--not needed?
%'(!*PUTARR &1 &2 &3) ->
% (BEGIN SCALAR V1,V2;
%	V1:=LOADIT('XX,&2);
%	V2:=LOADIT('YY,&3);
%	W "       ",&1,"(",V1,")=",V2$
%  RETURN T END),
%**********

'(!*STORE 1 0)->
	<<W "      store10;";
	  T>>,

'(!*STORE &1 (FLUID &2))->	PAS2 LIST('!*STORE,&1,LIST('GLOBAL,&2)),

'(!*STORE &1 (GLOBAL &2))->
  (BEGIN SCALAR V;
	IF !*SYSLISP THEN
	    W "      ",WSYSEVAL &2,":=",REGNAM &1,";"
	ELSE
	<<  V :=FNDID &2;
	    W "      idspace[",V,"].val := ",REGNAM &1,";">>$
  RETURN T END),

'(!*STORE NIL &1)->
	<< W "      storenil(", -&1 , ");" ;
	   T>>,

'(!*STORE &1 &2)->
	<<IF NUMBERP(&1) AND NUMBERP(&2) AND (&2 <=0 ) THEN
	    W "      store(", &1 , "," , -&2 , ");"
	  ELSE
	    W "      stk[st",&2,"] := ",REGNAM &1,";"$
	  T>>,

'(!*LBL &1)->	<<W MAPLBL &1,": "$ T>>,

'(!*JUMP &1)->	<<W "      GOTO ",MAPLBL &1,";"$ T>>,

%Delete? --> MAP to CASE?/MLG
'(!*JUMPTABLE &1)->
   <<	W "       JMPIT=R[1]+1"$
	W "       IF((JMPIT.LE.0).OR.(R[1].GE.",LENGTH &1,"))GOTO ",MAPLBL CAR &1;
	WX "      GOTO(",LBLLST CDR &1,")JMPIT"$ T>>,

'(!*JUMPE &1 &2)->
  (BEGIN SCALAR V;
	V:=LOADIT('XX,&2)$
	W "      IF R[1]=",V," THEN GOTO ",MAPLBL &1,";"$
  RETURN T END),

'(!*JUMPN &1 &2)->
  (BEGIN SCALAR V;
	V:=LOADIT('XX,&2)$
	W "      IF R[1] <> ",V," THEN GOTO ",MAPLBL &1,";"$
  RETURN T END),

'(!*JUMPWEQ &1 &2)->
  (BEGIN SCALAR V;
	V:=LOADIT('XX,&2)$
	W "      IF R[1]=",V," THEN GOTO ",MAPLBL &1,";"$
  RETURN T END),

'(!*JUMPWNE &1 &2)->
  (BEGIN SCALAR V;
	V:=LOADIT('XX,&2)$
	W "      IF info_of(R[1]) <> info_of(",V,") THEN GOTO ",MAPLBL &1,";"$
  RETURN T END),

'(!*JUMPWG &1 &2)->
  (BEGIN SCALAR V;
	V:=LOADIT('XX,&2)$
	W "      IF info_of(R[1]) > info_of(",V,") THEN GOTO ",MAPLBL &1,";"
  RETURN T END),

'(!*JUMPWGE &1 &2)->
  (BEGIN SCALAR V;
	V:=LOADIT('XX,&2)$
	W "      IF info_of(R[1]) >= info_of(",V,") THEN GOTO ",MAPLBL &1,";"
  RETURN T END),

'(!*JUMPWL &1 &2)->
  (BEGIN SCALAR V;
	V:=LOADIT('XX,&2)$
	W "      IF info_of(R[1]) < info_of(",V,") THEN GOTO ",MAPLBL &1,";"
  RETURN T END),

'(!*JUMPWLE &1 &2)->
  (BEGIN SCALAR V;
	V:=LOADIT('XX,&2)$
	W "      IF info_of(R[1]) <= info_of(",V,") THEN GOTO ",MAPLBL &1,";" $
  RETURN T END),

'(!*JUMPT &1)->
  <<W "      IF R[1] <> nilref THEN GOTO ",MAPLBL &1,";"; T>>,

'(!*JUMPNIL &1)->
  <<W "      IF R[1] = nilref THEN GOTO ",MAPLBL &1,";"; T>>,

% !*TEST stuff has been replaced by !*JUMPC and !*JUMPNC stuff.
% Form is (!*JUMPC LABL REG TYPE)
'(!*JUMPNC &1 &2 ATOM)->PAS2 LIST('!*JUMPC,&1,&2,'PAIRTAG),

'(!*JUMPC &1 &2 ATOM)->	PAS2 LIST('!*JUMPNC,&1,&2,'PAIRTAG),

'(!*JUMPC &1 &2 NUMTAG)->
  <<W "      IF (tag_of(",REGNAM &2,") = INTTAG)"$
    W "       or (tag_of(",REGNAM &2,") = FIXTAG) THEN GOTO ",MAPLBL &1,";" $
    T>>,

'(!*JUMPNC &1 &2 NUMTAG)->
  <<W "      IF not((tag_of(",REGNAM &2,") = INTTAG)"$
    W "       or (tag_of(",REGNAM &2,") = FIXTAG)) THEN GOTO ",MAPLBL &1,";" $
    T>>,

'(!*JUMPC &1 &2 &3)->
  <<W "      IF tag_of(",REGNAM &2,") = ",&3," THEN GOTO ",MAPLBL &1,";" $
    T>>,

'(!*JUMPNC &1 &2 &3)->
  <<W "      IF tag_of(",REGNAM &2,") <> ",&3," THEN GOTO ",MAPLBL &1,";" $
    T>>,

'(!*FREERSTR &1)->	<<W "      UNBIND(",LENGTH &1,");"$T>>,

'(!*PROGBIND &1)->	
  (BEGIN SCALAR Y$
	FOR EACH X IN &1 DO
	 <<FNDID CAR X$
	W "      PBIND(",-CADR X,!, ,V,");" $T>>$
  RETURN T END),

'(!*LAMBIND &1 &2)->	
  (BEGIN SCALAR X,Y$
	X:=&1$ Y:=&2$
	WHILE X DO
	 <<FNDID CAAR Y$
	   W "      LBIND(",REGNAM CAR X,!,,-CADAR Y,!,,V,");"$
	   X:=CDR X$ Y:=CDR Y>>$
  RETURN T END),

'( &1 &2 BASE &3 WORDS &4 LEFT )-> T,

'(!*CHECK &1 &2 &3) ->
  <<W "       IF tag_of(",REGNAM &1,") <> ",&2,"THEN GOTO ",MAPLBL &3,";"$ T>>,

'(!*CODE &1) -> <<W &1; T>>,

'(!*EVAL &1) -> <<EVAL &1; T>>,

&1->	<<WX "1*** Unknown ",&1," ***** "$T>> )$


PUT('CAAR,'CARCDRFN,'(CAR . CAR))$
PUT('CDAR,'CARCDRFN,'(CDR . CAR))$
PUT('CADR,'CARCDRFN,'(CAR . CDR))$
PUT('CDDR,'CARCDRFN,'(CDR . CDR))$
PUT('CAAAR,'CARCDRFN,'(CAAR . CAR))$
PUT('CADAR,'CARCDRFN,'(CADR . CAR))$
PUT('CAADR,'CARCDRFN,'(CAAR . CDR))$
PUT('CADDR,'CARCDRFN,'(CADR . CDR))$
PUT('CDAAR,'CARCDRFN,'(CDAR . CAR))$
PUT('CDDAR,'CARCDRFN,'(CDDR . CAR))$
PUT('CDADR,'CARCDRFN,'(CDAR . CDR))$
PUT('CDDDR,'CARCDRFN,'(CDDR . CDR))$
PUT('CAAAAR,'CARCDRFN,'(CAAAR . CAR))$
PUT('CAADAR,'CARCDRFN,'(CAADR . CAR))$
PUT('CAAADR,'CARCDRFN,'(CAAAR . CDR))$
PUT('CAADDR,'CARCDRFN,'(CAADR . CDR))$
PUT('CADAAR,'CARCDRFN,'(CADAR . CAR))$
PUT('CADDAR,'CARCDRFN,'(CADDR . CAR))$
PUT('CADADR,'CARCDRFN,'(CADAR . CDR))$
PUT('CADDDR,'CARCDRFN,'(CADDR . CDR))$
PUT('CDAAAR,'CARCDRFN,'(CDAAR . CAR))$
PUT('CDADAR,'CARCDRFN,'(CDADR . CAR))$
PUT('CDAADR,'CARCDRFN,'(CDAAR . CDR))$
PUT('CDADDR,'CARCDRFN,'(CDADR . CDR))$
PUT('CDDAAR,'CARCDRFN,'(CDDAR . CAR))$
PUT('CDDDAR,'CARCDRFN,'(CDDDR . CAR))$
PUT('CDDADR,'CARCDRFN,'(CDDAR . CDR))$
PUT('CDDDDR,'CARCDRFN,'(CDDDR . CDR))$


% Some of the OPEN coded functions;
% Take a LIST of strings, operating on R[1],R[2],...;


PUT('!*INF,'OPENCOD,'("      mkitem(INTTAG,info_of(R[1]),R[1]);"));
PUT('!*TAG,'OPENCOD,'("      mkitem(INTTAG,tag_of(R[1]),R[1]);"));

PUT('!*MKITEM,'OPENCOD,'("      mkitem(tag_of(R[1]),info_of(R[2]),R[1]);"));
PUT('!*INTINF,'OPENCOD,'("      mkitem(INTTAG,info_of(R[1]),R[1]);"));

%Only appropriate for systems lisp.  Solution used here is questionable.
PUT('!*WPLUS2,'OPENCOD,'("       R[1].info:=R[1].info+R[2].info;"));
PUT('!*WDIFFERENCE,'OPENCOD,'("       R[1].info:=R[1].info-R[2].info;"));
PUT('!*WADD1,'OPENCOD,'("       R[1].info:=R[1].info+1;"));
PUT('!*WSUB1,'OPENCOD,'("       R[1].info:=R[1].info-1;"));
PUT('!*WMINUS,'OPENCOD,'("       R[1].info:=-R[1].info;"));
PUT('!*WTIMES2,'OPENCOD,'("       R[1].info:=R[1].info*R[2].info;"));
PUT('!*WQUOTIENT,'OPENCOD,'("       R[1].info:=R[1].info div R[2].info;"));
PUT('!*WREMAINDER,'OPENCOD,'("       R[1].info:=R[1].info mod R[2].info;"));

%NEED support functions for these!
PUT('!*WAND,'OPENCOD,'("       R[1].info:=land(R[1].info, R[2].info);"));
PUT('!*WOR,'OPENCOD, '("       R[1].info:=lor(R[1].info, R[2].info);"));
PUT('!*WXOR,'OPENCOD,'("       R[1].info:=lxor(R[1].info, R[2].info);"));
PUT('!*WNOT,'OPENCOD,'("       R[1].info:=not R[1].info;"));

END$

Added perq-pascal-lisp-project/paslsp-20.bld version [dab79eac6a].











































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
; Command file to assemble PASn pieces together and then compile them.
; for Dec-20 version
;
COP PAS3.INI PASLSP.INI
APP PAS1.SLI PASLSP.INI
APP PAS2.SLI PASLSP.INI
APP PAS3.SLI PASLSP.INI
APP USER.SLI PASLSP.INI
filter d <pas0.pre >s:pl20.pas
append pas1.pas S:PL20.PAS
append pas2.pas S:PL20.PAS
append pas3.pas S:PL20.PAS
append exec.pas S:PL20.PAS
filter d <pasn.pre >s:pl20n.pas
append s:pl20n.pas S:PL20.PAS
pascal
S:PL20.rel
S:PL20.lst
S:PL20.PAS
load S:PL20.REL
save S:PL20.EXE

Added perq-pascal-lisp-project/paslsp-apollo.bld version [5513d23b7a].































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
; Command file to assemble PASn pieces together
; Apollo version
;
COP PAS3.INI PASLSP.INI
APP PAS1.SLI PASLSP.INI
APP PAS2.SLI PASLSP.INI
APP PAS3.SLI PASLSP.INI
APP USER.SLI PASLSP.INI
filter a <pas0.pre >s:plA.pas
append pas1.pas S:PLA.PAS
append pas2.pas S:PLA.PAS
append pas3.pas S:PLA.PAS
append exec.pas S:PLA.PAS
filter a <pasn.pre >s:plAn.pas
append S:plAn.pas S:PLA.PAS

Added perq-pascal-lisp-project/paslsp-ini-read.red version [d62b49912c].

























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
% File to read PASLSP.INI to produce sorted tables

FLUID '(NID!* IDLIST!* NCONST!* CONSTLIST!* NFN!* FNLIST!*);

lisp procedure IniErr x;
  Error LIST("Bad Ini File ",x);

load gsort;

lisp procedure prinl l;
 for each x in l do print x;

lisp procedure Sorts;
 Begin					
     ReadPaslspInit();
     Prin2t "--------------- Functions ----------------";
     prinl idsort FNLIST!*;
     Prin2t "--------------- Other IDS ----------------";
     prinl idsort IDLIST!*;
     Prin2t "--------------- CONST ----------------";
     prinl CONSTLIST!*;
 End;

lisp procedure ReadPaslspInit;
  BEGIN scalar infil,oldfil;
	% load "symbol table" with identifiers, constants, and functions.  
      infil:=open("paslsp.ini",'input);
      oldfil:=rds(infil);
      NID!*:=RATOM();     % get count of identifiers. 
      IF not fixp NID!* THEN
	    IniErr("*****BAD SYMBOL TABLE, INTEGER EXPECTED AT START");
      IDLIST!*:=NIL;
      FOR i :=  1:NID!* DO
	    IDLIST!* := RATOM() . IDLIST!*;
	% reading token magically loads it into id space. 
	IF not ZeroP RATOM()         % look for zero terminator. 
           then
	    IniErr("*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER IDENTIFIERS");
	NCONST!*:=RATOM();         % count of constants  
	IF not FIXP NCONST!* THEN
          IniErr("*****BAD SYMBOL TABLE, INTEGER EXPECTED BEFORE CONSTANTS");
        CONSTLIST!*:=NIL;
	FOR i := 1:NCONST!* DO
	  CONSTLIST!*:=READ() . CONSTLIST!*;
	IF  not ZeroP RATOM() then
         IniErr("*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER CONSTANTS");

	NFN!*:=RATOM();     % count of functions. 
	IF  not FIXP NFN!* then
	   IniErr("*****BAD SYMBOL TABLE, INTEGER EXPECTED BEFORE FUNCTIONS");
	FNLIST!*:=NIL;
	FOR i := 1:NFN!* DO
	    % for each function 
	    % store associated code 
	    FNLIST!*:=RATOM(). FNLIST!*;
	If not Zerop RATOM() then
         IniErr("*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER FUNCTIONS");
        RDS(oldfil);
	CLOSE infil;
  END;

Added perq-pascal-lisp-project/paslsp-perq.bld version [309a05ecb4].



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
; Command file to assemble PASn pieces together and then compile them.
def s: <scratch>
def pl: <griss.PASLSP>
; produces PERQ  version.
COP pl:PAS3.INI s:PLPERQ.INI
APP pl:PAS1.SLI s:PLPERQ.INI
APP pl:PAS2.SLI s:PLPERQ.INI
APP pl:PAS3.SLI s:PLPERQ.INI
APP pl:USER.SLI s:PLPERQ.INI
pl:filter p  <pl:pas0.pre >s:PlPerq.pas
pl:filter p  <pl:pasn.pre >s:PlPerqn.pas
append pl:pas1.pas S:PLPERQ.pas
append pl:pas2.pas S:PLPERQ.pas
append pl:pas3.pas S:PLPERQ.pas
append pl:exec.pas S:PLPERQ.pas
append s:PlPerqN.pas S:PLPERQ.pas
; Send S:PlPerq.ini S:PlPerq.pas

Added perq-pascal-lisp-project/paslsp-terak.bld version [9f102df688].































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
; Command file to assemble PASn pieces together and then compile them.
; for Terak-20 version
;
COP PAS3.INI PASLSP.INI
APP PAS1.SLI PASLSP.INI
APP PAS2.SLI PASLSP.INI
APP PAS3.SLI PASLSP.INI
APP USER.SLI PASLSP.INI
filter t <pas0.pre >s:plt.pas
append pas1.pas S:PLT.PAS
append pas2.pas S:PLT.PAS
append pas3.pas S:PLT.PAS
append exec.pas S:PLT.PAS
filter t <pasn.pre >s:pltn.pas
append s:pltn.pas S:PLT.PAS

Added perq-pascal-lisp-project/paslsp-test.photo version [79355f38f7].





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890

[PHOTO:  Recording initiated  Mon 15-Feb-82 5:11PM]

LINK FROM CAI.OTTENHEIMER, TTY 102

 TOPS-20 Command processor 4(714)-2
@PLJJS:PL20

PASCAL LISP V2 - 15 NOV 1981 
COPYRIGHT (C) 1981 U UTAH 
ALL RIGHTS RESERVED 
UserInitStart
UserInitEnd
>(*JSETQ *!RAISE T)
NIL
>(SETQ !*RAISE T)
T
>(SETQ !*ECHO T)
T
>(DSKIN "PASLSP>TSTJJJJ.TST")
%%%%%%%%%%%%  Standard - LISP Verification file. %%%%%%%%%%%%%%%%%%%%%%%
%
% Copyright (C) M. Griss and J. Marti, February 1981
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



% Flags for SYSLISP based PSL


(SETQ !*ECHO T)T

(SETQ FZERO (FLOAT 0))0

(SETQ FONE (FLOAT 1))1


%  The following should return T:
TT
  
(NULL NIL)T
 
(COND (T T))T
 
(COND (NIL NIL) (T T))T
 
%  The following should return NIL:
NILNIL
 
(NULL T)NIL
 
(COND (T NIL))NIL
 
(COND (NIL T) 
      (T NIL))NIL
 
%  The following should be 0
00
 (QUOTE 0)0
 
%  The following minimum set of functions must work:
%   PUTD, PROG, SET, QUOTE, COND, NULL, RETURN, LIST, CAR, CDR, 
%   EVAL, PRINT, PRIN1, TERPRI, PROGN, GO.
%  Check PUTD, GETD, LAMBDA 
(PUTD (QUOTE FOO) (QUOTE EXPR) (QUOTE (LAMBDA (X) 3)))FOO

% Expect (EXPR LAMBDA (X) 3)
(GETD (QUOTE FOO))(EXPR LAMBDA (X) 3)

%  Should return 3
(FOO 1)3

(FOO 2)3

%  Test SET :
(SET (QUOTE A) 1)1

A1

(SET (QUOTE B) 2)2

B2

%  Test LIST, CAR, CDR  
%  Expect (1 2 3 4) 1 and (2 3 4) 
(SET (QUOTE A) (LIST 1 2 3 4))(1 2 3 4)

(CAR A)1

(CDR A)(2 3 4)

% Test REDEFINITION in PUTD, PROGN, PRIN1, TERPRI 
(PUTD (QUOTE FOO) (QUOTE EXPR) 
      (QUOTE (LAMBDA (X) (PROGN (PRIN1 X) (TERPRI)))))*** (FUNCTION FOO REDEFINE
D)
FOO

%  expect 1 and 2 printed , value NIL
(FOO 1)1
NIL

(FOO 2)2
NIL

%  Test simple PROG, GO, RETURN 
(PROG NIL (PRINT 1) (PRINT 2))1 
2
NIL

(PROG (A) (PRINT A) (PRINT 1))NIL
1
NIL

% Now test GO, RETURN, PROG binding
(SET 'A 'AA)AA
 (SET 'B 'BB)BB

(PROG (A B) (PRINT 'test! binding! of! A!,! B! expect! NIL)
            (PRIN1 A) (PRINT B) 
            (PRINT 'Reset! to! 1!,2)
            (SET 'A 1) (SET 'B 2)
               (PRIN1 A) (PRINT B)
            (PRINT 'test! forward! GO)
               (GO LL)
               (PRINT 'forward! GO! failed)
LL            (PRINT 'Forward! GO! ok)
            (GO L2)
L1        (PRINT '! Should! be! after! BACKWARD! go ) 
        (PRINT '! now! return! 3)
        (RETURN 3)
L2        (PRINT 'Test! backward! GO)
        (GO L1) )TEST BINDING OF A, B EXPECT NIL
NILNIL
RESET TO 1,2
12
TEST FORWARD GO
FORWARD GO OK
TEST BACKWARD GO
 SHOULD BE AFTER BACKWARD GO
 NOW RETURN 3
3

% Test that A,B correctly rebound, expect AA and BB% 
AAA
 BBB

%  Test simple FEXPR% 
(PUTD (QUOTE FOO) (QUOTE FEXPR) (QUOTE (LAMBDA (X) (PRINT X))))*** (FUNCTION FOO
 REDEFINED)
FOO 

% Expect (FEXPR LAMBDA (X) (PRINT X))% 
(GETD (QUOTE FOO))(FEXPR LAMBDA (X) (PRINT X))

%  Expect (1) (1 2) and (1 2 3)% 
(FOO 1)(1)
(1)

(FOO 1 2)(1 2)
(1 2)

(FOO 1 2 3)(1 2 3)
(1 2 3)

%  Finally, TEST EVAL inside an FEXPR % 
(PUTD (QUOTE FOO) (QUOTE FEXPR)
  (QUOTE (LAMBDA (XX) (PRINT (EVAL (CAR XX))))))*** (FUNCTION FOO REDEFINED)
FOO

(FOO 1)1
1
 
(FOO (NULL NIL))T
T

%  PUTD is being used here to define a function !$TEST.%  
(PUTD (QUOTE !$TEST) (QUOTE FEXPR) (QUOTE 
  (LAMBDA (!$X) 
   (PROG (A B) 
     (SET (QUOTE A) (CDR !$X)) 
LOOP (while A (progn
         %  (print (list 'trying (car a)))
           (SET (QUOTE B) (EVAL (CAR A)))
           (COND ( (null (eq b T)) 
            (PROGN (PRIN1 (LIST '!*!*!*!*!*  (CAR A) '! returned B)) 
                   (TERPRI)))) 
     (SET (QUOTE A) (CDR A)) 
     (GO LOOP)))
     (return (LIST (CAR !$X) '! test! complete)) 
           ))))$TEST
 
% $TEST should be defined.
(GETD (QUOTE !$TEST))(FEXPR LAMBDA ($X) (PROG (A B) (SET (QUOTE A) (CDR $X)) LOO
P (WHILE A (PROGN (SET (QUOTE B) (EVAL (CAR A))) (COND ((NULL (EQ B T)) (PROGN ( 
PRIN1 (LIST (QUOTE *****) (CAR A) (QUOTE  RETURNED) B)) (TERPRI)))) (SET (QUOTE 
A) (CDR A)) (GO LOOP))) (RETURN (LIST (CAR $X) (QUOTE  TEST COMPLETE)))))
 
%  Global, vector, function-pointer partial test.
(!$TEST 'GLOBAL!,VECTOR (NULL (GLOBAL (QUOTE (!$VECTOR !$CODE TEMP)))) 
     (GLOBALP (QUOTE !$VECTOR)) 
     (GLOBALP (QUOTE !$CODE)) 
     (SET (QUOTE !$VECTOR) (MKVECT 4)) 
     (SET (QUOTE !$CODE) (CDR (GETD (QUOTE CDR)))) )(***** (GLOBALP (QUOTE $VECT
OR))  RETURNED (GLOBAL))
(***** (GLOBALP (QUOTE $CODE))  RETURNED (GLOBAL))
(***** (SET (QUOTE $VECTOR) (MKVECT 4))  RETURNED NIL)
(***** (SET (QUOTE $CODE) (CDR (GETD (QUOTE CDR))))  RETURNED  ##89)
((QUOTE GLOBAL,VECTOR)  TEST COMPLETE)
 
 
 
(!$TEST LIST (EQUAL (LIST 1 (QUOTE A) 'STRING ) 
                    (QUOTE (1 A STRING))))(LIST  TEST COMPLETE)
 

% -----3.1 Elementary Predicates-----%   
% This section tests the elementary predicates of section 3.1 of 
% the Standard LISP Report. In general they will test that the 
% predicate returns non-NIL for the correct case, and NIL for all 
% others.  
 
% CODEP should not return T for numbers as function 
% pointers must not be implemented in this way.  
(!$TEST CODEP (CODEP !$CODE) (NULL (CODEP 1)) 
     (NULL (CODEP T)) (NULL (CODEP NIL)) 
     (NULL (CODEP (QUOTE IDENTIFIER))) 
     (NULL (CODEP 'STRING)) (NULL (CODEP (QUOTE (A . B)))) 
     (NULL (CODEP (QUOTE (A B C)))) 
     (NULL (CODEP !$VECTOR)) )(CODEP  TEST COMPLETE)
 
 
% PAIRP must not return T for vectors even if vectors are 
% implemented as lists.  
(!$TEST PAIRP 
     (PAIRP (QUOTE (A . B))) (PAIRP (QUOTE (NIL))) 
     (PAIRP (QUOTE (A B C))) (NULL (PAIRP 0)) 
     (NULL (PAIRP (QUOTE IDENTIFIER))) 
     (NULL (PAIRP 'STRING))  
     (NULL (PAIRP !$VECTOR)) )(PAIRP  TEST COMPLETE)
 
 
(!$TEST FIXP (FIXP 1) 
     (NULL (FIXP (QUOTE IDENTIFIER))) 
     (NULL (FIXP (QUOTE 'STRING))) 
     (NULL (FIXP (QUOTE (A . B)))) 
     (NULL (FIXP (QUOTE (A B C)))) 
     (NULL (FIXP !$VECTOR)) 
     (NULL (FIXP !$CODE))  )(FIXP  TEST COMPLETE)
 
 
% T and NIL must test as identifiers as must specially 
% escaped character identifiers.  
(!$TEST IDP (IDP (QUOTE IDENTIFIER)) 
     (IDP NIL)  (IDP T) 
     (IDP (QUOTE !1)) (IDP (QUOTE !A)) (IDP (QUOTE !!)) 
     (IDP (QUOTE !()) (IDP (QUOTE !))) (IDP (QUOTE !.)) 
     (IDP (QUOTE !')) (IDP (QUOTE !*)) (IDP (QUOTE !/)) 
     (IDP (QUOTE !+)) (IDP (QUOTE !-)) (IDP (QUOTE !#)) 
     (IDP (QUOTE ! )) (IDP (QUOTE !1!2!3)) (IDP (QUOTE !*!*!*)) 
     (IDP (QUOTE !'ID))  
     (NULL (IDP 1)) 
     (NULL (IDP 'STRING)) 
     (NULL (IDP (QUOTE (A . B)))) 
     (NULL (IDP (QUOTE (A B C)))) 
     (NULL (IDP !$VECTOR)) 
     (NULL (IDP !$CODE)) )(***** (NULL (IDP (QUOTE STRING)))  RETURNED NIL)
(***** (NULL (IDP $VECTOR))  RETURNED NIL)
(IDP  TEST COMPLETE)
 
 
% STRINGP should answer T to strings only and not things 
% that might look like strings if the system implements them as 
% identifiers.  
(!$TEST STRINGP (STRINGP 'STRING) 
     (NULL (STRINGP (QUOTE (STRING NOTASTRING)))) 
     (NULL (STRINGP 1)) 
     (NULL (STRINGP (QUOTE A))) 
     (NULL (STRINGP (QUOTE (A . B)))) 
     (NULL (STRINGP (QUOTE (A B C)))) 
     (NULL (STRINGP !$VECTOR)) 
     (NULL (STRINGP !$CODE)) )(***** (NULL (STRINGP (QUOTE A)))  RETURNED NIL)
(***** (NULL (STRINGP $VECTOR))  RETURNED NIL) 
(STRINGP  TEST COMPLETE)
 
 
% VECTORP should not answer T to pairs if vectors are 
% implemented as pairs.  
(!$TEST VECTORP (VECTORP !$VECTOR) 
     (NULL (VECTORP 1)) 
     (NULL (VECTORP (QUOTE A))) 
     (NULL (VECTORP 'STRING)) 
     (NULL (VECTORP (QUOTE (A . B)))) 
     (NULL (VECTORP (QUOTE (A B C)))) 
     (NULL (VECTORP !$CODE)) )(***** (VECTORP $VECTOR)  RETURNED NIL)
(VECTORP  TEST COMPLETE)
 
 
% Vectors are constants in Standard LISP. However T and NIL 
% are special global variables with the values T and NIL.  
(!$TEST CONSTANTP (CONSTANTP 1) 
     (CONSTANTP 'STRING) 
     (CONSTANTP !$VECTOR) 
     (CONSTANTP !$CODE) 
     (NULL (CONSTANTP NIL))  
     (NULL (CONSTANTP T)) 
     (NULL (CONSTANTP (QUOTE A))) 
     (NULL (CONSTANTP (QUOTE (A . B)))) 
     (NULL (CONSTANTP (QUOTE (A B C)))) )(***** (CONSTANTP (QUOTE STRING))  RETU
RNED NIL)
(***** (CONSTANTP $VECTOR)  RETURNED NIL)

***GARBAGE COLLECTOR CALLED
CONSES:        3699
ST    :          58
        3465 PAIRS FREED.
         234 PAIRS IN USE.
MAX GC STACK WAS            5
(CONSTANTP  TEST COMPLETE)
 
 
% An ATOM is anything that is not a pair, thus vectors are 
% atoms.  
(!$TEST ATOM (ATOM T) (ATOM NIL) (ATOM 1) (ATOM 0) 
     (ATOM 'STRING) (ATOM (QUOTE IDENTIFIER)) 
     (ATOM !$VECTOR) 
     (NULL (ATOM (QUOTE (A . B))))  
     (NULL (ATOM (QUOTE (A B C)))) )(ATOM  TEST COMPLETE)
 
 
 
(!$TEST EQ (EQ NIL NIL) (EQ T T) 
     (EQ !$VECTOR !$VECTOR) 
     (EQ !$CODE !$CODE) 
     (EQ (QUOTE A) (QUOTE A)) 
     (NULL (EQ NIL T)) 
     (NULL (EQ NIL !$VECTOR)) 
     (NULL (EQ (QUOTE (A . B)) (QUOTE (A . B)))) )(***** (NULL (EQ NIL $VECTOR))
  RETURNED NIL)
(EQ  TEST COMPLETE)
 
 
% Function pointers are not numbers, therefore the function 
% pointer $CODE is not EQN to the fixed number 0. Numbers must have 
% the same type to be EQN.  
(!$TEST EQN (EQN 1 1) (EQN 0 0) 
     (EQN FONE FONE)  (EQN FZERO FZERO) 
     (NULL (EQN FONE FZERO)) (NULL (EQN FZERO FONE)) 
     (NULL (EQN 1 FONE)) (NULL (EQN 0 FZERO))  
     (NULL (EQN 1 0)) (NULL (EQN 0 1)) 
     (NULL (EQN 0 !$CODE)) 
     (NULL (EQN NIL 0)) 
     (EQN NIL NIL)  (EQN T T) (EQN !$VECTOR !$VECTOR) 
     (EQN !$CODE !$CODE) (EQN (QUOTE A) (QUOTE A)) 
     (NULL (EQN (QUOTE (A . B)) (QUOTE (A . B)))) 
     (NULL (EQN (QUOTE (A B C)) (QUOTE (A B C))))  )(***** (NULL (EQN 1 FONE))  
RETURNED NIL)
(***** (NULL (EQN 0 FZERO))  RETURNED NIL)
(EQN  TEST COMPLETE)
 
 
% EQUAL checks for general equality rather than specific, so 
% it must check all elements of general expressions and all elements 
% of vectors for equality. This test assumes that CAR does not have 
% the function pointer value  EQUAL to 0. Further tests of EQUAL 
% are in the vector section 3.9.  
(!$TEST EQUAL (EQUAL NIL NIL) 
     (EQUAL T T) 
     (NULL (EQUAL NIL T)) 
     (EQUAL !$CODE !$CODE) 
     (NULL (EQUAL !$CODE (CDR (GETD (QUOTE CAR)))))  
     (EQUAL (QUOTE IDENTIFIER) (QUOTE IDENTIFIER)) 
     (NULL (EQUAL (QUOTE IDENTIFIER1) (QUOTE IDENTIFIER2))) 
     (EQUAL 'STRING 'STRING) 
     (NULL (EQUAL 'STRING1 'STRING2)) 
     (EQUAL 0 0) 
     (NULL (EQUAL 0 1)) 
     (EQUAL (QUOTE (A . B)) (QUOTE (A . B))) 
     (NULL (EQUAL (QUOTE (A . B)) (QUOTE (A . C)))) 
     (NULL (EQUAL (QUOTE (A . B)) (QUOTE (C . B)))) 
     (EQUAL (QUOTE (A B)) (QUOTE (A B))) 
     (NULL (EQUAL (QUOTE (A B)) (QUOTE (A C)))) 
     (NULL (EQUAL (QUOTE (A B)) (QUOTE (C B)))) 
     (EQUAL !$VECTOR !$VECTOR) 
     (NULL (EQUAL 0 NIL)) 
     (NULL (EQUAL 'T T)) 
     (NULL (EQUAL 'NIL NIL)) )(***** (NULL (EQUAL (QUOTE T) T))  RETURNED NIL)
(***** (NULL (EQUAL (QUOTE NIL) NIL))  RETURNED NIL)
(EQUAL  TEST COMPLETE)
 
 
% -----3.2 Functions on Dotted-Pairs-----%  
% Test the C....R functions by simply verifying that they select 
% correct part of a structure.
(!$TEST CAR (EQ (CAR (QUOTE (A . B))) (QUOTE A)) 
    (EQUAL (CAR (QUOTE ((A) . B))) (QUOTE (A))) )(CAR  TEST COMPLETE)
 
 
(!$TEST CDR (EQ (CDR (QUOTE (A . B))) (QUOTE B)) 
     (EQUAL (CDR (QUOTE (A B))) (QUOTE (B))) )(CDR  TEST COMPLETE)
 
 
(!$TEST CAAR (EQ (CAAR (QUOTE ((A)))) (QUOTE A)))(CAAR  TEST COMPLETE)
 
(!$TEST CADR (EQ (CADR (QUOTE (A B))) (QUOTE B)))(CADR  TEST COMPLETE)
 
(!$TEST CDAR (EQ (CDAR (QUOTE ((A . B)))) (QUOTE B)))(CDAR  TEST COMPLETE)
 
(!$TEST CDDR (EQ (CDDR (QUOTE (A . (B . C)))) (QUOTE C)))(CDDR  TEST COMPLETE)
 
 
(!$TEST CAAAR (EQ (CAAAR (QUOTE (((A))))) (QUOTE A)))(CAAAR  TEST COMPLETE)
 
(!$TEST CAADR (EQ (CAADR (QUOTE (A (B)))) (QUOTE B)))(CAADR  TEST COMPLETE)
  
(!$TEST CADAR (EQ (CADAR (QUOTE ((A B)))) (QUOTE B)))(CADAR  TEST COMPLETE)
 
(!$TEST CADDR (EQ (CADDR (QUOTE (A B C))) (QUOTE C)))(CADDR  TEST COMPLETE)
 
(!$TEST CDAAR (EQ (CDAAR (QUOTE (((A . B)) C))) (QUOTE B)))(CDAAR  TEST COMPLETE
)
 
(!$TEST CDADR (EQ (CDADR (QUOTE (A (B . C)))) (QUOTE C)))(CDADR  TEST COMPLETE)
 
(!$TEST CDDAR (EQ (CDDAR (QUOTE ((A . (B . C))))) (QUOTE C)))(CDDAR  TEST COMPLE
TE)
 
(!$TEST CDDDR (EQ (CDDDR (QUOTE (A . (B . (C . D))))) (QUOTE D)))(CDDDR  TEST CO
MPLETE)
 
 
(!$TEST CAAAAR (EQ (CAAAAR (QUOTE ((((A)))))) (QUOTE A)))(CAAAAR  TEST COMPLETE)
 
(!$TEST CAAADR (EQ (CAAADR (QUOTE (A ((B))))) (QUOTE B)))(CAAADR  TEST COMPLETE)
 
(!$TEST CAADAR (EQ (CAADAR (QUOTE ((A (B))))) (QUOTE B)))(CAADAR  TEST COMPLETE)
  
(!$TEST CAADDR (EQ (CAADDR (QUOTE (A . (B (C))))) (QUOTE C)))(CAADDR  TEST COMPL
ETE)
 
(!$TEST CADAAR (EQ (CADAAR (QUOTE (((A . (B)))))) (QUOTE B)))(CADAAR  TEST COMPL
ETE)
 
(!$TEST CADADR (EQ (CADADR (QUOTE (A (B . (C))))) (QUOTE C)))(CADADR  TEST COMPL
ETE)
 
(!$TEST CADDAR (EQ (CADDAR (QUOTE ((A . (B . (C)))))) (QUOTE C)))
***GARBAGE COLLECTOR CALLED
CONSES:        3465
ST    :          84
        3500 PAIRS FREED.
         199 PAIRS IN USE.
MAX GC STACK WAS            5
(CADDAR  TEST COMPLETE)
 
(!$TEST CADDDR (EQ (CADDDR (QUOTE (A . (B . (C . (D)))))) (QUOTE D)))(CADDDR  TE
ST COMPLETE)
 
(!$TEST CDAAAR (EQ (CDAAAR (QUOTE ((((A . B)))))) (QUOTE B)))(CDAAAR  TEST COMPL 
ETE)
 
(!$TEST CDAADR (EQ (CDAADR (QUOTE (A ((B . C))))) (QUOTE C)))(CDAADR  TEST COMPL
ETE)
 
(!$TEST CDADAR (EQ (CDADAR (QUOTE ((A (B . C))))) (QUOTE C)))(CDADAR  TEST COMPL
ETE)
 
(!$TEST CDADDR (EQ (CDADDR (QUOTE (A . (B . ((C . D)))))) (QUOTE D)))(CDADDR  TE
ST COMPLETE)
 
(!$TEST CDDAAR (EQ (CDDAAR (QUOTE (((A . (B . C)))))) (QUOTE C)))(CDDAAR  TEST C
OMPLETE)
 
(!$TEST CDDADR (EQ (CDDADR (QUOTE (A . ((B . (C . D)))))) (QUOTE D)))(CDDADR  TE
ST COMPLETE)
 
(!$TEST CDDDAR (EQ (CDDDAR (QUOTE ((A  . (B . (C . D)))))) (QUOTE D)))(CDDDAR  T
EST COMPLETE)
 
(!$TEST CDDDDR (EQ (CDDDDR (QUOTE (A . (B . (C . (D . E)))))) (QUOTE E)))(CDDDDR
  TEST COMPLETE) 
 
 
% CONS should return a unique cell when invoked. Also test that
% the left and right parts are set correctly.
(!$TEST CONS (NULL (EQ (CONS (QUOTE A) (QUOTE B)) (QUOTE (A . B)))) 
     (EQ (CAR (CONS (QUOTE A) (QUOTE B))) (QUOTE A)) 
     (EQ (CDR (CONS (QUOTE A) (QUOTE B))) (QUOTE B)) )(CONS  TEST COMPLETE)
 
 
% Veryify that RPLACA doesn't modify the binding of a list, and
% that only the CAR part of the cell is affected.
(!$TEST RPLACA 
  (SET (QUOTE TEMP) (QUOTE (A))) 
  (EQ (RPLACA TEMP 1) TEMP) 
  (EQ (CAR (RPLACA TEMP (QUOTE B))) (QUOTE B))  
  (EQ (CDR TEMP) NIL) )(***** (SET (QUOTE TEMP) (QUOTE (A)))  RETURNED (A))
(RPLACA  TEST COMPLETE)

 
(!$TEST RPLACD 
  (SET (QUOTE TEMP) (QUOTE (A . B))) 
  (EQ (RPLACD TEMP (QUOTE A)) TEMP)  
  (EQ (CDR (RPLACD TEMP (QUOTE C))) (QUOTE C))  
  (EQ (CAR TEMP) (QUOTE A)) )(***** (SET (QUOTE TEMP) (QUOTE (A . B)))  RETURNED
 (A . B))
(RPLACD  TEST COMPLETE)

 
% -----3.3 Identifiers-----%  
% Verify that COMPRESS handles the various types of lexemes
% correctly.
(!$TEST COMPRESS 
  (NULL (EQ (COMPRESS (QUOTE (A B))) (COMPRESS (QUOTE (A B))))) 
  (EQN (COMPRESS (QUOTE (!1 !2))) 12) 
  (EQN (COMPRESS (QUOTE (!+ !1 !2))) 12) 
  (EQN (COMPRESS (QUOTE (!- !1 !2))) -12) 
  (EQUAL (COMPRESS (QUOTE ( S T R I N G ))) 'STRING) 
  (EQ (INTERN (COMPRESS (QUOTE (A B)))) (QUOTE AB))   
  (EQ (INTERN (COMPRESS (QUOTE (!! !$ A)))) (QUOTE !$A)) )(***** (NULL (EQ (COMP
RESS (QUOTE (A B))) (COMPRESS (QUOTE (A B)))))  RETURNED NIL)
(***** (EQ (INTERN (COMPRESS (QUOTE (! $ A)))) (QUOTE $A))  RETURNED NIL)
(COMPRESS  TEST COMPLETE)

  
% Verify that EXPLODE returns the expected lists and that COMPRESS
% and explode are inverses of each other.
(!$TEST EXPLODE 
  (EQUAL (EXPLODE 12) (QUOTE (!1 !2))) 
  (EQUAL (EXPLODE -12) (QUOTE (!- !1 !2))) 
  (EQUAL (EXPLODE 'STRING) (QUOTE ( S T R I N G ))) 
  (EQUAL (EXPLODE (QUOTE AB)) (QUOTE (A B)) ) 
  (EQUAL (EXPLODE (QUOTE !$AB)) (QUOTE (!! !$ A B)))   
  (EQUAL (COMPRESS (EXPLODE 12)) 12)
  (EQUAL (COMPRESS (EXPLODE -12)) -12)
  (EQUAL (COMPRESS (EXPLODE 'STRING)) 'STRING)
  (EQ (INTERN (COMPRESS (EXPLODE (QUOTE AB)))) (QUOTE AB))
  (EQ (INTERN (COMPRESS (EXPLODE (QUOTE !$AB)))) (QUOTE !$AB)) )(***** (EQUAL (E
XPLODE (QUOTE $AB)) (QUOTE (! $ A B)))  RETURNED NIL)
(EXPLODE  TEST COMPLETE)

 
% Test that GENSYM returns identifiers and that they are different.
(!$TEST GENSYM 
  (IDP (GENSYM)) 
  (NULL (EQ (GENSYM) (GENSYM))) )(GENSYM  TEST COMPLETE)
  
 
% Test that INTERN works on strings to produce identifiers the same
% as those read in. Try ID's with special characters in them (more
% will be tested with READ).
(!$TEST INTERN 
  (EQ (INTERN 'A) (QUOTE A)) 
  (EQ (INTERN 'A12) (QUOTE A12))
  (EQ (INTERN 'A!*) (QUOTE A!*))
  (NULL (EQ (INTERN 'A) (INTERN 'B))) )(INTERN  TEST COMPLETE)
 
 
% Just test that REMOB returns the ID removed.
(!$TEST REMOB 
  (EQ (REMOB (QUOTE AAAA)) (QUOTE AAAA)) )(***** (EQ (REMOB (QUOTE AAAA)) (QUOTE
 AAAA))  RETURNED NIL)
(REMOB  TEST COMPLETE)
 
 
% ----- 3.4 Property List Functions-----%  
% Test that FLAG always returns NIL. More testing is done in FLAGP.
(!$TEST FLAG 
  (NULL (FLAG NIL (QUOTE W)))  
  (NULL (FLAG (QUOTE (U V T NIL)) (QUOTE X))) 
  (NULL (FLAG (QUOTE (U)) NIL)) )(FLAG  TEST COMPLETE)
 
 
% Test that FLAG worked only on a list. Test all items in a flagged
% list were flagged and that those that weren't aren't.
(!$TEST FLAGP 
  (NULL (FLAGP NIL (QUOTE W))) 
  (FLAGP (QUOTE U) (QUOTE X)) 
  (FLAGP (QUOTE V) (QUOTE X)) 
  (FLAGP T (QUOTE X)) 
  (FLAGP NIL (QUOTE X)) 
  (FLAGP (QUOTE U) NIL) )(***** (FLAGP (QUOTE U) (QUOTE X))  RETURNED (X))
(***** (FLAGP (QUOTE V) (QUOTE X))  RETURNED (X))
(***** (FLAGP T (QUOTE X))  RETURNED (X))
(***** (FLAGP NIL (QUOTE X))  RETURNED (X))
(***** (FLAGP (QUOTE U) NIL)  RETURNED (NIL X))
(FLAGP  TEST COMPLETE)
 
 
% Test that REMFLAG always returns NIL and that flags removed are
% gone. Test that unremoved flags are still present. 
(!$TEST REMFLAG 
  (NULL (REMFLAG NIL (QUOTE X))) 
  (NULL (REMFLAG (QUOTE (U T NIL)) (QUOTE X))) 
  (NULL (FLAGP (QUOTE U) (QUOTE X))) 
  (FLAGP (QUOTE V) (QUOTE X)) 
  (NULL (FLAGP T (QUOTE X))) 
  (NULL (FLAGP NIL (QUOTE X))) )(***** (FLAGP (QUOTE V) (QUOTE X))  RETURNED (X)
)
(REMFLAG  TEST COMPLETE)
 
 
(!$TEST PUT 
  (EQ (PUT (QUOTE U) (QUOTE IND1) (QUOTE PROP)) (QUOTE PROP)) 
  (EQN (PUT (QUOTE U) (QUOTE IND2) 0) 0) 
  (EQ (PUT (QUOTE U) (QUOTE IND3) !$VECTOR) !$VECTOR) 
  (EQ (PUT (QUOTE U) (QUOTE IND4) !$CODE) !$CODE) )(PUT  TEST COMPLETE)
 
 
(!$TEST GET 
  (EQ (GET (QUOTE U) (QUOTE IND1)) (QUOTE PROP)) 
  (EQN (GET (QUOTE U) (QUOTE IND2)) 0) 
  (EQ (GET (QUOTE U) (QUOTE IND3)) !$VECTOR)  
  (EQ (GET (QUOTE U) (QUOTE IND4)) !$CODE) )
***GARBAGE COLLECTOR CALLED
CONSES:        3500
ST    :          68
        3460 PAIRS FREED.
         239 PAIRS IN USE.
MAX GC STACK WAS            5
(GET  TEST COMPLETE)
 
 
(!$TEST REMPROP 
  (NULL (REMPROP !$CODE !$CODE)) 
  (EQ (REMPROP (QUOTE U) (QUOTE IND1)) (QUOTE PROP)) 
  (NULL (GET (QUOTE U) (QUOTE IND1))) 
  (EQN (REMPROP (QUOTE U) (QUOTE IND2)) (QUOTE 0)) 
  (NULL (GET (QUOTE U) (QUOTE IND2))) 
  (EQ (REMPROP (QUOTE U) (QUOTE IND3)) !$VECTOR) 
  (NULL (GET (QUOTE U) (QUOTE IND3))) 
  (GET (QUOTE U) (QUOTE IND4)) 
  (EQ (REMPROP (QUOTE U) (QUOTE IND4)) !$CODE) 
  (NULL (GET (QUOTE U) (QUOTE IND4)))  )(***** (EQ (REMPROP (QUOTE U) (QUOTE IND
1)) (QUOTE PROP))  RETURNED NIL) 
(***** (EQN (REMPROP (QUOTE U) (QUOTE IND2)) (QUOTE 0))  RETURNED NIL)
(***** (GET (QUOTE U) (QUOTE IND4))  RETURNED  ##89)
(***** (EQ (REMPROP (QUOTE U) (QUOTE IND4)) $CODE)  RETURNED NIL)
(REMPROP  TEST COMPLETE)
 
 
 
% -----3.5 Function Definition-----% 
(!$TEST DE 
        (EQ (DE FIE (X) (PLUS2 X 1)) (QUOTE FIE))
        (GETD (QUOTE FIE))
        (EQN (FIE 1) 2)
)(***** (GETD (QUOTE FIE))  RETURNED (EXPR LAMBDA (X) (PLUS2 X 1)))
(DE  TEST COMPLETE)

% Expect (FIE 1) to return 2% 
(FIE 1)2

% Expect FIE redefined in DF test% 
(!$TEST DF 
        (EQ (DF FIE (X) (PROGN (PRINT X) (CAR X))) (QUOTE FIE))
        (GETD (QUOTE FIE)) 
        (EQN (FIE 1) 1)
        (EQN (FIE 2 3) 2)
)*** (FUNCTION FIE REDEFINED)
(***** (GETD (QUOTE FIE))  RETURNED (FEXPR LAMBDA (X) (PROGN (PRINT X) (CAR X)))
)
(1)
(2 3)
(DF  TEST COMPLETE)

% Expect (FIE 1) to return 1, and print (1)% 
(FIE 1)(1)
1

% Expect (FIE 1 2) to return 1, and print (1 2)% 
(FIE 1 2)(1 2)
1

% Expect FIE redefined in DM% 
(!$TEST DM 
        (EQ (DM FIE (X) 
             (LIST (QUOTE LIST) 
                              (LIST (QUOTE QUOTE)  X) 
                              (LIST (QUOTE QUOTE)  X) )) 
          (QUOTE FIE))
        (GETD (QUOTE FIE))
        (EQUAL (FIE 1) (QUOTE ((FIE 1) (FIE 1))))
)*** (FUNCTION FIE REDEFINED)
(***** (GETD (QUOTE FIE))  RETURNED (MACRO LAMBDA (X) (LIST (QUOTE LIST) (LIST (
QUOTE QUOTE) X) (LIST (QUOTE QUOTE) X))))
(DM  TEST COMPLETE)

% Expect (FIE 1) to return ((FIE 1) (FIE 1))% 
(FIE 1)((FIE 1) (FIE 1))

(!$TEST GETD 
        (PAIRP (GETD (QUOTE FIE)))
        (NULL (PAIRP (GETD (QUOTE FIEFIEFIE))))
        (EQ (CAR (GETD (QUOTE FIE))) (QUOTE MACRO))
)(GETD  TEST COMPLETE)


(!$TEST PUTD 
        (GLOBALP (QUOTE FIE))
 )(***** (GLOBALP (QUOTE FIE))  RETURNED NIL) 
(PUTD  TEST COMPLETE)

% Should check that a FLUID variable not PUTDable;
(!$TEST REMD 
        (PAIRP (REMD (QUOTE FIE)))
        (NULL (GETD (QUOTE FIE)))
             (NULL (REMD (QUOTE FIE)))
             (NULL (REMD (QUOTE FIEFIEFIE)))
)(REMD  TEST COMPLETE)

% -----3.6 Variables and Bindings------% 
%  Make FLUIDVAR1 and FLUIDVAR2 fluids% 
(FLUID (QUOTE (FLUIDVAR1 FLUIDVAR2)))(FLUIDVAR1 FLUIDVAR2)

% Check that FLUIDVAR1 and FLUIDVAR2 are fluid,expect T, T% 
(FLUIDP (QUOTE FLUIDVAR1))NIL

(FLUIDP (QUOTE FLUIDVAR2))NIL

% Give FLUIDVAR1 and FLUIDVAR2 initial values% 
(SETQ FLUIDVAR1 1)1
 
(SETQ FLUIDVAR2 2)2


(!$TEST 'FLUID! and! FLUIDP
        (NULL (FLUID (QUOTE (FLUIDVAR3 FLUIDVAR1 FLUIDVAR2 FLUIDVAR4))))
        (FLUIDP (QUOTE FLUIDVAR3))
        (FLUIDP (QUOTE FLUIDVAR1))
        (FLUIDP (QUOTE FLUIDVAR2))
        (FLUIDP (QUOTE FLUIDVAR4))
        (NULL (GLOBALP (QUOTE FLUIDVAR3)))
        (NULL (GLOBALP (QUOTE FLUIDVAR1)))
        (NULL FLUIDVAR3)
        (EQN FLUIDVAR1 1)
        (NULL (FLUIDP (QUOTE CAR)))
)(***** (NULL (FLUID (QUOTE (FLUIDVAR3 FLUIDVAR1 FLUIDVAR2 FLUIDVAR4))))  RETURN
ED NIL)
(***** (FLUIDP (QUOTE FLUIDVAR3))  RETURNED NIL)
(***** (FLUIDP (QUOTE FLUIDVAR1))  RETURNED NIL)
(***** (FLUIDP (QUOTE FLUIDVAR2))  RETURNED NIL)
(***** (FLUIDP (QUOTE FLUIDVAR4))  RETURNED NIL)
((QUOTE FLUID AND FLUIDP)  TEST COMPLETE)
 
(GLOBAL (QUOTE (FLUIDGLOBAL1)))NIL

% Expect ERROR that FLUIDGLOBAL1 already FLUID% 
(FLUID (QUOTE (FLUIDGLOBAL2)))(FLUIDGLOBAL2)


% Expect ERROR that cant change FLUID% 
(GLOBAL (QUOTE (FLUIDVAR1 FLUIDVAR2 GLOBALVAR1 GLOBALVAR2)))NIL

% Does error cause GLOBALVAR1, GLOBALVAR2 to be declared ;

(!$TEST 'GLOBAL! and! GLOBALP
        (NULL (GLOBAL (QUOTE (GLOBALVAR1 GLOBALVAR2))))
        (GLOBALP (QUOTE GLOBALVAR1))
        (GLOBALP (QUOTE GLOBALVAR2))
        (NULL (GLOBALP (QUOTE FLUIDVAR1)))
        (FLUIDP (QUOTE FLUIDVAR1))
        (NULL (FLUIDP (QUOTE GLOBALVAR1)))
        (NULL (FLUIDP (QUOTE GLOBALVAR2)))
        (GLOBALP (QUOTE CAR))
)(***** (GLOBALP (QUOTE GLOBALVAR1))  RETURNED (GLOBAL))
(***** (GLOBALP (QUOTE GLOBALVAR2))  RETURNED (GLOBAL)) 
(***** (NULL (GLOBALP (QUOTE FLUIDVAR1)))  RETURNED NIL)
(***** (FLUIDP (QUOTE FLUIDVAR1))  RETURNED NIL)
(***** (GLOBALP (QUOTE CAR))  RETURNED NIL)
((QUOTE GLOBAL AND GLOBALP)  TEST COMPLETE)


% Set SETVAR1 to have an ID value% 
(SET (QUOTE SETVAR1) (QUOTE SETVAR2))SETVAR2


% Expect SETVAR3 to be declared FLUID% 
(!$TEST SET
        (NULL (FLUIDP (QUOTE SETVAR3)))
        (EQN 3 (SET (QUOTE SETVAR3) 3))
        (EQN 3 SETVAR3)
        (FLUIDP (QUOTE SETVAR3))
        (EQN (SET SETVAR1 4) 4)
        (NULL (EQN SETVAR1 4))
        (EQ SETVAR1 (QUOTE SETVAR2))
        (EQN SETVAR2 4)
)(***** (FLUIDP (QUOTE SETVAR3))  RETURNED NIL)
(SET  TEST COMPLETE) 

% Expect ERROR if try to set non ID% 
(SET 1 2)(SET 1 2)

(SET (QUOTE SETVAR1) 1)1

(SET SETVAR1 2)(SET 1 2)


% Expect ERROR if try to SET T or NIL% 
(SET (QUOTE SAVENIL) NIL)NIL

(SET (QUOTE SAVET) T)T

(!$TEST 'Special! SET! value
        (SET (QUOTE NIL) 1)
        (NULL (EQN NIL 1))
        (SET (QUOTE NIL) SAVENIL)
        (SET (QUOTE T) 2)
        (NULL (EQN T 2))
        (SET (QUOTE T) SAVET)
)(***** (SET (QUOTE NIL) 1)  RETURNED 1 . 1) 
(***** (NULL (EQN NIL 1))  RETURNED NIL . 1)
(***** (SET (QUOTE NIL) SAVENIL)  RETURNED NIL)
(***** (NULL (EQN T 2))  RETURNED NIL)
((QUOTE SPECIAL SET VALUE)  TEST COMPLETE)



% Expect SETVAR3 to be declared FLUID% 
(!$TEST SETQ
        (NULL (FLUIDP (QUOTE SETVAR3)))
        (EQN 3 (SETQ SETVAR3 3))
        (EQN 3 SETVAR3)
        (FLUIDP (QUOTE SETVAR3))
)(***** (FLUIDP (QUOTE SETVAR3))  RETURNED NIL)
(SETQ  TEST COMPLETE)


% Expect ERROR if try to SETQ T or NIL% 
(SET (QUOTE SAVENIL) NIL)NIL

(SET (QUOTE SAVET) T)T
 
(!$TEST 'Special! SETQ! value
        (SETQ NIL 1)
        (NULL (EQN NIL 1))
        (SETQ NIL SAVENIL)
        (SETQ T 2)
        (NULL (EQN T 2))
        (SETQ T SAVET)
)(***** (SETQ NIL 1)  RETURNED 1 . 1)
(***** (NULL (EQN NIL 1))  RETURNED NIL . 1)
(***** (SETQ NIL SAVENIL)  RETURNED NIL)
(***** (NULL (EQN T 2))  RETURNED NIL)
((QUOTE SPECIAL SETQ VALUE)  TEST COMPLETE)


(!$TEST UNFLUID
        (GLOBALP (QUOTE GLOBALVAR1))
        (FLUIDP  (QUOTE FLUIDVAR1))
        (NULL (UNFLUID (QUOTE (GLOBALVAR1 FLUIDVAR1))))
        (GLOBALP (QUOTE GLOBALVAR1))
        (NULL (FLUIDP (QUOTE FLUIDVAR1)))
)(***** (GLOBALP (QUOTE GLOBALVAR1))  RETURNED (GLOBAL))
(***** (FLUIDP (QUOTE FLUIDVAR1))  RETURNED NIL) 
(***** (GLOBALP (QUOTE GLOBALVAR1))  RETURNED (GLOBAL))
(UNFLUID  TEST COMPLETE)



% ----- 3.7 Program Feature Functions -----% 

% These have been tested as part of BASIC tests;

% Check exact GO and RETURN scoping rules ;

% ----- 3.8 Error Handling -----% 

(!$TEST EMSG!* (GLOBALP (QUOTE EMSG!*)))(***** (GLOBALP (QUOTE EMSG*))  RETURNED
 NIL)
(EMSG*  TEST COMPLETE)


(!$TEST ERRORSET
        (EQUAL (ERRORSET 1 T T) (QUOTE (1)))
        (NULL (PAIRP (ERRORSET (QUOTE (CAR 1)) T T)))
) 
***GARBAGE COLLECTOR CALLED
CONSES:        3460
ST    :          83
        3483 PAIRS FREED.
         216 PAIRS IN USE.
MAX GC STACK WAS            5

%?	SCALAR OUT OF RANGE AT USER PC 000000

EXIT
@POP

[PHOTO:  Recording terminated  Mon 15-Feb-82 5:16PM]

Added perq-pascal-lisp-project/paslsp-wicat.bld version [4324b9d228].































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
; Command file to assemble PASn pieces together
; Wicat version
;
COP PAS3.INI PASLSP.INI
APP PAS1.SLI PASLSP.INI
APP PAS2.SLI PASLSP.INI
APP PAS3.SLI PASLSP.INI
APP USER.SLI PASLSP.INI
filter w <pas0.pre >s:plw.pas
append pas1.pas S:PLW.PAS
append pas2.pas S:PLW.PAS
append pas3.pas S:PLW.PAS
append exec.pas S:PLW.PAS
filter w <pasn.pre >s:plwn.pas
append S:plwn.pas S:PLW.PAS

Added perq-pascal-lisp-project/paslsp.bld version [6dfb647630].







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
; Command file to assemble PASn pieces together and then compile them.
;
COP PAS3.INI PASLSP.INI
APP PAS1.SLI PASLSP.INI
APP PAS2.SLI PASLSP.INI
APP PAS3.SLI PASLSP.INI
APP USER.SLI PASLSP.INI
copy pas0.pas S:PASLSP.pas
append pas1.pas S:PASLSP.pas
append pas2.pas S:PASLSP.pas
append pas3.pas S:PASLSP.pas
append exec.pas S:PASLSP.pas
append pasN.pas S:PASLSP.pas
pascal
S:PASLSP.rel
S:PASLSP.lst
S:PASLSP.pas
load S:PASLSP.REL
save S:PASLSP.EXE

Added perq-pascal-lisp-project/paslsp.ini version [9a6226cbfd].

cannot compute difference between binary files

Added perq-pascal-lisp-project/paslsp.mail version [e0c4e98ff1].







>
>
>
1
2
3
PASLSPers: GRISS, CAI.OTTENHEIMER,JW-PETERSON,
            PENDLETON, BENSON, GALWAY, VOELKER
; Working on PASCAL-LISP project

Added perq-pascal-lisp-project/paslsp.mic version [5ef41a958b].

















>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
@pascal
s:paslsp.rel

s:paslsp.pas
@load s:paslsp.rel
@save s:paslsp.exe
@st

Added perq-pascal-lisp-project/paslsp.mss version [cc5629311e].



































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
@Device(lpt)
@style(justification yes)
@style(spacing 1)
@use(Bibliography "<griss.docs>mtlisp.bib")
@make(article)
@modify(enumerate,numbered=<@a. @,@i. >, spread 1)
@modify(appendix,numbered=<APPENDIX @A: >)
@modify(itemize,spread 1)
@modify(description,leftmargin +2.0 inch,indent -2.0 inch)
@define(up,use text,capitalized on,  break off)
@define(mac,use text, underline off,  break off)
@define(LISPmac,use text, underline alphanumerics,  break off)
@pageheading(Left  "Utah Symbolic Computation Group",
             Right "November 1981", 
             Line "Operating Note xx"
            )
@set(page=1)
@newpage()
@begin(titlepage)
@begin(titlebox)
@b(A PASCAL Based Standard LISP for the PERQ)
@center[
by

M. L. Griss, R. Ottenheimer, S. Voelker, K. Boekleheide

Department of Computer Science
University of Utah
Salt Lake City, Utah 84112

@b(Preliminary  Version)

Last Revision: @value(date)]

@end(titlebox)
@begin(abstract)
This report describes  an interim implementation
of Standard LISP for the PERQ. This LISP is based upon the
Standard LISP report, and a newly developing Portable Standard LISP.
This interim implementation is designed to explore LISP implementations
in PASCAL on the PERQ and similar machines. The system consists of
a kernel, handcoded in PASCAL, with the rest of the system written in
LISP and compiled to PASCAL.
@End(abstract)
@begin(Researchcredit)
Work supported in part by the National Science Foundation
under Grant No. MCS80-07034, and by xxxx.
@end(Researchcredit)
@end(titlepage)
@pageheading(Left "PERQ Standard LISP",Center "@value(date)",
             Right "@value(Page)"
            )
@set(page=1)
@newpage
@section(Introduction)
In this preliminary report, we describe an implementation of Standard LISP
in PASCAL, PASLSP. Versions of PASLSP have been run on a number of
machines, ranging from LSI-11 based TERAK to APOLLO and PERQ. This report
concentrates on the PERQ implementation. This report is to be read in
conjunction with the Standard LISP report@cite(Marti79); we will
highlight the differences from the functions documented in the Standard
LISP, describe the implementation strategy, and discuss future work.

PASLSP is based on a series of small and medium sized LISP interpreters
that have been developed at the University of Utah; each of these LISP
systems consists of a small kernel handcoded in some language, with the
rest of the system written in LISP and compiled to the target language.
We have used FORTRAN, PASCAL and assembly language as targets. The PASLSP
series use PASCAL for the kernel, and have a LISP to PASCAL for the rest of the
system. Recent work has concentrated on reducing the hand-coded kernel,
and has extended the compiler to compile more systems level constructs
(SYSLISP level), resulting in a new Portable Standard LISP running
on the DEC-20@cite(xxx). The PSL system is a modern, efficient system,
and it is hoped to replace PASLSP with a PSL implemented in PASCAL.

@subsection(History of PASLSP)
The system now called PASLSP was originally developed (by M. Griss and W.
Galway), as a small LISP like kernel to support a small algebra system on
an LSI-11 TERAK; this was to be used as an answer analysis module within a
CAI system@cite(Brandtxx), written entirely in PASCAL. It was decided to
hand-code a very small kernel, and compile additional functions written in
LISP (LISP support functions and algebra package) to PASCAL, using a
modified Portable LISP compiler@cite(griss79). This version (call it V0)
did not even have user defined functions, since space on the TERAK was
at a premium.

About June 1981, PASLSP came to the attention of a number people evaluating
Apollo's and PERQ's, and it was suggested that we enhance V0 PASLSP for
this purpose. During the space of  a few days, sufficient features taken
from the Standard LISP Report were added to the kernel and support files
to produce V1 of PASLSP, running on a DEC-20 and Terak. This was
a fairly complete LISP (including Catch and Throw), but lacked a few
features (OPEN, CLOSE, RSD, WRS, PROG, GO, RETURN, Vectors and Strings).
V1 PASLSP was adapted to a PERQ, VAX and Apollo by Paul Milazo of Schlumberge
in the space of a few weeks (we did not have a PERQ or Apollo at that time).

We subsequently obtained a PERQ and an Apollo, and recent work has been
aimed at producing an enhanced PASLSP for these machines, as well as
the TERAK, and other personal machines. The current system, V2 PASLSP,
is produced from a single PASCAL kernel and set of LISP support files;
the machine specific features are handled by a simple Source Code
conditionalizer, changing the definition of certain constants and data
types. 

We are releasing a copy of V2 PASLSP as an small, interim LISP, until
a better LISP based on a more modern Portable Standard LISP can
be completed.
@subsection(Acknowledgement)

I would like to acknowledge the advice, and software contributions of
Will Galway,  Eric Benson and Paul Milazo.

@section(Implementation of PASLSP)

@section(Features of PASLSP and relation to Standard LISP)
PASLSP as far as possible provides all the functions mentioned
in the attached Standard LISP Report (note the hand-written
comments added to this appendix); some of the functions are simply
stubs, so that a Standard LISP Test-file can be run with out major
modification.

PASLSP-V2  does not implement the following features of Standard LISP:
@begin(enumeration,spread 0)
STRINGS or VECTORS (only a simple garbage collector is used).

Integers are limited in size (INTs and FIXNUMs,no BIGNUMs).

FLOATING Point. 

IDs can not be REMOB'ed or INTERN'd.

Only 3 Input Channels and 2 Output Channels are available to OPEN,
RDS, WRS, and CLOSE. Thus file input statements can not be nested
very deeply in files.

Line, Page and Character counting (POSN, LPOSN, etc).
@end(enumeration)

PASLSP-V2 provides some extensions over Standard LISP:
@begin(enumerate,spread 0)
CATCH and THROW (both tagged and Untagged).

Implicit PROGN in COND, and LAMBDA expressions.

WHILE loop.

CntrlC handlers.
@end(enumerate)
@Section(Features of PSL that will be incorporated in next PASLSP)

@subsection(Goals of the Utah PSL Project)

The goal of the PSL project is to produce an efficient and transportable
Standard LISP system that may be used to:
@begin(enumeration)
Experimentally  explore
a variety of LISP implementation issues (storage management, binding,
environments, etc.);

Effectively support the REDUCE algebra system on a number of machines;

Provide the same, uniform, modern LISP programming environment on all of
the
machines that we use (DEC-20, VAX/750, PDP-11/45 and some personal machine, perhaps 68000
based), of the power and complexity of UCI-LISP or MACLISP, with some
extensions and enhancements.
@end(enumeration)

The approach we have been using is to write the @b(entire) LISP system in
Standard LISP (with extensions for dealing with 
machine words and operations), and to bootstrap it to the desired target
machine
in two steps:
@begin(enumeration)
Cross compile an appropriate kernel to the assembly language of the
target machine;

Once the kernel is running, use a resident compiler and loader, or
fast-loader, to build the rest of the system.
@end(enumeration)

We currently think of the extensions to Standard LISP as having two levels:
the SYSLISP level, dealing with words and bytes and machine operations,
enabling us to write essentially all of the kernel in Standard LISP; and,
the STDLISP level, incorporating all of the features that make Standard
LISP into a modern LISP.

In our environment, we write LISP code using an ALGOL-like preprocessor
language, RLISP, that provides a number of syntactic niceties that
we find convenient; we do not distinguish LISP from RLISP, and can
mechanically translate from one to the other in either direction.
@section(References)
@Bibliography

Added perq-pascal-lisp-project/paslsp.table version [aa555dfd46].





















































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
NIL
--------------- Functions ----------------
!*FIRST!-PROCEDURE
ABS
ADD1
AND
APPEND
APPLY
APPLY1
ASSOC
ATOM
ATSOC
CAAAAR
CAAADR
CAAAR
CAADAR
CAADDR
CAADR
CAAR
CADAAR
CADADR
CADAR
CADDAR
CADDDR
CADDR
CADR
CAR
CATCH
CDAAAR
CDAADR
CDAAR
CDADAR
CDADDR
CDADR
CDAR
CDDAAR
CDDADR
CDDAR
CDDDAR
CDDDDR
CDDDR
CDDR
CDR
CLOSE
CODEP
COMPRESS
COND
CONS
CONSTANTP
DE
DEFLIST
DELATQ
DELETE
DELQ
DF
DIFFERENCE
DIGIT
DIVIDE
DM
DN
DSKIN
EOFP
EQ
EQCAR
EQN
EQUAL
ERROR
ERRORSET
ERRPRT
EVAL
EVLAM
EVLIS
EXPAND
EXPLODE
EXPT
FASTSTAT
FIX
FIXP
FLAG
FLAG1
FLAGP
FLOAT
FLOATP
FLUID
FLUIDP
FUNCELL
FUNCTION
GENSYM
GET
GETD
GETV
GLOBAL
GLOBALP
GO
GREATERP
IDP
INTERN
LBIND1
LBINDN
LENGTH
LESSP
LIST2
LIST3
LIST4
LIST5
LITER
MAP
MAPC
MAPCAN
MAPCAR
MAPCON
MAPLIST
MAX
MAX2
MEMBER
MEMQ
MIN
MIN2
MINUS
MINUSP
MKVECT
MSGPRT
NCONC
NCONS
NOT
NULL
NUMBERP
ONEP
OPEN
OR
ORDERP
P!.N
PAIR
PAIRP
PBIND1
PBINDN
PLIST
PLUS
PLUS2
PRIN1
PRIN2
PRIN2T
PRIN2TL
PRINC
PRINT
PROG
PROG2
PROGG0131
PROGN
PUT
PUTC
PUTD
PUTL
PUTV
QUOTIENT
RDEVPR
RDS
RDTOK
READ
READCH
RECLAIM
REMAINDER
REMD
REMFLAG
REMFLAG1
REMOB
REMPROP
RETURN
REV
REVERSE
REVX
RLIST
RPLACA
RPLACD
SASSOC
SET
SETFUNCELL
SETPLIST
SETVALUE
STRINGP
SUB1
SUBLIS
SUBST
TCATCH
TERPRI
THROW
TIMES
TIMES2
TOKEN
TTHROW
UNBIND1
UNBINDN
UNBINDTO
UNFLUID
UPBV
VALUE
VECTORP
WHILE
WRS
WRTOK
XAPPLY
XCONS
ZEROP
--------------- Other IDS ----------------
!$PROG!$
!*!*!*! 
!*!*!*!*
!*!*!*!*! 
!*!*!*!*! ERROR! 
!*RAISE
!.! 
ASSOC
BADLAMBDA
BE
BNDUNDERFLOW
BSTK!*
CANT
DEFINED
EMSG!*
ENUM!*
EXITING
EXPR
FEXPR
FLAGGED
FUNCTION
GLOBAL
INITFORM!*
INPUT
LABEL
LAMBDA
LIST
LOOP
LOSE
MACRO
MAX2
MIN2
NEXPR
NEXPRS
NOT
OUTPUT
P!.G
P!.P
PAIR
PLUS2
PROCS
PROGG0131
QUIT
QUOTE
REDEFINED
SET
SETQ
THROWING!*
THROWTAG!*
TIMES2
TOK!*
TOKTYPE
TOP
TYPE
--------------- CONST ----------------
(LIST)
(ALL RIGHTS RESERVED)
(COPYRIGHT (C) 1981 U UTAH)
(PASCAL LISP V2 !- 15 NOV 1981)
(EXPR FEXPR NEXPR MACRO)
(NIL)
NIL

Added perq-pascal-lisp-project/paslsp.tst version [7a430858f0].







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
%%%%%%%%%%%%  Standard - LISP Verification file. %%%%%%%%%%%%%%%%%%%%%%%
%
% Copyright (C) M. Griss and J. Marti, February 1981
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



% Flags for SYSLISP based PSL


(SETQ !*ECHO T)
(SETQ FZERO (FLOAT 0))
(SETQ FONE (FLOAT 1))
(SETQ !*RAISE 'T)

%  The following should return T:
T 
(NULL NIL) 
(COND (T T)) 
(COND (NIL NIL) (T T)) 
%  The following should return NIL:
NIL 
(NULL T) 
(COND (T NIL)) 
(COND (NIL T) 
      (T NIL)) 
%  The following should be 0
0 (QUOTE 0) 
%  The following minimum set of functions must work:
%   PUTD, PROG, SET, QUOTE, COND, NULL, RETURN, LIST, CAR, CDR,
%   EVAL, PRINT, PRIN1, TERPRI, PROGN, GO.
%  Check PUTD, GETD, LAMBDA 
(PUTD (QUOTE FOO) (QUOTE EXPR) (QUOTE (LAMBDA (X) 3)))
% Expect (EXPR LAMBDA (X) 3)
(GETD (QUOTE FOO))
%  Should return 3
(FOO 1)
(FOO 2)
%  Test SET :
(SET (QUOTE A) 1)
A
(SET (QUOTE B) 2)
B
%  Test LIST, CAR, CDR 
%  Expect (1 2 3 4) 1 and (2 3 4) 
(SET (QUOTE A) (LIST 1 2 3 4))
(CAR A)
(CDR A)
% Test REDEFINITION in PUTD, PROGN, PRIN1, TERPRI 
(PUTD (QUOTE FOO) (QUOTE EXPR) 
      (QUOTE (LAMBDA (X) (PROGN (PRIN1 X) (TERPRI)))))
%  expect 1 and 2 printed , value NIL
(FOO 1)
(FOO 2)
%  Test simple PROG, GO, RETURN 
(PROG NIL (PRINT 1) (PRINT 2))
(PROG (A) (PRINT A) (PRINT 1))
% Now test GO, RETURN, PROG binding
(SET 'A 'AA) (SET 'B 'BB)
(PROG (A B) (PRINT 'test! binding! of! A!,! B! expect! NIL)
            (PRIN1 A) (PRINT B) 
            (PRINT 'Reset! to! 1!,2)
            (SET 'A 1) (SET 'B 2)
               (PRIN1 A) (PRINT B)
            (PRINT 'test! forward! GO)
               (GO LL)
               (PRINT 'forward! GO! failed)
LL            (PRINT 'Forward! GO! ok)
            (GO L2)
L1        (PRINT '! Should! be! after! BACKWARD! go )
        (PRINT '! now! return! 3)
        (RETURN 3)
L2        (PRINT 'Test! backward! GO)
        (GO L1) )
% Test that A,B correctly rebound, expect AA and BB% 
A B
%  Test simple FEXPR% 
(PUTD (QUOTE FOO) (QUOTE FEXPR) (QUOTE (LAMBDA (X) (PRINT X))))
% Expect (FEXPR LAMBDA (X) (PRINT X))% 
(GETD (QUOTE FOO))
%  Expect (1) (1 2) and (1 2 3)% 
(FOO 1)
(FOO 1 2)
(FOO 1 2 3)
%  Finally, TEST EVAL inside an FEXPR % 
(PUTD (QUOTE FOO) (QUOTE FEXPR)
  (QUOTE (LAMBDA (XX) (PRINT (EVAL (CAR XX))))))
(FOO 1)
(FOO (NULL NIL))
%  PUTD is being used here to define a function !$TEST.%  
(PUTD (QUOTE !$TEST) (QUOTE FEXPR) (QUOTE 
  (LAMBDA (!$X) 
   (PROG (A B) 
     (SET (QUOTE A) (CDR !$X)) 
LOOP (while A (progn
         %  (print (list 'trying (car a)))
           (SET (QUOTE B) (EVAL (CAR A)))
           (COND ( (null (eq b T)) 
            (PROGN (PRIN1 (LIST '!*!*!*!*!*  (CAR A) '! returned B)) 
                   (TERPRI)))) 
     (SET (QUOTE A) (CDR A)) 
     (GO LOOP)))
     (return (LIST (CAR !$X) '! test! complete)) 
           )))) 
% $TEST should be defined.
(GETD (QUOTE !$TEST)) 
%  Global, vector, function-pointer partial test.
(!$TEST 'GLOBAL!,VECTOR (NULL (GLOBAL (QUOTE (!$VECTOR !$CODE TEMP)))) 
     (GLOBALP (QUOTE !$VECTOR)) 
     (GLOBALP (QUOTE !$CODE)) 
     (SET (QUOTE !$VECTOR) (MKVECT 4)) 
     (SET (QUOTE !$CODE) (CDR (GETD (QUOTE CDR)))) ) 
 
 
(!$TEST LIST (EQUAL (LIST 1 (QUOTE A) 'STRING ) 
                    (QUOTE (1 A STRING)))) 

% -----3.1 Elementary Predicates-----%  
% This section tests the elementary predicates of section 3.1 of 
% the Standard LISP Report. In general they will test that the 
% predicate returns non-NIL for the correct case, and NIL for all 
% others.  
 
% CODEP should not return T for numbers as function 
% pointers must not be implemented in this way.  
(!$TEST CODEP (CODEP !$CODE) (NULL (CODEP 1)) 
     (NULL (CODEP T)) (NULL (CODEP NIL)) 
     (NULL (CODEP (QUOTE IDENTIFIER))) 
     (NULL (CODEP 'STRING)) (NULL (CODEP (QUOTE (A . B)))) 
     (NULL (CODEP (QUOTE (A B C)))) 
     (NULL (CODEP !$VECTOR)) ) 
 
% PAIRP must not return T for vectors even if vectors are 
% implemented as lists.  
(!$TEST PAIRP 
     (PAIRP (QUOTE (A . B))) (PAIRP (QUOTE (NIL))) 
     (PAIRP (QUOTE (A B C))) (NULL (PAIRP 0)) 
     (NULL (PAIRP (QUOTE IDENTIFIER))) 
     (NULL (PAIRP 'STRING)) 
     (NULL (PAIRP !$VECTOR)) ) 
 
(!$TEST FIXP (FIXP 1) 
     (NULL (FIXP (QUOTE IDENTIFIER))) 
     (NULL (FIXP (QUOTE 'STRING))) 
     (NULL (FIXP (QUOTE (A . B)))) 
     (NULL (FIXP (QUOTE (A B C)))) 
     (NULL (FIXP !$VECTOR)) 
     (NULL (FIXP !$CODE))  ) 
 
% T and NIL must test as identifiers as must specially 
% escaped character identifiers.  
(!$TEST IDP (IDP (QUOTE IDENTIFIER)) 
     (IDP NIL)  (IDP T) 
     (IDP (QUOTE !1)) (IDP (QUOTE !A)) (IDP (QUOTE !!)) 
     (IDP (QUOTE !()) (IDP (QUOTE !))) (IDP (QUOTE !.)) 
     (IDP (QUOTE !')) (IDP (QUOTE !*)) (IDP (QUOTE !/)) 
     (IDP (QUOTE !+)) (IDP (QUOTE !-)) (IDP (QUOTE !#)) 
     (IDP (QUOTE ! )) (IDP (QUOTE !1!2!3)) (IDP (QUOTE !*!*!*)) 
     (IDP (QUOTE !'ID)) 
     (NULL (IDP 1)) 
     (NULL (IDP 'STRING)) 
     (NULL (IDP (QUOTE (A . B)))) 
     (NULL (IDP (QUOTE (A B C)))) 
     (NULL (IDP !$VECTOR)) 
     (NULL (IDP !$CODE)) ) 
 
% STRINGP should answer T to strings only and not things 
% that might look like strings if the system implements them as 
% identifiers.  
(!$TEST STRINGP (STRINGP 'STRING) 
     (NULL (STRINGP (QUOTE (STRING NOTASTRING)))) 
     (NULL (STRINGP 1)) 
     (NULL (STRINGP (QUOTE A))) 
     (NULL (STRINGP (QUOTE (A . B)))) 
     (NULL (STRINGP (QUOTE (A B C)))) 
     (NULL (STRINGP !$VECTOR)) 
     (NULL (STRINGP !$CODE)) ) 
 
% VECTORP should not answer T to pairs if vectors are 
% implemented as pairs.  
(!$TEST VECTORP (VECTORP !$VECTOR) 
     (NULL (VECTORP 1)) 
     (NULL (VECTORP (QUOTE A))) 
     (NULL (VECTORP 'STRING)) 
     (NULL (VECTORP (QUOTE (A . B)))) 
     (NULL (VECTORP (QUOTE (A B C)))) 
     (NULL (VECTORP !$CODE)) ) 
 
% Vectors are constants in Standard LISP. However T and NIL 
% are special global variables with the values T and NIL.  
(!$TEST CONSTANTP (CONSTANTP 1) 
     (CONSTANTP 'STRING) 
     (CONSTANTP !$VECTOR) 
     (CONSTANTP !$CODE) 
     (NULL (CONSTANTP NIL)) 
     (NULL (CONSTANTP T)) 
     (NULL (CONSTANTP (QUOTE A))) 
     (NULL (CONSTANTP (QUOTE (A . B)))) 
     (NULL (CONSTANTP (QUOTE (A B C)))) ) 
 
% An ATOM is anything that is not a pair, thus vectors are 
% atoms.  
(!$TEST ATOM (ATOM T) (ATOM NIL) (ATOM 1) (ATOM 0) 
     (ATOM 'STRING) (ATOM (QUOTE IDENTIFIER)) 
     (ATOM !$VECTOR) 
     (NULL (ATOM (QUOTE (A . B)))) 
     (NULL (ATOM (QUOTE (A B C)))) ) 
 
 
(!$TEST EQ (EQ NIL NIL) (EQ T T) 
     (EQ !$VECTOR !$VECTOR) 
     (EQ !$CODE !$CODE) 
     (EQ (QUOTE A) (QUOTE A)) 
     (NULL (EQ NIL T)) 
     (NULL (EQ NIL !$VECTOR)) 
     (NULL (EQ (QUOTE (A . B)) (QUOTE (A . B)))) ) 
 
% Function pointers are not numbers, therefore the function 
% pointer $CODE is not EQN to the fixed number 0. Numbers must have 
% the same type to be EQN.  
(!$TEST EQN (EQN 1 1) (EQN 0 0) 
     (EQN FONE FONE)  (EQN FZERO FZERO) 
     (NULL (EQN FONE FZERO)) (NULL (EQN FZERO FONE)) 
     (NULL (EQN 1 FONE)) (NULL (EQN 0 FZERO)) 
     (NULL (EQN 1 0)) (NULL (EQN 0 1)) 
     (NULL (EQN 0 !$CODE)) 
     (NULL (EQN NIL 0)) 
     (EQN NIL NIL)  (EQN T T) (EQN !$VECTOR !$VECTOR) 
     (EQN !$CODE !$CODE) (EQN (QUOTE A) (QUOTE A)) 
     (NULL (EQN (QUOTE (A . B)) (QUOTE (A . B)))) 
     (NULL (EQN (QUOTE (A B C)) (QUOTE (A B C))))  ) 
 
% EQUAL checks for general equality rather than specific, so 
% it must check all elements of general expressions and all elements 
% of vectors for equality. This test assumes that CAR does not have 
% the function pointer value  EQUAL to 0. Further tests of EQUAL 
% are in the vector section 3.9.  
(!$TEST EQUAL (EQUAL NIL NIL) 
     (EQUAL T T) 
     (NULL (EQUAL NIL T)) 
     (EQUAL !$CODE !$CODE) 
     (NULL (EQUAL !$CODE (CDR (GETD (QUOTE CAR))))) 
     (EQUAL (QUOTE IDENTIFIER) (QUOTE IDENTIFIER)) 
     (NULL (EQUAL (QUOTE IDENTIFIER1) (QUOTE IDENTIFIER2))) 
     (EQUAL 'STRING 'STRING) 
     (NULL (EQUAL 'STRING1 'STRING2)) 
     (EQUAL 0 0) 
     (NULL (EQUAL 0 1)) 
     (EQUAL (QUOTE (A . B)) (QUOTE (A . B))) 
     (NULL (EQUAL (QUOTE (A . B)) (QUOTE (A . C)))) 
     (NULL (EQUAL (QUOTE (A . B)) (QUOTE (C . B)))) 
     (EQUAL (QUOTE (A B)) (QUOTE (A B))) 
     (NULL (EQUAL (QUOTE (A B)) (QUOTE (A C)))) 
     (NULL (EQUAL (QUOTE (A B)) (QUOTE (C B)))) 
     (EQUAL !$VECTOR !$VECTOR) 
     (NULL (EQUAL 0 NIL)) 
     (NULL (EQUAL 'T T)) 
     (NULL (EQUAL 'NIL NIL)) ) 
 
% -----3.2 Functions on Dotted-Pairs-----%  
% Test the C....R functions by simply verifying that they select
% correct part of a structure.
(!$TEST CAR (EQ (CAR (QUOTE (A . B))) (QUOTE A)) 
    (EQUAL (CAR (QUOTE ((A) . B))) (QUOTE (A))) ) 
 
(!$TEST CDR (EQ (CDR (QUOTE (A . B))) (QUOTE B)) 
     (EQUAL (CDR (QUOTE (A B))) (QUOTE (B))) ) 
 
(!$TEST CAAR (EQ (CAAR (QUOTE ((A)))) (QUOTE A))) 
(!$TEST CADR (EQ (CADR (QUOTE (A B))) (QUOTE B))) 
(!$TEST CDAR (EQ (CDAR (QUOTE ((A . B)))) (QUOTE B))) 
(!$TEST CDDR (EQ (CDDR (QUOTE (A . (B . C)))) (QUOTE C))) 
 
(!$TEST CAAAR (EQ (CAAAR (QUOTE (((A))))) (QUOTE A))) 
(!$TEST CAADR (EQ (CAADR (QUOTE (A (B)))) (QUOTE B))) 
(!$TEST CADAR (EQ (CADAR (QUOTE ((A B)))) (QUOTE B))) 
(!$TEST CADDR (EQ (CADDR (QUOTE (A B C))) (QUOTE C))) 
(!$TEST CDAAR (EQ (CDAAR (QUOTE (((A . B)) C))) (QUOTE B))) 
(!$TEST CDADR (EQ (CDADR (QUOTE (A (B . C)))) (QUOTE C))) 
(!$TEST CDDAR (EQ (CDDAR (QUOTE ((A . (B . C))))) (QUOTE C))) 
(!$TEST CDDDR (EQ (CDDDR (QUOTE (A . (B . (C . D))))) (QUOTE D))) 
 
(!$TEST CAAAAR (EQ (CAAAAR (QUOTE ((((A)))))) (QUOTE A))) 
(!$TEST CAAADR (EQ (CAAADR (QUOTE (A ((B))))) (QUOTE B))) 
(!$TEST CAADAR (EQ (CAADAR (QUOTE ((A (B))))) (QUOTE B))) 
(!$TEST CAADDR (EQ (CAADDR (QUOTE (A . (B (C))))) (QUOTE C))) 
(!$TEST CADAAR (EQ (CADAAR (QUOTE (((A . (B)))))) (QUOTE B))) 
(!$TEST CADADR (EQ (CADADR (QUOTE (A (B . (C))))) (QUOTE C))) 
(!$TEST CADDAR (EQ (CADDAR (QUOTE ((A . (B . (C)))))) (QUOTE C))) 
(!$TEST CADDDR (EQ (CADDDR (QUOTE (A . (B . (C . (D)))))) (QUOTE D))) 
(!$TEST CDAAAR (EQ (CDAAAR (QUOTE ((((A . B)))))) (QUOTE B))) 
(!$TEST CDAADR (EQ (CDAADR (QUOTE (A ((B . C))))) (QUOTE C))) 
(!$TEST CDADAR (EQ (CDADAR (QUOTE ((A (B . C))))) (QUOTE C))) 
(!$TEST CDADDR (EQ (CDADDR (QUOTE (A . (B . ((C . D)))))) (QUOTE D))) 
(!$TEST CDDAAR (EQ (CDDAAR (QUOTE (((A . (B . C)))))) (QUOTE C))) 
(!$TEST CDDADR (EQ (CDDADR (QUOTE (A . ((B . (C . D)))))) (QUOTE D))) 
(!$TEST CDDDAR (EQ (CDDDAR (QUOTE ((A  . (B . (C . D)))))) (QUOTE D))) 
(!$TEST CDDDDR (EQ (CDDDDR (QUOTE (A . (B . (C . (D . E)))))) (QUOTE E))) 
 
% CONS should return a unique cell when invoked. Also test that
% the left and right parts are set correctly.
(!$TEST CONS (NULL (EQ (CONS (QUOTE A) (QUOTE B)) (QUOTE (A . B)))) 
     (EQ (CAR (CONS (QUOTE A) (QUOTE B))) (QUOTE A)) 
     (EQ (CDR (CONS (QUOTE A) (QUOTE B))) (QUOTE B)) ) 
 
% Veryify that RPLACA doesn't modify the binding of a list, and
% that only the CAR part of the cell is affected.
(!$TEST RPLACA 
  (SET (QUOTE TEMP) (QUOTE (A))) 
  (EQ (RPLACA TEMP 1) TEMP) 
  (EQ (CAR (RPLACA TEMP (QUOTE B))) (QUOTE B))  
  (EQ (CDR TEMP) NIL) )
 
(!$TEST RPLACD 
  (SET (QUOTE TEMP) (QUOTE (A . B))) 
  (EQ (RPLACD TEMP (QUOTE A)) TEMP) 
  (EQ (CDR (RPLACD TEMP (QUOTE C))) (QUOTE C))  
  (EQ (CAR TEMP) (QUOTE A)) )
 
% -----3.3 Identifiers-----%  
% Verify that COMPRESS handles the various types of lexemes
% correctly.
(!$TEST COMPRESS 
  (NULL (EQ (COMPRESS (QUOTE (A B))) (COMPRESS (QUOTE (A B))))) 
  (EQN (COMPRESS (QUOTE (!1 !2))) 12) 
  (EQN (COMPRESS (QUOTE (!+ !1 !2))) 12) 
  (EQN (COMPRESS (QUOTE (!- !1 !2))) -12) 
  (EQUAL (COMPRESS (QUOTE ( S T R I N G ))) 'STRING) 
  (EQ (INTERN (COMPRESS (QUOTE (A B)))) (QUOTE AB))   
  (EQ (INTERN (COMPRESS (QUOTE (!! !$ A)))) (QUOTE !$A)) )
 
% Verify that EXPLODE returns the expected lists and that COMPRESS
% and explode are inverses of each other.
(!$TEST EXPLODE 
  (EQUAL (EXPLODE 12) (QUOTE (!1 !2))) 
  (EQUAL (EXPLODE -12) (QUOTE (!- !1 !2))) 
  (EQUAL (EXPLODE 'STRING) (QUOTE ( S T R I N G ))) 
  (EQUAL (EXPLODE (QUOTE AB)) (QUOTE (A B)) ) 
  (EQUAL (EXPLODE (QUOTE !$AB)) (QUOTE (!! !$ A B)))   
  (EQUAL (COMPRESS (EXPLODE 12)) 12)
  (EQUAL (COMPRESS (EXPLODE -12)) -12)
  (EQUAL (COMPRESS (EXPLODE 'STRING)) 'STRING)
  (EQ (INTERN (COMPRESS (EXPLODE (QUOTE AB)))) (QUOTE AB))
  (EQ (INTERN (COMPRESS (EXPLODE (QUOTE !$AB)))) (QUOTE !$AB)) )
 
% Test that GENSYM returns identifiers and that they are different.
(!$TEST GENSYM 
  (IDP (GENSYM)) 
  (NULL (EQ (GENSYM) (GENSYM))) ) 
 
% Test that INTERN works on strings to produce identifiers the same
% as those read in. Try ID's with special characters in them (more
% will be tested with READ).
(!$TEST INTERN 
  (EQ (INTERN 'A) (QUOTE A)) 
  (EQ (INTERN 'A12) (QUOTE A12))
  (EQ (INTERN 'A!*) (QUOTE A!*))
  (NULL (EQ (INTERN 'A) (INTERN 'B))) ) 
 
% Just test that REMOB returns the ID removed.
(!$TEST REMOB 
  (EQ (REMOB (QUOTE AAAA)) (QUOTE AAAA)) ) 
 
% ----- 3.4 Property List Functions-----%  
% Test that FLAG always returns NIL. More testing is done in FLAGP.
(!$TEST FLAG 
  (NULL (FLAG NIL (QUOTE W))) 
  (NULL (FLAG (QUOTE (U V T NIL)) (QUOTE X))) 
  (NULL (FLAG (QUOTE (U)) NIL)) ) 
 
% Test that FLAG worked only on a list. Test all items in a flagged
% list were flagged and that those that weren't aren't.
(!$TEST FLAGP 
  (NULL (FLAGP NIL (QUOTE W))) 
  (FLAGP (QUOTE U) (QUOTE X)) 
  (FLAGP (QUOTE V) (QUOTE X)) 
  (FLAGP T (QUOTE X)) 
  (FLAGP NIL (QUOTE X)) 
  (FLAGP (QUOTE U) NIL) ) 
 
% Test that REMFLAG always returns NIL and that flags removed are
% gone. Test that unremoved flags are still present.
(!$TEST REMFLAG 
  (NULL (REMFLAG NIL (QUOTE X))) 
  (NULL (REMFLAG (QUOTE (U T NIL)) (QUOTE X))) 
  (NULL (FLAGP (QUOTE U) (QUOTE X))) 
  (FLAGP (QUOTE V) (QUOTE X)) 
  (NULL (FLAGP T (QUOTE X))) 
  (NULL (FLAGP NIL (QUOTE X))) ) 
 
(!$TEST PUT 
  (EQ (PUT (QUOTE U) (QUOTE IND1) (QUOTE PROP)) (QUOTE PROP)) 
  (EQN (PUT (QUOTE U) (QUOTE IND2) 0) 0) 
  (EQ (PUT (QUOTE U) (QUOTE IND3) !$VECTOR) !$VECTOR) 
  (EQ (PUT (QUOTE U) (QUOTE IND4) !$CODE) !$CODE) ) 
 
(!$TEST GET 
  (EQ (GET (QUOTE U) (QUOTE IND1)) (QUOTE PROP)) 
  (EQN (GET (QUOTE U) (QUOTE IND2)) 0) 
  (EQ (GET (QUOTE U) (QUOTE IND3)) !$VECTOR) 
  (EQ (GET (QUOTE U) (QUOTE IND4)) !$CODE) ) 
 
(!$TEST REMPROP 
  (NULL (REMPROP !$CODE !$CODE)) 
  (EQ (REMPROP (QUOTE U) (QUOTE IND1)) (QUOTE PROP)) 
  (NULL (GET (QUOTE U) (QUOTE IND1))) 
  (EQN (REMPROP (QUOTE U) (QUOTE IND2)) (QUOTE 0)) 
  (NULL (GET (QUOTE U) (QUOTE IND2))) 
  (EQ (REMPROP (QUOTE U) (QUOTE IND3)) !$VECTOR) 
  (NULL (GET (QUOTE U) (QUOTE IND3))) 
  (GET (QUOTE U) (QUOTE IND4)) 
  (EQ (REMPROP (QUOTE U) (QUOTE IND4)) !$CODE) 
  (NULL (GET (QUOTE U) (QUOTE IND4)))  ) 
 
 
% -----3.5 Function Definition-----% 
(!$TEST DE 
        (EQ (DE FIE (X) (PLUS2 X 1)) (QUOTE FIE))
        (GETD (QUOTE FIE))
        (EQN (FIE 1) 2)
)
% Expect (FIE 1) to return 2% 
(FIE 1)
% Expect FIE redefined in DF test% 
(!$TEST DF 
        (EQ (DF FIE (X) (PROGN (PRINT X) (CAR X))) (QUOTE FIE))
        (GETD (QUOTE FIE))
        (EQN (FIE 1) 1)
        (EQN (FIE 2 3) 2)
)
% Expect (FIE 1) to return 1, and print (1)% 
(FIE 1)
% Expect (FIE 1 2) to return 1, and print (1 2)% 
(FIE 1 2)
% Expect FIE redefined in DM% 
(!$TEST DM 
        (EQ (DM FIE (X) 
             (LIST (QUOTE LIST) 
                              (LIST (QUOTE QUOTE)  X)
                              (LIST (QUOTE QUOTE)  X) )) 
          (QUOTE FIE))
        (GETD (QUOTE FIE))
        (EQUAL (FIE 1) (QUOTE ((FIE 1) (FIE 1))))
)
% Expect (FIE 1) to return ((FIE 1) (FIE 1))% 
(FIE 1)
(!$TEST GETD 
        (PAIRP (GETD (QUOTE FIE)))
        (NULL (PAIRP (GETD (QUOTE FIEFIEFIE))))
        (EQ (CAR (GETD (QUOTE FIE))) (QUOTE MACRO))
)

(!$TEST PUTD 
        (GLOBALP (QUOTE FIE))
 )
% Should check that a FLUID variable not PUTDable;
(!$TEST REMD 
        (PAIRP (REMD (QUOTE FIE)))
        (NULL (GETD (QUOTE FIE)))
             (NULL (REMD (QUOTE FIE)))
             (NULL (REMD (QUOTE FIEFIEFIE)))
)
% -----3.6 Variables and Bindings------% 
%  Make FLUIDVAR1 and FLUIDVAR2 fluids% 
(FLUID (QUOTE (FLUIDVAR1 FLUIDVAR2)))
% Check that FLUIDVAR1 and FLUIDVAR2 are fluid,expect T, T% 
(FLUIDP (QUOTE FLUIDVAR1))
(FLUIDP (QUOTE FLUIDVAR2))
% Give FLUIDVAR1 and FLUIDVAR2 initial values% 
(SETQ FLUIDVAR1 1)
(SETQ FLUIDVAR2 2)

(!$TEST 'FLUID! and! FLUIDP
        (NULL (FLUID (QUOTE (FLUIDVAR3 FLUIDVAR1 FLUIDVAR2 FLUIDVAR4))))
        (FLUIDP (QUOTE FLUIDVAR3))
        (FLUIDP (QUOTE FLUIDVAR1))
        (FLUIDP (QUOTE FLUIDVAR2))
        (FLUIDP (QUOTE FLUIDVAR4))
        (NULL (GLOBALP (QUOTE FLUIDVAR3)))
        (NULL (GLOBALP (QUOTE FLUIDVAR1)))
        (NULL FLUIDVAR3)
        (EQN FLUIDVAR1 1)
        (NULL (FLUIDP (QUOTE CAR)))
)
(GLOBAL (QUOTE (FLUIDGLOBAL1)))
% Expect ERROR that FLUIDGLOBAL1 already FLUID% 
(FLUID (QUOTE (FLUIDGLOBAL2)))

% Expect ERROR that cant change FLUID% 
(GLOBAL (QUOTE (FLUIDVAR1 FLUIDVAR2 GLOBALVAR1 GLOBALVAR2)))
% Does error cause GLOBALVAR1, GLOBALVAR2 to be declared ;

(!$TEST 'GLOBAL! and! GLOBALP
        (NULL (GLOBAL (QUOTE (GLOBALVAR1 GLOBALVAR2))))
        (GLOBALP (QUOTE GLOBALVAR1))
        (GLOBALP (QUOTE GLOBALVAR2))
        (NULL (GLOBALP (QUOTE FLUIDVAR1)))
        (FLUIDP (QUOTE FLUIDVAR1))
        (NULL (FLUIDP (QUOTE GLOBALVAR1)))
        (NULL (FLUIDP (QUOTE GLOBALVAR2)))
        (GLOBALP (QUOTE CAR))
)

% Set SETVAR1 to have an ID value% 
(SET (QUOTE SETVAR1) (QUOTE SETVAR2))

% Expect SETVAR3 to be declared FLUID% 
(!$TEST SET
        (NULL (FLUIDP (QUOTE SETVAR3)))
        (EQN 3 (SET (QUOTE SETVAR3) 3))
        (EQN 3 SETVAR3)
        (FLUIDP (QUOTE SETVAR3))
        (EQN (SET SETVAR1 4) 4)
        (NULL (EQN SETVAR1 4))
        (EQ SETVAR1 (QUOTE SETVAR2))
        (EQN SETVAR2 4)
)
% Expect ERROR if try to set non ID% 
(SET 1 2)
(SET (QUOTE SETVAR1) 1)
(SET SETVAR1 2)

% Expect ERROR if try to SET T or NIL% 
(SET (QUOTE SAVENIL) NIL)
(SET (QUOTE SAVET) T)
(!$TEST 'Special! SET! value
        (SET (QUOTE NIL) 1)
        (NULL (EQN NIL 1))
        (SET (QUOTE NIL) SAVENIL)
        (SET (QUOTE T) 2)
        (NULL (EQN T 2))
        (SET (QUOTE T) SAVET)
)


% Expect SETVAR3 to be declared FLUID% 
(!$TEST SETQ
        (NULL (FLUIDP (QUOTE SETVAR3)))
        (EQN 3 (SETQ SETVAR3 3))
        (EQN 3 SETVAR3)
        (FLUIDP (QUOTE SETVAR3))
)

% Expect ERROR if try to SETQ T or NIL% 
(SET (QUOTE SAVENIL) NIL)
(SET (QUOTE SAVET) T)
(!$TEST 'Special! SETQ! value
        (SETQ NIL 1)
        (NULL (EQN NIL 1))
        (SETQ NIL SAVENIL)
        (SETQ T 2)
        (NULL (EQN T 2))
        (SETQ T SAVET)
)

(!$TEST UNFLUID
        (GLOBALP (QUOTE GLOBALVAR1))
        (FLUIDP  (QUOTE FLUIDVAR1))
        (NULL (UNFLUID (QUOTE (GLOBALVAR1 FLUIDVAR1))))
        (GLOBALP (QUOTE GLOBALVAR1))
        (NULL (FLUIDP (QUOTE FLUIDVAR1)))
)


% ----- 3.7 Program Feature Functions -----% 

% These have been tested as part of BASIC tests;

% Check exact GO and RETURN scoping rules ;

% ----- 3.8 Error Handling -----% 

(!$TEST EMSG!* (GLOBALP (QUOTE EMSG!*)))

(!$TEST ERRORSET
        (EQUAL (ERRORSET 1 T T) (QUOTE (1)))
        (NULL (PAIRP (ERRORSET (QUOTE (CAR 1)) T T)))
)

% Display ERRORSET range of messages and features% 

% First with primitive (CAR 1) error% 

(SETQ ERRORVAR1 (QUOTE (CAR 1)))

%  Expect MSG and BACKTRACE % 
(ERRORSET ERRORVAR1 T T)
(PRINT (LIST (QUOTE EMSG!*) EMSG!*))
%  Expect MSG, no backtrace % 
(ERRORSET ERRORVAR1 T NIL)
(PRINT (LIST (QUOTE EMSG!*) EMSG!*))
%  Expect no MSG, but BACKTRACE % 
(ERRORSET ERRORVAR1 NIL T)
(PRINT (LIST (QUOTE EMSG!*) EMSG!*))
% Expect neither MSG nor Backtrace% 
(ERRORSET ERRORVAR1 NIL NIL)
(PRINT (LIST (QUOTE EMSG!*) EMSG!*))

% Test with CALL on ERROR, with num=789, (A MESSAGE)% 

(SETQ ERRORVAR2 (QUOTE (ERROR 789 (LIST (QUOTE A) (QUOTE MESSAGE)))))
%  Expect MSG and BACKTRACE % 
(ERRORSET ERRORVAR2 T T)
(PRINT (LIST (QUOTE EMSG!*) EMSG!*))
%  Expect MSG, no backtrace % 
(ERRORSET ERRORVAR2 T NIL)
(PRINT (LIST (QUOTE EMSG!*) EMSG!*))
%  Expect no MSG, but BACKTRACE % 
(ERRORSET ERRORVAR2 NIL T)
(PRINT (LIST (QUOTE EMSG!*) EMSG!*))
% Expect neither MSG nor Backtrace% 
(ERRORSET ERRORVAR2 NIL NIL)
(PRINT (LIST (QUOTE EMSG!*) EMSG!*))

% Test of Rebinding/Unbinding% 

(FLUID (QUOTE (ERRORVAR3 ERRORVAR4)))
(SETQ ERRORVAR3 3)
(SETQ ERRORVAR4 4)

(DE ERRORFN1 (X ERRORVAR3)
  (PROGN (PRINT (LIST (QUOTE ERRORVAR3) ERRORVAR3))
         (SETQ ERRORVAR3 33)
  (PROG (Y ERRORVAR4)
        (PRINT (LIST (QUOTE ERRORVAR3) ERRORVAR3))
        (PRINT (LIST (QUOTE ERRORVAR4) ERRORVAR4))
        (SETQ ERRORVAR3 333)
        (SETQ ERRORVAR4 444)
        (ERROR 555 'Error! Inside! ERRORFN1)
          (RETURN 'Error! Failed))))

% Expect to see 3333 33 44 printed% 
% Followed by ERROR 555 messgae% 
(ERRORSET (QUOTE (ERRORFN1 3333 4444)) T T)
% Expect 3 and 4 as Final values of ERRORVAR3 and ERRORVAR4% 
ERRORVAR3
ERRORVAR4
(!$TEST ERRORVARS
        (EQN ERRORVAR3 3)
        (EQN ERRORVAR4 4)
)
% ----- 3.9 Vectors -----% 
%  Create a few variables that may be vectors % 
(SETQ VECTVAR1 NIL)
(SETQ VECTVAR2 (QUOTE (VECTOR 1 2 3)))
(SETQ VECTVAR3 (QUOTE [1 2 3 4]))

% Expect Type mismatch Error for next 2% 
(GETV VECTVAR1 1)
(GETV VECTVAR2 1)
% Expect 1 2 for next 2% 
(GETV VECTVAR3 0)
(GETV VECTVAR3 1)
% Expect Index error for next 2% 
(GETV VECVAR3 -1)
(GETV VECTVAR3 4)
        

(!$TEST MKVECT
        (VECTORP (SETQ VECTVAR3 (MKVECT 5)))
        (EQN 5 (UPBV VECTVAR3))
        (NULL (GETV VECTVAR3 0))
        (NULL (GETV VECTVAR3 5))
        (EQN 10 (PUTV VECTVAR3 0 10))
        (EQN 10 (GETV VECTVAR3 0))
        (EQN 20 (PUTV VECTVAR3 5 20))
        (EQN 20 (GETV VECTVAR3 5))
)
%  Expect VECTVAR3 to be [ 10 nil nil nil nil 20 ]% 
(PRINT VECTVAR3)

% Expect MKVECT error for index less than 0% 
(MKVECT -1)
% Expect length 1 vector% 
(MKVECT 0)
% Expect type error% 
(MKVECT NIL)
% Expect 2  TYPE  errors% 
(PUTV VECTVAR1 0 1)
(PUTV VECTVAR1 -1 1)

(!$TEST UPBV
        (NULL (UPBV VECTVAR1))
        (EQN (UPBV VECTVAR3 5) 5 )
)
% ----- 3.10 Booleans and Conditionals -----% 
(!$TEST AND
        (EQ T (AND))
        (EQ T (AND T))
        (EQ T (AND T T))
        (EQN 1 (AND T 1))
        (EQ T (AND 1 T))
        (EQ T (AND T T 1 1 T T))
        (NULL (AND NIL))
        (NULL (AND T NIL))
        (NULL (AND NIL T))
        (NULL (AND T T T T NIL T T))
)
% The next should not ERROR, else AND is evaluating all args% 
(AND T T NIL (ERROR 310 'AND! Failed) T)

(!$TEST COND
        (EQN 1 (COND (T 1)))
        (NULL (COND))
        (NULL (COND (NIL 1)))
        (EQN 1 (COND (T 1) (T 2)))
        (EQN 2 (COND (NIL 1) (T 2)))
        (NULL  (COND (NIL 1) (NIL 2)))
)
% Test COND with GO and RETURN% 
(PROG NIL
        (COND (T (GO L1)))
        (ERROR 310 'COND! fell! through)
 L1        (PRINT 'GO! in! cond! worked)
        (COND (T (RETURN (PRINT 'Return! 2))))
        (ERROR 310 'COND! did! not! RETURN)
)
% Certain Extensions to COND might fail% 
%/(COND 1 2)
%/(COND (T))
%/(COND (T 1 2 3))

(!$TEST NOT
        (NULL (NOT T))
        (EQ T (NOT NIL))
)

(!$TEST OR
        (NULL (OR))
        (EQ T (OR T))
        (EQ T (OR T T))
        (EQN T (OR T 1))
        (EQ 1 (OR 1 T))
        (EQ T (OR T T 1 1 T T))
        (NULL (OR NIL))
        (EQ T (OR T NIL))
        (EQ T (OR NIL T))
        (EQ T (OR T T T T NIL T T))
)
% The next should not ERROR, else OR is evaluating all args% 
(OR T NIL NIL (ERROR 310 'OR! Failed) T)

% -----3.11 Arithmetic Functions-----% 
% Setup some ints% 
% Setup some floats% 
(SETQ FZERO (FLOAT 0))
(SETQ FONE (FLOAT 1))
(SETQ FTWO (FLOAT 2))
(SETQ FTHREE (FLOAT 3))
(!$TEST ABS
        (EQN 0 (ABS 0))
        (EQN 1 (ABS 1))
        (EQN 1 (ABS -1))
        (EQN FZERO (ABS FZERO))
        (EQN FONE (ABS FONE))
        (EQN FONE (ABS (MINUS FONE)))
)

(!$TEST ADD1
        (EQN 1 (ADD1 0))
        (EQN 0 (ADD1 -1))
        (EQN 2 (ADD1 1))
        (EQN FONE (ADD1 FZERO))
        (EQN FTWO (ADD1 FONE))
)

(!$TEST DIFFERENCE
        (EQN 0 (DIFFERENCE 1 1))
        (EQN FZERO (DIFFERENCE FONE FONE))
        (EQN FZERO (DIFFERENCE 1 FONE))
        (EQN FZERO (DIFFERENCE FONE 1))
        (EQN 1 (DIFFERENCE 2 1))
        (EQN -1 (DIFFERENCE 1 2))
)

(!$TEST DIVIDE
        (EQUAL (CONS 1 2) (DIVIDE 7 5))
        (EQUAL (CONS -1 -2) (DIVIDE -7 5))
        (EQUAL (CONS -1 2) (DIVIDE 7 -5))
        (EQUAL (CONS 1 -2) (DIVIDE -7 -5))
)
(!$TEST EXPT
        (EQN (EXPT 2 0) 1)
        (EQN (EXPT 2 1) 2)
        (EQN (EXPT 2 2) 4)
        (EQN (EXPT 2 3) 8)
        (EQN (EXPT -2 2) 4)
        (EQN (EXPT -2 3) -8)
)

(!$TEST FIX
        (NUMBERP (FIX FONE))
        (FIXP (FIX FONE))
        (NULL (FLOATP (FIX FONE)))
        (EQN (FIX FONE ) 1)
        (NUMBERP (FIX 1))
        (FIXP (FIX 1))
)

(!$TEST FLOAT
        (NUMBERP (FLOAT 1))
        (FLOATP (FLOAT 1))
        (NULL (FIXP (FLOAT 1)))
        (EQN FONE (FLOAT 1))
)

(!$TEST GREATERP
        (GREATERP 2 1)
        (GREATERP 1 0)
        (GREATERP 0 -1)
        (NULL (GREATERP 2 2))
        (NULL (GREATERP 1 1))
        (NULL (GREATERP 0 0))
        (NULL (GREATERP 0 1))
        (NULL (GREATERP -1 0))
)
(!$TEST LESSP
        (NULL (LESSP 2 1))
        (NULL (LESSP 1 0))
        (NULL (LESSP 0 -1))
        (NULL (LESSP 2 2))
        (NULL (LESSP 1 1))
        (NULL (LESSP 0 0))
        (LESSP 0 1)
        (LESSP -1 0)
)
(!$TEST MAX
        (EQN (MAX 1 2 3) 3)
        (EQN (MAX 3 2 1) 3)
        (EQN 1 (MAX 1 0))
        (EQN 1 (MAX 1))
)
% What is (MAX) ;

(!$TEST MAX2
        (EQN (MAX2 1 2) 2)
        (EQN (MAX2 2 1) 2)
        (EQN 1 (MAX2 1 0))
        (EQN -1 (MAX2 -1 -2))
)
(!$TEST MIN
        (EQN (MIN 1 2 3) 1)
        (EQN (MIN 3 2 1) 1)
        (EQN 0 (MIN 1 0))
        (EQN 1 (MIN 1))
)
% What is (MIN) ;

(!$TEST MIN2
        (EQN (MIN2 1 2) 1)
        (EQN (MIN2 2 1) 1)
        (EQN 0 (MIN2 1 0))
        (EQN 0 (MIN2 0 1))
        (EQN -2 (MIN2 -1 -2))
)
(!$TEST MINUS
        (EQN 0 (MINUS 0))
        (EQN -1 (MINUS 1))
        (MINUSP (MINUS 1))
        (MINUSP -1)
        (LESSP -1 0)
        (EQN 1 (MINUS -1))
)

(!$TEST PLUS
        (EQN 6 (PLUS 1 2 3))
        (EQN 10 (PLUS 1 2 3 4))
        (EQN 0 (PLUS 1 2 3 -6))
        (EQN 3 (PLUS 1 2))
        (EQN 1 (PLUS 1))
)
% What is (PLUS) ;

(!$TEST PLUS2
        (EQN 3 (PLUS2 1 2))
        (EQN 0 (PLUS2 1 -1))
        (EQN 1 (PLUS2 -2 3))
)

(!$TEST QUOTIENT
        (EQN 1 (QUOTIENT 3 3))
        (EQN 1 (QUOTIENT 4 3))
        (EQN 1 (QUOTIENT 5 3))
        (EQN 2 (QUOTIENT 6 3))
        (EQN -1 (QUOTIENT -3 3))
        (EQN -1 (QUOTIENT 3 -3))
        (EQN -1 (QUOTIENT 4 -3))
        (EQN -1 (QUOTIENT -4 3))
)

% Expect 2 ZERO DIVISOR error messages% 
(QUOTIENT 1 0)
(QUOTIENT 0 0)

(!$TEST REMAINDER
        (EQN 0 (REMAINDER 3 3))
        (EQN 1 (REMAINDER 4 3))
        (EQN 2 (REMAINDER 5 3))
        (EQN 0 (REMAINDER 6 3))
        (EQN 0 (REMAINDER -3 3))
        (EQN 0 (REMAINDER 3 -3))
        (EQN -1 (REMAINDER 4 -3))
        (EQN -1 (REMAINDER -4 3))
)

% Expect 2 ZERO DIVISOR  error messages% 
%(REMAINDER 1 0)
%(REMAINDER 0 0)

(!$TEST SUB1
        (EQN 1 (SUB1 2))
        (EQN 0 (SUB1 1))
        (EQN -1 (SUB1 0))
)

(!$TEST TIMES
        (EQN 6 (TIMES 1 2 3))
        (EQN 1 (TIMES 1))
        (EQN 2 (TIMES 1 2))
)
% What is (TIMES) ;

(!$TEST TIMES2
        (EQN 0 (TIMES2 1 0))
        (EQN 0 (TIMES2 0 1))
        (EQN 10 (TIMES2 5 2))
        (EQN -10 (TIMES2 5 -2))
)

% -----3.12 MAP composite functions ------% 

(SETQ LST (QUOTE (1 2 3)))
(DE LISTX (X) (LIST X (QUOTE X)))
(DE PRNTX (X) (PRINT (LISTX X)))

% MAP: Expect 3 lines of output, equivalent to:% 
% ((1 2 3) X)% 
% ((2 3) X)% 
% ((3) X)% 
(!$TEST MAP (NULL (MAP LST (FUNCTION PRNTX))))

% MAPC:          Expect 3 lines of output, equivalent to:% 
% (1 X)% 
% (2 X)% 
% (3 X)% 
(!$TEST MAPC (NULL (MAPC LST (FUNCTION PRNTX))))

% MAPCAN:  Expect 3 lines of output, equivalent to:% 
% (1 X)% 
% (2 X)% 
% (3 X)% 
(!$TEST MAPCAN 
        (EQUAL (MAPCAN LST (FUNCTION PRNTX))
                (QUOTE (1 X 2 X 3 X)))
)

% MAPCAR:  Expect 3 Lines of output, equivalent to:% 
% (1 X)% 
% (2 X)% 
% (3 X)% 
(!$TEST MAPCAR
        (EQUAL        (MAPCAR LST (FUNCTION PRNTX))
                (QUOTE ((1 X) (2 X) (3 X))))
)

% MAPCON:  Expect 3 lines of output, equivalent to:% 
% ((1 2 3) X)% 
% ((2 3) X)% 
% ((3) X)% 
(!$TEST MAPCON
        (EQUAL         (MAPCON LST (FUNCTION PRNTX))
        (QUOTE ((1 2 3) X (2 3) X (3) X)))
)

% MAPLIST: Expect 3 lines of output, equivalent to:% 
% ((1 2 3) X)% 
% ((2 3) X)% 
% ((3) X)% 

(!$TEST MAPLIST
        (EQUAL        (MAPLIST LST (FUNCTION PRNTX))
                (QUOTE (((1 2 3) X) ((2 3) X) ((3) X))))
)

% ----- 3 . 13 Composite Functions -----% 
(SETQ APPVAR1 (QUOTE (1 2 3)))

(!$TEST APPEND
        (NULL (APPEND NIL NIL))
        (EQUAL APPVAR1 (SETQ APPVAR2 (APPEND APPVAR1 NIL)))
        (NULL (EQ APPVAR1 APPVAR2))
        (EQUAL APPVAR1 (SETQ APPVAR2 (APPEND NIL APPVAR1)))
        (EQ APPVAR1 APPVAR2)
        (EQUAL APPVAR1 (APPEND (QUOTE (1)) (QUOTE (2 3))))
        (EQUAL APPVAR1 (APPEND (QUOTE (1 2)) (QUOTE (3))))
)

(SETQ ASSVAR 
   (QUOTE ( ((1 . 1) . ONE) ((2 . 2) . TWO) ((3 . 3) . THREE) ) ) )
(!$TEST ASSOC
        (NULL (ASSOC NIL NIL))
        (NULL (ASSOC 1 NIL))
        (NULL (ASSOC 1 ASSVAR))
        (EQUAL (QUOTE ((1 . 1) . ONE)) (ASSOC (QUOTE (1 . 1)) ASSVAR))
        (EQUAL (QUOTE ((2 . 2) . TWO)) (ASSOC (QUOTE (2 . 2)) ASSVAR))
)
% Expect Error MSG on poor ALIST% 
%(ASSOC (QUOTE (1)) (QUOTE (1 2 3)))

(SETQ DLIST (QUOTE ((AA BB) (EE FF))))

(!$TEST DEFLIST
        (EQUAL (QUOTE (AA EE)) (DEFLIST DLIST (QUOTE DEFLIST)))
        (EQ (QUOTE BB) (GET (QUOTE AA) (QUOTE DEFLIST)))
        (EQ (QUOTE FF) (GET (QUOTE EE) (QUOTE DEFLIST)))
)

(!$TEST DELETE
        (EQUAL (QUOTE ((1 . 1) (2 . 2))) 
               (DELETE (QUOTE (0 . 0)) (QUOTE ((0 . 0) (1 . 1) (2 . 2)))))
        (EQUAL (QUOTE ((0 . 0) (2 . 2))) 
               (DELETE (QUOTE (1 . 1)) (QUOTE ((0 . 0) (1 . 1) (2 . 2)))))
        (EQUAL (QUOTE ((0 . 0) (2 . 2) (1 . 1))) 
               (DELETE (QUOTE (1 . 1)) 
                        (QUOTE ((0 . 0) (1 . 1) (2 . 2) (1 . 1)))))
)

% remove the comments when digit and liter are added.

%(SETQ DIGITLST (QUOTE (!0 !1 !2 !3 !4 !5 !6 !7 !8 !9)))

%(DE TESTEACH (LST FN)
%        (PROG (X)
%         L1     (while t (progn
%            (COND ((NULL (PAIRP LST)) (RETURN T)))
%                (SETQ X (APPLY FN (LIST (CAR LST))))  % Not (FN (CAR LST)) ?
%                (COND ((NULL X) 
%                 (PRINT (LIST '!*!*!*! TESTEACH (CAR LST) 'failed))))
%                (SETQ LST (CDR LST))
%                (GO L1)))))
%
%(!$TEST DIGIT
%        (TESTEACH DIGITLST (FUNCTION DIGIT))
%        (NULL (DIGIT 1))
%        (NULL (DIGIT (QUOTE A)))
%        (NULL (DIGIT '1))
%)

(!$TEST LENGTH
        (EQN 0 (LENGTH (QUOTE A)))
        (EQN 0 (LENGTH 1))
        (EQN 1 (LENGTH (QUOTE (A))))
        (EQN 1 (LENGTH (QUOTE (A . B))))
        (EQN 2 (LENGTH (QUOTE (A B))))
)

%(SETQ UPVAR 
% (QUOTE (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)))
%(SETQ DNVAR
% (QUOTE (a b c d e f g h i j k l m n o p q r s t u v w x y z)))
%
%(!$TEST LITER
%        (TESTEACH UPVAR (FUNCTION LITER))
%        (TESTEACH DNVAR (FUNCTION LITER))
%        (NULL (LITER 'A))
%        (NULL (LITER 1))
%        (NULL (LITER (QUOTE AA)))
%)

(SETQ MEMBVAR (QUOTE ((1 . 1) ( 2 . 2) (3 . 3))))

(!$TEST MEMBER
        (NULL (MEMBER NIL NIL))
        (NULL (MEMBER NIL MEMBVAR))
        (NULL (MEMBER (QUOTE (4 . 4)) MEMBVAR))
        (EQ (CDR MEMBVAR) (MEMBER (QUOTE (2 . 2)) MEMBVAR))
)

(!$TEST MEMQ
        (NULL (MEMQ NIL NIL))
        (EQ MEMBVAR (MEMQ (CAR MEMBVAR) MEMBVAR))
        (NULL (MEMQ (QUOTE (1 . 1)) MEMBVAR))
        (EQ (CDR MEMBVAR) (MEMQ (CADR MEMBVAR) MEMBVAR))
)


(SETQ NCONCVAR1 (LIST 1 2 3))

(!$TEST NCONC
        (EQUAL (QUOTE ( 1 2 3 4 5)) 
         (SETQ NCONCVAR2 (NCONC NCONCVAR1 (QUOTE ( 4 5)))))
        (EQ NCONCVAR1 NCONCVAR2)
        (EQUAL NCONCVAR1 (QUOTE (1 2 3 4 5)))
)

(!$TEST PAIR
        (EQUAL NIL (PAIR NIL NIL))
        (EQUAL (QUOTE ((1 . ONE) (2 . TWO))) 
            (PAIR (QUOTE (1 2)) (QUOTE (ONE TWO))))
)

% expect 2 PAIR mismatch errors% 

%(PAIR (QUOTE (1)) (QUOTE ( ONE TWO)))
%(PAIR (QUOTE (1)) NIL)

(!$TEST REVERSE
        (NULL (REVERSE NIL))
        (EQUAL (QUOTE (1)) (REVERSE (QUOTE (1))))
        (EQUAL (QUOTE (1 2 3)) (REVERSE (QUOTE (3 2 1))))
        (EQUAL (QUOTE ((1 . 2) (2 . 3) (3 4 5)))
           (REVERSE (QUOTE ((3 4 5) (2 . 3) (1 . 2)))))
)

(DE SASSFN NIL
        (PROG2 (PRINT 'Sassfn! Called) 99))

(SETQ SASSVAR (QUOTE ((1 . ONE) (2 . TWO))))

(!$TEST SASSOC
        (EQN 99 (SASSOC NIL NIL (FUNCTION SASSFN)))
        (EQN 99 (SASSOC NIL SASSVAR (FUNCTION SASSFN)))
        (EQUAL (QUOTE (2 . TWO))
                (SASSOC 2 SASSVAR (FUNCTION SASSFN)))
)

% Expect ERROR for poor alist:
%(SASSOC (QUOTE A) (QUOTE (B (A . 1))) (FUNCTION SASSFN))

% Set up SUBLIS values
(SETQ SUBLVAR1 (QUOTE ((X . 1) ((X . X) . 2))))
(SETQ SUBLVAR2 (QUOTE (X X (X . 1) (X . X) ((X . X)))))
(SETQ SUBLVAR3 (QUOTE (1 1 (1 . 1) 2 (2))))

%(!$TEST SUBLIS
%        (NULL (SUBLIS NIL NIL))
%        (EQN 1 (SUBLIS NIL 1))
%        (EQ SUBLVAR2 (SUBLIS NIL SUBLVAR2))
%        (EQUAL SUBLVAR2 (SUBLIS NIL SUBLVAR2))
%        (EQ SUBLVAR2 (SUBLIS (QUOTE ((Y . 3))) SUBLVAR2))
%% Will fail, but nice opt if no action;
%        (EQUAL SUBLVAR2 (SUBLIS (QUOTE ((Y . 3))) SUBLVAR2))
%        (EQUAL SUBLVAR3 (SUBLIS SUBLVAR1 SUBLVAR2))
%)
%
(!$TEST SUBST
        (NULL (SUBST NIL 1 NIL))
        (EQ (QUOTE A) (SUBST NIL 1 (QUOTE A)))
        (EQN 1 (SUBST  1 2 2))
        (EQUAL (CONS 2 2) (SUBST 2 1 (CONS 1 1)))
        (EQUAL (QUOTE (1 1 (1 . 1) (1 . 1) ((1 . 1))))
                (SUBST 1 (QUOTE X) SUBLVAR2))
)
% ----- 3.14 The Interpreter ----% 

% To be done ;

% ----- 3.15 IO -----% 
% ----- 3.16 The Standard LISP Reader ----% 
% To be done ;

% ----- 4.0 Globals ----% 

% To be done ;

% ----- 5.0 Miscellaneous functions -----% 

% to be done ;

(RDS NIL)

Added perq-pascal-lisp-project/pasn.pas version [4549c76bd3].



























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
(*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 %               PASCAL BASED MINI-LISP
 %
 % File:         PASN.RED - Trailer File
 % ChangeDate:   12:26pm  Saturday, 18 July 1981
 % By:           M. L. Griss
 %               Change to add Features for Schlumberger Demo
 %               Add Hooks for CATCH/THROW
 %
 %           All RIGHTS RESERVED
 %           COPYRIGHT (C) - 1981 - M. L. GRISS
 %           Computer Science Department
 %           University of Utah
 %
 %           Do Not distribute with out written consent of M. L. Griss
 %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*)


(* pasN.PAS ---- the last file to be appended, close CATCH, do init *)
BEGIN     (*  Body of Catch  *)
IF initphase=0 THEN  (* Kludge to get into scope of CATCH *)
    BEGIN init; initphase := 1; firstp; END
ELSE BEGIN
    idspace[xthrowing].val := nilref;
    catch_stk:=st;                        (* Capture Stack *)
    catch_bstk:=idspace[xbstack].val;     (* Capture Bstack *)
    xeval;
9999:                                 (* Return Point *)
    IF idspace[xthrowing].val <> nilref
    THEN BEGIN
	st:=catch_stk;
	r[2]:=catch_bstk;
	xunbindto; (* return value, old stack *)
	END;
    END
END (* catch *);

BEGIN   (* Top Level *)
    initphase := 0;
    r[1] := 0;
    Xcatch;
    writeln(tty,'halt');break(tty);
end.

Added perq-pascal-lisp-project/pasn.perq version [35e067ff3f].































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
(*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 %               PASCAL BASED MINI-LISP
 %
 % File:         PASN.RED - Trailer File
 % ChangeDate:   5:39am  Saturday, 26 September 1981
 % By:           M. L. Griss
 %               Add Hooks for CATCH/THROW
 %
 %           All RIGHTS RESERVED
 %           COPYRIGHT (C) - 1981 - M. L. GRISS
 %           Computer Science Department
 %           University of Utah
 %
 %           Do Not distribute with out written consent of M. L. Griss
 %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*)


(* pasN.PAS ---- the last file to be appended, close CATCH, do init *)
BEGIN     (*  Body of Catch  *)
IF initphase=0 THEN  (* Kludge to get into scope of CATCH *)
    BEGIN init; initphase := 1; firstp; END
ELSE BEGIN
    initphase := initphase + 1;
    idspace[xthrowing].val := nilref;
    catch_stk:=st;                        (* Capture Stack *)
    catch_bstk:=idspace[xbstack].val;     (* Capture Bstack *)
    xeval;
    initphase := initphase - 1;
   (* Return Point *)
    IF idspace[xthrowing].val <> nilref
    THEN BEGIN
	st:=catch_stk;
	r[2]:=catch_bstk;
	xunbindto; (* return value, old stack *)
	END;
    END
END (* catch *);

BEGIN   (* Top Level *)
    initphase := 0;
    r[1] := nilref;
    Xcatch;
      writeln('halt after top catch');
 exit(pas0);
end.

Added perq-pascal-lisp-project/pasn.pre version [7dcab7157e].

































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#adptwv      (* Pre-process with filter *)
(*
 
                PASCAL BASED MINI-LISP
 
  File:         PASN.RED - Trailer File
  ChangeDate:   5:39am  Saturday, 26 September 1981
  By:           M. L. Griss
                Add Hooks for CATCH/THROW
 
            All RIGHTS RESERVED
            COPYRIGHT (C) - 1981 - M. L. GRISS
            Computer Science Department
            University of Utah
 
            Do Not distribute with out written consent of M. L. Griss
 
*)


(* pasN.PAS ---- the last file to be appended, close CATCH, do init *)
BEGIN     (*  Body of Catch  *)
IF initphase=0 THEN  (* Kludge to get into scope of CATCH *)
    BEGIN init; initphase := 1; firstp; END
ELSE BEGIN
#p  initphase:=initphase+1;               (* ??? *)
    idspace[xthrowing].val := nilref;
    catch_stk:=st;                        (* Capture Stack *)
    catch_bstk:=idspace[xbstack].val;     (* Capture Bstack *)
    xeval;
#p    initphase:=initphase-1;            (* ??? *)
   (* Return Point *)
#adv 9999:
    IF idspace[xthrowing].val <> nilref
    THEN BEGIN
        st:=catch_stk;
        r[2]:=catch_bstk;
        xunbindto; (* return value, old stack *)
        END;
    END
END (* catch *);

BEGIN   (* Top Level *)
    initphase := 0;
    r[1] := nilref;
    Xcatch;
#d  break(tty);
end.

Added perq-pascal-lisp-project/pl20.prc version [ff1955f149].





































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
PASCAL/UTAH FROM  31-MAR-79     PROC/FUNC LINE NUMBER REPORT OF PL20  .PAS ON 14-MAR-82  AT 16:45:36  

PROC/FUNC   HEAD BEGIN   END

        XTHROW       236   237   240
        TAG_OF       250   252   254
        INFO_OF      257   259   264
        XNULL        267   268   271
                    MARK         288   289   297
                GC_INT       283   299   321
            MKFIXINT     280   323   343
        MKITEM       274   347   363
        MKERR        366   367   369
        SET_INFO     372   373   375
        SET_TAG      378   379   381
        MKIDENT      384   386   388
        MKINT        391   392   394
        MKPAIR       397   398   400
        INT_VAL      403   408   415
        ALLOC        425   426   436
        DEALLOC      438   439   444
        ALLOC1       448   449   449
        DEALLOC1     451   452   452
        ALLOC2       454   455   455
        DEALLOC2     457   458   458
        ALLOC3       460   461   461
        DEALLOC3     463   464   464
        LOAD         473   474   478
        STORE        480   481   483
        LOAD10       486   487   489
        STORE10      491   492   494
        STORENIL     496   497   499
        NMHASH       508   513   522
        EQSTR        524   525   532
        NMLOOKUP     534   540   567
        PUTNM        569   575   587
        XFASTSTAT    596   598   607
            PUSHREF      620   622   639
            MARK         641   646   655
        XGCOLLECT    610   657   709
        XCONS        719   722   739
        XNCONS       741   742   744
        XXCONS       746   747   751
        XCAR         763   764   769
        XCDR         771   772   777
        XRPLACA      779   780   785
        XRPLACD      787   788   793
        ANYCAR       796   797   802
        ANYCDR       804   805   810
            IS_INT       825   828   844
        COMPRESS     819   846   884
            ID_EXPLODE   888   889   898
            INT_EXPLOD   900   903   926
        EXPLODE      886   928   939
            KICK         944   945   953
        GENSYM       941   955   970
        XOPEN        979   985  1023
        XCLOSE      1025  1026  1034
        XRDS        1036  1039  1043
        XWRS        1045  1048  1052
        XTERPRI     1054  1055  1060
        INT_FIELD   1062  1065  1075
        XWRITEINT   1077  1078  1083
        XWRITECHAR  1085  1086  1091
        XWRTOK      1093  1096  1142
        RDCHNL      1145  1146  1171
        EOFCHNL     1174  1175  1181
            DIGIT       1201  1202  1204
            ESCALPHA    1207  1210  1228
            ALPHANUM    1230  1233  1238
            WHITESP     1240  1241  1245
        XRDTOK      1190  1247  1351
            INIT1       1372  1373  1455
            INIT2       1458  1459  1505
        INIT        1360  1528  1531
        XADD1       1540  1543  1546
        XDIFFERENC  1548  1551  1555
        XDIVIDE     1557  1561  1569
        XGREATERP   1571  1574  1582
        XLESSP      1584  1587  1595
        XMINUS      1597  1600  1603
        XPLUS2      1605  1608  1612
        XQUOTIENT   1614  1617  1622
        XREMAINDER  1624  1627  1632
        XTIMES2     1634  1637  1641
        XXAPPLY     1656  1662  1682
        PAS11       1698  1699  1708
        PAS12       1711  1712  1721
        PAS13       1724  1725  1734
        PAS14       1737  1738  1747
        PAS15       1750  1751  1762
        PAS16       1765  1766  1777
        PAS17       1780  1781  1792
        PAS18       1795  1796  1807
        PAS19       1810  1811  1822
        PAS110      1825  1826  1837
        PAS111      1840  1841  1852
        PAS112      1855  1856  1867
        PAS113      1870  1871  1882
        PAS114      1885  1886  1897
        PAS115      1900  1901  1912
        PAS116      1915  1916  1927
        PAS117      1930  1931  1942
        PAS118      1945  1946  1957
        PAS119      1960  1961  1972
        PAS120      1975  1976  1987
        PAS121      1990  1991  2001
        PAS122      2004  2005  2015
        PAS123      2018  2019  2029
        PAS124      2032  2033  2043
        PAS125      2046  2047  2057
        PAS126      2060  2061  2071
        PAS127      2074  2075  2085
        PAS128      2088  2089  2099
        PAS129      2104  2110  2170
        PAS130      2173  2178  2222
        PAS131      2225  2226  2236
        PAS132      2239  2243  2266
        XREAD       2271  2278  2351
        PAS133      2354  2363  2465
        PAS21       2478  2482  2498
        PAS23       2503  2504  2512
        XCODEP      2515  2519  2535
        PAS26       2542  2545  2565
        PAS27       2568  2569  2575
        PAS28       2578  2579  2595
        PAS29       2598  2599  2619
        PAS210      2622  2623  2647
        PAS211      2650  2651  2679
        PAS212      2682  2683  2689
        PAS213      2692  2696  2730
        PAS214      2735  2740  2773
        PAS216      2780  2786  2842
        PAS218      2849  2854  2900
        PAS220      2907  2912  2968
        PAS221      2973  2978  3032
        PAS222      3037  3042  3065
        PAS223      3070  3076  3120
        PAS219      3123  3129  3185
        PAS225      3192  3196  3242
        PAS227      3249  3254  3296
        PAS228      3301  3306  3341
        PAS229      3346  3352  3400
        PAS230      3403  3407  3437
        PAS224      3440  3446  3514
        PAS231      3517  3518  3526
        PAS232      3531  3535  3555
        PAS233      3558  3559  3575
        PAS234      3578  3579  3595
        PAS235      3598  3601  3627
        PAS237      3634  3638  3668
        PAS236      3671  3676  3722
        PAS239      3729  3733  3763
        PAS238      3766  3770  3816
        PAS22       3819  3823  3839
        PAS240      3842  3846  3866
        PAS25       3869  3870  3878
        PAS241      3881  3882  3888
        PAS242      3891  3892  3898
        PAS243      3901  3902  3908
        PAS244      3911  3912  3918
        PAS245      3921  3922  3928
        PAS246      3931  3932  3938
        PAS247      3941  3942  3966
        PAS248      3969  3972  3988
        PAS226      3991  3997  4043
        PAS215      4046  4047  4077
        PAS249      4080  4085  4133
        PAS251      4138  4139  4145
        PAS253      4150  4154  4178
        PAS254      4181  4182  4190
        PAS255      4193  4194  4202
        PAS256      4205  4206  4214
        PAS24       4217  4221  4237
        PAS257      4242  4247  4296
        PAS258      4299  4300  4304
        PAS259      4307  4308  4312
        PAS261      4317  4318  4328
        PAS262      4331  4332  4342
        PAS263      4345  4346  4356
        PAS264      4359  4360  4370
        PAS265      4373  4377  4401
        PAS266      4404  4408  4432
        PAS267      4435  4436  4442
        PAS260      4445  4449  4481
        PAS250      4484  4488  4505
        PAS268      4508  4512  4528
        PAS252      4531  4535  4558
        PAS269      4561  4566  4606
        PAS270      4609  4610  4616
        PAS271      4619  4620  4626
        XPRINT      4629  4630  4644
        PAS272      4647  4648  4662
        PAS273      4665  4666  4694
        PAS274      4697  4698  4724
        PAS275      4727  4730  4766
        PAS276      4769  4773  4803
        XUNBINDTO   4806  4810  4838
        PAS279      4845  4849  4898
        PAS277      4903  4908  4948
        PAS280      4951  4955  4981
        PAS31       4994  4999  5043
        PAS32       5046  5047  5065
        PAS33       5068  5073  5125
        PAS34       5128  5136  5253
        PAS35       5256  5259  5289
        PAS36       5294  5298  5332
        PAS37       5335  5336  5358
        PAS38       5361  5362  5384
        PAS39       5387  5388  5410
        PAS310      5413  5414  5436
        XEVAL       5443  5457  5606
        PAS312      5609  5610  5628
        PAS217      5631  5635  5659
        PAS311      5662  5666  5698
        PAS313      5701  5702  5708
        PAS314      5711  5712  5718
        PAS278      5721  5725  5753
        PAS315      5756  5757  5771
        PAS316      5774  5779  5853
        PAS317      5856  5860  5888
        PAS319      5893  5899  6021
        PAS320      6024  6029  6063
        PAS321      6066  6071  6115
        PAS322      6118  6126  6194
        PAS323      6197  6202  6236
        PAS318      6239  6243  6271
        PAS324      6274  6278  6306
        PAS325      6313  6317  6357
        PAS327      6362  6366  6404
        PAS328      6409  6413  6453
        PAS329      6458  6462  6500
        PAS326      6503  6509  6551
        PAS330      6554  6555  6561
        PAS331      6564  6565  6569
        PAS332      6574  6578  6608
        PAS333      6611  6612  6618
        PAS334      6621  6622  6628
        PAS335      6631  6632  6638
        PAS336      6641  6642  6648
        PAS337      6651  6652  6656
        PAS338      6659  6660  6666
        PAS339      6669  6673  6697
        PAS340      6700  6701  6709
        PAS341      6712  6713  6719
        PAS342      6722  6723  6729
        PAS343      6732  6733  6739
        PAS344      6742  6743  6749
        PAS345      6752  6753  6759
        PAS346      6762  6763  6769
        PAS347      6772  6773  6779
        PAS348      6782  6783  6789
        PAS349      6792  6796  6818
        PAS350      6821  6824  6860
        FIRSTP      6863  6871  7007
        EXECUTE     7008  7009  7417
    XCATCH       219  7439  7456
PAS0          31  7458  7463

Added perq-pascal-lisp-project/poltok.red version [0daa262c75].

































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
LISP$
% Simple TOKEN scanner to Debug POLY. RED;
% Griss and Morrison

GLOBAL '(CURCHARTYPE!* CURCHAR!* TOK!*);

SYMBOLIC PROCEDURE CLEARTOKEN;              %. Clear token scanner
 <<CURCHARTYPE!* := 'WHITE; CURCHAR!* := '! >>;

SYMBOLIC PROCEDURE NTOKEN;		%. get next token
BEGIN SCALAR TOK;
  WHILE CURCHARTYPE!* MEMQ '(WHITE COMMENT) DO
    IF CURCHARTYPE!* EQ 'WHITE THEN
      READCHAR()
    ELSE << % Skip the comment
      REPEAT
	READCHAR()
      UNTIL CURCHAR!* MEMQ COMMENTEND!*;
    READCHAR() >>;
  IF CURCHARTYPE!* EQ 'DIGIT THEN <<
    WHILE CURCHARTYPE!* EQ 'DIGIT DO <<
      TOK := CURCHAR!* . TOK;
      READCHAR() >>;
    TOK!* := COMPRESS REVERSIP TOK >>
  ELSE IF CURCHARTYPE!* MEMQ '(LETTER ESCAPE) THEN <<
    WHILE CURCHARTYPE!* MEMQ '(LETTER ESCAPE) DO <<
      IF CURCHARTYPE!* EQ 'ESCAPE THEN <<
	TOK := '!! . TOK;
	READCHAR() >>;
      TOK := CURCHAR!* . TOK;
      READCHAR() >>;
    TOK!* := INTERN COMPRESS REVERSIP TOK >>
  ELSE IF CURCHARTYPE!* EQ 'DELIMITER THEN <<
    TOK!* := CURCHAR!*;
    READCHAR();TOK!* >>
  ELSE IF CURCHARTYPE!* EQ 'TERMINATOR THEN <<
     TOK!* := CURCHAR!*;    CLEARTOKEN();   TOK!*>>
  ELSE
    ERROR(1010,
	  LIST( "Illegal character `",COMPRESS LIST('!!,CURCHAR!*),
			          "' in input stream -- NTOKEN") );
END NTOKEN;

SYMBOLIC PROCEDURE READCHAR;	%. Get next char and classify
<< CURCHAR!* := READCH();
   CURCHARTYPE!* := GET(CURCHAR!*,'CHARACTERTYPE) >>;

SYMBOLIC PROCEDURE INITTOKEN;	%. Initialise TOKEN scan
 BEGIN
DEFLIST('(
 (A LETTER)
 (B LETTER)
 (C LETTER)
 (D LETTER)
 (E LETTER)
 (F LETTER)
 (G LETTER)
 (H LETTER)
 (I LETTER)
 (J LETTER)
 (K LETTER)
 (L LETTER)
 (M LETTER)
 (N LETTER)
 (O LETTER)
 (P LETTER)
 (Q LETTER)
 (R LETTER)
 (S LETTER)
 (T LETTER)
 (U LETTER)
 (V LETTER)
 (W LETTER)
 (X LETTER)
 (Y LETTER)
 (Z LETTER)
 (a LETTER)
 (b LETTER)
 (c LETTER)
 (d LETTER)
 (e LETTER)
 (f LETTER)
 (g LETTER)
 (h LETTER)
 (i LETTER)
 (j LETTER)
 (k LETTER)
 (l LETTER)
 (m LETTER)
 (n LETTER)
 (o LETTER)
 (p LETTER)
 (q LETTER)
 (r LETTER)
 (s LETTER)
 (t LETTER)
 (u LETTER)
 (v LETTER)
 (w LETTER)
 (x LETTER)
 (y LETTER)
 (z LETTER)
 (!_ LETTER)
 (!. LETTER)
 (!0 DIGIT)
 (!1 DIGIT)
 (!2 DIGIT)
 (!3 DIGIT)
 (!4 DIGIT)
 (!5 DIGIT)
 (!6 DIGIT)
 (!7 DIGIT)
 (!8 DIGIT)
 (!9 DIGIT)
 (!+ DELIMITER)
 (!- DELIMITER)
 (!* DELIMITER)
 (!/ DELIMITER)
 (!^ DELIMITER)
 (!' DELIMITER)
 (!( DELIMITER)
 (!) DELIMITER)
 (!, DELIMITER)
 (!; TERMINATOR)
 (!! ESCAPE)
 (!  WHITE)     % Blank
 (!	 WHITE)	% Tab
 (!  WHITE)	% Carriage Return
 (!
 WHITE)	% Line Feed
 (! WHITE)	% Form Feed
 (!% COMMENT)
   ), 'CHARACTERTYPE);
	PUT(!$EOL!$,'CHARACTERTYPE,'WHITE);
	COMMENTEND!* := LIST !$EOL!$;
	CLEARTOKEN();
END;

INITTOKEN();

SYMBOLIC PROCEDURE XAPPLY(FN,ARGS);     %. Interface for PLISP
   APPLY(FN,ARGS)$

END$

Added perq-pascal-lisp-project/poly.ini version [11eb9a5528].

cannot compute difference between binary files

Added perq-pascal-lisp-project/poly.red version [63bc0160db].

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
OFF ECHO,RAISE$
LISP;

% Simple POLY, RAT AND ALG system, based on POLY by Fitch and Marti. 
% Modifed by GRISS and GALWAY
% September 1980. 
% Further modified by MORRISON
% October 1980.
% Parser modified by OTTENHEIMER
% February 1981, to be left associative March 1981.
% Current bug: print routines print as if right associative.
% MORRISON again, March 1981.
% Parses INFIX expressions to PREFIX, then SIMPlifies and PRINTs
% Handles also PREFIX expressions

% RUNNING: After loading POLY.RED, run function ALGG();
%   This accepts a sequence of expressions:
%	 <exp> ;	 (Semicolon terminator)
%	 <exp> ::= <term> [+ <exp>  | - <exp>]
%	 <term> ::= <primary> [* <term> | / <term>]
%	 <primary> ::= <primary0> [^ <primary0> | ' <primary0> ]
%		 ^ is exponentiation, ' is derivative
%	 <primary0> ::= <number> | <variable> | ( <exp> )

% PREFIX Format:	<number> | <id> | (op arg1 arg2)
%		+ -> PLUS2
%		- -> DIFFERENCE (or MINUS)
%		* -> TIMES2
%		/ -> QUOTIENT
%		^ -> EXPT
%		' -> DIFF

% Canonical Formats: Polynomial: integer | (term . polynomial)
%                    term      : (power . polynomial)
%                    power     : (variable . integer)
%                    Rational  : (polynomial .  polynomial)

%******************** Selectors and Constructors **********************

SYMBOLIC SMACRO PROCEDURE RATNUM X; % parts of Rational
 CAR X;

SYMBOLIC SMACRO PROCEDURE RATDEN X;
 CDR X;

SYMBOLIC SMACRO PROCEDURE MKRAT(X,Y);
  CONS(X,Y);

SYMBOLIC SMACRO PROCEDURE POLTRM X;	% parts of Poly
 CAR X;

SYMBOLIC SMACRO PROCEDURE POLRED X;
 CDR X;

SYMBOLIC SMACRO PROCEDURE MKPOLY(X,Y);
 CONS(X,Y);

SYMBOLIC SMACRO PROCEDURE TRMPWR X;	% parts of TERM
 CAR X;

SYMBOLIC SMACRO PROCEDURE TRMCOEF X;
 CDR X;

SYMBOLIC SMACRO PROCEDURE MKTERM(X,Y);
 CONS(X,Y);

SYMBOLIC SMACRO PROCEDURE PWRVAR X;	% parts of Poly
 CAR X;

SYMBOLIC SMACRO PROCEDURE PWREXPT X;
 CDR X;

SYMBOLIC SMACRO PROCEDURE MKPWR(X,Y);
 CONS(X,Y);

SYMBOLIC SMACRO PROCEDURE POLVAR X;
 PWRVAR TRMPWR POLTRM X;

SYMBOLIC SMACRO PROCEDURE POLEXPT X;
 PWREXPT TRMPWR POLTRM X;

SYMBOLIC SMACRO PROCEDURE POLCOEF X;
  TRMCOEF POLTRM X;

%*********************** Utility Routines *****************************

SYMBOLIC PROCEDURE VARP X;
 IDP X OR (PAIRP X AND IDP CAR X);


%*********************** Entry Point **********************************

GLOBAL '(!*RBACKTRACE !*RECHO REXPRESSION!* !*RMESSAGE);

!*RECHO := !*RMESSAGE := T;

SYMBOLIC PROCEDURE ALGG();	%. Main LOOP, end with QUIT OR Q
BEGIN SCALAR VVV;
      ALGINIT();
      CLEARTOKEN();		% Initialize scanner
LOOP: VVV := ERRORSET('(RPARSE),T,!*RBACKTRACE);
      IF ATOM VVV THEN		% What about resetting the Scanner?
	<<PRINT LIST('ALGG, 'error, VVV); CLEARTOKEN();GO TO LOOP>>;
      REXPRESSION!* := CAR VVV;
      IF !*RECHO THEN PRINT REXPRESSION!*;
      IF REXPRESSION!* EQ 'QUIT THEN <<
	PRINT 'QUITTING;
	RETURN >>;
      ERRORSET('(PREPRINT (PRESIMP REXPRESSION!*)),T,!*RBACKTRACE);
  GO TO LOOP
END ALGG;

SYMBOLIC PROCEDURE ALGINIT();   %. Called to INIT tables
 BEGIN  
	INITTOKEN();
	PUT('TIMES2,'RSIMP,'R!*);	%. Simplifier Tables
	PUT('PLUS2,'RSIMP,'R!+);
	PUT('DIFFERENCE,'RSIMP,'R!-);
	PUT('QUOTIENT,'RSIMP,'R!/);
	PUT('EXPT,'RSIMP,'R!^);
	PUT('DIFF,'RSIMP,'R!');
	PUT('MINUS,'RSIMP,'R!.NEG);
	PUT('!+,'REXP,'PLUS2);	 % Use corresponding 'R!xx in EVAL mode
	PUT('!-,'REXP,'DIFFERENCE);
	PUT('!*,'RTERM,'TIMES2);;
	PUT('!/,'RTERM,'QUOTIENT);
	PUT('!^,'RPRIMARY,'EXPT);
	PUT('!','RPRIMARY,'DIFF);
	PUT('PLUS2,'PRINOP,'PLUSPRIN);	%. Output funs
	PUT('DIFFERENCE,'PRINOP,'DIFFERENCEPRIN);
	PUT('TIMES2,'PRINOP,'TIMESPRIN);
	PUT('QUOTIENT,'PRINOP,'QUOTPRIN);
	PUT('EXPT,'PRINOP,'EXPPRIN);
 END;

SYMBOLIC PROCEDURE RSIMP X;	 %. Simplify Prefix Form to Canonical
 IF ATOM X THEN RCREATE X
  ELSE BEGIN SCALAR Y,OP;
   OP:=CAR X; 
   IF (Y:=GET(OP,'RSIMP)) THEN RETURN XAPPLY(Y,RSIMPL CDR X);
  Y:=PRESIMP X;      % As "variable" ? 
  IF ATOM Y OR NOT(X=Y) THEN RETURN RSIMP Y;
  RETURN RCREATE Y;
 END;

SYMBOLIC PROCEDURE RSIMPL X;	%. Simplify argument list
 IF NULL X THEN NIL  ELSE RSIMP(CAR X) . RSIMPL CDR X;

SYMBOLIC PROCEDURE PRESIMP X;	 %. Simplify Prefix Form to PREFIX
 IF ATOM X THEN X
  ELSE BEGIN SCALAR Y,OP;
   OP:=CAR X; 
   IF (Y:=GET(OP,'RSIMP)) THEN RETURN RAT2PRE XAPPLY(Y,RSIMPL CDR X);
   X:=PRESIMPL CDR X;
   IF (Y:=GET(OP,'PRESIMP)) THEN RETURN XAPPLY(Y,X);
   RETURN (OP . X);
 END;

SYMBOLIC PROCEDURE PRESIMPL X;	%. Simplify argument list
 IF NULL X THEN NIL  ELSE PRESIMP(CAR X) . PRESIMPL CDR X;

%**************** Simplification Routines for Rationals ***************

SYMBOLIC PROCEDURE R!+(A,B);	%. RAT addition
    IF RATDEN A = RATNUM B THEN
	MAKERAT(P!+(RATNUM A,RATNUM B),CDR A)
     ELSE
	MAKERAT(P!+(P!*(RATNUM A,RATDEN B),
		     P!*(RATDEN A,RATNUM B)),
		P!*(RATDEN A,RATDEN B));

SYMBOLIC PROCEDURE R!-(A,B);	%. RAT subtraction
    R!+(A,R!.NEG B);

SYMBOLIC PROCEDURE R!.NEG A;	%. RAT negation
    MKRAT(P!.NEG RATNUM A,RATDEN A);

SYMBOLIC PROCEDURE R!*(A,B);	%. RAT multiplication
    BEGIN SCALAR X,Y;
	X:=MAKERAT(RATNUM A,RATDEN B);
	Y:=MAKERAT(RATNUM B,RATDEN A);
	IF RATNUM X=0 OR RATNUM Y=0 THEN RETURN 0 . 1;
	RETURN MKRAT(P!*(RATNUM X,RATNUM Y),
		    P!*(RATDEN X,RATDEN Y))
END;

SYMBOLIC PROCEDURE R!.RECIP A;	%. RAT inverse
    IF RATNUM A=0 THEN ERROR(777,'(ZERO DIVISOR))
    ELSE MKRAT(RATDEN A,RATNUM A);

SYMBOLIC PROCEDURE R!/(A,B); 	%. RAT division
   R!*(A,R!.RECIP B);

SYMBOLIC PROCEDURE R!.LVAR A;	%. Leading VARIABLE of RATIONAL
 BEGIN SCALAR P;
	P:=RATNUM A;
	IF NUMBERP P THEN RETURN ERROR(99,'(non structured polynomial));
	P:=POLVAR P;
	RETURN P;
 END;

SYMBOLIC PROCEDURE R!'(A,X);	%. RAT derivative
 <<X:=R!.LVAR X;
   IF RATDEN A=1 THEN MKRAT(PDIFF(RATNUM A,X),1)
    ELSE R!-(MAKERAT(PDIFF(RATNUM A,X),RATDEN A),
	     MAKERAT(P!*(RATNUM A,PDIFF(RATDEN A,X)),
		     P!*(RATDEN A,RATDEN A) ) ) >>;

SYMBOLIC PROCEDURE RCREATE X;		%. RAT create
    IF NUMBERP X THEN X . 1
     ELSE IF VARP X THEN (PCREATE X) . 1
     ELSE ERROR(100,LIST(X, '(non kernel)));

SYMBOLIC PROCEDURE MAKERAT(A,B);
IF A=B THEN MKRAT(1,1)
 ELSE IF A=0 THEN 0 . 1
 ELSE IF B=0 THEN ERROR(777,'(ZERO DIVISOR))
 ELSE IF NUMBERP A AND NUMBERP B THEN 
	BEGIN SCALAR GG;
	    GG:=NUMGCD(A,B);
            IF B<0 THEN <<B:=-B; A := -A>>;
    	    RETURN MKRAT(A/GG,B/GG)
	END
 ELSE BEGIN SCALAR GG,NN;
	GG:=PGCD(A,B);
	IF GG=1 THEN RETURN MKRAT(A,B);
	NN:=GG;
LL:	IF NUMBERP NN THEN NN:=GCDPT(GG,NN)
	 ELSE << NN:=POLCOEF GG; GOTO LL >>;
	GG:=CAR PDIVIDE(GG,NN);
	RETURN MKRAT(DIVIDEOUT(A,GG),DIVIDEOUT(B,GG))
END;

SYMBOLIC PROCEDURE R!^(A,N);		%. RAT Expt
 BEGIN  SCALAR AA;
   N:=RATNUM N;
   IF NOT NUMBERP N THEN RETURN ERROR(777,'(Non numeric exponent))
      ELSE IF N=0 THEN RETURN RCREATE 1;
     IF N<0 THEN <<A:=R!.RECIP A; N:=-N>>;
	AA:=1 . 1;
	FOR I:=1:N DO AA:=R!*(AA,A);
	RETURN AA
  END;

%**************** Simplification Routines for Polynomials *************

SYMBOLIC PROCEDURE P1!+(A, B);	% Fix for UCSD pascal to cut down proc size
    BEGIN SCALAR AA,BB;
    AA:=P!+(POLCOEF A,POLCOEF B);
    IF AA=0 THEN RETURN P!+(POLRED A,POLRED B);
    AA:=MKPOLY(TRMPWR POLTRM A,AA);
    AA:=ZCONS AA; BB:=P!+(POLRED A,POLRED B);
    RETURN P!+(AA,BB) 
    END P1!+;

SYMBOLIC PROCEDURE P!+(A,B);	%. POL addition
    IF A=0 THEN B  ELSE IF B=0 THEN A  ELSE
    IF NUMBERP A AND NUMBERP B THEN PLUS2(A,B)
     ELSE IF NUMBERP A THEN MKPOLY(POLTRM B,P!+(A,POLRED B))
     ELSE IF NUMBERP B THEN MKPOLY(POLTRM A,P!+(B,POLRED A))
     ELSE BEGIN SCALAR ORD;
	ORD:=PORDERP(POLVAR A,POLVAR B);
	IF ORD=1 THEN RETURN MKPOLY(POLTRM A,P!+(POLRED A,B));
	IF ORD=-1 THEN RETURN MKPOLY(POLTRM B,P!+(POLRED B,A));
	IF POLEXPT A=POLEXPT B THEN RETURN P1!+(A, B);
	IF POLEXPT A>POLEXPT B THEN RETURN
		MKPOLY(POLTRM A,P!+(POLRED A,B));
	RETURN MKPOLY(POLTRM B,P!+(POLRED B,A))
    END;

SYMBOLIC PROCEDURE PORDERP(A,B);	%. POL variable ordering
  IF A EQ B THEN 0
	 ELSE IF ORDERP(A,B) THEN 1  ELSE -1;

SYMBOLIC PROCEDURE P!*(A,B);		%. POL multiply
    IF NUMBERP A THEN
        IF A=0 THEN 0
	 ELSE IF NUMBERP B THEN TIMES2(A,B)
	 ELSE CONS(CONS(CAAR B,PNTIMES(CDAR B,A)),
		  PNTIMES(CDR B,A))
     ELSE IF NUMBERP B THEN  PNTIMES(A,B)
     ELSE P!+(PTTIMES(CAR A,B),P!*(CDR A,B));

SYMBOLIC PROCEDURE PTTIMES(TT,A);	%. POL term mult
    IF NUMBERP A THEN
	IF A=0 THEN 0  ELSE
	ZCONS CONS(CAR TT,PNTIMES(CDR TT,A))
     ELSE P!+(TTTIMES(TT,CAR A),PTTIMES(TT,CDR A));

SYMBOLIC PROCEDURE PNTIMES(A,N);	%. POL numeric coef mult
    IF N=0 THEN 0
     ELSE IF NUMBERP A THEN TIMES2(A,N)
     ELSE CONS(CONS(CAAR A,PNTIMES(CDAR A,N)),PNTIMES(CDR A,N));

SYMBOLIC PROCEDURE TTTIMES(TA,TB);	%. TERM Mult
    BEGIN SCALAR ORD;
	ORD:=PORDERP(CAAR TA,CAAR TB);
	RETURN IF ORD=0 THEN
		ZCONS(CONS(CONS(CAAR TA,PLUS2(CDAR TA,CDAR TB)),
			P!*(CDR TA,CDR TB)))
	 ELSE IF ORD=1 THEN
		ZCONS(CONS(CAR TA,P!*(ZCONS TB,CDR TA)))
	 ELSE    ZCONS(CONS(CAR TB,P!*(ZCONS TA,CDR TB)))
END;

SYMBOLIC PROCEDURE ZCONS A; 		%. Make single term POL
  CONS(A,0);

SYMBOLIC PROCEDURE PCREATE1(X);          %. Create POLY from Variable/KERNEL
	ZCONS(CONS(CONS(X,1),1));

SYMBOLIC PROCEDURE PCREATE X;
 IF IDP X THEN PCREATE1 X
  ELSE IF PAIRP X AND IDP CAR X THEN PCREATE1 MKKERNEL X
  ELSE ERROR(1000,LIST(X, '(bad kernel)));

SYMBOLIC PROCEDURE PGCD(A,B);		%. POL Gcd
% A and B must be primitive.
IF A=1 OR B=1 THEN 1  ELSE
IF NUMBERP A AND NUMBERP B THEN NUMGCD(A,B)
 ELSE IF NUMBERP A THEN GCDPT(B,A)
 ELSE IF NUMBERP B THEN GCDPT(A,B)
 ELSE BEGIN SCALAR ORD;
	ORD:=PORDERP(CAAAR A,CAAAR B);
	IF ORD=0 THEN RETURN GCDPP(A,B);
	IF ORD>0 THEN RETURN GCDPT(A,B);
	RETURN GCDPT(B,A)
END;

SYMBOLIC PROCEDURE NUMGCD(A,B);		%. Numeric GCD
	IF A=0 THEN ABS B
	 ELSE NUMGCD(REMAINDER(B,A),A);

SYMBOLIC PROCEDURE GCDPT(A,B);		%. POL GCD, non-equal vars
IF NUMBERP A THEN IF NUMBERP B THEN NUMGCD(A,B)  ELSE
	GCDPT(B,A)  ELSE
BEGIN SCALAR ANS,ANS1;
	ANS:=PGCD(CDAR A,B);
	A:=CDR A;
	WHILE NOT NUMBERP A DO <<
	    ANS1:=PGCD(CDAR A,B);
	    ANS:=PGCD(ANS,ANS1);
	    A:=CDR A;
	    IF ANS=1 THEN RETURN ANS >>;
	RETURN IF A=0 THEN ANS  ELSE GCDPT(ANS,A)
END;

SYMBOLIC PROCEDURE GCDPP(A,B);		%. POL GCD, equal vars
BEGIN SCALAR TT,PA,ALPHA,PREVALPHA;
	IF POLEXPT B>POLEXPT A THEN <<
	  TT := A;
	  A := B;
	  B := TT >>;
	ALPHA := 1;
LOOP:	PREVALPHA := ALPHA;
	ALPHA := POLCOEF B;
	PA := POLEXPT A - POLEXPT B;
	IF PA<0 THEN <<
          PRINT A;
	  PRINT B;
	  PRINT PA;
	  ERROR(999,'(WRONG)) >>;
	WHILE NOT (PA=0) DO <<
	  PA := PA-1;
	  ALPHA := P!*(POLCOEF B,ALPHA) >>;
	A := P!*(A,ALPHA);	% to ensure no fractions;
	TT := CDR PDIVIDE(A,B);	% quotient and remainder of polynomials;
	IF TT=0 THEN
	  RETURN B;	% which is the GCD;
	A := B;
	B := PDIVIDE(TT,PREVALPHA);
	IF NOT(CDR B=0) THEN
	  ERROR(12,'(REDUCED PRS FAILS));
	B := CAR B;
	IF NUMBERP B OR NOT (POLVAR A EQ POLVAR B) THEN RETURN 1;
                % Lost leading VAR we started with. /MLG
	GO TO LOOP
END;

SYMBOLIC PROCEDURE DIVIDEOUT(A,B);	%. POL exact division
	CAR PDIVIDE(A,B);
	    
SYMBOLIC PROCEDURE PDIVIDE(A,B);	%. POL (quotient.remainder)
    IF NUMBERP A THEN
	IF NUMBERP B THEN DIVIDE(A,B)
	 ELSE CONS(0,A)
    ELSE IF NUMBERP B THEN
	BEGIN SCALAR SS,TT;
	SS:=PDIVIDE(CDR A,B);
	TT:=PDIVIDE(CDAR A,B);
	RETURN CONS(
		P!+(P!*(ZCONS CONS(CAAR A,1),CAR TT),CAR SS),
		P!+(P!*(ZCONS CONS(CAAR A,1),CDR TT),CDR SS))
	END
    ELSE
	BEGIN SCALAR QQ,BB,CC,TT;
        IF NOT(POLVAR A EQ POLVAR B) OR POLEXPT A < POLEXPT B THEN
	    RETURN CONS(0,A);		% Not same var/MLG, degree check/DFM
	
	QQ:=PDIVIDE(POLCOEF A,POLCOEF B);	% Look for leading term;
	IF NOT(CDR QQ=0) THEN RETURN CONS(0,A);
	QQ:=CAR QQ;			%Get the quotient;
	BB:=P!*(B,QQ);
	IF CDAAR A > CDAAR B THEN
	    << TT:=ZCONS CONS(CONS(CAAAR A,CDAAR A-CDAAR B),1);
	    BB:=P!*(BB,TT);
	    QQ:=P!*(QQ,TT)
	    >>;
	CC:=P!-(A,BB);			%Take it off;
        BB:=PDIVIDE(CC,B);
	RETURN CONS(P!+(QQ,CAR BB),CDR BB)
        END;

SYMBOLIC PROCEDURE P!-(A,B);		%. POL subtract
    P!+(A,P!.NEG B);

SYMBOLIC PROCEDURE P!.NEG(A);		%. POL Negate
  IF NUMBERP A THEN -A
     ELSE CONS(CONS(CAAR A,P!.NEG CDAR A),P!.NEG CDR A);

SYMBOLIC PROCEDURE PDIFF(A,X);		%. POL derivative (to variable)
    IF NUMBERP A THEN 0
     ELSE BEGIN SCALAR ORD;
	ORD:=PORDERP(POLVAR A,X);
	RETURN
	IF ORD=-1 THEN 0
	 ELSE IF ORD=0 THEN 
	    IF CDAAR A=1 THEN
		CDAR A
	     ELSE P!+(ZCONS CONS(CONS(X,CDAAR A-1),P!*(CDAAR A,CDAR A)),
		     PDIFF(CDR A,X))
	 ELSE P!+(P!*(ZCONS CONS(CAAR A,1),PDIFF(CDAR A,X)),PDIFF(CDR A,X))
END;

SYMBOLIC PROCEDURE MKKERNEL X;
 BEGIN SCALAR KERNELS,K,OP;
       K:=KERNELS:=GET(OP:=CAR X,'KERNELS);
 L:    IF NULL K THEN RETURN<<PUT(OP,'KERNELS,X.KERNELS);X>>;
       IF X=CAR K THEN RETURN CAR K;
	K:=CDR K;
	GOTO L
  END;

%***************************** Parser *********************************

% Simple parser creates expressions to be evaluated by the
% rational polynomial routines.
% J.  Marti, August 1980. 
% Modified and Extended by GRISS and GALWAY
% Rewritten to be left associative by OTTENHEIMER, March 1981


GLOBAL '(TOK!*);

SYMBOLIC PROCEDURE RPARSE();	%. PARSE Infix to Prefix
BEGIN SCALAR X;
  NTOKEN();
  IF TOK!* EQ '!; THEN RETURN NIL;	% Fix for null exp RBO 9 Feb 81
  IF NULL(X := REXP()) THEN RETURN ERROR(105, '(Unparsable Expression));
  IF TOK!* NEQ '!; THEN RETURN ERROR(106, '(Missing !; at end of expression));
  RETURN X
END RPARSE;

SYMBOLIC PROCEDURE REXP();	 %. Parse an EXP and rename OP
BEGIN SCALAR LEFT, RIGHT,OP;
  IF NOT (LEFT := RTERM()) THEN RETURN NIL;
  WHILE (OP := GET(TOK!*,'REXP)) DO
    << NTOKEN();
       IF NOT(RIGHT := RTERM()) THEN RETURN ERROR(100, '(Missing Term in Exp));
       LEFT := LIST(OP, LEFT, RIGHT)
    >>;
  RETURN LEFT
END REXP;

SYMBOLIC PROCEDURE RTERM();	%. PARSE a TERM
BEGIN SCALAR LEFT, RIGHT, OP;
  IF NOT (LEFT := RPRIMARY()) THEN RETURN NIL;
  WHILE (OP := GET(TOK!*,'RTERM)) DO
    << NTOKEN();
       IF NOT (RIGHT := RPRIMARY()) THEN
	  RETURN ERROR (101, '(Missing Primary in Term));
       LEFT := LIST(OP, LEFT, RIGHT)
    >>;
  RETURN LEFT
END RTERM;

SYMBOLIC PROCEDURE RPRIMARY();	%. RPRIMARY, allows "^" and "'"
BEGIN SCALAR LEFT, RIGHT, OP;
  IF TOK!* EQ '!+ THEN RETURN <<NTOKEN(); RPRIMARY0()>>;
  IF TOK!* EQ '!- 
      THEN RETURN << NTOKEN();
		     IF (LEFT := RPRIMARY0()) THEN LIST('MINUS, LEFT) 
                     ELSE RETURN ERROR(200,'(Missing Primary0 after MINUS))
		  >>;

  IF NOT (LEFT := RPRIMARY0()) THEN RETURN NIL;
  WHILE (OP := GET(TOK!*,'RPRIMARY)) DO
    << NTOKEN();
       IF NOT (RIGHT := RPRIMARY0()) THEN 
		RETURN ERROR(200, '(Missing Primary0 in Primary));
       LEFT := LIST(OP, LEFT, RIGHT) 
    >>;
  RETURN LEFT;
END RPRIMARY;

SYMBOLIC PROCEDURE RPRIMARY0();		%. Variables, etc
BEGIN SCALAR EXP, ARGS;
  IF TOK!* EQ '!( THEN
    << NTOKEN();
       IF NOT (EXP := REXP()) THEN RETURN ERROR(102, '(Missing Expression));
       IF TOK!* NEQ '!) THEN RETURN ERROR(103, '(Missing Right Parenthesis));
       NTOKEN();
       RETURN EXP
    >>;

    IF NUMBERP(EXP := TOK!*) 
      THEN RETURN <<NTOKEN(); EXP>>;

    IF NOT IDP EXP THEN  RETURN NIL;
    NTOKEN();
    IF ARGS := RARGS(EXP) THEN RETURN ARGS;
    RETURN EXP;
END RPRIMARY0;

SYMBOLIC PROCEDURE RARGS(X);
  BEGIN SCALAR ARGS,ARG;
	IF TOK!* NEQ '!( THEN RETURN NIL;
	NTOKEN();
	IF TOK!* EQ '!) THEN RETURN <<NTOKEN();X . NIL>>;
  L:	IF NOT (ARG :=REXP()) THEN ERROR(104,'(Not expression in ARGLST));
	ARGS := ARG . ARGS;
	IF TOK!* EQ '!, THEN <<NTOKEN(); GOTO L>>;
	IF TOK!* EQ '!) THEN RETURN <<NTOKEN();X . REVERSE ARGS>>;
        ERROR(105,'(Missing !) or !, in ARGLST));
  END;

SYMBOLIC PROCEDURE MKATOM X;
%  Use LIST('RCREATE, LIST('QUOTE,x)); if doing EVAL mode
 X;

%******************* Printing Routines ********************************

SYMBOLIC PROCEDURE PPRINT A;
% Print internal canonical form in Infix notation.
    IF NUMBERP A THEN PRIN2 A  ELSE
BEGIN
	IF NUMBERP CDAR A THEN
	  IF CDAR A = 0 THEN
	    << PRIN2 '0; RETURN NIL >>
	   ELSE IF CDAR A NEQ 1 THEN 
	    << PRIN2 CDAR A; PRIN2 '!* >>
	   ELSE
	 ELSE IF RPREC!* CDAR A THEN << PPRINT CDAR A; PRIN2 '!* >> 
	   ELSE <<PRIN2 '!(; PPRINT CDAR A; PRIN2 '!)!* >>;
	IF CDAAR A = 0 THEN PRIN2 1
	   ELSE IF CDAAR A = 1 THEN PRIN2 CAAAR A
	   ELSE << PRIN2 CAAAR A; PRIN2 '!^;
		  IF RPREC!^ CDAAR A THEN PPRINT CDAAR A
		    ELSE <<PRIN2 '!(; PPRINT CAAAR A; PRIN2 '!) >> >>;
	IF NUMBERP CDR A THEN
	  IF CDR A> 0 THEN <<PRIN2 '!+ ; PRIN2 CDR A; RETURN NIL>>
	   ELSE IF CDR A < 0 THEN <<PRIN2 '!-! ; PRIN2 (-CDR A);
                                        RETURN NIL>>
           ELSE RETURN NIL;
	IF ATOM CDR A THEN <<PRIN2  '!+ ; PRIN2 CDR A; RETURN NIL>>;
	PRIN2 '!+ ; PPRINT CDR A;
END;

SYMBOLIC PROCEDURE RPREC!* X;	%. T if there is no significant addition in X.
  ATOM X OR (NUMBERP POLRED X AND POLRED X = 0);

SYMBOLIC PROCEDURE RPREC!^ X;	%. T if there is not significant addition or multiplication in X.
RPREC!* X AND (ATOM X OR
  (ATOM CDAR X AND NUMBERP CDAR X));

SYMBOLIC PROCEDURE SIMPLE X;	%. POL that doest need ()
 ATOM X OR ((POLRED X=0) AND (POLEXPT X=1) AND (POLCOEF X =1));

SYMBOLIC PROCEDURE RATPRINT A;	%. Print a RAT
BEGIN
        IF CDR A = 1 THEN PPRINT CAR A
         ELSE <<NPRINT CAR A;
		PRIN2 '!/; 
	        NPRINT CDR A>>;
	TERPRI()
END;

SYMBOLIC PROCEDURE NPRINT A; 	%. Add parens, if needed
 IF NOT SIMPLE A THEN <<PRIN2 '!( ; PPRINT A; PRIN2 '!) >>
  ELSE PPRINT A;

%. Convert RCAN back to PREFIX form

SYMBOLIC PROCEDURE RAT2PRE X;           %. RATIONAL to Prefix
 IF RATDEN X = 1 THEN POL2PRE RATNUM X
  ELSE LIST('QUOTIENT,POL2PRE RATNUM X, POL2PRE RATDEN X);

SYMBOLIC PROCEDURE POL2PRE X;		%. Polynomial to Prefix
BEGIN SCALAR TT,RR;
 IF NOT PAIRP X THEN RETURN X;
  TT:=TRM2PRE POLTRM X;
  RR:=POL2PRE POLRED X;
  IF RR = 0 THEN RETURN TT;
  IF NUMBERP RR AND RR <0 THEN RETURN LIST('DIFFERENCE,TT,-RR);
  RETURN  LIST('PLUS2,TT,RR);
END;

SYMBOLIC PROCEDURE TRM2PRE X;		%. Term to Prefix
 IF TRMCOEF X = 1 THEN PWR2PRE TRMPWR X
  ELSE IF TRMCOEF X = (-1) THEN LIST('MINUS,PWR2PRE TRMPWR X)
  ELSE LIST('TIMES2,POL2PRE TRMCOEF X,PWR2PRE TRMPWR X);

SYMBOLIC PROCEDURE PWR2PRE X;		%. Power to Prefix
 IF PWREXPT X = 1 THEN PWRVAR X
  ELSE LIST('EXPT,PWRVAR X,PWREXPT X);

%. prefix Pretty print

SYMBOLIC PROCEDURE PREPRIN(A,PARENS);	%. Print PREFIX form in Infix notation.
 BEGIN SCALAR PRINOP;
	IF ATOM A THEN RETURN PRIN2 A;
        IF (PRINOP:=GET(CAR A,'PRINOP)) 
	 THEN RETURN XAPPLY(PRINOP,LIST(A,PARENS));
	PRIN2(CAR A); PRINARGS CDR A;
	RETURN A;
 END;

SYMBOLIC PROCEDURE PRINARGS A;	%. Print ArgLIST
 IF NOT PAIRP A THEN PRIN2 '!(!)
  ELSE <<PRIN2 '!(; WHILE PAIRP A DO
		    <<PREPRIN(CAR A,NIL); 
		      IF PAIRP (A:=CDR A) THEN PRIN2 '!,>>;
	PRIN2 '!)>>;

SYMBOLIC PROCEDURE PREPRINT A;
 <<PREPRIN(A,NIL); TERPRI(); A>>;

SYMBOLIC PROCEDURE NARYPRIN(OP,ARGS,PARENS);
  IF NOT PAIRP ARGS THEN NIL
   ELSE IF NOT PAIRP CDR ARGS THEN PREPRIN(CAR ARGS,PARENS)
   ELSE <<IF PARENS THEN PRIN2 '!(; 
	  WHILE PAIRP ARGS DO
		  <<PREPRIN(CAR ARGS,T); % Need precedence here
		    IF PAIRP(ARGS:=CDR ARGS) THEN PRIN2 OP>>;
          IF PARENS THEN PRIN2 '!)>>;
	
         
SYMBOLIC PROCEDURE PLUSPRIN(A,PARENS);
  NARYPRIN('! !+! ,CDR A,PARENS);

SYMBOLIC PROCEDURE DIFFERENCEPRIN(A,PARENS);
  NARYPRIN('! !-! ,CDR A,PARENS);

SYMBOLIC PROCEDURE TIMESPRIN(A,PARENS);
  NARYPRIN('!*,CDR A,PARENS);

SYMBOLIC PROCEDURE QUOTPRIN(A,PARENS);
   NARYPRIN('!/,CDR A,PARENS);

SYMBOLIC PROCEDURE EXPPRIN(A,PARENS);
  NARYPRIN('!^,CDR A,PARENS);

ON RAISE;
END;

Added perq-pascal-lisp-project/test.sl version [3291c80a73].









>
>
>
>
1
2
3
4
1
2
(PRINT '(AHA OHO))
(RDS NIL)

Added perq-pascal-lisp-project/tpas0.pas version [7ab967767e].

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
(* include following two lines for terak *)
(*  [$s+] *) (* swapping mode to manage this large file *)
(*  [$g+] *) (* goto is legal *)

PROGRAM pas0(symin*,input*,output);

    (************************************************************)
    (* support routines for a "lisp" machine.  uses a register  *)
    (* model with a stack for holding frames.  stack also used  *)
    (* to hold compiler generated constants.                    *)
    (* written by william f. galway and martin l. griss         *)
    (* modified by ralph ottenheimer may 81                     *)
    (* append pas1...pasn at  end                               *)
    (* -------------------------------------------------------- *)
    (* symin is input channel one--used to initialize "symbol   *)
    (* table".  input is input channel two--standard input.     *)
    (* output is output channel one--the standard output.       *)
    (************************************************************)

CONST
    (* for terak  *)
     sp = ' ';  
     ht = 9;           (* ascii codes *)
     lf = 10; 
     cr = 13; 
     nul = 0; 

    eos = nul;      (* terminator character for strings. *)
    (* note: use chr(eos) on terak *)
    inchns = 2;       (* number of input channels.  *)
    outchns = 1;      (* number of output channels. *)

    xtoktype  =  129; (* slot in idspace for toktype. *)
    chartype  =  3;   (* various token types *)
    inttype  =  1;
    idtype  =  2;

    shift_const = 8192; (* tags and info are packed into an integer *)
    (* assumed to be at least 16 bits long.  low order 13 bits  *)
    (* are the info, top 3 are the tag.                         *)
    int_offset = 4096;  (* small integers are stored 0..8191    *)
    (* instead of -4096..4095 because it will pack smaller      *)
    (* under ucsd pascal.                                       *)

    (* the various tags - can't use a defined scalar type *)
    (* because of the lack of convertion functions.       *)
    inttag = 0;    (* info is an integer                  *)
    chartag = 1;   (* info is a character code            *)
    pairtag = 2;   (* info points to pair                 *)
    idtag = 3;     (* info points to identifier           *)
    codetag = 4;   (* info is index into a case statement *)
    (*                that calls appropriate function.    *)
    errtag = 5;    (* info is an error code - see below.  *)
    bigtag = 6;    (* info points to a full word (or      *)
    (*                longer) integer.                    *)
    flotag = 7;    (* info points to a float number.      *)

    (* error codes.  corresponding to tag = errtag.  *)
    noprspace = 1;    (* no more "pair space"--can't cons. *)
    notpair = 2;      (* a pair operation attempted on a non-pair. *)
    noidspace = 3;    (* no more free identifiers *)
    undefined = 4;    (* used to mark undefined function cells (etc?) *)

    maxpair = 2500;   (* max number of pairs allowed. *)
    maxident = 400;   (* max number of identifiers *)
    maxstrsp = 2000;  (* size of string (literal) storage space. *)
    maxintsp = 50;      (* max number of long integers allowed *)
    maxflosp = 50;      (* max number of floating numbers allowed *)

    hidmax = 50;      (* number of hash values for identifiers *)
    maxgcstk = 100;   (* size of garbage collection stack.    *)
    stksize = 500;    (* stack size *)
    maxreg = 15;      (* number of registers in lisp machine. *)

    eofcode = 26;     (* magic character code for eof, ascii for *)
    (*  cntrl-z.  kludge, see note in xrdtok.  *)
    choffset = 1;     (* add choffset to ascii code to get address  *)
    (* in id space for corresponding identifier.  *)
    nillnk = 0;       (* when integers are used as pointers.  *)


TYPE
    (* onechar = ascii; *)
    onechar = char;     (* for terak *)

    (* note we allow zero for id_ptr, allowing a "nil" link. *)
    stringp = 1..maxstrsp;        (* pointer into string space. *)
    id_ptr = 0..maxident;            (* pointer into id space. *)

    itemref = integer;
    itemtype = 0..7;    (* the tags *)


    pair = PACKED RECORD
		      prcar: itemref;
		      prcdr: itemref;
		      markflg: boolean;        (* for garbage collection   *)
		  END;


    ascfile = PACKED FILE OF onechar;

    ident = PACKED RECORD           (* identifier *)
		       idname: stringp;
		       val: itemref;       (* value *)
		       plist: itemref;     (* property list *)
		       funcell: itemref;   (* function cell *)
		       idhlink: id_ptr;   (* hash link *)
		   END;
    longint = integer;    (* use long int on terak *)

VAR
    (* global information *)
    nilref,trueref: itemref;    (* refers to identifiers "nil", and "t". *)

    r: ARRAY[1..maxreg] OF itemref;
    rxx,ryy: itemref;

    (* "st" is the stack pointer into "stk".  it counts the number of  *)
    (* items on the stack, so it runs from zero while the stack starts *)
    (* at one.                                                         *)
    st: 0..stksize;
    stk: ARRAY[1..stksize] OF itemref;

    (* pair space *)
    prspace: PACKED ARRAY[1..maxpair] OF pair; (* all pairs stored here. *)
    freepair: integer;          (* pointer to next free pair in prspace. *)

    (* identifier space *)
    idhead: ARRAY[0..hidmax] OF id_ptr;
    idspace: PACKED ARRAY[1..maxident] OF ident;
    freeident: integer;

    (* string space *)
    strspace: PACKED ARRAY[1..maxstrsp] OF onechar;
    freestr: stringp;

    (* large integer space *)
    intspace: ARRAY[1..maxintsp] OF longint;
    freeint: 1..maxintsp;

    (* i/o channels *)
    symin: ascfile;
(*    input: ascfile; (* comment out for terak. *)

    inchnl: 1..inchns;      (* current input channel number  *)
    outchnl: 1..outchns;    (* current output channel number *)

    (* "current character" for each input channel.                    *)
    (* may want to include more than one character at some later date *)
    (* (for more lookahead).                                          *)
    ichrbuf: ARRAY[1..inchns] OF onechar;

    (* for collecting statistics. *)
    gccount: integer;           (* counts garbage collections *)
    (* counts from last garbage collection. *)
    consknt: integer;           (* number of times "cons" called *)
    pairknt: integer;           (* number of pairs created *)


    (********************************************************)
    (*                                                      *)
    (*             item selectors & constructors            *)
    (*                                                      *)
    (********************************************************)


FUNCTION tag_of(item: itemref): itemtype;
    BEGIN (* tag_of *)
    tag_of := item DIV shift_const;
    END;
    (* tag_of *)

FUNCTION info_of(item: itemref): integer;
    BEGIN (* info_of *)
    IF item DIV shift_const = inttag THEN
	info_of := item MOD shift_const - int_offset
    ELSE
	info_of := item MOD shift_const
    END;
    (* info_of *)

PROCEDURE mkitem(tag: itemtype; info: longint; VAR item: itemref);
    (* do range checking on info. ints run from -4096 to +4095 *)
    (* everything else runs from 0 to 8191. ints & chars       *)
    (* contain their info, all others points into an           *)
    (* appropriate space.                                      *)

    PROCEDURE mkbigint;
	BEGIN (* mkbigint *)
	IF freeint <= maxintsp THEN     (* convert to bignum *)
	    BEGIN
	    tag := bigtag;
	    intspace[freeint] := info;
	    info := freeint;        (* since we want the pointer *)
	    freeint := freeint + 1;
	    END
	ELSE writeln('*****BIGNUM SPACE EXHAUSTED')     (* should do gc *)
	END;
	(* mkbigint *)


    BEGIN (* mkitem *)
    IF tag = inttag THEN
	IF (info < -int_offset) OR (info > int_offset - 1) THEN mkbigint
	ELSE info := info + int_offset    (* info was in range so add offset *)

    ELSE IF tag = bigtag THEN mkbigint

	 ELSE IF info < 0 THEN
		  BEGIN
		  writeln('*****MKITEM: BAD NEG');
		  break(output); halt
		  END;
    (* nothing special to do for other types *)

    (* pack tag and info into 16-bit item.   *)
    item := tag * shift_const + info
    END;
    (* mkitem *)

PROCEDURE set_info(VAR item: itemref; newinfo: longint);
    BEGIN (* set_info *)
    mkitem(tag_of(item), newinfo, item)
    END;
    (* set_info *)

PROCEDURE set_tag(VAR item: itemref; newtag: itemtype);
    BEGIN (* set_tag *)
    mkitem(newtag, info_of(item), item)
    END;
    (* set_tag *)

PROCEDURE mkident(id: integer; reg: integer);
    (* make identifier "id" in register "reg" *)
    BEGIN       (* mkident *)
    mkitem(idtag, id, r[reg]);
    END;
    (* mkident *)

PROCEDURE mkint(int: longint; reg: integer);
    BEGIN       (* mkint *)
    mkitem(inttag, int, r[reg]);
    END;
    (* mkint *)

PROCEDURE mkpair(pr: integer; reg: integer);
    BEGIN (* mkpair *)
    mkitem(pairtag, pr, r[reg])
    END;
    (* mkpair *)

PROCEDURE int_val(item: itemref; VAR number: longint);
    (* returns integer value of item (int or bignum). *)
    (* must return 'number' in var parameter instead  *)
    (* of function value since long integers are not  *)
    (* a legal function type in ucsd pascal.          *)
    BEGIN (* int_val *)
    IF tag_of(item) = inttag THEN
	number := info_of(item)
    ELSE IF tag_of(item) = bigtag THEN
	     number := intspace[info_of(item)]
	 ELSE writeln('***** ILLEGAL DATA TYPE FOR NUMERIC OPERATION')
    END;
    (* int_val *)


    (********************************************************)
    (*                                                      *)
    (*                  stack allocation                    *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xsetuniq;     (* just here temporarily until i can *)
    BEGIN (* xsetuniq *)(* figure out how to get them out of *)
    END;
    (* execute.                          *)
    (* xsetuniq *)

PROCEDURE xgetuniq;
    BEGIN (* xgetuniq *)
    END;
    (* xgetuniq *)


PROCEDURE alloc(n: integer);
    BEGIN
    IF n + st <= stksize THEN
	st := n+st
    ELSE
	BEGIN
	writeln('*****LISP STACK OVERFLOW');
	writeln('     TRIED TO ALLOCATE ',n);
	writeln('     CURRENT STACK TOP IS ',st);
	END;
    END;

PROCEDURE dealloc(n: integer);
    BEGIN
    IF st - n >= 0 THEN
	st := st - n
    ELSE
	writeln('*****LISP STACK UNDERFLOW');
    END;

    (* optimized allocs *)

PROCEDURE alloc1;
    BEGIN alloc(1) END;

PROCEDURE dealloc1;
    BEGIN dealloc(1) END;

PROCEDURE alloc2;
    BEGIN alloc(2) END;

PROCEDURE dealloc2;
    BEGIN dealloc(2) END;

PROCEDURE alloc3;
    BEGIN alloc(3) END;

PROCEDURE dealloc3;
    BEGIN dealloc(3) END;


    (********************************************************)
    (*                                                      *)
    (*              support for register model              *)
    (*                                                      *)
    (********************************************************)

PROCEDURE load(reg: integer; sloc: integer);
    BEGIN
    IF sloc < 0 THEN r[reg] := r[-sloc]
    ELSE  r[reg] := stk[st-sloc];
    (* will, fix for load (pos,pos) *)
    END;

PROCEDURE store(reg: integer; sloc: integer);
    BEGIN
    stk[st-sloc] := r[reg];
    END;

    (* optimized load/store. *)
PROCEDURE load10;
    BEGIN
    load(1,0);
    END;

PROCEDURE store10;
    BEGIN
    store(1,0);
    END;

PROCEDURE storenil(sloc: integer);
    BEGIN
    stk[st-sloc] := nilref;
    END;


    (********************************************************)
    (*                                                      *)
    (*               standard lisp functions                *)
    (*                                                      *)
    (********************************************************)

    (* the following standard lisp functions appear in *)
    (* eval.red: reverse, append, memq, atsoc, get,    *)
    (* put, remprop, eq, null, equal, error, errorset, *)
    (* abs, idp, numberp, atom, minusp, eval, xapply,  *)
    (* evlis, prin1, print, prin2t, list2 ... list5.   *)

FUNCTION atom(item : itemref): itemref;
    BEGIN       (* atom *)
    IF tag_of(item) <> pairtag THEN atom := trueref
    ELSE atom := nilref
    END (* atom *);

FUNCTION codep(item: itemref): itemref;
    BEGIN       (* codep *)
    IF (tag_of(item) = codetag) AND (info_of(item) <> undefined) THEN
	codep := trueref
    ELSE codep := nilref
    END (* codep *);

FUNCTION idp(item: itemref): itemref;
    BEGIN       (* idp *)
    IF tag_of(item) = idtag THEN idp := trueref
    ELSE idp := nilref
    END (* idp *);

FUNCTION pairp(item: itemref): itemref;
    BEGIN (* pairp *)
    IF tag_of(item) = pairtag THEN pairp := trueref
    ELSE pairp := nilref
    END (* pairp *);

FUNCTION constantp(item: itemref): itemref;
    BEGIN       (* constantp *)
    IF NOT((pairp(item) = trueref) OR (idp(item) = trueref)) THEN
	constantp := trueref
    ELSE constantp := nilref
    END (* constantp *);

FUNCTION eq(u, v: itemref): itemref;
    BEGIN       (* eq *)
    IF u = v THEN eq := trueref
    ELSE eq := nilref
    END (* eq *);

FUNCTION eqn(u, v: itemref): itemref;
    VAR i, j: longint;

    BEGIN       (* eqn *)
    int_val(u, i);
    int_val(v, j);
    IF i = j THEN eqn := trueref
    ELSE eqn := nilref
    END (* eqn *);

FUNCTION fixp(item: itemref): itemref;
    BEGIN       (* fixp *)
    IF (tag_of(item) = inttag) OR (tag_of(item) = bigtag) THEN
	fixp := trueref
    ELSE fixp := nilref
    END (* fixp *);

FUNCTION floatp(item: itemref): itemref;
    BEGIN       (* floatp *)
    IF tag_of(item) = flotag THEN floatp := trueref
    ELSE floatp := nilref
    END (* floatp *);

FUNCTION numberp(item: itemref): itemref;
    BEGIN       (* numberp *)
    numberp := fixp(item)       (* will have to be fixed for floats *)
    END (* numberp *);


    (********************************************************)
    (*                                                      *)
    (*              identifier lookup & entry               *)
    (*                                                      *)
    (********************************************************)

FUNCTION nmhash(nm: stringp): integer;
    CONST
	hashc = 256;
    VAR
	i,tmp: integer;
    BEGIN
    tmp := 0;
    i := 1;     (* get hash code from first three chars of string. *)
    WHILE (i <= 3) AND (strspace[nm+i] <> chr(eos)) DO
	BEGIN
	tmp := ord(strspace[nm+i]) + hashc*tmp;
	i := i + 1;
	END;
    nmhash := abs(tmp) MOD hidmax;      (* abs because mod is screwy. *)
    END;

FUNCTION eqstr(s1,s2: stringp): boolean;
    BEGIN
    WHILE (strspace[s1] = strspace[s2]) AND (strspace[s1] <> chr(eos)) DO
	BEGIN
	s1 := s1 + 1;
	s2 := s2 + 1;
	END;
    eqstr := (strspace[s1] = strspace[s2]);
    END;

PROCEDURE nmlookup(nm: stringp; VAR found: boolean; VAR hash: integer;
		   VAR loc: itemref);
    (* lookup a name in "identifier space".                                 *)
    (* "hash" returns the hash value for the name.                          *)
    (* "loc" returns the location in the space for the (possibly new)       *)
    (* identifier.                                                          *)
    BEGIN
    hash := nmhash(nm);
    mkitem(idtag, idhead[hash], loc);
    (* default is identifier, but may be "error". *)
    (* start at appropriate hash chain. *)

    found := false;
    WHILE (info_of(loc) <> nillnk) AND (NOT found) DO
	BEGIN
	found := eqstr(nm, idspace[info_of(loc)].idname);
	IF NOT found THEN
	    set_info(loc, idspace[info_of(loc)].idhlink);
	(* next id in chain *)
	END;
    IF NOT found THEN               (* find spot for new identifier *)
	BEGIN
	IF freeident=nillnk THEN    (* no more free identifiers. *)
	    mkitem(errtag, noidspace, loc)
	ELSE
	    BEGIN
	    set_info(loc, freeident);
	    freeident := idspace[freeident].idhlink;
	    END;
	END;
    END;

PROCEDURE putnm(nm: stringp; VAR z: itemref; VAR found: boolean);
    (* put a new name into identifier space, or return old location *)
    (* if it's already there.                                       *)
    VAR
	tmp: ident;
	hash: integer;
    BEGIN
    nmlookup(nm, found, hash, z);
    IF (NOT found) AND (tag_of(z) = idtag) THEN
	BEGIN
	tmp.idname := nm;
	tmp.idhlink := idhead[hash];   (* put new ident at head of chain     *)
	tmp.val := nilref;             (* initialize value and property list *)
	tmp.plist := nilref;
	tmp.funcell := nilref;         (* also, the function cell *)
	idhead[hash] := info_of(z);
	idspace[info_of(z)] := tmp;
	END;
    END;

PROCEDURE xfaststat;
    (* give quick summary of statistics gathered *)
    BEGIN
    writeln('CONSES:',consknt);
    writeln('PAIRS :',pairknt);
    writeln('CONSES/PAIRS: ',consknt/pairknt);
    writeln('ST    :',st);
    END;


    (********************************************************)
    (*                                                      *)
    (*              the garbage collector                   *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xgcollect;
    VAR
	i: integer;
	markedk: integer;   (* counts the number of pairs marked *)
	freedk: integer;    (* counts the number of pairs freed. *)
	gcstkp: 0..maxgcstk; (* note the garbage collection stack   *)
	mxgcstk: 0..maxgcstk;           (* is local to this procedure. *)
	gcstk: ARRAY[1..maxgcstk] OF integer;

    PROCEDURE pushref(pr: itemref);
	(* push the address of an unmarked pair, if that's what it is. *)
	BEGIN
	IF tag_of(pr) = pairtag THEN
	    IF NOT prspace[info_of(pr)].markflg THEN
		BEGIN
		IF gcstkp < maxgcstk THEN
		    BEGIN
		    gcstkp := gcstkp + 1;
		    gcstk[gcstkp] := info_of(pr);
		    IF gcstkp > mxgcstk THEN
			mxgcstk := gcstkp;
		    END
		ELSE
		    BEGIN
		    writeln('*****GARBAGE STACK OVERFLOW');
		    halt;       (* fatal error *)
		    END;
		END;
	END;

    PROCEDURE mark;
	(* "recursively" mark pairs referred to from gcstk. gcstk is used to *)
	(* simulate recursion.                                               *)
	VAR
	    prloc: integer;
	BEGIN
	WHILE gcstkp > 0 DO
	    BEGIN
	    prloc := gcstk[gcstkp];
	    gcstkp := gcstkp - 1;
	    prspace[prloc].markflg := true;
	    pushref(prspace[prloc].prcdr);
	    pushref(prspace[prloc].prcar);  (* trace the car first. *)
	    END;
	END;

    BEGIN       (* xgcollect *)
    writeln('***GARBAGE COLLECTOR CALLED');
    gccount := gccount + 1;          (* count garbage collections. *)
    xfaststat;   (* give summary of statistics collected *)
    consknt := 0;       (* clear out the cons/pair counters *)
    pairknt := 0;
    gcstkp := 0;                    (* initialize the garbage stack pointer. *)
    mxgcstk := 0;                   (* keeps track of max stack depth. *)

    (* mark things from the "computation" stack. *)
    FOR i := 1 TO st DO
	BEGIN
	pushref(stk[i]);
	mark;
	END;
    (* mark things from identifier space. *)
    FOR i := 1 TO maxident DO
	BEGIN
	pushref(idspace[i].val);
	mark;
	pushref(idspace[i].plist);
	mark;
	pushref(idspace[i].funcell);
	mark;
	END;

    (* reconstruct free list by adding things to the head. *)
    freedk := 0;
    markedk := 0;
    FOR i:= 1 TO maxpair - 1 DO
	BEGIN
	IF prspace[i].markflg THEN
	    BEGIN
	    markedk := markedk + 1;
	    prspace[i].markflg := false
	    END
	ELSE
	    BEGIN
	    prspace[i].prcar := nilref;
	    mkitem(pairtag, freepair, prspace[i].prcdr);
	    freepair := i;
	    freedk := freedk + 1
	    END
	END;
    writeln(freedk,' PAIRS FREED.');
    writeln(markedk,' PAIRS IN USE.');
    writeln('MAX GC STACK WAS ',mxgcstk);
    END;
    (* xgcollect *)

    (********************************************************)
    (*                                                      *)
    (*                  lisp primitives                     *)
    (*                                                      *)
    (********************************************************)

    (* return r[1].r[2] in r[1] *)
PROCEDURE xcons;
    VAR p: integer;

    BEGIN
    (* push args onto stack, in case we need to garbage collect the *)
    (* references will be detected.                                 *)
    alloc(2);
    stk[st] := r[1];
    stk[st-1] := r[2];

    IF prspace[freepair].prcdr = nilref THEN xgcollect;

    p := freepair;
    freepair := info_of(prspace[p].prcdr);
    prspace[p].prcar := stk[st];
    prspace[p].prcdr := stk[st - 1];
    mkpair(p, 1);       (* leave r[1] pointing at new pair. *)

    pairknt := pairknt + 1;
    consknt := consknt + 1;
    dealloc(2);
    END;

PROCEDURE xncons;
    BEGIN r[2] := nilref;
    xcons;
    END;

PROCEDURE xxcons;
    BEGIN rxx := r[1];
    r[1] := r[2];
    r[2] := rxx;
    xcons;
    END;

    (* return car of r[1] in r[1] *)
PROCEDURE xcar;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
	r[1] := prspace[info_of(r[1])].prcar
    ELSE
	mkitem(errtag, notpair, r[1]);
    END;

PROCEDURE xcdr;
    BEGIN
    IF tag_of(r[1]) = pairtag THEN
	r[1] := prspace[info_of(r[1])].prcdr
    ELSE
	mkitem(errtag, notpair, r[1]);
    END;

    (* anyreg car and cdr *)
PROCEDURE anycar(VAR a, b: itemref);
    BEGIN
    IF tag_of(a) = pairtag THEN
	b := prspace[info_of(a)].prcar
    ELSE
	mkitem(errtag, notpair, b);
    END;

PROCEDURE anycdr(VAR a, b: itemref);
    BEGIN
    IF tag_of(a) = pairtag THEN
	b := prspace[info_of(a)].prcdr
    ELSE
	mkitem(errtag, notpair, b);
    END;

    (********************************************************)
    (*                                                      *)
    (*                    i/o primitives                    *)
    (*                                                      *)
    (********************************************************)


PROCEDURE xterpri;
    (* need to change for multiple output channels.  *)
    (* improve choice of break/nobreak.              *)
    BEGIN
    writeln(output);
    END;


PROCEDURE xwrtok;
    (* doesn't expand escaped characters in identifier names *)
    VAR
	i: integer;
    BEGIN
    IF tag_of(r[1]) = inttag THEN
	BEGIN
	IF info_of(r[1]) = 0 THEN
	    write('0')
	ELSE
	    write(info_of(r[1]): 2+trunc(log(abs(info_of(r[1])))));
	END

    ELSE IF tag_of(r[1]) = bigtag THEN
	     write(intspace[info_of(r[1])])

	 ELSE IF tag_of(r[1]) = flotag THEN
		  write(flospace[info_of(r[1])])

	      ELSE IF tag_of(r[1]) = idtag THEN
		       BEGIN
		       i := idspace[info_of(r[1])].idname;
		       WHILE (i <= maxstrsp) AND (strspace[i] <> chr(eos)) DO
			   BEGIN
			   write(strspace[i]);
			   i:= i + 1;
			   END;
		       END

		   ELSE IF tag_of(r[1]) = chartag THEN
			    write(chr(info_of(r[1]) - choffset))

			ELSE
			    writeln('XWRTOK GIVEN ',tag_of(r[1]), info_of(r[1]));
    END;

PROCEDURE rdchnl(chnlnum: integer; VAR ch: onechar);
    BEGIN
    IF (chnlnum < 1) OR (chnlnum > inchns) THEN
	writeln('*****BAD INPUT CHANNEL FOR RDCHNL')
    ELSE
	CASE chnlnum OF
	    1:  BEGIN
	    ch := symin^;  (* a little strange, but avoids  *)
	    get(symin);              (* initialization problems *)
	    ichrbuf[inchnl] := symin^;
	    END;

	    2:  BEGIN
	    ch := input^;
	    get(input);
	    ichrbuf[inchnl] := input^;
	    END;
	    END;
    (* case *)
    END;
    (* rdchnl *)

FUNCTION eofchnl(chnlnum: integer): boolean;
    BEGIN
    IF (chnlnum < 1) OR (chnlnum > inchns) THEN
	writeln('*****BAD INPUT CHANNEL FOR EOFCHNL')
    ELSE
	CASE chnlnum OF
	    1:  eofchnl := eof(symin);
	    2:  eofchnl := eof(input);
	    END;
    END;

    (********************************************************)
    (*                                                      *)
    (*                   token scanner                      *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xrdtok;
    VAR
	ch: onechar;
	i: integer;
	anint: longint;
	moreid: boolean;
	found: boolean;

    FUNCTION digit(ch: onechar): boolean;
	BEGIN
	digit := ( '0' <= ch ) AND ( ch <= '9');
	END;

    FUNCTION escalpha(VAR ch: onechar): boolean;
	(* test for alphabetic or escaped character.                 *)
	(* note possible side effect.                                *)
	BEGIN
	IF ( 'A' <= ch ) AND ( ch <= 'Z') THEN
	    escalpha := true
	ELSE IF ( ord('A')+32 <= ord(ch)) AND ( ord(ch) <= ord('Z')+32) THEN
		 escalpha := true    (* lower case alphabetics *)
	     ELSE IF ch='!' THEN
		      BEGIN
		      rdchnl(inchnl,ch);
		      escalpha := true;
		      END
		  ELSE
		      escalpha := false;
	END;

    FUNCTION alphanum(VAR ch: onechar): boolean;
	(* test if escalfa or digit *)
	VAR b: boolean;
	BEGIN
	b := digit(ch);
	IF NOT b THEN b := escalpha(ch);
	alphanum := b;
	END;

	    function whitesp(ch: onechar): boolean; *)
	    var asccode: integer; *)
	    begin 
	      asccode := ord(ch);       (* ascii character code *)
	        WHITESP := (CH = SP) OR (ASCCODE = CR) OR (ASCCODE = LF)
	 OR (asccode = ht) or (asccode = nul);         (* null?? *)
	    end; 
	(* end of terak version *)

	(* reads bignums...need to read flonums too *)
    BEGIN       (* xrdtok *)
    IF NOT eofchnl(inchnl) THEN
	REPEAT                          (* skip leading white space. *)
	    rdchnl(inchnl,ch)
	UNTIL (NOT whitesp(ch)) OR eofchnl(inchnl);
    IF eofchnl(inchnl) THEN
	mkitem(chartag, eofcode + choffset, r[1])
	(* should really return !$eof!$  *)
    ELSE
	BEGIN
	IF digit(ch) THEN
	    set_tag(r[1], inttag)
	ELSE IF escalpha(ch) THEN
		 set_tag(r[1], idtag)
	     ELSE
		 set_tag(r[1], chartag);

	CASE tag_of(r[1]) OF
	    chartag:  BEGIN
		  set_tag(r[1], idtag);
		  mkitem(inttag, chartype, idspace[xtoktype].val);
		  set_info(r[1], ord(ch) + choffset);
		  END;
	    inttag:   BEGIN
		 mkitem(inttag, inttype, idspace[xtoktype].val);
		 anint := ord(ch) - ord('0');
		 WHILE digit(ichrbuf[inchnl]) DO
		     BEGIN
		     rdchnl(inchnl,ch);
		     anint := 10 * anint + (ord(ch) - ord('0'))
		     END;
		 set_info(r[1], anint)
		 END;
	    idtag:    BEGIN
		mkitem(inttag, idtype, idspace[xtoktype].val);
		i := freestr; (* point to possible new string *)
		moreid := true;
		WHILE (i < maxstrsp) AND moreid DO
		    BEGIN
		    strspace[i] := ch;
		    i:= i + 1;
		    moreid := alphanum(ichrbuf[inchnl]);
		    IF moreid THEN
			rdchnl(inchnl,ch);
		    END;
		strspace[i] := chr(eos);   (* terminate string *)
		IF (i >= maxstrsp) THEN
		    writeln('*****STRING SPACE EXHAUSTED')
		ELSE  (* look the name up, return itemref for it *)
		    BEGIN
		    putnm(freestr, r[1], found);
		    IF NOT found THEN
			freestr := i + 1;
		    END;
		END;
		(* of case idtag *)
	    END;
	(* of case *)
	END;
    END;
    (* xrdtok *)

    (********************************************************)
    (*                                                      *)
    (*                    initialization                    *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xread;
    FORWARD;

PROCEDURE init;
    (* initialization procedure depends on  *)
    (* ability to load stack with constants *)
    (* from a file.                         *)
    VAR
	strptr: stringp;
	nam: PACKED ARRAY[1..3] OF onechar;
	(* holds 'nil', other strings? *)
	i, n: integer;
	idref: itemref;
	found: boolean;

	(* init is divided into two parts so it can compile on terak *)
    PROCEDURE init1;
	BEGIN
	(* initialize top of stack *)
	st := 0;

	freefloat := 1;
	freeint := 1;

	(* define nilref - the id, nil, is defined a little later. *)
	freeident := 1;
	mkitem(idtag, freeident, nilref);

	(* initialize pair space. *)
	FOR i := 1 TO maxpair - 1 DO      (* initialize free list. *)
	    BEGIN
	    prspace[i].markflg := false;        (* redundant? *)
	    prspace[i].prcar := nilref;         (* just for fun *)
	    mkitem(pairtag, i + 1, prspace[i].prcdr);
	    END;
	prspace[maxpair].prcar := nilref;
	prspace[maxpair].prcdr := nilref;       (* end flag *)
	freepair := 1;                  (* point to first free pair *)


	(* initialize identifier space and string space. *)
	freestr := 1;
	FOR i := 0 TO hidmax - 1 DO
	    idhead[i] := nillnk;
	FOR i := 1 TO maxident DO
	    BEGIN
	    IF i < maxident THEN
		idspace[i].idhlink := i + 1
	    ELSE    (* nil to mark the final identifier in the table. *)
		idspace[i].idhlink := nillnk;
	    (* set function cells to undefined *)
	    mkitem(errtag, undefined, idspace[i].funcell);
	    END;

	(* nil must be the first identifier in the table--id #1 *)
	(* must fill in fields by hand for nilref.*)
	(* putnm can handle any later additions.  *)
	nam := 'NIL';
	strptr := freestr;
	FOR i := 1 TO 3 DO
	    BEGIN
	    strspace[strptr] := nam[i];
	    strptr:= strptr + 1;
	    END;
	strspace[strptr] := chr(eos);
	putnm(freestr, nilref, found);
	IF NOT found THEN
	    freestr := strptr + 1;

	(* make the single character ascii identifiers, except nul(=eos). *)
	FOR i := 1 TO 127  DO
	    BEGIN
	    strspace[freestr] := chr(i);
	    strspace[freestr + 1] := chr(eos);
	    putnm(freestr, idref, found);
	    IF NOT found THEN
		freestr := freestr + 2;
	    IF i = ord('T') THEN
		trueref := idref;
	    (* returns location for 't. *)
	    END;

	(* clear the counters *)
	gccount := 0;
	consknt := 0;
	pairknt := 0;
	END;
	(* init1 *)

    PROCEDURE init2;
	BEGIN
	(* load "symbol table" with identifiers, constants, and functions.  *)
	inchnl := 1;        (* select symbol input file. *)
	reset(symin,'#5:paslsp.data');  (* for terak *)

	xrdtok;     (* get count of identifiers. *)
	IF tag_of(r[1]) <> inttag THEN
	    writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED AT START');
	n := info_of(r[1]);
	FOR i := 1 TO n DO
	    xrdtok;
	(* reading token magically loads it into id space. *)
	xrdtok;         (* look for zero terminator. *)
	IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
	    writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER IDENTIFIERS');

	xrdtok;         (* count of constants  *)
	IF tag_of(r[1]) <> inttag THEN
	    writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED BEFORE CONSTANTS');
	n := info_of(r[1]);
	alloc(n);       (* space for constants on the stack *)
	FOR i := 1 TO n DO
	    BEGIN
	    xread;
	    stk[i] := r[1];
	    END;
	xrdtok;
	IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
	    writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER CONSTANTS');

	xrdtok;     (* count of functions. *)
	IF tag_of(r[1]) <> inttag THEN
	    writeln('*****BAD SYMBOL TABLE, INTEGER EXPECTED BEFORE FUNCTIONS');
	n := info_of(r[1]);
	FOR i := 1 TO n DO
	    (* for each function *)
	    (* store associated code *)
	    BEGIN
	    xrdtok;
	    mkitem(codetag, i, idspace[info_of(r[1])].funcell);
	    END;
	xrdtok;
	IF (tag_of(r[1]) <> inttag) OR (info_of(r[1]) <> 0) THEN
	    writeln('*****BAD SYMBOL TABLE, ZERO EXPECTED AFTER FUNCTIONS');

	inchnl := 2;        (* select standard input. *)
	END;
	(* init2 *)
    BEGIN       (* init *)
    init1;
    init2;
    END;
    (* init *)

    (********************************************************)
    (*                                                      *)
    (*                 arithmetic functions                 *)
    (*                                                      *)
    (********************************************************)

PROCEDURE xadd1;
    VAR i: longint;

    BEGIN
    int_val(r[1], i);
    mkint(i + 1, 1)
    END;

PROCEDURE xdifference;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 - i2, 1)
    END;

PROCEDURE xdivide;      (* returns dotted pair (quotient . remainder). *)
    VAR quot, rem: integer;
	i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);

    mkint(i1 DIV i2, 1);
    mkint(i1 MOD i2, 2);
    xcons
    END;

PROCEDURE xgreaterp;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);

    IF i1 > i2 THEN
	r[1] := trueref
    ELSE
	r[1] := nilref;
    END;

PROCEDURE xlessp;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);

    IF i1 < i2 THEN
	r[1] := trueref
    ELSE
	r[1] := nilref;
    END;

PROCEDURE xminus;
    VAR i: longint;

    BEGIN
    int_val(r[1], i);
    mkint(-i, 1)
    END;

PROCEDURE xplus2;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 + i2, 1)
    END;

PROCEDURE xquotient;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 DIV i2, 1)
    END;

PROCEDURE xremainder;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 MOD i2, 1)
    END;

PROCEDURE xtimes2;
    VAR i1, i2: longint;

    BEGIN
    int_val(r[1], i1);
    int_val(r[2], i2);
    mkint(i1 * i2, 1)
    END;
    (* xtimes2 *)


    (********************************************************)
    (*                                                      *)
    (*                    support for eval                  *)
    (*                                                      *)
    (********************************************************)


PROCEDURE execute(code: integer);
    FORWARD;

    (* apply(fn,arglist)-- "fn" is an operation code. *)
PROCEDURE xapply;
    VAR
	i: integer;
	code: integer;
	tmp: itemref;
	tmpreg: ARRAY[1..maxreg] OF itemref;
    BEGIN
    code := info_of(r[1]);
    r[1] := r[2];
    i := 1;
    (* spread the arguments  *)
    WHILE (r[1] <> nilref) AND (i <= maxreg) DO
	BEGIN
	tmp := r[1];
	xcar;
	tmpreg[i] := r[1];
	i := i + 1;
	r[1] := tmp;
	xcdr;
	END;
    WHILE i > 1 DO
	BEGIN
	i := i - 1;
	r[i] := tmpreg[i];
	END;
    execute(code);
    END;

    (*  rest of pas1...pasn follow *)

Added perq-pascal-lisp-project/user.sli version [6bed3928d8].





















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
% user LISP init for PASLSP

(PRINT  "User Init Start")
(DN LIST (AA) AA)
(SETQ INITFORM!* '(RDEVPR))
(DF ON (X) (SET (CAR X) T))
(DF OFF (X) (SET (CAR X) NIL))
(ON !*RAISE)
(OFF !*ECHO)
(PRINT  "User Init End")

Added perq-pascal-lisp-project/wicat-paslsp.aux version [c2f3c25903].

















>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
@Comment{AUXFILE of WICAT-PASLSP.MSS.1 by Scribe 3C(1250) on 1 March 1982 at 15:57}
@AuxCitation{BENSON81$=(1;;)}
@AuxCitation{BRANDT81$=(2;;)}
@AuxCitation{GRISS79$=(3;;)}
@AuxCitation{GRISS81$=(4;;)}
@AuxCitation{GRISS81E$=(5;;)}
@AuxCitation{HEARN73$=(6;;)}
@AuxCitation{MARTI79$=(7;;)}

Added perq-pascal-lisp-project/wicat-paslsp.err version [d134284fba].











>
>
>
>
>
1
2
3
4
5
@Comment{ErrLog of WICAT-PASLSP.MSS.1 by Scribe 3C(1250) on 1 March 1982 at 15:57}

Error found while finishing up after the end of the manuscript:
Cross references to 7 labels could be wrong.
Run the file through Scribe again if you need to be sure they are right.

Added perq-pascal-lisp-project/wicat-paslsp.lpt version [125b5cc6b7].

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
Utah Symbolic Computation Group                     December 1981
Operating Note 60










         A PASCAL Based Standard LISP for the Wicat 100          A PASCAL Based Standard LISP for the Wicat 100          A PASCAL Based Standard LISP for the Wicat 100


                               by

                 M. L. Griss and R. Ottenheimer

                 Department of Computer Science
                       University of Utah
                   Salt Lake City, Utah 84112

                      Preliminary  Version                       Preliminary  Version                       Preliminary  Version

                   Last Revision: 1 March 1982






                            ABSTRACT                             ABSTRACT                             ABSTRACT


This  report describes an interim implementation of Standard LISP
for the Wicat 100. This LISP is  based  upon  the  Standard  LISP
report,  and  a  newly  developing  Portable Standard LISP.  This
interim   implementation   is   designed    to    explore    LISP
implementations  in PASCAL on the Wicat 100 and similar machines.
The system consists of a kernel, handcoded in  PASCAL,  with  the
rest of the system written in LISP and compiled to PASCAL.









Work  supported  in part by the National Science Foundation under
Grant No. MCS80-07034. Wicat Pascal LISP         1 March 1982                          1


1. Introduction 1. Introduction 1. Introduction

  In  this  preliminary  report, we describe an implementation of
Standard LISP in PASCAL, PASLSP. Versions of PASLSP have been run
on a number of machines, ranging from an LSI-11  based  TERAK  to
Apollo  and  PERQ.  This  report  concentrates  on  the Wicat 100
implementation. This report is to be read in conjunction with the
Standard LISP report [Marti79]; we will highlight the differences
from the functions documented in the Standard LISP, describe  the
implementation strategy, and discuss future work.


  PASLSP  is  based  on  a  series of small and medium sized LISP
interpreters that have been developed at the University  of  Utah
to  explore  LISP implementations in higher level languages. Each
of these LISP systems consists of a  small  kernel  handcoded  in
some  language,  with  the rest of the system written in LISP and
compiled to the target language.  We have  used  FORTRAN,  PASCAL
and  assembly  language  as targets. The PASLSP series use PASCAL
for the kernel, and have a LISP to PASCAL compiler for  the  rest
of the system.


  Recent  work  has  concentrated  on  reducing  the  size of the
hand-coded kernel, and extending the compiler to  handle  systems
level  constructs.  This  has resulted in a new Portable Standard
LISP,     PSL,      running      on      the      DEC-20      and
VAX-11/750 [Benson81, Griss81].  An  implementation  of  PSL  for
MC68000 is underway. The PSL system is a modern, efficient  LISP,
written  entirely in itself; it uses an efficient LISP to machine
code compiler to produce the kernel, and then the rest of LISP is
loaded. In the future we hope to produce a complete PSL  targeted
at  a  higher level languages, such as PASCAL, C or ADA, and this
will replace the current PASLSP.


1.1. History of PASLSP 1.1. History of PASLSP 1.1. History of PASLSP

  The system now  called  PASLSP  was  originally  developed  (by
M. Griss and W. Galway), as a small LISP like kernel to support a
small  computer algebra system on an LSI-11 TERAK; this was to be
used as an answer analysis module within a CAI system [Brandt81],
written entirely in PASCAL. It was decided to  hand-code  a  very
small  kernel,  and  compile additional functions written in LISP
(LISP support functions, parser and simplifier) to PASCAL,  using
a  modified  Portable LISP compiler [griss79]. This version (call
it V0) did not even have user defined functions, since  space  on
the TERAK was at a premium.


  About  June  1981,  PASLSP  came  to  the attention of a number
people evaluating Apollo's and PERQ's, and it was suggested  that Wicat Pascal LISP         1 March 1982                          2


we  enhance V0 PASLSP for this purpose. During the space of a few
days, features taken from the  Standard  LISP  Report  and  newly
developing  PSL files were added to produce PASLSP-V1, running on
a DEC-20 and Terak. This was a fairly  complete  LISP  (including
Catch  and  Throw),  but lacked a few features (OPEN, CLOSE, RDS,
WRS, PROG, GO, RETURN, COMPRESS, EXPLODE,  Vectors  and  Strings,
etc.).    V1 PASLSP was adapted to a PERQ, VAX and Apollo by Paul
Milazo of Schlumberge in the space of a few  weeks  (we  did  not
have a PERQ or Apollo at that time).


  We subsequently obtained a PERQ, Apollo and a Wicat, and recent
work  has  been  aimed  at producing an enhanced PASLSP for these
machines, maintaining all versions in one set  of  source  files.
The  current  system, PASLSP-V2, is produced from a single PASCAL
kernel and set  of  LISP  support  files;  the  machine  specific
features  are  handled  by  a simple Source Code Conditionalizer,
changing the definition of certain constants and data types. Only
a few features of the Standard LISP report are missing, and there
are a number of additions.


1.2. Acknowledgement 1.2. Acknowledgement 1.2. Acknowledgement

  We would like to acknowledge the contributions and  support  of
Eric Benson, Dick Brandt, Will Galway, and Paul Milazo.



2. Features of PASLSP and relation to Standard LISP 2. Features of PASLSP and relation to Standard LISP 2. Features of PASLSP and relation to Standard LISP

  PASLSP  as far as possible provides all the functions mentioned
in the attached  Standard  LISP  Report  (note  the  hand-written
comments  added  to  this  appendix);  some  of the functions are
simply stubs, so that  a  Standard  LISP  Test-file  can  be  run
without major modification.


  PASLSP-V2 does not implement the following features of Standard
LISP:


   a. VECTORS (only a simple garbage collector is used).
   b. Strings  are  implemented  as identifiers (not garbage
      collected).
   c. Integers are limited in size  (INTs  and  FIXNUMs,  no
      BIGNUMs).
   d. FLOATING Point is not implemented.
   e. IDs can not be REMOB'ed or INTERN'd.
   f. Only  3  Input  Channels  and  2  Output  Channels are
      available to OPEN, RDS,  WRS,  and  CLOSE.  Thus  file
      input  statements  can  not  be  nested very deeply in Wicat Pascal LISP         1 March 1982                          3


      files.
   g. Line,  Page  and Character counting (POSN, LPOSN, etc)
      are not implemented.


  PASLSP-V2 provides some extensions over Standard LISP:


   a. (CATCH form) and (THROW form) and the tagged versions:
      (TCATCH tag form) and (TTHROW tag form)  are  used  to
      implement error and errorset, and higher level control
      functions.
   b. Implicit PROGN in COND, and LAMBDA expressions.
   c. (WHILE pred action-1 action-2 ... action-n).
   d. (DSKIN 'filename) or (DSKIN "filename")


  PASLSP-V2  has not been extensively tested, and there may still
be a number  of  bugs.  While  some  effort  has  been  spent  in
adjusting  PASLSP to the Wicat, it is clear that the various heap
sizes are not yet optimal.  See appendix A for  current  list  of
functions,  and appendix B for a copy of the Standard LISP Report
annotated to reflect the current status of PASLSP.



3. Using PASLSP on the Wicat 100 3. Using PASLSP on the Wicat 100 3. Using PASLSP on the Wicat 100

  Initializing the system from the floppy looks like this:


Create a directory (call it pl):
Mount the floppy:
Copy the files of interest:

    The files copied will be: paslsp (executable file)
                              paslsp.ini (initialization file)
                              paslsp.tst (a test file)


  Run paslsp as you would any other file.  If you get an error it
is most likely because the paslsp.ini file couldn't be found.  If
this happens, locate paslsp.ini and  try  again.    If  it  still
hangs,  try  calling  Ralph  Ottenheimer  at  (801)  355-0226  or
M. Griss at (801) 581-6542.


  Previously prepared files of LISP  (e.g.,  library  procedures)
can be input by using the function "DSKIN".  For Example,


(DSKIN 'Paslsp!.tst) or (DSKIN "Paslsp.tst") Wicat Pascal LISP         1 March 1982                          4


would  load the paslsp test file. The PASLSP test is adapted from
an extensive test of Standard LISP  (avoiding  features  not  yet
implemented).    This  is a good excercise, try it. [Note that if
the filename is given as an ID, that special characters should be
prefaced by an "escape character", ! . This is also the case  for
filenames  in  OPEN.  Alternately the string form may be used, in
that case special characters need not be escaped.]


  Paslsp is "case-sensitive" with regard to identifiers.  All  of
the kernel procedures have upper-case identifiers associated with
them.      This  means  that  ordinarily  the  expression  (dskin
'paslsp!.tst)  would  not  be  recognized  since  "dskin"  is  in
lowercase.  However, there is a global flag !*RAISE which if true
will  convert all lower-case typin to upper-case.  This Wicat 100
paslsp implementation sets !*RAISE to T as a  default  by  having
(SETQ !*RAISE T) in the paslsp.ini file.  You may put any special
initialization  code  you  like  at  the  end  of  paslsp.ini  as
indicated by the  comments  in  the  file.    Toggling  would  be
accomplished by typing the following lisp-expressions:


        (ON !*RAISE)     equivalent to  (SETQ !*RAISE T)
        (OFF !*RAISE)    equivalent to  (SETQ !*RAISE NIL)


  Any Wicat 100 filename (60 characters maximum)is allowable as a
paslsp  filename.  Remember to prefix all special characters with
an  exclamation-mark:  "!".    Special  characters  include   all
non-alphanumerics.  For  example:  !*RAISE goforit!! paslsp!.test
!/login!/smith!/foo!.sl .


  If the global !*ECHO is not NIL (default is NIL), input will be
echoed  to  the  selected  output  channel.    It  is   sometimes
convienient to put:


        (SETQ !*ECHO T)


at the beginning of a file to be read by DSKIN, and:


        (SETQ !*ECHO NIL)


at the end.  This will echo the file to the screen (or to a file)
as it is read.


  Certain low level errors do not display any explanatory message Wicat Pascal LISP         1 March 1982                          5


but  instead display a numeric code (such as *** # 2), below is a
summary of these codes and their meanings:


  (* error codes.  corresponding to tag = errtag. *)
  noprspace = 1;    (* no more "pair space"--can't cons. *)
  notpair = 2;      (* a pair operation attempted on non-pair.*)
  noidspace = 3;    (* no more free identifiers *)
  undefined = 4;    (* used to mark undefined function cells *)
  noint = 5;        (* no free integer space after gc. *)
  notid = 6;        (* id was expected *)



4. Implementation of PASLSP 4. Implementation of PASLSP 4. Implementation of PASLSP


4.1. Building PASLSP 4.1. Building PASLSP 4.1. Building PASLSP

  PASLSP is built in the following steps:


  ______  _____   Kernel  files,  PAS0.PRE,  and  trailer  file  (main   program)
PASN.PRE are run through a filter program to produce PAS0.PAS and
PASN.PAS,  tailored  to the Wicat 100 (appropriate Include files,
Consts, etc).  This kernel provides the Basic I/O (Token  reading
and printing), handcoded storage allocator and garbage collector,
lowlevel   arithmetic   primitives,   lowlevel  calls  (via  Case
statement) from LISP to kernel, etc.


  ____ __ ____   Rest of LISP, currently files PAS1.RED, PAS2.RED  and  PAS3.RED
are  compiled  to  PASCAL  using  a  version of the Portable LISP
Compiler (PLC) [griss79].  During  compilation,  a  Symbol  Table
file,  PASn.SYM  is  read  in and written out. These files record
(for "incremental" compilation) the names and ID table  locations
of  each  ID encountered, so that the compiler can refer to an ID
by its offset in the ID table. LISP constants are  also  recorded
in the PASn.SYM files. PAS0.SYM is modified by hand as the kernel
is changed.


  The  compilation  model  used  is  that  of a Register Machine:
Arguments to LISP functions are passed  in  registers  (a  PASCAL
array), and the result returned in Register 1. Space is allocated
on  a  software  stack  (not the PASCAL recursion stack), for any
temporaries or save arguments required. Short  functions  usually
do  not  require  any  stack.  The reason for this choice was the
existence of the PLC (targeted at comventional machines), and the
fact that inline access to  the  register  array  compiles  quite
well, while a "PUSH/POP" stack would be much less efficient. Wicat Pascal LISP         1 March 1982                          6


  ______________   Initialization.    After  the PAS0.PAS,..PASN.PAS are produced,
the symbol  table  file  (pas3.sym)  is  converted  into  a  file
PASLSP.INI,  which  contains  the  names  of  all  ID's, the LISP
constants used, and also  ID's  for  all  kernel  functions  that
should  be known to the user LISP level. Also produced is a file,
EXEC.PAS, that contains a case statement  associating  each  user
callable  kernel  function  with  an  integer.   The PAS0.PAS ...
PASN.PAS and EXEC.PAS are compiled and linked into an  executable
file. When this file is executed, PASLSP.INI is read in:  each id
is   read   and   stored  in  the  appropriate  location  in  the
symbol-table, the kernel function names have the associated  Case
index  put  into  a function cell, and the LISP s-expressions are
READ in. Finally, some s-expressions will be executed (with care,
the user can add  his  own  expressions,  including  requests  to
(DSKIN 'library), etc.


4.2. Internal data structures 4.2. Internal data structures 4.2. Internal data structures

  The  data  spaces  (or  heaps)  in  PASLSP  are  divided into 4
sections: the pair space, id space (the oblist), string space and
large integer (fixnum) space.  These are all arrays of objects of
the appropriate type (see declarations below).    The  system  is
fully  tagged,  that is, every LISP item has associated with it a
tag field which denotes the type of the item and an 'info'  field
which  either  points  to  the  item  in an array (in the case of
pairs, identifiers and  fixnums),  or  contains  the  information
itself   (in  the  case  of  inums,  character  codes  and  error
conditions). The info field of a code pointer contains the  index
into  a case staement (see procedure 'execute') by means of which
any LISP callable function may be invoked.


itemref = RECORD
           tag:  integer;   (* Small integer denoting  type.   *)
           info: integer;   (* Item or a pointer to it         *)
                            (* depending upon the type.        *)
          END;

   pair = PACKED RECORD
            prcar: itemref;
            prcdr: itemref;
          END;

  ident = PACKED RECORD           (* identifier *)
            idname: stringp;
               val: itemref; (* value *)
             plist: itemref; (* property list *)
           funcell: itemref; (* function cell *)
           idhlink: id_ptr;  (* hash link *)
                   END; Wicat Pascal LISP         1 March 1982                          7


4.3. Adding user functions to the kernel 4.3. Adding user functions to the kernel 4.3. Adding user functions to the kernel

  It  is  fairly  easy  to  add handcoded Pascal functions to the
kernel so that  they  can  be  called  from  LISP.  For  example,
consider  adding  the  function  SQR(x), that squares its integer
argument.  Since SQR is already the name of  an  existing  PASCAL
function, we will call it "Xsqr" in PASCAL, and SQR in LISP.


  The  function  Xsqr  has  to take its argument from R[1], check
that it is an integer, square the information part, and retag  as
integer:


PROCEDURE Xsqr;
    VAR i1 : longint;

    BEGIN
    int_val(r[1], i1);  (* Test type and extract Info *)
    mkint(i1 * i1, 1)   (* Square, retag, and put in R[1] *)
    END;


  Now  procedure  Xsqr  needs be to be installed into the EXECUTE
table, so that it can be found as the N'th code item. The  number
of  defined procedures will have to be increased by 1 in the 3'rd
line of  procedure  EXECUTE,  (currently  201  defined),  and  an
additional case added:


202:    Xsqr;


  Note  also  that  this  table  gives the Internal names of each
available procedure, should one of  these  be  required  in  your
handcoded  procedure.    Finally,  the Identifier SQR needs to be
associated with case 202 in PASLSP.INI.  Note that PASLAP.INI has
3 tables of objects, each prefixed by a count and terminated by a
0. The first is the Random ID table, consisting of  special  ID's
used  for  messages  etc.  The  second  block is for S-expression
constants, which get  loaded  into  the  base  of  the  stack  as
Globals.  The next batch are the names of LISP callable functions
in the order  corresponding  to  the  EXECUTE  procedure.  Simply
modify  the  count  form 201 to 202 (or whatever), and add SQR at
the end, just before the 0.


  In general, look for  a  sample  procedure  in  the  kernel  if
possible,  or  in  the  compiled part (although these are hard to
follow), and adapt to the specific needs. Note  the  use  of  the
ALLOC(n)  and  DEALLOC(n)  procedures  to  allocate  a  block  of
temporaries on the stack.  These  should  be  used,  rather  than Wicat Pascal LISP         1 March 1982                          8


PASCAL  VAR's, since the garbage collector may need to trace from
one of the saved objects.



5. Future work on PASLSP 5. Future work on PASLSP 5. Future work on PASLSP

  PASLSP V2 is based on a fairly old model of  a  portable  LISP,
and  has been used mainly to explore the capbilities of PASCAL as
a target language. In particular, V2 PASCAL is not  yet  powerful
enough to run the PLC compiler itself; instead, the PLC is run on
our  PSL  system on the DEC-20. In order for the full benefits of
PASLSP (or PSL) to be  realized,  the  user  should  be  able  to
compile  his  own LISP modules into PASCAL and link them with the
kernel.  In order to make the system  even  more  adapatable,  we
would  like  to  write even less of the kernel in PASCAL by hand.
This goal has lead us to the development of PSL.


5.1. Goals of the Utah PSL Project 5.1. Goals of the Utah PSL Project 5.1. Goals of the Utah PSL Project

  The goal of the PSL project is  to  produce  an  efficient  and
transportable Standard LISP system that may be used to:


   a. Experimentally    explore    a    variety    of   LISP
      implementation issues  (storage  management,  binding,
      environments, etc.).

   b. Effectively   support   the  REDUCE  computer  algebra
      system [hearn73] on a number of machines.

   c. Provide the same,  uniform,  modern  LISP  programming
      environment  on  all  of  the  machines  that  we  use
      (DEC-20, VAX/750, PDP-11/45, PERQ, Wicat and  Apollo),
      of  the power and complexity of UCI-LISP, FranzLISP or
      MACLISP, with some extensions and enhancements derived
      from LISP Machine LISP or CommonLISP.


                                                     entire                                                      entire   The approach we have been using is to  write  the  entire  LISP
system  in  PSL  (using  LISP extensions for dealing with machine
words and operations), and to bootstrap it to the desired  target
machine in two steps:


   a. Cross  compile  an  appropriate kernel to the assembly
      language of the target machine;

   b. Once the kernel is running, use  a  resident  compiler
      and  loader,  or fast-loader, to build the rest of the
      system. Wicat Pascal LISP         1 March 1982                          9


  The  PASLSP  system,  and other early implementations, have the
problem that the implementation language (PASCAL) is  a  distinct
language  from  LISP, so that communication between "system" code
and "LISP" code was difficult.  We have incorporated all  of  the
good  features of the earlier work into a new efficient LISP-like
systems  language,  SYSLISP,  recoded  all  useful  modules  into
SYSLISP,  and  proceeded  from there.  SYSLISP currently produces
targeted  assembly  code;  earlier  verisions  were  targeted  at
high-level languages such as FORTRAN, PASCAL, C or ADA.  The goal
is  a  portability  strategy  that  leads  to an efficient enough
system  for  a  production  quality,  yet  portable  system.   We
currently  think of the extensions to Standard LISP as having two
levels: the SYSLISP level,  dealing  with  words  and  bytes  and
machine  operations,  enabling us to write essentially all of the
kernel in Standard LISP; and, the LISP level,  incorporating  all
of  the features that make PSL into a modern LISP.  Both modes of
PSL are compiled by an improved version of the Portable  Standard
LISP  Compiler.  The  SYSLISP  mode  of  the  PSL  compiler  does
compile-time  folding  of  constants,  and   more   comprehensive
register  allocation  than  the previous LISP-only version of the
compiler.


  The current state of PSL is fully described  in  an  "overview"
document  obtainable  from the authors [griss81e].  Currently PSL
runs on the DEC-20 under TOPS-20, and on the DEC VAX-11/750 under
Unix.  We are now  concentrating  on  the  MC68000  PSL  for  the
Apollo.  All  of  the  code-generators  and  assembler support is
complete, and a number of large files  have  been  compiled  from
LISP  to  assembly  code, and correctly assembled and executed on
the Apollo, testing basic I/O and arithmetic. We are now  in  the
process of writing the PSL support code (small functions in LAP),
and  testing  that  various  decisions  about register and memory
usage are correct. Based on the development history on  the  VAX,
we  are  about  1-2  months  away  from  a preliminary PSL on the
Apollo.



6. References 6. References 6. References

[1]   Benson, E. and Griss, M. L.
      _______  _ ________ ____ _____ _______ ______________       SYSLISP: A portable LISP based systems implementation
         ________          language.
      Utah Symbolic Computation Group, Report UCP-81, University
         of Utah, February, 1981.

[2]   Brandt, R. C. and Knapp, B. H.
      The University of Utah Video Computer Authoring System.
         ___________ __ ___ _________ __ ________ __________       In Proceedings of the Symposium on Learning Technology,
         pages 18-23.  Orlando, Florida, Feb, 1981. Wicat Pascal LISP         1 March 1982                         10


[3]   Griss, M. L.; Kessler, R. R.; and Maguire, G. Q. Jr.
      TLISP - A Portable LISP Implemented in P-code.
         ___________ __ _______ __       In Proceedings of EUROSAM 79, pages 490-502.  ACM, June,
         1979.

[4]   Griss, M. L. and Morrison, B.
      ___ ________ ________ ____ _____ ______       The Portable Standard LISP Users Manual.
      Utah Symbolic Computation Group,  TR-10, University of
         Utah, March, 1981.

[5]   Griss, M. L.
      ________ ________ ____  _ _____ ________       Portable Standard LISP: A Brief Overview.
      Utah Symbolic Computation Group, Operating Note 58,
         University of Utah, October, 1981.

[6]   Hearn, A. C.
      ______ _ _____ ______       REDUCE 2 Users Manual.
      Utah Symbolic Computation Group UCP-19, University of Utah,
         1973.

[7]   Marti, J. B., et al.
      Standard LISP Report.
      _______ _______       SIGPLAN Notices 14(10):48-68, October, 1979.



APPENDIX A:  A List of Current PASLSP Functions and Globals APPENDIX A:  A List of Current PASLSP Functions and Globals APPENDIX A:  A List of Current PASLSP Functions and Globals


____ ________ __________ ___ ________ ____ ______ Lisp Callable Functions, see Standard LISP Report
!*FIRST!-PROCEDURE      The top loop LISP reader
ABS
ADD1
AND
APPEND
APPLY
APPLY1                  (APPLY f (LIST u))
ASSOC
ATOM
ATSOC
CAAAAR
CAAADR
CAAAR
CAADAR
CAADDR
CAADR
CAAR
CADAAR
CADADR
CADAR
CADDAR
CADDDR Wicat Pascal LISP         1 March 1982                         11


CADDR
CADR
CAR
CATCH
CDAAAR
CDAADR
CDAAR
CDADAR
CDADDR
CDADR
CDAR
CDDAAR
CDDADR
CDDAR
CDDDAR
CDDDDR
CDDDR
CDDR
CDR
CLOSE
CODEP
COMPRESS
COND
CONS
CONSTANTP
DE
DEFLIST
DELATQ          (DELATQ 'X alist) deletes (X . any) from alist
DELETE
DELQ             Efficient DELETE (using EQ)
DF
DIFFERENCE
DIGIT
DIVIDE
DM
DN
DSKIN           (DSKIN file-id)
EOFP            (EOFP channel)
EQ
EQCAR
EQN
EQUAL
ERROR
ERRORSET
ERRPRT           Prints message with *'s
EVAL
EVLAM            Evaluates a LAMBDA expression
EVLIS
EXPAND
EXPLODE
EXPT
FASTSTAT        Prints RECLAIM message Wicat Pascal LISP         1 March 1982                         12


FIX
FIXP
FLAG
FLAG1           (FLAG (LIST x) y)
FLAGP
FLOAT
FLOATP
FLUID
FLUIDP
FUNCELL         Accesses function cell
FUNCTION
GENSYM
GET
GETD
GETV
GLOBAL
GLOBALP
GO
GREATERP
IDP
INTERN
LBIND1          Binds a single ID in LAMBDA
LBINDN
LENGTH
LESSP
LIST2           For efficent LIST compilation
LIST3
LIST4
LIST5
LITER
MAP
MAPC
MAPCAN
MAPCAR
MAPCON
MAPLIST
MAX
MAX2
MEMBER
MEMQ
MIN
MIN2
MINUS
MINUSP
MKVECT
MSGPRT
NCONC
NCONS
NOT
NULL
NUMBERP
ONEP Wicat Pascal LISP         1 March 1982                         13


OPEN
OR
ORDERP
P!.N                    Evaluates Implicit PROGNs
PAIR
PAIRP
PBIND1                  PROG binding
PBINDN
PLIST                   Access full property list
PLUS
PLUS2
PRIN1
PRIN2
PRIN2T
PRIN2TL
PRINC
PRINT
PROG
PROG2
PROGG0131
PROGN
PUT
PUTC
PUTD
PUTL
PUTV
QUOTIENT
RDEVPR          A read-eval-print loop
RDS
RDTOK
READ
READCH
RECLAIM
REMAINDER
REMD
REMFLAG
REMFLAG1
REMOB
REMPROP
RETURN
REV
REVERSE
REVX
RLIST
RPLACA
RPLACD
SASSOC
SET
SETFUNCELL
SETPLIST
SETVALUE
STRINGP         Equivalent to IDP Wicat Pascal LISP         1 March 1982                         14


SUB1
SUBLIS
SUBST
TCATCH
TERPRI
THROW
TIMES
TIMES2
TOKEN
TTHROW
UNBIND1
UNBINDN
UNBINDTO
UNFLUID
UPBV
VALUE
VECTORP
WHILE
WRS
WRTOK
XAPPLY
XCONS
ZEROP
___________ _______ Interesting Globals
!*RAISE         Raise lower case typing to upper case if not NIL
!*ECHO          Selected input to selected output if not NIL.
BSTK!*          Holds old values of rebound IDS
EMSG!*          Error message in most recent call on ERROR
ENUM!*          Error number in most recent call on ERROR.
INITFORM!*      First Expression EVAL'ed
THROWING!*      Indicates if throwing
THROWTAG!*      Indicates TAG in TTHROW
TOK!*           Holds last token scanned
TOKTYPE         Indicates type of token scanned:
                        1: integer
                        2: id
                        3: character Wicat Pascal LISP         1 March 1982                          i


                        Table of Contents                         Table of Contents                         Table of Contents

1. Introduction                                                 1
     1.1. History of PASLSP                                     1
     1.2. Acknowledgement                                       2
2. Features of PASLSP and relation to Standard LISP             2
3. Using PASLSP on the Wicat 100                                3
4. Implementation of PASLSP                                     5
     4.1. Building PASLSP                                       5
     4.2. Internal data structures                              6
     4.3. Adding user functions to the kernel                   7
5. Future work on PASLSP                                        8
     5.1. Goals of the Utah PSL Project                         8
6. References                                                   9
APPENDIX A:  A List of Current PASLSP Functions and Globals    10

Added perq-pascal-lisp-project/wicat-paslsp.mss version [a62d5c5151].





















































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
@Device(lpt)
@style(justification yes)
@style(spacing 1)
@use(Bibliography "<griss.docs>mtlisp.bib")
@make(article)
@modify(enumerate,numbered=<@a. @,@i. >, spread 1)
@modify(appendix,numbered=<APPENDIX @A: >)
@modify(itemize,spread 1)
@modify(description,leftmargin +2.0 inch,indent -2.0 inch)
@define(up,use text,capitalized on,  break off)
@define(mac,use text, underline off,  break off)
@define(LISPmac,use text, underline alphanumerics,  break off)
@pageheading(Left  "Utah Symbolic Computation Group",
             Right "December 1981", 
             Line "Operating Note 60"
            )
@set(page=1)
@newpage()
@begin(titlepage)
@begin(titlebox)
@b(A PASCAL Based Standard LISP for the Wicat 100)
@center[
by

M. L. Griss and R. Ottenheimer

Department of Computer Science
University of Utah
Salt Lake City, Utah 84112

@b(Preliminary  Version)

Last Revision: @value(date)]

@end(titlebox)
@begin(abstract)
This report describes an interim implementation of Standard LISP for the
Wicat 100. This LISP is based upon the Standard LISP report, and a
newly developing Portable Standard LISP.  This interim implementation is
designed to explore LISP implementations in PASCAL on the Wicat 100 and
similar machines.  The system consists of a kernel, handcoded in PASCAL,
with the rest of the system written in LISP and compiled to PASCAL.
@End(abstract)
@begin(Researchcredit)
Work supported in part by the National Science Foundation
under Grant No. MCS80-07034.
@end(Researchcredit)
@end(titlepage)
@pageheading(Left "Wicat Pascal LISP",Center "@value(date)",
             Right "@value(Page)"
            )
@set(page=1)
@newpage
@section(Introduction)
In this preliminary report, we describe an implementation of Standard LISP
in PASCAL, PASLSP. Versions of PASLSP have been run on a number of
machines, ranging from an LSI-11 based TERAK to Apollo and PERQ. This report
concentrates on the Wicat 100 implementation. This report is to be read in
conjunction with the Standard LISP report@cite(Marti79); we will
highlight the differences from the functions documented in the Standard
LISP, describe the implementation strategy, and discuss future work.

PASLSP is based on a series of small and medium sized LISP interpreters
that have been developed at the University of Utah to explore LISP
implementations in higher level languages. Each of these LISP systems
consists of a small kernel handcoded in some language, with the rest of the
system written in LISP and compiled to the target language.  We have used
FORTRAN, PASCAL and assembly language as targets. The PASLSP series use
PASCAL for the kernel, and have a LISP to PASCAL compiler for the rest of
the system. 

Recent work has concentrated on reducing the size of the hand-coded kernel,
and extending the compiler to handle systems level constructs. This has
resulted in a new Portable Standard LISP, PSL, running on the DEC-20 and
VAX-11/750@cite(Benson81,Griss81). An implementation of PSL for MC68000 is
underway. The PSL system is a modern, efficient LISP, written entirely in
itself; it uses an efficient LISP to machine code compiler to produce the
kernel, and then the rest of LISP is loaded. In the future we hope to
produce a complete PSL targeted at a higher level languages, such as
PASCAL, C or ADA, and this will replace the current PASLSP.

@subsection(History of PASLSP)
The system now called PASLSP was originally developed (by M. Griss and W.
Galway), as a small LISP like kernel to support a small computer algebra
system on an LSI-11 TERAK; this was to be used as an answer analysis module
within a CAI system@cite(Brandt81), written entirely in PASCAL. It was
decided to hand-code a very small kernel, and compile additional functions
written in LISP (LISP support functions, parser and
simplifier) to PASCAL,
using a modified Portable LISP compiler@cite(griss79). This version (call
it V0) did not even have user defined functions, since space on the TERAK
was at a premium.

About June 1981, PASLSP came to the attention of a number people evaluating
Apollo's and PERQ's, and it was suggested that we enhance V0 PASLSP for
this purpose. During the space of a few days, features taken from the
Standard LISP Report and newly developing PSL files were added to produce
PASLSP-V1, running on a DEC-20 and Terak. This was a fairly complete LISP
(including Catch and Throw), but lacked a few features (OPEN, CLOSE, RDS,
WRS, PROG, GO, RETURN, COMPRESS, EXPLODE, Vectors and Strings, etc.).  V1
PASLSP was adapted to a PERQ, VAX and Apollo by Paul Milazo of Schlumberge
in the space of a few weeks (we did not have a PERQ or Apollo at that
time).

We subsequently obtained a PERQ,  Apollo and a Wicat, and recent work has been
aimed at producing an enhanced PASLSP for these machines, maintaining all
versions in one set of source files.  The current system, PASLSP-V2, is
produced from a single PASCAL kernel and set of LISP support files; the
machine specific features are handled by a simple Source Code
Conditionalizer, changing the definition of certain constants and data
types. Only a few features of the Standard LISP report are missing,
and there are a number of additions.

@subsection(Acknowledgement)

We would like to acknowledge the contributions and support of
Eric Benson, Dick Brandt, Will Galway,   and Paul Milazo.

@section(Features of PASLSP and relation to Standard LISP)
PASLSP as far as possible provides all the functions mentioned
in the attached Standard LISP Report (note the hand-written
comments added to this appendix); some of the functions are simply
stubs, so that a Standard LISP Test-file can be run without major
modification.

PASLSP-V2  does not implement the following features of Standard LISP:
@begin(enumeration,spread 0)
VECTORS (only a simple garbage collector is used).

Strings are implemented as identifiers (not garbage collected).

Integers are limited in size (INTs and FIXNUMs, no BIGNUMs).

FLOATING Point is not implemented.

IDs can not be REMOB'ed or INTERN'd.

Only 3 Input Channels and 2 Output Channels are available to OPEN,
RDS, WRS, and CLOSE. Thus file input statements can not be nested
very deeply in files.

Line, Page and Character counting (POSN, LPOSN, etc) are not implemented.
@end(enumeration)

PASLSP-V2 provides some extensions over Standard LISP:
@begin(enumerate,spread 0)
(CATCH form) and (THROW form) and the tagged versions: (TCATCH tag form)
and (TTHROW tag form) are used to implement error and errorset, 
and higher level control functions.

Implicit PROGN in COND, and LAMBDA expressions.

(WHILE pred action-1 action-2 ... action-n).

(DSKIN 'filename) or (DSKIN "filename")
@end(enumerate)

PASLSP-V2 has not been extensively tested, and there may still be a number
of bugs. While some effort has been spent in adjusting PASLSP to the Wicat,
it is clear that the various heap sizes are not yet optimal. 
See appendix A for current list of functions, and appendix B for a copy
of the Standard LISP Report annotated to reflect the current status of 
PASLSP.

@section(Using PASLSP on the Wicat 100)
	Initializing the system from the floppy looks like this:
@begin(verbatim)
Create a directory (call it pl):
Mount the floppy:
Copy the files of interest:

    The files copied will be: paslsp (executable file)
                              paslsp.ini (initialization file)
                              paslsp.tst (a test file)
@end(verbatim)

Run paslsp as you would any other file.  If you
get an error it is most likely because the paslsp.ini file couldn't be found.
If this happens, locate paslsp.ini and try again.  If it still hangs,
try calling Ralph Ottenheimer at (801) 355-0226 or M. Griss at (801) 581-6542.


Previously prepared files of LISP (e.g., library procedures)
can be input by
using the function "DSKIN".  For Example,
@begin(verbatim)
(DSKIN 'Paslsp!.tst) or (DSKIN "Paslsp.tst")
@end
would load the paslsp test file. The PASLSP test is adapted from an extensive
test of Standard LISP (avoiding features not yet implemented).  This is a
good excercise, try it. [Note that if the filename is given as an ID,
that special characters should be prefaced by an "escape character",
! . This is  also the case for filenames in OPEN.  Alternately the string
form may be used, in that case special characters need not be escaped.]

  Paslsp is "case-sensitive" with regard to identifiers.  All of the
kernel procedures have upper-case identifiers associated with them.  This
means that ordinarily the expression (dskin 'paslsp!.tst) would not be
recognized since "dskin" is in lowercase.  However, there is a global flag
!*RAISE which if true will convert all lower-case typin to upper-case.
This Wicat 100 paslsp implementation sets !*RAISE to T as a default by
having (SETQ !*RAISE T) in the paslsp.ini file.  You may put any special
initialization code you like at the end of paslsp.ini as indicated by the
comments in the file.
Toggling would be accomplished by typing the following lisp-expressions:
@begin(verbatim)
	(ON !*RAISE)     equivalent to  (SETQ !*RAISE T)
        (OFF !*RAISE)    equivalent to  (SETQ !*RAISE NIL)
@end(verbatim)

	Any Wicat 100 filename (60 characters maximum)is allowable
 as a paslsp filename.
Remember to prefix all special characters with an exclamation-mark: "!". 
Special characters include all non-alphanumerics. For example: !*RAISE
 goforit!! paslsp!.test !/login!/smith!/foo!.sl .

If the global !*ECHO is not NIL (default is NIL), input will be echoed to
the selected output channel.  It is sometimes convienient to put:
@begin(verbatim)
        (SETQ !*ECHO T)
@end(verbatim)
at the beginning of a file to be read by DSKIN, and:
@begin(verbatim)
        (SETQ !*ECHO NIL)
@end(verbatim)
at the end.  This will echo the file to the screen (or to a file) as it is
read. 

Certain low level errors do not display any explanatory message but
instead display a numeric code (such as *** # 2), below is a summary of these
codes and their meanings:

@begin(verbatim)
  (* error codes.  corresponding to tag = errtag. *)
  noprspace = 1;    (* no more "pair space"--can't cons. *)
  notpair = 2;      (* a pair operation attempted on non-pair.*)
  noidspace = 3;    (* no more free identifiers *)
  undefined = 4;    (* used to mark undefined function cells *)
  noint = 5;        (* no free integer space after gc. *)
  notid = 6;        (* id was expected *)
@end(verbatim)


@section(Implementation of PASLSP)
@subsection(Building PASLSP)
PASLSP is built in the following steps:

@u(Kernel files), PAS0.PRE, and trailer file (main program) PASN.PRE
are run through a filter program to produce PAS0.PAS and PASN.PAS,
tailored to the Wicat 100 (appropriate Include files, Consts, etc).
This kernel provides the Basic I/O (Token reading and printing),
handcoded storage allocator and garbage collector, lowlevel arithmetic
primitives, lowlevel calls (via Case statement) from LISP to kernel, etc.

@u(Rest of LISP), currently files PAS1.RED, PAS2.RED and PAS3.RED are
compiled to PASCAL using a version of the Portable LISP Compiler
(PLC)@cite(griss79). During compilation, a Symbol Table file, PASn.SYM is
read in and written out. These files record (for "incremental" compilation)
the names and ID table locations of each ID encountered, so that the compiler
can refer to an ID by its offset in the ID table. LISP constants are also
recorded in the PASn.SYM files. PAS0.SYM is modified by hand as the kernel
is changed.  

The compilation model used is that of a Register Machine: Arguments to LISP
functions are passed in registers (a PASCAL array), and the result returned
in Register 1. Space is allocated on a software stack (not the PASCAL
recursion stack), for any temporaries or save arguments required. Short
functions usually do not require any stack. The reason for this choice was
the existence of the PLC (targeted at comventional machines), and the fact
that inline access to the register array compiles quite well, while a
"PUSH/POP" stack would be much less efficient.

@u(Initialization). 
After the PAS0.PAS,..PASN.PAS are produced,
the symbol table file (pas3.sym) is converted into a file
PASLSP.INI, which contains the names of all ID's, the LISP constants
used, and also ID's for all kernel functions that should be known to the
user LISP level. Also produced is a file, EXEC.PAS, that contains a case
statement associating each user callable kernel function with an integer.
The PAS0.PAS ... PASN.PAS and EXEC.PAS are compiled and linked into an
executable file. When this file is executed, PASLSP.INI is read in:
each id is read and stored in the appropriate location in the symbol-table,
the kernel function names have the associated Case index put into
a function cell, and the LISP s-expressions are READ in. Finally,
some s-expressions will be executed (with care, the user can add his own
expressions, including requests to (DSKIN 'library), etc.
@subsection(Internal data structures)
The data spaces (or heaps) in PASLSP are divided into 4 sections: the
pair space, id space (the oblist), string space and large integer
(fixnum) space.  These are all arrays of objects of the appropriate type
(see declarations below).  The system is fully tagged, that is, every LISP
item has associated with it a tag field which denotes the type of the item 
and an 'info' field which either points to the item in an array (in the
case of pairs, identifiers and fixnums), or contains the information 
itself (in the case of inums, character codes and error conditions). The
info field of a code pointer contains the index into a case staement (see
procedure 'execute') by means of which any LISP callable function may be
invoked.

@begin(verbatim,leftmargin 0)
itemref = RECORD
           tag:  integer;   (* Small integer denoting  type.   *)
           info: integer;   (* Item or a pointer to it         *)
                            (* depending upon the type.        *)
          END;

   pair = PACKED RECORD
            prcar: itemref;
            prcdr: itemref;
          END;

  ident = PACKED RECORD           (* identifier *)
            idname: stringp;
               val: itemref; (* value *)
             plist: itemref; (* property list *)
           funcell: itemref; (* function cell *)
           idhlink: id_ptr;  (* hash link *)
                   END;
@end(verbatim)
@subsection(Adding user functions to the kernel)
It is fairly easy to add handcoded Pascal functions to
the kernel so that they can be called from LISP. For example,
consider adding the function SQR(x), that squares its integer argument.
Since SQR is already the name of an existing PASCAL function, we will
call it "Xsqr" in PASCAL, and SQR in LISP.

The function Xsqr has to take its argument from R[1], check that it is
an integer, square the information part, and retag as integer:
@begin(verbatim)
PROCEDURE Xsqr;
    VAR i1 : longint;

    BEGIN
    int_val(r[1], i1);  (* Test type and extract Info *)
    mkint(i1 * i1, 1)   (* Square, retag, and put in R[1] *)
    END;
@end(verbatim)

Now procedure Xsqr needs be to be installed into the EXECUTE table, so that
it can be found as the N'th code item. The number of defined procedures
will have to be increased by 1 in the 3'rd line of procedure EXECUTE,
(currently 201 defined), and an additional case added:
@begin(verbatim)
202:    Xsqr;
@end(verbatim)

Note also that this table gives the Internal names of each available
procedure, should one of these be required in your handcoded procedure.
Finally, the Identifier SQR needs to be associated with case 202 in
PASLSP.INI.  Note that PASLAP.INI has 3 tables of objects, each prefixed by
a count and terminated by a 0. The first is the Random ID table, consisting
of special ID's used for messages etc. The second block is for S-expression
constants, which get loaded into the base of the stack as Globals. The
next batch are the names of LISP callable functions in the order
corresponding to the EXECUTE procedure. Simply modify the count form
201 to 202 (or whatever), and add SQR at the end, just before the 0.

In general, look for a sample procedure in the kernel if possible,
or in the compiled part (although these are hard to follow), and adapt
to the specific needs. Note the use of the ALLOC(n) and DEALLOC(n)
procedures to allocate a block of temporaries on the stack.
These should be used, rather than PASCAL VAR's, since the garbage collector
may need to trace from one of the saved objects.
@Section(Future work on PASLSP)
PASLSP V2 is based on a fairly old model of a portable LISP, and
has been used mainly to explore the capbilities of PASCAL as a
target language. In particular, V2 PASCAL is not yet powerful enough to
run the PLC compiler  itself;
instead, the PLC is run on our PSL system on the DEC-20. In order for the
full benefits of PASLSP (or PSL) to be realized, the user should be able to
compile his own LISP modules into PASCAL and link them with the kernel.
In order to make the system even more adapatable, we would like to write
even less of the kernel in PASCAL by hand. This goal has lead us to the
development of PSL. 

@subsection(Goals of the Utah PSL Project)

The goal of the PSL project is to produce an efficient and transportable
Standard LISP system that may be used to:
@begin(enumeration)
Experimentally  explore
a variety of LISP implementation issues (storage management, binding,
environments, etc.).

Effectively support the REDUCE computer algebra system@cite(hearn73)
on a number of machines.

Provide the same, uniform, modern LISP programming environment on all of
the machines that we use (DEC-20, VAX/750, PDP-11/45, PERQ, Wicat and
Apollo), of the power and complexity of UCI-LISP, FranzLISP or MACLISP, 
with some extensions and enhancements derived from LISP Machine LISP or 
CommonLISP.
@end(enumeration)

The approach we have been using is to write the @b(entire) LISP system in
PSL (using LISP extensions for dealing with 
machine words and operations), and to bootstrap it to the desired target
machine
in two steps:
@begin(enumeration)
Cross compile an appropriate kernel to the assembly language of the
target machine;

Once the kernel is running, use a resident compiler and loader, or
fast-loader, to build the rest of the system.
@end(enumeration)

 The PASLSP system, and other early implementations, have the problem that
the implementation language (PASCAL) is a distinct language from LISP, so
that communication between "system" code and "LISP" code was difficult.  We
have incorporated all of the good features of the earlier work into a new
efficient LISP-like systems language, SYSLISP, recoded all useful modules
into SYSLISP, and proceeded from there.  SYSLISP currently produces
targeted assembly code; earlier verisions were targeted at high-level
languages such as FORTRAN, PASCAL, C or ADA.  The goal is a portability
strategy that leads to an efficient enough system for a production quality,
yet portable system. We currently think of the extensions to Standard LISP
as having two levels: the SYSLISP level, dealing with words and bytes and
machine operations, enabling us to write essentially all of the kernel in
Standard LISP; and, the LISP level, incorporating all of the features that
make PSL into a modern LISP.  Both modes of PSL are compiled by an improved
version of the Portable Standard LISP Compiler. The SYSLISP mode of the PSL
compiler does compile-time folding of constants, and more comprehensive
register allocation than the previous LISP-only version of the compiler.

The current state of PSL is fully described in an "overview" document
obtainable from the authors @cite(griss81e).  Currently PSL runs on the
DEC-20 under TOPS-20, and on the DEC VAX-11/750 under Unix.  We are now
concentrating on the MC68000 PSL for the Apollo. All of the code-generators
and assembler support is complete, and a number of large files have been
compiled from LISP to assembly code, and correctly assembled and executed
on the Apollo, testing basic I/O and arithmetic. We are now in the process
of writing the PSL support code (small functions in LAP), and testing that
various decisions about register and memory usage are correct. Based on the
development history on the VAX, we are about 1-2 months away from a
preliminary PSL on the Apollo.
@section(References)
@Bibliography
@appendix(A List of Current PASLSP Functions and Globals)
@begin(verbatim,leftmargin 0)
@include(Appendix-A.table)
@end(verbatim)

Added perq-pascal-lisp-project/wicat-paslsp.otl version [f9df769f6f].







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Comment{OUTLINE of WICAT-PASLSP.MSS.1 by Scribe 3C(1250) on 1 March 1982 at 15:57}
1. Introduction                                           1 WICAT-PASLSP.MSS.1 line 54
  1.1. History of PASLSP                                  1 WICAT-PASLSP.MSS.1 line 82
  1.2. Acknowledgement                                    2 WICAT-PASLSP.MSS.1 line 114
2. Features of PASLSP and relation to Standard LISP       2 WICAT-PASLSP.MSS.1 line 119
3. Using PASLSP on the Wicat 100                          3 WICAT-PASLSP.MSS.1 line 165
4. Implementation of PASLSP                               5 WICAT-PASLSP.MSS.1 line 244
  4.1. Building PASLSP                                    5 WICAT-PASLSP.MSS.1 line 245
  4.2. Internal data structures                           6 WICAT-PASLSP.MSS.1 line 287
  4.3. Adding user functions to the kernel                7 WICAT-PASLSP.MSS.1 line 320
5. Future work on PASLSP                                  8 WICAT-PASLSP.MSS.1 line 364
  5.1. Goals of the Utah PSL Project                      8 WICAT-PASLSP.MSS.1 line 376
6. References                                             9 WICAT-PASLSP.MSS.1 line 437
APPENDIX A:  A List of Current PASLSP Functions and Glo  10 WICAT-PASLSP.MSS.1 line 439
 Table of Contents                                        1 -SCRIBE-SCRATCH-.13-27-1.100013 line 3
	Alphabetic Listing of Cross-Reference Tags and Labels

Tag or Label Name                    Page   Label Value  Source file Location
-----------------------------------------------------------------------------

Added perq-pascal-lisp-project/wicat-problems.txt version [94ead12563].









>
>
>
>
1
2
3
4
what is the relationship between 'a string', "a string" and arrays?

buildup of old files          

Added psl-1983/20-comp/dec20-asm.b version [1691fba461].

cannot compute difference between binary files

Added psl-1983/20-comp/dec20-asm.build version [647128045f].





















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
CompileTime <<
load If!-System;
load SysLisp;
off UserMode;
>>;
CompileTime if_system(PDP10, NIL, <<
in "DEC20-DATA-MACHINE.RED"$
in "PC:DATA-MACHINE.RED"$
>>)$
in "DEC20-ASM.RED"$

Added psl-1983/20-comp/dec20-asm.ctl version [6283c939cc].





















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
; Rebuild the ASM module
@term page 0
@get psl:rlisp
@st
*loaddirectories!*:='("pl:");
*load build;
*build "DEC20-ASM";
*quit;
@reset .
@term page 24

Added psl-1983/20-comp/dec20-asm.log version [9f1a8a4b68].

cannot compute difference between binary files

Added psl-1983/20-comp/dec20-asm.red version [1de9ae2065].













































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

% 20-ASM.RED - Dec-20 specific information for LAP-TO-ASM
% 
% Author:      Eric Benson
%	       Symbolic Computation Group
%              Computer Science Dept.
%              University of Utah
% Date:        5 January 1982
% Copyright (c) 1982 University of Utah
%

%  <PSL.20-COMP>20-ASM.RED.1, 25-Feb-82 16:46:44, Edit by BENSON
%  Converted from VAX version

fluid '(CodeFileNameFormat!*
	DataFileNameFormat!*
	InputSymFile!*
	OutputSymFile!*
	CommentFormat!*
	LabelFormat!*
	ExternalDeclarationFormat!*
	ExportedDeclarationFormat!*
	FullWordFormat!*
	DoubleFloatFormat!*
	ReserveZeroBlockFormat!*
	ReserveDataBlockFormat!*
	DefinedFunctionCellFormat!*
	UndefinedFunctionCellInstructions!*
	MainEntryPointName!*
	!*MainFound
	CodeOut!*
	DataOut!*
	!*Lower
	ASMOpenParen!*
	ASMCloseParen!*
	NumericRegisterNames!*);

CodeFileNameFormat!* := "%w.mac";
DataFileNameFormat!* := "d%w.mac";
InputSymFile!* := "20.sym";
OutputSymFile!* := "20.sym";
GlobalDataFileName!* := "global-data.red"$
MainEntryPointName!* := 'MAIN!.;
NumericRegisterNames!* := '[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15];
CommentFormat!* := "; %p%n";
LabelFormat!* := "%w:";
ExternalDeclarationFormat!* := "	extern %w%n";
ExportedDeclarationFormat!* := "	intern %w%n";
FullWordFormat!* := "	%e%n";	% FullWord expects %e for parameter
DoubleFloatFormat!* := "	%w%n	0%n";
ReserveZeroBlockFormat!* := "%w:	block %e%n";
ReserveDataBlockFormat!* := "	block %e%n";
DefinedFunctionCellFormat!* := "	jrst %w##%n";
UndefinedFunctionCellInstructions!* :=
	       '((jsp (reg t5) (Entry UndefinedFunction)));
ASMOpenParen!* := '!<;
ASMCloseParen!* := '!>;

DefList('((LAnd !&)
	  (LOr !!)
	  (LXor !^!!)
	  (LSH !_)), 'BinaryASMOp);

put('LNot, 'UnaryASMOp, '!^!-);

DefList('((t1 6)
	  (t2 7)
	  (t3 8)
	  (t4 9)
	  (t5 10)
	  (t6 11)
	  (nil 0)
	  (st 15)), 'RegisterName);

put('MkItem, 'ASMExpressionFormat, "<%e_31>+%e");

lisp procedure CodeFileHeader();
    CodePrintF "	search monsym%n	radix 10%n";

lisp procedure DataFileHeader();
    DataPrintF "	radix 10%n";

lisp procedure CodeFileTrailer();
    CodePrintF(if !*MainFound then "	end MAIN.%n" else "	end%n");

lisp procedure DataFileTrailer();
    DataPrintF "	end%n";

lisp procedure CodeBlockHeader();
    NIL;

lisp procedure CodeBlockTrailer();
    NIL;

lisp procedure DataAlignFullWord();
    NIL;

lisp procedure PrintString S;
begin scalar N;
    N := Size S;
    PrintF "	byte(7)";
    for I := 0 step 1 until N do
    <<  PrintExpression Indx(S, I);
	Prin2 '!, >>;
    PrintExpression 0;
    TerPri();
end;

lisp procedure PrintByteList L;
    if null L then NIL else
    <<  PrintF "	byte(7)";
	while cdr L do
	<<  PrintExpression car L;
	    Prin2 '!,;
	    L := cdr L >>;
	PrintExpression car L;
	TerPri() >>;

lisp procedure PrintByte X;
<<  PrintF "	byte(7)";
    PrintExpression X;
    TerPri() >>;

lisp procedure PrintHalfWordList L;
    if null L then NIL else
    <<  PrintF "	byte(18)";
	while cdr L do
	<<  PrintExpression car L;
	    Prin2 '!,;
	    L := cdr L >>;
	PrintExpression car L;
	TerPri() >>;

lisp procedure PrintOpcode X;
    Prin2 X;

lisp procedure SpecialActionForMainEntryPoint();
    CodePrintF "	intern MAIN.%nMAIN.:";

lisp procedure ASMSymbolP X;
    Radix50SymbolP(if IDP X then ID2String X else X);

lisp procedure Radix50SymbolP X;
begin scalar N, C, I;
    N := Size X;
    if N > 5 then return NIL;
    C := Indx(X, 0);
    if not (C >= char A and C <= char Z
		or C = char !% or C = char !. or C = char !$) then return NIL;
    I := 1;
Loop:
    if I > N then return T;
    C := Indx(X, I);
    if not (C >= char A and C <= char Z
		or C >= char !0 and C <= char !9
		or C = char !% or C = char !. or C = char !$) then return NIL;
    I := I + 1;
    goto Loop;
end;

lisp procedure PrintNumericOperand X;
    if ImmediateP X then Prin2 X else PrintF("[%w]", X);

lisp procedure OperandPrintIndirect X;
<<  Prin2 '!@;
    PrintOperand cadr X >>;

put('Indirect, 'OperandPrintFunction, 'OperandPrintIndirect);

lisp procedure OperandPrintIndexed X;
<<  X := cdr X;
    PrintExpression cadr X;
    Prin2 '!(;
    PrintOperand car X;
    Prin2 '!) >>;

put('Indexed, 'OperandPrintFunction, 'OperandPrintIndexed);

macro procedure Immediate X;		% immediate does nothing on the 20
    cadr X;

lisp procedure ASMPseudoFieldPointer U;
%
% (FieldPointer Operand StartingBit Length)
%
<<  U := cdr U;
    Prin2 "point ";
    PrintExpression third U;
    Prin2 '!, ;
    PrintOperand first U;
    Prin2 '!, ;
    PrintExpression list('difference, list('plus2, second U, third U), 1) >>;

put('FieldPointer, 'ASMExpressionFunction, 'ASMPseudoFieldPointer);

procedure MCPrint(x); % Echo of MC's
 CodeP