2017-05-31 22:22:55 +03:00
|
|
|
{-# LANGUAGE GADTs, RankNTypes, ScopedTypeVariables #-}
|
2017-04-20 21:00:02 +03:00
|
|
|
module Renderer.SExpression
|
2017-05-29 23:51:32 +03:00
|
|
|
( renderSExpressionDiff
|
|
|
|
, renderSExpressionTerm
|
2017-04-20 21:00:02 +03:00
|
|
|
) where
|
2016-12-09 19:31:13 +03:00
|
|
|
|
2017-09-10 21:14:44 +03:00
|
|
|
import Data.Bifunctor (bimap)
|
2017-09-12 15:58:33 +03:00
|
|
|
import Data.ByteString.Char8 hiding (intersperse, foldr, spanEnd, length, null)
|
2017-09-10 01:01:51 +03:00
|
|
|
import Data.Foldable (fold)
|
2017-09-11 19:54:47 +03:00
|
|
|
import Data.Functor.Binding (BindingF(..), Env(..), Metavar(..))
|
2017-09-09 18:55:32 +03:00
|
|
|
import Data.Functor.Foldable (cata)
|
2017-09-09 20:14:05 +03:00
|
|
|
import Data.List (intersperse)
|
2017-03-31 23:12:26 +03:00
|
|
|
import Data.Record
|
2017-07-28 21:37:02 +03:00
|
|
|
import Data.Semigroup
|
2016-12-09 19:31:13 +03:00
|
|
|
import Diff
|
2017-09-12 15:48:53 +03:00
|
|
|
import Patch
|
2017-07-28 21:37:02 +03:00
|
|
|
import Prelude hiding (replicate)
|
2017-09-08 18:40:23 +03:00
|
|
|
import Term
|
2016-12-09 19:31:13 +03:00
|
|
|
|
2017-04-21 01:13:28 +03:00
|
|
|
-- | Returns a ByteString SExpression formatted diff.
|
2017-09-09 18:55:32 +03:00
|
|
|
renderSExpressionDiff :: (ConstrainAll Show fields, Foldable f, Functor f) => Diff f (Record fields) -> ByteString
|
2017-09-11 19:54:47 +03:00
|
|
|
renderSExpressionDiff diff = cata printBindingF diff 0 <> "\n"
|
2017-02-22 01:01:39 +03:00
|
|
|
|
2017-04-21 01:13:28 +03:00
|
|
|
-- | Returns a ByteString SExpression formatted term.
|
2017-09-09 18:55:32 +03:00
|
|
|
renderSExpressionTerm :: (ConstrainAll Show fields, Foldable f, Functor f) => Term f (Record fields) -> ByteString
|
2017-09-10 01:16:24 +03:00
|
|
|
renderSExpressionTerm term = cata (\ term n -> nl n <> replicate (2 * n) ' ' <> printTermF term n) term 0 <> "\n"
|
2017-04-20 21:00:02 +03:00
|
|
|
|
2017-09-11 19:54:47 +03:00
|
|
|
printBindingF :: (ConstrainAll Show fields, Foldable f, Functor f) => BindingF (DiffF f (Record fields)) (Int -> ByteString) -> Int -> ByteString
|
|
|
|
printBindingF bind n = case bind of
|
2017-09-12 15:58:33 +03:00
|
|
|
Let vars body | null vars -> printDiffF body n
|
|
|
|
| otherwise -> nl n <> pad n <> showBindings (($ n) <$> vars) <> printDiffF body n
|
2017-09-11 19:54:47 +03:00
|
|
|
Var v -> nl n <> pad n <> showMetavar v
|
|
|
|
|
2017-09-10 01:06:31 +03:00
|
|
|
printDiffF :: (ConstrainAll Show fields, Foldable f, Functor f) => DiffF f (Record fields) (Int -> ByteString) -> Int -> ByteString
|
2017-09-12 15:48:53 +03:00
|
|
|
printDiffF diff n = case diffF diff of
|
|
|
|
Left (Delete term) -> nl n <> pad (n - 1) <> "{-" <> printTermF term n <> "-}"
|
|
|
|
Left (Insert term) -> nl n <> pad (n - 1) <> "{+" <> printTermF term n <> "+}"
|
|
|
|
Left (Replace term1 term2) -> nl n <> pad (n - 1) <> "{ " <> printTermF term1 n
|
|
|
|
<> nl (n + 1) <> pad (n - 1) <> "->" <> printTermF term2 n <> " }"
|
|
|
|
Right (In (_, ann) syntax) -> nl n <> pad n <> "(" <> showAnnotation ann <> foldMap (\ d -> d (n + 1)) syntax <> ")"
|
2017-09-10 01:06:31 +03:00
|
|
|
|
|
|
|
printTermF :: (ConstrainAll Show fields, Foldable f, Functor f) => TermF f (Record fields) (Int -> ByteString) -> Int -> ByteString
|
2017-09-11 23:20:57 +03:00
|
|
|
printTermF (In annotation syntax) n = "(" <> showAnnotation annotation <> foldMap (\t -> t (n + 1)) syntax <> ")"
|
2017-09-10 01:16:24 +03:00
|
|
|
|
|
|
|
nl :: Int -> ByteString
|
|
|
|
nl n | n <= 0 = ""
|
|
|
|
| otherwise = "\n"
|
2017-09-10 01:06:31 +03:00
|
|
|
|
|
|
|
pad :: Int -> ByteString
|
2017-09-10 01:16:24 +03:00
|
|
|
pad n = replicate (2 * n) ' '
|
2017-09-09 23:36:18 +03:00
|
|
|
|
2016-12-09 22:30:37 +03:00
|
|
|
|
2017-05-31 22:22:55 +03:00
|
|
|
showAnnotation :: ConstrainAll Show fields => Record fields -> ByteString
|
|
|
|
showAnnotation Nil = ""
|
2017-07-28 21:37:02 +03:00
|
|
|
showAnnotation (only :. Nil) = pack (show only)
|
|
|
|
showAnnotation (first :. rest) = pack (show first) <> " " <> showAnnotation rest
|
2017-09-09 20:14:05 +03:00
|
|
|
|
2017-09-11 19:54:47 +03:00
|
|
|
showBindings :: Env ByteString -> ByteString
|
|
|
|
showBindings (Env []) = ""
|
|
|
|
showBindings (Env bindings) = "[ " <> fold (intersperse "\n, " (showBinding <$> bindings)) <> " ]"
|
2017-09-10 20:28:21 +03:00
|
|
|
where showBinding (var, val) = showMetavar var <> "/" <> val
|
2017-09-09 20:14:05 +03:00
|
|
|
|
2017-09-10 20:28:21 +03:00
|
|
|
showMetavar :: Metavar -> ByteString
|
2017-09-10 21:14:44 +03:00
|
|
|
showMetavar (Metavar i) = pack (toName i)
|
|
|
|
where toName i | i < 0 = ""
|
|
|
|
| otherwise = uncurry (++) (bimap (toName . pred) (pure . (alphabet !!)) (i `divMod` la))
|
|
|
|
alphabet = ['a'..'z']
|
|
|
|
la = length alphabet
|