summaryrefslogtreecommitdiff
path: root/ghc/compiler/yaccParser/listcomp.c
blob: 6258869966277ccb7f05e110a1fa7ce7e56ae468 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/*
   Implementation of optimally compiled list comprehensions using Wadler's algorithm from
   Peyton-Jones "Implementation of Functional Programming Languages", 1987

   TQ transforms a list of qualifiers (either boolean expressions or generators) into a
   single expression which implements the list comprehension.

   TE << [E || Q] >>  =  TQ <<  [E || Q] ++ [] >>

   TQ << [E || p <- L1, Q]  ++  L2 >> =

      h ( TE << L1 >> ) where
      			h = us -> case us in
	  			[]        ->  TE << L2 >>
				(u : us') ->
					(TE << p >> ->  ( TQ << [E || Q]  ++  (h us') >> )) u
 */

tree TQ(quals,l2)
list quals, l2;
{
  tree qualh;
  list rest;

  if(tlist(quals) == lnil)
    return(mkcons(zfexpr,l2));

  qualh = (tree) lhd(quals);
  rest = ltl(quals);

  if(ttree(qualh) != qual)
    return(mkif(qualh,TQ(rest,l2),l2));

  {
    tree h = mkident(uniqueident("Zh%d")),
         u = mkident(uniqueident("Iu%d")),
         us = mkident(uniqueident("Ius%d")),
         pat = gqpat(qualh);

    pbinding tq = mkppat(gqpat(qualh),TQ(rest,mkap(h,us)));


    return(
       mkletv(
	 mkrbind(
	   mkpbind(
	     lsing(
	       mkppat(h,
		 mklam(us,
		   mkcasee(us,
		     ldub(
		       mkppat(niltree,l2),
		       mkppat(
			  mkcons(u,us),
			  mkcasee(u,lsing(tq))
/*
  replaces the following code which elides patterns in list comprehensions a la M*****a

			  mkcasee(u,
			    ttree(pat) == ident && !isconstr(gident(pat))?
			      lsing(tq):
			      ldub(tq,mkppat(mkident("_"),mkap(h,us))))
*/
			    )))))))),
	 mkap(h,gqexp(qualh))));
  }
}