|
|
1.1 ! root 1: (* Copyright 1989 by AT&T Bell Laboratories *) ! 2: (* structure Opt: extended by NICK, to add a new lambda-lifting function, ! 3: bareCloseTop, a more general form of closeTop. *) ! 4: ! 5: structure CGoptions = System.Control.CG ! 6: ! 7: signature OPT = ! 8: sig ! 9: structure L : LAMBDA sharing L=Lambda ! 10: structure A : ACCESS sharing A=Access ! 11: val reduce : L.lexp -> L.lexp ! 12: exception BadSwitch ! 13: val switch : L.lexp -> L.lexp ! 14: val hoist : L.lexp -> L.lexp ! 15: val closestr : (int -> string) * L.lexp * int list -> L.lexp ! 16: val bareCloseTop: ! 17: {lambda: L.lexp, looker: int, extras: int list, keepFree: int list} -> L.lexp ! 18: (* bareCloseTop is a more general form of closetop. It is passed an already ! 19: existing looker lvar, and also a keepFree list of lvars which it must ! 20: keep free (they'll be abstracted later). *) ! 21: ! 22: val closetop : L.lexp * int list -> L.lexp ! 23: val closeModDecl: L.lexp * A.lvar list * int list -> L.lexp ! 24: (* closeModDecl will be obselete when I finish the new moduleComp, but I'll ! 25: keep it here for the old moduleComp. *) ! 26: exception Freevars ! 27: val free : L.lexp -> A.lvar -> A.lvar list ! 28: val mix0free : L.lexp -> A.lvar -> A.lvar list * A.lvar list ! 29: val alphaConvert : L.lexp -> L.lexp ! 30: val mapfree : (A.lvar -> L.lexp) -> (L.lexp -> L.lexp) ! 31: val pure : L.lexp -> bool ! 32: end ! 33: ! 34: structure Opt : OPT = ! 35: struct ! 36: ! 37: structure A : ACCESS = Access ! 38: structure L : LAMBDA = Lambda ! 39: ! 40: open A Basics L ! 41: ! 42: fun root [v] = v | root (_::p) = root p ! 43: | root _ = ErrorMsg.impossible "root [] in codegen/opt"; ! 44: ! 45: exception Freevars ! 46: ! 47: fun mapfree lookfree = ! 48: let val m = Intmap.new(32, Freevars) : lexp Intmap.intmap ! 49: val add = Intmap.add m ! 50: fun look v = Intmap.map m v ! 51: handle Freevars => ! 52: let val x = lookfree v in add(v,x); x end ! 53: fun copycon (DATAcon(DATACON{rep=(VARIABLE(Access.PATH p)),const,name,typ,sign})) = ! 54: let fun f [v] = let val VAR w = look v in [w] end ! 55: | f (i::r) = i::(f r) ! 56: in DATAcon(DATACON{rep=(VARIABLE (Access.PATH(f p))),const=const, ! 57: name=name,typ=typ,sign=sign}) ! 58: end ! 59: | copycon c = c ! 60: fun newvar v = let val w = dupLvar v in add(v,VAR w); w end ! 61: val rec f = ! 62: fn VAR v => look v ! 63: | FN(v,b) => FN(newvar v, f b) ! 64: | FIX(vl,el,b) => FIX(map newvar vl, map f el, f b) ! 65: | APP(a,b) => APP(f a, f b) ! 66: | SELECT(i,a) => SELECT(i, f a) ! 67: | RECORD l => RECORD(map f l) ! 68: | SWITCH(a, l, SOME d) => ! 69: SWITCH(f a, map(fn(c,x)=>(copycon c, f x))l, SOME(f d)) ! 70: | SWITCH(a, l, NONE) => ! 71: SWITCH(f a,map(fn(c,x)=>(copycon c, f x))l,NONE) ! 72: | HANDLE(a,b) => HANDLE(f a, f b) ! 73: | RAISE x => RAISE(f x) ! 74: | e as INT _ => e ! 75: | e as STRING _ => e ! 76: | e as REAL _ => e ! 77: | e as PRIM _ => e ! 78: in f ! 79: end ! 80: ! 81: val alphaConvert = mapfree VAR ! 82: ! 83: val simple = fn VAR _ => true ! 84: | RECORD [] => true ! 85: | INT _ => true ! 86: | STRING s => size s = 1 ! 87: | _ => false ! 88: ! 89: fun all f = not o (exists (not o f)) ! 90: ! 91: val rec pure = ! 92: fn VAR _ => true ! 93: | APP(FN(_,a),b) => pure a andalso pure b ! 94: | FIX(vl,el,b) => pure b ! 95: | APP(PRIM P.callcc, FN(_,b)) => pure b ! 96: | APP(PRIM i, z) => Prim.pure i andalso pure z ! 97: | FN _ => true ! 98: | INT _ => true ! 99: | REAL _ => true ! 100: | PRIM _ => true ! 101: | STRING _ => true ! 102: | SELECT(_, x) => pure x ! 103: | RECORD l => all pure l ! 104: | SWITCH(a, l, NONE) => pure a andalso all (pure o #2) l ! 105: | SWITCH(a, l, SOME d) => pure a andalso pure d andalso ! 106: all (pure o #2) l ! 107: | _ => false ! 108: ! 109: exception BadSwitch ! 110: ! 111: fun testint i = fn INTcon j => i=j ! 112: | DATAcon(DATACON{rep=(CONSTANT j),...}) => i=j ! 113: | STRINGcon j => size j = 1 andalso i = ord j ! 114: | DATAcon(DATACON{rep=(TRANSU),...}) => true ! 115: | _ => false ! 116: val testboxed = fn DATAcon(DATACON{rep=(TRANSB),...}) => true ! 117: | DATAcon(DATACON{rep=(TRANSPARENT),...}) => true ! 118: | DATAcon(DATACON{rep=(TAGGED j),...}) => raise BadSwitch ! 119: | DATAcon(DATACON{rep=(VARIABLE j),...}) => raise BadSwitch ! 120: | _ => false ! 121: fun testtag i = fn DATAcon(DATACON{rep=(TRANSB),...}) => true ! 122: | DATAcon(DATACON{rep=(TRANSPARENT),...}) => true ! 123: | DATAcon(DATACON{rep=(TAGGED j),...}) => i=j ! 124: | _ => false ! 125: fun teststring s = fn STRINGcon j => s=j ! 126: | _ => false ! 127: ! 128: fun switch(SWITCH(e,l,d)) = ! 129: let val test = case e ! 130: of INT i => testint i ! 131: | STRING s => if size s = 1 then testint(ord s) ! 132: else teststring s ! 133: | RECORD[_,INT i] => testtag i ! 134: | RECORD [] => testtag 0 ! 135: | RECORD _ => testboxed ! 136: | FN _ => testboxed ! 137: | FIX _ => testboxed ! 138: | REAL _ => testboxed ! 139: | _ => raise BadSwitch ! 140: fun f ((c,x)::r) = if test c then x else f r ! 141: | f [] = case d ! 142: of SOME z => z ! 143: | NONE => ErrorMsg.impossible "no default" ! 144: in f l ! 145: end ! 146: ! 147: fun reduce exp = ! 148: let val clicked = ref false ! 149: fun click() = clicked := true ! 150: exception Reducemap ! 151: val t = Intmap.new(32, Reducemap) : lexp Intmap.intmap ! 152: val set = Intmap.add t ! 153: val set = fn x as (v, VAR w) => (sameName(v,w); set x) ! 154: | x => set x ! 155: val unset = Intmap.rem t ! 156: val imap = Intmap.map t ! 157: val s = Intset.new() ! 158: val mark = Intset.add s ! 159: val marked = Intset.mem s ! 160: fun mapvar v = (imap v handle Reducemap => VAR v) ! 161: fun makp [v] = ((case imap v of VAR w => makp[w] ! 162: | _ => (mark v; [v])) ! 163: handle Reducemap => (mark v; [v])) ! 164: | makp (i::p) = i :: makp p ! 165: val rec makcon = ! 166: fn (DATAcon(DATACON{rep=(VARIABLE(PATH p)), ! 167: name,const,typ,sign}), e) => ! 168: (DATAcon(DATACON{rep=(VARIABLE(PATH(makp p))), ! 169: name=name,const=const,typ=typ,sign=sign}), ! 170: mak e) ! 171: | (c,e) => (c, mak e) ! 172: and mak = ! 173: fn FN(v,b as APP(l,VAR w)) => ! 174: if v=w andalso pure l ! 175: then let val body = mak l ! 176: in if marked v then FN(v,mak(APP(body,VAR v))) ! 177: else (click(); body) ! 178: end ! 179: else FN(v, mak b) ! 180: | APP(FN(v, sw as SWITCH(VAR v',l,d)), e) => ! 181: if v=v' then ! 182: let val e' = mak e ! 183: val _ = set(v,e') ! 184: in let val sw' = mak(switch(SWITCH(e',l,d))) ! 185: val _ = unset v ! 186: in if marked v orelse not (pure e') ! 187: then APP(FN(v,sw'),e') else (click(); sw') ! 188: end ! 189: handle BadSwitch => ! 190: let val l' = map makcon l ! 191: val d' = case d of NONE => NONE | SOME a => SOME(mak a) ! 192: val _ = unset v ! 193: in if marked v then APP(FN (v, SWITCH(VAR v, l', d')), e') ! 194: else (click(); SWITCH(e', l', d')) ! 195: end ! 196: end ! 197: else let val arg = mak e ! 198: val body = (set(v, arg); mak sw before unset v) ! 199: in if marked v orelse not(pure arg) ! 200: then APP(FN(v,body),arg) ! 201: else (click(); body) ! 202: end ! 203: | APP(FN(v,e'),e) => ! 204: let val arg = mak e ! 205: val body = (set(v, arg); mak e' before unset v) ! 206: in if marked v orelse not(pure arg) ! 207: then APP(FN(v,body),arg) ! 208: else (click(); body) ! 209: end ! 210: | FIX([],[],b) => (click(); mak b) ! 211: | FIX(vl,el,b) => FIX(vl,map (fn FN(v,e) => FN(v,mak e)) el,mak b) ! 212: | e as VAR v => (let val e' = imap v ! 213: in if simple e' then (click(); mak e') ! 214: else (mark v; e) ! 215: end handle Reducemap => (mark v; e)) ! 216: | e as SELECT(i, VAR v) => ! 217: ((case imap v ! 218: of RECORD l => ! 219: let val e' = nth(l,i) ! 220: in if simple e' then (click(); e') ! 221: else (mark v; e) ! 222: end ! 223: | ew as VAR w => mak(SELECT(i,ew)) ! 224: | _ => (mark v; e)) ! 225: handle Reducemap => (mark v; e)) ! 226: | FN (w,b) => FN(w,mak b) ! 227: | APP (f,a) => APP(mak f, mak a) ! 228: | SWITCH(e,l,d) => ! 229: ((case e ! 230: of VAR v => mak(switch(SWITCH(imap v ! 231: handle Reducemap => raise BadSwitch ! 232: , l, d))) ! 233: | _ => raise BadSwitch ! 234: ) handle BadSwitch => ! 235: let val e' = mak e ! 236: in mak(switch(SWITCH(e', l, d))) ! 237: handle BadSwitch => SWITCH(e', map makcon l, ! 238: case d of NONE => NONE ! 239: | SOME a => SOME(mak a)) ! 240: end) ! 241: | RECORD l => RECORD(map mak l) ! 242: | SELECT (i,e) => SELECT(i,mak e) ! 243: | HANDLE (a,h) => HANDLE(mak a, mak h) ! 244: | RAISE e => RAISE(mak e) ! 245: | e as INT _ => e ! 246: | e as REAL _ => e ! 247: | e as STRING _ => e ! 248: | e as PRIM _ => e ! 249: val exp' = mak exp ! 250: in if !clicked then reduce exp' else exp' ! 251: end ! 252: ! 253: (* minimal hoist function: does not move bindings around, evaluation order ! 254: is unchanged. *) ! 255: fun hoist (FN(v,b)) = FN(v,hoist b) ! 256: | hoist (APP(FN(v,b),f as FN _)) = hoist(FIX([v],[f],b)) ! 257: | hoist (APP(l,r)) = APP(hoist l,hoist r) ! 258: | hoist (FIX(vl,bl,FIX(vs,bs,b))) = hoist(FIX(vl@vs,bl@bs,b)) ! 259: | hoist (FIX(vl,bl,APP(FN(v,b),f as FN _))) = hoist(FIX(v::vl,f::bl,b)) ! 260: | hoist (FIX(vl,bl,b)) = FIX(vl,map hoist bl, hoist b) ! 261: | hoist (SWITCH(e,l,d)) = ! 262: SWITCH(hoist e, map (fn (c,e) => (c, hoist e)) l, ! 263: case d of NONE => NONE ! 264: | SOME a => SOME(hoist a)) ! 265: | hoist (RECORD l) = RECORD(map hoist l) ! 266: | hoist (SELECT (i,e)) = SELECT(i,hoist e) ! 267: | hoist (RAISE e) = RAISE(hoist e) ! 268: | hoist (HANDLE (a,h)) = HANDLE(hoist a, hoist h) ! 269: | hoist x = x ! 270: ! 271: fun freevars e = ! 272: let val t = Intset.new() ! 273: val set = Intset.add t ! 274: val unset = Intset.rem t ! 275: val done = Intset.mem t ! 276: val free : int list ref = ref [] ! 277: val rec mak = ! 278: fn VAR w => if done w then () else (set w; free := w :: !free) ! 279: | FN (w,b) => (set w; mak b; unset w) ! 280: | FIX (vl,el,b) => (app set vl; app mak (b::el); app unset vl) ! 281: | APP (f,a) => (mak f; mak a) ! 282: | SWITCH(e,l,d) => ! 283: (mak e; ! 284: app (fn (DATAcon(DATACON{rep=(VARIABLE(PATH p)),...}),e) => ! 285: (mak(VAR(root p)); mak e) ! 286: | (c,e) => mak e) ! 287: l; ! 288: case d of NONE => () | SOME a => mak a) ! 289: | RECORD l => app mak l ! 290: | SELECT (i,e) => mak e ! 291: | HANDLE (a,h) => (mak a; mak h) ! 292: | RAISE e => mak e ! 293: | INT _ => () ! 294: | REAL _ => () ! 295: | STRING _ => () ! 296: | PRIM _ => () ! 297: in mak e; !free ! 298: end ! 299: ! 300: local val save = (!saveLvarNames before saveLvarNames := true) ! 301: in ! 302: val boot_zero = namedLvar(Symbol.symbol "boot_zero") (* receives unit *) ! 303: val boot_one = namedLvar(Symbol.symbol "boot_one") (* traverses free list *) ! 304: val boot_two = namedLvar(Symbol.symbol "boot_two") (* final bogus arg *) ! 305: ! 306: val (lookLvar, indexerLvar) = ! 307: (saveLvarNames := save; ! 308: (namedLvar(Symbol.symbol "lookup"), ! 309: namedLvar(Symbol.symbol "indexer")) ! 310: ) ! 311: end ! 312: ! 313: fun closestr(lookup: int->string, e:lexp, extras : int list) : lexp = ! 314: let val fv = extras @ freevars e ! 315: val names = map lookup fv ! 316: in if !ErrorMsg.debugging ! 317: then app (fn s => (print s; print " ")) names ! 318: else (); ! 319: FN(dupLvar boot_zero, ! 320: RECORD ! 321: [fold (fn (v,f) => ! 322: let val w = dupLvar boot_one ! 323: in FN(w,APP(FN(v,APP(f,SELECT(1,(VAR w)))), ! 324: SELECT(0,(VAR w)))) ! 325: end) ! 326: fv ! 327: (FN(dupLvar boot_two,e)), ! 328: fold (fn (s,f) => RECORD[STRING s, f]) ! 329: names ! 330: (RECORD [])]) ! 331: end ! 332: ! 333: fun remove(v :: vs: int list, from: int list) = ! 334: let ! 335: fun removeV(x :: xs) = if x=v then xs else x :: removeV xs ! 336: | removeV [] = [] ! 337: in ! 338: remove(vs, removeV from) ! 339: end ! 340: | remove([], from) = from ! 341: ! 342: fun bareCloseTop{lambda, looker, extras, keepFree} = ! 343: let ! 344: val fv = extras @ freevars lambda (* Free vars plus extras *) ! 345: val fv' = remove(keepFree, fv) (* The ones we actually abstract *) ! 346: in ! 347: FN(looker, ! 348: fold (fn (v, f) => APP(FN(v, f), APP(VAR looker, INT v))) ! 349: fv' lambda ! 350: ) ! 351: end ! 352: ! 353: (*** ! 354: val bareCloseTop = ! 355: fn (args as {lambda, looker, extras, keepFree}) => ! 356: (print(implode ["bareCloseTop: looker=", ! 357: Integer.makestring looker, ! 358: ", extras=[ ", ! 359: fold (fn (i, s) => makestring i ^ " " ^ s) extras "]", ! 360: ", keepFree=[ ", ! 361: fold (fn (i, s) => makestring i ^ " " ^ s) keepFree "]", ! 362: ", lambda:\n" ! 363: ] ! 364: ); ! 365: MCprint.printLexp lambda; ! 366: print ".\n"; ! 367: let val resultLamb = bareCloseTop args ! 368: in ! 369: print "bareCloseTop: result:\n"; ! 370: MCprint.printLexp resultLamb; ! 371: print ".\n"; ! 372: resultLamb ! 373: end ! 374: ) ! 375: ***) ! 376: ! 377: fun closetop(e: lexp, extras: int list): lexp = ! 378: bareCloseTop{lambda=e, looker=dupLvar lookLvar, extras=extras, keepFree=[]} ! 379: ! 380: fun closeModDecl(lambda: lexp, slotLvars: lvar list, extras: int list): lexp = ! 381: let ! 382: val looker = dupLvar lookLvar ! 383: val indexer = dupLvar indexerLvar ! 384: val fv = extras @ freevars lambda ! 385: ! 386: fun findLvarSlot(lvar: lvar, this :: rest, n) = ! 387: if lvar = this then SOME n else findLvarSlot(lvar, rest, n+1) ! 388: | findLvarSlot(_, [], _) = NONE ! 389: ! 390: fun liftVar(freevar, lambda) = ! 391: APP(FN(freevar, lambda), ! 392: case findLvarSlot(freevar, slotLvars, 0) ! 393: of SOME slot => APP(VAR indexer, INT slot) ! 394: | NONE => APP(VAR looker, INT freevar) ! 395: ) ! 396: in ! 397: FN(looker, FN(indexer, fold liftVar fv lambda)) ! 398: end ! 399: ! 400: (* free variable analysis *) ! 401: open SortedList ! 402: ! 403: fun free e = ! 404: let val vars : lvar list Intmap.intmap = Intmap.new(32, Freevars) ! 405: val setvars = Intmap.add vars ! 406: val rec freevars = ! 407: fn PRIM _ => [] ! 408: | VAR w => [w] ! 409: | APP(FN(w,b),a) => rem(w,merge(freevars b, freevars a)) ! 410: | APP(f,a) => merge(freevars f, freevars a) ! 411: | FN(w,b) => let val z = rem(w,freevars b) ! 412: in setvars(w,z); z ! 413: end ! 414: | FIX([],_,b) => freevars b ! 415: | FIX(vl as v::_,el,b) => ! 416: let val z' = foldmerge(map (fn FN(v,a) => rem(v,freevars a)) el) ! 417: val uvl = uniq vl ! 418: val z = remove(uvl, z') ! 419: in setvars(v,z); ! 420: merge(remove(uvl, freevars b), z) ! 421: end ! 422: | SWITCH(e,l,d) => ! 423: let fun freevcon(DATAcon(DATACON{rep=(VARIABLE(Access.PATH p)), ! 424: ...})) = [root p] ! 425: | freevcon _ = [] ! 426: val zz = (case d of ! 427: NONE => freevars e ! 428: | SOME x => merge(freevars e, freevars x)) ! 429: in foldmerge(zz::map(fn(c,e')=>merge(freevcon c, freevars e')) l) ! 430: end ! 431: | RECORD l => foldmerge(map freevars l) ! 432: | SELECT(_,e) => freevars e ! 433: | HANDLE(a,h) => merge(freevars a, freevars h) ! 434: | RAISE e => freevars e ! 435: | INT _ => [] ! 436: | REAL _ => [] ! 437: | STRING _ => [] ! 438: in freevars e; ! 439: Intmap.map vars ! 440: end ! 441: ! 442: fun mix0free e = ! 443: let val vars : (lvar list * lvar list) Intmap.intmap = Intmap.new(32, Freevars) ! 444: val setvars = Intmap.add vars ! 445: val rec freevars = ! 446: fn PRIM _ => ([],[]) ! 447: | VAR w => let val f = [w] in (f,f) end ! 448: | APP(FN(w,b),e as FN(_,_)) => ! 449: let val (fe,_) = freevars e ! 450: val (fb,cb) = freevars b ! 451: in (merge(rem(w,fb),fe),rem(w,cb)) ! 452: end ! 453: | APP(FN(w,b),a) => ! 454: let val (fa,ca) = freevars a ! 455: val (fb,cb) = freevars b ! 456: in (merge(rem(w,fb),fa),merge(rem(w,cb),ca)) ! 457: end ! 458: | APP(f,a) => ! 459: let val (fa,ca) = freevars a ! 460: val (ff,cf) = freevars f ! 461: in (merge(ff,fa),merge(cf,ca)) ! 462: end ! 463: | FN(v,b) => ! 464: let val (f,c) = freevars b ! 465: val fr = (rem(v,f),rem(v,c)) ! 466: in setvars(v,fr); fr ! 467: end ! 468: | FIX([],_,b) => freevars b ! 469: | FIX(vl as v::_,el,b) => ! 470: let val fr as (f,_) = ! 471: fold (fn (x,(f,c)) => (rem(x,f),rem(x,c))) ! 472: vl ! 473: (fold (fn(FN(v,a),(f',c')) => ! 474: let val (f,c) = freevars a ! 475: in (merge(rem(v,f),f'), ! 476: merge(rem(v,c),c')) ! 477: end) ! 478: el ([],[])) ! 479: val (fb,cb) = freevars b ! 480: val uvl = uniq vl ! 481: in setvars(v,fr); (merge(remove(uvl,fb),f),remove(uvl,cb)) ! 482: end ! 483: | SWITCH(e,l,d) => ! 484: let fun freevcon(DATAcon(DATACON{rep=(VARIABLE(Access.PATH p)), ! 485: ...})) = [root p] ! 486: | freevcon _ = [] ! 487: in fold (fn ((con,e'),(f,c)) => ! 488: let val (f',c') = freevars e' ! 489: in (merge(merge(freevcon con, f'),f), ! 490: merge(merge(freevcon con,c'),c)) ! 491: end) ! 492: l ! 493: (let val (fe,ce) = freevars e ! 494: val (fd,cd) = case d of SOME x => freevars x ! 495: | NONE => ([],[]) ! 496: in (merge(fe,fd),merge(ce,cd)) ! 497: end) ! 498: end ! 499: | RECORD l => fold (fn (a,(f,c)) => ! 500: let val (f',c') = freevars a ! 501: in (merge(f,f'),merge(c,c')) ! 502: end) ! 503: l ([],[]) ! 504: | SELECT(_,e) => freevars e ! 505: | HANDLE(a,h) => ! 506: let val (fa,ca) = freevars a ! 507: val (fh,ch) = freevars h ! 508: in (merge(fa,fh),merge(ca,ch)) ! 509: end ! 510: | RAISE e => freevars e ! 511: | INT _ => ([],[]) ! 512: | REAL _ => ([],[]) ! 513: | STRING _ => ([],[]) ! 514: in freevars e; ! 515: Intmap.map vars ! 516: end ! 517: ! 518: ! 519: end (* structure Opt *)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.