Annotation of researchv10no/cmd/sml/src/codegen/opt.sml, revision 1.1.1.1

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 *)

unix.superglobalmegacorp.com

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