Skip to content
This repository was archived by the owner on Apr 1, 2025. It is now read-only.

Commit 4598da7

Browse files
committed
Define prettify direct-recursively.
This uses fromScope to recur, and accumulates a continuation for the variables to avoid n² fmaps.
1 parent 72701fe commit 4598da7

File tree

1 file changed

+55
-53
lines changed

1 file changed

+55
-53
lines changed

semantic-core/src/Data/Core/Pretty.hs

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ module Data.Core.Pretty
1111
import Control.Effect.Reader
1212
import Data.Core
1313
import Data.File
14-
import Data.Functor.Const
1514
import Data.Name
1615
import Data.Scope
1716
import Data.Term
@@ -56,57 +55,62 @@ inParens amount go = do
5655
body <- with amount go
5756
pure (encloseIf (amount >= prec) (symbol "(") (symbol ")") body)
5857

59-
prettify :: (Member (Reader [AnsiDoc]) sig, Member (Reader Prec) sig, Carrier sig m)
58+
prettify :: (Member (Reader Prec) sig, Carrier sig m)
6059
=> Style
61-
-> Core (Const (m AnsiDoc)) a
60+
-> Term Core User
6261
-> m AnsiDoc
63-
prettify style = \case
64-
Let a -> pure $ keyword "let" <+> name a
65-
Const a :>> Const b -> do
66-
prec <- ask @Prec
67-
fore <- with 12 a
68-
aft <- with 12 b
69-
70-
let open = symbol ("{" <> softline)
71-
close = symbol (softline <> "}")
72-
separator = ";" <> Pretty.line
73-
body = fore <> separator <> aft
74-
75-
pure . Pretty.align $ encloseIf (12 > prec) open close (Pretty.align body)
76-
77-
Lam n f -> inParens 11 $ do
78-
(x, body) <- bind n f
79-
pure (lambda <> x <+> arrow <+> body)
80-
81-
Frame -> pure $ primitive "frame"
82-
Unit -> pure $ primitive "unit"
83-
Bool b -> pure $ primitive (if b then "true" else "false")
84-
String s -> pure . strlit $ Pretty.viaShow s
85-
86-
Const f :$ Const x -> inParens 11 $ (<+>) <$> f <*> x
87-
88-
If (Const con) (Const tru) (Const fal) -> do
89-
con' <- "if" `appending` con
90-
tru' <- "then" `appending` tru
91-
fal' <- "else" `appending` fal
92-
pure $ Pretty.sep [con', tru', fal']
93-
94-
Load (Const p) -> "load" `appending` p
95-
Edge Lexical (Const n) -> "lexical" `appending` n
96-
Edge Import (Const n) -> "import" `appending` n
97-
Const item :. Const body -> inParens 4 $ do
98-
f <- item
99-
g <- body
100-
pure (f <> symbol "." <> g)
101-
102-
Const lhs := Const rhs -> inParens 3 $ do
103-
f <- lhs
104-
g <- rhs
105-
pure (f <+> symbol "=" <+> g)
106-
107-
-- Annotations are not pretty-printed, as it lowers the signal/noise ratio too profoundly.
108-
Ann _ (Const c) -> c
109-
where bind (Ignored x) f = let x' = name x in (,) x' <$> local (x':) (getConst (unScope f))
62+
prettify style = go (pure . name)
63+
where go :: (Member (Reader Prec) sig, Carrier sig m) => (a -> m AnsiDoc) -> Term Core a -> m AnsiDoc
64+
go var = \case
65+
Var v -> var v
66+
Term t -> case t of
67+
Let a -> pure $ keyword "let" <+> name a
68+
a :>> b -> do
69+
prec <- ask @Prec
70+
fore <- with 12 a
71+
aft <- with 12 b
72+
73+
let open = symbol ("{" <> softline)
74+
close = symbol (softline <> "}")
75+
separator = ";" <> Pretty.line
76+
body = fore <> separator <> aft
77+
78+
pure . Pretty.align $ encloseIf (12 > prec) open close (Pretty.align body)
79+
80+
Lam n f -> inParens 11 $ do
81+
(x, body) <- bind n f
82+
pure (lambda <> x <+> arrow <+> body)
83+
84+
Frame -> pure $ primitive "frame"
85+
Unit -> pure $ primitive "unit"
86+
Bool b -> pure $ primitive (if b then "true" else "false")
87+
String s -> pure . strlit $ Pretty.viaShow s
88+
89+
f :$ x -> inParens 11 $ (<+>) <$> go var f <*> go var x
90+
91+
If con tru fal -> do
92+
con' <- "if" `appending` go var con
93+
tru' <- "then" `appending` go var tru
94+
fal' <- "else" `appending` go var fal
95+
pure $ Pretty.sep [con', tru', fal']
96+
97+
Load p -> "load" `appending` go var p
98+
Edge Lexical n -> "lexical" `appending` go var n
99+
Edge Import n -> "import" `appending` go var n
100+
item :. body -> inParens 4 $ do
101+
f <- go var item
102+
g <- go var body
103+
pure (f <> symbol "." <> g)
104+
105+
lhs := rhs -> inParens 3 $ do
106+
f <- go var lhs
107+
g <- go var rhs
108+
pure (f <+> symbol "=" <+> g)
109+
110+
-- Annotations are not pretty-printed, as it lowers the signal/noise ratio too profoundly.
111+
Ann _ c -> go var c
112+
where with n m = local (const (n :: Prec)) (go var m)
113+
bind (Ignored x) f = let x' = name x in (,) x' <$> go (incr (const (pure x')) var) (fromScope f)
110114
lambda = case style of
111115
Unicode -> symbol "λ"
112116
Ascii -> symbol "\\"
@@ -119,6 +123,4 @@ appending :: Functor f => AnsiDoc -> f AnsiDoc -> f AnsiDoc
119123
appending k item = (keyword k <+>) <$> item
120124

121125
prettyCore :: Style -> Term Core User -> AnsiDoc
122-
prettyCore s = run . runReader @Prec 0 . runReader @[AnsiDoc] [] . cata id (prettify s) bound (pure . name)
123-
where bound (Z _) = asks (head @AnsiDoc)
124-
bound (S n) = local (tail @AnsiDoc) n
126+
prettyCore s = run . runReader @Prec 0 . prettify s

0 commit comments

Comments
 (0)