llvm-tf 12.2 → 15.0
raw patch · 7 files changed
+152/−100 lines, 7 filesdep ~llvm-ffi
Dependency ranges changed: llvm-ffi
Files
- llvm-tf.cabal +3/−3
- private/LLVM/Core/CodeGen.hs +1/−0
- private/LLVM/Core/Instructions.hs +101/−72
- private/LLVM/Core/Instructions/Guided.hs +11/−8
- private/LLVM/Core/Instructions/Private.hs +14/−5
- private/LLVM/Core/Util.hs +15/−9
- src/LLVM/Util/Arithmetic.hs +7/−3
llvm-tf.cabal view
@@ -1,5 +1,5 @@ Name: llvm-tf-Version: 12.2+Version: 15.0 License: BSD3 License-File: LICENSE Synopsis: Bindings to the LLVM compiler toolkit using type families.@@ -37,7 +37,7 @@ Location: http://code.haskell.org/~thielema/llvm-tf/ Source-Repository this- Tag: 12.2+ Tag: 15.0 Type: darcs Location: http://code.haskell.org/~thielema/llvm-tf/ @@ -53,7 +53,7 @@ Library private Default-Language: Haskell98 Build-Depends:- llvm-ffi >=9.1 && <15.0,+ llvm-ffi >=15.0 && <16.0, tfp >=1.0 && <1.1, transformers >=0.3 && <0.7, storable-record >=0.0.2 && <0.1,
private/LLVM/Core/CodeGen.hs view
@@ -21,6 +21,7 @@ FunctionArgs, FunctionCodeGen, FunctionResult, TFunction, CodeValue, CodeResult,+ proxyFromFunction, -- * Global variable creation Global, newGlobal, newNamedGlobal, defineGlobal, createGlobal, createNamedGlobal, TGlobal,
private/LLVM/Core/Instructions.hs view
@@ -81,7 +81,7 @@ import qualified LLVM.Core.Proxy as LP import qualified LLVM.Core.CodeGen as CodeGen import LLVM.Core.Instructions.Private- (ValueCons, unValue, convert, unop,+ (ValueCons, unValue, convert, unop, binopValue, proxyFromValuePtr, FFIBinOp, FFIConstBinOp, GetField, FieldType, GetElementPtr, ElementPtrType, IsIndexArg, IsIndexType, getIxList, getArg,@@ -92,6 +92,7 @@ import LLVM.Core.CodeGenMonad import LLVM.Core.CodeGen (BasicBlock(BasicBlock), Function, withCurrentBuilder,+ proxyFromFunction, ConstValue(ConstValue), zero, Value(Value), value, valueOf, UnValue, CodeResult) @@ -383,22 +384,21 @@ add, sub, mul ::- (ValueCons2 value0 value1, IsArithmetic a) =>- value0 a -> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)+ (IsArithmetic a) => Value a -> Value a -> CodeGenFunction r (Value a) add = curry $ withArithmeticType $ \typ -> uncurry $ case typ of- IntegerType -> binop FFI.constAdd FFI.buildAdd- FloatingType -> binop FFI.constFAdd FFI.buildFAdd+ IntegerType -> binopValue FFI.buildAdd+ FloatingType -> binopValue FFI.buildFAdd sub = curry $ withArithmeticType $ \typ -> uncurry $ case typ of- IntegerType -> binop FFI.constSub FFI.buildSub- FloatingType -> binop FFI.constFSub FFI.buildFSub+ IntegerType -> binopValue FFI.buildSub+ FloatingType -> binopValue FFI.buildFSub mul = curry $ withArithmeticType $ \typ -> uncurry $ case typ of- IntegerType -> binop FFI.constMul FFI.buildMul- FloatingType -> binop FFI.constFMul FFI.buildFMul+ IntegerType -> binopValue FFI.buildMul+ FloatingType -> binopValue FFI.buildFMul iadd, isub, imul :: (ValueCons2 value0 value1, IsInteger a) =>@@ -418,45 +418,35 @@ sbinop FFI.constNSWMul FFI.buildNSWMul FFI.constNUWMul FFI.buildNUWMul -- | signed or unsigned integer division depending on the type-idiv ::- (ValueCons2 value0 value1, IsInteger a) =>- value0 a -> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)-idiv = sbinop FFI.constSDiv FFI.buildSDiv FFI.constUDiv FFI.buildUDiv+idiv :: (IsInteger a) => Value a -> Value a -> CodeGenFunction r (Value a)+idiv = sbinopValue FFI.buildSDiv FFI.buildUDiv -- | signed or unsigned remainder depending on the type-irem ::- (ValueCons2 value0 value1, IsInteger a) =>- value0 a -> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)-irem = sbinop FFI.constSRem FFI.buildSRem FFI.constURem FFI.buildURem+irem :: (IsInteger a) => Value a -> Value a -> CodeGenFunction r (Value a)+irem = sbinopValue FFI.buildSRem FFI.buildURem {-# DEPRECATED udiv "use idiv instead" #-} {-# DEPRECATED sdiv "use idiv instead" #-} {-# DEPRECATED urem "use irem instead" #-} {-# DEPRECATED srem "use irem instead" #-} udiv, sdiv, urem, srem ::- (ValueCons2 value0 value1, IsInteger a) =>- value0 a -> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)-udiv = binop FFI.constUDiv FFI.buildUDiv-sdiv = binop FFI.constSDiv FFI.buildSDiv-urem = binop FFI.constURem FFI.buildURem-srem = binop FFI.constSRem FFI.buildSRem+ (IsInteger a) => Value a -> Value a -> CodeGenFunction r (Value a)+udiv = binopValue FFI.buildUDiv+sdiv = binopValue FFI.buildSDiv+urem = binopValue FFI.buildURem+srem = binopValue FFI.buildSRem fadd, fsub, fmul ::- (ValueCons2 value0 value1, IsFloating a) =>- value0 a -> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)-fadd = binop FFI.constFAdd FFI.buildFAdd-fsub = binop FFI.constFSub FFI.buildFSub-fmul = binop FFI.constFMul FFI.buildFMul+ (IsFloating a) => Value a -> Value a -> CodeGenFunction r (Value a)+fadd = binopValue FFI.buildFAdd+fsub = binopValue FFI.buildFSub+fmul = binopValue FFI.buildFMul -- | Floating point division.-fdiv ::- (ValueCons2 value0 value1, IsFloating a) =>- value0 a -> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)-fdiv = binop FFI.constFDiv FFI.buildFDiv+fdiv :: (IsFloating a) => Value a -> Value a -> CodeGenFunction r (Value a)+fdiv = binopValue FFI.buildFDiv -- | Floating point remainder.-frem ::- (ValueCons2 value0 value1, IsFloating a) =>- value0 a -> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a)-frem = binop FFI.constFRem FFI.buildFRem+frem :: (IsFloating a) => Value a -> Value a -> CodeGenFunction r (Value a)+frem = binopValue FFI.buildFRem shl, lshr, ashr, and, or, xor :: (ValueCons2 value0 value1, IsInteger a) =>@@ -473,6 +463,16 @@ value0 a -> value1 a -> CodeGenFunction r (BinOpValue value0 value1 a) shr = sbinop FFI.constAShr FFI.buildAShr FFI.constLShr FFI.buildLShr +sbinopValue ::+ forall a b r.+ (IsInteger a) =>+ FFIBinOp -> FFIBinOp ->+ Value a -> Value a -> CodeGenFunction r (Value b)+sbinopValue sop uop =+ if isSigned (LP.Proxy :: LP.Proxy a)+ then binopValue sop+ else binopValue uop+ sbinop :: forall value0 value1 a b r. (ValueCons2 value0 value1, IsInteger a) =>@@ -894,19 +894,23 @@ -} -- |Acceptable arguments to 'call'.-class (r ~ CodeResult g, f ~ CalledFunction g, g ~ CallerFunction r f) =>- CallArgs r f g where+class+ (r ~ CodeResult g, f ~ CalledFunction g, g ~ CallerFunction r f,+ IsFunction f) =>+ CallArgs r f g where type CalledFunction g type CallerFunction r f doCall :: Call f -> g -instance (Value a ~ a', CallArgs r b b') => CallArgs r (a -> b) (a' -> b') where+instance+ (IsFirstClass a, Value a ~ a', CallArgs r b b') =>+ CallArgs r (a -> b) (a' -> b') where type CalledFunction (a' -> b') = UnValue a' -> CalledFunction b' type CallerFunction r (a -> b) = Value a -> CallerFunction r b doCall f a = doCall (applyCall f a) instance- (Value a ~ a', r ~ r') =>+ (IsFirstClass a, Value a ~ a', r ~ r') => CallArgs r (IO a) (CodeGenFunction r' a') where type CalledFunction (CodeGenFunction r' a') = IO (UnValue a') type CallerFunction r (IO a) = CodeGenFunction r (Value a)@@ -924,9 +928,22 @@ data Call a = Call Caller [FFI.ValueRef] -callFromFunction :: Function a -> Call a-callFromFunction (Value f) = Call (U.makeCall f) []+typedCall ::+ (IsFunction f) =>+ Function f ->+ (U.FunctionWithType -> FFI.BuilderRef ->+ [FFI.ValueRef] -> IO FFI.ValueRef) ->+ Call a+typedCall func@(Value f) makeCall =+ Call+ (\bld args -> do+ typ <- typeRef $ proxyFromFunction func+ makeCall (typ, f) bld args)+ [] +callFromFunction :: (IsFunction f) => Function f -> Call f+callFromFunction func = typedCall func U.makeCall+ -- like Applicative.<*> infixl 4 `applyCall` @@ -938,12 +955,13 @@ invokeFromFunction ::- BasicBlock -- ^Normal return point.+ (IsFunction f)+ => BasicBlock -- ^Normal return point. -> BasicBlock -- ^Exception return point. -> Function f -- ^Function to call. -> Call f-invokeFromFunction (BasicBlock norm) (BasicBlock expt) (Value f) =- Call (U.makeInvoke norm expt f) []+invokeFromFunction (BasicBlock norm) (BasicBlock expt) func =+ typedCall func $ U.makeInvoke norm expt -- | Call a function with exception handling. invoke :: (CallArgs r f g)@@ -953,9 +971,9 @@ -> g invoke norm expt f = doCall $ invokeFromFunction norm expt f -callWithConvFromFunction :: FFI.CallingConvention -> Function f -> Call f-callWithConvFromFunction cc (Value f) =- Call (U.makeCallWithCc cc f) []+callWithConvFromFunction ::+ (IsFunction f) => FFI.CallingConvention -> Function f -> Call f+callWithConvFromFunction cc func = typedCall func $ U.makeCallWithCc cc -- | Call a function with the given arguments. The 'call' instruction -- is variadic, i.e., the number of arguments it takes depends on the@@ -968,13 +986,14 @@ callWithConv cc f = doCall $ callWithConvFromFunction cc f invokeWithConvFromFunction ::- FFI.CallingConvention -- ^Calling convention+ (IsFunction f)+ => FFI.CallingConvention -- ^Calling convention -> BasicBlock -- ^Normal return point. -> BasicBlock -- ^Exception return point. -> Function f -- ^Function to call. -> Call f-invokeWithConvFromFunction cc (BasicBlock norm) (BasicBlock expt) (Value f) =- Call (U.makeInvokeWithCc cc norm expt f) []+invokeWithConvFromFunction cc (BasicBlock norm) (BasicBlock expt) func =+ typedCall func $ U.makeInvokeWithCc cc norm expt -- | Call a function with exception handling. -- This also sets the calling convention of the call to the function.@@ -1154,17 +1173,22 @@ -- | Load a value from memory.-load :: Value (Ptr a) -- ^ Address to load from.- -> CodeGenFunction r (Value a)-load (Value p) =+load ::+ (IsType a)+ => Value (Ptr a) -- ^ Address to load from.+ -> CodeGenFunction r (Value a)+load ptr@(Value p) = liftM Value $- withCurrentBuilder $ \ bldPtr ->- U.withEmptyCString $ FFI.buildLoad bldPtr p+ withCurrentBuilder $ \ bldPtr -> do+ typ <- typeRef $ proxyFromValuePtr ptr+ U.withEmptyCString $ FFI.buildLoad2 bldPtr typ p -- | Store a value in memory-store :: Value a -- ^ Value to store.- -> Value (Ptr a) -- ^ Address to store to.- -> CodeGenFunction r ()+store ::+ (IsType a)+ => Value a -- ^ Value to store.+ -> Value (Ptr a) -- ^ Address to store to.+ -> CodeGenFunction r () store (Value v) (Value p) = do withCurrentBuilder_ $ \ bldPtr -> FFI.buildStore bldPtr v p@@ -1172,37 +1196,39 @@ -- | Address arithmetic. See LLVM description. -- (The type isn't as accurate as it should be.)-_getElementPtrDynamic :: (IsInteger i) =>+_getElementPtrDynamic :: (IsType a, IsInteger i) => Value (Ptr a) -> [Value i] -> CodeGenFunction r (Value (Ptr b))-_getElementPtrDynamic (Value ptr) ixs =+_getElementPtrDynamic ptr@(Value p) ixs = liftM Value $- withCurrentBuilder $ \ bldPtr ->+ withCurrentBuilder $ \ bldPtr -> do+ typ <- typeRef $ proxyFromValuePtr ptr U.withArrayLen [ v | Value v <- ixs ] $ \ idxLen idxPtr -> U.withEmptyCString $- FFI.buildGEP bldPtr ptr idxPtr (fromIntegral idxLen)+ FFI.buildGEP2 bldPtr typ p idxPtr (fromIntegral idxLen) -- | Address arithmetic. See LLVM description. -- The index is a nested tuple of the form @(i1,(i2,( ... ())))@. -- (This is without a doubt the most confusing LLVM instruction, but the types help.)-getElementPtr :: forall a o i r . (GetElementPtr o i, IsIndexArg a) =>+getElementPtr :: forall a o i r . (GetElementPtr o i, IsType o, IsIndexArg a) => Value (Ptr o) -> (a, i) -> CodeGenFunction r (Value (Ptr (ElementPtrType o i)))-getElementPtr (Value ptr) (a, ixs) =+getElementPtr ptr@(Value p) (a, ixs) = let ixl = getArg a : getIxList (LP.Proxy :: LP.Proxy o) ixs in liftM Value $- withCurrentBuilder $ \ bldPtr ->+ withCurrentBuilder $ \ bldPtr -> do+ typ <- typeRef $ proxyFromValuePtr ptr U.withArrayLen ixl $ \ idxLen idxPtr -> U.withEmptyCString $- FFI.buildGEP bldPtr ptr idxPtr (fromIntegral idxLen)+ FFI.buildGEP2 bldPtr typ p idxPtr (fromIntegral idxLen) -- | Like getElementPtr, but with an initial index that is 0. -- This is useful since any pointer first need to be indexed off the pointer, and then into -- its actual value. This first indexing is often with 0.-getElementPtr0 :: (GetElementPtr o i) =>+getElementPtr0 :: (GetElementPtr o i, IsType o) => Value (Ptr o) -> i -> CodeGenFunction r (Value (Ptr (ElementPtrType o i))) getElementPtr0 p i = getElementPtr p (0::Word32, i) _getElementPtr :: forall value o i i0 r.- (ValueCons value, GetElementPtr o i, IsIndexType i0) =>+ (ValueCons value, IsType o, GetElementPtr o i, IsIndexType i0) => value (Ptr o) -> (value i0, i) -> CodeGenFunction r (value (Ptr (ElementPtrType o i))) _getElementPtr vptr (a, ixs) =@@ -1212,10 +1238,13 @@ \ idxLen idxPtr -> act idxPtr (fromIntegral idxLen) in unop- (\ptr -> withArgs $ FFI.constGEP ptr)- (\bldPtr ptr cstr ->+ (\ptr -> do+ typ <- typeRef $ proxyFromValuePtr vptr+ withArgs $ FFI.constGEP2 typ ptr)+ (\bldPtr ptr cstr -> do+ typ <- typeRef $ proxyFromValuePtr vptr withArgs $ \idxPtr idxLen ->- FFI.buildGEP bldPtr ptr idxPtr idxLen cstr)+ FFI.buildGEP2 bldPtr typ ptr idxPtr idxLen cstr) vptr --------------------------------------
private/LLVM/Core/Instructions/Guided.hs view
@@ -50,7 +50,7 @@ import qualified LLVM.Core.Type as Type import qualified LLVM.Core.Util as U import qualified LLVM.Core.Proxy as LP-import LLVM.Core.Instructions.Private (ValueCons)+import LLVM.Core.Instructions.Private (ValueCons, proxyFromValuePtr) import LLVM.Core.CodeGenMonad (CodeGenFunction) import LLVM.Core.CodeGen (ConstValue, zero) import LLVM.Core.Data (Ptr)@@ -58,7 +58,7 @@ (IsArithmetic, IsInteger, IsIntegerOrPointer, IsFloating, IsFirstClass, IsPrimitive, Signed, Positive, IsType, IsSized, SizeOf,- isFloating, sizeOf, typeDesc)+ isFloating, sizeOf, typeDesc, typeRef) import qualified LLVM.FFI.Core as FFI @@ -88,7 +88,7 @@ type VT value shape a = value (Type shape a) getElementPtr ::- (ValueCons value, Priv.GetElementPtr o i, Priv.IsIndexType i0) =>+ (ValueCons value, IsType o, Priv.GetElementPtr o i, Priv.IsIndexType i0) => Guide shape (Ptr o, i0) -> VT value shape (Ptr o) -> (VT value shape i0, i) ->@@ -97,7 +97,7 @@ getElementPtrGen (fmap fst guide) vptr (Priv.unValue a, ixs) getElementPtr0 ::- (ValueCons value, Priv.GetElementPtr o i) =>+ (ValueCons value, IsType o, Priv.GetElementPtr o i) => Guide shape (Ptr o) -> VT value shape (Ptr o) -> i -> CodeGenFunction r (VT value shape (Ptr (Priv.ElementPtrType o i)))@@ -106,7 +106,7 @@ (Priv.unConst (zero :: ConstValue Word32), ixs) getElementPtrGen ::- (ValueCons value, Priv.GetElementPtr o i) =>+ (ValueCons value, IsType o, Priv.GetElementPtr o i) => Guide shape (Ptr o) -> VT value shape (Ptr o) -> (FFI.ValueRef, i) -> CodeGenFunction r (VT value shape (Ptr (Priv.ElementPtrType o i)))@@ -117,10 +117,13 @@ \ idxLen idxPtr -> act idxPtr (fromIntegral idxLen) in Priv.unop- (\ptr -> withArgs $ FFI.constGEP ptr)- (\bldPtr ptr cstr ->+ (\ptr -> do+ typ <- typeRef $ proxyFromValuePtr guide+ withArgs $ FFI.constGEP2 typ ptr)+ (\bldPtr ptr cstr -> do+ typ <- typeRef $ proxyFromValuePtr guide withArgs $ \idxPtr idxLen ->- FFI.buildGEP bldPtr ptr idxPtr idxLen cstr)+ FFI.buildGEP2 bldPtr typ ptr idxPtr idxLen cstr) vptr
private/LLVM/Core/Instructions/Private.hs view
@@ -10,7 +10,7 @@ import qualified LLVM.Core.Util as U import qualified LLVM.Core.Proxy as LP import LLVM.Core.Type (IsType, IsPrimitive, typeRef)-import LLVM.Core.Data (Vector, Array, Struct, PackedStruct)+import LLVM.Core.Data (Vector, Array, Struct, PackedStruct, Ptr) import LLVM.Core.CodeGenMonad (CodeGenFunction) import LLVM.Core.CodeGen (ConstValue(ConstValue), constOf, Value(Value), withCurrentBuilder)@@ -51,6 +51,10 @@ U.CString -> IO FFI.ValueRef +proxyFromValuePtr :: value (Ptr a) -> LP.Proxy a+proxyFromValuePtr _ = LP.Proxy++ class ValueCons value where switchValueCons :: f ConstValue -> f Value -> f value @@ -122,10 +126,15 @@ switchValueCons (BinOp $ \(ConstValue a) (ConstValue b) -> liftIO $ fmap ConstValue $ cop a b)- (BinOp $ \(Value a) (Value b) ->- liftM Value $- withCurrentBuilder $ \ bld ->- U.withEmptyCString $ op bld a b)+ (BinOp $ binopValue op)++binopValue ::+ FFIBinOp ->+ Value a -> Value b -> CodeGenFunction r (Value c)+binopValue op (Value a) (Value b) =+ liftM Value $+ withCurrentBuilder $ \ bld ->+ U.withEmptyCString $ op bld a b newtype TrinOp a b c d r value = TrinOp {
private/LLVM/Core/Util.hs view
@@ -15,6 +15,7 @@ appendBasicBlock, getBasicBlocks, -- * Functions Function,+ FunctionWithType, addFunction, getParam, getParams, -- * Structs structType,@@ -226,6 +227,7 @@ -------------------------------------- type Function = FFI.ValueRef+type FunctionWithType = (FFI.TypeRef, FFI.ValueRef) addFunction :: Module -> FFI.Linkage -> String -> Type -> IO Function addFunction modul linkage name typ =@@ -275,11 +277,13 @@ withBasicBlock :: FFI.BasicBlockRef -> (FFI.BasicBlockRef -> IO a) -> IO a withBasicBlock v f = f v -makeCall :: Function -> FFI.BuilderRef -> [Value] -> IO Value+makeCall :: FunctionWithType -> FFI.BuilderRef -> [Value] -> IO Value makeCall = makeCallWithCc FFI.C -makeCallWithCc :: FFI.CallingConvention -> Function -> FFI.BuilderRef -> [Value] -> IO Value-makeCallWithCc cc func bldPtr args = do+makeCallWithCc ::+ FFI.CallingConvention -> FunctionWithType -> FFI.BuilderRef ->+ [Value] -> IO Value+makeCallWithCc cc (funcType, func) bldPtr args = do {- print "makeCall" FFI.dumpValue func@@ -288,21 +292,23 @@ -} withArrayLen args $ \ argLen argPtr -> withEmptyCString $ \cstr -> do- i <- FFI.buildCall bldPtr func argPtr+ i <- FFI.buildCall2 bldPtr funcType func argPtr (fromIntegral argLen) cstr FFI.setInstructionCallConv i (FFI.fromCallingConvention cc) return i -makeInvoke :: BasicBlock -> BasicBlock -> Function -> FFI.BuilderRef ->+makeInvoke :: BasicBlock -> BasicBlock -> FunctionWithType -> FFI.BuilderRef -> [Value] -> IO Value makeInvoke = makeInvokeWithCc FFI.C -makeInvokeWithCc :: FFI.CallingConvention -> BasicBlock -> BasicBlock -> Function -> FFI.BuilderRef ->- [Value] -> IO Value-makeInvokeWithCc cc norm expt func bldPtr args =+makeInvokeWithCc ::+ FFI.CallingConvention -> BasicBlock -> BasicBlock ->+ FunctionWithType -> FFI.BuilderRef -> [Value] -> IO Value+makeInvokeWithCc cc norm expt (funcType, func) bldPtr args = withArrayLen args $ \ argLen argPtr -> withEmptyCString $ \cstr -> do- i <- FFI.buildInvoke bldPtr func argPtr (fromIntegral argLen) norm expt cstr+ i <- FFI.buildInvoke2 bldPtr funcType+ func argPtr (fromIntegral argLen) norm expt cstr FFI.setInstructionCallConv i (FFI.fromCallingConvention cc) return i
src/LLVM/Util/Arithmetic.hs view
@@ -231,19 +231,22 @@ class- (TFunB r a ~ b, TFunA b ~ a, CodeResult b ~ r) =>+ (TFunB r a ~ b, TFunA b ~ a, CodeResult b ~ r, IsFunction a) => ToArithFunction r a b where type TFunA b type TFunB r a toArithFunction' :: CodeGenFunction r (Call a) -> b -instance (Value a ~ b) => ToArithFunction r (IO a) (CodeGenFunction r b) where+instance+ (Value a ~ b, IsFirstClass a) =>+ ToArithFunction r (IO a) (CodeGenFunction r b) where type TFunA (CodeGenFunction r b) = IO (UnValue b) type TFunB r (IO a) = TValue r a toArithFunction' cl = runCall =<< cl instance- (ToArithFunction r b0 b1, CodeGenFunction r (Value a0) ~ a1) =>+ (ToArithFunction r b0 b1, CodeGenFunction r (Value a0) ~ a1,+ IsFirstClass a0) => ToArithFunction r (a0 -> b0) (a1 -> b1) where type TFunA (a1 -> b1) = UnValue (CodeValue a1) -> TFunA b1 type TFunB r (a0 -> b0) = TValue r a0 -> TFunB r b0@@ -252,6 +255,7 @@ _toArithFunction2 ::+ (IsFirstClass a, IsFirstClass b, IsFirstClass c) => Function (a -> b -> IO c) -> TValue r a -> TValue r b -> TValue r c _toArithFunction2 f tx ty = do x <- tx