acfba4a2dfb5524473019cdf436b9ee52f077197
[ghc-hetmet.git] / ghc / compiler / prelude / TysWiredIn.lhs
1 %
2 % (c) The GRASP Project, Glasgow University, 1994-1998
3 %
4 \section[TysWiredIn]{Wired-in knowledge about {\em non-primitive} types}
5
6 This module is about types that can be defined in Haskell, but which
7 must be wired into the compiler nonetheless.
8
9 This module tracks the ``state interface'' document, ``GHC prelude:
10 types and operations.''
11
12 \begin{code}
13 module TysWiredIn (
14         addrDataCon,
15         addrTy,
16         addrTyCon,
17         boolTy,
18         boolTyCon,
19         charDataCon,
20         charTy,
21         charTyCon,
22         consDataCon,
23         doubleDataCon,
24         doubleTy,
25         isDoubleTy,
26         doubleTyCon,
27         falseDataCon,
28         floatDataCon,
29         floatTy,
30         isFloatTy,
31         floatTyCon,
32
33         intDataCon,
34         intTy,
35         intTyCon,
36         isIntTy,
37         inIntRange,
38
39         integerTy,
40         integerTyCon,
41         smallIntegerDataCon,
42         largeIntegerDataCon,
43         isIntegerTy,
44
45         listTyCon,
46
47         mkListTy,
48         nilDataCon,
49
50         -- tuples
51         mkTupleTy,
52         tupleTyCon, tupleCon, unitTyCon, unitDataCon, pairTyCon, pairDataCon,
53
54         -- unboxed tuples
55         mkUnboxedTupleTy,
56         unboxedTupleTyCon, unboxedTupleCon, 
57         unboxedPairTyCon, unboxedPairDataCon,
58
59         stablePtrTyCon,
60         stringTy,
61         trueDataCon,
62         unitTy,
63         voidTy,
64         wordDataCon,
65         wordTy,
66         wordTyCon,
67
68         isFFIArgumentTy,  -- :: Type -> Bool
69         isFFIResultTy,    -- :: Type -> Bool
70         isFFIExternalTy,  -- :: Type -> Bool
71         isAddrTy,         -- :: Type -> Bool
72
73     ) where
74
75 #include "HsVersions.h"
76
77 import {-# SOURCE #-} MkId( mkDataConId )
78
79 -- friends:
80 import PrelMods
81 import TysPrim
82
83 -- others:
84 import Constants        ( mAX_TUPLE_SIZE )
85 import Module           ( Module, mkPrelModule )
86 import Name             ( mkWiredInTyConName, mkWiredInIdName, mkSrcOccFS, dataName )
87 import DataCon          ( DataCon, StrictnessMark(..),  mkDataCon )
88 import Var              ( TyVar, tyVarKind )
89 import TyCon            ( TyCon, ArgVrcs, mkAlgTyCon, mkSynTyCon, mkTupleTyCon )
90 import BasicTypes       ( Arity, NewOrData(..), RecFlag(..) )
91 import Type             ( Type, mkTyConTy, mkTyConApp, mkSigmaTy, mkTyVarTys, 
92                           mkArrowKinds, boxedTypeKind, unboxedTypeKind,
93                           mkFunTy, mkFunTys, isUnLiftedType,
94                           splitTyConApp_maybe, splitAlgTyConApp_maybe,
95                           ThetaType, TauType )
96 import PrimRep          ( PrimRep(..) )
97 import Unique
98 import CmdLineOpts      ( opt_GlasgowExts )
99 import Util             ( assoc )
100 import Panic            ( panic )
101 import Array
102
103 alpha_tyvar       = [alphaTyVar]
104 alpha_ty          = [alphaTy]
105 alpha_beta_tyvars = [alphaTyVar, betaTyVar]
106
107 pcRecDataTyCon, pcNonRecDataTyCon, pcNonRecNewTyCon
108         :: Unique{-TyConKey-} -> Module -> FAST_STRING
109         -> [TyVar] -> ArgVrcs -> [DataCon] -> TyCon
110
111 pcRecDataTyCon    = pcTyCon DataType Recursive
112 pcNonRecDataTyCon = pcTyCon DataType NonRecursive
113 pcNonRecNewTyCon  = pcTyCon NewType  NonRecursive
114
115 pcTyCon new_or_data is_rec key mod str tyvars argvrcs cons
116   = tycon
117   where
118     tycon = mkAlgTyCon name kind 
119                 tyvars 
120                 []              -- No context
121                 argvrcs
122                 cons
123                 []              -- No derivings
124                 Nothing         -- Not a dictionary
125                 new_or_data
126                 is_rec
127
128     name = mkWiredInTyConName key mod str tycon
129     kind = mkArrowKinds (map tyVarKind tyvars) boxedTypeKind
130
131 pcSynTyCon key mod str kind arity tyvars expansion argvrcs  -- this fun never used!
132   = tycon
133   where
134     tycon = mkSynTyCon name kind arity tyvars expansion argvrcs
135     name  = mkWiredInTyConName key mod str tycon
136
137 pcDataCon :: Unique{-DataConKey-} -> Module -> FAST_STRING
138           -> [TyVar] -> ThetaType -> [TauType] -> TyCon -> DataCon
139 pcDataCon key mod str tyvars context arg_tys tycon
140   = data_con
141   where
142     data_con = mkDataCon name 
143                 [ NotMarkedStrict | a <- arg_tys ]
144                 [ {- no labelled fields -} ]
145                 tyvars context [] [] arg_tys tycon id
146     name = mkWiredInIdName key mod (mkSrcOccFS dataName str) id
147     id   = mkDataConId data_con
148 \end{code}
149
150 %************************************************************************
151 %*                                                                      *
152 \subsection[TysWiredIn-tuples]{The tuple types}
153 %*                                                                      *
154 %************************************************************************
155
156 \begin{code}
157 tupleTyCon :: Arity -> TyCon
158 tupleTyCon i | i > mAX_TUPLE_SIZE = fst (mk_tuple i)    -- Build one specially
159              | otherwise          = tupleTyConArr!i
160
161 tupleCon :: Arity -> DataCon
162 tupleCon i | i > mAX_TUPLE_SIZE = snd (mk_tuple i)      -- Build one specially
163            | otherwise          = tupleConArr!i
164
165 tupleTyCons :: [TyCon]
166 tupleTyCons = elems tupleTyConArr
167
168 tupleTyConArr :: Array Int TyCon
169 tupleTyConArr = array (0,mAX_TUPLE_SIZE) ([0..] `zip` map fst tuples)
170
171 tupleConArr :: Array Int DataCon
172 tupleConArr = array (0,mAX_TUPLE_SIZE) ([0..] `zip` map snd tuples)
173
174 tuples :: [(TyCon,DataCon)]
175 tuples = [mk_tuple i | i <- [0..mAX_TUPLE_SIZE]]
176
177 mk_tuple :: Int -> (TyCon,DataCon)
178 mk_tuple arity = (tycon, tuple_con)
179   where
180         tycon   = mkTupleTyCon tc_name tc_kind arity tyvars tuple_con True
181         tc_name = mkWiredInTyConName tc_uniq mod name_str tycon
182         tc_kind = mkArrowKinds (map tyVarKind tyvars) boxedTypeKind
183
184         tuple_con = pcDataCon dc_uniq mod name_str tyvars [] tyvar_tys tycon
185         tyvars    = take arity alphaTyVars
186         tyvar_tys = mkTyVarTys tyvars
187         (mod_name, name_str) = mkTupNameStr arity
188         tc_uniq   = mkTupleTyConUnique   arity
189         dc_uniq   = mkTupleDataConUnique arity
190         mod       = mkPrelModule mod_name
191
192 unitTyCon = tupleTyCon 0
193 pairTyCon = tupleTyCon 2
194
195 unitDataCon = tupleCon 0
196 pairDataCon = tupleCon 2
197 \end{code}
198
199 %************************************************************************
200 %*                                                                      *
201 \subsection[TysWiredIn-ubx-tuples]{Unboxed Tuple Types}
202 %*                                                                      *
203 %************************************************************************
204
205 \begin{code}
206 unboxedTupleTyCon :: Arity -> TyCon
207 unboxedTupleTyCon i | i > mAX_TUPLE_SIZE = fst (mk_unboxed_tuple i)
208                     | otherwise          = unboxedTupleTyConArr!i
209
210 unboxedTupleCon :: Arity -> DataCon
211 unboxedTupleCon i | i > mAX_TUPLE_SIZE = snd (mk_unboxed_tuple i)
212                   | otherwise          = unboxedTupleConArr!i
213
214 unboxedTupleTyConArr :: Array Int TyCon
215 unboxedTupleTyConArr = array (0,mAX_TUPLE_SIZE) ([0..] `zip` map fst ubx_tuples)
216
217 unboxedTupleConArr :: Array Int DataCon
218 unboxedTupleConArr = array (0,mAX_TUPLE_SIZE) ([0..] `zip` map snd ubx_tuples)
219
220 ubx_tuples :: [(TyCon,DataCon)]
221 ubx_tuples = [mk_unboxed_tuple i | i <- [0..mAX_TUPLE_SIZE]]
222
223 mk_unboxed_tuple :: Int -> (TyCon,DataCon)
224 mk_unboxed_tuple arity = (tycon, tuple_con)
225   where
226         tycon   = mkTupleTyCon tc_name tc_kind arity tyvars tuple_con False
227         tc_name = mkWiredInTyConName tc_uniq mod name_str tycon
228         tc_kind = mkArrowKinds (map tyVarKind tyvars) unboxedTypeKind
229
230         tuple_con = pcDataCon dc_uniq mod name_str tyvars [] tyvar_tys tycon
231         tyvars    = take arity openAlphaTyVars
232         tyvar_tys = mkTyVarTys tyvars
233         (mod_name, name_str) = mkUbxTupNameStr arity
234         tc_uniq   = mkUbxTupleTyConUnique   arity
235         dc_uniq   = mkUbxTupleDataConUnique arity
236         mod       = mkPrelModule mod_name
237
238 unboxedPairTyCon   = unboxedTupleTyCon 2
239 unboxedPairDataCon = unboxedTupleCon 2
240 \end{code}
241
242 %************************************************************************
243 %*                                                                      *
244 \subsection[TysWiredIn-boxed-prim]{The ``boxed primitive'' types (@Char@, @Int@, etc)}
245 %*                                                                      *
246 %************************************************************************
247
248 \begin{code}
249 -- The Void type is represented as a data type with no constructors
250 -- It's a built in type (i.e. there's no way to define it in Haskell;
251 --      the nearest would be
252 --
253 --              data Void =             -- No constructors!
254 --
255 -- ) It's boxed; there is only one value of this
256 -- type, namely "void", whose semantics is just bottom.
257 --
258 -- Haskell 98 drops the definition of a Void type, so we just 'simulate'
259 -- voidTy using ().
260 voidTy = unitTy
261 \end{code}
262
263
264 \begin{code}
265 charTy = mkTyConTy charTyCon
266
267 charTyCon = pcNonRecDataTyCon charTyConKey  pREL_BASE  SLIT("Char") [] [] [charDataCon]
268 charDataCon = pcDataCon charDataConKey pREL_BASE SLIT("C#") [] [] [charPrimTy] charTyCon
269
270 stringTy = mkListTy charTy -- convenience only
271 \end{code}
272
273 \begin{code}
274 intTy = mkTyConTy intTyCon 
275
276 intTyCon = pcNonRecDataTyCon intTyConKey pREL_BASE SLIT("Int") [] [] [intDataCon]
277 intDataCon = pcDataCon intDataConKey pREL_BASE SLIT("I#") [] [] [intPrimTy] intTyCon
278
279 isIntTy :: Type -> Bool
280 isIntTy ty
281   = case (splitAlgTyConApp_maybe ty) of
282         Just (tycon, [], _) -> getUnique tycon == intTyConKey
283         _                   -> False
284
285 inIntRange :: Integer -> Bool   -- Tells if an integer lies in the legal range of Ints
286 inIntRange i = (min_int <= i) && (i <= max_int)
287
288 max_int, min_int :: Integer
289 max_int = toInteger maxInt  
290 min_int = toInteger minInt
291
292 \end{code}
293
294 \begin{code}
295
296 wordTy = mkTyConTy wordTyCon
297
298 wordTyCon = pcNonRecDataTyCon wordTyConKey   pREL_ADDR SLIT("Word") [] [] [wordDataCon]
299 wordDataCon = pcDataCon wordDataConKey pREL_ADDR SLIT("W#") [] [] [wordPrimTy] wordTyCon
300 \end{code}
301
302 \begin{code}
303 addrTy = mkTyConTy addrTyCon
304
305 addrTyCon = pcNonRecDataTyCon addrTyConKey   pREL_ADDR SLIT("Addr") [] [] [addrDataCon]
306 addrDataCon = pcDataCon addrDataConKey pREL_ADDR SLIT("A#") [] [] [addrPrimTy] addrTyCon
307
308 isAddrTy :: Type -> Bool
309 isAddrTy ty
310   = case (splitAlgTyConApp_maybe ty) of
311         Just (tycon, [], _) -> getUnique tycon == addrTyConKey
312         _                   -> False
313
314 \end{code}
315
316 \begin{code}
317 floatTy = mkTyConTy floatTyCon
318
319 floatTyCon = pcNonRecDataTyCon floatTyConKey pREL_BASE SLIT("Float") [] [] [floatDataCon]
320 floatDataCon = pcDataCon floatDataConKey pREL_BASE SLIT("F#") [] [] [floatPrimTy] floatTyCon
321
322 isFloatTy :: Type -> Bool
323 isFloatTy ty
324   = case (splitAlgTyConApp_maybe ty) of
325         Just (tycon, [], _) -> getUnique tycon == floatTyConKey
326         _                   -> False
327
328 \end{code}
329
330 \begin{code}
331 doubleTy = mkTyConTy doubleTyCon
332
333 isDoubleTy :: Type -> Bool
334 isDoubleTy ty
335   = case (splitAlgTyConApp_maybe ty) of
336         Just (tycon, [], _) -> getUnique tycon == doubleTyConKey
337         _                   -> False
338
339 doubleTyCon = pcNonRecDataTyCon doubleTyConKey pREL_BASE SLIT("Double") [] [] [doubleDataCon]
340 doubleDataCon = pcDataCon doubleDataConKey pREL_BASE SLIT("D#") [] [] [doublePrimTy] doubleTyCon
341 \end{code}
342
343 \begin{code}
344 stablePtrTyCon
345   = pcNonRecDataTyCon stablePtrTyConKey pREL_STABLE SLIT("StablePtr")
346         alpha_tyvar [(True,False)] [stablePtrDataCon]
347   where
348     stablePtrDataCon
349       = pcDataCon stablePtrDataConKey pREL_STABLE SLIT("StablePtr")
350             alpha_tyvar [] [mkStablePtrPrimTy alphaTy] stablePtrTyCon
351 \end{code}
352
353 \begin{code}
354 foreignObjTyCon
355   = pcNonRecDataTyCon foreignObjTyConKey pREL_IO_BASE SLIT("ForeignObj")
356         [] [] [foreignObjDataCon]
357   where
358     foreignObjDataCon
359       = pcDataCon foreignObjDataConKey pREL_IO_BASE SLIT("ForeignObj")
360             [] [] [foreignObjPrimTy] foreignObjTyCon
361 \end{code}
362
363 %************************************************************************
364 %*                                                                      *
365 \subsection[TysWiredIn-Integer]{@Integer@ and its related ``pairing'' types}
366 %*                                                                      *
367 %************************************************************************
368
369 @Integer@ and its pals are not really primitive.  @Integer@ itself, first:
370 \begin{code}
371 integerTy :: Type
372 integerTy = mkTyConTy integerTyCon
373
374 integerTyCon = pcNonRecDataTyCon integerTyConKey pREL_BASE SLIT("Integer")
375                    [] [] [smallIntegerDataCon, largeIntegerDataCon]
376
377 smallIntegerDataCon = pcDataCon smallIntegerDataConKey pREL_BASE SLIT("S#")
378                 [] [] [intPrimTy] integerTyCon
379 largeIntegerDataCon = pcDataCon largeIntegerDataConKey pREL_BASE SLIT("J#")
380                 [] [] [intPrimTy, byteArrayPrimTy] integerTyCon
381
382
383 isIntegerTy :: Type -> Bool
384 isIntegerTy ty
385   = case (splitAlgTyConApp_maybe ty) of
386         Just (tycon, [], _) -> getUnique tycon == integerTyConKey
387         _                   -> False
388 \end{code}
389
390
391 %************************************************************************
392 %*                                                                      *
393 \subsection[TysWiredIn-ext-type]{External types}
394 %*                                                                      *
395 %************************************************************************
396
397 The compiler's foreign function interface supports the passing of a
398 restricted set of types as arguments and results (the restricting factor
399 being the )
400
401 \begin{code}
402 isFFIArgumentTy :: Type -> Bool
403 isFFIArgumentTy ty =
404   (opt_GlasgowExts && isUnLiftedType ty) || --leave out for now: maybeToBool (maybeBoxedPrimType ty))) ||
405   case (splitAlgTyConApp_maybe ty) of
406     Just (tycon, _, _) -> (getUnique tycon) `elem` primArgTyConKeys
407     _                  -> False
408
409 -- types that can be passed as arguments to "foreign" functions
410 primArgTyConKeys 
411   = [ intTyConKey, int8TyConKey, int16TyConKey, int32TyConKey, int64TyConKey
412     , wordTyConKey, word8TyConKey, word16TyConKey, word32TyConKey, word64TyConKey
413     , floatTyConKey, doubleTyConKey
414     , addrTyConKey, charTyConKey, foreignObjTyConKey
415     , stablePtrTyConKey
416     , byteArrayTyConKey, mutableByteArrayTyConKey
417     ]
418
419 -- types that can be passed from the outside world into Haskell.
420 -- excludes (mutable) byteArrays.
421 isFFIExternalTy :: Type -> Bool
422 isFFIExternalTy ty = 
423   (opt_GlasgowExts && isUnLiftedType ty) || --leave out for now: maybeToBool (maybeBoxedPrimType ty))) ||
424   case (splitAlgTyConApp_maybe ty) of
425     Just (tycon, _, _) -> 
426        let 
427         u_tycon = getUnique tycon
428        in  
429        (u_tycon `elem` primArgTyConKeys) &&
430        not (u_tycon `elem` notLegalExternalTyCons)
431     _                  -> False
432
433
434 isFFIResultTy :: Type -> Bool
435 isFFIResultTy ty =
436    not (isUnLiftedType ty) &&
437    case (splitAlgTyConApp_maybe ty) of
438     Just (tycon, _, _) -> 
439         let
440          u_tycon = getUnique tycon
441         in
442         (u_tycon == getUnique unitTyCon) ||
443         ((u_tycon `elem` primArgTyConKeys) && 
444          not (u_tycon `elem` notLegalExternalTyCons))
445     _                  -> False
446
447 -- it's illegal to return foreign objects and (mutable)
448 -- bytearrays from a _ccall_ / foreign declaration
449 -- (or be passed them as arguments in foreign exported functions).
450 notLegalExternalTyCons =
451   [ foreignObjTyConKey, byteArrayTyConKey, mutableByteArrayTyConKey ]
452     
453 \end{code}
454
455 %************************************************************************
456 %*                                                                      *
457 \subsection[TysWiredIn-Bool]{The @Bool@ type}
458 %*                                                                      *
459 %************************************************************************
460
461 An ordinary enumeration type, but deeply wired in.  There are no
462 magical operations on @Bool@ (just the regular Prelude code).
463
464 {\em BEGIN IDLE SPECULATION BY SIMON}
465
466 This is not the only way to encode @Bool@.  A more obvious coding makes
467 @Bool@ just a boxed up version of @Bool#@, like this:
468 \begin{verbatim}
469 type Bool# = Int#
470 data Bool = MkBool Bool#
471 \end{verbatim}
472
473 Unfortunately, this doesn't correspond to what the Report says @Bool@
474 looks like!  Furthermore, we get slightly less efficient code (I
475 think) with this coding. @gtInt@ would look like this:
476
477 \begin{verbatim}
478 gtInt :: Int -> Int -> Bool
479 gtInt x y = case x of I# x# ->
480             case y of I# y# ->
481             case (gtIntPrim x# y#) of
482                 b# -> MkBool b#
483 \end{verbatim}
484
485 Notice that the result of the @gtIntPrim@ comparison has to be turned
486 into an integer (here called @b#@), and returned in a @MkBool@ box.
487
488 The @if@ expression would compile to this:
489 \begin{verbatim}
490 case (gtInt x y) of
491   MkBool b# -> case b# of { 1# -> e1; 0# -> e2 }
492 \end{verbatim}
493
494 I think this code is a little less efficient than the previous code,
495 but I'm not certain.  At all events, corresponding with the Report is
496 important.  The interesting thing is that the language is expressive
497 enough to describe more than one alternative; and that a type doesn't
498 necessarily need to be a straightforwardly boxed version of its
499 primitive counterpart.
500
501 {\em END IDLE SPECULATION BY SIMON}
502
503 \begin{code}
504 boolTy = mkTyConTy boolTyCon
505
506 boolTyCon = pcTyCon EnumType NonRecursive boolTyConKey 
507                     pREL_BASE SLIT("Bool") [] [] [falseDataCon, trueDataCon]
508
509 falseDataCon = pcDataCon falseDataConKey pREL_BASE SLIT("False") [] [] [] boolTyCon
510 trueDataCon  = pcDataCon trueDataConKey  pREL_BASE SLIT("True")  [] [] [] boolTyCon
511 \end{code}
512
513 %************************************************************************
514 %*                                                                      *
515 \subsection[TysWiredIn-List]{The @List@ type (incl ``build'' magic)}
516 %*                                                                      *
517 %************************************************************************
518
519 Special syntax, deeply wired in, but otherwise an ordinary algebraic
520 data types:
521 \begin{verbatim}
522 data [] a = [] | a : (List a)
523 data () = ()
524 data (,) a b = (,,) a b
525 ...
526 \end{verbatim}
527
528 \begin{code}
529 mkListTy :: Type -> Type
530 mkListTy ty = mkTyConApp listTyCon [ty]
531
532 alphaListTy = mkSigmaTy alpha_tyvar [] (mkTyConApp listTyCon alpha_ty)
533
534 listTyCon = pcRecDataTyCon listTyConKey pREL_BASE SLIT("[]") 
535                         alpha_tyvar [(True,False)] [nilDataCon, consDataCon]
536
537 nilDataCon  = pcDataCon nilDataConKey  pREL_BASE SLIT("[]") alpha_tyvar [] [] listTyCon
538 consDataCon = pcDataCon consDataConKey pREL_BASE SLIT(":")
539                 alpha_tyvar [] [alphaTy, mkTyConApp listTyCon alpha_ty] listTyCon
540 -- Interesting: polymorphic recursion would help here.
541 -- We can't use (mkListTy alphaTy) in the defn of consDataCon, else mkListTy
542 -- gets the over-specific type (Type -> Type)
543 \end{code}
544
545 %************************************************************************
546 %*                                                                      *
547 \subsection[TysWiredIn-Tuples]{The @Tuple@ types}
548 %*                                                                      *
549 %************************************************************************
550
551 The tuple types are definitely magic, because they form an infinite
552 family.
553
554 \begin{itemize}
555 \item
556 They have a special family of type constructors, of type @TyCon@
557 These contain the tycon arity, but don't require a Unique.
558
559 \item
560 They have a special family of constructors, of type
561 @Id@. Again these contain their arity but don't need a Unique.
562
563 \item
564 There should be a magic way of generating the info tables and
565 entry code for all tuples.
566
567 But at the moment we just compile a Haskell source
568 file\srcloc{lib/prelude/...} containing declarations like:
569 \begin{verbatim}
570 data Tuple0             = Tup0
571 data Tuple2  a b        = Tup2  a b
572 data Tuple3  a b c      = Tup3  a b c
573 data Tuple4  a b c d    = Tup4  a b c d
574 ...
575 \end{verbatim}
576 The print-names associated with the magic @Id@s for tuple constructors
577 ``just happen'' to be the same as those generated by these
578 declarations.
579
580 \item
581 The instance environment should have a magic way to know
582 that each tuple type is an instances of classes @Eq@, @Ix@, @Ord@ and
583 so on. \ToDo{Not implemented yet.}
584
585 \item
586 There should also be a way to generate the appropriate code for each
587 of these instances, but (like the info tables and entry code) it is
588 done by enumeration\srcloc{lib/prelude/InTup?.hs}.
589 \end{itemize}
590
591 \begin{code}
592 mkTupleTy :: Int -> [Type] -> Type
593 mkTupleTy arity tys = mkTyConApp (tupleTyCon arity) tys
594
595 mkUnboxedTupleTy :: Int -> [Type] -> Type
596 mkUnboxedTupleTy arity tys = mkTyConApp (unboxedTupleTyCon arity) tys
597
598 unitTy    = mkTupleTy 0 []
599 \end{code}