|
|
1.1 ! root 1: (include-if (null (get 'chead 'version)) "../chead.l") ! 2: (Liszt-file funb ! 3: "$Header: funb.l,v 1.13 87/12/15 17:02:17 sklower Exp $") ! 4: ! 5: ;;; ---- f u n b function compilation ! 6: ;;; ! 7: ;;; -[Wed Aug 24 17:14:56 1983 by layer]- ! 8: ! 9: ;--- c-declare :: handle the "declare" form ! 10: ; if a declare is seen inside a function definition, we just ! 11: ; ignore it. We probably should see what it is declareing, as it ! 12: ; might be declaring a special. ! 13: ; ! 14: (defun c-declare nil nil) ! 15: ! 16: ;--- c-do :: compile a "do" expression ! 17: ; ! 18: ; a do has this form: ! 19: ; (do vrbls tst . body) ! 20: ; we note the special case of tst being nil, in which case the loop ! 21: ; is evaluated only once, and thus acts like a let with labels allowed. ! 22: ; The do statement is a cross between a prog and a lambda. It is like ! 23: ; a prog in that labels are allowed. It is like a lambda in that ! 24: ; we stack the values of all init forms then bind to the variables, just ! 25: ; like a lambda expression (that is the initial values of even specials ! 26: ; are stored on the stack, and then copied into the value cell of the ! 27: ; atom during the binding phase. From then on the stack location is ! 28: ; not used). ! 29: ; ! 30: (defun c-do nil ! 31: (let (b-vrbls b-tst b-body chklab bodylab x-repeat x-vrbs x-fst ! 32: g-loc g-cc oldreguse (g-decls g-decls)) ! 33: (forcecomment '(beginning do)) ! 34: (setq g-loc 'reg chklab (d-genlab) bodylab (d-genlab)) ! 35: ! 36: (if (and (cadr v-form) (atom (cadr v-form))) ! 37: then (setq v-form (d-olddo-to-newdo (cdr v-form)))) ! 38: ! 39: (push (cons 'do 0) g-locs) ; begin our frame ! 40: ! 41: (setq b-vrbls (cadr v-form) ! 42: b-tst (caddr v-form) ! 43: b-body (cdddr v-form)) ! 44: ! 45: (d-scanfordecls b-body) ! 46: ! 47: ; push value of init forms on stack ! 48: (d-pushargs (mapcar '(lambda (x) ! 49: (if (atom x) ! 50: then nil ; no init form => nil ! 51: else (cadr x))) ! 52: b-vrbls)) ! 53: ! 54: ; now bind to the variables in the vrbls form ! 55: (d-bindlamb (mapcar '(lambda (x) ! 56: (if (atom x) then x ! 57: else (car x))) ! 58: b-vrbls)) ! 59: ! 60: ; search through body for all labels and assign them gensymed labels ! 61: (push (cons (d-genlab) ! 62: (do ((ll b-body (cdr ll)) ! 63: (res)) ! 64: ((null ll) res) ! 65: (if (and (car ll) (symbolp (car ll))) ! 66: then (Push res ! 67: (cons (car ll) (d-genlab)))))) ! 68: g-labs) ! 69: ! 70: ; if the test is non nil, we do the test ! 71: ; another strange thing, a test form of (pred) will not return ! 72: ; the value of pred if it is not nil! it will return nil -- in this ! 73: ; way, it is not like a cond clause ! 74: (d-clearreg) ! 75: (if b-tst then (e-label chklab) ! 76: (let ((g-cc (cons nil bodylab)) g-loc g-ret) ! 77: (d-exp (car b-tst))) ; eval test ! 78: ; if false, do body ! 79: (if (cdr b-tst) ! 80: then (setq oldreguse (copy g-reguse)) ! 81: (d-exps (cdr b-tst)) ! 82: (setq g-reguse oldreguse) ! 83: else (d-move 'Nil 'reg)) ! 84: (e-goto (caar g-labs)) ; leave do ! 85: (e-label bodylab)) ; begin body ! 86: ! 87: ; process body ! 88: (do ((ll b-body (cdr ll)) ! 89: (g-cc) (g-loc)(g-ret)) ! 90: ((null ll)) ! 91: (if (or (null (car ll)) (not (symbolp (car ll)))) ! 92: then (d-exp (car ll)) ! 93: else (e-label (cdr (assoc (car ll) (cdar g-labs)))) ! 94: (d-clearreg))) ! 95: ! 96: (if b-tst ! 97: then ; determine all repeat forms which must be ! 98: ; evaluated, and all the variables affected. ! 99: ; store the results in x-repeat and x-vrbs ! 100: ; if there is just one repeat form, we calculate ! 101: ; its value directly into where it is stored, ! 102: ; if there is more than one, we stack them ! 103: ; and then store them back at once. ! 104: (do ((ll b-vrbls (cdr ll))) ! 105: ((null ll)) ! 106: (if (and (dtpr (car ll)) (cddar ll)) ! 107: then (Push x-repeat (caddar ll)) ! 108: (Push x-vrbs (caar ll)))) ! 109: (if x-vrbs ! 110: then (if (null (cdr x-vrbs)) ; if just one repeat ! 111: then (let ((g-loc (d-locv (car x-vrbs))) ! 112: (g-cc nil)) ! 113: (d-exp (car x-repeat))) ! 114: else (setq x-fst (car x-repeat)) ! 115: (d-pushargs (nreverse ! 116: (cdr x-repeat))) ! 117: (let ((g-loc (d-locv (car x-vrbs))) ! 118: (g-cc) ! 119: (g-ret)) ! 120: (d-exp x-fst)) ! 121: (do ((ll (cdr x-vrbs) (cdr ll))) ! 122: ((null ll)) ! 123: (d-move 'unstack ! 124: (d-locv (car ll))) ! 125: (setq g-locs (cdr g-locs)) ! 126: (decr g-loccnt)))) ! 127: (e-goto chklab)) ! 128: ! 129: (e-label (caar g-labs)) ; end of do label ! 130: (d-clearreg) ! 131: (d-unbind) ! 132: (setq g-labs (cdr g-labs)))) ! 133: ! 134: ;--- d-olddo-to-newdo :: map old do to new do ! 135: ; ! 136: ; form of old do is (do var tst . body) ! 137: ; where var is a symbol, not nil ! 138: ; ! 139: (defun d-olddo-to-newdo (v-l) ! 140: `(do ((,(car v-l) ,(cadr v-l) ,(caddr v-l))) ! 141: (,(cadddr v-l)) ! 142: ,@(cddddr v-l))) ! 143: ! 144: ;--- cc-dtpr :: check for dtprness ! 145: ; ! 146: (defun cc-dtpr nil ! 147: (d-typesimp (cadr v-form) #.(immed-const 3))) ! 148: ! 149: ;--- cc-eq :: compile an "eq" expression ! 150: ; ! 151: (defun cc-eq nil ! 152: (let ((arg1 (cadr v-form)) ! 153: (arg2 (caddr v-form)) ! 154: arg1loc ! 155: arg2loc) ! 156: (if (setq arg2loc (d-simple arg2)) ! 157: then (if (setq arg1loc (d-simple arg1)) ! 158: then ; eq <simple> <simple> ! 159: (d-cmp arg1loc arg2loc) ! 160: else ; eq <nonsimple> <simple> ! 161: (let ((g-loc 'reg) ; put <nonsimple> in reg ! 162: ; must rebind because ! 163: ; cc->& may have modified ! 164: (g-trueop #+(or for-vax for-tahoe) 'jneq ! 165: #+for-68k 'jne) ! 166: (g-falseop #+(or for-vax for-tahoe) 'jeql ! 167: #+for-68k 'jeq) ! 168: g-cc ! 169: g-ret) ! 170: (d-exp arg1)) ! 171: (d-cmp 'reg arg2loc)) ! 172: else ; since second is nonsimple, must stack first ! 173: ; arg out of harms way ! 174: (let ((g-loc 'stack) ! 175: (g-trueop #+(or for-vax for-tahoe) 'jneq #+for-68k 'jne) ! 176: (g-falseop #+(or for-vax for-tahoe) 'jeql #+for-68k 'jeq) ! 177: g-cc ! 178: g-ret) ! 179: (d-exp arg1) ! 180: (push nil g-locs) ! 181: (incr g-loccnt) ! 182: (setq g-loc 'reg) ; second arg to reg ! 183: (d-exp arg2)) ! 184: (d-cmp 'unstack 'reg) ! 185: (setq g-locs (cdr g-locs)) ! 186: (decr g-loccnt))) ! 187: (d-invert)) ! 188: ! 189: ;--- cc-equal :: compile `equal' ! 190: ; ! 191: (defun cc-equal nil ! 192: (let ((lab1 (d-genlab)) ! 193: (lab11 (d-genlab)) ! 194: lab2) ! 195: (d-pushargs (cdr v-form)) ! 196: (e-cmp '(-8 #.np-reg) '(-4 #.np-reg)) ! 197: (e-gotonil lab1) ! 198: (d-calltran 'equal '2) ; not eq, try equal. ! 199: (d-clearreg) ! 200: #+(or for-vax for-tahoe) (e-tst (e-cvt 'reg)) ! 201: #+for-68k (e-cmpnil (e-cvt 'reg)) ! 202: (e-gotot lab11) ! 203: (if g-loc then (d-move 'Nil g-loc)) ! 204: (if (cdr g-cc) then (e-goto (cdr g-cc)) ! 205: else (e-goto (setq lab2 (d-genlab)))) ! 206: (e-writel lab1) ! 207: (e-dropnp 2) ! 208: (e-writel lab11) ! 209: (if g-loc then (d-move 'T g-loc)) ! 210: (if (car g-cc) then (e-goto (car g-cc))) ! 211: (if lab2 then (e-writel lab2)) ! 212: (setq g-locs (cddr g-locs)) ! 213: (setq g-loccnt (- g-loccnt 2)))) ! 214: ! 215: ;--- c-errset :: compile an errset expression ! 216: ; ! 217: ; the errset has this form: (errset 'value ['tag]) ! 218: ; where tag defaults to t. ! 219: ; ! 220: (defun c-errset nil ! 221: (let ((g-loc 'reg) ! 222: (g-cc nil) ! 223: (g-ret nil) ! 224: (finlab (d-genlab)) ! 225: (beglab (d-genlab))) ! 226: (d-exp (if (cddr v-form) then (caddr v-form) else t)) ! 227: (d-pushframe #.F_CATCH (d-loclit 'ER%all nil) 'reg) ! 228: (push nil g-labs) ; disallow labels ! 229: ; If retval is non zero then an error has throw us here so we ! 230: ; must recover the value thrown (from _lispretval) and leave ! 231: ; If retval is zero then we shoud calculate the expression ! 232: ; into r0 and put a cons cell around it ! 233: (e-tst '_retval) ! 234: (e-write2 #+(or for-vax for-tahoe) 'jeql #+for-68k 'jeq beglab) ! 235: (e-move '_lispretval (e-cvt 'reg)) ! 236: (e-write2 #+(or for-vax for-tahoe) 'jbr #+for-68k 'jra finlab) ! 237: (e-label beglab) ! 238: (let ((g-loc 'stack) ! 239: (g-cc nil)) ! 240: (d-exp (cadr v-form))) ! 241: (d-move 'Nil 'stack) ; haven't updated g-loc, g-loccnt but it ! 242: ; shouldn't hurt (famous last words) ! 243: (e-quick-call '_qcons) ! 244: (e-label finlab) ! 245: (d-popframe) ! 246: (unpush g-locs) ; remove (catcherrset . 0) ! 247: (unpush g-labs) ; remove nil ! 248: (d-clearreg))) ! 249: ! 250: ;--- cm-fixnum-cxr :: open code a fixnum-cxr expression. ! 251: ; ! 252: ; fixnum-cxr is a compile only hacky function which accesses an element ! 253: ; of a fixnum space and boxes the resulting fixnum. It can be used ! 254: ; for rapid access to user defined structures. ! 255: ; ! 256: (defun cm-fixnum-cxr () ! 257: `(internal-fixnum-box (cxr ,@(cdr v-form)))) ! 258: ! 259: (defun c-internal-fixnum-box () ! 260: (let ((g-cc nil) ! 261: (g-ret nil) ! 262: (g-loc '#.fixnum-reg)) ! 263: #+for-68k (d-regused '#.fixnum-reg) ! 264: (d-exp (cadr v-form)) ! 265: (e-call-qnewint))) ! 266: ! 267: ;--- cc-offset-cxr ! 268: ; return a pointer to the address of the object instead of the object. ! 269: ; ! 270: (defun cc-offset-cxr nil ! 271: (d-supercxr nil t)) ! 272: ! 273: ;--- cc-fixp :: check for a fixnum or bignum ! 274: ; ! 275: (defun cc-fixp nil ! 276: (d-typecmplx (cadr v-form) ! 277: '#.(immed-const (plus 1_2 1_9)))) ! 278: ! 279: ;--- cc-floatp :: check for a flonum ! 280: ; ! 281: (defun cc-floatp nil ! 282: (d-typesimp (cadr v-form) #.(immed-const 4))) ! 283: ! 284: ;--- c-funcall :: compile a funcall ! 285: ; ! 286: ; we open code a funcall the resulting object is a compiled lambda. ! 287: ; We don't open code nlambda and macro funcalls since they are ! 288: ; rarely used and it would waste space to check for them ! 289: (defun c-funcall nil ! 290: (if (null (cdr v-form)) ! 291: then (comp-err "funcall requires at least one argument " v-form)) ! 292: (let ((g-locs g-locs) ! 293: (g-loccnt g-loccnt) ! 294: (args (length (cdr v-form))) ! 295: (g-loc nil) ! 296: (g-ret nil) ! 297: (g-cc nil)) ! 298: (d-pushargs (cdr v-form)) ! 299: (rplaca (nthcdr (1- args) g-locs) 'funcallfcn) ! 300: ! 301: (d-exp '(cond ((and (symbolp funcallfcn) ! 302: (getd funcallfcn)) ! 303: (setq funcallfcn (getd funcallfcn))))) ! 304: ! 305: (d-exp `(cond ((and (bcdp funcallfcn) (eq 'lambda (getdisc funcallfcn))) ! 306: (Internal-bcdcall ,args t)) ! 307: (t (Internal-bcdcall ,args nil)))))) ! 308: ! 309: ;--- c-Internal-bcdcall ! 310: ; this is a compiler internal function call. when this occurs, there ! 311: ; are argnum objects stacked, the first of which is a function name ! 312: ; or bcd object. If dobcdcall is t then we want to do a bcdcall of ! 313: ; the first object stacked. If it is not true then we want to ! 314: ; call the interpreter funcall function to handle it. ! 315: ; ! 316: (defun c-Internal-bcdcall nil ! 317: (let ((argnum (cadr v-form)) ! 318: (dobcdcall (caddr v-form))) ! 319: (cond (dobcdcall (d-bcdcall argnum)) ! 320: (t (d-calltran 'funcall argnum))))) ! 321: ! 322: ;--- cc-function :: compile a function function ! 323: ; ! 324: ; function is an nlambda, which the interpreter treats as 'quote' ! 325: ; If the argument is a lambda expression, then Liszt will generate ! 326: ; a new function and generate code to return the name of ! 327: ; that function. If the argument is a symbol, then 'symbol ! 328: ; is compiled. It would probably be better to return the function ! 329: ; cell of the symbol, but Maclisp returns the symbol and it ! 330: ; would cause compatibility problems. ! 331: ; ! 332: (defun cc-function nil ! 333: (if (or (null (cdr v-form)) ! 334: (cddr v-form)) ! 335: then (comp-err "Wrong number of arguments to 'function': " v-form)) ! 336: (let ((arg (cadr v-form))) ! 337: (if (symbolp arg) ! 338: then (d-exp `',arg) ! 339: elseif (and (dtpr arg) ! 340: (memq (car arg) '(lambda nlambda lexpr))) ! 341: then (let ((newname (concat "in-line-lambda:" ! 342: (setq in-line-lambda-number ! 343: (add1 in-line-lambda-number))))) ! 344: (Push liszt-process-forms ! 345: `(def ,newname ,arg)) ! 346: (d-exp `',newname)) ! 347: else (comp-err "Illegal argument to 'function': " v-form)))) ! 348: ! 349: ;--- c-get :: do a get from the prop list ! 350: ; ! 351: (defun c-get nil ! 352: (if (not (eq 2 (length (cdr v-form)))) ! 353: then (comp-err "Wrong number of args to get " v-form)) ! 354: (d-pushargs (cdr v-form)) ; there better be 2 args ! 355: (e-quick-call '_qget) ! 356: (d-clearreg) ! 357: (setq g-locs (cddr g-locs)) ! 358: (setq g-loccnt (- g-loccnt 2))) ! 359: ! 360: ;--- cm-getaccess :: compile a getaccess instruction ! 361: ; ! 362: (defun cm-getaccess nil `(cdr ,(cadr v-form))) ! 363: ! 364: ;--- cm-getaux :: compile a getaux instruction ! 365: ; ! 366: (defun cm-getaux nil `(car ,(cadr v-form))) ! 367: ! 368: ;--- cm-getd :: compile a getd instruction ! 369: ; ! 370: ; the getd function is open coded to look in the third part of a symbol ! 371: ; cell ! 372: ; ! 373: (defun cm-getd nil `(cxr 2 ,(cadr v-form))) ! 374: ! 375: ;--- cm-getdata :: compile a getdata instruction ! 376: ; ! 377: ; the getdata function is open coded to look in the third part of an ! 378: ; array header. ! 379: (defun cm-getdata nil `(cxr 2 ,(cadr v-form))) ! 380: ! 381: ;--- cm-getdisc :: compile a getdisc expression ! 382: ; getdisc accessed the discipline field of a binary object. ! 383: ; ! 384: (defun cm-getdisc nil `(cxr 1 ,(cadr v-form))) ! 385: ! 386: ;--- c-go :: compile a "go" expression ! 387: ; ! 388: ; we only compile the (go symbol)type expression, we do not ! 389: ; allow symbol to be anything by a non null symbol. ! 390: ; ! 391: (defun c-go nil ! 392: ; find number of frames we have to go down to get to the label ! 393: (do ((labs g-labs (cdr labs)) ! 394: (locs g-locs) ! 395: (locals 0) ! 396: (specials 0) ! 397: (catcherrset 0) ! 398: (label)) ! 399: ((null labs) ! 400: (comp-err "go label not found for expression: " (or v-form))) ! 401: ! 402: (if (car labs) ; if we have a set of labels to look at... ! 403: then (if (setq label ! 404: (do ((lbs (cdar labs) (cdr lbs))) ! 405: ((null lbs)) ! 406: (if (eq (caar lbs) (cadr v-form)) ! 407: then (return (cdar lbs))))) ! 408: then (if (not (eq labs g-labs)) ! 409: then (comp-note g-fname ": non local go used : " ! 410: (or v-form))) ! 411: ; three stack to pop: namestack, bindstack ! 412: ; and execution stack ! 413: (e-pop locals) ! 414: (if (greaterp specials 0) ! 415: then (e-unshallowbind specials)) ! 416: (if (greaterp catcherrset 0) ! 417: then (comp-note g-fname ! 418: ": Go through a catch or errset " ! 419: v-form) ! 420: (do ((i 0 (1+ i))) ! 421: ((=& catcherrset i)) ! 422: (d-popframe))) ! 423: (e-goto label) ! 424: (return))) ! 425: ; tally all locals, specials and catcherrsets used in this frame ! 426: (do () ! 427: ((dtpr (car locs)) ! 428: (if (eq 'catcherrset (caar locs)) ! 429: then (incr catcherrset) ! 430: elseif (eq 'progv (caar locs)) ! 431: then (comp-err "Attempt to 'go' through a progv")) ! 432: (setq specials (+ specials (cdar locs)) ! 433: locs (cdr locs))) ! 434: (setq locs (cdr locs)) ! 435: (incr locals)))) ! 436: ! 437: ;--- cc-ignore :: just ignore this code ! 438: ; ! 439: (defun cc-ignore nil ! 440: nil) ! 441: ! 442: ;--- c-lambexp :: compile a lambda expression ! 443: ; ! 444: (defun c-lambexp nil ! 445: (let ((g-loc (if (or g-loc g-cc) then 'reg)) ! 446: (g-cc nil) ! 447: (g-locs (cons (cons 'lambda 0) g-locs)) ! 448: (g-labs (cons nil g-labs))) ! 449: (d-pushargs (cdr v-form)) ; then push vals ! 450: (d-lambbody (car v-form)) ! 451: (d-clearreg))) ! 452: ! 453: ;--- d-lambbody :: do a lambda body ! 454: ; - body : body of lambda expression, eg (lambda () dld) ! 455: ; ! 456: (defun d-lambbody (body) ! 457: (let ((g-decls g-decls)) ! 458: (d-scanfordecls (cddr body)) ; look for declarations ! 459: (d-bindlamb (cadr body)) ; bind locals ! 460: (d-clearreg) ! 461: (d-exp (do ((ll (cddr body) (cdr ll)) ! 462: (g-loc) ! 463: (g-cc) ! 464: (g-ret)) ! 465: ((null (cdr ll)) (car ll)) ! 466: (d-exp (car ll)))) ! 467: ! 468: (d-unbind))) ; unbind this frame ! 469: ! 470: ;--- d-bindlamb :: bind variables in lambda list ! 471: ; - vrbs : list of lambda variables, may include nil meaning ignore ! 472: ; ! 473: (defun d-bindlamb (vrbs) ! 474: (let ((res (d-bindlrec (reverse vrbs) g-locs 0 g-loccnt))) ! 475: (if res then (e-setupbind) ! 476: (mapc '(lambda (vrb) (e-shallowbind (car vrb) (cdr vrb))) ! 477: res) ! 478: (e-unsetupbind)))) ! 479: ! 480: ;--- d-bindlrec :: recusive routine to bind lambda variables ! 481: ; - vrb : list of variables yet to bind ! 482: ; - locs : current location in g-loc ! 483: ; - specs : number of specials seen so far ! 484: ; - lev : how far up from the bottom of stack we are. ! 485: ; returns: list of elements, one for each special, of this form: ! 486: ; (<specialvrbname> stack <n>) ! 487: ; where specialvrbname is the name of the special variable, and n is ! 488: ; the distance from the top of the stack where its initial value is ! 489: ; located ! 490: ; also: puts the names of the local variables in the g-locs list, as well ! 491: ; as placing the number of special variables in the lambda header. ! 492: ; ! 493: (defun d-bindlrec (vrb locs specs lev) ! 494: (if vrb ! 495: then (let ((spcflg (d-specialp (car vrb))) ! 496: retv) ! 497: (if spcflg then (setq specs (1+ specs))) ! 498: ! 499: (if (cdr vrb) ; if more vrbls to go ... ! 500: then (setq retv (d-bindlrec (cdr vrb) ! 501: (cdr locs) ! 502: specs ! 503: (1- lev))) ! 504: else (rplacd (cadr locs) ! 505: specs)) ; else fix up lambda hdr ! 506: ! 507: (if (not spcflg) then (rplaca locs (car vrb)) ! 508: else (Push retv `(,(car vrb) stack ,lev))) ! 509: ! 510: retv))) ! 511: ! 512: ;--- d-scanfordecls ! 513: ; forms - the body of a lambda, prog or do. ! 514: ; we look down the form for 'declare' forms. They should be at the ! 515: ; beginning, but there are macros which may unintentionally put forms ! 516: ; in front of user written forms. Thus we check a little further than ! 517: ; the first form. ! 518: (defun d-scanfordecls (forms) ! 519: ; look for declarations in the first few forms ! 520: (do ((count 3 (1- count))) ! 521: ((= 0 count)) ! 522: (cond ((and (dtpr (car forms)) ! 523: (eq 'declare (caar forms)) ! 524: (apply 'liszt-declare (cdar forms))))) ! 525: (setq forms (cdr forms)))) ! 526: ! 527: ;--- c-list :: compile a list expression ! 528: ; ! 529: ; this is compiled as a bunch of conses with a nil pushed on the ! 530: ; top for good measure ! 531: ; ! 532: (defun c-list nil ! 533: (prog (nargs) ! 534: (setq nargs (length (cdr v-form))) ! 535: (makecomment '(list expression)) ! 536: (if (zerop nargs) ! 537: then (d-move 'Nil 'reg) ; (list) ==> nil ! 538: (return)) ! 539: (d-pushargs (cdr v-form)) ! 540: #+(or for-vax for-tahoe) (e-write2 'clrl '#.np-plus) ; stack one nil ! 541: #+for-68k (L-push (e-cvt 'Nil)) ! 542: ! 543: ; now do the consing ! 544: (do ((i (max 1 nargs) (1- i))) ! 545: ((zerop i)) ! 546: (e-quick-call '_qcons) ! 547: (d-clearreg) ! 548: (if (> i 1) then (L-push (e-cvt 'reg)))) ! 549: ! 550: (setq g-locs (nthcdr nargs g-locs) ! 551: g-loccnt (- g-loccnt nargs)))) ! 552: ! 553: ;--- d-mapconvert - access : function to access parts of lists ! 554: ; - join : function to join results ! 555: ; - resu : function to apply to result ! 556: ; - form : mapping form ! 557: ; This function converts maps to an equivalent do form. ! 558: ; ! 559: ; in this function, the variable vrbls contains a list of forms, one form ! 560: ; per list we are mapping over. The form of the form is ! 561: ; (dummyvariable realarg (cdr dummyvariable)) ! 562: ; realarg may be surrounded by (setq <variable which holds result> realarg) ! 563: ; in the case that the result is the list to be mapped over (this only occurs ! 564: ; with the function mapc). ! 565: ; ! 566: (defun d-mapconvert (access join resu form ) ! 567: (prog (vrbls finvar acc accform compform ! 568: tmp testform tempvar lastvar) ! 569: ! 570: (setq finvar (gensym 'X) ; holds result ! 571: ! 572: vrbls ! 573: (reverse ! 574: (maplist '(lambda (arg) ! 575: ((lambda (temp) ! 576: (cond ((or resu (cdr arg)) ! 577: `(,temp ,(car arg) ! 578: (cdr ,temp))) ! 579: (t `(,temp ! 580: (setq ,finvar ! 581: ,(car arg)) ! 582: (cdr ,temp))))) ! 583: (gensym 'X))) ! 584: (reverse (cdr form)))) ! 585: ! 586: ; the access form will either be nil or car. If it is ! 587: ; nil, then we are doing something like a maplist, ! 588: ; if the access form is car, then we are doing something ! 589: ; like a mapcar. ! 590: acc (mapcar '(lambda (tem) ! 591: (cond (access `(,access ,(car tem))) ! 592: (t (car tem)))) ! 593: vrbls) ! 594: ! 595: accform (cond ((or (atom (setq tmp (car form))) ! 596: (null (setq tmp (d-macroexpand tmp))) ! 597: (not (member (car tmp) '(quote function)))) ! 598: `(funcall ,tmp ,@acc)) ! 599: (t `(,(cadr tmp) ,@acc))) ! 600: ! 601: ; the testform checks if any of the lists we are mapping ! 602: ; over is nil, in which case we quit. ! 603: testform (cond ((null (cdr vrbls)) `(null ,(caar vrbls))) ! 604: (t `(or ,@(mapcar '(lambda (x) ! 605: `(null ,(car x))) ! 606: vrbls))))) ! 607: ! 608: ; in the case of mapcans and mapcons, you need two ! 609: ; extra variables to simulate the nconc. ! 610: ; testvar gets intermediate results and lastvar ! 611: ; points to then end of the list ! 612: (if (eq join 'nconc) ! 613: then (setq tempvar (gensym 'X) ! 614: lastvar (gensym 'X) ! 615: vrbls `((,tempvar) (,lastvar) ,@vrbls))) ! 616: ! 617: (return ! 618: `((lambda ! 619: (,finvar) ! 620: (liszt-internal-do ! 621: ( ,@vrbls) ! 622: (,testform) ! 623: ,(cond ((eq join 'nconc) ! 624: `(cond ((setq ,tempvar ,accform) ! 625: (cond (,lastvar ! 626: (liszt-internal-do ! 627: () ! 628: ((null (cdr ,lastvar))) ! 629: (setq ,lastvar ! 630: (cdr ,lastvar))) ! 631: (rplacd ,lastvar ,tempvar)) ! 632: (t (setq ,finvar ! 633: (setq ,lastvar ! 634: ,tempvar))))))) ! 635: (join `(setq ,finvar (,join ,accform ,finvar))) ! 636: (t accform))) ! 637: ,(cond ((eq resu 'identity) finvar) ! 638: (resu `(,resu ,finvar)) ! 639: (t finvar))) ! 640: nil )))) ! 641: ! 642: ; apply to successive elements, return second arg ! 643: (defun cm-mapc nil ! 644: (d-mapconvert 'car nil nil (cdr v-form))) ! 645: ! 646: ; apply to successive elements, return list of results ! 647: (defun cm-mapcar nil ! 648: (d-mapconvert 'car 'cons 'nreverse (cdr v-form))) ! 649: ! 650: ; apply to successive elements, returned nconc of results ! 651: (defun cm-mapcan nil ! 652: (d-mapconvert 'car 'nconc 'identity (cdr v-form))) ! 653: ! 654: ; apply to successive sublists, return second arg ! 655: (defun cm-map nil ! 656: (d-mapconvert nil nil nil (cdr v-form))) ! 657: ! 658: ; apply to successive sublists, return list of results ! 659: (defun cm-maplist nil ! 660: (d-mapconvert nil 'cons 'reverse (cdr v-form))) ! 661: ! 662: ; apply to successive sublists, return nconc of results ! 663: (defun cm-mapcon nil ! 664: (d-mapconvert nil 'nconc 'identity (cdr v-form))) ! 665: ! 666: ;--- cc-memq :: compile a memq expression ! 667: ; ! 668: #+(or for-vax for-tahoe) ! 669: (defun cc-memq nil ! 670: (let ((loc1 (d-simple (cadr v-form))) ! 671: (loc2 (d-simple (caddr v-form))) ! 672: looploc finlab) ! 673: (if loc2 ! 674: then (d-clearreg 'r1) ! 675: (if loc1 ! 676: then (d-move loc1 'r1) ! 677: else (let ((g-loc 'r1) ! 678: g-cc ! 679: g-ret) ! 680: (d-exp (cadr v-form)))) ! 681: (d-move loc2 'reg) ! 682: else (let ((g-loc 'stack) ! 683: g-cc ! 684: g-ret) ! 685: (d-exp (cadr v-form))) ! 686: (push nil g-locs) ! 687: (incr g-loccnt) ! 688: (let ((g-loc 'reg) ! 689: g-cc ! 690: g-ret) ! 691: (d-exp (caddr v-form))) ! 692: (L-pop 'r1) ! 693: (d-clearreg 'r1) ! 694: (unpush g-locs) ! 695: (decr g-loccnt)) ! 696: ; now set up the jump addresses ! 697: (if (null g-loc) ! 698: then (setq loc1 (if (car g-cc) thenret else (d-genlab)) ! 699: loc2 (if (cdr g-cc) thenret else (d-genlab))) ! 700: else (setq loc1 (d-genlab) ! 701: loc2 (d-genlab))) ! 702: ! 703: (setq looploc (d-genlab)) ! 704: (e-tst 'r0) ! 705: (e-write2 'jeql loc2) ! 706: (e-label looploc) ! 707: (e-cmp 'r1 '(4 r0)) ! 708: (e-write2 'jeql loc1) ! 709: (e-move '(0 r0) 'r0) ! 710: (e-write2 'jneq looploc) ! 711: (if g-loc ! 712: then (e-label loc2) ; nil result ! 713: (d-move 'reg g-loc) ! 714: (if (cdr g-cc) ! 715: then (e-goto (cdr g-cc)) ! 716: else (e-goto (setq finlab (d-genlab)))) ! 717: else (if (cdr g-cc) ! 718: then (e-goto (cdr g-cc)) ! 719: else (e-label loc2))) ! 720: (if g-loc ! 721: then (e-label loc1) ; non nil result ! 722: (d-move 'reg g-loc) ! 723: (if (car g-cc) then (e-goto (car g-cc))) ! 724: else (if (null (car g-cc)) then (e-label loc1))) ! 725: (if finlab then (e-label finlab)))) ! 726: ! 727: #+for-68k ! 728: (defun cc-memq nil ! 729: (let ((loc1 (d-simple (cadr v-form))) ! 730: (loc2 (d-simple (caddr v-form))) ! 731: looploc finlab ! 732: (tmp-data-reg (d-alloc-register 'd nil))) ! 733: (d-clearreg tmp-data-reg) ! 734: (d-clearreg 'a0) ! 735: (if loc2 ! 736: then (if loc1 ! 737: then (d-move loc1 tmp-data-reg) ! 738: else (let ((g-loc tmp-data-reg) ! 739: g-cc ! 740: g-ret) ! 741: (d-exp (cadr v-form)))) ! 742: (d-move loc2 'reg) ! 743: else (let ((g-loc 'stack) ! 744: g-cc ! 745: g-ret) ! 746: (d-exp (cadr v-form))) ! 747: (push nil g-locs) ! 748: (incr g-loccnt) ! 749: (let ((g-loc 'reg) ! 750: g-cc ! 751: g-ret) ! 752: (d-exp (caddr v-form))) ! 753: (L-pop tmp-data-reg) ! 754: (unpush g-locs) ! 755: (decr g-loccnt)) ! 756: ; now set up the jump addresses ! 757: (if (null g-loc) ! 758: then (setq loc1 (if (car g-cc) thenret else (d-genlab)) ! 759: loc2 (if (cdr g-cc) thenret else (d-genlab))) ! 760: else (setq loc1 (d-genlab) ! 761: loc2 (d-genlab))) ! 762: (setq looploc (d-genlab)) ! 763: (e-cmpnil 'd0) ! 764: (e-write2 'jeq loc2) ! 765: (e-move 'd0 'a0) ! 766: (e-label looploc) ! 767: (e-cmp tmp-data-reg '(4 a0)) ! 768: (e-write2 'jeq loc1) ! 769: (e-move '(0 a0) 'a0) ! 770: (e-cmpnil 'a0) ! 771: (e-write2 'jne looploc) ! 772: (e-move 'a0 'd0) ! 773: (if g-loc ! 774: then (e-label loc2) ; nil result ! 775: (d-move 'reg g-loc) ! 776: (if (cdr g-cc) ! 777: then (e-goto (cdr g-cc)) ! 778: else (e-goto (setq finlab (d-genlab)))) ! 779: else (if (cdr g-cc) ! 780: then (e-goto (cdr g-cc)) ! 781: else (e-label loc2))) ! 782: (if g-loc ! 783: then (e-label loc1) ; non nil result ! 784: (d-move 'a0 g-loc) ;a0 was cdr of non-nil result ! 785: (if (car g-cc) then (e-goto (car g-cc))) ! 786: else (if (null (car g-cc)) then (e-label loc1))) ! 787: (if finlab then (e-label finlab))))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.