|
|
1.1 ! root 1: (* Copyright 1989 by AT&T Bell Laboratories *) ! 2: (* notes: ! 3: OFFSET should not be generated by this module ! 4: RECORD fields should contain only empty paths (pure variables) ! 5: *) ! 6: ! 7: (* xgrep '[^a-z]n[^a-z]' cps/convert.sml *) ! 8: structure Convert = ! 9: struct ! 10: ! 11: open CPS Access ! 12: fun sublist test = ! 13: let fun subl(a::r) = if test a then a::(subl r) else subl r ! 14: | subl x = x ! 15: in subl ! 16: end ! 17: ! 18: local open Lambda Basics ! 19: in ! 20: fun translatepath [v] = VAR v ! 21: | translatepath (x::p) = SELECT(x,translatepath p) ! 22: | translatepath nil = ErrorMsg.impossible "convert.translatepath nil" ! 23: ! 24: fun isboxedRep(CONSTANT _) = false ! 25: | isboxedRep(TRANSU) = false ! 26: | isboxedRep(_) = true ! 27: ! 28: fun isboxed (DATAcon(DATACON{rep,...})) = isboxedRep(rep) ! 29: | isboxed (REALcon _) = true ! 30: | isboxed (STRINGcon s) = (size s <> 1) ! 31: | isboxed _ = false ! 32: end ! 33: ! 34: fun mk f = f (mkLvar()) ! 35: ! 36: val sortcases = Sort.sort (fn ((i:int,_),(j,_)) => i>j) ! 37: ! 38: val calling = ! 39: fn P.boxed => (1,0,2) ! 40: | P.< => (2,0,2) ! 41: | P.<= => (2,0,2) ! 42: | P.> => (2,0,2) ! 43: | P.>= => (2,0,2) ! 44: | P.ieql => (2,0,2) ! 45: | P.ineq => (2,0,2) ! 46: | P.feql => (2,0,2) ! 47: | P.fge => (2,0,2) ! 48: | P.fgt => (2,0,2) ! 49: | P.fle => (2,0,2) ! 50: | P.flt => (2,0,2) ! 51: | P.fneq => (2,0,2) ! 52: | P.gethdlr => (0,1,1) ! 53: | P.* => (2,1,1) ! 54: | P.+ => (2,1,1) ! 55: | P.- => (2,1,1) ! 56: | P.div => (2,1,1) ! 57: | P.orb => (2,1,1) ! 58: | P.andb => (2,1,1) ! 59: | P.xorb => (2,1,1) ! 60: | P.rshift => (2,1,1) ! 61: | P.lshift => (2,1,1) ! 62: | P.fadd => (2,1,1) ! 63: | P.fdiv => (2,1,1) ! 64: | P.fmul => (2,1,1) ! 65: | P.fsub => (2,1,1) ! 66: | P.subscript => (2,1,1) ! 67: | P.ordof => (2,1,1) ! 68: | P.! => (1,1,1) ! 69: | P.alength => (1,1,1) ! 70: | P.fneg => (1,1,1) ! 71: | P.makeref => (1,1,1) ! 72: | P.delay => (2,1,1) ! 73: | P.slength => (1,1,1) ! 74: | P.~ => (1,1,1) ! 75: | P.notb => (1,1,1) ! 76: | P.sethdlr => (1,0,1) ! 77: | P.:= => (2,0,1) ! 78: | P.unboxedassign => (2,0,1) ! 79: | P.store => (3,0,1) ! 80: | P.unboxedupdate => (3,0,1) ! 81: | P.update => (3,0,1) ! 82: | _ => ErrorMsg.impossible "calling with bad primop" ! 83: ! 84: fun nthcdr(l, 0) = l ! 85: | nthcdr(a::r, n) = nthcdr(r, n-1) ! 86: | nthcdr _ = ErrorMsg.impossible "nthcdr in convert" ! 87: ! 88: fun count test = ! 89: let fun subl acc (a::r) = subl(if test a then 1+acc else acc) r ! 90: | subl acc nil = acc ! 91: in subl 0 ! 92: end ! 93: ! 94: fun convert lexp = ! 95: let ! 96: local open Intmap ! 97: val m : const intmap = new(32, Ctable) ! 98: val enter = add m ! 99: in fun bindconst(c,cont) = mk(fn v => (enter(v,c); cont v)) ! 100: val ctable = m ! 101: end ! 102: ! 103: local open Intmap ! 104: exception Rename ! 105: val m : lvar intmap = new(32, Rename) ! 106: val rename = map m ! 107: in fun ren v = rename v handle Rename => v ! 108: val newname = add m ! 109: end ! 110: ! 111: fun switch1(e : lvar, cases : (int*cexp) list, d : lvar, (lo,hi)) = ! 112: let val delta = 2 ! 113: fun collapse (l as (li,ui,ni,xi)::(lj,uj,nj,xj)::r ) = ! 114: if ((ni+nj) * delta > ui-lj) ! 115: then collapse((lj,ui,ni+nj,xj)::r) ! 116: else l ! 117: | collapse l = l ! 118: fun f (z, x as (i,_)::r) = f(collapse((i,i,1,x)::z), r) ! 119: | f (z, nil) = z ! 120: fun tackon (stuff as (l,u,n,x)::r) = ! 121: if n*delta > u-l andalso n>4 andalso hi>u ! 122: then tackon((l,u+1,n+1,x@[(u+1,APP(d,nil))])::r) ! 123: else stuff ! 124: fun separate((z as (l,u,n,x))::r) = ! 125: if n<4 andalso n>1 ! 126: then let val ix as (i,_) = nth(x, (n-1)) ! 127: in (i,i,1,[ix])::separate((l,l,n-1,x)::r) ! 128: end ! 129: else z :: separate r ! 130: | separate nil = nil ! 131: val chunks = rev (separate (tackon (f (nil,cases)))) ! 132: fun g(1,(l,h,1,(i,b)::_)::_,(lo,hi)) = ! 133: if lo=i andalso hi=i then b ! 134: else bindconst(INTconst i, fn i' => ! 135: PRIMOP(P.ineq,[e, i'], nil, [APP(d,nil), b])) ! 136: | g(1,(l,h,n,x)::_,(lo,hi)) = ! 137: let fun f(0,_,_) = nil ! 138: | f(n,i,l as (j,b)::r) = ! 139: if i+lo = j then b::f(n-1,i+1,r) ! 140: else (APP(d,nil))::f(n,i+1,l) ! 141: val list = f(n,0,x) ! 142: val body = if lo=0 then SWITCH(e,list) ! 143: else bindconst(INTconst lo, fn lo' => ! 144: mk(fn e' => ! 145: PRIMOP(P.-,[e, lo'], [e'], ! 146: [SWITCH(e', list)]))) ! 147: val a = if (lo<l) ! 148: then bindconst(INTconst l, fn l' => ! 149: PRIMOP(P.<,[e, l'], nil, [APP(d,nil), body])) ! 150: else body ! 151: val b = if (hi > h) ! 152: then bindconst(INTconst h, fn h' => ! 153: PRIMOP(P.>,[e, h'], nil, [APP(d,nil), a])) ! 154: else a ! 155: in b ! 156: end ! 157: | g(n,cases,(lo,hi)) = ! 158: let val n2 = n div 2 ! 159: val c2 as (l,_,_,_)::r = nthcdr(cases, n2) ! 160: in bindconst(INTconst l, fn l' => ! 161: PRIMOP(P.<,[e,l'],nil, [g(n2,cases,(lo,l-1)), ! 162: g(n-n2,c2,(l,hi))])) ! 163: end ! 164: in g (length chunks, chunks, (lo, hi)) ! 165: end ! 166: ! 167: fun switch(e, l, d, inrange) = ! 168: let val len = List.length l ! 169: val d' = case d of SOME d' => d' | NONE => mkLvar() ! 170: fun ifelse nil = APP(d',nil) ! 171: | ifelse ((i,b)::r) = ! 172: bindconst(INTconst i, fn v => ! 173: PRIMOP(P.ineq,[v, e], nil, [ifelse r, b])) ! 174: fun ifelseN [(i,b)] = b ! 175: | ifelseN ((i,b)::r) = ! 176: bindconst(INTconst i, fn v => ! 177: PRIMOP(P.ineq,[v, e], nil, [ifelseN r, b])) ! 178: | ifelseN _ = ErrorMsg.impossible "convert.224" ! 179: val l = sortcases l ! 180: in case (len<4, inrange) ! 181: of (true, NONE) => ifelse l ! 182: | (true, SOME n) => if n+1=len then ifelseN l else ifelse l ! 183: | (false, NONE) => ! 184: let fun last [x] = x | last (_::r) = last r ! 185: val (hi,_) = last l and (low,_)::r = l ! 186: in bindconst(INTconst low, fn low' => ! 187: bindconst(INTconst hi, fn hi' => ! 188: PRIMOP(P.>,[low', e], nil, [APP(d',[]), ! 189: PRIMOP(P.<,[hi', e], nil, [APP(d',[]), ! 190: switch1(e, l, d', (low,hi))])]))) ! 191: end ! 192: | (false, SOME n) => switch1(e, l, d', (0,n)) ! 193: end ! 194: ! 195: val zero = bindconst(INTconst 0, fn x => x) ! 196: val one = bindconst(INTconst 1, fn x => x) ! 197: val neg1 = bindconst(INTconst ~1, fn x => x) ! 198: val unevaled = bindconst(INTconst (System.Tags.tag_suspension div 2), fn x => x) ! 199: val evaled = bindconst(INTconst((System.Tags.tag_suspension ! 200: +System.Tags.power_tags)div 2), fn x => x) ! 201: ! 202: fun convlist (el,c) = ! 203: let fun f(le::r, vl) = conv(le, fn v => f(r,v::vl)) ! 204: | f(nil, vl) = c (rev vl) ! 205: in f (el,nil) ! 206: end ! 207: ! 208: and getargs(1,a,g) = conv(a, fn z => g[z]) ! 209: | getargs(n,Lambda.RECORD l,g) = convlist(l,g) ! 210: | getargs(n, a, g) = conv(a, fn v => ! 211: let fun f (j,wl) = if j=n ! 212: then g(rev wl) ! 213: else mk(fn w => SELECT(j,v,w,f(j+1,w::wl))) ! 214: in f(0,nil) ! 215: end) ! 216: ! 217: and conv (le, c) = ! 218: case le of ! 219: Lambda.APP(Lambda.PRIM P.callcc, f) => ! 220: let val k = mkLvar() and k' = mkLvar() and k'' = mkLvar() ! 221: and x = mkLvar() and y = mkLvar() and h = mkLvar() ! 222: in FIX([(k,[x],c x)], ! 223: PRIMOP(P.gethdlr,[],[h], ! 224: [FIX([(k',[y,k''],PRIMOP(P.sethdlr,[h],[],[APP(k,[y])]))], ! 225: conv(f, fn vf => APP(vf,[k',k])))])) ! 226: end ! 227: | Lambda.APP(Lambda.PRIM P.throw, k) => conv(k,c) ! 228: | Lambda.APP(Lambda.PRIM P.cast, k) => conv(k,c) ! 229: | Lambda.APP(Lambda.PRIM P.force, k) => ! 230: let val c0=mkLvar() and c0v=mkLvar() and w=mkLvar() and x=mkLvar() ! 231: and y=mkLvar() and c1=mkLvar() and c1v=mkLvar() ! 232: in conv(k, fn v => ! 233: FIX([(c0,[c0v],c c0v)], ! 234: PRIMOP(P.boxed,[v],[],[PRIMOP(P.subscript,[v,neg1],[w],[ ! 235: PRIMOP(P.ieql,[w,evaled],[],[PRIMOP(P.!,[v],[x],[APP(c0,[x])]), ! 236: PRIMOP(P.ineq,[w,unevaled],[],[APP(c0,[v]), ! 237: FIX([(c1,[c1v], ! 238: PRIMOP(P.:=,[v,c1v],[],[ ! 239: PRIMOP(P.update,[v,neg1,evaled],[],[ ! 240: APP(c0,[c1v])])]))], ! 241: PRIMOP(P.!,[v],[y],[APP(y,[zero,c1])]))])])]), ! 242: APP(c0,[v])]))) ! 243: end ! 244: | Lambda.APP(Lambda.PRIM i, a) => ! 245: (case calling i of ! 246: (n,1,1) => getargs(n,a,fn vl => mk(fn w => PRIMOP(i,vl,[w],[c w]))) ! 247: | (n,0,1) => getargs(n,a,fn vl => PRIMOP(i,vl,[],[c zero])) ! 248: | (n,0,2) => getargs(n,a,fn vl => ! 249: let val cv = mkLvar() and v = mkLvar() ! 250: in FIX([(cv,[v],c v)],PRIMOP(i,vl,[],[APP(cv,[one]),APP(cv,[zero])])) ! 251: end)) ! 252: | Lambda.PRIM i => mk(fn v => conv(Lambda.FN(v,Lambda.APP(le,Lambda.VAR v)),c)) ! 253: | Lambda.VAR v => c (ren v) ! 254: | Lambda.APP(Lambda.FN(v,e),a) => ! 255: conv(a, fn w => (newname(v,w);Access.sameName(v,w); conv(e, c))) ! 256: | Lambda.FN (v,e) => let val f = mkLvar() and w = mkLvar() ! 257: in FIX([(f,[v,w],conv(e, fn z => APP(w,[z])))], c f) ! 258: end ! 259: | Lambda.APP (f,a) => ! 260: let val fc = mkLvar() and x = mkLvar() ! 261: in FIX([(fc,[x],c x)], conv(f,fn vf => conv(a,fn va => APP(vf,[va,fc])))) ! 262: end ! 263: | Lambda.FIX (fl, el, body) => ! 264: let fun g(f::fl, Lambda.FN(v,b)::el) = ! 265: mk(fn w => (f,[v,w], conv(b, fn z => APP(w,[z])))) :: g(fl,el) ! 266: | g(nil,nil) = nil ! 267: in FIX(g(fl,el), conv(body,c)) ! 268: end ! 269: | Lambda.INT i => ! 270: ((i+i; bindconst(INTconst i, c)) ! 271: handle Overflow => ! 272: let open Lambda ! 273: in conv(APP(PRIM P.+, RECORD[INT(i div 2), INT(i - i div 2)]),c) ! 274: end) ! 275: | Lambda.REAL i => bindconst(REALconst i, c) ! 276: | Lambda.STRING i => (case size i ! 277: of 1 => bindconst(INTconst(ord i),c) ! 278: | _ => bindconst(STRINGconst i, c)) ! 279: | Lambda.RECORD nil => c zero ! 280: | Lambda.RECORD l => convlist(l,fn vl => mk(fn x => RECORD(recordpath vl,x,c x))) ! 281: | Lambda.SELECT(i, e) => mk(fn w => conv(e, fn v => SELECT(i, v, w, c w))) ! 282: | Lambda.SWITCH(e,l as (Lambda.DATAcon(Basics.DATACON{ ! 283: rep=Basics.VARIABLE _,...}), _)::_, SOME d) => ! 284: let val cf = mkLvar() and vf = mkLvar() ! 285: in FIX([(cf, [vf], c vf)], ! 286: conv(Lambda.SELECT(1,e), fn w => ! 287: let fun g((Lambda.DATAcon(Basics.DATACON{ ! 288: rep=Basics.VARIABLE(Access.PATH p),const=true,...}), x)::r) = ! 289: conv(translatepath(1::p), fn v => ! 290: PRIMOP(P.ineq, [w,v], [], [g r, conv(x, fn z => APP(cf,[z]))])) ! 291: | g((Lambda.DATAcon(Basics.DATACON{ ! 292: rep=Basics.VARIABLE(Access.PATH p),...}), x)::r) = ! 293: conv(translatepath p, fn v => ! 294: PRIMOP(P.ineq, [w,v], [], [g r, conv(x, fn z => APP(cf,[z]))])) ! 295: | g nil = conv(d, fn z => APP(cf,[z])) ! 296: | g _ = ErrorMsg.impossible "convert.21" ! 297: in g l ! 298: end)) ! 299: end ! 300: | Lambda.SWITCH(e,l as (Lambda.REALcon _, _)::_, SOME d) => ! 301: let val cf = mkLvar() and vf = mkLvar() ! 302: in FIX([(cf, [vf], c vf)], ! 303: conv(e, fn w => ! 304: let fun g((Lambda.REALcon rval, x)::r) = ! 305: bindconst(REALconst rval, fn v => ! 306: PRIMOP(P.fneq, [w,v],[], [g r, conv(x,fn z => APP(cf,[z]))])) ! 307: | g nil = conv(d, fn z => APP(cf,[z])) ! 308: | g _ = ErrorMsg.impossible "convert.81" ! 309: in g l ! 310: end)) ! 311: end ! 312: | Lambda.SWITCH(e,l as (Lambda.INTcon _, _)::_, SOME d) => ! 313: let val cf = mkLvar() and vf = mkLvar() and df = mkLvar() ! 314: in FIX([(cf, [vf], c vf), (df, [], conv(d, fn z => APP(cf,[z])))], ! 315: conv(e, fn w => ! 316: let fun g (Lambda.INTcon j, a) = (j,conv(a, fn z => APP(cf,[z]))) ! 317: in switch(w, map g l, SOME df, NONE) ! 318: end)) ! 319: end ! 320: | Lambda.SWITCH(e,l as (Lambda.STRINGcon _, _)::_, SOME d) => ! 321: let val cf = mkLvar() and vf = mkLvar() and df = mkLvar() and vd = mkLvar() ! 322: val cont = fn z => APP(cf,[z]) ! 323: fun isboxed (Lambda.STRINGcon s, _) = size s <> 1 ! 324: val b = sublist isboxed l ! 325: val u = sublist (not o isboxed) l ! 326: fun g(Lambda.STRINGcon j, e) = (ord j, conv(e,cont)) ! 327: val z = map g u ! 328: val [p1,p2] = !CoreInfo.stringequalPath ! 329: in FIX([(cf, [vf], c vf), (df, [], conv(d, cont))], ! 330: conv(e, fn w => ! 331: let val genu = switch(w, z, SOME df, NONE) ! 332: fun genb [] = APP(df,[]) ! 333: | genb cases = ! 334: let val len1 = mkLvar() ! 335: fun g((Lambda.STRINGcon s, x)::r) = ! 336: let val ssize = size s ! 337: val k = mkLvar() and seq = mkLvar() and pair = mkLvar() ! 338: and c2 = mkLvar() and ans = mkLvar() ! 339: in FIX((k,[], g r):: ! 340: if ssize=0 then [] ! 341: else [(c2,[ans],PRIMOP(P.ieql,[ans,zero],[], ! 342: [APP(k,[]), conv(x,cont)]))], ! 343: bindconst(STRINGconst s, fn v => ! 344: bindconst(INTconst ssize, fn len0 => ! 345: bindconst(INTconst((ssize + 3) div 4 - 1), fn len0' => ! 346: PRIMOP(P.ineq,[len0,len1],[], ! 347: [APP(k,[]), ! 348: if ssize=0 then conv(x,cont) ! 349: else SELECT(p1,ren p2,seq, ! 350: RECORD([(w,OFFp 0),(v,OFFp 0)], ! 351: pair, APP(seq,[pair,c2])))]))))) ! 352: end ! 353: | g nil = APP(df, []) ! 354: in PRIMOP(P.slength,[w],[len1], [g cases]) ! 355: end ! 356: in PRIMOP(P.boxed,[w],[],[genb b, genu]) ! 357: end)) ! 358: end ! 359: | Lambda.SWITCH ! 360: (x as (Lambda.APP(Lambda.PRIM i, args), ! 361: [(Lambda.DATAcon(Basics.DATACON{rep=(Basics.CONSTANT c1),...}),e1), ! 362: (Lambda.DATAcon(Basics.DATACON{rep=(Basics.CONSTANT c2),...}),e2)], ! 363: NONE)) => ! 364: let fun g(n,a,b) = ! 365: let val cf = mkLvar() and v = mkLvar() ! 366: val cont = (fn w => APP(cf,[w])) ! 367: in FIX([(cf,[v],c v)], ! 368: getargs(n,args,fn vl => PRIMOP(i,vl,[],[conv(a,cont),conv(b,cont)]))) ! 369: end ! 370: in case (calling i, c1, c2) of ! 371: ((n,0,2), 1, 0) => g(n,e1,e2) ! 372: | ((n,0,2), 0, 1) => g(n,e2,e1) ! 373: | _ => genswitch(x,c) ! 374: end ! 375: | Lambda.SWITCH x => genswitch(x,c) ! 376: | Lambda.RAISE(e) => ! 377: conv(e,fn w => mk(fn h => PRIMOP(P.gethdlr,[],[h],[APP(h,[w])]))) ! 378: | Lambda.HANDLE(a,b) => ! 379: let val h = mkLvar() and vb = mkLvar() and vc = mkLvar() ! 380: and x = mkLvar() and v = mkLvar () ! 381: in FIX([(vc,[x],c x)], ! 382: PRIMOP(P.gethdlr,[],[h], ! 383: [FIX([(vb,[v],PRIMOP(P.sethdlr,[h],[],[conv(b,fn f => APP(f,[v,vc]))]))], ! 384: PRIMOP(P.sethdlr,[vb],[], ! 385: [conv(a, fn va => PRIMOP(P.sethdlr,[h],[], [APP(vc,[va])]))]))])) ! 386: end ! 387: ! 388: and genswitch ((e, l as (Lambda.DATAcon(Basics.DATACON{sign,...}),_)::_, d),c) = ! 389: let val cf = mkLvar() and cv = mkLvar() and df = mkLvar() ! 390: val cont = fn z => APP(cf,[z]) ! 391: val boxed = sublist (isboxed o #1) l ! 392: val unboxed = sublist (not o isboxed o #1) l ! 393: val w = mkLvar() and t = mkLvar() ! 394: fun tag (Lambda.DATAcon(Basics.DATACON{rep=Basics.CONSTANT i,...}), e) = ! 395: (i, conv(e,cont)) ! 396: | tag (Lambda.DATAcon(Basics.DATACON{rep=Basics.TAGGED i,...}), e) = ! 397: (i, conv(e,cont)) ! 398: | tag (c,e) = (0, conv(e,cont)) ! 399: in FIX((cf,[cv],c cv) :: ! 400: case d of NONE => [] | SOME d' => [(df,[],conv(d',cont))], ! 401: conv(e, fn w => ! 402: case (count isboxedRep sign, count (not o isboxedRep) sign) ! 403: of (0, n) => switch(w, map tag l, SOME df, SOME(n-1)) ! 404: | (n, 0) => SELECT(1, w, t, switch(t, map tag l, SOME df, SOME(n-1))) ! 405: | (1, nu) => ! 406: PRIMOP(P.boxed, [w], [], ! 407: [switch(zero, map tag boxed, SOME df, SOME 0), ! 408: switch(w, map tag unboxed, SOME df, SOME(nu-1))]) ! 409: | (nb,nu) => ! 410: PRIMOP(P.boxed, [w], [], ! 411: [SELECT(1,w,t, switch(t, map tag boxed, SOME df, SOME(nb-1))), ! 412: switch(w, map tag unboxed, SOME df, SOME(nu-1))]))) ! 413: end ! 414: val v = mkLvar() and x = mkLvar() and f = mkLvar() ! 415: in ((f, [v,x], conv(lexp, fn w => APP(w,[v,x]))), ctable) ! 416: end ! 417: ! 418: end ! 419:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.