packages feed

llvm-extra 0.10 → 0.10.1

raw patch · 8 files changed

+307/−118 lines, 8 filesdep ~enumset

Dependency ranges changed: enumset

Files

llvm-extra.cabal view
@@ -1,6 +1,6 @@ Cabal-Version:  2.2 Name:           llvm-extra-Version:        0.10+Version:        0.10.1 License:        BSD-3-Clause License-File:   LICENSE Author:         Henning Thielemann <haskell@henning-thielemann.de>@@ -61,7 +61,7 @@   default:     False  Source-Repository this-  Tag:         0.10+  Tag:         0.10.1   Type:        darcs   Location:    http://code.haskell.org/~thielema/llvm-extra/ @@ -101,7 +101,9 @@     LLVM.Extra.MaybeContinuation     LLVM.Extra.Either     LLVM.Extra.Tuple+    LLVM.Extra.Struct     LLVM.Extra.Control+    LLVM.Extra.Function     LLVM.Extra.Array     LLVM.Extra.Scalar     LLVM.Extra.Vector
src/LLVM/Extra/Control.hs view
@@ -363,6 +363,11 @@  -- * return with better type inference +{- |+'ret' terminates a basic block which interferes badly+with other control structures in this module.+If you use the control structures then better use "LLVM.Extra.Function".+-} ret :: Value a -> CodeGenFunction a () ret = LLVM.ret 
+ src/LLVM/Extra/Function.hs view
@@ -0,0 +1,112 @@+{-# LANGUAGE TypeFamilies #-}+{- |+Alternative to 'LLVM.Core.defineFunction'+that creates the final 'LLVM.Core.ret' instruction for you.+-}+module LLVM.Extra.Function (+   C,+   CodeGen,+   define,+   create,+   createNamed,+   Return, Result, ret,+   ) where++import qualified LLVM.Util.Proxy as LP+import qualified LLVM.Core as LLVM++import Foreign.StablePtr (StablePtr)+import Foreign.Ptr (Ptr, FunPtr)++import Control.Applicative ((<*>))++import Data.Int (Int8, Int16, Int32, Int64)+import Data.Word (Word8, Word16, Word32, Word64, Word)+++define ::+   (C f) => LLVM.Function f -> CodeGen f -> LLVM.CodeGenModule ()+define fn body =+   LLVM.defineFunction fn (addRet (proxyFromElement2 fn) body)++proxyFromElement2 :: f (g a) -> LP.Proxy a+proxyFromElement2 _ = LP.Proxy+++create ::+   (C f) =>+   LLVM.Linkage -> CodeGen f -> LLVM.CodeGenModule (LLVM.Function f)+create linkage body = do+   f <- LLVM.newFunction linkage+   define f body+   return f++createNamed ::+   (C f) =>+   LLVM.Linkage -> String -> CodeGen f -> LLVM.CodeGenModule (LLVM.Function f)+createNamed linkage name body = do+   f <- LLVM.newNamedFunction linkage name+   define f body+   return f+++{- |+> CodeGen (a->b->...-> IO z) =+>    Value a -> Value b -> ... CodeGenFunction r (Value z)@.+-}+class LLVM.FunctionArgs f => C f where+   type CodeGen f :: *+   addRet :: LP.Proxy f -> CodeGen f -> LLVM.FunctionCodeGen f++instance (C b, LLVM.IsFirstClass a) => C (a -> b) where+   type CodeGen (a -> b) = LLVM.Value a -> CodeGen b+   addRet proxy f a = addRet (proxy<*>LP.Proxy) (f a)++instance Return a => C (IO a) where+   type CodeGen (IO a) = LLVM.CodeGenFunction a (Result a)+   addRet LP.Proxy code = code >>= ret+++class (LLVM.IsFirstClass a) => Return a where+   type Result a+   ret :: Result a -> LLVM.CodeGenFunction a ()+instance Return () where+   type Result () = ()+   ret = LLVM.ret++instance Return Bool where+   type Result Bool = LLVM.Value Bool; ret = LLVM.ret+instance Return Int where+   type Result Int = LLVM.Value Int; ret = LLVM.ret+instance Return Int8 where+   type Result Int8 = LLVM.Value Int8; ret = LLVM.ret+instance Return Int16 where+   type Result Int16 = LLVM.Value Int16; ret = LLVM.ret+instance Return Int32 where+   type Result Int32 = LLVM.Value Int32; ret = LLVM.ret+instance Return Int64 where+   type Result Int64 = LLVM.Value Int64; ret = LLVM.ret+instance Return Word where+   type Result Word = LLVM.Value Word; ret = LLVM.ret+instance Return Word8 where+   type Result Word8 = LLVM.Value Word8; ret = LLVM.ret+instance Return Word16 where+   type Result Word16 = LLVM.Value Word16; ret = LLVM.ret+instance Return Word32 where+   type Result Word32 = LLVM.Value Word32; ret = LLVM.ret+instance Return Word64 where+   type Result Word64 = LLVM.Value Word64; ret = LLVM.ret++instance Return Float where+   type Result Float = LLVM.Value Float; ret = LLVM.ret+instance Return Double where+   type Result Double = LLVM.Value Double; ret = LLVM.ret++instance Return (Ptr a) where+   type Result (Ptr a) = LLVM.Value (Ptr a); ret = LLVM.ret+instance (LLVM.IsType a) => Return (LLVM.Ptr a) where+   type Result (LLVM.Ptr a) = LLVM.Value (LLVM.Ptr a); ret = LLVM.ret+instance (LLVM.IsFunction a) => Return (FunPtr a) where+   type Result (FunPtr a) = LLVM.Value (FunPtr a); ret = LLVM.ret+instance Return (StablePtr a) where+   type Result (StablePtr a) = LLVM.Value (StablePtr a); ret = LLVM.ret
src/LLVM/Extra/Memory.hs view
@@ -16,15 +16,12 @@  import qualified LLVM.Extra.Multi.Vector as MultiVector import qualified LLVM.Extra.Multi.Value as MultiValue-import qualified LLVM.Extra.ArithmeticPrivate as A-import qualified LLVM.Extra.Vector as Vector import qualified LLVM.Extra.Scalar as Scalar-import qualified LLVM.Extra.Array as Array import qualified LLVM.Extra.Tuple as Tuple+import qualified LLVM.Extra.Struct as Struct import qualified LLVM.Extra.Either as Either import qualified LLVM.Extra.Maybe as Maybe -import qualified LLVM.Util.Proxy as LP import qualified LLVM.Core as LLVM import LLVM.Core    (getElementPtr0,@@ -36,17 +33,13 @@ import qualified Type.Data.Num.Decimal as TypeNum import qualified Type.Data.Num.Unary as Unary import Type.Data.Num.Decimal (d0, d1, d2, d3)-import Type.Base.Proxy (Proxy(Proxy), )--import Foreign.StablePtr (StablePtr, )-import Foreign.Ptr (FunPtr)+import Type.Base.Proxy (Proxy(Proxy))  import qualified Data.Traversable as Trav import qualified Data.Foldable as Fold import qualified Data.FixedLength as FixedLength import Data.Tuple.HT (fst3, snd3, thd3, )-import Data.Word (Word8, Word16, Word32, Word64, Word)-import Data.Int  (Int8,  Int16,  Int32,  Int64, )+import Data.Word (Word)  import qualified Control.Applicative.HT as App import Control.Monad (ap, (<=<))@@ -237,10 +230,10 @@       Fold.foldlM          (\arr (x,i) -> compose x >>= \xc -> LLVM.insertvalue arr xc i)          (LLVM.value LLVM.undef) $-      FixedLength.zipWith (,) xs $ iterateTrav (1+) (0::Word64)+      FixedLength.zipWith (,) xs $ iterateTrav (1+) (0::Word)    decompose arr =       Trav.mapM (decompose <=< LLVM.extractvalue arr) $-      iterateTrav (1+) (0::Word64)+      iterateTrav (1+) (0::Word)  iterateTrav :: (Applicative t, Trav.Traversable t) => (a -> a) -> a -> t a iterateTrav f a0 = snd $ Trav.mapAccumL (\a () -> (f a, a)) a0 $ pure ()@@ -296,114 +289,45 @@    compose = return  -class (LLVM.IsFirstClass llvmType, IsType (Stored llvmType)) =>-      FirstClass llvmType where-   type Stored llvmType :: *-   fromStorable :: Value (Stored llvmType) -> CodeGenFunction r (Value llvmType)-   toStorable :: Value llvmType -> CodeGenFunction r (Value (Stored llvmType))--instance FirstClass Float  where type Stored Float  = Float  ; fromStorable = return; toStorable = return-instance FirstClass Double where type Stored Double = Double ; fromStorable = return; toStorable = return-instance FirstClass Int    where type Stored Int    = Int    ; fromStorable = return; toStorable = return-instance FirstClass Int8   where type Stored Int8   = Int8   ; fromStorable = return; toStorable = return-instance FirstClass Int16  where type Stored Int16  = Int16  ; fromStorable = return; toStorable = return-instance FirstClass Int32  where type Stored Int32  = Int32  ; fromStorable = return; toStorable = return-instance FirstClass Int64  where type Stored Int64  = Int64  ; fromStorable = return; toStorable = return-instance FirstClass Word   where type Stored Word   = Word   ; fromStorable = return; toStorable = return-instance FirstClass Word8  where type Stored Word8  = Word8  ; fromStorable = return; toStorable = return-instance FirstClass Word16 where type Stored Word16 = Word16 ; fromStorable = return; toStorable = return-instance FirstClass Word32 where type Stored Word32 = Word32 ; fromStorable = return; toStorable = return-instance FirstClass Word64 where type Stored Word64 = Word64 ; fromStorable = return; toStorable = return-instance FirstClass Bool   where-   type Stored Bool = Word32-   fromStorable = A.cmp LLVM.CmpNE (LLVM.value LLVM.zero)-   toStorable = LLVM.zext-instance-   (TypeNum.Positive n, LLVM.IsPrimitive a, LLVM.IsPrimitive (Stored a), FirstClass a) =>-      FirstClass (LLVM.Vector n a) where-   type Stored (LLVM.Vector n a) = LLVM.Vector n (Stored a)-   fromStorable = Vector.map fromStorable-   toStorable = Vector.map toStorable-instance-   (TypeNum.Natural n, LLVM.IsFirstClass (Stored a),-    FirstClass a, IsSized a, IsSized (Stored a)) =>-      FirstClass (LLVM.Array n a) where-   type Stored (LLVM.Array n a) = LLVM.Array n (Stored a)-   fromStorable = Array.map fromStorable-   toStorable = Array.map toStorable--instance (IsType a) => FirstClass (LLVM.Ptr a) where-   type Stored (LLVM.Ptr a) = LLVM.Ptr a-   fromStorable = return; toStorable = return-instance (LLVM.IsFunction a) => FirstClass (FunPtr a) where-   type Stored (FunPtr a) = FunPtr a-   fromStorable = return; toStorable = return-instance FirstClass (StablePtr a) where-   type Stored (StablePtr a) = StablePtr a-   fromStorable = return; toStorable = return-+type family StructStruct s+type instance StructStruct (a,as) = (Struct a, StructStruct as)+type instance StructStruct () = ()  instance-   (LLVM.IsFirstClass (LLVM.Struct s),-    IsType (LLVM.Struct (StoredStruct s)),-    ConvertStruct s TypeNum.D0 s) =>-      FirstClass (LLVM.Struct s) where-   type Stored (LLVM.Struct s) = LLVM.Struct (StoredStruct s)-   fromStorable sm =-      case LP.Proxy of-         sfields -> do-            s <- decomposeField sfields d0 sm-            let _ = asTypeOf (fields s) sfields-            return s-   toStorable s =-      composeField (fields s) d0 s--fields :: Value (LLVM.Struct s) -> LP.Proxy s-fields _ = LP.Proxy---type family StoredStruct s :: *-type instance StoredStruct () = ()-type instance StoredStruct (s,rem) = (Stored s, StoredStruct rem)+   (Struct.Phi s, Struct.Undefined s,+    LLVM.StructFields (StructStruct s),+    ConvertStruct (StructStruct s) TypeNum.D0 s) =>+      C (Struct.T s) where+   type Struct (Struct.T s) = LLVM.Struct (StructStruct s)+   decompose = fmap Struct.Cons . decomposeFields TypeNum.d0+   compose (Struct.Cons s) = composeFields TypeNum.d0 s  class ConvertStruct s i rem where-   decomposeField ::-      LP.Proxy rem -> Proxy i -> Value (LLVM.Struct (StoredStruct s)) ->-      CodeGenFunction r (Value (LLVM.Struct s))-   composeField ::-      LP.Proxy rem -> Proxy i -> Value (LLVM.Struct s) ->-      CodeGenFunction r (Value (LLVM.Struct (StoredStruct s)))+   decomposeFields ::+      Proxy i -> Value (LLVM.Struct s) -> CodeGenFunction r rem+   composeFields ::+      Proxy i -> rem -> CodeGenFunction r (Value (LLVM.Struct s))  instance-   (sm ~ StoredStruct s,-    FirstClass a, am ~ Stored a,-    LLVM.GetValue (LLVM.Struct s) (Proxy i),-    LLVM.GetValue (LLVM.Struct sm) (Proxy i),-    LLVM.ValueType (LLVM.Struct s) (Proxy i) ~ a,-    LLVM.ValueType (LLVM.Struct sm) (Proxy i) ~ am,+   (TypeNum.Natural i, LLVM.GetField s i, LLVM.FieldType s i ~ Struct a, C a,     ConvertStruct s (TypeNum.Succ i) rem) =>       ConvertStruct s i (a,rem) where-   decomposeField flds i sm = do-      s <- decomposeField (fmap snd flds) (decSucc i) sm-      a <- fromStorable =<< LLVM.extractvalue sm i-      LLVM.insertvalue s a i-   composeField flds i s = do-      sm <- composeField (fmap snd flds) (decSucc i) s-      am <- toStorable =<< LLVM.extractvalue s i+   decomposeFields i sm =+      liftA2 (,)+         (decompose =<< LLVM.extractvalue sm i)+         (decomposeFields (decSucc i) sm)+   composeFields i (a,as) = do+      sm <- composeFields (decSucc i) as+      am <- compose a       LLVM.insertvalue sm am i  decSucc :: Proxy n -> Proxy (TypeNum.Succ n) decSucc Proxy = Proxy -instance-   (sm ~ StoredStruct s,-    IsType (LLVM.Struct s),-    IsType (LLVM.Struct sm)) =>-      ConvertStruct s i () where-   decomposeField _ _ _ =-      return (LLVM.value LLVM.undef)-   composeField _ _ _ =-      return (LLVM.value LLVM.undef)+instance (LLVM.StructFields s) => ConvertStruct s i () where+   decomposeFields _ _ = return ()+   composeFields _ _ = return (LLVM.value LLVM.undef)+   instance (MultiValue.C a, C (Tuple.ValueOf a)) => C (MultiValue.T a) where
src/LLVM/Extra/Multi/Value/Private.hs view
@@ -8,6 +8,7 @@ import qualified LLVM.Extra.Arithmetic as A import qualified LLVM.Extra.Control as C import qualified LLVM.Extra.Tuple as Tuple+import qualified LLVM.Extra.Struct as Struct import qualified LLVM.Extra.MaybePrivate as Maybe  import qualified LLVM.Core as LLVM@@ -32,7 +33,6 @@ import Data.Complex (Complex((:+))) import Data.Tagged (Tagged(Tagged, unTagged)) import Data.Function (id, (.), ($), )-import Data.Tuple.HT (uncurry3, ) import Data.Maybe (Maybe(Nothing,Just), ) import Data.Bool (Bool(False,True), ) import Data.Word (Word8, Word16, Word32, Word64, Word)@@ -445,24 +445,30 @@ thd3 :: T (a,b,c) -> T c thd3 (Cons (_a,_b,c)) = Cons c +curry3 :: (T (a,b,c) -> d) -> (T a -> T b -> T c -> d)+curry3 f a b c = f $ zip3 a b c +uncurry3 :: (T a -> T b -> T c -> d) -> (T (a,b,c) -> d)+uncurry3 f = TupleHT.uncurry3 f . unzip3++ mapFst3 :: (T a0 -> T a1) -> T (a0,b,c) -> T (a1,b,c)-mapFst3 f = uncurry3 zip3 . TupleHT.mapFst3 f . unzip3+mapFst3 f = TupleHT.uncurry3 zip3 . TupleHT.mapFst3 f . unzip3  mapSnd3 :: (T b0 -> T b1) -> T (a,b0,c) -> T (a,b1,c)-mapSnd3 f = uncurry3 zip3 . TupleHT.mapSnd3 f . unzip3+mapSnd3 f = TupleHT.uncurry3 zip3 . TupleHT.mapSnd3 f . unzip3  mapThd3 :: (T c0 -> T c1) -> T (a,b,c0) -> T (a,b,c1)-mapThd3 f = uncurry3 zip3 . TupleHT.mapThd3 f . unzip3+mapThd3 f = TupleHT.uncurry3 zip3 . TupleHT.mapThd3 f . unzip3  mapFst3F :: (Functor f) => (T a0 -> f (T a1)) -> T (a0,b,c) -> f (T (a1,b,c))-mapFst3F f = fmap (uncurry3 zip3) . FuncHT.mapFst3 f . unzip3+mapFst3F f = fmap (TupleHT.uncurry3 zip3) . FuncHT.mapFst3 f . unzip3  mapSnd3F :: (Functor f) => (T b0 -> f (T b1)) -> T (a,b0,c) -> f (T (a,b1,c))-mapSnd3F f = fmap (uncurry3 zip3) . FuncHT.mapSnd3 f . unzip3+mapSnd3F f = fmap (TupleHT.uncurry3 zip3) . FuncHT.mapSnd3 f . unzip3  mapThd3F :: (Functor f) => (T c0 -> f (T c1)) -> T (a,b,c0) -> f (T (a,b,c1))-mapThd3F f = fmap (uncurry3 zip3) . FuncHT.mapThd3 f . unzip3+mapThd3F f = fmap (TupleHT.uncurry3 zip3) . FuncHT.mapThd3 f . unzip3   zip :: T a -> T b -> T (a,b)@@ -498,6 +504,48 @@ untuple (Cons a) = Cons a  +class Struct struct where+   consStruct :: (Struct.T struct ~ a) => a -> T a+   undefStruct :: (Struct.T struct ~ a) => T a+   zeroStruct :: (Struct.T struct ~ a) => T a+   phiStruct :: (Struct.T struct ~ a) =>+      LLVM.BasicBlock -> T a -> LLVM.CodeGenFunction r (T a)+   addPhiStruct :: (Struct.T struct ~ a) =>+      LLVM.BasicBlock -> T a -> T a -> LLVM.CodeGenFunction r ()++instance (Struct struct) => C (Struct.T struct) where+   cons = consStruct+   undef = undefStruct+   zero = zeroStruct+   phi = phiStruct+   addPhi = addPhiStruct++instance Struct () where+   consStruct unit = Cons unit+   undefStruct = Cons (Struct.Cons ())+   zeroStruct = Cons (Struct.Cons ())+   phiStruct _bb = return+   addPhiStruct _bb _a _b = return ()++structCons :: T a -> T (Struct.T as) -> T (Struct.T (a,as))+structCons (Cons b) (Cons (Struct.Cons bs)) = Cons (Struct.Cons (b,bs))++structUncons :: T (Struct.T (a,as)) -> (T a, T (Struct.T as))+structUncons (Cons (Struct.Cons (b,bs))) = (Cons b, Cons (Struct.Cons bs))++instance (C a, Struct as) => Struct (a,as) where+   consStruct (Struct.Cons (a,as)) =+      structCons (cons a) (consStruct (Struct.Cons as))+   undefStruct = structCons undef undefStruct+   zeroStruct = structCons zero zeroStruct+   phiStruct bb at =+      case structUncons at of+         (a,as) -> Monad.lift2 structCons (phi bb a) (phiStruct bb as)+   addPhiStruct bb at bt =+      case (structUncons at, structUncons bt) of+         ((a,as), (b,bs)) -> addPhi bb a b >> addPhiStruct bb as bs++ instance C a => C (Tagged tag a) where    cons = tag . cons . unTagged    undef = tag undef@@ -648,7 +696,7 @@  instance (Compose a, Compose b, Compose c) => Compose (a,b,c) where    type Composed (a,b,c) = (Composed a, Composed b, Composed c)-   compose = uncurry3 zip3 . TupleHT.mapTriple (compose, compose, compose)+   compose = TupleHT.uncurry3 zip3 . TupleHT.mapTriple (compose, compose, compose)  instance    (Decompose pa, Decompose pb, Decompose pc) =>
src/LLVM/Extra/Multi/Vector.hs view
@@ -64,6 +64,8 @@  import qualified Type.Data.Num.Decimal as TypeNum +import qualified Foreign.Storable.Record.Tuple as StoreTuple+ import qualified Data.Traversable as Trav import qualified Data.NonEmpty.Class as NonEmptyC import qualified Data.NonEmpty as NonEmpty@@ -433,6 +435,23 @@                (insert k a0 v0)                (insert k a1 v1)                (insert k a2 v2)+++instance (C tuple) => C (StoreTuple.Tuple tuple) where+   cons = tuple . cons . fmap StoreTuple.getTuple+   undef = tuple undef+   zero = tuple zero+   phi bb = fmap tuple . phi bb . untuple+   addPhi bb a b = addPhi bb (untuple a) (untuple b)+   shuffle is u v = fmap tuple $ shuffle is (untuple u) (untuple v)+   extract k v = fmap MultiValue.tuple $ extract k (untuple v)+   insert k a v = fmap tuple $ insert k (MultiValue.untuple a) (untuple v)++tuple :: T n tuple -> T n (StoreTuple.Tuple tuple)+tuple (Cons a) = Cons a++untuple :: T n (StoreTuple.Tuple tuple) -> T n tuple+untuple (Cons a) = Cons a   class (MultiValue.IntegerConstant a, C a) => IntegerConstant a where
src/LLVM/Extra/Storable/Private.hs view
@@ -439,7 +439,7 @@ update f = MS.StateT $ \a0 -> do a1 <- f a0; return (a0,a1)  advancePtrState ::-   (C a, Tuple.ValueOf a ~ al, Value (Ptr a) ~ ptr) =>+   (C a, Value (Ptr a) ~ ptr) =>    MS.StateT ptr (CodeGenFunction r) ptr advancePtrState = update $ advancePtrStatic 1 
+ src/LLVM/Extra/Struct.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{- |+In contrast to 'LLVM.Struct' it allows to store high-level values+and thus allows to implement arbitrary-sized tuples of MultiValue's.+-}+module LLVM.Extra.Struct where++import qualified LLVM.Extra.Tuple as Tuple++import qualified LLVM.Core as LLVM++import qualified Control.Applicative.HT as App+import Control.Applicative ((<$>))+++newtype T struct = Cons struct+++class Undefined struct where+   undef :: struct++instance (Undefined struct) => Tuple.Undefined (T struct) where+   undef = Cons undef++instance+   (Tuple.Undefined a, Undefined as) =>+      Undefined (a,as) where+   undef = (Tuple.undef, undef)++instance Undefined () where+   undef = ()+++class Zero struct where+   zero :: struct++instance (Zero struct) => Tuple.Zero (T struct) where+   zero = Cons zero++instance (Tuple.Zero a, Zero as) => Zero (a,as) where+   zero = (Tuple.zero, zero)++instance Zero () where+   zero = ()+++class Phi struct where+   phi :: LLVM.BasicBlock -> struct -> LLVM.CodeGenFunction r struct+   addPhi :: LLVM.BasicBlock -> struct -> struct -> LLVM.CodeGenFunction r ()++instance (Phi struct) => Tuple.Phi (T struct) where+   phi bb (Cons s) = Cons <$> phi bb s+   addPhi bb (Cons a) (Cons b) = addPhi bb a b++instance (Tuple.Phi a, Phi as) => Phi (a,as) where+   phi bb (a,as) = App.lift2 (,) (Tuple.phi bb a) (phi bb as)+   addPhi bb (a,as) (b,bs) = Tuple.addPhi bb a b >> addPhi bb as bs++instance Phi () where+   phi _bb = return+   addPhi _bb () () = return ()+++class (Undefined (ValueOf struct)) => Value struct where+   type ValueOf struct+   valueOf :: struct -> ValueOf struct++instance (Value struct) => Tuple.Value (T struct) where+   type ValueOf (T struct) = T (ValueOf struct)+   valueOf (Cons struct) = Cons $ valueOf struct++instance (Tuple.Value a, Value as) => Value (a,as) where+   type ValueOf (a,as) = (Tuple.ValueOf a, ValueOf as)+   valueOf (a,as) = (Tuple.valueOf a, valueOf as)++instance Value () where+   type ValueOf () = ()+   valueOf () = ()