|
|
1.1 root 1: (* Copyright 1989 by AT&T Bell Laboratories *)
2: signature MC = sig
3: structure A : BAREABSYN
4: structure L : LAMBDA
5: val matchCompile : (A.pat * L.lexp) list -> L.lexp
6: val bindCompile : (A.pat * L.lexp) list -> L.lexp
7: end
8:
9: structure MC : MC = struct
10:
11: structure A : BAREABSYN = BareAbsyn
12: structure L : LAMBDA = Lambda
13:
14: open A L
15: open Access Basics ErrorMsg
16:
17: val printDepth = System.Control.Print.printDepth
18:
19: val patsUsed : int list ref = ref []
20: val maybeUsed : int list ref = ref []
21: val results : (lvar * lvar list) list ref = ref []
22:
23: fun mark(taglist,tag : int) =
24: let fun newtag[] = [tag]
25: | newtag(taglist as (t::more)) =
26: if tag = t then taglist
27: else if tag < t then tag :: taglist
28: else t :: newtag more
29: in taglist := newtag (!taglist)
30: end
31:
32: fun unused rules =
33: let fun find([],[],_) = []
34: | find([],_::r,i) = i :: find([],r,i+1)
35: | find(taglist as tag::tags,_::r,i) =
36: if tag = i
37: then find(tags,r,i+1)
38: else i :: find(taglist,r,i+1)
39: | find _ = ErrorMsg.impossible "unused in mc"
40: in find(!patsUsed,rules,0)
41: end
42: fun redundant rules =
43: if length rules = length (!patsUsed) then []
44: else unused rules
45: fun areNotRedundant () =
46: case !maybeUsed of
47: [] => ()
48: | (tag::_) => (mark(patsUsed,tag); maybeUsed := [])
49: fun areRedundant () = maybeUsed := []
50:
51: fun bind(x,v,(bindings,tag)) = ((v,x)::bindings,tag)
52:
53: fun layer (x,CONSTRAINTpat(pat,_),rhs) = layer(x,pat,rhs)
54: | layer (x,VARpat(VALvar{access=LVAR v,...}),rhs) = bind(x,v,rhs)
55: | layer _ = impossible "bad layered pattern in mc"
56:
57: fun convert(bindings,tag) =
58: let val (f,free) = nth(!results,tag)
59: fun order [] = []
60: | order (v::tl) =
61: let fun f [] = ErrorMsg.impossible "convert in translate/mc.sml"
62: | f ((w,z)::tl) = if v=w then z else f tl
63: in f bindings :: order tl
64: end
65: val args = order free
66: in mark(patsUsed,tag); APP(VAR f,RECORD(map VAR args))
67: end
68: fun convertDefault(bindings,tag) =
69: let val (f,free) = nth(!results,tag)
70: fun order [] = []
71: | order (v::tl) =
72: let fun f [] = ErrorMsg.impossible "convertD in translate/mc.sml"
73: | f ((w,z)::tl) = if v=w then z else f tl
74: in f bindings :: order tl
75: end
76: val args = order free
77: in mark(maybeUsed,tag); APP(VAR f,RECORD(map VAR args))
78: end
79:
80: val rec freevars =
81: fn VARpat(VALvar{access=LVAR v,...}) => [v]
82: | RECORDpat{pats=ref pats,...} => SortedList.foldmerge(map freevars pats)
83: | APPpat(_,pat) => freevars pat
84: | CONSTRAINTpat(pat,_) => freevars pat
85: | LAYEREDpat(l,r) => SortedList.merge(freevars l,freevars r)
86: | _ => []
87:
88: fun setup rules =
89: let val arg = mkLvar()
90: fun t(i,(pat,result)::more) =
91: let val (header,r) = t(i+1,more)
92: val record = mkLvar()
93: val returnit = mkLvar()
94: val free = freevars pat
95: fun f(_,[]) = result
96: | f(i,v::tl) = APP(FN(v,f(i+1,tl)),SELECT(i,VAR record))
97: in results := (returnit,free) :: !results;
98: (fn l => header(APP(FN(returnit,l),FN(record,f(0,free)))),
99: (pat,([],i)) :: r)
100: end
101: | t _ = (fn x => x,[])
102: in patsUsed := []; maybeUsed := [];
103: let val (header,r) = t(0,rules)
104: in (fn l => FN(arg,header(APP(l,VAR arg))),r)
105: end
106: end
107:
108: fun bindfields(record,fields,e)=
109: let fun select(i, []) = e
110: | select(i, x::xs) = APP(FN(x,select(i+1,xs)),SELECT(i,VAR record))
111: in select(0,fields)
112: end
113:
114: fun andSwitch x =
115: let
116: fun andS [] = ([],[])
117: | andS ((p::fields,rhs)::more) =
118: (case p of
119: INTpat i =>
120: let val (cases,default) = andS more
121: fun addto ((switch as (INTcon j,pats))::more) =
122: if i = j then ((INTcon i,(fields,rhs)::pats)::more)
123: else switch :: addto more
124: | addto [] = [(INTcon i,(fields,rhs)::default)]
125: | addto _ = impossible "983 type error in match compiler"
126: in (addto cases,default)
127: end
128: | REALpat r =>
129: let val (cases,default) = andS more
130: fun addto ((switch as (REALcon s,pats))::more) =
131: if r = s then ((REALcon r,(fields,rhs)::pats)::more)
132: else switch :: addto more
133: | addto [] = [(REALcon r,(fields,rhs)::default)]
134: | addto _ = impossible "48 type error in match compiler"
135: in (addto cases,default)
136: end
137: | STRINGpat s =>
138: let val (cases,default) = andS more
139: fun addto ((switch as (STRINGcon t,pats))::more) =
140: if s = t then ((STRINGcon s,(fields,rhs)::pats)::more)
141: else switch :: addto more
142: | addto [] = [(STRINGcon s,(fields,rhs)::default)]
143: | addto _ = impossible "482 type error in match compiler"
144: in (addto cases,default)
145: end
146: | CONpat(dcon as DATACON{name=r1,...}) =>
147: let val (cases,default) = andS more
148: fun addto ((switch as (DATAcon(DATACON {name=r2,...}),pats))::more) =
149: if Symbol.eq(r1,r2)
150: then (DATAcon dcon,(fields,rhs)::pats)::more
151: else switch :: addto more
152: | addto [] = [(DATAcon dcon,(fields,rhs)::default)]
153: | addto _ = impossible "87 type error in match compiler"
154: in (addto cases,default)
155: end
156: | APPpat(dcon as DATACON{name=r1,...},p) =>
157: let val (cases,default) = andS more
158: fun addto ((switch as (DATAcon(DATACON {name=r2,...}),pats))::more) =
159: if Symbol.eq(r1,r2)
160: then ((DATAcon dcon,(p::fields,rhs)::pats)::more)
161: else switch :: addto more
162: | addto [] =
163: let fun addwild (fields,rhs) = (WILDpat::fields,rhs)
164: in [(DATAcon dcon,(p::fields,rhs)::(map addwild default))]
165: end
166: | addto _ = impossible "444 type error in match compiler"
167: in (addto cases,default)
168: end
169: | WILDpat =>
170: let val (cases,default) = andS more
171: fun addto (((con as DATAcon(DATACON{const=false,...})),pats)::more) =
172: (con,(WILDpat::fields,rhs)::pats) :: addto more
173: | addto ((con,pats)::more) =
174: (con,(fields,rhs)::pats) :: addto more
175: | addto [] = []
176: in (addto cases,(fields,rhs)::default)
177: end
178: | VARpat(VALvar{access=LVAR v,...}) =>
179: andS ((WILDpat::fields,bind(x,v,rhs))::more)
180: | LAYEREDpat(v,p) => andS((p::fields,layer(x,v,rhs))::more)
181: | CONSTRAINTpat(p,_) => andS((p::fields,rhs)::more)
182: | _ => impossible "andS in mc")
183: | andS _ = impossible "andS2 in mc"
184: in andS
185: end
186:
187: fun orSwitch x =
188: let fun diffPats samefn =
189: let fun diff [] = []
190: | diff ((hd as (p,rhs))::more) =
191: case p of
192: WILDpat => [hd]
193: | VARpat(VALvar{access=LVAR v,...}) => [(WILDpat,bind(x,v,rhs))]
194: | LAYEREDpat(v,p) =>
195: diff ((p,layer(x,v,rhs))::more)
196: | CONSTRAINTpat(p,_) =>
197: diff ((p,rhs)::more)
198: | _ => (if samefn p then diff more else hd::diff more)
199: handle Match =>
200: impossible "orS.diff: type error in match compiler"
201: in diff
202: end
203: fun orS [] = impossible "orSwitch [] in mc"
204: | orS (arg as (p,rhs)::more) =
205: case p of
206: INTpat i =>
207: let val (cases,default) = orS (diffPats (fn INTpat j => i=j) arg)
208: in ((INTcon i,convert rhs)::cases,default)
209: end
210: | REALpat r =>
211: let val (cases,default) = orS (diffPats (fn REALpat s => r=s) arg)
212: in ((REALcon r,convert rhs)::cases,default)
213: end
214: | STRINGpat s =>
215: let val (cases,default) = orS (diffPats (fn STRINGpat t => s=t) arg)
216: in ((STRINGcon s,convert rhs)::cases,default)
217: end
218: | WILDpat => ([],SOME(convert rhs))
219: | VARpat(VALvar{access=LVAR v,...}) => ([],SOME(convert(bind(x,v,rhs))))
220: | CONSTRAINTpat(p,_) => orS ((p,rhs)::more)
221: | LAYEREDpat(v,p) => orS ((p,layer(x,v,rhs))::more)
222: | _ => impossible "orS in mc"
223: in orS
224: end
225:
226: fun mcand (arg as ([_],_)::_,[x]) =
227: let val singlelist = fn ([pat],rhs) => (pat,rhs)
228: | _ => impossible "singlelist in match compiler"
229: in APP(mcor (map singlelist arg), VAR x)
230: end
231: | mcand (arg as (p::fields,rhs)::more,xl as x::xs) =
232: let fun mconto (con as DATAcon(con1 as DATACON{const = false,...}),pats) =
233: let val new = mkLvar ()
234: in (con,APP(FN(new,mcand (MCopt.opt (pats,new::xs))),DECON (con1,VAR x)))
235: end
236: | mconto (con as DATAcon(DATACON {const = true,...}),pats) =
237: (con,mcand (MCopt.opt (pats,xs)))
238: | mconto _ = impossible "mconto in mc"
239: in
240: case p of
241: WILDpat => mcand([(fields,rhs)],xs)
242: | VARpat(VALvar{access=LVAR v,...}) => mcand([(fields,bind(x,v,rhs))],xs)
243: | LAYEREDpat(v,p) => mcand(((p::fields,layer(x,v,rhs))::more),xl)
244: | CONSTRAINTpat(p,_) => mcand((p::fields,rhs)::more,xl)
245: | APPpat(DATACON{sign = [_],...},_) =>
246: let val newx = mkLvar()
247: val ([(DATAcon dcon,list)],_) = andSwitch x arg
248: in APP(FN(newx,mcand(MCopt.opt(list,newx::xs))),DECON(dcon,VAR x))
249: end
250: | APPpat(DATACON{sign,...},_) =>
251: let val (cases,default) = andSwitch x arg
252: in SWITCH(VAR x,
253: map mconto cases,
254: if length cases = length sign then NONE
255: else SOME (mcand (MCopt.opt (default,xs))))
256: end
257: | CONpat(DATACON{sign=[_],...}) => mcand([(fields,rhs)],xs)
258: | CONpat(DATACON{sign,...}) =>
259: let val (cases,default) = andSwitch x arg
260: in SWITCH(VAR x,
261: map mconto cases,
262: if length cases = length sign then NONE
263: else SOME (mcand (MCopt.opt (default,xs))))
264: end
265: | RECORDpat{pats=ref [],...} => mcand([(fields,rhs)],xs)
266: | RECORDpat{pats,...} =>
267: let val newfields = map (fn _ => mkLvar()) (!pats)
268: val wild = map (fn _ => WILDpat) newfields
269: fun expand [] = []
270: | expand ((p::fields,rhs)::more) =
271: (case p of
272: RECORDpat{pats,...} => (!pats@fields,rhs) :: expand more
273: | LAYEREDpat(v,p) => expand ((p::fields,layer(x,v,rhs))::more)
274: | CONSTRAINTpat(p,_) => expand ((p::fields,rhs)::more)
275: | WILDpat => (wild@fields,rhs) :: expand more
276: | VARpat(VALvar{access=LVAR v,...}) =>
277: (wild@fields,bind(x,v,rhs)) :: expand more
278: | _ => impossible "mcand.expand in mc")
279: | expand _ = impossible "mcand.expand2 in mc"
280: in bindfields(x,newfields,mcand(MCopt.opt(expand arg,newfields@xs)))
281: end
282: | _ => (* INTpat,REALpat,STRINGpat; possibly bad VARpats *)
283: let val (cases,default) = andSwitch x arg
284: in SWITCH(VAR x,
285: map (fn (con,pats) => (con,mcand(MCopt.opt(pats,xs)))) cases,
286: SOME(mcand(MCopt.opt(default,xs))))
287: end
288: end
289: | mcand _ = impossible "mcand in mc"
290:
291: and conSwitch x =
292: let
293: fun conS [] = ([],NONE)
294: | conS (arg as (p,rhs)::more) =
295: case p of
296: CONpat(dcon as DATACON{name=r1,...}) =>
297: let fun diff [] = []
298: | diff ((hd as (p,rhs))::more) =
299: case p of
300: CONpat(DATACON{name=r2,...}) =>
301: if Symbol.eq(r1,r2) then diff more
302: else (hd::diff more)
303: | APPpat (_,_) => hd::diff more
304: | WILDpat => [hd]
305: | VARpat _ => [hd]
306: | CONSTRAINTpat(p,_) => diff ((p,rhs)::more)
307: | LAYEREDpat(v,p) => diff ((p,layer(x,v,rhs))::more)
308: | _ => impossible "conS.diff: type error in match compiler"
309: val (cases,default) = conS (diff more)
310: in ((DATAcon dcon,convert rhs)::cases,default)
311: end
312: | APPpat(dcon as DATACON{name=r1,...},_) =>
313: let fun divide [] = ([],[])
314: | divide ((hd as (p,rhs))::more) =
315: case p of
316: CONpat _ =>
317: let val (same,diff) = divide more
318: in (same,hd::diff)
319: end
320: | APPpat(DATACON{name=r2,...},p) =>
321: let val (same,diff) = divide more
322: in if Symbol.eq(r1,r2)
323: then ((p,rhs)::same,diff)
324: else (same,hd::diff)
325: end
326: | WILDpat => ([hd],[hd])
327: | VARpat(VALvar{access=LVAR v,...}) =>
328: ([(WILDpat,bind(x,v,rhs))],[hd])
329: | CONSTRAINTpat(p,_) => divide ((p,rhs)::more)
330: | LAYEREDpat(v,p) => divide ((p,layer(x,v,rhs))::more)
331: | _ => impossible "conS.divide: type error in match compiler"
332: val con = DATAcon dcon
333: val (same,diff) = divide arg
334: val lexp = mcor same (* Order imp. here: side- *)
335: val (cases,default) = conS diff (* effects in redund. chk. *)
336: in ((con,APP(lexp,DECON(dcon,VAR x)))::cases,default)
337: end
338: | WILDpat => ([],SOME(convertDefault rhs))
339: | VARpat(VALvar{access=LVAR v,...}) =>
340: ([],SOME(convertDefault(bind(x,v,rhs))))
341: | LAYEREDpat(v,p) => conS ((p,layer(x,v,rhs))::more)
342: | CONSTRAINTpat(p,_) => conS ((p,rhs)::more)
343: | _ => impossible "conS: type error in match compiler"
344: in conS
345: end
346:
347: and mcor [] = impossible "mcor.[] in mc"
348: | mcor (arg as (p,rhs)::more) =
349: let val x = mkLvar()
350: in case p of
351: CONpat(DATACON{sign=[],...}) => (* exception *)
352: let val (cases,default) = conSwitch x arg
353: in areNotRedundant();
354: FN(x,SWITCH(VAR x,cases,default))
355: end
356: | APPpat (DATACON{sign=[],...},_) => (* exn *)
357: let val (cases,default) = conSwitch x arg
358: in areNotRedundant();
359: FN(x,SWITCH(VAR x,cases,default))
360: end
361: | CONpat(DATACON{sign=[_],...}) => FN(x, convert rhs)
362: | CONpat(DATACON{sign,...}) =>
363: let val (cases,default) = conSwitch x arg
364: in FN(x,SWITCH(VAR x, cases,
365: (if length cases = length sign
366: then (areRedundant(); NONE)
367: else (areNotRedundant(); default))))
368: end
369: | APPpat(DATACON{sign=[_],...},_) =>
370: let val ([(con,lexp)],_) = conSwitch x arg
371: in areRedundant();
372: FN(x,lexp)
373: end
374: | APPpat(DATACON{sign,...},_) =>
375: let val (cases,default) = conSwitch x arg
376: in FN(x,SWITCH(VAR x, cases,
377: (if length cases = length sign
378: then (areRedundant(); NONE)
379: else (areNotRedundant(); default))))
380: end
381: | INTpat _ =>
382: let val (cases,default) = orSwitch x arg
383: in FN(x,SWITCH(VAR x,cases,default))
384: end
385: | REALpat _ =>
386: let val (cases,default) = orSwitch x arg
387: in FN(x,SWITCH(VAR x,cases,default))
388: end
389: | STRINGpat _ =>
390: let val (cases,default) = orSwitch x arg
391: in FN(x,SWITCH(VAR x,cases,default))
392: end
393: | RECORDpat{pats=ref [],...} => FN(x, convert rhs)
394: | RECORDpat{pats,...} =>
395: let val newfields = map (fn _ => mkLvar()) (!pats)
396: val wild = map (fn _ => WILDpat) newfields
397: fun expand [] = []
398: | expand ((p,rhs)::more) =
399: case p of
400: RECORDpat{pats,...} => (!pats,rhs) :: expand more
401: | LAYEREDpat(v,p) => expand ((p,layer(x,v,rhs))::more)
402: | CONSTRAINTpat(p,_) => expand ((p,rhs)::more)
403: | WILDpat => [(wild,rhs)]
404: | VARpat(VALvar{access=LVAR v,...}) =>
405: [(wild,bind(x,v,rhs))]
406: | _ => impossible "mcor.expand in mc"
407: in FN(x,bindfields(x,newfields,mcand(MCopt.opt(expand arg,newfields))))
408: end
409: | WILDpat => FN(x, convert rhs)
410: | VARpat(VALvar{access=LVAR v,...}) => FN(x,convert(bind(x,v,rhs)))
411: | LAYEREDpat(v,p) => FN(x,APP(mcor((p,layer(x,v,rhs))::more),VAR x))
412: | CONSTRAINTpat(p,_) => mcor((p,rhs)::more)
413: | _ => impossible "mcor: type error in match compiler"
414: end (* fun mcor *)
415:
416: open PrintUtil
417: fun matchPrint [] _ _ = ()
418: | matchPrint [(pat,_)] _ _ = () (* never print last rule *)
419: | matchPrint ((pat,_)::more) [] _ =
420: (print " "; PrintAbsyn.printPat(pat,!printDepth); print " => ...\n";
421: matchPrint more [] 0)
422: | matchPrint ((pat,_)::more) (taglist as (tag::tags)) i =
423: if i = tag
424: then (print " --> "; PrintAbsyn.printPat(pat,!printDepth);
425: print " => ...\n"; matchPrint more tags (i+1))
426: else (print " "; PrintAbsyn.printPat(pat,!printDepth);
427: print " => ...\n"; matchPrint more taglist (i+1))
428:
429: fun bindPrint ((pat,_)::_) =
430: (print " "; PrintAbsyn.printPat(pat,!printDepth); print " = ...\n")
431: | bindPrint _ = impossible "bindPrint in mc"
432:
433: fun noVarsIn ((pat,_)::_) =
434: let fun var WILDpat = true (* might want to flag this *)
435: | var (VARpat _) = true
436: | var (LAYEREDpat _) = true
437: | var (CONSTRAINTpat(p,_)) = var p
438: | var (APPpat(_,p)) = var p
439: | var (RECORDpat{pats=ref patlist,...}) = exists var patlist
440: | var _ = false
441: in not(var pat)
442: end
443: | noVarsIn _ = impossible "noVarsIn in mc"
444:
445: open System.Control.MC
446:
447: fun genCompile(flag1,warning1,flag2,test,warning2,printer) rules =
448: let val (header,rules') = setup rules
449: val match = header(mcor rules')
450: val unused = redundant rules
451: val last = length rules - 1
452: val printit = if !flag1 andalso not(exists (fn i => i=last) unused)
453: then (warn(warning1 ^ " not exhaustive"); true)
454: else false
455: val printit = if !flag2 andalso test(rules,unused,last)
456: then (warn warning2; true)
457: else printit
458: in if !printArgs
459: then (warn "MC called with:"; MCprint.printMatch rules)
460: else ();
461: if printit
462: then printer(rules,unused)
463: else ();
464: if !printRet
465: then (print "MC: returns with\n"; MCprint.printLexp match; newline())
466: else ();
467: match
468: end handle Syntax => (warn "MC called with:"; MCprint.printMatch rules;
469: raise Syntax)
470:
471: val bindCompile =
472: genCompile(bindExhaustive,
473: "binding",
474: bindContainsVar,
475: fn (rules,unused,last) => noVarsIn rules,
476: "binding contains no variables",
477: fn(rules,unused) => bindPrint rules)
478:
479: val matchCompile =
480: genCompile(matchExhaustive,
481: "match",
482: matchRedundant,
483: fn(rules,unused,last) => exists (fn i => i<last) unused,
484: "redundant patterns in match",
485: fn(rules,unused) => matchPrint rules unused 0)
486:
487: end (* struct MC *)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.