git.iko.soy/rowtype-yoga/purescript-native
on cpp help sign in
234 lines 4.3 kB history raw
1-- | Common code generation utility functions
2module CodeGen.IL.Common where
4import Prelude.Compat
6import Control.Monad.Supply.Class (MonadSupply, freshName)
7import Data.Char
8import Data.Monoid ((<>))
9import Data.Text (Text)
10import qualified Data.Text as T
12import Language.PureScript.Crash
13import Language.PureScript.Names
15moduleNameToIL :: ModuleName -> Text
16moduleNameToIL (ModuleName mn) =
17 let name = T.replace "." "_" mn
18 in if nameIsILBuiltIn name then (name <> "_") else name
20-- | Convert an 'Ident' into a valid C++ identifier:
21--
22-- * Alphanumeric characters are kept unmodified.
23--
24-- * Reserved C++ identifiers are wrapped with '_'.
25--
26identToIL :: Ident -> Text
27identToIL UnusedIdent = unusedName
28identToIL (Ident "$__unused") = unusedName
29identToIL (Ident name) = properToIL name
30identToIL (GenIdent _ _) = internalError "GenIdent in identToIL"
32unusedName :: Text
33unusedName = "_"
35properToIL :: Text -> Text
36properToIL name
37 | nameIsILReserved name || nameIsILBuiltIn name || prefixIsReserved name = name <> "_"
38 | otherwise = T.concatMap identCharToText name
40-- | Test if a string is a valid AST identifier without escaping.
41identNeedsEscaping :: Text -> Bool
42identNeedsEscaping s = s /= properToIL s || T.null s
44-- | Attempts to find a human-readable name for a symbol, if none has been specified returns the
45-- ordinal value.
46identCharToText :: Char -> Text
47identCharToText c | isAlphaNum c = T.singleton c
48identCharToText '_' = "_"
49identCharToText '\'' = "Prime_"
50identCharToText '$' = "$"
51identCharToText c = "_code_point_" <> T.pack (show (ord c))
53-- | Checks whether an identifier name is reserved in C++.
54nameIsILReserved :: Text -> Bool
55nameIsILReserved name =
56 name `elem` ilAnyReserved
58-- | Checks whether a name matches a built-in value in C++.
59nameIsILBuiltIn :: Text -> Bool
60nameIsILBuiltIn name =
61 name `elem`
62 [ "final"
63 , "override"
64 , "posix"
65 , "std"
66 ]
68ilAnyReserved :: [Text]
69ilAnyReserved =
70 concat
71 [ ilKeywords
72 , ilLiterals
73 ]
75ilKeywords :: [Text]
76ilKeywords =
77 [ "alignas"
78 , "alignof"
79 , "and"
80 , "and_eq"
81 , "asm"
82 , "assert"
83 , "atomic_cancel"
84 , "atomic_commit"
85 , "atomic_noexcept"
86 , "auto"
87 , "bitand"
88 , "bitor"
89 , "bool"
90 , "break"
91 , "case"
92 , "catch"
93 , "char"
94 , "char16_t"
95 , "char32_t"
96 , "class"
97 , "compl"
98 , "concept"
99 , "const"
100 , "constexpr"
101 , "const_cast"
102 , "continue"
103 , "concept"
104 , "decltype"
105 , "default"
106 , "delete"
107 , "do"
108 , "double"
109 , "dynamic_cast"
110 , "else"
111 , "enum"
112 , "explicit"
113 , "export"
114 , "extern"
115 , "false"
116 , "float"
117 , "for"
118 , "friend"
119 , "goto"
120 , "if"
121 , "import"
122 , "inline"
123 , "int"
124 , "long"
125 , "module"
126 , "mutable"
127 , "namespace"
128 , "new"
129 , "noexcept"
130 , "not"
131 , "not_eq"
132 , "nullptr"
133 , "nullptr_t"
134 , "operator"
135 , "or"
136 , "or_eq"
137 , "private"
138 , "protected"
139 , "public"
140 , "register"
141 , "reinterpret_cast"
142 , "requires"
143 , "return"
144 , "short"
145 , "signed"
146 , "sizeof"
147 , "static"
148 , "static_assert"
149 , "static_cast"
150 , "struct"
151 , "switch"
152 , "synchronized"
153 , "template"
154 , "this"
155 , "thread_local"
156 , "throw"
157 , "true"
158 , "try"
159 , "typedef"
160 , "typeid"
161 , "typename"
162 , "typeof"
163 , "union"
164 , "unsigned"
165 , "using"
166 , "virtual"
167 , "void"
168 , "volatile"
169 , "wchar_t"
170 , "while"
171 , "xor"
172 , "xor_eq"
173 ]
175prefixIsReserved :: Text -> Bool
176prefixIsReserved name =
177 any (`T.isPrefixOf` name)
178 [ "__"
179 ]
181ilLiterals :: [Text]
182ilLiterals =
183 [ "box"
184 , "boxed"
185 , "copy"
186 , "errno"
187 , "peek"
188 , "purescript"
189 , "runtime_error"
190 , "setjmp"
191 , "string"
192 , "unbox"
193 ]
195dictType :: Text
196dictType = "dict_t"
198arrayType :: Text
199arrayType = "array_t"
201uncurriedFnType :: Int -> Text
202uncurriedFnType i = "Fn" <> (T.pack . show $ i)
204int :: Text
205int = "int"
207float :: Text
208float = "double"
210bool :: Text
211bool = "bool"
213string :: Text
214string = "string"
216auto :: Text
217auto = "const auto"
219unbox :: Text -> Text
220unbox t = "unbox<" <> t <> ">"
222arrayLengthFn :: Text
223arrayLengthFn = "array_length"
225unretainedSuffix :: Text
226unretainedSuffix = "_weak_"
228freshName' :: MonadSupply m => m Text
229freshName' = do
230 name <- freshName
231 return $ T.replace "$" "_var" name <> "_"
233moduleRenamerMarker :: Text
234moduleRenamerMarker = "__"