on master help sign in
Start using the PrettyPrint library to show expressions, literals, and patterns.
commitf2b3ed7027422b479821124cca22bd18479d3740 authorEvan Czaplicki <evan@Evans-MacBook-Air.local> dateSun 7 Jul 2013, 12:56 (13 years ago) parent078692a
9 files changed+170−117
compiler/Parse/Expression.hs+28−27 compiler/Parse/Type.hs+3−3 compiler/SourceSyntax/Declaration.hs+2−2 compiler/SourceSyntax/Everything.hs+1−1 compiler/SourceSyntax/Expression.hs+78−52 compiler/SourceSyntax/Helpers.hs+5−4 compiler/SourceSyntax/Literal.hs+11−10 compiler/SourceSyntax/Pattern.hs+27−18 compiler/SourceSyntax/PrettyPrint.hs+15
compiler/Parse/Expression.hs+28−27
@@ -1,4 +1,4 @@
1−module Parse.Expression (def,term) where
1+module Parse.Expression {-(def,term)-} where
22
33import Control.Applicative ((<$>), (<*>))
44import Data.List (foldl')
@@ -12,6 +12,7 @@ import qualified Parse.Type as Type
1212import Parse.Binop
1313import Parse.Literal
1414
15+import SourceSyntax.PrettyPrint
1516import SourceSyntax.Location as Location
1617import SourceSyntax.Pattern hiding (tuple,list)
1718import qualified SourceSyntax.Literal as Literal
@@ -21,14 +22,13 @@ import SourceSyntax.Declaration (Declaration(Definition))
2122import Unique
2223import Types.Types (Type (VarT), Scheme (Forall))
2324
24−import System.IO.Unsafe
25−
2625
2726-------- Basic Terms --------
2827
2928varTerm :: IParser (Expr t v)
3029varTerm = toVar <$> var <?> "variable"
3130
31+toVar :: String -> Expr t v
3232toVar v = case v of "True" -> Literal (Literal.Boolean True)
3333 "False" -> Literal (Literal.Boolean False)
3434 _ -> Var v
@@ -39,7 +39,7 @@ accessor = do
3939 lbl <- try (string "." >> rLabel)
4040 end <- getPosition
4141 let loc e = Location.add ("." ++ lbl) (Location.at start end e)
42− return (Lambda "_" (loc $ Access (loc $ Var "_") lbl))
42+ return (Lambda (PVar "_") (loc $ Access (loc $ Var "_") lbl))
4343
4444
4545-------- Complex Terms --------
@@ -61,7 +61,7 @@ parensTerm = parens $ choice
6161 op <- try anyOp
6262 end <- getPosition
6363 let loc = Location.at start end
64− return . loc . Lambda "x" . loc . Lambda "y" . loc $
64+ return . loc . Lambda (PVar "x") . loc . Lambda (PVar "y") . loc $
6565 Binop op (loc $ Var "x") (loc $ Var "y")
6666 , do start <- getPosition
6767 let comma = char ',' <?> "comma ','"
@@ -70,7 +70,7 @@ parensTerm = parens $ choice
7070 let vars = map (('v':) . show) [ 0 .. length commas + 1 ]
7171 loc = Location.at start end
7272 return $ foldr (\x e -> loc $ Lambda x e)
73− (loc . tuple $ map (loc . Var) vars) vars
73+ (loc . tuple $ map (loc . Var) vars) (map PVar vars)
7474 , do start <- getPosition
7575 es <- commaSep expr
7676 end <- getPosition
@@ -83,14 +83,11 @@ recordTerm = brackets $ choice [ misc, addLocation record ]
8383 where field = do
8484 label <- rLabel
8585 patterns <- spacePrefix Pattern.term
86− whitespace
87− e <- string "=" >> whitespace >> expr
88− return (label, foldr Lambda e patterns)
86+ whitespace >> string "=" >> whitespace
87+ body <- expr
88+ return (label, makeFunction patterns body)
8989
90− extract [ Def f args exp ] = return (f,args,exp)
91− extract _ = fail "Improperly formed record field."
92−
93− record = Record <$> (mapM extract =<< commaSep field)
90+ record = Record <$> commaSep field
9491
9592 change = do
9693 lbl <- rLabel
@@ -156,13 +153,13 @@ ifExpr = reserved "if" >> whitespace >> (normal <|> multiIf)
156153lambdaExpr :: IParser (LExpr t v)
157154lambdaExpr = do char '\\' <|> char '\x03BB' <?> "anonymous function"
158155 whitespace
159− pats <- spaceSep1 Pattern.term
156+ args <- spaceSep1 Pattern.term
160157 whitespace ; arrow ; whitespace
161− e <- expr
162− return (foldr Lambda pats e)
158+ body <- expr
159+ return (makeFunction args body)
163160
164161defSet :: IParser [Def t v]
165−defSet = concat <$> block (do d <- anyDef ; whitespace ; return d)
162+defSet = block (do d <- anyDef ; whitespace ; return d)
166163
167164letExpr :: IParser (Expr t v)
168165letExpr = do
@@ -197,19 +194,23 @@ funcDef = try (do p1 <- try Pattern.term ; infics p1 <|> func p1)
197194 return $ if o == '`' then [ PVar $ takeWhile (/='`') p, p1, p2 ]
198195 else [ PVar (o:p), p1, p2 ]
199196
200−assignExpr :: IParser [Def t v]
197+makeFunction :: [Pattern] -> LExpr t v -> LExpr t v
198+makeFunction args body@(L a b _) =
199+ let pos = L a b in
200+ foldr (\arg body' -> pos $ Lambda arg body') body args
201+
202+assignExpr :: IParser (Def t v)
201203assignExpr = withPos $ do
202− fDefs <- funcDef
203− whitespace
204− e <- string "=" >> whitespace >> expr
205− n <- sourceLine <$> getPosition
206− runAt (1000 * n) $ Pattern.flatten fDefs e
204+ (name:args) <- funcDef
205+ whitespace >> string "=" >> whitespace
206+ body <- expr
207+ return . Def name $ makeFunction args body
207208
208−anyDef =
209− ((\d -> [d]) <$> Type.annotation) <|>
210− assignExpr
209+anyDef :: IParser (Def t v)
210+anyDef = Type.annotation <|> assignExpr
211211
212−def = map Definition <$> anyDef
212+def :: IParser (Declaration t v)
213+def = Definition <$> anyDef
213214
214215parseDef str =
215216 case iParse def "" str of
compiler/Parse/Type.hs+3−3
@@ -85,9 +85,9 @@ typeAlias = do
8585 Right t -> return (TypeAlias alias [1..n] t : ctor)
8686 where ctor = case tipe of
8787 RecordPT extension kvs ->
88− [toConstructor start end alias extension kvs]
88+ [] --toConstructor start end alias extension kvs]
8989 _ -> []
90−
90+{--
9191toConstructor start end alias Nothing kvs =
9292 Definition (Def alias args (loc (Record rec)))
9393 where
@@ -102,7 +102,7 @@ toConstructor start end alias (Just _) kvs =
102102 args = map fst kvs
103103 rec = foldl insert (Var "_ext_") (zip args (map (loc . Var) args))
104104 insert e (k,v) = Insert (loc e) k v
105−
105+--}
106106annotation :: IParser (Def t v)
107107annotation = TypeAnnotation <$> try start <*> (toType <$> typeExpr)
108108 where start = do v <- lowVar <|> parens symOp
compiler/SourceSyntax/Declaration.hs+2−2
@@ -12,7 +12,7 @@ data Declaration tipe var
1212 | ImportEvent String (Expr.LExpr tipe var) String Type
1313 | ExportEvent String String Type
1414 | Fixity Assoc Int String
15− deriving (Eq, Show, Data, Typeable)
15+ deriving (Eq, Show, Data, Typeable, Show)
1616
1717data Assoc = L | N | R
18− deriving (Eq, Show, Data, Typeable)
18+ deriving (Eq, Show, Data, Typeable, Show)
compiler/SourceSyntax/Everything.hs+1−1
@@ -12,7 +12,7 @@ module SourceSyntax.Everything
1212import SourceSyntax.Helpers
1313import SourceSyntax.Location
1414import SourceSyntax.Literal
15−import SourceSyntax.Pattern hiding (tuple, list, cons, nil)
15+import SourceSyntax.Pattern hiding (tuple, list, cons, nil, prettyParens)
1616import SourceSyntax.Expression
1717import SourceSyntax.Declaration hiding (Assoc(..))
1818import SourceSyntax.Module
compiler/SourceSyntax/Expression.hs+78−52
@@ -4,6 +4,8 @@ module SourceSyntax.Expression where
44import Data.Data
55import Data.List (intercalate)
66import qualified Text.Pandoc as Pandoc
7+import SourceSyntax.PrettyPrint
8+import Text.PrettyPrint as PP
79import qualified SourceSyntax.Helpers as Help
810import qualified SourceSyntax.Location as Location
911import qualified SourceSyntax.Pattern as Pattern
@@ -29,70 +31,94 @@ data Expr t v
2931 | Modify (LExpr t v) [(String, LExpr t v)]
3032 | Record [(String, LExpr t v)]
3133 | Markdown Pandoc.Pandoc
32− deriving (Eq, Data, Typeable)
34+ deriving (Eq, Data, Typeable, Show)
3335
3436data Def tipe var
3537 = Def Pattern.Pattern (LExpr tipe var)
3638 | TypeAnnotation String Type
37− deriving (Eq, Data, Typeable)
39+ deriving (Eq, Data, Typeable, Show)
3840
3941tuple es = Data ("Tuple" ++ show (length es)) es
4042
4143delist (Location.L _ _ (Data "::" [h,t])) = h : delist t
4244delist _ = []
4345
44−
45−instance Show (Expr t v) where
46− show e =
47− let show' (Location.L _ _ e) = Help.parensIf (needsParens e) (show e) in
48− case e of
49− Literal lit -> show lit
50− Range e1 e2 -> "[" ++ show e1 ++ ".." ++ show e2 ++ "]"
51− ExplicitList es -> "[" ++ intercalate "," (map show es) ++ "]"
52− Binop op e1 e2 -> show' e1 ++ " " ++ op ++ " " ++ show' e2
53− Lambda x e -> let (xs,e') = getLambdas (Location.none $ Lambda x e) in
54− concat [ "\\", intercalate " " xs, " -> ", show e' ]
55− App e1 e2 -> show' e1 ++ " " ++ show' e2
56− MultiIf (p:ps) -> concat [ "if | ", iff p, sep (map iff ps) ]
57− where iff (b,e) = show b ++ " -> " ++ show e
58− sep = concatMap ("\n | " ++)
59− Let defs e -> "let { "++intercalate " ; " (map show defs)++" } in "++show e
60− Var (c:cs) -> if Help.isOp c then Help.parens (c:cs) else c:cs
61− Case e pats -> "case "++ show e ++" of " ++ Help.brkt (intercalate " ; " pats')
62− where pats' = map (\(p,e) -> show p ++ " -> " ++ show e) pats
63− Data "::" [h,t] -> show h ++ " :: " ++ show t
64− Data "[]" [] -> "[]"
65− Data name es -> name ++ " " ++ intercalate " " (map show' es)
66− Access e x -> show' e ++ "." ++ x
67− Remove e x -> Help.brkt (show e ++ " - " ++ x)
46+instance Pretty (Expr t v) where
47+ pretty expr =
48+ case expr of
49+ Literal lit -> pretty lit
50+ Var x@(c:_) -> parensIf (Help.isOp c) (PP.text x)
51+ Range e1 e2 -> PP.brackets (pretty e1 <> PP.text ".." <> pretty e2)
52+ ExplicitList es -> PP.brackets (commaCat (map pretty es))
53+ Binop op e1 e2 -> PP.sep [ prettyParens e1 <+> PP.text op, prettyParens e2 ]
54+ Lambda p e -> let (ps,body) = collectLambdas (Location.none $ Lambda p e)
55+ in PP.text "\\" <> PP.sep ps <+> PP.text "->" <+> pretty body
56+ App _ _ -> PP.hang func 2 (PP.sep args)
57+ where func:args = map prettyParens (collectApps (Location.none expr))
58+ MultiIf branches -> PP.text "if" $$ nest 3 (vcat $ map iff branches)
59+ where
60+ iff (b,e) = PP.text "|" <+> PP.hang (pretty b <+> PP.text "->") 2 (pretty e)
61+ Let defs e ->
62+ PP.sep [ PP.hang (PP.text "let") 4 (PP.vcat (map pretty defs))
63+ , PP.text "in" <+> pretty e ]
64+ Case e pats ->
65+ PP.hang pexpr 2 (PP.vcat (map pretty' pats))
66+ where
67+ pexpr = PP.sep [ PP.text "case" <+> pretty e, PP.text "of" ]
68+ pretty' (p,e) = pretty p <+> PP.text "->" <+> pretty e
69+ Data "::" [hd,tl] -> pretty hd <+> PP.text "::" <+> pretty tl
70+ Data "[]" [] -> PP.text "[]"
71+ Data name es -> PP.hang (PP.text name) 2 (PP.sep (map prettyParens es))
72+ Access e x -> prettyParens e <> PP.text "." <> PP.text x
73+ Remove e x -> PP.braces (pretty e <+> PP.text "-" <+> PP.text x)
6874 Insert (Location.L _ _ (Remove e y)) x v ->
69− Help.brkt (show e ++ " - " ++ y ++ " | " ++ x ++ " = " ++ show v)
70− Insert e x v -> Help.brkt (show e ++ " | " ++ x ++ " = " ++ show v)
71− Modify e fs -> Help.brkt (show e ++" | "++ intercalate ", " (map field fs))
72− where field (x,e) = x ++ " <- " ++ show e
73− Record r -> Help.brkt (intercalate ", " (map fields r))
74− where fields (f,e) = f ++ " = " ++ show e
75− Markdown _ -> "[markdown| ... |]"
75+ PP.braces (pretty e <+> PP.text "-" <+> PP.text y <+> PP.text "|" <+> PP.text x <+> PP.text "=" <+> pretty v)
76+ Insert e x v ->
77+ PP.braces (pretty e <+> PP.text "|" <+> PP.text x <+> PP.text "=" <+> pretty v)
78+
79+ Modify e fs ->
80+ PP.braces $ PP.hang (pretty e <+> PP.text "|")
81+ 4
82+ (PP.sep . PP.punctuate PP.comma $ map field fs)
83+ where
84+ field (x,e) = PP.text x <+> PP.text "<-" <+> pretty e
85+
86+ Record fs ->
87+ PP.braces $ PP.nest 2 (PP.sep . PP.punctuate PP.comma $ map field fs)
88+ where
89+ field (x,e) = PP.text x <+> PP.text "=" <+> pretty e
90+
91+ Markdown _ -> PP.text "[markdown| ... |]"
7692
93+instance Pretty (Def t v) where
94+ pretty def =
95+ case def of
96+ TypeAnnotation name tipe ->
97+ PP.text name <+> PP.text ":" <+> PP.text (show tipe)
98+ Def pattern expr ->
99+ pretty pattern <+> PP.text "=" <+> pretty expr
77100
78−instance Show (Def t v) where
79− show e =
80− case e of
81− TypeAnnotation n t -> n ++ " : " ++ show t
82− Def pattern e ->
83− show pattern ++ " = " ++ show e
101+collectApps lexpr@(Location.L _ _ expr) =
102+ case expr of
103+ App a b -> collectApps a ++ [b]
104+ _ -> [lexpr]
84105
85−getLambdas (Location.L _ _ (Lambda x e)) = (show x:xs,e')
86− where (xs,e') = getLambdas e
87−getLambdas e = ([],e)
106+collectLambdas lexpr@(Location.L _ _ expr) =
107+ case expr of
108+ Lambda pattern body ->
109+ let (ps, body') = collectLambdas body
110+ in (pretty pattern : ps, body')
111+ _ -> ([], lexpr)
88112
89−needsParens e =
90− case e of
91− Binop _ _ _ -> True
92− Lambda _ _ -> True
93− App _ _ -> True
94− MultiIf _ -> True
95− Let _ _ -> True
96− Case _ _ -> True
97− Data name (x:xs) -> name /= "::"
98− _ -> False
113+prettyParens (Location.L _ _ expr) = parensIf needed (pretty expr)
114+ where
115+ needed =
116+ case expr of
117+ Binop _ _ _ -> True
118+ Lambda _ _ -> True
119+ App _ _ -> True
120+ MultiIf _ -> True
121+ Let _ _ -> True
122+ Case _ _ -> True
123+ Data name (x:xs) -> name /= "::"
124+ _ -> False
compiler/SourceSyntax/Helpers.hs+5−4
@@ -1,11 +1,12 @@
11
22module SourceSyntax.Helpers where
33
4−import Data.Char (isSymbol)
4+import Data.Char (isSymbol,isDigit)
55
66brkt s = "{ " ++ s ++ " }"
77
8−parens s = "(" ++ s ++ ")"
9−parensIf b s = if b then parens s else s
8+isTuple name =
9+ take 5 name == "Tuple" && all isDigit (drop 5 name)
1010
11−isOp c = isSymbol c || elem c "+-/*=.$<>:&|^?%#@~!"
11+isOp c =
12+ isSymbol c || elem c "+-/*=.$<>:&|^?%#@~!"
compiler/SourceSyntax/Literal.hs+11−10
@@ -2,20 +2,21 @@
22module SourceSyntax.Literal where
33
44import Data.Data
5+import SourceSyntax.PrettyPrint
6+import qualified Text.PrettyPrint as PP
57
68data Literal = IntNum Int
79 | FloatNum Float
810 | Chr Char
911 | Str String
1012 | Boolean Bool
11− deriving (Eq, Ord, Data, Typeable)
13+ deriving (Eq, Ord, Data, Typeable, Show)
1214
13−
14−instance Show Literal where
15− show e =
16− case e of
17− IntNum n -> show n
18− FloatNum n -> show n
19− Chr c -> show c
20− Str s -> show s
21− Boolean b -> show b
15+instance Pretty Literal where
16+ pretty literal =
17+ case literal of
18+ IntNum n -> PP.int n
19+ FloatNum n -> PP.float n
20+ Chr c -> PP.char c
21+ Str s -> PP.text (show s)
22+ Boolean bool -> PP.text (show bool)
compiler/SourceSyntax/Pattern.hs+27−18
@@ -1,11 +1,12 @@
11{-# LANGUAGE DeriveDataTypeable #-}
22module SourceSyntax.Pattern where
33
4−import Data.Char (isDigit)
54import Data.List (intercalate)
65import Data.Data
76import SourceSyntax.Helpers
8−import qualified SourceSyntax.Literal as Literal
7+import SourceSyntax.PrettyPrint
8+import Text.PrettyPrint as PP
9+import SourceSyntax.Literal as Literal
910
1011data Pattern = PData String [Pattern]
1112 | PRecord [String]
@@ -13,7 +14,7 @@ data Pattern = PData String [Pattern]
1314 | PVar String
1415 | PAnything
1516 | PLiteral Literal.Literal
16− deriving (Eq, Ord, Data, Typeable)
17+ deriving (Eq, Ord, Data, Typeable, Show)
1718
1819cons h t = PData "::" [h,t]
1920nil = PData "[]" []
@@ -21,19 +22,27 @@ list = foldr cons nil
2122tuple es = PData ("Tuple" ++ show (length es)) es
2223
2324
24−instance Show Pattern where
25− show p =
26− case p of
27− PVar x -> x
28− PLiteral lit -> show lit
29− PRecord fs -> brkt (intercalate ", " fs)
30− PAlias x p -> show p ++ " as " ++ x
31− PAnything -> "_"
32− PData "::" [hd@(PData "::" _),tl] ->
33− parens (show hd) ++ " :: " ++ show tl
34− PData "::" [hd,tl] -> show hd ++ " :: " ++ show tl
35− PData "[]" [] -> "[]"
25+instance Pretty Pattern where
26+ pretty pattern =
27+ case pattern of
28+ PVar x -> PP.text x
29+ PLiteral lit -> pretty lit
30+ PRecord fs -> PP.braces (commaCat $ map PP.text fs)
31+ PAlias x p -> prettyParens p <+> PP.text "as" <+> PP.text x
32+ PAnything -> PP.text "_"
33+ PData "::" [hd,tl] -> parensIf isCons (pretty hd) <+> PP.text "::" <+> pretty tl
34+ where isCons = case hd of
35+ PData "::" _ -> True
36+ _ -> False
3637 PData name ps ->
37− if take 5 name == "Tuple" && all isDigit (drop 5 name) then
38− parens . intercalate ", " $ map show ps
39− else parensIf (not (null ps)) $ unwords (name : map show ps)
38+ if isTuple name then
39+ PP.parens . commaCat $ map pretty ps
40+ else sep (PP.text name : map prettyParens ps)
41+
42+prettyParens pattern = parensIf needsThem (pretty pattern)
43+ where
44+ needsThem =
45+ case pattern of
46+ PData name (_:_) | not (isTuple name) -> True
47+ PAlias _ _ -> True
48+ _ -> False
compiler/SourceSyntax/PrettyPrint.hsnew file+15
@@ -0,0 +1,15 @@
1+
2+module SourceSyntax.PrettyPrint where
3+
4+import Text.PrettyPrint
5+import SourceSyntax.Location
6+
7+class Pretty a where
8+ pretty :: a -> Doc
9+
10+instance Pretty a => Pretty (Located a) where
11+ pretty (L _ _ e) = pretty e
12+
13+commaCat docs = cat (punctuate comma docs)
14+
15+parensIf bool doc = if bool then parens doc else doc