-
Notifications
You must be signed in to change notification settings - Fork 182
Expand file tree
/
Copy pathCType.hs
More file actions
706 lines (574 loc) · 23.4 KB
/
Copy pathCType.hs
File metadata and controls
706 lines (574 loc) · 23.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
{-# LANGUAGE CPP #-}
{-# LANGUAGE GeneralizedNewtypeDeriving, PatternGuards, DeriveDataTypeable #-}
-- | The CType package defines the concrete representation of types and kinds.
module CType(
-- * Types
Type(..), CType, TyVar(..), TyCon(..), TISort(..), StructSubType(..),
-- ** Examining Types
getTyVarId, getTypeKind,
isTNum, getTNum,
isTStr, getTStr,
isTVar, isTCon, isIfc, isInterface, isDictType, isDictFun, isUpdateable,
leftCon, leftTyCon, allTyCons, allTConNames, tyConArgs,
splitTAp, normTAp,
isATFAp,
isTypeBit, isTypeString,
isTypePrimAction, isTypeAction,
isTypeActionValue, isTypeActionValue_,
isTypePolyBit, bitWidth,
isTypeUnit,
noTyVarNo, isGeneratedTVar,
getArrows, getRes,
seqCType,
-- if the above are not sufficient, use these:
isTypeTConNoArgs, isTypeTConArgs,
getActionValueArg,
isTConArrow, isTConPair,
-- ** Constructing Types
noType, tVar, tVarKind, cTVar, cTVarKind, cTVarNum, cTCon, cTNum, cTStr,
cTApplys, setTypePosition,
-- * Kinds
Kind(..), PartialKind(..),
-- ** Examining Kinds
isKVar, getArgKinds, getResKind,
-- ** Constructing Kinds
baseKVar, mkKFun,
-- * Type Classes
CTypeclass(..),
-- ** Examining Type Classes
typeclassId,
-- * Type class constraints
CQType(..), CPred(..),
getCQArrows,
) where
#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 804)
import Prelude hiding ((<>))
#endif
import Data.Char(isDigit, chr)
import Data.List(union)
import Data.Maybe
import qualified Data.Generics as Generic
import Eval
import PPrint
import Position
import Id
import IdPrint
import PreIds(idArrow, idPrimPair, idPrimUnit, idBit, idString,
idPrimAction, idAction, idActionValue_, idActionValue,
idTNumToStr)
import Util(itos)
import ErrorUtil
import Pragma(IfcPragma)
import TypeOps
import PVPrint(PVPrint(..))
import FStringCompat
-- Data structures
-- | Representation of types
data Type = TVar TyVar -- ^ type variable
| TCon TyCon -- ^ type constructor
| TAp Type Type -- ^ type-level application
| TGen Position Int -- ^ quantified type variable used in type schemes
| TDefMonad Position -- ^ not used after CVParserImperative
deriving (Show, Generic.Data, Generic.Typeable)
-- | Representation of a type variable
data TyVar = TyVar { tv_name :: Id -- ^ name of the type variable
, tv_num :: Int -- ^ number for a generated type variable
, tv_kind :: Kind -- ^ kind of the type variable
}
deriving (Show, Generic.Data, Generic.Typeable)
-- | Representation of a type constructor
data TyCon = -- | A constructor for a type of value kind
TyCon { tcon_name :: Id -- ^ name of the type constructor
, tcon_kind :: (Maybe Kind) -- ^ kind of the type constructor
, tcon_sort :: TISort -- ^ purpose of the type constructor
}
-- | A constructor for a type of numeric kind
| TyNum { tynum_value :: Integer -- ^ type-level numeric value
, tynum_pos :: Position -- ^ position of introduction
}
-- | A constructor for a type of string kind
| TyStr { tystr_value :: FString -- ^ type-level string value
, tystr_pos :: Position -- ^ position of introduction
}
deriving (Show, Generic.Data, Generic.Typeable)
data TISort
= -- type synonym
TItype Integer Type
| TIdata { tidata_cons :: [Id]
, tidata_enum :: Bool
}
| TIstruct StructSubType [Id]
-- primitive abstract type
-- e.g. Integer, Bit, Module, etc.
| TIabstract
-- Associated type function: resolved by looking up the corresponding
-- typeclass instance. Stores the class that defines this type function,
-- and the indices of the ATF params and the target param within the class's
-- parameter list.
| TIatf { atf_class_id :: Id -- the class this type function belongs to
, atf_param_idxs :: [Int] -- index of each ATF param in the class param list
, atf_target_idx :: Int -- index of the result param in the class param list
}
deriving (Eq, Ord, Show, Generic.Data, Generic.Typeable)
data StructSubType
= SStruct
| SClass
| SDataCon { sdatacon_id :: Id
, sdatacon_named_fields :: Bool
}
| SInterface [IfcPragma]
| SPolyWrap { spolywrap_id :: Id -- ^ name of the type with the wrapped field
, spolywrap_ctor :: Maybe Id -- ^ name of the data constructor
, spolywrap_field :: Id -- ^ name of the wrapped field
}
deriving (Eq, Ord, Show, Generic.Data, Generic.Typeable)
type CType = Type
-- | Representation of kinds
data Kind = KStar -- ^ kind of a simple value type
| KNum -- ^ kind of a simple numeric type
| KStr -- ^ kind of a simple string type
| Kfun Kind Kind -- ^ kind of type constructors (type-level function)
| KVar Int -- ^ generated kind variable (used only during kind inference)
deriving (Eq, Ord, Show, Generic.Data, Generic.Typeable)
-- Used for providing partial Kind information
data PartialKind
= PKNoInfo -- this is what makes it partial
| PKStar
| PKNum
| PKStr
| PKfun PartialKind PartialKind
deriving (Eq, Ord, Show)
-- | A named typeclass
newtype CTypeclass = CTypeclass Id
deriving (Eq, Ord, Show, PPrint, HasPosition, NFData)
-- | Representation of the provisos and other class constraints
data CPred = CPred { cpred_tc :: CTypeclass -- ^ constraint class, e.g., "Eq"
, cpred_args :: [CType] -- ^ argument types
}
deriving (Eq, Ord, Show)
-- Eq instances
-- | used to do the sorting of instances
-- so that overlapping matches go to the most specific
-- TAp first because it brings forward instances with larger structure
-- see the Has_tpl_n instances in the Prelude
cmp :: Type -> Type -> Ordering
cmp (TAp f1 a1) (TAp f2 a2) = compare (f1, a1) (f2, a2)
cmp (TAp _ _) _ = LT
cmp (TCon c1) (TCon c2) = compare c1 c2
cmp (TCon _) (TAp _ _) = GT
cmp (TCon _) _ = LT
cmp (TVar _) (TCon _) = GT
cmp (TVar _) (TAp _ _) = GT
cmp (TVar v1) (TVar v2) = compare v1 v2
cmp (TVar _) _ = LT
cmp (TGen _ i1) (TGen _ i2) = compare i1 i2
cmp (TGen _ _) (TDefMonad _) = LT
cmp (TGen _ _) _ = GT
cmp (TDefMonad _) (TDefMonad _) = EQ
cmp (TDefMonad _) _ = GT
instance Eq Type where
x == y = cmp x y == EQ
instance Eq TyVar where
TyVar i n _ == TyVar i' n' _ = (n, i) == (n', i')
-- TyCon comparison and the one-tycon-per-qualified-name invariant
--
-- BSC's front end enforces one type constructor per qualified name, so a
-- qualified Id determines its (kind, sort) payload. The invariant holds
-- ONLY for qualified names: unqualified TyCons exist during scope
-- resolution, where the same base name may denote different constructors.
-- The tconcheck build step (src/comp/tconcheck.hs) verifies the compiler's
-- handwritten copies of Prelude tycon payloads against the compiled
-- Prelude, keeping the invariant checkable.
--
-- Eq is therefore scoped by qualification:
-- * both ids qualified: the invariant's regime. Comparison is by Id;
-- the payloads are determined by the name (checker-verified), so a
-- payload comparison would be a dead tail.
-- * either id unqualified: resolution-era fuzz, where the invariant is
-- undefined; the kind comparison is kept as a hedge.
--
-- Two pre-existing quirks, both deliberate and unchanged:
-- * Eq is non-transitive: qualEq compares by base name alone when either
-- side is unqualified, so P.T == T and T == Q.T but P.T /= Q.T.
-- * Eq and Ord disagree: Ord compares the full qualifier on both sides
-- (a lawful total order), while Eq admits the qualEq fuzz. Containers
-- key on Ord.
instance Eq TyCon where
TyCon i k _ == TyCon i' k' _ = qualEq i i' && (bothQualified i i' || k == k')
TyNum i _ == TyNum i' _ = i == i'
TyStr s _ == TyStr s' _ = s == s'
_ == _ = False
-- both ids carry a package qualifier (see the invariant note above)
bothQualified :: Id -> Id -> Bool
bothQualified i i' = not (isUnqualId i) && not (isUnqualId i')
-- Ord instances
instance Ord Type where
compare x y = cmp x y
instance Ord TyVar where
TyVar i n _ <= TyVar i' n' _ = (n, i) <= (n', i')
TyVar i n _ < TyVar i' n' _ = (n, i) < (n', i')
TyVar i n _ >= TyVar i' n' _ = (n, i) >= (n', i')
TyVar i n _ > TyVar i' n' _ = (n, i) > (n', i')
TyVar i n _ `compare` TyVar i' n' _ = (n, i) `compare` (n', i')
instance Ord TyCon where
-- lexicographic on (base, qual); within a (base, qual) bucket either
-- both ids are qualified -- unique by the invariant documented at Eq,
-- so EQ without consulting the kinds -- or both are unqualified, where
-- the kind comparison is kept, as in Eq. This remains a lawful total
-- order.
TyCon i k _ `compare` TyCon i' k' _ =
case (getIdBase i, getIdQual i) `compare` (getIdBase i', getIdQual i') of
EQ -> if bothQualified i i' then EQ else compare k k'
o -> o
TyCon _ _ _ `compare` TyNum _ _ = LT
TyCon _ _ _ `compare` TyStr _ _ = LT
TyNum _ _ `compare` TyCon _ _ _ = GT
TyNum i _ `compare` TyNum i' _ = i `compare` i'
TyNum _ _ `compare` TyStr _ _ = LT
TyStr _ _ `compare` TyCon _ _ _ = GT
TyStr _ _ `compare` TyNum _ _ = GT
TyStr s _ `compare` TyStr s' _ = s `compare` s'
instance PPrint Type where
pPrint d p (TCon (TyCon unit _ _)) | unit == idPrimUnit = text "()"
pPrint d p (TCon c) = pPrint d 0 c
pPrint d p (TVar i) = pPrint d 0 i
pPrint d p (TAp (TAp (TCon pair) a) b) | isTConPair pair =
pparen (p >= 0) (sep [pPrint d 0 a <> text ",", pPrint d (-1) b])
pPrint d p (TAp (TAp (TCon arr) a) r) | isTConArrow arr =
pparen (p > 8) (sep [pPrint d 9 a <+> text "->", pPrint d 8 r])
pPrint d p (TAp e e') = pparen (p>9) $
sep [pPrint d 9 e, pPrint d 10 e']
pPrint d p (TDefMonad _) = text ("TDefMonad")
pPrint d p (TGen _ n) = pparen True (text "TGen" <+> pPrint d p n)
instance NFData Type where
rnf (TVar v) = rnf v
rnf (TCon c) = rnf c
rnf (TAp t1 t2) = rnf2 t1 t2
rnf (TGen p i) = rnf2 p i
rnf (TDefMonad _) = ()
instance HasPosition Type where
getPosition (TVar var) = getPosition var
getPosition (TCon con) = getPosition con
getPosition (TAp f a) = getPosition f `bestPosition` getPosition a
getPosition (TGen pos _) = pos
getPosition (TDefMonad pos) = pos
instance NFData TyVar where
rnf (TyVar i n k) = rnf3 i n k
instance HasPosition TyVar where
getPosition (TyVar name _ _) = getPosition name
getTyVarId :: TyVar -> Id
getTyVarId = tv_name
instance PPrint TyVar where
pPrint d _ (TyVar i _ _) = ppVarId d i
instance PPrint TyCon where
pPrint d _ (TyCon i _ _) = ppConId d i
pPrint d _ (TyNum i _) = text (itos i)
pPrint d _ (TyStr s _) = text (show s)
instance NFData TyCon where
rnf (TyCon i k s) = rnf3 i k s
rnf (TyNum i p) = rnf2 i p
rnf (TyStr s p) = rnf2 s p
instance HasPosition TyCon where
getPosition (TyCon name k _) = getPosition name
getPosition (TyNum _ pos) = pos
getPosition (TyStr _ pos) = pos
instance HasPosition CQType where
-- prefer t to ps, since that is a better position for BSV
getPosition (CQType ps t) = getPosition t `bestPosition` getPosition ps
instance HasPosition CPred where
getPosition (CPred c ts) = getPosition (c, ts)
data CQType = CQType [CPred] CType
deriving (Eq, Ord, Show)
instance NFData CQType where
rnf (CQType ps t) = rnf2 ps t
{-
-- should typeclass ids be equal if they are qualEq?
instance Eq CTypeclass where
(==) (CTypeclass i) (Ctypeclass i') = qualEq i i'
instance Ord CTypeclass where
compare (CTypeclass i) (CTypeclass i') | qualEq i i' = EQ
| otherwise = compare i i'
-}
-- This function is dangerous, it allows a CTypeclass to be "coerced" in type to a
-- bare Id, which in turn might be interpreted as something else.
typeclassId :: CTypeclass -> Id
typeclassId (CTypeclass i) = i
instance PVPrint CTypeclass where
pvPrint d p (CTypeclass i) = pvPrint d p i
instance NFData CPred where
rnf (CPred c ts) = rnf2 c ts
instance PPrint CQType where
pPrint d p (CQType [] ct) = pPrint d p ct
pPrint d p (CQType preds ct) = sep [text "(" <> sepList (map (pPrint d 0) preds) (text ",") <> text ")" <+> text "=>", pPrint d 0 ct]
instance PPrint CPred where
pPrint d p (CPred (CTypeclass c) []) = ppConId d c
pPrint d p (CPred (CTypeclass c) ts) = ppConId d c <+> sep (map (pPrint d (maxPrec+1)) ts)
noTyVarNo :: Int
noTyVarNo = -1
tVarKind :: Id -> Kind -> TyVar
tVarKind i k = TyVar i noTyVarNo k
tVar :: Id -> TyVar
-- XXX KVar (-42) below is a hack so that undefined is not visible
-- XXX when deriving Show
tVar i = tVarKind i (KVar (-42))
cTVar :: Id -> CType
cTVar i = TVar (tVar i)
cTVarKind :: Id -> Kind -> CType
cTVarKind name kind = TVar (tVarKind name kind)
cTVarNum :: Id -> CType
cTVarNum name = cTVarKind name KNum
cTCon :: Id -> CType
cTCon i | all isDigit s = cTNum (read s) (getIdPosition i)
| head s == '"' = cTStr (mkFString $ read s) (getIdPosition i)
where s = getIdString i
cTCon i = TCon (TyCon i Nothing TIabstract)
cTNum :: Integer -> Position -> CType
cTNum n pos = TCon (TyNum n pos)
isTNum :: CType -> Bool
isTNum (TCon (TyNum _ _)) = True
isTNum _ = False
getTNum :: CType -> Integer
getTNum (TCon (TyNum n _)) = n
getTNum t = internalError $ "getTNum: not a type-level integer -- " ++ (show t)
cTStr :: FString -> Position -> CType
cTStr s pos = TCon (TyStr s pos)
isTStr :: CType -> Bool
isTStr (TCon (TyStr _ _)) = True
isTStr _ = False
getTStr :: CType -> FString
getTStr (TCon (TyStr s _)) = s
getTStr t = internalError $ "getTNum: not a type-level string -- " ++ (show t)
isTVar :: Type -> Bool
isTVar (TVar _) = True
isTVar _ = False
isTCon :: Type -> Bool
isTCon (TCon _) = True
isTCon _ = False
isGeneratedTVar :: TyVar -> Bool
isGeneratedTVar (TyVar _ n _) = n /= noTyVarNo
isIfc :: StructSubType -> Bool
isIfc SInterface {} = True
--isIfc SStruct = True -- XXX why??
isIfc _ = False
isInterface :: CType -> Bool
isInterface t | Just (TyCon _ _ (TIstruct s _)) <- leftTyCon t = isIfc s
isInterface _ = False
isDictType :: CType -> Bool
isDictType t | Just (TyCon _ _ (TIstruct SClass _)) <- leftTyCon t = True
isDictType _ = False
isDictFun :: CType -> Bool
isDictFun t = all isDictType (res:args)
where (args, res) = getArrows t
isUpdateable :: StructSubType -> Bool
isUpdateable SStruct = True
isUpdateable SInterface {} = True
isUpdateable _ = False
noType :: Type
noType = TGen noPosition (-1)
getCQArrows :: CQType -> ([CQType], CQType)
getCQArrows (CQType preds ctype) =
let (args, result) = getArrows ctype
in (map (CQType preds) args, CQType preds result)
getArrows :: Type -> ([Type], Type)
getArrows t = getArrowsAccum [] t
where getArrowsAccum ts (TAp (TAp (TCon arr) a) r) | isTConArrow arr
= getArrowsAccum (a:ts) r
getArrowsAccum ts r = (reverse ts, r)
getRes :: Type -> Type
getRes t = snd (getArrows t)
isTConArrow :: TyCon -> Bool
isTConArrow (TyCon i _ _) = i == idArrow noPosition
isTConArrow t = internalError("isTConArrow: not TCon " ++ show t)
isTConPair :: TyCon -> Bool
isTConPair (TyCon i _ _) = i == idPrimPair
isTConPair t = internalError("isTConPair: not TCon " ++ show t)
-- is a type a specific TCon with no arguments
isTypeTConNoArgs :: Id -> Type -> Bool
isTypeTConNoArgs cid (TCon (TyCon i _ _)) | (i == cid) = True
isTypeTConNoArgs _ _ = False
-- is a type a specific TCon with arguments
isTypeTConArgs :: Id -> Type -> Bool
isTypeTConArgs cid (TAp (TCon (TyCon i _ _)) _) | (i == cid) = True
isTypeTConArgs _ _ = False
isTypeBit, isTypeString, isTypePrimAction, isTypeAction :: Type -> Bool
isTypeBit = isTypeTConArgs idBit
isTypeString = isTypeTConNoArgs idString
isTypePrimAction = isTypeTConNoArgs idPrimAction
isTypeAction = isTypeTConNoArgs idAction
isTypeActionValue, isTypeActionValue_, isTypeUnit :: Type -> Bool
isTypeActionValue = isTypeTConArgs idActionValue
isTypeActionValue_ = isTypeTConArgs idActionValue_
isTypeUnit = isTypeTConNoArgs idPrimUnit
getActionValueArg :: Type -> Type
getActionValueArg (TAp (TCon (TyCon i _ _)) arg) | (i == idActionValue) = arg
getActionValueArg t = internalError ("getActionValueArg: " ++ ppReadable t)
-- These are used during foreign function processing to determine if arguments
-- and return values are polymorphic or of a known size.
isTypePolyBit :: Type -> Bool
isTypePolyBit (TAp (TCon (TyCon i _ _)) (TAp (TCon (TyCon i' _ _)) arg))
| (i == idActionValue) || (i == idActionValue_), (i' == idBit) = isTVar arg
isTypePolyBit (TAp (TCon (TyCon i _ _)) arg)
| (i == idBit) || (i == idActionValue) || (i == idActionValue_) = isTVar arg
isTypePolyBit _ = False
-- Note that this is only used for foreign functions, so it does not currently handle tuples of Bits
bitWidth :: Type -> Integer
bitWidth (TAp (TCon (TyCon i _ _)) (TAp (TCon (TyCon i' _ _)) arg))
| ((i == idActionValue) || (i == idActionValue_)) &&
(i' == idBit) &&
(isTNum arg) = getTNum arg
bitWidth (TAp (TCon (TyCon i _ _)) arg)
| (i == idBit) && (isTNum arg) = getTNum arg
bitWidth t =
internalError $ "bitWidth: not a Bit type of known width -- " ++ (show t)
cTApplys :: CType -> [CType] -> CType
cTApplys t ts = foldl TAp t ts
leftCon :: CType -> Maybe Id
leftCon (TAp f _) = leftCon f
leftCon (TCon (TyCon i _ _)) = Just i
leftCon _ = Nothing
leftTyCon :: CType -> Maybe TyCon
leftTyCon (TAp f _) = leftTyCon f
leftTyCon (TCon tc) = Just tc
leftTyCon _ = Nothing
tyConArgs :: CType -> [CType]
tyConArgs (TAp f a) = tyConArgs f ++ [a]
tyConArgs (TCon _) = []
tyConArgs t = internalError("tyConArgs: " ++ show t)
allTyCons :: CType -> [TyCon]
allTyCons (TCon c) = [c]
allTyCons (TAp f a) = allTyCons f `union` allTyCons a
allTyCons _ = []
getTConName :: TyCon -> Maybe Id
getTConName (TyCon i _ _) = Just i
getTConName (TyNum {}) = Nothing
getTConName (TyStr {}) = Nothing
allTConNames :: CType -> [Id]
allTConNames = mapMaybe getTConName . allTyCons
-- like the above functions, but works even if the left-most is not a tycon
splitTAp :: CType -> (CType, [CType])
splitTAp (TAp f a) = let (l,as) = splitTAp f
in (l,as ++ [a])
splitTAp t = (t,[])
-- Copied from the IType reduction rules (now IType.mkITAp)
normTAp :: Type -> Type -> Type
normTAp (TAp (TCon (TyCon op _ _)) (TCon (TyNum x xpos))) (TCon (TyNum y ypos))
| isJust (res) = cTNum (fromJust res) (getPosition op)
where res = opNumT op [x, y]
normTAp (TCon (TyCon op _ _)) (TCon (TyNum x xpos))
| isJust (res) = cTNum (fromJust res) (getPosition op)
where res = opNumT op [x]
normTAp (TAp (TCon (TyCon op _ _)) (TCon (TyStr x xpos))) (TCon (TyStr y ypos))
| isJust (res) = cTStr (fromJust res) (getPosition op)
where res = opStrT op [x, y]
normTAp (TCon (TyCon op _ _)) (TCon (TyNum x xpos))
| op == idTNumToStr = cTStr (mkNumFString x) (getPosition op)
normTAp f a = TAp f a
isATFAp :: Type -> Bool
isATFAp t0 =
let (f, as) = splitTAp t0
in case f of
TCon (TyCon _ _ (TIatf { atf_param_idxs = pIdxs })) -> length as == length pIdxs
_ -> False
getTypeKind :: Type -> Maybe Kind
getTypeKind (TVar (TyVar _ _ k)) = Just k
getTypeKind (TCon (TyCon _ mk _)) = mk
getTypeKind (TCon (TyNum _ _)) = Just KNum
getTypeKind (TCon (TyStr _ _)) = Just KStr
getTypeKind (TAp t1 t2) = case (getTypeKind t1) of
Just (Kfun k1 k2) -> Just k2
_ -> Nothing -- don't know or isn't Kfun
getTypeKind _ = Nothing
----
-- KIMisc.newKVar starts at this number
baseKVar :: Int
baseKVar = 1000
isKVar :: Kind -> Bool
isKVar (KVar _) = True
isKVar _ = False
-- Display the kind variable with letters
showKVar :: Int -> String
showKVar v =
let
makeDigit x = chr (x + 97) -- 97 = ASCII a
showDigits :: Int -> String
showDigits x | (x < 26) = [makeDigit x]
showDigits x = (showDigits (x `div` 26)) ++ [makeDigit (x `mod` 26)]
in
if (v < baseKVar)
then (itos v)
else (showDigits (v - baseKVar))
-- this differs from the version in KIMisc because it does not include the kind of the result
getArgKinds :: Kind -> [Kind]
getArgKinds (Kfun a b) = a : getArgKinds b
getArgKinds _ = []
getResKind :: Kind -> Kind
getResKind (Kfun a b) = getResKind b
getResKind k = k
mkKFun :: [Kind] -> Kind -> Kind
mkKFun [] k = k
mkKFun (a:as) k = Kfun a (mkKFun as k)
instance PPrint Kind where
pPrint _ _ KStar = text "*"
pPrint _ _ KNum = text "#"
pPrint _ _ KStr = text "$"
pPrint d p (Kfun l r) = pparen (p>9) $ pPrint d 10 l <+> text "->" <+> pPrint d 9 r
pPrint _ _ (KVar i) = text (showKVar i)
instance NFData Kind where
rnf KStar = ()
rnf KNum = ()
rnf KStr = ()
rnf (Kfun k1 k2) = rnf2 k1 k2
rnf (KVar n) = rnf n
----
instance PPrint PartialKind where
pPrint _ _ PKNoInfo = text "?"
pPrint _ _ PKStar = text "*"
pPrint _ _ PKNum = text "#"
pPrint _ _ PKStr = text "$"
pPrint d p (PKfun l r) =
pparen (p>9) $ pPrint d 10 l <+> text "->" <+> pPrint d 9 r
instance NFData PartialKind where
rnf PKNoInfo = ()
rnf PKStar = ()
rnf PKNum = ()
rnf PKStr = ()
rnf (PKfun k1 k2) = rnf2 k1 k2
----
instance PPrint TISort where
pPrint d p (TItype n t) = pparen (p>0) $ text "TItype" <+> pPrint d 0 n <+> pPrint d 1 t
pPrint d p (TIdata is enum) = pparen (p>0) $ text (if enum then "TIdata (enum)" else "TIdata") <+> pPrint d 1 is
pPrint d p (TIstruct ss is) = pparen (p>0) $ text "TIstruct" <+> pPrint d 1 ss <+> pPrint d 1 is
pPrint d p (TIabstract) = text "TIabstract"
pPrint d p (TIatf { atf_param_idxs = pIdxs, atf_class_id = cls }) =
pparen (p>0) $ text "TIatf" <+> pPrint d 0 (length pIdxs) <+> pPrint d 0 cls
instance NFData TISort where
rnf (TItype i t) = rnf2 i t
rnf (TIdata is enum) = rnf2 is enum
rnf (TIstruct ss is) = rnf2 ss is
rnf (TIabstract) = ()
rnf (TIatf { atf_class_id = c, atf_param_idxs = ps, atf_target_idx = t }) =
rnf3 c ps t
instance PPrint StructSubType where
pPrint _ _ ss = text (show ss)
instance NFData StructSubType where
rnf SStruct = ()
rnf SClass = ()
rnf (SDataCon i nm) = rnf2 i nm
rnf (SInterface ps) = rnf ps
rnf (SPolyWrap i con field) = rnf3 i con field
-- Force evaluation of a Ctype
seqCType :: CType -> CType
seqCType t@(TVar v) = seq v t
seqCType t@(TCon c) = t
seqCType t@(TAp t1 t2) = seq (seqCType t1) (seq (seqCType t2) t)
seqCType t@(TGen _ _) = t
seqCType t@(TDefMonad _) = t
----
setTypePosition :: Position -> Type -> Type
setTypePosition pos (TVar (TyVar id n k)) = (TVar (TyVar (setIdPosition pos id) n k))
setTypePosition pos (TCon (TyCon id k s)) = (TCon (TyCon (setIdPosition pos id) k s))
setTypePosition pos (TCon (TyNum n _)) = (TCon (TyNum n pos))
setTypePosition pos (TCon (TyStr s _)) = (TCon (TyStr s pos))
setTypePosition pos (TAp f a) = (TAp (setTypePosition pos f) (setTypePosition pos a))
setTypePosition pos (TGen _ n) = (TGen pos n)
setTypePosition pos (TDefMonad _) = (TDefMonad pos)