|
|
1.1 root 1: (* Copyright 1989 by AT&T Bell Laboratories *)
2: signature MCOPT =
3: sig
4: structure Absyn : BAREABSYN
5: structure Access : ACCESS
6: type rhs
7: val opt : (Absyn.pat list * rhs) list * Access.lvar list ->
8: (Absyn.pat list * rhs) list * Access.lvar list
9: end
10:
11: structure MCopt : MCOPT = struct
12:
13: structure Absyn : BAREABSYN = Absyn
14: structure Lambda : LAMBDA = Lambda
15: structure Access : ACCESS = Access
16: open Basics Absyn Lambda
17: open PrintUtil PrintBasics PrintAbsyn MCprint ErrorMsg
18:
19: type rhs = (Access.lvar * Access.lvar) list * int (* bindings and tag *)
20:
21: fun cons2 (hd::hds,tl::tls) = (hd::tl)::cons2(hds,tls)
22: | cons2 (hd::hds,[]) = [hd]::cons2(hds,[])
23: | cons2 ([],[]) = []
24: | cons2 _ = impossible "cons2 in mcopt"
25:
26: infixr cons2
27:
28: (* take a list of record patterns and return the list
29: of the tail fields of each record pattern *)
30: fun tl2 ([_]::_) = []
31: | tl2 ((_::tl)::pats) = tl::(tl2 pats)
32: | tl2 [] = []
33: | tl2 _ = impossible "tl2 in mcopt"
34:
35: (* take a list of record patterns and return the list
36: of the first field of each record pattern *)
37: fun hd2 ((hd::_)::pats) = hd::(hd2 pats)
38: | hd2 [] = []
39: | hd2 _ = impossible "hd2 in mcopt"
40:
41: fun combine(relf::relfs,irrelf::irrelfs) = (relf@irrelf)::(combine(relfs,irrelfs))
42: | combine([],[]) = []
43: | combine([],irrel) = irrel
44: | combine(rel,[]) = rel
45: fun addtail (fields::pats,rhs::tl) = (fields,rhs)::addtail(pats,tl)
46: | addtail ([],[]) = []
47: | addtail _ = impossible "addtail in mcopt"
48: fun strip ((fields,rhs)::pats) =
49: let val (fl,tl) = strip pats in (fields::fl,rhs::tl) end
50: | strip [] = ([],[])
51:
52: fun branch_factor fs =
53: let fun existsPat f =
54: let val rec ePat =
55: fn [] => false
56: | VARpat _::more => ePat more
57: | WILDpat::more => ePat more
58: | LAYEREDpat (_,p)::more => ePat (p::more)
59: | CONSTRAINTpat (p,_)::more => ePat (p::more)
60: | p::more => (f p orelse ePat more
61: handle Match => impossible "ePat in mcopt")
62: in ePat
63: end
64: fun within(p,plist) =
65: case p
66: of APPpat(DATACON{name=r1,...},_) =>
67: existsPat (fn APPpat(DATACON{name=r2,...},_) => Symbol.eq(r1,r2)
68: | CONpat _ => false) plist
69: | CONpat(DATACON{name=r1,...}) =>
70: existsPat (fn CONpat(DATACON{name=r2,...}) => Symbol.eq(r1,r2)
71: | APPpat _ => false) plist
72: | INTpat i => existsPat (fn INTpat j => i=j) plist
73: | REALpat r => existsPat (fn REALpat s => r=s) plist
74: | STRINGpat s => existsPat (fn STRINGpat t => s=t) plist
75: | VARpat _ => true
76: | WILDpat => true
77: | LAYEREDpat (_,p) => within (p,plist)
78: | CONSTRAINTpat (p,_) => within (p,plist)
79: | _ => impossible "within in mcopt"
80: in length (fold (fn(a::_,b) => if within(a,b) then b else a::b) fs [])
81: end
82:
83: fun arity ((hd::_)::_) =
84: let val rec ar =
85: fn INTpat _ => 1
86: | REALpat _ => 1
87: | STRINGpat _ => 1
88: | VARpat _ => 0
89: | WILDpat => 0
90: | RECORDpat{pats=ref pats,...} => length pats
91: | APPpat (_,p) => 1 + ar p
92: | CONpat _ => 1
93: | LAYEREDpat (_,p) => ar p
94: | CONSTRAINTpat (p,_) => ar p
95: in ar hd
96: end
97: | arity _ = impossible "arity in mcopt"
98:
99: exception Record
100: val rec relevant =
101: fn VARpat _ => false
102: | WILDpat => false (* any var always matches so never relevant *)
103: | RECORDpat{pats=ref [],...} => false (* unit isDCB never relevant *)
104: | RECORDpat _ => raise Record (* otherwise, immediately expand records *)
105: | LAYEREDpat (_,p) => relevant p
106: | CONSTRAINTpat (p,_) => relevant p
107: (* if only one data constructor, no need to test *)
108: | CONpat(DATACON{sign = [_],...}) => false
109: | APPpat(DATACON{sign = [_],...},p) => relevant p
110: | _ => true (* everything else is relevant *)
111:
112: fun rel fs = fold (fn (a::_,b) => if relevant a then b else b+1) fs 0
113:
114: (* a record should be immediately expanded by mcand so that
115: the nested fields can be considered as well;
116: don't bother to look at the rest of the fields,
117: and leave the record at the end of relf.
118: otherwise, just check the relevant.
119: *)
120: local
121: fun r_o([],[],relf,relx,irrelf,irrelx) = (relf,relx,irrelf,irrelx)
122: | r_o(arg as (hd::_)::_,x::xs,relf,relx,irrelf,irrelx) =
123: ((if relevant hd
124: then r_o(tl2 arg,xs,(hd2 arg) cons2 relf,x::relx,irrelf,irrelx)
125: else r_o(tl2 arg,xs,relf,relx,(hd2 arg) cons2 irrelf,x::irrelx))
126: handle Record =>
127: ((hd2 arg) cons2 [],[x],combine(relf,combine(tl2 arg,irrelf)),relx@xs@irrelx))
128: | r_o _ = impossible "r_o in mcopt"
129: in fun rel_order(a,x) = r_o(a,x,[],[],[],[])
130: end
131:
132: local
133: fun gen_order f =
134: let fun order([],[],_,bestf,bestx,otherfs,otherxs) =
135: (bestf,bestx,otherfs,otherxs)
136: | order(argp,x::xs,old,bestf,bestx,otherfs,otherxs) =
137: let val head = hd2 argp
138: val tail = tl2 argp
139: val new = f argp
140: in if Integer.<(new,old)
141: then order(tail,xs,new,head cons2 [],[x],
142: combine(bestf,otherfs),bestx@otherxs)
143: else if new > old
144: then order(tail,xs,old,bestf,bestx,head cons2 otherfs,x::otherxs)
145: else order(tail,xs,old,head cons2 bestf,x::bestx,otherfs,otherxs)
146: end
147: | order _ = impossible "order in mcopt"
148: in fn(a,x::xs) =>
149: let val hd = hd2 a
150: val tl = tl2 a
151: val bestf = hd cons2 []
152: in order(tl,xs,f bestf,bestf,[x],[],[])
153: end
154: end
155: in
156: val relevance_order = gen_order rel
157: val branch_order = gen_order branch_factor
158: val arity_order = gen_order arity
159: end
160:
161: (* OPT: rearrange the fields of a tuple into a better order to evaluate.
162: use the relevant test. if there are no relevant fields,
163: then the first pattern will match - don't bother returning
164: the rest. if one of the fields is a record, return it first
165: so it is expanded. if the relevant test does not isolate
166: one field, use the branch factor test, then the arity test. *)
167:
168: fun opt (arg as ([],_)) = arg
169: | opt (pl as hd::_,xl) =
170: let val (pats,tl) = strip pl
171: val (relf,relx,irrelf,irrelx) = rel_order(pats,xl)
172: in case relf of
173: [] => ([hd],xl)
174: | [_]::_ => (addtail(combine(relf,irrelf),tl),relx@irrelx)
175: | _ =>
176: let val (rf,rx,irf,irx) = relevance_order(relf,relx)
177: val rrest = combine(irf,irrelf)
178: val rrestx = irx@irrelx
179: in case rf of
180: [_]::_ => (addtail(combine(rf,rrest),tl),rx@rrestx)
181: | _ =>
182: let val (branchf,branchx,branchfs,branchxs) = branch_order(rf,rx)
183: val brest = combine(branchfs,rrest)
184: val brestx = branchxs@rrestx
185: in case branchf of
186: [_]::_ => (addtail(combine(branchf,brest),tl),branchx@brestx)
187: | _ => let val (arityf,arityx,arityfs,arityxs) =
188: arity_order(branchf,branchx)
189: in (addtail(combine(arityf,combine(arityfs,brest)),tl),
190: arityx@arityxs@brestx)
191: end
192: end
193: end
194: end
195:
196: end (* structure MCopt *)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.