|
|
1.1 root 1:
2:
3: ; l i s z t v 4
4:
5:
6:
7:
8: ; Copyright (c) 1980 , The Regents of the University of California.
9: ; All rights reserved.
10: ; author: j. foderaro
11:
12: ; Section EXPR -- general expression compiler
13:
14: (include "caspecs.l")
15:
16: (eval-when (compile eval)
17: (cond ((not (getd 'If))
18: (fasl 'camacs))))
19:
20: (setq sectioncadrid "@(#)cadr.l 5.4 10/22/80") ; id for SCCS
21:
22: ;--- d-exp :: compile a lisp expression = d-exp =
23: ; v-form : a lisp expression to compile
24: ; returns an IADR which tells where the value was located.
25: ;
26: (defun d-exp (v-form)
27: (prog (first resloc tmp ftyp)
28:
29: begin
30: (If (atom v-form)
31: then (setq tmp (d-loc v-form)) ;locate vrble
32: (If (null g-loc)
33: then (If g-cc then (d-tst tmp))
34: else (d-move tmp g-loc))
35: (d-handlecc)
36: (return tmp)
37:
38: elseif (atom (setq first (car v-form)))
39: then (If (and fl-xref (not (get first g-refseen)))
40: then (Push g-reflst first)
41: (putprop first t g-refseen))
42: (setq ftyp (d-functyp first))
43: (If (eq 'macro ftyp)
44: then (setq v-form (apply first v-form))
45: (go begin)
46: elseif (setq tmp (get first 'fl-exprcc))
47: then (return (funcall tmp))
48: elseif (setq tmp (get first 'fl-exprm))
49: then (setq v-form (funcall tmp))
50: (go begin)
51: elseif (setq tmp (get first 'fl-expr))
52: then (funcall tmp)
53: elseif (setq tmp (or (and (eq 'car first)
54: '( a ))
55: (and (eq 'cdr first)
56: '( d ))
57: (d-cxxr first)))
58: then (return (cc-cxxr (cadr v-form) tmp))
59: elseif (eq 'nlambda ftyp)
60: then (d-callbig first `(',(cdr v-form)))
61: elseif (or (eq 'lambda ftyp) (eq 'lexpr ftyp))
62: then (setq tmp (length v-form))
63:
64: (d-callbig first (cdr v-form)))
65: elseif (eq 'lambda (car first))
66: then (c-lambexp)
67:
68: elseif (or (eq 'quote (car first)) (eq 'function (car first)))
69: then (comp-warn "bizzare function name " (or first))
70: (setq v-form (cons (cadr first) (cdr v-form)))
71: (go begin)
72:
73: else (comp-err "bad expression" (or v-form)))
74:
75: (If (null g-loc)
76: then (If g-cc then (d-tst 'reg))
77: elseif (eq g-loc 'reg)
78: then (If g-cc then (d-tst 'reg))
79: else (d-move 'reg g-loc))
80: (If g-cc then (d-handlecc))))
81:
82: ;--- d-functyp :: return the type of function
83: ; - name : function name
84: ;
85: (defun d-functyp (name)
86: (let (ftyp )
87: (If (atom name) then
88: (If (setq ftyp (getd name))
89: then (If (bcdp ftyp)
90: then (getdisc ftyp)
91: elseif (dtpr ftyp)
92: then (car ftyp))
93: elseif (get name g-functype) thenret
94: else 'lambda)))) ; default is lambda
95:
96:
97: ;--- d-exps :: compile a list of expressions
98: ; - exps : list of expressions
99: ; the last expression is evaluated according to g-loc and g-cc, the others
100: ; are evaluated with g-loc and g-cc nil.
101: ;
102: (defun d-exps (exps)
103: (d-exp (do ((ll exps (cdr ll))
104: (g-loc nil)
105: (g-cc nil)
106: (g-ret nil))
107: ((null (cdr ll)) (car ll))
108: (d-exp (car ll)))))
109:
110:
111: ;--- d-pushargs :: compile and push a list of expressions
112: ; - exps : list of expressions
113: ; compiles and stacks a list of expressions
114: ;
115: (defun d-pushargs (args)
116: (If args then (do ((ll args (cdr ll))
117: (g-loc 'stack)
118: (g-cc nil)
119: (g-ret nil))
120: ((null ll))
121: (d-exp (car ll))
122: (Push g-locs nil)
123: (incr g-loccnt))))
124:
125: ;--- d-cxxr :: split apart a cxxr function name
126: ; - name : a possible cxxr function name
127: ; returns the a's and d's between c and r in reverse order, or else
128: ; returns nil if this is not a cxxr name
129: ;
130: (defun d-cxxr (name)
131: (let ((expl (explodec name)))
132: (If (eq 'c (car expl)) ; must begin with c
133: then (do ((ll (cdr expl) (cdr ll))
134: (tmp)
135: (res))
136: (nil)
137: (setq tmp (car ll))
138: (If (null (cdr ll))
139: then (If (eq 'r tmp) ; must end in r
140: then (return res)
141: else (return nil))
142: elseif (or (eq 'a tmp) ; and contain only a's and d's
143: (eq 'd tmp))
144: then (setq res (cons tmp res))
145: else (return nil))))))
146:
147: ;--- d-call :: call another function
148: ; - name : name of funtion to call
149: ; - nargs : number of args stacked (including the function name)
150: ;
151: (defun d-call (name nargs)
152: (prog (tmp)
153: (forcecomment `(calling ,name))
154: (If (null (setq tmp (cdr (assoc nargs
155: '( (1 . (* -8 #.bind-reg))
156: (2 . (* -12 #.bind-reg))
157: (3 . (* -16 #.bind-reg))
158: (4 . (* -20 #.bind-reg))
159: (5 . (* -24 #.bind-reg)))))))
160: then ; lbot will not be set up automatically
161: (e-write3 'movab ; must set up lbot
162: `(,(* -4 nargs) #.Np-reg)
163: '#.Lbot-reg)
164: (setq tmp '(* -28 #.bind-reg)))
165: (e-write2 'jsb tmp)))
166:
167: ;--- d-callbig :: call a local or global function
168: ;
169: ;
170: (defun d-callbig (name args)
171: (let ((tmp (get name g-localf))
172: c)
173: (forcecomment `(calling ,name))
174: (If (d-dotailrecursion name args) thenret
175: elseif tmp then ;-- local function call
176: (d-pushargs args)
177: (e-write2 'jsb (car tmp))
178: (setq g-locs (nthcdr (setq c (length args)) g-locs))
179: (setq g-loccnt (- g-loccnt c))
180: else (If fl-tran ;-- transfer table linkage
181: then (d-pushargs args)
182: (setq c (length args))
183: (d-calltran name c)
184: else ;--- standard function call
185: (d-pushargs `(',name ,@args))
186: (d-call name (setq c (1+ (length args)))))
187: (setq g-locs (nthcdr c g-locs))
188: (setq g-loccnt (- g-loccnt c)))
189: (d-clearreg)))
190:
191:
192: ;--- d-calltran :: call a function through the transfer table = d-calltran =
193: ; name - name of function to call
194: ; c - number of arguments to the function
195: ;
196: (defun d-calltran (name c)
197: (e-write3 'movab `(,(* -4 c) #.Np-reg) '#.Lbot-reg)
198: (e-write3 'calls '$0 (concat "*trantb+" (d-tranloc name)))
199: (e-write3 'movl '#.Lbot-reg '#.Np-reg))
200:
201: ;--- d-tranloc :: locate a function in the transfer table = d-tranloc =
202: ;
203: ; return the offset we should use for this function call
204: ;
205: (defun d-tranloc (fname)
206: (cond ((get fname g-tranloc))
207: (t (Push g-tran fname)
208: (let ((newval (* 8 g-trancnt)))
209: (putprop fname newval g-tranloc)
210: (incr g-trancnt)
211: newval))))
212:
213: ;--- d-dotailrecursion :: do tail recursion if possible
214: ; name - function name we are to call
215: ; args - arguments to give to function
216: ;
217: ; return t iff we were able to do tail recursion
218: ; We can do tail recursion if:
219: ; g-ret is set indicating that the result of this call will be returned
220: ; as the value of the function we are compiling
221: ; the function we are calling, name, is the same as the function we are
222: ; compiling, g-fname
223: ; there are no variables shallow bound, since we would have to unbind
224: ; them, which may cause problems in the function.
225: ;
226: (defun d-dotailrecursion (name args)
227: (If (and g-ret
228: (eq name g-fname)
229: (do ((loccnt 0)
230: (ll g-locs (cdr ll)))
231: ((null ll) (return t))
232: (If (dtpr (car ll))
233: then (If (or (eq 'catcherrset (caar ll))
234: (greaterp (cdar ll) 0))
235: then (return nil))
236: else (incr loccnt))))
237: then
238: ; evalate the arguments and pop them back to the location of
239: ; the original args.
240: (makecomment '(tail merging))
241: (comp-note "Tail merging being done: " v-form)
242: (let ((g-locs g-locs)
243: (g-loccnt g-loccnt))
244: (d-pushargs args)) ; push then forget about
245: (let (base-reg nargs)
246: (If (eq g-ftype 'lexpr)
247: then ; the beginning of the local variables
248: ;has been stacked
249: (e-write3 'addl2 '$4 'sp) ; pop off arg count
250: (e-write4 'addl3 '$4 "(sp)" Lbot-reg)
251: (setq base-reg Lbot-reg) ; will push from bot
252: else (setq base-reg oLbot-reg)) ; will push from olbot
253: (setq nargs (length args))
254: (do ((i nargs (1- i))
255: (top (* nargs -4) (+ top 4))
256: (bot 0 (+ bot 4)))
257: ((zerop i))
258: (e-write3 'movl `(,top ,Np-reg) `(,bot ,base-reg)))
259: (e-write3 'movab `(,(* 4 nargs) ,base-reg) Np-reg)
260: (e-goto g-topsym))
261: t)) ; return t to indicate that tailrecursion was successful
262:
263:
264:
265:
266: ; Section xxx -- specific function compilers
267: ;
268:
269: ;--- cc-and :: compile an and expression
270: ; We evaluate forms from left to right as long as they evaluate to
271: ; a non nil value. We only have to worry about storing the value of
272: ; the last expression in g-loc.
273: ;
274: (defun cc-and nil
275: (let ((finlab (d-genlab))
276: (finlab2)
277: (exps (If (cdr v-form) thenret else '(t)))) ; (and) ==> t
278: (If (null (cdr g-cc))
279: then (d-exp (do ((g-cc (cons nil finlab))
280: (g-loc)
281: (g-ret)
282: (ll exps (cdr ll)))
283: ((null (cdr ll)) (car ll))
284: (d-exp (car ll))))
285: (If g-loc then (setq finlab2 (d-genlab))
286: (e-goto finlab2)
287: (e-label finlab)
288: (d-move 'Nil g-loc)
289: (e-label finlab2)
290: else (e-label finlab))
291: else ;--- cdr g-cc is non nil, thus there is
292: ; a quick escape possible if one of the
293: ; expressions evals to nil
294:
295: (If (null g-loc) then (setq finlab (cdr g-cc)))
296: (d-exp (do ((g-cc (cons nil finlab))
297: (g-loc)
298: (g-ret)
299: (ll exps (cdr ll)))
300: ((null (cdr ll)) (car ll))
301: (d-exp (car ll))))
302: ; if g-loc is non nil, then we have evaled the and
303: ; expression to yield nil, which we must store in
304: ; g-loc and then jump to where the cdr of g-cc takes us
305: (If g-loc then (setq finlab2 (d-genlab))
306: (e-goto finlab2)
307: (e-label finlab)
308: (d-move 'Nil g-loc)
309: (e-goto (cdr g-cc))
310: (e-label finlab2))))
311: (d-clearreg)) ; we cannot predict the state of the registers
312:
313:
314:
315:
316: ;--- cc-arg :: get the nth arg from the current lexpr = cc-arg =
317: ;
318: ; the syntax for Franz lisp is (arg i)
319: ; for interlisp the syntax is (arg x i) where x is not evaluated and is
320: ; the name of the variable bound to the number of args. We can only handle
321: ; the case of x being the variable for the current lexpr we are compiling
322: ;
323: (defun cc-arg nil
324: (let ((nillab (d-genlab)) (finlab (d-genlab)))
325: (If (not (eq 'lexpr g-ftype))
326: then (comp-err " arg only allowed in lexprs"))
327: (If (and (eq (length (cdr v-form)) 2) fl-inter)
328: then (If (not (eq (car g-args) (cadr v-form)))
329: then (comp-err " arg expression is for non local lexpr "
330: v-form)
331: else (setq v-form (cdr v-form))))
332: (If (or g-loc g-cc)
333: then (let ((g-loc 'reg)
334: (g-cc (cons nil nillab))
335: (g-ret))
336: (d-exp `(cdr ,(cadr v-form)))) ; calc the numeric arg
337: (If g-loc then (d-move '"*-4(fp)[r0]" g-loc)
338: else (e-tst '"*-4(fp)[r0]"))
339: (d-handlecc)
340: (e-goto finlab)
341: (e-label nillab)
342: ; here we are doing (arg nil) which returns the number of args
343: ; which is always true if anyone is testing
344: (If g-loc then (d-move '"-8(fp)" g-loc)
345: (d-handlecc)
346: elseif (car g-cc) then (e-goto (car g-cc))) ;always true
347: (e-label finlab))))
348:
349:
350: ;--- cc-atom :: test for atomness = cc-atom =
351: ;
352: (defun cc-atom nil
353: (d-typecmplx (cadr v-form)
354: '#.(concat '$ (plus 1_0 1_1 1_2 1_4 1_5 1_6 1_7 1_9 1_10))))
355:
356:
357: ;--- cc-bcdp :: check for bcdpness = cc-bcdp =
358: ;
359: (defun cc-bcdp nil
360: (d-typesimp (cadr v-form) '$5))
361:
362:
363: ;--- cc-bigp :: check for bignumness = cc-bigp =
364: ;
365: (defun cc-bigp nil
366: (d-typesimp (cadr v-form) '$9))
367:
368: ;--- c-*catch :: compile a *catch expression = c-*catch =
369: ;
370: ; the form of *catch is (*catch 'tag 'val)
371: ; we evaluate 'tag and set up a catch frame, and then eval 'val
372: ;
373: (defun c-*catch nil
374: (let ((g-loc 'reg)
375: (g-cc nil)
376: (g-ret nil)
377: (finlab (d-genlab)))
378: (d-exp (cadr v-form)) ; calculate tag into r0
379: (d-catcherrset finlab 'reg 'T (caddr v-form))
380: (e-label finlab)))
381:
382:
383:
384: ;--- d-catcherrset :: common code to catch and errset
385: ;
386: (defun d-catcherrset (finlab tagloc flagloc expr)
387: (e-write2 'pushab finlab)
388: (e-write2 'pushr '$0x2540) ; save registers
389: (e-write2 'jsb '_svkludg) ; save rest of state
390: (e-write2 'pushl Bnp-val)
391: (e-write2 'pushl (e-cvt tagloc)) ; push tag
392: (e-write2 'pushl (e-cvt flagloc)) ; non-nil flag
393: (e-write2 'pushl '_errp) ; old error pointer
394: (e-write3 'movl 'sp '_errp) ; set up new error pointer
395: (Push g-locs '(catcherrset . 0))
396: (d-exp expr) ; now do the expression
397: (unpush g-locs)
398: (e-write3 'movl '"(sp)" '_errp) ; unlink this error frame
399: (e-write3 'addl2 '$80 'sp)
400: (d-clearreg)) ; cant predict contents after retune
401:
402:
403: ;--- c-cond :: compile a "cond" expression = c-cond =
404: ;
405: ; not that this version of cond is a 'c' rather than a 'cc' .
406: ; this was done to make coding this routine easier and because
407: ; it is believed that it wont harm things much if at all
408: ;
409: (defun c-cond nil
410: (makecomment '(beginning cond))
411: (do ((clau (cdr v-form) (cdr clau))
412: (finlab (d-genlab))
413: (nxtlab)
414: (save-reguse)
415: (seent))
416: ((or (null clau) seent)
417: ; end of cond
418: ; if haven't seen a t must store a nil in r0
419: (If (null seent) then (d-move 'Nil 'reg))
420: (e-label finlab))
421:
422: ; case 1 - expr
423: (If (atom (car clau))
424: then (comp-err "bad cond clause " (car clau))
425: ; case 2 - (expr)
426: elseif (null (cdar clau))
427: then (let ((g-loc (If (or g-cc g-loc) then 'reg))
428: (g-cc (cons finlab nil))
429: (g-ret))
430: (d-exp (caar clau)))
431: ; case 3 - (t expr1 expr2 ...)
432: elseif (or (eq t (caar clau))
433: (equal ''t (caar clau)))
434: then (let ((g-loc (If (or g-cc g-loc) then 'reg))
435: g-cc)
436: (d-exps (cdar clau)))
437: (setq seent t)
438: ; case 4 - (expr1 expr2 ...)
439: else (let ((g-loc nil)
440: (g-cc (cons nil (setq nxtlab (d-genlab))))
441: (g-ret nil))
442: (d-exp (caar clau)))
443: (setq save-reguse (copy g-reguse))
444: (let ((g-loc (If (or g-cc g-loc) then 'reg))
445: g-cc)
446: (d-exps (cdar clau)))
447: (If (or (cdr clau) (null seent)) then (e-goto finlab))
448: (e-label nxtlab)
449: (setq g-reguse save-reguse)))
450:
451: (d-clearreg))
452:
453:
454:
455: ;--- c-cons :: do a cons instruction quickly = c-cons =
456: ;
457: (defun c-cons nil
458: (d-pushargs (cdr v-form)) ; there better be 2 args
459: (e-write2 'jsb '_qcons)
460: (setq g-locs (cddr g-locs))
461: (setq g-loccnt (- g-loccnt 2))
462: (d-clearreg))
463:
464:
465: ;--- c-cxr :: compile a cxr instruction = c-cxr =
466: ;
467: ; this code would also be useful for accessing any vector of lispvals.
468: ;
469: (defun c-cxr nil
470: (prog (arg1 arg2 arg1loc arg2loc)
471: (setq arg1loc (d-simple (setq arg1 (list 'cdr (cadr v-form))))
472: arg2loc (d-simple (setq arg2 (caddr v-form))))
473:
474: (If (not (and (dtpr arg1loc) (eq 'immed (car arg1loc))))
475: then
476: (If arg2loc
477: then (If (null arg1loc)
478: then (let ((g-loc 'r1)
479: (g-cc))
480: (d-exp arg1))
481: else (d-move arg1loc 'r1))
482: (d-move arg2loc 'r0)
483: else (d-pushargs (ncons arg1))
484: (let ((g-loc 'r0)
485: (g-cc))
486: (d-exp arg2))
487: (d-move 'unstack 'r1)
488: (decr g-loccnt)
489: (Pop g-locs))
490: (d-inreg 'r1 nil) ; register clobbered
491: (If g-loc then (e-move `(0 r0 r1) (e-cvt g-loc))
492: (d-handlecc)
493: elseif g-cc then (e-tst `(0 r0 r1))
494: (d-handlecc))
495: else (let ((g-loc 'r0)
496: (g-cc))
497: (d-exp arg2))
498: (setq arg1loc (list (* 4 (cadr arg1loc)) 'r0))
499: (If g-loc then (e-move arg1loc (e-cvt g-loc))
500: (d-handlecc)
501: elseif g-cc then (e-tst arg1loc)
502: (d-handlecc)))))
503:
504:
505: ;--- cc-cxxr :: compile a "c*r" instr where * = c-cxxr =
506: ; is any sequence of a's and d's
507: ; - arg : argument of the cxxr function
508: ; - pat : a list of a's and d's in the reverse order of that
509: ; which appeared between the c and r
510: ;
511: (defun cc-cxxr (arg pat)
512: (prog (resloc loc qloc sofar togo keeptrack)
513: ; check for the special case of nil, since car's and cdr's
514: ; are nil anyway
515: (If (null arg) then (If g-loc then (d-move 'Nil g-loc)
516: (d-handlecc)
517: elseif (cdr g-cc) then (e-goto (cdr g-cc)))
518: (return))
519:
520: (If (and (symbolp arg) (setq qloc (d-bestreg arg pat)))
521: then (setq resloc (car qloc)
522: loc resloc
523: sofar (cadr qloc)
524: togo (caddr qloc))
525: else (setq resloc (If (d-simple arg) thenret
526: else (let ((g-loc 'reg)
527: (g-cc nil)
528: (g-ret nil))
529: (d-exp arg))
530: 'r0))
531: (setq sofar nil
532: togo pat))
533:
534: (If (and arg (symbolp arg)) then (setq keeptrack t))
535:
536: ; if resloc is a global variable, we must move it into a register
537: ; right away to be able to do car's and cdr's
538: (If (and (dtpr resloc) (or (eq (car resloc) 'bind)
539: (eq (car resloc) 'vstack)))
540: then (d-move resloc 'reg)
541: (setq resloc 'r0))
542:
543: ; now do car's and cdr's . Values are placed in r0. We stop when
544: ; we can get the result in one machine instruction. At that point
545: ; we see whether we want the value or just want to set the cc's.
546: ; If the intermediate value is in a register,
547: ; we can do : car cdr cddr cdar
548: ; If the intermediate value is on the local vrbl stack or lbind
549: ; we can do : cdr
550: (do ((curp togo newp)
551: (newp))
552: ((null curp) (If g-loc then (d-movespec loc g-loc)
553: elseif g-cc then (e-tst loc))
554: (d-handlecc))
555: (If (symbolp resloc)
556: then (If (eq 'd (car curp))
557: then (If (or (null (cdr curp))
558: (eq 'a (cadr curp)))
559: then (setq newp (cdr curp) ; cdr
560: loc `(0 ,resloc)
561: sofar (append sofar (list 'd)))
562: else (setq newp (cddr curp) ; cddr
563: loc `(* 0 ,resloc)
564: sofar (append sofar (list 'd 'd))))
565: else (If (or (null (cdr curp))
566: (eq 'a (cadr curp)))
567: then (setq newp (cdr curp) ; car
568: loc `(4 ,resloc)
569: sofar (append sofar (list 'a)))
570: else (setq newp (cddr curp) ; cdar
571: loc `(* 4 ,resloc)
572: sofar (append sofar (list 'a 'd)))))
573: elseif (and (eq 'd (car curp))
574: (not (eq '* (car (setq loc (e-cvt resloc))))))
575: then (setq newp (cdr curp) ; (cdr <local>)
576: loc (cons '* loc)
577: sofar (append sofar (list 'd)))
578: else (setq loc (e-cvt resloc)
579: newp curp))
580: (If newp ; if this is not the last move
581: then (setq resloc (d-allocreg (If keeptrack then nil else 'r0)))
582: (d-movespec loc resloc)
583: (If keeptrack then (d-inreg resloc (cons arg sofar)))))))
584:
585: ;--- c-declare :: handle the "declare" form
586: ; if a declare is seen inside a function definition, we just
587: ; ignore it. We probably should see what it is declareing, as it
588: ; might be declaring a special.
589: ;
590: (defun c-declare nil)
591:
592: ;--- c-do :: compile a "do" expression = c-do =
593: ;
594: ; a do has this form:
595: ; (do vrbls tst . body)
596: ; we note the special case of tst being nil, in which case the loop
597: ; is evaluated only once, and thus acts like a let with labels allowed.
598: ; The do statement is a cross between a prog and a lambda. It is like
599: ; a prog in that labels are allowed. It is like a lambda in that
600: ; we stack the values of all init forms then bind to the variables, just
601: ; like a lambda expression (that is the initial values of even specials
602: ; are stored on the stack, and then copied into the value cell of the
603: ; atom during the binding phase. From then on the stack location is
604: ; not used).
605: ;
606: (defun c-do nil
607: (prog (b-vrbls b-tst b-body chklab bodylab x-repeat x-vrbs x-fst
608: g-loc g-cc oldreguse)
609: (forcecomment '(beginning do))
610: (setq g-loc 'reg chklab (d-genlab) bodylab (d-genlab))
611:
612: (If (and (cadr v-form) (atom (cadr v-form)))
613: then (setq v-form (d-olddo-to-newdo (cdr v-form))))
614:
615: (Push g-locs (cons 'do 0 )) ; begin our frame
616:
617: (setq b-vrbls (cadr v-form)
618: b-tst (caddr v-form)
619: b-body (cdddr v-form))
620:
621: ; push value of init forms on stack
622: (d-pushargs (mapcar '(lambda (x)
623: (If (atom x) then nil ; no init form => nil
624: else (cadr x)))
625: b-vrbls))
626:
627: ; now bind to the variables in the vrbls form
628: (d-bindlamb (mapcar '(lambda (x)
629: (If (atom x) then x
630: else (car x)))
631: b-vrbls))
632:
633: ; search through body for all labels and assign them gensymed labels
634: (Push g-labs (cons (d-genlab)
635: (do ((ll b-body (cdr ll))
636: (res))
637: ((null ll) res)
638: (If (and (car ll) (symbolp (car ll)))
639: then (Push res (cons (car ll) (d-genlab)))))))
640:
641: ; if the test is non nil, we do the test
642: ; another strange thing, a test form of (pred) will not return
643: ; the value of pred if it is not nil! it will return nil (in this
644: ; way, it is not like a cond clause)
645: (d-clearreg)
646: (If b-tst then (e-label chklab)
647: (let ((g-cc (cons nil bodylab)) g-loc g-ret)
648: (d-exp (car b-tst))) ; eval test
649: ; if false, do body
650: (If (cdr b-tst)
651: then (setq oldreguse (copy g-reguse))
652: (d-exps (cdr b-tst))
653: (setq g-reguse oldreguse)
654: else (d-move 'Nil 'reg))
655: (e-goto (caar g-labs)) ; leave do
656: (e-label bodylab)) ; begin body
657:
658: ; process body
659: (do ((ll b-body (cdr ll))
660: (g-cc) (g-loc)(g-ret))
661: ((null ll))
662: (If (or (null (car ll)) (not (symbolp (car ll))))
663: then (d-exp (car ll))
664: else (e-label (cdr (assoc (car ll) (cdar g-labs))))
665: (d-clearreg)))
666:
667: (If b-tst then ; determine all repeat forms which must be
668: ; evaluated, and all the variables affected.
669: ; store the results in x-repeat and x-vrbs
670: ; if there is just one repeat form, we calculate
671: ; its value directly into where it is stored,
672: ; if there is more than one, we stack them
673: ; and then store them back at once.
674: (do ((ll b-vrbls (cdr ll)))
675: ((null ll))
676: (If (and (dtpr (car ll)) (cddar ll))
677: then (Push x-repeat (caddar ll))
678: (Push x-vrbs (caar ll))))
679: (If x-vrbs
680: then (If (null (cdr x-vrbs)) ; if just one repeat..
681: then (let ((g-loc (d-locv (car x-vrbs)))
682: (g-cc nil))
683: (d-exp (car x-repeat)))
684: else (setq x-fst (car x-repeat))
685: (d-pushargs (nreverse (cdr x-repeat)))
686: (let ((g-loc (d-locv (car x-vrbs)))
687: (g-cc)
688: (g-ret))
689: (d-exp x-fst))
690: (do ((ll (cdr x-vrbs) (cdr ll)))
691: ((null ll))
692: (d-move 'unstack (d-locv (car ll)))
693: (setq g-locs (cdr g-locs))
694: (decr g-loccnt))))
695: (e-goto chklab))
696:
697: (e-label (caar g-labs)) ; end of do label
698: (d-clearreg)
699: (d-unbind)
700: (setq g-labs (cdr g-labs))))
701:
702:
703: ;--- d-olddo-to-newdo :: map old do to new do
704: ;
705: ; form of old do is (do var tst . body)
706: ; where var is a symbol, not nil
707: ;
708: (defun d-olddo-to-newdo (v-l)
709: `(do ((,(car v-l) ,(cadr v-l) ,(caddr v-l)))
710: (,(cadddr v-l))
711: ,@(cddddr v-l)))
712:
713:
714:
715: ;--- cc-dtpr :: check for dtprness = cc-dtpr =
716: ;
717: (defun cc-dtpr nil
718: (d-typesimp (cadr v-form) '$3))
719:
720:
721: ;--- cc-eq :: compile an "eq" expression = cc-eq =
722: ;
723: (defun cc-eq nil
724: (let ((arg1 (cadr v-form))
725: (arg2 (caddr v-form))
726: arg1loc
727: arg2loc)
728: (If (setq arg2loc (d-simple arg2))
729: then (If (setq arg1loc (d-simple arg1))
730: then ; eq <simple> <simple>
731: (d-cmp arg1loc arg2loc)
732: else ; eq <nonsimple> <simple>
733: (let ((g-loc 'reg) ; put <nonsimple> in r0
734: g-cc
735: g-ret)
736: (d-exp arg1))
737: (d-cmp 'reg arg2loc))
738: else ; since second is nonsimple, must stack first
739: ; arg out of harms way
740: (let ((g-loc 'stack)
741: g-cc
742: g-ret)
743: (d-exp arg1)
744: (Push g-locs nil)
745: (incr g-loccnt)
746: (setq g-loc 'reg) ; second arg to r0
747: (d-exp arg2))
748: (d-cmp 'unstack 'reg)
749: (setq g-locs (cdr g-locs))
750: (decr g-loccnt)))
751:
752: (d-invert))
753:
754: (defun cc-equal nil
755: (let ((lab1 (d-genlab))
756: (lab11 (d-genlab))
757: lab2)
758: (d-pushargs (cdr v-form))
759: (e-write3 'cmpl "-8(r6)" "-4(r6)")
760: (e-gotonil lab1)
761: (d-calltran 'equal '2) ; not eq, try equal.
762: (d-clearreg)
763: (e-write2 'tstl 'r0)
764: (e-gotot lab11)
765: (If g-loc then (d-move 'Nil g-loc))
766: (If (cdr g-cc) then (e-goto (cdr g-cc))
767: else (e-goto (setq lab2 (d-genlab))))
768: (e-writel lab1)
769: (e-dropnp 2)
770: (e-writel lab11)
771: (If g-loc then (d-move 'T g-loc))
772: (If (car g-cc) then (e-goto (car g-cc)))
773: (If lab2 then (e-writel lab2))
774: (setq g-locs (cddr g-locs))
775: (setq g-loccnt (- g-loccnt 2))))
776:
777:
778:
779:
780: ;--- c-errset :: compile an errset expression = c-errset =
781: ;
782: ; the errset has this form: (errset 'value ['tag])
783: ; where tag defaults to t.
784: ;
785: (defun c-errset nil
786: (let ((g-loc 'reg)
787: (g-cc nil)
788: (g-ret nil)
789: (finlab (d-genlab)))
790: (d-exp (If (cddr v-form) then (caddr v-form) else t))
791: (d-catcherrset finlab (d-loclit '(ER%all) nil) 'reg (cadr v-form))
792: (d-move 'reg 'stack)
793: (d-calltran 'ncons 1)
794: (e-label finlab)
795: (d-clearreg)))
796:
797:
798: ;--- cc-fixp :: check for a fixnum or bignum = cc-fixp =
799: ;
800: (defun cc-fixp nil
801: (d-typecmplx (cadr v-form)
802: '#.(concat '$ (plus 1_2 1_9))))
803:
804:
805: ;--- cc-floatp :: check for a flonum = cc-floatp =
806: ;
807: (defun cc-floatp nil
808: (d-typesimp (cadr v-form) '$4))
809:
810:
811: ;--- c-get :: do a get from the prop list
812: ;
813: (defun c-get nil
814: (If (not (eq 2 (length (cdr v-form))))
815: then (comp-err "Wrong number of args to get " v-form))
816: (d-pushargs (cdr v-form)) ; there better be 2 args
817: (e-write2 'jsb '_qget)
818: (d-clearreg)
819: (setq g-locs (cddr g-locs))
820: (setq g-loccnt (- g-loccnt 2)))
821:
822: ;--- c-go :: compile a "go" expression = c-go =
823: ;
824: ; we only compile the (go symbol)type expression, we do not
825: ; allow symbol to be anything by a non null symbol.
826: ;
827: (defun c-go nil
828: ; find number of frames we have to go down to get to the label
829: (do ((labs g-labs (cdr labs))
830: (locs g-locs)
831: (locals 0)
832: (specials 0)
833: (catcherrset 0)
834: (label))
835: ((null labs) (comp-err "go label not found for expression: " (or v-form)))
836: ; if there are any enclosing *catches or errsets, they will be
837: ; first in g-locs
838: (do nil
839: ((not (and (dtpr (car locs)) (eq (caar locs) 'catcherrset))))
840: (incr catcherrset)
841: (unpush locs))
842:
843: (If (car labs)
844: then (If (setq label (do ((lbs (cdar labs) (cdr lbs)))
845: ((null lbs))
846: (If (eq (caar lbs) (cadr v-form))
847: then (return (cdar lbs)))))
848: then (If (not (eq labs g-labs))
849: then (comp-warn "non local go used : " (or v-form)))
850: (If (greaterp catcherrset 0)
851: then (comp-warn "Go through a catch or errset " v-form)
852: (do ((i 0 (1+ i)))
853: ((equal catcherrset i))
854: (e-write3 'movl "(sp)" '_errp)
855: (e-write3 'addl2 '$80 'sp)))
856: (e-pop locals)
857: (If (greaterp specials 0)
858: then (e-unshallowbind specials))
859: (e-goto label)
860: (return)))
861: ; tally all locals and specials used in this frame
862: (do ()
863: ((dtpr (car locs)) (setq specials (+ specials (cdar locs))
864: locs (cdr locs)))
865: (setq locs (cdr locs))
866: (incr locals))))
867:
868:
869: ;--- cc-ingnore :: just ignore this code
870: ;
871: (defun cc-ignore nil
872: nil)
873:
874: ;--- c-lambexp :: compile a lambda expression = c-lambexp =
875: ;
876: (defun c-lambexp nil
877: (let ((g-loc (If (or g-loc g-cc) then 'reg))
878: (g-cc nil))
879: (Push g-locs (cons 'lambda 0)) ; add null lambda header
880: (d-pushargs (cdr v-form)) ; then push vals
881: (d-lambbody (car v-form))
882: (d-clearreg)))
883:
884: ;--- d-lambbody :: do a lambda body
885: ; - body : body of lambda expression, eg (lambda () dld)
886: ;
887: (defun d-lambbody (body)
888: (d-bindlamb (cadr body)) ; bind locals
889: (setq g-labs (cons nil g-labs)) ; no labels allowed
890: (d-clearreg)
891: (d-exp (do ((ll (cddr body) (cdr ll))
892: (g-loc)
893: (g-cc)
894: (g-ret))
895: ((null (cdr ll)) (car ll))
896: (d-exp (car ll))))
897:
898: (setq g-labs (cdr g-labs))
899: (d-unbind)) ; unbind this frame
900:
901:
902: ;--- d-bindlamb :: bind variables in lambda list
903: ; - vrbs : list of lambda variables, may include nil meaning ignore
904: ;
905: (defun d-bindlamb (vrbs)
906: (let ((res (d-bindlrec (reverse vrbs) g-locs 0 g-loccnt)))
907: (If res then (e-setupbind)
908: (mapc '(lambda (vrb) (e-shallowbind (car vrb) (cdr vrb)))
909: res)
910: (e-unsetupbind))))
911:
912: ;--- d-bindlrec :: recusive routine to bind lambda variables
913: ; - vrb : list of variables yet to bind
914: ; - locs : current location in g-loc
915: ; - specs : number of specials seen so far
916: ; - lev : how far up from the bottom of stack we are.
917: ; returns: list of elements, one for each special, of this form:
918: ; (<specialvrbname> stack <n>)
919: ; where specialvrbname is the name of the special variable, and n is
920: ; the distance from the top of the stack where its initial value is
921: ; located
922: ; also: puts the names of the local variables in the g-locs list, as well
923: ; as placing the number of special variables in the lambda header.
924: ;
925: (defun d-bindlrec (vrb locs specs lev)
926: (If vrb
927: then (let ((spcflg (d-specialp (car vrb)))
928: retv)
929: (If spcflg then (setq specs (1+ specs)))
930:
931: (If (cdr vrb) ; if more vrbls to go ...
932: then (setq retv (d-bindlrec (cdr vrb)
933: (cdr locs)
934: specs
935: (1- lev)))
936: else (rplacd (cadr locs) specs)) ; else fix up lambda hdr
937:
938: (If (not spcflg) then (rplaca locs (car vrb))
939: else (Push retv `(,(car vrb) stack ,lev)))
940:
941: retv)))
942: ;--- c-list :: compile a list expression = c-list =
943: ;
944: ; this is compiled as a bunch of conses with a nil pushed on the
945: ; top for good measure
946: ;
947: (defun c-list nil
948: (prog (nargs)
949: (setq nargs (length (cdr v-form)))
950: (makecomment '(list expression))
951: (If (zerop nargs) then (d-move 'Nil 'reg) ; (list) ==> nil
952: (return))
953: (d-pushargs (cdr v-form))
954: (e-write2 'clrl '(+ #.Np-reg)) ; stack one nil
955:
956: ; now do the consing
957: (do ((i (max 1 nargs) (1- i)))
958: ((zerop i))
959: (e-write2 'jsb '_qcons)
960: (d-clearreg)
961: (If (> i 1) then (d-move 'reg 'stack)))
962:
963: (setq g-locs (nthcdr nargs g-locs)
964: g-loccnt (- g-loccnt nargs))))
965:
966:
967:
968: ;--- d-mapconvert - access : function to access parts of lists
969: ; - join : function to join results
970: ; - resu : function to apply to result
971: ; - form : mapping form
972: ; This function converts maps to an equivalent do form.
973: ;
974: (defun d-mapconvert (access join resu form )
975: (prog (vrbls finvar acc accform compform tmp)
976:
977: (setq finvar (gensym 'X) ; holds result
978:
979: vrbls (reverse
980: (maplist '(lambda (arg)
981: ((lambda (temp)
982: (cond ((or resu (cdr arg))
983: `(,temp ,(car arg)
984: (cdr ,temp)))
985: (t `(,temp
986: (setq ,finvar ,(car arg))
987: (cdr ,temp)))))
988: (gensym 'X)))
989: (reverse (cdr form))))
990:
991: acc (mapcar '(lambda (tem)
992: (cond (access `(,access ,(car tem)))
993: (t (car tem))))
994: vrbls)
995:
996: accform (cond ((or (atom (setq tmp (car form)))
997: (null (setq tmp (d-macroexpand tmp)))
998: (not (member (car tmp) '(quote function))))
999: `(funcall ,tmp ,@acc))
1000: (t `(,(cadr tmp) ,@acc))))
1001: (return
1002: `((lambda (,finvar)
1003: (do ( ,@vrbls)
1004: ((null ,(caar vrbls)))
1005: ,(cond ((eq join 'nconc)
1006: `(setq ,finvar (nconc ,finvar ,accform)))
1007: (join `(setq ,finvar (,join ,accform ,finvar)))
1008: (t accform)))
1009: ,(cond ((eq resu 'identity) finvar)
1010: (resu `(,resu ,finvar))
1011: (t finvar)))
1012: nil ))))
1013: ; apply to successive elements, return second arg
1014: (defun cm-mapc nil
1015: (d-mapconvert 'car nil nil (cdr v-form)))
1016:
1017: ; apply to successive elements, return list of results
1018: (defun cm-mapcar nil
1019: (d-mapconvert 'car 'cons 'nreverse (cdr v-form)))
1020:
1021: ; apply to successive elements, returned nconc of results
1022: (defun cm-mapcan nil
1023: (d-mapconvert 'car 'nconc 'identity (cdr v-form)))
1024:
1025:
1026: ; apply to successive sublists, return second arg
1027: (defun cm-map nil
1028: (d-mapconvert nil nil nil (cdr v-form)))
1029:
1030:
1031: ; apply to successive sublists, return list of results
1032: (defun cm-maplist nil
1033: (d-mapconvert nil 'cons 'reverse (cdr v-form)))
1034:
1035: ; apply to successive sublists, return nconc of results
1036: (defun cm-mapcon nil
1037: (d-mapconvert nil 'nconc 'identity (cdr v-form)))
1038:
1039:
1040: ;--- cc-memq :: compile a memq expression = cc-memq =
1041: ;
1042: (defun cc-memq nil
1043: (let ((loc1 (d-simple (cadr v-form)))
1044: (loc2 (d-simple (caddr v-form)))
1045: looploc finlab)
1046: (If loc2 then (d-clearreg 'r1)
1047: (If loc1 then (d-move loc1 'r1)
1048: else (let ((g-loc 'r1)
1049: g-cc
1050: g-ret)
1051: (d-exp (cadr v-form))))
1052: (d-move loc2 'reg)
1053: else (let ((g-loc 'stack)
1054: g-cc
1055: g-ret)
1056: (d-exp (cadr v-form)))
1057: (Push g-locs nil)
1058: (incr g-loccnt)
1059: (let ((g-loc 'reg)
1060: g-cc
1061: g-ret)
1062: (d-exp (caddr v-form)))
1063: (d-move 'unstack 'r1)
1064: (d-clearreg 'r1)
1065: (unpush g-locs)
1066: (decr g-loccnt))
1067: ; now set up the jump addresses
1068: (If (null g-loc)
1069: then (setq loc1 (If (car g-cc) thenret
1070: else (d-genlab))
1071: loc2 (If (cdr g-cc) thenret
1072: else (d-genlab)))
1073: else (setq loc1 (d-genlab)
1074: loc2 (d-genlab)))
1075:
1076: (setq looploc (d-genlab))
1077:
1078: (e-write2 'tstl 'r0)
1079: (e-write2 'jeql loc2)
1080: (e-label looploc)
1081: (e-write3 'cmpl 'r1 "4(r0)")
1082: (e-write2 'jeql loc1)
1083: (e-write3 'movl "(r0)" 'r0)
1084: (e-write2 'jneq looploc)
1085: (If g-loc then (e-label loc2) ; nil result
1086: (d-move 'reg g-loc)
1087: (If (cdr g-cc) then (e-goto (cdr g-cc))
1088: else (e-goto (setq finlab (d-genlab))))
1089: else (If (cdr g-cc) then (e-goto (cdr g-cc))
1090: else (e-label loc2)))
1091: (If g-loc then (e-label loc1) ; non nil result
1092: (d-move 'reg g-loc)
1093: (If (car g-cc) then (e-goto (car g-cc)))
1094: else (If (null (car g-cc)) then (e-label loc1)))
1095: (If finlab then (e-label finlab))))
1096:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.