[project @ 1996-07-25 20:43:49 by partain]
[ghc-hetmet.git] / ghc / docs / NOTES.desugar
diff --git a/ghc/docs/NOTES.desugar b/ghc/docs/NOTES.desugar
deleted file mode 100644 (file)
index b9e6ce7..0000000
+++ /dev/null
@@ -1,323 +0,0 @@
-(91/08/08: OLD!)
-
-These are notes about a _simple_ but complete pattern-matching
-compiler for Haskell.  I presume familiarity with Phil's
-pattern-matching stuff in Simon's book and use roughly the same notation.
-
-Abbreviations: "p" for pattern, "e" (or "E") for expression, "g" for
-guard, "v" for variable, "u" for new variable I made up. "[]" for
-FATBAR.
-
-Subscripts: "p11" is really short for "p_{1,1}".  Sometimes I'll use
-a "?", as in "pm1 ... pm?", to mean the second subscript goes up to
-something I'm really not worried about.
-
-NB: LETRECS NOT DEALT WITH YET.
-
----------------------------------------------------------------------
-We need a slightly souped-up "match" for Haskell (vs the Phil-chapter
-one).  Simon suggested a re-arrangement of things, which I have then
-further re-arranged...
-
-Proposal (Simon)
-~~~~~~~~
-
-Eliminate default arg of match (3rd arg in Phil-chapter match) in
-favour of returning the variable (not special value) fail.  Thus a
-possible translation for
-
-       f [] [] = e1
-       f x  y  = e2
-
-would be
-
-       f p q = case p of 
-               [] -> case q of
-                       [] -> e1
-                       _  -> fail
-               _ -> fail
-               where
-               fail = e2
-
-Now the issue of whether to duplicate code or share it becomes whether
-to substitute copies of e2 or not.  This is a decision we need to take
-anyway for all other let-bound things, so why not for fail too?  If
-fail is used only once, we will certainly substitute for it.
-
-We could even detect that fail is used only in a head position, so it
-can be implemented as a stack-adjust then a jump.  This might well
-apply to other let-bound things too.
-
-Now here's a proposal for the "match" function.  The main difference is
-    1) no default argument
-    2) [contra simon's suggestion]  Patterns are still per-row as in
-       Phil's chapter.
-    3) [partain] even the input exprs are CoreExprs
-
-OK, for a "match" for m equations each with n patterns:
-
-match :: [Name]
-               -- n (variable) names, one per pattern column, bound
-               -- to the n expressions we are matching against the
-               -- patterns
-
-      -> [([Pat], CoreExpr)]
-               -- one pair for each of the m equations: the n
-               -- patterns in that equation, then the CoreExpr that
-               -- is evaluated if we get a match.  The CoreExpr may
-               -- contain free "fail"s; some hackery required to
-               -- ensure that is OK; see below
-
-      -> CoreExpr
-               -- the resulting code to do the matching
-
-In words,
-  takes
-    (1) a list of n (match-expression, pattern-column) pairs
-    (2) a list of m post-match expressions, expr i to be inserted
-       immediately after equation i's lhs matches
-  returns
-    (1) a desugared expr equivalent of the whole "match"
-
-Meaning
-~~~~~~~
-    match [u1, ..., un]
-         [([p11, ..., p1n], e1), ..., ([pm1, ..., pmn], em)]
-
-    match [ (e1, [p11, ...,pm1]), ..., (en, [p1n, ...,pmn])]
-         [ E1, ... Em ]
-
-    ********* MEANS *********
-
-    case (u1, ..., un) of
-        (p11, ..., p1n) -> e1
-        _               -> fail
-    where
-    fail = case (u1, ..., un) of
-               (p21, ..., p2n) -> e2
-               _               -> fail
-    ... and so on ...
-
-Alternatively, this specification could be given in terms of
-pattern-matching lambdas, as in Phil's chapter.
-
-NOT CHANGED BEYOND HERE
-
--------------------------------------------------------------------
-Cranking through a good old function definition with the above:
-
-    f p11 p12 ... p1n | g11 = e11
-                     | g12 = e12
-                     ...
-                     | g1? = e1?
-    ...
-    f pm1 pm2 ... pmn | gm1 = em1
-                     ...
-                     | gm? = em?
-
-The "match" equivalent is:
-
-f = \u1.\u2...\un ->
-       match [ (u1, [p11, ...,pm1]), ..., (un, [p1n, ...,pmn])]
-             [ E1, ..., Em ]
-       where fail = error "pattern-match for f failed\n"
-             E1   = if g11 then e11 else if g12 then ... else fail
-             ...
-             Em   = if gm1 then em1 else if gm2 then ... else fail
-
-Boring, huh?
-
--------------------------------------------------------------------
-It is helpful to me to think about the simple/base cases for this
-complicated "match".
-
-ALL LISTS EMPTY
-
-    match [] []
-
-  corresponds to the syntactically bogus (zero equations!?)
-
-    case () of
-      () -> {- nothing!! -}
-      _  -> fail
-
-
-EMPTY RULE -- no more patterns
-
-    match [] [ ([], E1), ..., ([], Em) ]
-
-  [where, incidentally, each Ei will be of the form
-   (not that it has to be...)
-
-    Ei = let x1 = e1 in
-         let x2 = e2 in
-        ...
-        let x? = e? in
-        if g1 then e'1
-        else if g2 then 
-        ...
-        else if g? then e'?
-        else fail
-  ]
-
-  becomes ("E1 [] E2 [] ... [] Em" in Phil's chapter...)
-
-    E1
-    where
-       fail = E2
-       where
-       ...
-         fail = Em-1
-        where fail = Em
-
-  with any "fail" in Em being bound from an outer scope; perhaps it's
-  easier to see written as:
-
-    let fail = Em
-     in let fail = Em-1
-        in ...
-           let fail = E2 in E1
--------------------------------------------------------------------
-HANDLING LAZY ("TWIDDLE") PATTERNS
-
-For Haskell, the "mixture rule" (p.~88) looks at a pattern-column and
-splits the equations into groups, depending on whether it sees
-
-    * all constructors, or
-    * all variables _OR LAZY PATTERNS_
-
-The following example shows what "match" does when confronted by one
-of these variables/lazy-patterns combinations.  Note the use of the
-binding lists.
-
-    f  v | g11 = e11
-        ...
-        | g1? = e1?
-    f ~p | g21 = e21
-        ...
-        | g2? = e2?
-
-is
-
-    f = \ u1 ->
-       match [(u1, [ v, ~p ])]
-             [ if g11 then e11 else if ... else fail, -- E1
-               if g21 then e21 else if ... else fail  -- E2
-             ]
-    where fail = error "no match in f\n"
-
-which transmogrifies into
-
-    f = \ u1 ->
-       let u2 = u1 in
-       match []
-             [ -- E1 --
-               let v = u2 
-               in
-               if g11 then e11 else if ... else fail
-
-              ,-- E2 --
-               let free_var1_of_p = match [(u2, [ p ])] [ free_var1_of_p ]
-                   ...
-                   free_var?_of_p = match [(u2, [ p ])] [ free_var?_of_p ]
-               in
-               if g21 then e21 else if ... else fail  -- E2
-
-             ]
-    where fail = error "no match in f\n"
-
-For more specific match-failure error messages, one could insert
-"let fail = ..."'s in strategic places.
-
--------------------------------------------------------------------
-"match" EQUIVALENTS FOR VARIOUS HASKELL CONSTRUCTS
-
-* function definition -- shown above
-
-* pattern-matching lambda (souped up version in static semantics)
-
-    \ p1 p2 ... pn | g1 -> e1
-                  | g2 -> e2
-                  ...
-                  | gm -> em
-
-  is the same as
-
-    \ u1.\u2 ... \un ->
-       match [ (u1, [p1]), ..., (un, [pn])]
-             [ if g1 then e1 else if ... then em else fail
-             ]
-       where fail = error "no match in pattern-matching lambda at line 293\n"
-
-* pattern-matching (simple, non-recursive) "let"
-
-    let p = e
-    in E
-
-  corresponds to
-
-    case e of
-      ~p -> E
-
-  which has a "match" equivalent of
-
-    match [(e, [~p])] [ E ]
-
-  The full-blown Haskell "let" is more horrible:
-
-    let p | g1 = e1
-         ...
-         | gn = en
-    in E
-
-  corresponds to
-
-    case ( if g1 then e1 else... else if gn then en else error "?" ) of
-      ~p -> E
-
-  thinking about which I am not able to sleep well at night.
-  (Won't those g's have things bound from inside p ?)
-
-* pattern-matching (not-quite-so simple, non-recursive) "let"
-
-<mumble>
-
-* pattern binding
-
-    p | g1 = e1
-      | g2 = e2
-      ...
-      | gm = em
-
-  That's the same as
-
-    p = if g1 then e1 else if ... else if gm then em else fail
-    where fail = "...some appropriate thing..."
-
-  which corresponds to
-
-    match [ (if g1 ... then em else fail, [ ~p ]) ]
-         [ {-nothing-} ]
-    where fail = "...some appropriate thing..."
-
-* "case" expressions (souped up version in static semantics)
-
-    case e0 of
-      p1 | g11 -> e11
-        ...
-        | g1? -> e1?
-      ...
-      pm | gm1 -> em1
-        ...
-        | gm? -> em?
-
-  is the same as
-
-    match [ (e0, [p1, ..., pm]) ]
-         [ if g11 then e11 else if ... else fail -- E1
-           , ... ,
-           if gm1 then em1 else if ... else fail
-         ]
-    where fail = error "pattern-matching case at line xxx failed\n"
-
-* list comprehensions