------------------------------------------------------------------------------ --The files in this directory are based on the programs described in: -- -- A Modular fully-lazy lambda lifter in Haskell -- Simon L. Peyton Jones and David Lester -- Software -- Practice and Experience -- Vol 21(5), pp.479-506 -- MAY 1991 -- --See the Readme file for more details. ------------------------------------------------------------------------------ -- Instance of Text for printing expressions: instance Text Constant where showsPrec p (CNum n) = shows n showsPrec p (CFun n) = showString n instance Text (Expr [Char]) where showsPrec p (EConst k) = shows k showsPrec p (EVar v) = showString v showsPrec p e@(EAp _ _) = showChar '(' . showsAp e . showChar ')' where showsAp (EAp l r) = showsAp l . showChar ' ' . shows r showsAp e = shows e showsPrec p (ELet isRec defns body) = showString (if isRec then "letrec" else "let") . showChar ' ' . showsDefns defns . showString " in " . shows body showsPrec p (ELam binders body) = showString "(\\" . foldr1 (\h t-> h . showChar ' ' . t) (map showString binders) . showChar '.' . shows body . showChar ')' showWithSep :: Text a => String -> [a] -> ShowS showWithSep s [x] = shows x showWithSep s (x:xs) = shows x . showString s . showWithSep s xs showsDefns :: [Defn Name] -> ShowS showsDefns [] = showString "{}" showsDefns [d] = showsDefn d showsDefns defns = showChar '{' . foldr1 (\h t-> h . showString "; " . t) (map showsDefn defns) . showChar '}' showsDefn :: Defn Name -> ShowS showsDefn (x,e) = showString x . showString " = " . shows e -- display lists of supercombinators: showSCs :: [SCDefn] -> String showSCs = layn . map showSc where showSc (name,args,body) = foldr1 (\n ns -> n ++ " " ++ ns) (name:args) ++ " = " ++ show body -- Parser for input of expressions: (sorry, this is rather a hack!) number :: Parser Int number = sp (many1 (sat isDigit) `do` strToNum) where strToNum = foldl (\n d->10*n+d) 0 . map (\c->ord c - ord '0') variable :: Parser String variable = sp (sat isLower `seq` many (sat isAlpha) `do` (\(c,cs) -> c:cs)) constant :: Parser String constant = sp (sat isUpper `seq` many (sat isAlpha) `do` (\(c,cs) -> c:cs)) expr :: Parser Expression expr = sptok "letrec" `seq` variable `seq` sptok "=" `seq` expr `seq` sptok "in" `seq` expr `do` (\(lt,(v,(eq,(def,(inn,rhs)))))-> ELet True [(v,def)] rhs) `orelse` sptok "let" `seq` variable `seq` sptok "=" `seq` expr `seq` sptok "in" `seq` expr `do` (\(lt,(v,(eq,(def,(inn,rhs)))))-> ELet False [(v,def)] rhs) `orelse` sptok "\\" `seq` listOf variable (sp (okay ())) `seq` sptok "." `seq` expr `do` (\(l,(vs,(dot,e))) -> ELam vs e) `orelse` atomic atomic :: Parser Expression atomic = sptok "(" `seq` many1 expr `seq` sptok ")" `do` (\(o,(e,c))->foldl1 EAp e) `orelse` variable `do` EVar `orelse` constant `do` (EConst . CFun) `orelse` number `do` (EConst . CNum) inp :: String -> Expression inp s = case expr s of ((p,""):_) -> p _ -> error "Cannot parse input" -- Examples: ll, fll :: Expression -> String ll = showSCs . lambdaLift fll = showSCs . fullyLazyLift example1 :: Expression example1 = inp "let f = \\x. let g = \\y.(Plus (Times x x) y) in \ \(Plus (g 3) (g 4)) \ \in (f 6)" {- Results: ? ll example1 -- normal lambda lifting 1) $main = let f = SC1 in (f 6) 2) SC1 x = let g = (SC0 x) in (Plus (g 3) (g 4)) 3) SC0 x y = (Plus (Times x x) y) ? fll example1 -- fully lazy version 1) $main = let f0 = SC1 in (f0 6) 2) SC1 x1 = let v4 = (Plus (Times x1 x1)) in let g2 = (SC0 v4) in (Plus (g2 3) (g2 4)) 3) SC0 v4 y3 = (v4 y3) -} example2 :: Expression example2 = inp "let \ \ f = \\x. letrec g = \\y. (Cons (Times x x) (g y)) \ \ in (g 3) \ \in (f 6)" {- Results: ? ll example2 -- normal lambda lifting 1) $main = let f = SC1 in (f 6) 2) SC1 x = letrec g = (SC0 g x) in (g 3) 3) SC0 g x y = (Cons (Times x x) (g y)) ? fll example2 -- fully lazy version 1) $main = let f0 = SC1 in (f0 6) 2) SC1 x1 = let v4 = (Cons (Times x1 x1)) in letrec g2 = (SC0 g2 v4) in (g2 3) 3) SC0 g2 v4 y3 = (v4 (g2 y3)) -}