git.iko.soy/rowtype-yoga/purescript-native
on ba2cc5c help sign in
183 lines 3.7 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.Maybe (maybe)
9import Data.Monoid ((<>))
10import Data.Text (Text)
11import qualified Data.Text as T
13import Language.PureScript.Crash
14import Language.PureScript.Names
16import qualified Language.PureScript.Constants as C
18moduleNameToIL :: ModuleName -> Text
19moduleNameToIL (ModuleName pns) =
20 let name = T.intercalate "_" (runProperName `map` pns)
21 in moduleNameToIL' name
23moduleNameToIL' :: Text -> Text
24moduleNameToIL' name =
25 if moduleIsReserved name then (name <> "_") else name
27-- | Convert an 'Ident' into a valid IL identifier:
28--
29-- * Alphanumeric characters are kept unmodified.
30--
31-- * Reserved IL identifiers are wrapped with '_'.
32--
33identToIL :: Ident -> Text
34identToIL UnusedIdent = unusedName
35identToIL (Ident "$__unused") = unusedName
36identToIL (Ident name) | name == C.undefined = undefinedName
37identToIL (Ident name) = properToIL name
38identToIL (GenIdent _ _) = internalError "GenIdent in identToIL"
40moduleIdentToIL :: Ident -> Text
41moduleIdentToIL UnusedIdent = unusedName
42moduleIdentToIL (Ident name) | name == C.undefined = undefinedName
43moduleIdentToIL (Ident name) = moduleProperToIL name
44moduleIdentToIL (GenIdent _ _) = internalError "GenIdent in identToIL"
46undefinedName :: Text
47undefinedName = "Undefined"
49unusedName :: Text
50unusedName = "_"
52properToIL :: Text -> Text
53properToIL name
54 | nameIsILReserved name || nameIsILBuiltIn name || prefixIsReserved name = name <> "ˉ"
55 | otherwise = T.concatMap identCharToText name
57-- | Attempts to find a human-readable name for a symbol, if none has been specified returns the
58-- ordinal value.
59identCharToText :: Char -> Text
60identCharToText c | isAlphaNum c = T.singleton c
61identCharToText '_' = "_"
62identCharToText '\'' = "ʹ"
63identCharToText c = "ᵤ" <> T.pack (show (ord c))
65moduleProperToIL :: Text -> Text
66moduleProperToIL = T.concatMap identCharToText
68-- | Checks whether an identifier name is reserved in IL.
69nameIsILReserved :: Text -> Bool
70nameIsILReserved name =
71 name `elem` ilAnyReserved
73-- | Checks whether a name matches a built-in value in IL.
74nameIsILBuiltIn :: Text -> Bool
75nameIsILBuiltIn name =
76 name `elem`
77 [
78 ]
80ilAnyReserved :: [Text]
81ilAnyReserved =
82 concat
83 [ ilKeywords
84 , ilLiterals
85 ]
87ilKeywords :: [Text]
88ilKeywords =
89 [ "break"
90 , "case"
91 , "chan"
92 , "const"
93 , "continue"
94 , "default"
95 , "defer"
96 , "else"
97 , "fallthrough"
98 , "for"
99 , "func"
100 , "go"
101 , "goto"
102 , "if"
103 , "import"
104 , "interface"
105 , "map"
106 , "package"
107 , "range"
108 , "return"
109 , "select"
110 , "struct"
111 , "switch"
112 , "type"
113 , "var"
114 ]
116moduleIsReserved :: Text -> Bool
117moduleIsReserved "Main" = False
118moduleIsReserved name = not $ T.isInfixOf "_" name
120prefixIsReserved :: Text -> Bool
121prefixIsReserved name =
122 any (`T.isPrefixOf` name)
123 [
124 ]
126ilLiterals :: [Text]
127ilLiterals =
128 [ "init"
129 , "nil"
130 , "int"
131 , "int8"
132 , "int16"
133 , "int32"
134 , "int64"
135 , "uint"
136 , "uint8"
137 , "uint16"
138 , "uint32"
139 , "uint64"
140 , "uintptr"
141 , "float32"
142 , "float64"
143 , "complex64"
144 , "complex128"
145 , "byte"
146 , "rune"
147 , "string"
148 ]
150withPrefix :: Text -> Text
151withPrefix s = "PS__" <> s
153anyType :: Text
154anyType = "Any"
156dictType :: Text
157dictType = "map[string]Any"
159arrayType :: Text
160arrayType = "[]Any"
162int :: Text
163int = "int"
165float :: Text
166float = "float64"
168bool :: Text
169bool = "bool"
171string :: Text
172string = "string"
174arrayLengthFn :: Text
175arrayLengthFn = "Length"
177tcoLoop :: Text
178tcoLoop = "ᵗᶜloop"
180freshName' :: MonadSupply m => m Text
181freshName' = do
182 name <- freshName
183 return $ T.replace "$" "ᵗ" name