1 {-# LANGUAGE DataKinds #-}
2 {-# LANGUAGE FlexibleContexts #-}
3 {-# LANGUAGE FlexibleInstances #-}
4 {-# LANGUAGE InstanceSigs #-}
5 -- {-# LANGUAGE GeneralizedNewtypeDeriving #-}
6 {-# LANGUAGE MultiParamTypeClasses #-}
7 {-# LANGUAGE NamedFieldPuns #-}
8 {-# LANGUAGE NoIncoherentInstances #-}
9 {-# LANGUAGE NoMonomorphismRestriction #-}
10 {-# LANGUAGE OverloadedLists #-}
11 {-# LANGUAGE OverloadedStrings #-}
12 {-# LANGUAGE ScopedTypeVariables #-}
13 {-# LANGUAGE TupleSections #-}
14 {-# LANGUAGE TypeFamilies #-}
15 {-# LANGUAGE NoUndecidableInstances #-}
16 {-# OPTIONS_GHC -fno-warn-tabs #-}
18 module Hcompta.Repr.Text.Write where
20 import Data.Eq (Eq(..))
21 import Data.Function (($), (.))
23 import Data.Monoid ((<>))
24 import Data.Ord (Ord(..))
25 import Data.Text.Buildable (Buildable(..))
26 import qualified Data.Text.Lazy as TL
27 import qualified Data.Text.Lazy.Builder as TL
28 import Prelude (pred, succ)
29 import Text.Show (Show(..))
33 -- * Type 'Repr_Text_Write'
35 -- | /Tagless-final interpreter/
36 -- to evaluate an expression to a 'TL.Builder'.
37 newtype Repr_Text_Write h
40 :: Precedence -> Var_Depth -- inherited attributes
41 -> TL.Builder -- synthetised attributes
46 { Write_Precedence :: Precedence
47 , Write_Var_Depth :: Var_Depth
51 { Write_Syn_Text :: TL.Builder
56 repr_text_write :: Repr_Text_Write a -> TL.Builder
57 repr_text_write x = unRepr_Text_Write x precedence_Toplevel 0
58 instance Show (Repr_Text_Write a) where
59 show = TL.unpack . TL.toLazyText . repr_text_write
61 instance Expr_Lit Repr_Text_Write where
62 lit a = Repr_Text_Write $ \_p _v -> build a
63 instance Expr_Bool Repr_Text_Write where
64 and (Repr_Text_Write x) (Repr_Text_Write y) =
65 Repr_Text_Write $ \p v ->
66 let p' = precedence_And in
67 paren p p' $ x p' v <> " & " <> y p' v
68 or (Repr_Text_Write x) (Repr_Text_Write y) =
69 Repr_Text_Write $ \p v ->
70 let p' = precedence_Or in
71 paren p p' $ x p' v <> " | " <> y p' v
72 neg (Repr_Text_Write x) =
73 Repr_Text_Write $ \p v ->
74 let p' = precedence_Neg in
75 paren p p' $ "!" <> x (precedence_succ p') v
76 instance Expr_Fun Repr_Text_Write where
77 app (Repr_Text_Write f) (Repr_Text_Write x) = Repr_Text_Write $ \p v ->
78 let p' = precedence_App in
80 f p' v <> " " <> x p' v
81 lazy = repr_text_write_fun "~"
82 val = repr_text_write_fun ""
83 inline = repr_text_write_fun "!"
84 let_lazy = repr_text_write_let "~"
85 let_val = repr_text_write_let ""
86 let_inline = repr_text_write_let "!"
88 -- ** Instance 'Fun' helpers
89 repr_text_write_fun :: TL.Builder -> (Repr_Text_Write a2 -> Repr_Text_Write a1) -> Repr_Text_Write a
90 repr_text_write_fun mode e =
91 Repr_Text_Write $ \p v ->
92 let p' = precedence_Fun in
93 let x = "x" <> build v in
95 "\\" <> mode <> x <> " -> " <>
96 unRepr_Text_Write (e (Repr_Text_Write $ \_p _v -> x)) p' (succ v)
100 -> (Repr_Text_Write a3 -> Repr_Text_Write a2)
102 repr_text_write_let mode e in_ =
103 Repr_Text_Write $ \p v ->
104 let p' = precedence_Let in
105 let x = "x" <> build v in
107 "let" <> mode <> " " <> x <> " = " <> unRepr_Text_Write e p (succ v) <> " in " <>
108 unRepr_Text_Write (in_ (Repr_Text_Write $ \_p _v -> x)) p (succ v)
110 instance Expr_If Repr_Text_Write where
112 (Repr_Text_Write cond)
114 (Repr_Text_Write ko) =
115 Repr_Text_Write $ \p v ->
116 let p' = precedence_If in
118 "if " <> cond p' v <>
119 " then " <> ok p' v <>
121 when_ (Repr_Text_Write cond) (Repr_Text_Write ok) =
122 Repr_Text_Write $ \p v ->
123 let p' = precedence_If in
125 "when " <> cond p' v <>
128 -- ** Type 'Precedence'
130 -- TODO: use an Enum?
131 newtype Precedence = Precedence Int
132 deriving (Eq, Ord, Show)
133 precedence_pred :: Precedence -> Precedence
134 precedence_pred (Precedence p) = Precedence (pred p)
135 precedence_succ :: Precedence -> Precedence
136 precedence_succ (Precedence p) = Precedence (succ p)
137 paren :: Precedence -> Precedence -> TL.Builder -> TL.Builder
143 precedence_Toplevel :: Precedence
144 precedence_Toplevel = Precedence 0
145 precedence_Fun :: Precedence
146 precedence_Fun = Precedence 1
147 precedence_Let :: Precedence
148 precedence_Let = Precedence 2
149 precedence_If :: Precedence
150 precedence_If = Precedence 3
151 precedence_Or :: Precedence
152 precedence_Or = Precedence 4
153 precedence_And :: Precedence
154 precedence_And = Precedence 5
155 precedence_App :: Precedence
156 precedence_App = Precedence 6
157 precedence_Neg :: Precedence
158 precedence_Neg = Precedence 7
159 precedence_Atomic :: Precedence
160 precedence_Atomic = Precedence 8