Annotation of researchv10no/cmd/sml/src/cps/convert.sml, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.