Commit | Line | Data |
---|---|---|
7129096e C |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ucisubset.l ;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ; Functions for a subset of UCI Lisp that are either used by PEARL | |
3 | ; or were needed by PEARL users at Berkeley. | |
4 | ; This was purposely designed to interfere as little as necessary | |
5 | ; with Franz Lisp, so things like the standard UCI do macro | |
6 | ; and the Charniak (et al) let macro are not provided. | |
7 | ; Includes what used to be sprint.l (at the end). | |
8 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
9 | ; Copyright (c) 1983 , The Regents of the University of California. | |
10 | ; All rights reserved. | |
11 | ; Authors: Joseph Faletti and Michael Deering. | |
12 | ||
13 | (eval-when (compile) | |
14 | (declare (special defmacro-for-compiling *savedefs*)) | |
15 | (setq defmacro-for-compiling t) | |
16 | (setq *savedefs* nil)) | |
17 | ||
18 | (declare (macros t)) | |
19 | ||
20 | (defvar poport) | |
21 | (defvar pparm1 50) | |
22 | (defvar pparm2 100) | |
23 | (defvar lpar) | |
24 | (defvar rpar) | |
25 | (defvar form) | |
26 | (defvar linel) | |
27 | (defvar *outport* nil) | |
28 | (defvar *fileopen*) | |
29 | (defvar prettyprops '((comment . pp-comment) | |
30 | (function . pp-function) | |
31 | (value . pp-value))) | |
32 | ||
33 | (declare (localf *patom1)) | |
34 | ||
35 | (defvar *file* nil) | |
36 | (defvar *oldfunctiondefinition*) | |
37 | (defvar *savedefs* t) | |
38 | ||
39 | (defmacro funl (&rest rest) | |
40 | `(function (lambda .,rest))) | |
41 | ||
42 | ; | |
43 | ; ucilisp (de df dm) declare function macros. | |
44 | ; | |
45 | ; (DE name args body) -> declare exprs and lexprs. | |
46 | ; If *savedefs* is t and function has previous definition, | |
47 | ; save it under the property OLDDEF, and return '(name Redefined). | |
48 | ; Otherwise, just do a defun and return name (as with defun). | |
49 | ; | |
50 | (defun de macro (l) | |
51 | (cond (*savedefs* | |
52 | `(progn 'compile | |
53 | (setq *oldfunctiondefinition* (getd ',(cadr l))) | |
54 | (defun .,(cdr l)) | |
55 | (and *file* | |
56 | (putprop ',(cadr l) *file* 'sourcefile)) | |
57 | (cond (*oldfunctiondefinition* | |
58 | (putprop ',(cadr l) *oldfunctiondefinition* 'olddef) | |
59 | (list ',(cadr l) 'Redefined)) | |
60 | ( t ',(cadr l))))) | |
61 | ( t `(defun .,(cdr l))))) | |
62 | ||
63 | ; | |
64 | ; (df name args body) -> declare fexprs. | |
65 | ; | |
66 | (defun df macro (l) | |
67 | (cond (*savedefs* | |
68 | `(progn 'compile | |
69 | (setq *oldfunctiondefinition* (getd ',(cadr l))) | |
70 | (defun ,(cadr l) fexpr .,(cddr l)) | |
71 | (and *file* | |
72 | (putprop ',(cadr l) *file* 'sourcefile)) | |
73 | (cond (*oldfunctiondefinition* | |
74 | (putprop ',(cadr l) *oldfunctiondefinition* 'olddef) | |
75 | (list ',(cadr l) 'Redefined)) | |
76 | ( t ',(cadr l))))) | |
77 | ( t `(defun ,(cadr l) fexpr .,(cddr l))))) | |
78 | ||
79 | ; | |
80 | ; macro's are not compiled except under the same | |
81 | ; conditions as in franz lisp. | |
82 | ; (usually just do (declare (macros t)) | |
83 | ; to have macros also compiled). | |
84 | ; | |
85 | ; | |
86 | ; (dm name args body) -> declare macros. same as (defun name 'macro body) | |
87 | ; | |
88 | (defun dm macro (l) | |
89 | (cond (*savedefs* | |
90 | `(progn 'compile | |
91 | (setq *oldfunctiondefinition* (getd ',(cadr l))) | |
92 | (defun ,(cadr l) macro .,(cddr l)) | |
93 | (and *file* | |
94 | (putprop ',(cadr l) *file* 'sourcefile)) | |
95 | (cond (*oldfunctiondefinition* | |
96 | (putprop ',(cadr l) *oldfunctiondefinition* 'olddef) | |
97 | (list ',(cadr l) 'Redefined)) | |
98 | ( t ',(cadr l))))) | |
99 | ( t `(defun ,(cadr l) macro .,(cddr l))))) | |
100 | ||
101 | ; UCI Lisp character macros are non-separating when occurring in | |
102 | ; the middle of atoms. | |
103 | (eval-when (compile load eval) | |
104 | (add-syntax-class 'vucisplicemacro | |
105 | '(csplicing-macro escape-when-first)) | |
106 | (add-syntax-class 'vucireadmacro | |
107 | '(cmacro escape-when-first))) | |
108 | ||
109 | ; | |
110 | ; ucilisp functions which declare character macros. | |
111 | ; | |
112 | ; | |
113 | ; dsm - declare splicing read macro. | |
114 | ; | |
115 | (defun dsm macro (l) | |
116 | (cond (*savedefs* | |
117 | `(progn 'compile | |
118 | (setq *oldfunctiondefinition* | |
119 | (and (memq (getsyntax ',(cadr l)) | |
120 | '(vucireadmacro vucisplicemacro | |
121 | vsplicing-macro vmacro)) | |
122 | (get ',(cadr l) readtable))) | |
123 | (eval-when (compile load eval) | |
124 | (setsyntax ',(cadr l) 'vucisplicemacro ',(caddr l))) | |
125 | ||
126 | (and *file* | |
127 | (putprop ',(cadr l) *file* 'sourcefile)) | |
128 | (cond (*oldfunctiondefinition* | |
129 | (putprop ',(cadr l) *oldfunctiondefinition* 'oldmacro) | |
130 | (list ',(cadr l) 'Redefined)) | |
131 | ( t ',(cadr l))))) | |
132 | ( t `(eval-when (compile load eval) | |
133 | (setsyntax ',(cadr l) 'vucisplicemacro ',(caddr l)))))) | |
134 | ||
135 | ; | |
136 | ; drm - declare read macro. | |
137 | ; | |
138 | (defun drm macro (l) | |
139 | (cond (*savedefs* | |
140 | `(progn 'compile | |
141 | (setq *oldfunctiondefinition* | |
142 | (and (memq (getsyntax ',(cadr l)) | |
143 | '(vucireadmacro vucisplicemacro | |
144 | vsplicing-macro vmacro)) | |
145 | (get ',(cadr l) readtable))) | |
146 | (eval-when (compile load eval) | |
147 | (setsyntax ',(cadr l) 'vucireadmacro ',(caddr l))) | |
148 | ||
149 | (and *file* | |
150 | (putprop ',(cadr l) *file* 'sourcefile)) | |
151 | (cond (*oldfunctiondefinition* | |
152 | (putprop ',(cadr l) *oldfunctiondefinition* 'oldmacro) | |
153 | (list ',(cadr l) 'Redefined)) | |
154 | ( t ',(cadr l))))) | |
155 | ( t `(eval-when (compile load eval) | |
156 | (setsyntax ',(cadr l) 'vucireadmacro ',(caddr l)))))) | |
157 | ||
158 | ; | |
159 | ; ucilisp selectq function. (written by jkf) | |
160 | ; | |
161 | (defun selectq* macro (form) | |
162 | ((lambda (x) | |
163 | `((lambda (,x) | |
164 | (cond | |
165 | ,@(maplist | |
166 | (function | |
167 | (lambda (ff) | |
168 | (cond ((null (cdr ff)) | |
169 | `( t ,(car ff))) | |
170 | ((atom (caar ff)) | |
171 | `((eq ,x ',(caar ff)) | |
172 | . ,(cdar ff))) | |
173 | (t | |
174 | `((memq ,x ',(caar ff)) | |
175 | . ,(cdar ff)))))) | |
176 | (cddr form)))) | |
177 | ,(cadr form))) | |
178 | (gensym 'z))) | |
179 | ||
180 | (defun some macro (l) | |
181 | `((lambda (f a) | |
182 | (prog () | |
183 | loop | |
184 | (cond ((null a) (return nil)) | |
185 | ((funcall f (car a)) | |
186 | (return a)) | |
187 | ( t (setq a (cdr a)) | |
188 | (go loop))))) | |
189 | ,(cadr l) | |
190 | ,(caddr l))) | |
191 | ||
192 | (defmacro subset (fun lis) | |
193 | `(mapcan (function (lambda (ele) | |
194 | (cond ((funcall ,fun ele) (ncons ele))))) | |
195 | ,lis)) | |
196 | ||
197 | (defun length (l) | |
198 | (prog (n) | |
199 | (setq n 0) | |
200 | loop | |
201 | (and (atom l) | |
202 | (return n)) | |
203 | (setq l (cdr l)) | |
204 | (setq n (1+ n)) | |
205 | (go loop))) | |
206 | ||
207 | (defmacro apply* (fcn args) | |
208 | `(prog (fcndef) | |
209 | (return | |
210 | (cond ((atom ,fcn) | |
211 | (or (and (eq 'binary (type ,fcn)) | |
212 | (setq fcndef ,fcn)) | |
213 | (setq fcndef (getd ,fcn))) | |
214 | (cond ((or (and (eq 'binary (type fcndef)) | |
215 | (eq 'macro (getdisc fcndef))) | |
216 | (and (dtpr fcndef) | |
217 | (eq 'macro (car fcndef)))) | |
218 | (funcall ,fcn (cons ,fcn ,args))) | |
219 | ( t (apply ,fcn ,args)))) | |
220 | ( t (apply ,fcn ,args)))))) | |
221 | ||
222 | (defmacro every (fcn args) | |
223 | `(prog (kkkk) | |
224 | (setq kkkk ,args) | |
225 | loop | |
226 | (cond ((null kkkk) | |
227 | (return t)) | |
228 | ((apply* ,fcn (list (pop kkkk))) | |
229 | (go loop))) | |
230 | (return nil))) | |
231 | ||
232 | (defun timer fexpr (request) | |
233 | (let ((timein (ptime)) timeout result cpu garbage) | |
234 | (prog () | |
235 | loop | |
236 | (setq result (eval (car request))) | |
237 | (and (setq request (cdr request)) | |
238 | (go loop))) | |
239 | (setq timeout (ptime)) | |
240 | (setq cpu (quotient (fix (times 1000 | |
241 | (quotient (difference (car timeout) | |
242 | (car timein)) | |
243 | 60.0))) | |
244 | 1000.0)) | |
245 | (setq garbage (quotient (fix (times 1000 | |
246 | (quotient (difference (cadr timeout) | |
247 | (cadr timein)) | |
248 | 60.0))) | |
249 | 1000.0)) | |
250 | (print (cons cpu garbage)) | |
251 | (terpri) | |
252 | result)) | |
253 | ||
254 | (putd 'consp (getd 'dtpr)) | |
255 | ||
256 | (putd 'msgprintfn (getd 'patom)) | |
257 | ||
258 | ; | |
259 | ; ucilisp msg function. (written by jkf) | |
260 | ; | |
261 | (defmacro msg ( &rest body) | |
262 | `(progn ,@(mapcar | |
263 | (function | |
264 | (lambda (form) | |
265 | (cond ((eq form t) '(line-feed 1)) | |
266 | ((numberp form) | |
267 | (cond ((>& form 0) | |
268 | `(msg-space ,form)) | |
269 | ( t `(line-feed ,(minus form))))) | |
270 | ((atom form) `(msgprintfn ,form)) | |
271 | ((eq (car form) t) '(msgprintfn '\ )) | |
272 | ((eq (car form) 'e) | |
273 | `(msgprintfn ,(cadr form))) | |
274 | ( t `(msgprintfn ,form))))) | |
275 | body) | |
276 | nil)) ; return nil! | |
277 | ||
278 | ; | |
279 | ; this NEED NOT be fixed to not use do. | |
280 | ; | |
281 | (defmacro msg-space (n) | |
282 | (cond ((eq 1 n) '(patom '" ")) | |
283 | ( t `(do i ,n (1- i) (<& i 1) (patom '\ ))))) | |
284 | ||
285 | (defmacro line-feed (n) | |
286 | (cond ((eq 1 n) '(terpr)) | |
287 | ( t `(do i ,n (1- i) (<& i 1) (terpr))))) | |
288 | ||
289 | ; compatability functions: functions required by uci lisp but not | |
290 | ; present in franz | |
291 | ; | |
292 | ; union uses the franz do loop (not the ucilisp one). | |
293 | ||
294 | (defvar membfn 'member) | |
295 | ||
296 | (defun union n | |
297 | (and (> n 0) | |
298 | (do ((res (ncons nil)) | |
299 | (i 1 (1+ i))) | |
300 | ((eq i (1+ n)) (car res)) | |
301 | (mapc (function | |
302 | (lambda (arg) | |
303 | (or (apply* membfn (list arg (car res))) | |
304 | (tconc res arg)))) | |
305 | (arg i))))) | |
306 | ||
307 | (defun enter (v l) | |
308 | (cond ((apply* membfn (list v l)) l) | |
309 | ( t (cons v l)))) | |
310 | ||
311 | (defun append2 (a b &aux (c (ncons nil))) | |
312 | (do ((a a (cdr a))) | |
313 | ((null a)) | |
314 | (tconc c (car a))) | |
315 | (rplacd (cdr c) b) | |
316 | (car c)) | |
317 | ||
318 | (putd 'noduples (getd 'union)) | |
319 | (putd 'append* (getd 'append)) | |
320 | (putd '*append (getd 'append)) | |
321 | (putd '*dif (getd 'diff)) | |
322 | (putd '*eval (getd 'eval)) | |
323 | (putd '*great (getd 'greaterp)) | |
324 | (putd '*less (getd 'lessp)) | |
325 | (putd '*max (getd 'max)) | |
326 | (putd '*nconc (getd 'nconc)) | |
327 | (putd '*plus (getd 'plus)) | |
328 | (putd '*times (getd 'times)) | |
329 | (putd 'expandmacro (getd 'macroexpand)) | |
330 | (putd 'mapcl (getd 'mapcar)) | |
331 | (putd 'memb (getd 'member)) | |
332 | ||
333 | (dm clrbfi () | |
334 | '(drain piport)) | |
335 | ||
336 | (defun save fexpr (l) | |
337 | (let ((fcnname (car l))) | |
338 | (putprop fcnname (getd fcnname) 'olddef))) | |
339 | ||
340 | (defun unsave fexpr (l) | |
341 | (let* ((name (car l)) | |
342 | (old (get name 'olddef))) | |
343 | (and old | |
344 | (putprop name (getd name) 'olddef) | |
345 | (putd name old)) | |
346 | old)) | |
347 | ||
348 | (putd 'atcat (getd 'concat)) | |
349 | ||
350 | (putd 'gt (getd '>)) | |
351 | (putd 'lt (getd '<)) | |
352 | ||
353 | (defun le macro (x) | |
354 | `(not (> .,(cdr x)))) | |
355 | ||
356 | (defun ge macro (x) | |
357 | `(not (< .,(cdr x)))) | |
358 | ||
359 | (defun litatom macro (x) | |
360 | `(and (atom .,(cdr x)) | |
361 | (not (numberp .,(cdr x))))) | |
362 | ||
363 | (putd 'peekc (getd 'tyipeek)) | |
364 | ||
365 | ; | |
366 | ; unbound - (setq x (unbound)) will unbind x. | |
367 | ; "this [code] is sick" - jkf. | |
368 | ; | |
369 | (defun unbound macro (l) | |
370 | `(fake -4)) | |
371 | ||
372 | (or (getd 'franzboundp) | |
373 | (putd 'franzboundp (getd 'boundp))) | |
374 | ||
375 | (defun boundp (item) | |
376 | (cond ((arrayp item)) | |
377 | ((franzboundp item)))) | |
378 | ||
379 | (defvar *dskin* t) | |
380 | (defvar piport) | |
381 | ||
382 | ;(eval-when (load eval compile) | |
383 | ; (or (boundp '*dskin*) | |
384 | ; (setq *dskin* t))) | |
385 | ||
386 | (eval-when (load eval) | |
387 | (or (getd 'dskprintfn) | |
388 | (putd 'dskprintfn (getd 'patom)))) | |
389 | ||
390 | (defun dskin fexpr (l) | |
391 | (mapc 'dskin1 l) | |
392 | (terpri) t ) | |
393 | ||
394 | (defun dskin1 (*file*) | |
395 | (prog (port) | |
396 | (terpri) | |
397 | (patom '|>>>|) | |
398 | (cond ((null (setq port (car (errset (infile *file*) nil)))) | |
399 | (patom '|couldn't open file |) | |
400 | (patom *file*)) | |
401 | ( t (patom *file*) | |
402 | (patom '| |) | |
403 | (dskin2 port) | |
404 | (close port))))) | |
405 | ||
406 | (defun dskin2 (port) | |
407 | (prog (expr value) | |
408 | loop | |
409 | (cond ((null (setq expr (read port))) nil) | |
410 | ( t (cond ((memq (car expr) '(de df defmacro dm drm | |
411 | dsm setq def defun)) | |
412 | (cond ((memq *dskin* '(name both)) | |
413 | (patom (cadr expr)) | |
414 | (patom '|: |)))) | |
415 | ((eq (car expr) 'create) | |
416 | (cond ((memq *dskin* '(name both)) | |
417 | (patom (caddr expr)) | |
418 | (patom '|: |))))) | |
419 | (setq value (eval expr)) | |
420 | (and (memq *dskin* '(t both)) | |
421 | (or (eq value '*invisible*) | |
422 | (progn (dskprintfn value) | |
423 | (patom '| |)))) | |
424 | (go loop))))) | |
425 | ||
426 | (defun nequal (arg1 arg2) | |
427 | (not (equal arg1 arg2))) | |
428 | ||
429 | (defun readl fexpr (l) | |
430 | (cond ((null l) (readl1 nil)) | |
431 | ( t (readl1 (eval (car l)))))) | |
432 | ||
433 | (putd 'lineread (getd 'readl)) | |
434 | ||
435 | (defun readl1 (flag) | |
436 | (cond ((not (and flag | |
437 | (eq (tyipeek) 10) | |
438 | (tyi))) | |
439 | (prog (input) | |
440 | (setq input (ncons nil)) ; initialize for tconc. | |
441 | loop | |
442 | (cond ((not (eq (tyipeek) 10)) | |
443 | (tconc input (read)) | |
444 | (go loop)) | |
445 | ( t ; the actual list is in the CAR. | |
446 | (tyi) | |
447 | (return (car input)))))))) | |
448 | ||
449 | (defun defv fexpr (l) | |
450 | (set (car l) (cadr l))) | |
451 | ||
452 | (defun remprops (item proplist) | |
453 | (mapc (funl (prop) | |
454 | (remprop item prop)) | |
455 | proplist) | |
456 | nil) | |
457 | ||
458 | (defun addprop (id value prop) | |
459 | (putprop id (enter value (get id prop)) prop)) | |
460 | ||
461 | (defun nconc1 (l elmt) | |
462 | (rplacd (last l) (cons elmt nil))) | |
463 | ||
464 | (defun dremove (elmt l) | |
465 | (let (newl) | |
466 | (cond ((dtpr l) | |
467 | (cond ((eq elmt (car l)) | |
468 | (setq newl (delq elmt l)) | |
469 | (rplaca l (car newl)) | |
470 | (rplacd l (cdr newl))) | |
471 | ( t (delq elmt l)))) | |
472 | ( t l)))) | |
473 | ||
474 | (defun intersection (set1 set2) | |
475 | (prog (inter) | |
476 | (mapc (funl (elt) (putprop elt t '*inter*)) set1) | |
477 | (mapc (funl (elt) (and (get elt '*inter*) | |
478 | (setq inter (cons elt inter)))) | |
479 | set2) | |
480 | (mapc (funl (elt) (remprop elt '*inter*)) set1) | |
481 | (return inter))) | |
482 | ||
483 | (defun initsym1 expr (l) | |
484 | (prog (num) | |
485 | (cond ((dtpr l) | |
486 | (setq num (cadr l)) | |
487 | (setq l (car l))) | |
488 | ( t (setq num 0))) | |
489 | (putprop l num 'symctr) | |
490 | (return (concat l num)))) | |
491 | ||
492 | (defun initsym fexpr (l) | |
493 | (mapcar (function initsym1) l)) | |
494 | ||
495 | (defun newsym fexpr (l) | |
496 | (let ((name (car l))) | |
497 | (concat name | |
498 | (putprop name | |
499 | (1+ (or (get name 'symctr) | |
500 | -1)) | |
501 | 'symctr)))) | |
502 | ||
503 | (defun oldsym fexpr (l) | |
504 | (let ((sym (car l))) | |
505 | (concat sym (get sym 'symctr)))) | |
506 | ||
507 | (defun allsym fexpr (l) | |
508 | (prog (num symctr syms) | |
509 | (cond ((dtpr (car l)) | |
510 | (setq num (cadar l)) | |
511 | (setq l (caar l))) | |
512 | ( t (setq num 0) | |
513 | (setq l (car l)))) | |
514 | (or (setq symctr (get l 'symctr)) | |
515 | (return)) | |
516 | loop | |
517 | (and (>& num symctr) | |
518 | (return syms)) | |
519 | (setq syms (cons (concat l symctr) syms)) | |
520 | (setq symctr (1- symctr)) | |
521 | (go loop))) | |
522 | ||
523 | (defun remsym1 expr (l) | |
524 | (prog1 (funcall (function oldsym) | |
525 | (cond ((dtpr (car l)) (car l)) | |
526 | ( t l))) | |
527 | (mapc (function remob) (apply (function allsym) l)) | |
528 | (cond ((dtpr (car l)) (putprop (caar l) (1- (cadar l)) 'symctr)) | |
529 | ( t (remprop (car l) 'symctr))))) | |
530 | ||
531 | (defun remsym fexpr (l) | |
532 | (maplist (function remsym1) l)) | |
533 | ||
534 | (defun symstat fexpr (l) | |
535 | (mapcar (funl (k) | |
536 | (list k (get k 'symctr))) | |
537 | l)) | |
538 | ||
539 | (defun suflist (itemlist num) | |
540 | (cond ((dtpr itemlist) (nth (1+ num) itemlist)))) | |
541 | ||
542 | ;;;;;;;;;;;;;;;;;;;;;;; (formerly sprint.l) ;;;;;;;;;;;;;;;;;;;;;;;; | |
543 | ; A few additions to the library file ucbpp.l, mostly to add | |
544 | ; a UCI Lisp-like "sprint" including some modifications for | |
545 | ; more flexible printmacros. | |
546 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
547 | ||
548 | ; Moved to front and converted to defvar. | |
549 | ; (declare (special poport pparm1 pparm2 lpar rpar form linel)) | |
550 | ; (declare (localf *patom1)) | |
551 | ; (declare (special *outport* *fileopen* prettyprops)) | |
552 | ||
553 | ; ======================================= | |
554 | ; pretty printer top level routine pp | |
555 | ; | |
556 | ; | |
557 | ; calling form- (pp arg1 arg2 ... argn) | |
558 | ; the args may be names of functions, atoms with associated values | |
559 | ; or output descriptors. | |
560 | ; if argi is: | |
561 | ; an atom - it is assumed to be a function name, if there is no | |
562 | ; function property associated with it,then it is assumed | |
563 | ; to be an atom with a value | |
564 | ; (P port)- port is the output port where the results of the | |
565 | ; pretty printing will be sent. | |
566 | ; poport is the default if no (P port) is given. | |
567 | ; (F fname)- fname is a file name to write the results in | |
568 | ; (A atmname) - means, treat this as an atom with a value, dont | |
569 | ; check if it is the name of a function. | |
570 | ; (E exp)- evaluate exp without printing anything | |
571 | ; other - pretty-print the expression as is - no longer an error | |
572 | ; | |
573 | ; Also, rather than printing only a function defn or only a value, we will | |
574 | ; let prettyprops decide which props to print. Finally, prettyprops will | |
575 | ; follow the CMULisp format where each element is either a property | |
576 | ; or a dotted pair of the form (prop . fn) where in order to print the | |
577 | ; given property we call (fn id val prop). The special properties | |
578 | ; function and value are used to denote those "properties" which | |
579 | ; do not actually appear on the plist. | |
580 | ; | |
581 | ; [history of this code: originally came from Harvard Lisp, hacked to | |
582 | ; work under franz at ucb, hacked to work at cmu and finally rehacked | |
583 | ; to work without special cmu macros] | |
584 | ; THEN, hacked to use for PEARL. | |
585 | ||
586 | ; moved to front. | |
587 | ;(setq prettyprops '((comment . pp-comment) | |
588 | ; (function . pp-function) | |
589 | ; (value . pp-value))) | |
590 | ||
591 | ; printret is like print yet it returns the value printed, this is used | |
592 | ; by pp | |
593 | (def printret | |
594 | (macro (*l*) | |
595 | `(progn (print ,@(cdr *l*)) ,(cadr *l*)))) | |
596 | ||
597 | (def pp | |
598 | (nlambda (*xlist*) | |
599 | (prog (*outport* *cur* *fileopen* *prl* *atm*) | |
600 | ||
601 | (setq *outport* poport) ; default port | |
602 | ; check if more to do, if not close output file if it is | |
603 | ; open and leave | |
604 | ||
605 | ||
606 | toploop (cond ((null (setq *cur* (car *xlist*))) | |
607 | (condclosefile) | |
608 | (terpr) | |
609 | (return t))) | |
610 | ||
611 | (cond ((dtpr *cur*) | |
612 | (cond ((equal 'P (car *cur*)) ; specifying a port | |
613 | (condclosefile) ; close file if open | |
614 | (setq *outport* (eval (cadr *cur*)))) | |
615 | ||
616 | ((equal 'F (car *cur*)) ; specifying a file | |
617 | (condclosefile) ; close file if open | |
618 | (setq *outport* (outfile (cadr *cur*)) | |
619 | *fileopen* t)) | |
620 | ||
621 | ||
622 | ((equal 'E (car *cur*)) | |
623 | (eval (cadr *cur*))) | |
624 | ||
625 | ( t (terpri *outport*) | |
626 | (*prpr *cur*))) ;-DNC inserted | |
627 | (go botloop))) | |
628 | ||
629 | ||
630 | (mapc (function | |
631 | (lambda (prop) | |
632 | (prog (printer) | |
633 | (cond ((dtpr prop) | |
634 | (setq printer (cdr prop)) | |
635 | (setq prop (car prop))) | |
636 | ( t (setq printer 'pp-prop))) | |
637 | (cond ((eq 'value prop) | |
638 | (cond ((boundp *cur*) | |
639 | (apply printer | |
640 | (list *cur* | |
641 | (eval *cur*) | |
642 | 'value))))) | |
643 | ((eq 'function prop) | |
644 | (cond ((and (getd *cur*) | |
645 | (not (bcdp (getd *cur*)))) | |
646 | (apply printer | |
647 | (list *cur* | |
648 | (getd *cur*) | |
649 | 'function))))) | |
650 | ((get *cur* prop) | |
651 | (apply printer | |
652 | (list *cur* | |
653 | (get *cur* prop) | |
654 | prop))))))) | |
655 | prettyprops) | |
656 | ||
657 | ||
658 | botloop (setq *xlist* (cdr *xlist*)) | |
659 | ||
660 | (go toploop)))) | |
661 | ||
662 | ; moved to front. | |
663 | ;(setq pparm1 50 pparm2 100) | |
664 | ||
665 | ; -DNC These "prettyprinter parameters" are used to decide when we should | |
666 | ; quit printing down the right margin and move back to the left - | |
667 | ; Do it when the leftmargin > pparm1 and there are more than pparm2 | |
668 | ; more chars to print in the expression | |
669 | ||
670 | ; cmu prefers dv instead of setq | |
671 | ||
672 | #+cmu | |
673 | (def pp-value (lambda (i v p) | |
674 | (terpri *outport*) (*prpr (list 'dv i v)))) | |
675 | ||
676 | #-cmu | |
677 | (def pp-value (lambda (i v p) | |
678 | (terpr *outport*) (*prpr `(setq ,i ',v)))) | |
679 | (def pp-function (lambda (i v p) | |
680 | (terpri *outport*) (*prpr (list 'def i v)))) | |
681 | (def pp-prop (lambda (i v p) | |
682 | (terpri *outport*) (*prpr (list 'defprop i v p)))) | |
683 | ||
684 | (def condclosefile | |
685 | (lambda nil | |
686 | (cond (*fileopen* | |
687 | (terpr *outport*) | |
688 | (close *outport*) | |
689 | (setq *fileopen* nil))))) | |
690 | ||
691 | ; | |
692 | ; these routines are meant to be used by pp but since | |
693 | ; some people insist on using them we will set *outport* to nil | |
694 | ; as the default (moved to front). | |
695 | ;(setq *outport* nil) | |
696 | ||
697 | ||
698 | (def *prpr | |
699 | (lambda (x) | |
700 | (cond ((not (boundp '*outport*)) (setq *outport* poport))) | |
701 | (terpr *outport*) | |
702 | (*prdf x 0 0))) | |
703 | ||
704 | ; This is the principle addition for PEARL. | |
705 | ; SPRINT simply calls *prdf after filling in any missing parameters. | |
706 | (defun sprint (value &optional (lmar 0) (rmar 0)) | |
707 | (cond ((not (boundp '*outport*)) (setq *outport* poport))) | |
708 | (*prdf value lmar rmar)) | |
709 | ||
710 | (defvar rmar) ; -DNC this used to be m - I've tried to | |
711 | ; to fix up the pretty printer a bit. It | |
712 | ; used to mess up regularly on (a b .c) types | |
713 | ; of lists. Also printmacros have been added. | |
714 | ||
715 | ||
716 | ||
717 | ; Used to be $prdf but added a bit and changed to * to avoid | |
718 | ; PEARL's history read macro $. | |
719 | (def *prdf | |
720 | (lambda (l lmar rmar) | |
721 | (prog (pmac) | |
722 | ; | |
723 | ; - DNC - Here we try to fix the tendency to print a | |
724 | ; thin column down the right margin by allowing it | |
725 | ; to move back to the left if necessary. | |
726 | ; | |
727 | (cond ((and (>& lmar pparm1) (>& (flatc l (1+ pparm2)) pparm2)) | |
728 | (terpri *outport*) | |
729 | (princ '"; <<<<< start back on the left <<<<<" *outport*) | |
730 | (*prdf l 5 0) | |
731 | (terpri *outport*) | |
732 | (princ '"; >>>>> continue on the right >>>>>" *outport*) | |
733 | (terpri *outport*) | |
734 | (return nil))) | |
735 | (tab lmar *outport*) | |
736 | a (cond ((and (dtpr l) | |
737 | (atom (car l)) | |
738 | (setq pmac (get (car l) 'printmacro)) | |
739 | (cond ((stringp pmac) | |
740 | ; Added for PEARL (and UCI Lisp compatibility). | |
741 | ; a string printmacro means print this | |
742 | ; string and then the cadr of l if | |
743 | ; it's not nil, and only if l is | |
744 | ; a one- or two-element list. | |
745 | (cond ((cddr l) ; more than two elements. | |
746 | nil) | |
747 | ((null (cdr l)) ; only one element. | |
748 | (patom pmac) | |
749 | t) | |
750 | ( t (patom pmac) ; two elements. | |
751 | (patom (cadr l)) | |
752 | t))) | |
753 | ( t (apply pmac (list l lmar rmar))))) | |
754 | (return nil)) | |
755 | ; | |
756 | ; -DNC - a printmacro is a lambda (l lmar rmar) | |
757 | ; attached to the atom. If it returns nil then | |
758 | ; we assume it did not apply and we continue. | |
759 | ; Otherwise we assume it did the job. | |
760 | ; | |
761 | ((or (not (dtpr l)) | |
762 | ; (*** at the moment we just punt hunks etc) | |
763 | (and (atom (car l)) (atom (cdr l)))) | |
764 | (return (printret l *outport*))) | |
765 | ((<& (+ rmar (flatc l (chrct *outport*))) | |
766 | (chrct *outport*)) | |
767 | ; | |
768 | ; This is just a heuristic - if print can fit it in then figure that | |
769 | ; the printmacros won't hurt. Note that despite the pretentions there | |
770 | ; is no guarantee that everything will fit in before rmar - for example | |
771 | ; atoms (and now even hunks) are just blindly printed. - DNC | |
772 | ; | |
773 | (printaccross l lmar rmar)) | |
774 | ((and (*patom1 lpar) | |
775 | (atom (car l)) | |
776 | (not (atom (cdr l))) | |
777 | (not (atom (cddr l)))) | |
778 | (prog (c) | |
779 | (printret (car l) *outport*) | |
780 | (*patom1 '" ") | |
781 | (setq c (nwritn *outport*)) | |
782 | a (*prd1 (cdr l) c) | |
783 | (cond | |
784 | ((not (atom (cdr (setq l (cdr l))))) | |
785 | (terpr *outport*) | |
786 | (go a))))) | |
787 | (t | |
788 | (prog (c) | |
789 | (setq c (nwritn *outport*)) | |
790 | a (*prd1 l c) | |
791 | (cond | |
792 | ((not (atom (setq l (cdr l)))) | |
793 | (terpr *outport*) | |
794 | (go a)))))) | |
795 | b (*patom1 rpar)))) | |
796 | ||
797 | (def *prd1 | |
798 | (lambda (l n) | |
799 | (prog nil | |
800 | (*prdf (car l) | |
801 | n | |
802 | (cond ((null (setq l (cdr l))) (|1+| rmar)) | |
803 | ((atom l) (setq n nil) (+ 4 rmar (pntlen l))) | |
804 | ( t rmar))) | |
805 | (cond | |
806 | ((null n) (*patom1 '" . ") (return (printret l *outport*)))) | |
807 | ; (*** setting n is pretty disgusting) | |
808 | ; (*** the last arg to *prdf is the space needed for the suffix) | |
809 | ; ;Note that this is still not really right - if the prefix | |
810 | ; takes several lines one would like to use the old rmar | |
811 | ;( until the last line where the " . mumble)" goes. | |
812 | ))) | |
813 | ||
814 | ; -DNC here's the printmacro for progs - it replaces some hackery that | |
815 | ; used to be in the guts of *prdf. | |
816 | ||
817 | (def printprog | |
818 | (lambda (l lmar rmar) | |
819 | (prog (col) | |
820 | (cond ((cdr (last l)) (return nil))) | |
821 | (setq col (1+ lmar)) | |
822 | (princ '|(| *outport*) | |
823 | (princ (car l) *outport*) | |
824 | (princ '| | *outport*) | |
825 | (print (cadr l) *outport*) | |
826 | (mapc '(lambda (x) | |
827 | (cond ((atom x) | |
828 | (tab col *outport*) | |
829 | (print x *outport*)) | |
830 | ( t (*prdf x (+ lmar 6) rmar)))) | |
831 | (cddr l)) | |
832 | (princ '|)| *outport*) | |
833 | (return t)))) | |
834 | ||
835 | (putprop 'prog 'printprog 'printmacro) | |
836 | ||
837 | ; Here's the printmacro for def. The original *prdf had some special code | |
838 | ; for lambda and nlambda. | |
839 | ||
840 | (def printdef | |
841 | (lambda (l lmar rmar) | |
842 | (cond ((and (\=& 0 lmar) ; only if we're really printing a defn | |
843 | (\=& 0 rmar) | |
844 | (cadr l) | |
845 | (atom (cadr l)) | |
846 | (caddr l) | |
847 | (null (cdddr l)) | |
848 | (memq (caaddr l) '(lambda nlambda macro lexpr)) | |
849 | (null (cdr (last (caddr l))))) | |
850 | (princ '|(| *outport*) | |
851 | (princ 'def *outport*) | |
852 | (princ '| | *outport*) | |
853 | (princ (cadr l) *outport*) | |
854 | (terpri *outport*) | |
855 | (princ '| (| *outport*) | |
856 | (princ (caaddr l) *outport*) | |
857 | (princ '| | *outport*) | |
858 | (princ (cadaddr l) *outport*) | |
859 | (terpri *outport*) | |
860 | (mapc '(lambda (x) (*prdf x 4 0)) (cddaddr l)) | |
861 | (princ '|))| *outport*) | |
862 | t)))) | |
863 | ||
864 | (putprop 'def 'printdef 'printmacro) | |
865 | ||
866 | ; There's a version of this hacked into the printer (where it don't belong!) | |
867 | ; Note that it must NOT apply to things like (quote a b). | |
868 | ||
869 | (def printquote | |
870 | (lambda (l lmar rmar) | |
871 | (cond ((or (null (cdr l)) (cddr l)) nil) | |
872 | ( t (princ '|'| *outport*) | |
873 | (*prdf (cadr l) (1+ lmar) rmar) | |
874 | t)))) | |
875 | ||
876 | (putprop 'quote 'printquote 'printmacro) | |
877 | ||
878 | ||
879 | ||
880 | ||
881 | (def printaccross | |
882 | (lambda (l lmar rmar) | |
883 | (prog nil | |
884 | ; (*** this is needed to make sure the printmacros are executed) | |
885 | (princ '|(| *outport*) ;) | |
886 | l: (cond ((null l)) | |
887 | ((atom l) (princ '|. | *outport*) (princ l *outport*)) | |
888 | ( t (*prdf (car l) (nwritn *outport*) rmar) | |
889 | (setq l (cdr l)) | |
890 | (cond (l (princ '| | *outport*))) | |
891 | (go l:)))))) | |
892 | ||
893 | ||
894 | ||
895 | (def tab (lexpr (n) | |
896 | (prog (nn prt) (setq nn (arg 1)) | |
897 | (cond ((>& n 1) (setq prt (arg 2)))) | |
898 | (cond ((>& (nwritn prt) nn) (terpri prt))) | |
899 | (printblanks (- nn (nwritn prt)) prt)))) | |
900 | ||
901 | ; ======================================== | |
902 | ; | |
903 | ; (charcnt port) | |
904 | ; returns the number of characters left on the current line | |
905 | ; on the given port | |
906 | ; | |
907 | ; ======================================= | |
908 | ||
909 | ||
910 | (def charcnt | |
911 | (lambda (port) (- linel (nwritn port)))) | |
912 | ||
913 | (putd 'chrct (getd 'charcnt)) | |
914 | ||
915 | (def *patom1 (lambda (x) (patom x *outport*))) | |
916 | ||
917 | ; vi: set lisp: |