git.iko.soy/rowtype-yoga/purescript-native
on 90fcee2 help sign in
220 lines 4.0 kB history raw
1-- | Common code generation utility functions
2module CodeGen.Cpp.Common where
4import Prelude.Compat
6import Data.Char
7import Data.Monoid ((<>))
8import Data.Text (Text)
9import qualified Data.Text as T
11import Language.PureScript.Crash
12import Language.PureScript.Names
14moduleNameToCpp :: ModuleName -> Text
15moduleNameToCpp (ModuleName pns) =
16 let name = T.intercalate "_" (runProperName `map` pns)
17 in if nameIsCppBuiltIn name then "$$" <> name else name
19-- | Convert an 'Ident' into a valid C++ identifier:
20--
21-- * Alphanumeric characters are kept unmodified.
22--
23-- * Reserved C++ identifiers are prefixed with '$$'.
24--
25-- * Symbols are prefixed with '$' followed by a symbol name or their ordinal value.
26identToCpp :: Ident -> Text
27identToCpp UnusedIdent = unusedName
28identToCpp (Ident "$__unused") = unusedName
29identToCpp (Ident name) = properToCpp name
30identToCpp (GenIdent _ _) = internalError "GenIdent in identToCpp"
32unusedName :: Text
33unusedName = "$unused$"
35properToCpp :: Text -> Text
36properToCpp name
37 | nameIsCppReserved name || nameIsCppBuiltIn 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 /= properToCpp 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 = '$' `T.cons` T.pack (show (ord c))
53-- | Checks whether an identifier name is reserved in C++.
54nameIsCppReserved :: Text -> Bool
55nameIsCppReserved name =
56 name `elem` cppAnyReserved
58-- | Checks whether a name matches a built-in value in C++.
59nameIsCppBuiltIn :: Text -> Bool
60nameIsCppBuiltIn name =
61 name `elem`
62 [ "final"
63 , "override"
64 , "posix"
65 , "std"
66 ]
68cppAnyReserved :: [Text]
69cppAnyReserved =
70 concat
71 [ cppKeywords
72 , cppLiterals
73 ]
75cppKeywords :: [Text]
76cppKeywords =
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 ]
181cppLiterals :: [Text]
182cppLiterals =
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"
201int :: Text
202int = "int"
204float :: Text
205float = "double"
207bool :: Text
208bool = "bool"
210string :: Text
211string = "string"
213unbox :: Text -> Text
214unbox t = "unbox<" <> t <> ">"
216arrayLengthFn :: Text
217arrayLengthFn = "array_length"
219tcoLoop :: Text
220tcoLoop = "$TCO_loop$"