1 /* -*- mode: hugs-c; -*- */
2 /* --------------------------------------------------------------------------
5 * Copyright (c) The University of Nottingham and Yale University, 1994-1997.
6 * All rights reserved. See NOTICE for details and conditions of use etc...
7 * Hugs version 1.4, December 1997
11 * $Date: 1998/12/02 13:22:28 $
12 * ------------------------------------------------------------------------*/
23 /* --------------------------------------------------------------------------
24 * Local function prototypes:
25 * ------------------------------------------------------------------------*/
27 static Cell local refutePat Args((Cell));
28 static Cell local refutePatAp Args((Cell));
29 static Cell local matchPat Args((Cell));
30 static List local remPat1 Args((Cell,Cell,List));
32 /* --------------------------------------------------------------------------
33 * Elimination of pattern bindings:
35 * The following code adopts the definition of failure free patterns as given
36 * in the Haskell 1.3 report; the term "irrefutable" is also used there for
37 * a subset of the failure free patterns described here, but has no useful
38 * role in this implementation. Basically speaking, the failure free patterns
39 * are: variable, wildcard, ~apat
40 * var@apat, if apat is failure free
41 * C apat1 ... apatn if C is a product constructor
42 * (i.e. an only constructor) and
43 * apat1,...,apatn are failure free
44 * Note that the last case automatically covers the case where C comes from
45 * a newtype construction.
46 * ------------------------------------------------------------------------*/
48 Bool failFree(pat) /* is pattern failure free? (do we need */
49 Cell pat; { /* a conformality check?) */
50 Cell c = getHead(pat);
53 case ASPAT : return failFree(snd(snd(pat)));
55 case NAME : if (!isCfun(c) || cfunOf(c)!=0)
57 /*intentional fall-thru*/
58 case TUPLE : for (; isAp(pat); pat=fun(pat))
59 if (!failFree(arg(pat)))
61 /*intentional fall-thru*/
66 case WILDCARD : return TRUE;
69 case EXT : return failFree(extField(pat)) &&
70 failFree(extRow(pat));
73 case CONFLDS : if (cfunOf(fst(snd(c)))==0) {
74 List fs = snd(snd(c));
75 for (; nonNull(fs); fs=tl(fs))
76 if (!failFree(snd(hd(fs))))
80 /*intentional fall-thru*/
81 default : return FALSE;
85 static Cell local refutePat(pat) /* find pattern to refute in conformality*/
86 Cell pat; { /* test with pat. */
87 /* e.g. refPat (x:y) == (_:_) */
88 /* refPat ~(x:y) == _ etc.. */
90 switch (whatIs(pat)) {
91 case ASPAT : return refutePat(snd(snd(pat)));
93 case FINLIST : { Cell ys = snd(pat);
95 for (; nonNull(ys); ys=tl(ys)) {
96 xs = ap2(nameCons,refutePat(hd(ys)),xs);
98 return revOnto(xs,nameNil);
101 case CONFLDS : { Cell ps = NIL;
102 Cell fs = snd(snd(pat));
103 for (; nonNull(fs); fs=tl(fs)) {
104 Cell p = refutePat(snd(hd(fs)));
105 ps = cons(pair(fst(hd(fs)),p),ps);
107 return pair(CONFLDS,pair(fst(snd(pat)),rev(ps)));
114 case LAZYPAT : return WILDCARD;
122 case NAME : return pat;
124 case AP : return refutePatAp(pat);
126 default : internal("refutePat");
127 return NIL; /*NOTREACHED*/
131 static Cell local refutePatAp(p) /* find pattern to refute in conformality*/
134 if (h==nameFromInt || h==nameFromInteger || h==nameFromDouble)
137 else if (whatIs(h)==ADDPAT)
138 return ap(fun(p),refutePat(arg(p)));
142 Cell pf = refutePat(extField(p));
143 Cell pr = refutePat(extRow(p));
144 return ap2(fun(fun(p)),pf,pr);
148 List as = getArgs(p);
149 mapOver(refutePat,as);
150 return applyToArgs(h,as);
154 static Cell local matchPat(pat) /* find pattern to match against */
155 Cell pat; { /* replaces parts of pattern that do not */
156 /* include variables with wildcards */
157 switch (whatIs(pat)) {
158 case ASPAT : { Cell p = matchPat(snd(snd(pat)));
159 return (p==WILDCARD) ? fst(snd(pat))
161 pair(fst(snd(pat)),p));
164 case FINLIST : { Cell ys = snd(pat);
166 for (; nonNull(ys); ys=tl(ys))
167 xs = cons(matchPat(hd(ys)),xs);
168 while (nonNull(xs) && hd(xs)==WILDCARD)
170 for (ys=nameNil; nonNull(xs); xs=tl(xs))
171 ys = ap2(nameCons,hd(xs),ys);
175 case CONFLDS : { Cell ps = NIL;
176 Name c = fst(snd(pat));
177 Cell fs = snd(snd(pat));
179 for (; nonNull(fs); fs=tl(fs)) {
180 Cell p = matchPat(snd(hd(fs)));
181 ps = cons(pair(fst(hd(fs)),p),ps);
185 return avar ? pair(CONFLDS,pair(c,rev(ps)))
191 case DICTVAR : return pat;
193 case LAZYPAT : { Cell p = matchPat(snd(pat));
194 return (p==WILDCARD) ? WILDCARD : ap(LAZYPAT,p);
199 case CHARCELL : return WILDCARD;
203 case AP : { Cell h = getHead(pat);
204 if (h==nameFromInt ||
205 h==nameFromInteger || h==nameFromDouble)
208 else if (whatIs(h)==ADDPAT)
213 Cell pf = matchPat(extField(pat));
214 Cell pr = matchPat(extRow(pat));
215 return (pf==WILDCARD && pr==WILDCARD)
217 : ap2(fun(fun(pat)),pf,pr);
223 for (; isAp(pat); pat=fun(pat)) {
224 Cell p = matchPat(arg(pat));
229 return avar ? applyToArgs(pat,args)
234 default : internal("matchPat");
235 return NIL; /*NOTREACHED*/
239 #define addEqn(v,val,lds) cons(pair(v,singleton(pair(NIL,val))),lds)
241 List remPat(pat,expr,lds)
242 Cell pat; /* Produce list of definitions for eqn */
243 Cell expr; /* pat = expr, including a conformality */
244 List lds; { /* check if required. */
246 /* Conformality test (if required):
247 * pat = expr ==> nv = LETREC confCheck nv@pat = nv
249 * remPat1(pat,nv,.....);
252 if (!failFree(pat)) {
253 Cell confVar = inventVar();
254 Cell nv = inventVar();
255 Cell locfun = pair(confVar, /* confVar [([nv@refPat],nv)] */
256 singleton(pair(singleton(ap(ASPAT,
261 if (whatIs(expr)==GUARDED) { /* A spanner ... special case */
262 lds = addEqn(nv,expr,lds); /* for guarded pattern binding*/
267 if (whatIs(pat)==ASPAT) { /* avoid using new variable if*/
268 nv = fst(snd(pat)); /* a variable is already given*/
269 pat = snd(snd(pat)); /* by an as-pattern */
272 lds = addEqn(nv, /* nv = */
273 ap(LETREC,pair(singleton(locfun), /* LETREC [locfun] */
274 ap(confVar,expr))), /* IN confVar expr */
277 return remPat1(matchPat(pat),nv,lds);
280 return remPat1(matchPat(pat),expr,lds);
283 static List local remPat1(pat,expr,lds)
284 Cell pat; /* Add definitions for: pat = expr to */
285 Cell expr; /* list of local definitions in lds. */
289 switch (whatIs(c=getHead(pat))) {
292 case CHARCELL : break;
294 case ASPAT : return remPat1(snd(snd(pat)), /* v@pat = expr */
296 addEqn(fst(snd(pat)),expr,lds));
298 case LAZYPAT : { Cell nv;
300 if (isVar(expr) || isName(expr))
304 lds = addEqn(nv,expr,lds);
307 return remPat(snd(pat),nv,lds);
311 case ADDPAT : return remPat1(arg(pat), /* n + k = expr */
312 ap3(namePmSub, arg(fun(pat)), snd(c),
317 case FINLIST : return remPat1(mkConsList(snd(pat)),expr,lds);
319 case CONFLDS : { Name h = fst(snd(pat));
320 Int m = name(h).arity;
322 List fs = snd(snd(pat));
326 for (; nonNull(fs); fs=tl(fs)) {
328 for (i=m-sfunPos(fst(hd(fs)),h); i>0; i--)
330 arg(r) = snd(hd(fs));
332 return remPat1(p,expr,lds);
335 case DICTVAR : /* shouldn't really occur */
336 assert(0); /* so let's test for it then! ADR */
338 case VAROPCELL : return addEqn(pat,expr,lds);
340 case NAME : if (c==nameFromInt || c==nameFromInteger
341 || c==nameFromDouble) {
343 arg(fun(pat)) = translate(arg(fun(pat)));
347 if (argCount==1 && isCfun(c) /* for newtype */
348 && cfunOf(c)==0 && name(c).defn==nameId)
349 return remPat1(arg(pat),expr,lds);
351 /* intentional fall-thru */
352 case TUPLE : { List ps = getArgs(pat);
358 if (isVar(expr) || isName(expr))
362 lds = addEqn(nv,expr,lds);
365 sel = ap2(nameSel,c,nv);
366 for (i=1; nonNull(ps); ++i, ps=tl(ps))
367 lds = remPat1(hd(ps),
375 case EXT : { Cell nv = inventVar();
377 = translate(arg(fun(fun(pat))));
383 lds = remPat1(extField(pat),ap(nameFst,nv),lds);
384 lds = remPat1(extRow(pat),ap(nameSnd,nv),lds);
389 default : internal("remPat1");
395 /* --------------------------------------------------------------------------
397 * ------------------------------------------------------------------------*/
399 Void patControl( Int what )
409 /*-------------------------------------------------------------------------*/