2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[Literal]{@Literal@: Machine literals (unboxed, of course)}
7 #include "HsVersions.h"
12 mkMachInt, mkMachWord,
13 literalType, literalPrimRep,
15 isNoRepLit, isLitLitLit
22 import PrimRep ( PrimRep(..) ) -- non-abstract
23 import TysPrim ( getPrimRepInfo,
24 addrPrimTy, intPrimTy, floatPrimTy,
25 doublePrimTy, charPrimTy, wordPrimTy )
28 import CStrings ( stringToC, charToC, charToEasyHaskell )
29 import TysWiredIn ( stringTy )
30 import Pretty -- pretty-printing stuff
31 import PprStyle ( PprStyle(..), codeStyle )
32 import Util ( thenCmp, panic )
35 So-called @Literals@ are {\em either}:
38 An unboxed (``machine'') literal (type: @IntPrim@, @FloatPrim@, etc.),
39 which is presumed to be surrounded by appropriate constructors
40 (@mKINT@, etc.), so that the overall thing makes sense.
42 An Integer, Rational, or String literal whose representation we are
43 {\em uncommitted} about; i.e., the surrounding with constructors,
44 function applications, etc., etc., has not yet been done.
51 | MachAddr Integer -- whatever this machine thinks is a "pointer"
52 | MachInt Integer -- for the numeric types, these are
53 Bool -- True <=> signed (Int#); False <=> unsigned (Word#)
56 | MachLitLit FAST_STRING
59 | NoRepStr FAST_STRING -- the uncommitted ones
60 | NoRepInteger Integer Type{-save what we learned in the typechecker-}
61 | NoRepRational Rational Type{-ditto-}
63 -- deriving (Eq, Ord): no, don't want to compare Types
64 -- The Ord is needed for the FiniteMap used in the lookForConstructor
65 -- in SimplEnv. If you declared that lookForConstructor *ignores*
66 -- constructor-applications with LitArg args, then you could get
69 mkMachInt, mkMachWord :: Integer -> Literal
71 mkMachInt x = MachInt x True{-signed-}
72 mkMachWord x = MachInt x False{-unsigned-}
74 instance Ord3 Literal where
75 cmp (MachChar a) (MachChar b) = a `tcmp` b
76 cmp (MachStr a) (MachStr b) = a `tcmp` b
77 cmp (MachAddr a) (MachAddr b) = a `tcmp` b
78 cmp (MachInt a b) (MachInt c d) = (a `tcmp` c) `thenCmp` (b `tcmp` d)
79 cmp (MachFloat a) (MachFloat b) = a `tcmp` b
80 cmp (MachDouble a) (MachDouble b) = a `tcmp` b
81 cmp (MachLitLit a b) (MachLitLit c d) = (a `tcmp` c) `thenCmp` (b `tcmp` d)
82 cmp (NoRepStr a) (NoRepStr b) = a `tcmp` b
83 cmp (NoRepInteger a _) (NoRepInteger b _) = a `tcmp` b
84 cmp (NoRepRational a _) (NoRepRational b _) = a `tcmp` b
86 -- now we *know* the tags are different, so...
88 | tag1 _LT_ tag2 = LT_
94 tagof (MachChar _) = ILIT(1)
95 tagof (MachStr _) = ILIT(2)
96 tagof (MachAddr _) = ILIT(3)
97 tagof (MachInt _ _) = ILIT(4)
98 tagof (MachFloat _) = ILIT(5)
99 tagof (MachDouble _) = ILIT(6)
100 tagof (MachLitLit _ _) = ILIT(7)
101 tagof (NoRepStr _) = ILIT(8)
102 tagof (NoRepInteger _ _) = ILIT(9)
103 tagof (NoRepRational _ _) = ILIT(10)
105 tcmp x y = case _tagCmp x y of { _LT -> LT_; _EQ -> EQ_; GT__ -> GT_ }
107 instance Eq Literal where
108 a == b = case (a `cmp` b) of { EQ_ -> True; _ -> False }
109 a /= b = case (a `cmp` b) of { EQ_ -> False; _ -> True }
111 instance Ord Literal where
112 a <= b = case (a `cmp` b) of { LT_ -> True; EQ_ -> True; GT__ -> False }
113 a < b = case (a `cmp` b) of { LT_ -> True; EQ_ -> False; GT__ -> False }
114 a >= b = case (a `cmp` b) of { LT_ -> False; EQ_ -> True; GT__ -> True }
115 a > b = case (a `cmp` b) of { LT_ -> False; EQ_ -> False; GT__ -> True }
116 _tagCmp a b = case (a `cmp` b) of { LT_ -> _LT; EQ_ -> _EQ; GT__ -> _GT }
120 isNoRepLit (NoRepStr _) = True -- these are not primitive typed!
121 isNoRepLit (NoRepInteger _ _) = True
122 isNoRepLit (NoRepRational _ _) = True
125 isLitLitLit (MachLitLit _ _) = True
126 isLitLitLit _ = False
130 literalType :: Literal -> Type
132 literalType (MachChar _) = charPrimTy
133 literalType (MachStr _) = addrPrimTy
134 literalType (MachAddr _) = addrPrimTy
135 literalType (MachInt _ signed) = if signed then intPrimTy else wordPrimTy
136 literalType (MachFloat _) = floatPrimTy
137 literalType (MachDouble _) = doublePrimTy
138 literalType (MachLitLit _ k) = case (getPrimRepInfo k) of { (_,t,_) -> t }
139 literalType (NoRepInteger _ t) = t
140 literalType (NoRepRational _ t) = t
141 literalType (NoRepStr _) = stringTy
145 literalPrimRep :: Literal -> PrimRep
147 literalPrimRep (MachChar _) = CharRep
148 literalPrimRep (MachStr _) = AddrRep -- specifically: "char *"
149 literalPrimRep (MachAddr _) = AddrRep
150 literalPrimRep (MachInt _ signed) = if signed then IntRep else WordRep
151 literalPrimRep (MachFloat _) = FloatRep
152 literalPrimRep (MachDouble _) = DoubleRep
153 literalPrimRep (MachLitLit _ k) = k
155 literalPrimRep (NoRepInteger _ _) = panic "literalPrimRep:NoRepInteger"
156 literalPrimRep (NoRepRational _ _) = panic "literalPrimRep:NoRepRational"
157 literalPrimRep (NoRepStr _) = panic "literalPrimRep:NoRepString"
161 The boring old output stuff:
163 ppCast :: PprStyle -> FAST_STRING -> Pretty
164 ppCast PprForC cast = ppPStr cast
167 instance Outputable Literal where
168 ppr sty (MachChar ch)
172 PprForC -> charToC ch
173 PprForAsm _ _ -> charToC ch
174 PprUnfolding -> charToEasyHaskell ch
177 ppBeside (ppBesides [ppCast sty SLIT("(C_)"), ppChar '\'', ppStr char_encoding, ppChar '\''])
181 = ppBeside (if codeStyle sty
182 then ppBesides [ppChar '"', ppStr (stringToC (_UNPK_ s)), ppChar '"']
183 else ppStr (show (_UNPK_ s)))
186 ppr sty (MachAddr p) = ppBesides [ppCast sty SLIT("(void*)"), ppInteger p, if_ubxd sty]
187 ppr sty (MachInt i signed)
189 && ((signed && (i >= toInteger minInt && i <= toInteger maxInt))
190 || (not signed && (i >= toInteger 0 && i <= toInteger maxInt)))
191 -- ToDo: Think about these ranges!
192 = ppBesides [ppInteger i, if_ubxd sty]
194 | not (codeStyle sty) -- we'd prefer the code to the error message
195 = ppBesides [ppInteger i, if_ubxd sty]
198 = error ("ERROR: Int " ++ show i ++ " out of range [" ++
199 show range_min ++ " .. " ++ show maxInt ++ "]\n")
201 range_min = if signed then minInt else 0
203 ppr sty (MachFloat f) = ppBesides [ppCast sty SLIT("(StgFloat)"), ppRational f, if_ubxd sty]
204 ppr sty (MachDouble d) = ppBesides [ppRational d, if_ubxd sty, if_ubxd sty]
206 ppr sty (NoRepInteger i _)
207 | codeStyle sty = ppInteger i
208 | ufStyle sty = ppCat [ppStr "_NOREP_I_", ppInteger i]
209 | otherwise = ppBesides [ppInteger i, ppChar 'I']
211 ppr sty (NoRepRational r _)
212 | ufStyle sty = ppCat [ppStr "_NOREP_R_", ppInteger (numerator r), ppInteger (denominator r)]
213 | codeStyle sty = panic "ppr.ForC.NoRepRational"
214 | otherwise = ppBesides [ppRational r, ppChar 'R']
217 | codeStyle sty = ppBesides [ppStr (show (_UNPK_ s))]
218 | ufStyle sty = ppCat [ppStr "_NOREP_S_", ppStr (show (_UNPK_ s))]
219 | otherwise = ppBesides [ppStr (show (_UNPK_ s)), ppChar 'S']
221 ppr sty (MachLitLit s k)
222 | codeStyle sty = ppPStr s
223 | ufStyle sty = ppBesides [ppStr "``", ppPStr s, ppStr "'' _K_ ", ppr sty k]
224 | otherwise = ppBesides [ppStr "``", ppPStr s, ppStr "''"]
226 ufStyle PprUnfolding = True
229 if_ubxd sty = if codeStyle sty then ppNil else ppChar '#'
231 showLiteral :: PprStyle -> Literal -> String
233 showLiteral sty lit = ppShow 80 (ppr sty lit)