Ticket #3865: testinput

File testinput, 14.1 KB (added by dsf, 3 years ago)

A file from haskell-hsx that can't be read by ghc 6.13-20091231 on an amd64

Line 
1    -- | Generate declarations for optional patterns, ? and #?.
2    -- (Unfortunally we must place this function here since both variations
3    -- of transformations of optional patterns should be able to call it...)
4    mkOptDecl :: SrcLoc -> Bool -> MFunMetaInfo -> Tr MFunMetaInfo
5    mkOptDecl s greedy nvt@(_, vs, t) = do
6        -- Un nome, s'il vouz plaît.
7        n <- genMatchName
8        let -- Generate a generator for matching the subpattern
9            (g, val) = mkGenExp s nvt               -- (harp_valX, (foo, bar, ...)) <- harp_matchY
10            -- ... and apply a Just to its value
11            ret1 = metaReturn $ tuple               -- return (Just harp_val1, (foo, bar, ...))
12                    [app (var just_name)
13                     (var val), varTuple vs]
14            -- ... and do those two steps in a do-expression
15            exp1 = doE [g, qualStmt ret1]           -- do ....
16            -- For the non-matching branch, all the variables should be empty
17            ids  = map (const idFun) vs             -- (id, id, ...)
18            -- ... and the value should be Nothing.
19            ret2 = metaReturn $ tuple               -- return (Nothing, (id, id, ...))
20                    [var nothing_name, tuple ids]   -- i.e. no vars were bound
21            -- The order of the arguments to the choice (+++) operator
22            -- is determined by greed...
23            mc   = if greedy
24                    then metaChoice        -- standard order
25                    else (flip metaChoice) -- reversed order
26            -- ... and then apply it to the branches.
27            rhs  = (paren exp1) `mc`                -- (do ....) +++
28                    (paren ret2)                    --  (return (Nothing, .....))
29        -- Finally we create a declaration for this function and
30        -- add it to the store.
31        pushDecl $ nameBind s n rhs                 -- harp_matchZ = (do ....) +++ (return ....)
32        -- The type of the returned value will be Maybe the type
33        -- of the value of the subpattern.
34        return (n, vs, M t)
35
36    -- | Generate declarations for star patterns, * and #*
37    -- (Unfortunally we must place this function here since both variations
38    -- of transformations of repeating patterns should be able to call it...)
39    mkStarDecl :: SrcLoc -> Bool -> MFunMetaInfo -> Tr MFunMetaInfo
40    mkStarDecl s greedy (mname, vs, t) = do
41        -- Ett namn, tack!
42        n <- genMatchName
43        let -- Create a generator that matches the subpattern
44            -- many times, either greedily or non-greedily
45            g = mkManyGen s greedy mname
46            -- ... and unzip the result, choosing the proper unzip
47            -- function depending on the number of variables returned.
48            metaUnzipK = mkMetaUnzip s (length vs)
49            -- ... first unzip values from variables
50            dec1    = patBind s (pvarTuple [valname, varsname])
51                    (metaUnzip $ var valsvarsname)
52            -- ... and then unzip the variables
53            dec2    = patBind s (pvarTuple vs)
54                    (metaUnzipK $ var varsname)
55            -- ... fold all the values for variables
56            retExps = map ((app foldCompFun) . var) vs
57            -- ... and return value and variables
58            ret     = metaReturn $ tuple $
59                    [var valname, tuple retExps]
60        -- Finally we need to generate a function that does all this,
61        -- using a let-statement for the non-monadic stuff and a
62        -- do-expression to wrap it all in.
63        pushDecl $ nameBind s n $
64            doE [g, letStmt [dec1, dec2], qualStmt ret]
65        -- The type of the returned value is a list ([]) of the
66        -- type of the subpattern.
67        return (n, vs, L t)
68
69    -- | Generate declarations for plus patterns, + and #+
70    -- (Unfortunally we must place this function here since both variations
71    -- of transformations of non-empty repeating patterns should be able to call it...)
72    mkPlusDecl :: SrcLoc -> Bool -> MFunMetaInfo -> Tr MFunMetaInfo
73    mkPlusDecl s greedy nvt@(mname, vs, t) = do
74        -- and now I've run out of languages...
75        n <- genMatchName
76        let k = length vs
77            -- First we want a generator to match the
78            -- subpattern exactly one time
79            (g1, val1) = mkGenExp s nvt                     -- (harp_valX, (foo, ...)) <- harpMatchY
80            -- ... and then one that matches it many times.
81            g2         = mkManyGen s greedy mname           -- harp_vvs <- manyMatch harpMatchY
82            -- ... we want to unzip the result, using
83            -- the proper unzip function
84            metaUnzipK = mkMetaUnzip s k
85            -- ... first unzip values from variables
86            dec1    = patBind s                             -- (harp_vals, harp_vars) = unzip harp_vvs
87                        (pvarTuple [valsname, varsname])
88                        (metaUnzip $ var valsvarsname)
89            -- .. now we need new fresh names for variables
90            -- since the ordinary ones are already taken.
91            vlvars  = genNames "harp_vl" k
92            -- ... and then we can unzip the variables
93            dec2    = patBind s (pvarTuple vlvars)          -- (harp_vl1, ...) = unzipK harp_vars
94                        (metaUnzipK $ var varsname)
95            -- .. and do the unzipping in a let-statement
96            letSt   = letStmt [dec1, dec2]
97            -- ... fold variables from the many-match,
98            -- prepending the variables from the single match
99            retExps = map mkRetFormat $ zip vs vlvars       -- foo . (foldComp harp_vl1), ...
100            -- ... prepend values from the single match to
101            -- those of the many-match.
102            retVal  = (var val1) `metaCons`
103                        (var valsname)                      -- harp_valX : harp_vals
104            -- ... return all values and variables
105            ret     = metaReturn $ tuple $                  -- return (harp_valX:harpVals,
106                        [retVal, tuple retExps]             --   (foo . (...), ...))
107            -- ... and wrap all of it in a do-expression.
108            rhs     = doE [g1, g2, letSt, qualStmt ret]
109        -- Finally we create a declaration for this function and
110        -- add it to the store.
111        pushDecl $ nameBind s n rhs
112        -- The type of the returned value is a list ([]) of the
113        -- type of the subpattern.
114        return (n, vs, L t)
115
116      where mkRetFormat :: (Name, Name) -> Exp
117            mkRetFormat (v, vl) =
118                -- Prepend variables using function composition.
119                (var v) `metaComp`
120                  (paren $ (app foldCompFun) $ var vl)
121
122
123--------------------------------------------------------------------------
124-- HaRP-specific functions and ids
125
126-- | Functions and ids from the @Match@ module,
127-- used in the generated matching functions
128runMatchFun, baseMatchFun, manyMatchFun, gManyMatchFun :: Exp
129runMatchFun = match_qual runMatch_name
130baseMatchFun = match_qual baseMatch_name
131manyMatchFun = match_qual manyMatch_name
132gManyMatchFun = match_qual gManyMatch_name
133
134runMatch_name, baseMatch_name, manyMatch_name, gManyMatch_name :: Name
135runMatch_name = Ident "runMatch"
136baseMatch_name = Ident "baseMatch"
137manyMatch_name = Ident "manyMatch"
138gManyMatch_name = Ident "gManyMatch"
139
140match_mod, match_qual_mod :: ModuleName
141match_mod = ModuleName "Harp.Match"
142match_qual_mod = ModuleName "HaRPMatch"
143
144match_qual :: Name -> Exp
145match_qual = qvar match_qual_mod
146
147choiceOp :: QOp
148choiceOp = QVarOp $ Qual match_qual_mod choice
149
150appendOp :: QOp
151appendOp = QVarOp $ UnQual append
152
153-- foldComp = foldl (.) id, i.e. fold by composing
154foldCompFun :: Exp
155foldCompFun = match_qual $ Ident "foldComp"
156
157mkMetaUnzip :: SrcLoc -> Int -> Exp -> Exp
158mkMetaUnzip s k | k <= 7 = let n = "unzip" ++ show k
159                            in (\e -> matchFunction n [e])
160                | otherwise =
161                   let vs      = genNames "x" k
162                       lvs     = genNames "xs" k
163                       uz      = name $ "unzip" ++ show k
164                       ys      = name "ys"
165                       xs      = name "xs"
166                       alt1    = alt s peList $ tuple $ replicate k eList   -- [] -> ([], [], ...)
167                       pat2    = (pvarTuple vs) `metaPCons` (pvar xs)       -- (x1, x2, ...)
168                       ret2    = tuple $ map appCons $ zip vs lvs           -- (x1:xs1, x2:xs2, ...)
169                       rhs2    = app (var uz) (var xs)                      -- unzipK xs
170                       dec2    = patBind s (pvarTuple lvs) rhs2             -- (xs1, xs2, ...) = unzipK xs
171                       exp2    = letE [dec2] ret2
172                       alt2    = alt s pat2 exp2
173                       topexp  = lamE s [pvar ys] $ caseE (var ys) [alt1, alt2]
174                       topbind = nameBind s uz topexp
175                    in app (paren $ letE [topbind] (var uz))
176  where appCons :: (Name, Name) -> Exp
177        appCons (x, xs) = metaCons (var x) (var xs)
178
179matchFunction :: String -> [Exp] -> Exp
180matchFunction s es = mf s (reverse es)
181  where mf s []     = match_qual $ Ident s
182        mf s (e:es) = app (mf s es) e
183
184-- | Some 'magic' gensym-like functions, and functions
185-- with related functionality.
186retname :: Name
187retname = name "harp_ret"
188
189varsname :: Name
190varsname = name "harp_vars"
191
192valname :: Name
193valname = name "harp_val"
194
195valsname :: Name
196valsname = name "harp_vals"
197
198valsvarsname :: Name
199valsvarsname = name "harp_vvs"
200
201mkValName :: Int -> Name
202mkValName k = name $ "harp_val" ++ show k
203
204extendVar :: Name -> String -> Name
205extendVar (Ident n) s = Ident $ n ++ s
206extendVar n _ = n
207
208xNameParts :: XName -> (Maybe String, String)
209xNameParts n = case n of
210                XName s      -> (Nothing, s)
211                XDomName d s -> (Just d, s)
212
213---------------------------------------------------------
214-- meta-level functions, i.e. functions that represent functions,
215-- and that take arguments representing arguments... whew!
216
217metaReturn, metaConst, metaMap, metaUnzip :: Exp -> Exp
218metaReturn e = metaFunction "return" [e]
219metaConst e  = metaFunction "const" [e]
220metaMap e    = metaFunction "map" [e]
221metaUnzip e  = metaFunction "unzip" [e]
222
223metaEither, metaMaybe :: Exp -> Exp -> Exp
224metaEither e1 e2 = metaFunction "either" [e1,e2]
225metaMaybe e1 e2 = metaFunction "maybe" [e1,e2]
226
227metaConcat :: [Exp] -> Exp
228metaConcat es = metaFunction "concat" [listE es]
229
230metaAppend :: Exp -> Exp -> Exp
231metaAppend l1 l2 = infixApp l1 appendOp l2
232
233-- the +++ choice operator
234metaChoice :: Exp -> Exp -> Exp
235metaChoice e1 e2 = infixApp e1 choiceOp e2
236
237metaPCons :: Pat -> Pat -> Pat
238metaPCons p1 p2 = PInfixApp p1 cons p2
239
240metaCons, metaComp :: Exp -> Exp -> Exp
241metaCons e1 e2 = infixApp e1 (QConOp cons) e2
242metaComp e1 e2 = infixApp e1 (op fcomp) e2
243
244metaPJust :: Pat -> Pat
245metaPJust p = pApp just_name [p]
246
247metaPNothing :: Pat
248metaPNothing = pvar nothing_name
249
250metaPMkMaybe :: Maybe Pat -> Pat
251metaPMkMaybe mp = case mp of
252    Nothing -> metaPNothing
253    Just p  -> pParen $ metaPJust p
254
255metaJust :: Exp -> Exp
256metaJust e = app (var just_name) e
257
258metaNothing :: Exp
259metaNothing = var nothing_name
260
261metaMkMaybe :: Maybe Exp -> Exp
262metaMkMaybe me = case me of
263    Nothing -> metaNothing
264    Just e  -> paren $ metaJust e
265
266---------------------------------------------------
267-- some other useful functions at abstract level
268consFun, idFun :: Exp
269consFun = Con cons
270idFun = function "id"
271
272cons :: QName
273cons = Special Cons
274
275fcomp, choice, append :: Name
276fcomp = Symbol "."
277choice = Symbol "+++"
278append = Symbol "++"
279
280just_name, nothing_name, left_name, right_name :: Name
281just_name = Ident "Just"
282nothing_name = Ident "Nothing"
283left_name = Ident "Left"
284right_name = Ident "Right"
285
286------------------------------------------------------------------------
287-- Help functions for meta programming xml
288
289{- No longer used.
290hsx_data_mod :: ModuleName
291hsx_data_mod = ModuleName "HSP.Data"
292
293-- Also no longer used, literal PCDATA should be considered a string.
294-- | Create an xml PCDATA value
295metaMkPcdata :: String -> Exp
296metaMkPcdata s = metaFunction "pcdata" [strE s]
297-}
298
299-- | Create an xml tag, given its domain, name, attributes and
300-- children.
301metaGenElement :: XName -> [Exp] -> Maybe Exp -> [Exp] -> Exp
302metaGenElement name ats mat cs =
303    let (d,n) = xNameParts name
304        ne    = tuple [metaMkMaybe $ fmap strE d, strE n]
305        m = maybe id (\x y -> paren $ y `metaAppend` (metaMap $ metaAsAttr x)) mat
306        attrs = m $ listE $ map metaAsAttr ats
307     in metaFunction "genElement" [ne, attrs, listE cs]
308
309-- | Create an empty xml tag, given its domain, name and attributes.
310metaGenEElement :: XName -> [Exp] -> Maybe Exp -> Exp
311metaGenEElement name ats mat =
312    let (d,n) = xNameParts name
313        ne    = tuple [metaMkMaybe $ fmap strE d, strE n]
314        m = maybe id (\x y -> paren $ y `metaAppend` (metaMap $ metaAsAttr x)) mat
315        attrs = m $ listE $ map metaAsAttr ats
316     in metaFunction "genEElement" [ne, attrs]
317
318-- | Create an attribute by applying the overloaded @asAttr@
319metaAsAttr :: Exp -> Exp
320metaAsAttr e = metaFunction "asAttr" [e]
321
322-- | Create a property from an attribute and a value.
323metaAssign :: Exp -> Exp -> Exp
324metaAssign e1 e2 = infixApp e1 assignOp e2
325  where assignOp = QVarOp $ UnQual $ Symbol ":="
326
327-- | Make xml out of some expression by applying the overloaded function
328-- @asChild@.
329metaAsChild :: Exp -> Exp
330metaAsChild e = metaFunction "asChild" [paren e]
331
332
333-- TODO: We need to fix the stuff below so pattern matching on XML could also be overloaded.
334-- Right now it only works on HSP XML, or anything that is syntactically identical to it.
335
336-- | Lookup an attribute in the set of attributes.
337metaExtract :: XName -> Name -> Exp
338metaExtract name attrs =
339    let (d,n) = xNameParts name
340        np    = tuple [metaMkMaybe $ fmap strE d, strE n]
341     in metaFunction "extract" [np, var attrs]
342
343-- | Generate a pattern under the Tag data constructor.
344metaTag :: (Maybe String) -> String -> Pat -> Pat -> Pat
345metaTag dom name ats cpat =
346    let d = metaPMkMaybe $ fmap strP dom
347        n = pTuple [d, strP name]
348     in metaConPat "Element" [n, ats, cpat]
349
350-- | Generate a pattern under the PCDATA data constructor.
351metaPcdata :: String -> Pat
352metaPcdata s = metaConPat "CDATA" [strP s]
353
354metaMkName :: XName -> Exp
355metaMkName n = case n of
356    XName s      -> strE s
357    XDomName d s -> tuple [strE d, strE s]