imperative-edsl 0.5 → 0.6
raw patch · 22 files changed
+1157/−706 lines, 22 filesdep +data-default-classdep +filepathdep +randomdep −open-typerepdep ~language-c-quotedep ~microlens-mtldep ~operational-alacartePVP ok
version bump matches the API change (PVP)
Dependencies added: data-default-class, filepath, random, stm
Dependencies removed: open-typerep
Dependency ranges changed: language-c-quote, microlens-mtl, operational-alacarte, syntactic
API changes (from Hackage documentation)
- Language.C.Monad: (<<%=) :: MonadState s m => (forall f. Functor f => LensLike' f s a) -> (a -> a) -> m a
- Language.C.Monad: (<<.=) :: MonadState s m => (forall f. Functor f => LensLike' f s a) -> a -> m a
- Language.C.Monad: [_finalStms] :: CEnv -> [Stm]
- Language.C.Monad: [_stms] :: CEnv -> [Stm]
- Language.C.Monad: finalStms :: Lens' CEnv [Stm]
- Language.C.Monad: stms :: Lens' CEnv [Stm]
- Language.Embedded.Backend.C: defaultExtCompilerOpts :: ExternalCompilerOpts
- Language.Embedded.Backend.C: icompileAll :: (Interp instr CGen (Param2 exp pred), HFunctor instr) => Program instr (Param2 exp pred) a -> IO ()
- Language.Embedded.Backend.C: instance GHC.Base.Monoid Language.Embedded.Backend.C.ExternalCompilerOpts
- Language.Embedded.Backend.C.Expression: instance Data.TypeRep.Representation.PWitness Language.Embedded.Backend.C.Expression.CType Data.TypeRep.Types.Basic.BoolType t
- Language.Embedded.Backend.C.Expression: instance Data.TypeRep.Representation.PWitness Language.Embedded.Backend.C.Expression.CType Data.TypeRep.Types.Basic.CharType t
- Language.Embedded.Backend.C.Expression: instance Data.TypeRep.Representation.PWitness Language.Embedded.Backend.C.Expression.CType Data.TypeRep.Types.Basic.DoubleType t
- Language.Embedded.Backend.C.Expression: instance Data.TypeRep.Representation.PWitness Language.Embedded.Backend.C.Expression.CType Data.TypeRep.Types.Basic.FloatType t
- Language.Embedded.Backend.C.Expression: instance Data.TypeRep.Representation.PWitness Language.Embedded.Backend.C.Expression.CType Data.TypeRep.Types.Basic.FunType t
- Language.Embedded.Backend.C.Expression: instance Data.TypeRep.Representation.PWitness Language.Embedded.Backend.C.Expression.CType Data.TypeRep.Types.Basic.ListType t
- Language.Embedded.Backend.C.Expression: instance Data.TypeRep.Representation.PWitness Language.Embedded.Backend.C.Expression.CType Data.TypeRep.Types.IntWord.IntWordType t
- Language.Embedded.Backend.C.Expression: instance Data.TypeRep.Representation.PWitness Language.Embedded.Backend.C.Expression.CType Data.TypeRep.Types.Tuple.TupleType t
- Language.Embedded.Backend.C.Expression: instance Data.TypeRep.Representation.ShowClass Language.Embedded.Backend.C.Expression.CType
- Language.Embedded.Backend.C.Expression: instance Data.TypeRep.Representation.Witness Language.Embedded.Backend.C.Expression.CType Data.TypeRep.Types.Basic.BoolType t
- Language.Embedded.Backend.C.Expression: instance Data.TypeRep.Representation.Witness Language.Embedded.Backend.C.Expression.CType Data.TypeRep.Types.Basic.DoubleType t
- Language.Embedded.Backend.C.Expression: instance Data.TypeRep.Representation.Witness Language.Embedded.Backend.C.Expression.CType Data.TypeRep.Types.Basic.FloatType t
- Language.Embedded.Backend.C.Expression: instance Data.TypeRep.Representation.Witness Language.Embedded.Backend.C.Expression.CType Data.TypeRep.Types.IntWord.IntWordType t
- Language.Embedded.Backend.C.Expression: instance Language.C.Quote.Base.ToExp GHC.Int.Int16
- Language.Embedded.Backend.C.Expression: instance Language.C.Quote.Base.ToExp GHC.Int.Int32
- Language.Embedded.Backend.C.Expression: instance Language.C.Quote.Base.ToExp GHC.Int.Int64
- Language.Embedded.Backend.C.Expression: instance Language.C.Quote.Base.ToExp GHC.Int.Int8
- Language.Embedded.Backend.C.Expression: instance Language.C.Quote.Base.ToExp GHC.Word.Word16
- Language.Embedded.Backend.C.Expression: instance Language.C.Quote.Base.ToExp GHC.Word.Word32
- Language.Embedded.Backend.C.Expression: instance Language.C.Quote.Base.ToExp GHC.Word.Word64
- Language.Embedded.Backend.C.Expression: instance Language.C.Quote.Base.ToExp GHC.Word.Word8
- Language.Embedded.Backend.C.Expression: pCType :: Proxy CType
- Language.Embedded.CExp: ArrIx :: IArr i a -> Sym (i :-> Full a)
- Language.Embedded.CExp: BiAdd :: Binary (a -> a -> a)
- Language.Embedded.CExp: BiAnd :: Binary (Bool -> Bool -> Bool)
- Language.Embedded.CExp: BiDiv :: Binary (a -> a -> a)
- Language.Embedded.CExp: BiEq :: Binary (a -> a -> Bool)
- Language.Embedded.CExp: BiGe :: Binary (a -> a -> Bool)
- Language.Embedded.CExp: BiGt :: Binary (a -> a -> Bool)
- Language.Embedded.CExp: BiLe :: Binary (a -> a -> Bool)
- Language.Embedded.CExp: BiLt :: Binary (a -> a -> Bool)
- Language.Embedded.CExp: BiMul :: Binary (a -> a -> a)
- Language.Embedded.CExp: BiNEq :: Binary (a -> a -> Bool)
- Language.Embedded.CExp: BiOr :: Binary (Bool -> Bool -> Bool)
- Language.Embedded.CExp: BiQuot :: Binary (a -> a -> a)
- Language.Embedded.CExp: BiRem :: Binary (a -> a -> a)
- Language.Embedded.CExp: BiSub :: Binary (a -> a -> a)
- Language.Embedded.CExp: Cast :: (a -> b) -> Sym (a :-> Full b)
- Language.Embedded.CExp: Cond :: Sym (Bool :-> (a :-> (a :-> Full a)))
- Language.Embedded.CExp: Const :: SupportCode -> String -> a -> Sym (Full a)
- Language.Embedded.CExp: Fun :: SupportCode -> String -> Denotation sig -> Sym sig
- Language.Embedded.CExp: Lit :: String -> a -> Sym (Full a)
- Language.Embedded.CExp: Op :: Binary (a -> b -> c) -> Sym (a :-> (b :-> Full c))
- Language.Embedded.CExp: T :: Sym sig -> T sig
- Language.Embedded.CExp: UOp :: Unary (a -> b) -> Sym (a :-> Full b)
- Language.Embedded.CExp: UnNeg :: Unary (a -> a)
- Language.Embedded.CExp: UnNot :: Unary (Bool -> Bool)
- Language.Embedded.CExp: Var :: VarId -> Sym (Full a)
- Language.Embedded.CExp: [unT] :: T sig -> Sym sig
- Language.Embedded.CExp: instance (GHC.Float.Floating a, GHC.Classes.Ord a, Language.Embedded.Backend.C.Expression.CType a) => GHC.Float.Floating (Language.Embedded.CExp.CExp a)
- Language.Embedded.CExp: round_ :: (RealFrac a, Integral b, CType b) => CExp a -> CExp b
- Language.Embedded.Concurrent: ChanEval :: (BoundedChan a) -> (IORef Bool) -> (IORef Bool) -> Chan t a
- Language.Embedded.Concurrent: TIDEval :: ThreadId -> (Flag ()) -> ThreadId
- Language.Embedded.Concurrent: type ChanBound = Word16
- Language.Embedded.Concurrent.CMD: ChanEval :: (BoundedChan a) -> (IORef Bool) -> (IORef Bool) -> Chan t a
- Language.Embedded.Concurrent.CMD: CloseChan :: Chan Closeable a -> ChanCMD (Param3 prog exp pred) ()
- Language.Embedded.Concurrent.CMD: ForkWithId :: (ThreadId -> prog ()) -> ThreadCMD (Param3 prog exp pred) ThreadId
- Language.Embedded.Concurrent.CMD: Kill :: ThreadId -> ThreadCMD (Param3 prog exp pred) ()
- Language.Embedded.Concurrent.CMD: NewChan :: exp ChanBound -> ChanCMD (Param3 prog exp pred) (Chan t a)
- Language.Embedded.Concurrent.CMD: ReadChan :: Chan t a -> ChanCMD (Param3 prog exp pred) (Val a)
- Language.Embedded.Concurrent.CMD: ReadOK :: Chan Closeable a -> ChanCMD (Param3 prog exp pred) (Val Bool)
- Language.Embedded.Concurrent.CMD: TIDEval :: ThreadId -> (Flag ()) -> ThreadId
- Language.Embedded.Concurrent.CMD: Wait :: ThreadId -> ThreadCMD (Param3 prog exp pred) ()
- Language.Embedded.Concurrent.CMD: WriteChan :: Chan t a -> exp a -> ChanCMD (Param3 prog exp pred) (Val Bool)
- Language.Embedded.Concurrent.CMD: instance (Language.Embedded.Concurrent.CMD.ChanCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Concurrent.CMD.ChanCMD instr
- Language.Embedded.Concurrent.CMD: instance forall (k :: BOX) (k1 :: BOX) (instr :: (,) (* -> *) ((,) (k -> *) ((,) k1 *)) -> * -> *). (Language.Embedded.Concurrent.CMD.ThreadCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Concurrent.CMD.ThreadCMD instr
- Language.Embedded.Concurrent.CMD: instance forall (k :: BOX) (pred :: k). Control.Monad.Operational.Higher.InterpBi Language.Embedded.Concurrent.CMD.ThreadCMD GHC.Types.IO (Data.ALaCarte.Param1 pred)
- Language.Embedded.Concurrent.CMD: type ChanBound = Word16
- Language.Embedded.Expression: ValEval :: a -> Val a
- Language.Embedded.Expression: valExp :: (FreeExp exp, VarPred exp a) => a -> exp a
- Language.Embedded.Imperative.Args: ArrArg :: Arr i a -> ArrArg pred
- Language.Embedded.Imperative.Args: IArrArg :: IArr i a -> IArrArg pred
- Language.Embedded.Imperative.Args: ObjArg :: Object -> ObjArg pred
- Language.Embedded.Imperative.Args: PtrArg :: Ptr a -> PtrArg pred
- Language.Embedded.Imperative.Args: RefArg :: Ref a -> RefArg pred
- Language.Embedded.Imperative.Args: StrArg :: String -> StrArg pred
- Language.Embedded.Imperative.Args: instance Language.Embedded.Imperative.CMD.Arg Language.Embedded.Imperative.Args.ArrArg Language.Embedded.Backend.C.Expression.CType
- Language.Embedded.Imperative.Args: instance Language.Embedded.Imperative.CMD.Arg Language.Embedded.Imperative.Args.IArrArg Language.Embedded.Backend.C.Expression.CType
- Language.Embedded.Imperative.Args: instance Language.Embedded.Imperative.CMD.Arg Language.Embedded.Imperative.Args.PtrArg Language.Embedded.Backend.C.Expression.CType
- Language.Embedded.Imperative.Args: instance Language.Embedded.Imperative.CMD.Arg Language.Embedded.Imperative.Args.RefArg Language.Embedded.Backend.C.Expression.CType
- Language.Embedded.Imperative.Args: instance forall (k :: BOX) (pred :: k). Language.Embedded.Imperative.CMD.Arg Language.Embedded.Imperative.Args.ObjArg pred
- Language.Embedded.Imperative.Args: instance forall (k :: BOX) (pred :: k). Language.Embedded.Imperative.CMD.Arg Language.Embedded.Imperative.Args.StrArg pred
- Language.Embedded.Imperative.CMD: AddDefinition :: Definition -> C_CMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: AddExternFun :: String -> proxy res -> [FunArg exp pred] -> C_CMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: AddExternProc :: String -> [FunArg exp pred] -> C_CMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: AddInclude :: String -> C_CMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: AddrArg :: FunArg exp pred -> FunArg exp pred
- Language.Embedded.Imperative.CMD: ArrEval :: (IORef (IOArray i a)) -> Arr i a
- Language.Embedded.Imperative.CMD: Assert :: exp Bool -> String -> ControlCMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: Break :: ControlCMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: CallFun :: String -> [FunArg exp pred] -> C_CMD (Param3 prog exp pred) (Val a)
- Language.Embedded.Imperative.CMD: CallProc :: Maybe obj -> String -> [FunArg exp pred] -> C_CMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: CopyArr :: Arr i a -> Arr i a -> exp i -> ArrCMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: DerefArg :: FunArg exp pred -> FunArg exp pred
- Language.Embedded.Imperative.CMD: FClose :: Handle -> FileCMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: FEof :: Handle -> FileCMD (Param3 prog exp pred) (Val Bool)
- Language.Embedded.Imperative.CMD: FGet :: Handle -> FileCMD (Param3 prog exp pred) (Val a)
- Language.Embedded.Imperative.CMD: FOpen :: FilePath -> IOMode -> FileCMD (Param3 prog exp pred) Handle
- Language.Embedded.Imperative.CMD: FPrintf :: Handle -> String -> [PrintfArg exp] -> FileCMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: For :: IxRange (exp i) -> (Val i -> prog ()) -> ControlCMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: FunArg :: arg pred -> FunArg exp pred
- Language.Embedded.Imperative.CMD: GetArr :: exp i -> Arr i a -> ArrCMD (Param3 prog exp pred) (Val a)
- Language.Embedded.Imperative.CMD: GetRef :: Ref a -> RefCMD (Param3 prog exp pred) (Val a)
- Language.Embedded.Imperative.CMD: HandleEval :: Handle -> Handle
- Language.Embedded.Imperative.CMD: IArrEval :: (Array i a) -> IArr i a
- Language.Embedded.Imperative.CMD: If :: exp Bool -> prog () -> prog () -> ControlCMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: InModule :: String -> prog () -> C_CMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: InitArr :: String -> [a] -> ArrCMD (Param3 prog exp pred) (Arr i a)
- Language.Embedded.Imperative.CMD: InitRef :: String -> exp a -> RefCMD (Param3 prog exp pred) (Ref a)
- Language.Embedded.Imperative.CMD: NewArr :: String -> exp i -> ArrCMD (Param3 prog exp pred) (Arr i a)
- Language.Embedded.Imperative.CMD: NewObject :: String -> String -> Bool -> C_CMD (Param3 prog exp pred) Object
- Language.Embedded.Imperative.CMD: NewPtr :: String -> C_CMD (Param3 prog exp pred) (Ptr a)
- Language.Embedded.Imperative.CMD: NewRef :: String -> RefCMD (Param3 prog exp pred) (Ref a)
- Language.Embedded.Imperative.CMD: PrintfArg :: exp a -> PrintfArg exp
- Language.Embedded.Imperative.CMD: PtrToArr :: Ptr a -> C_CMD (Param3 prog exp pred) (Arr i a)
- Language.Embedded.Imperative.CMD: RefEval :: (IORef a) -> Ref a
- Language.Embedded.Imperative.CMD: SetArr :: exp i -> exp a -> Arr i a -> ArrCMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: SetRef :: Ref a -> exp a -> RefCMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: SwapPtr :: a -> a -> PtrCMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: UnsafeFreezeArr :: Arr i a -> ArrCMD (Param3 prog exp pred) (IArr i a)
- Language.Embedded.Imperative.CMD: UnsafeFreezeRef :: Ref a -> RefCMD (Param3 prog exp pred) (Val a)
- Language.Embedded.Imperative.CMD: UnsafeThawArr :: IArr i a -> ArrCMD (Param3 prog exp pred) (Arr i a)
- Language.Embedded.Imperative.CMD: ValArg :: exp a -> FunArg exp pred
- Language.Embedded.Imperative.CMD: While :: prog (exp Bool) -> prog () -> ControlCMD (Param3 prog exp pred) ()
- Language.Embedded.Imperative.CMD: formatSpecifier :: Formattable a => Proxy a -> String
- Language.Embedded.Imperative.CMD: instance (Language.Embedded.Imperative.CMD.ArrCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Imperative.CMD.ArrCMD instr
- Language.Embedded.Imperative.CMD: instance (Language.Embedded.Imperative.CMD.C_CMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Imperative.CMD.C_CMD instr
- Language.Embedded.Imperative.CMD: instance (Language.Embedded.Imperative.CMD.ControlCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Imperative.CMD.ControlCMD instr
- Language.Embedded.Imperative.CMD: instance (Language.Embedded.Imperative.CMD.FileCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Imperative.CMD.FileCMD instr
- Language.Embedded.Imperative.CMD: instance (Language.Embedded.Imperative.CMD.RefCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Imperative.CMD.RefCMD instr
- Language.Embedded.Imperative.CMD: instance Language.Embedded.Backend.C.Expression.CompExp exp => Language.Embedded.Imperative.CMD.Arg (Language.Embedded.Imperative.CMD.FunArg exp) Language.Embedded.Backend.C.Expression.CType
- Language.Embedded.Imperative.CMD: instance forall (k :: BOX) (k1 :: BOX) (instr :: (,) (* -> *) ((,) (k -> *) ((,) k1 *)) -> * -> *). (Language.Embedded.Imperative.CMD.PtrCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Imperative.CMD.PtrCMD instr
- Language.Embedded.Imperative.CMD: instance forall (k :: BOX) (pred :: k). Control.Monad.Operational.Higher.InterpBi Language.Embedded.Imperative.CMD.PtrCMD GHC.Types.IO (Data.ALaCarte.Param1 pred)
- Language.Embedded.Imperative.Frontend.General: AddrArg :: FunArg exp pred -> FunArg exp pred
- Language.Embedded.Imperative.Frontend.General: DerefArg :: FunArg exp pred -> FunArg exp pred
- Language.Embedded.Imperative.Frontend.General: FunArg :: arg pred -> FunArg exp pred
- Language.Embedded.Imperative.Frontend.General: ValArg :: exp a -> FunArg exp pred
- Language.Embedded.Signature: Empty :: Ann exp a
- Language.Embedded.Signature: Lam :: Ann exp a -> (Val a -> Signature exp pred b) -> Signature exp pred (a -> b)
- Language.Embedded.Signature: Named :: String -> Ann exp a
- Language.Embedded.Signature: Native :: exp len -> Ann exp [a]
- Language.Embedded.Signature: Ptr :: String -> exp a -> Signature exp pred a
- Language.Embedded.Signature: Ret :: String -> exp a -> Signature exp pred a
- Language.Embedded.Traversal: instance forall (k :: BOX) (i1 :: (,) (* -> *) k -> * -> *) (i2 :: (,) (* -> *) k -> * -> *). (Language.Embedded.Traversal.DryInterp i1, Language.Embedded.Traversal.DryInterp i2) => Language.Embedded.Traversal.DryInterp (i1 Data.ALaCarte.:+: i2)
+ Language.C.Monad: [_finalItems] :: CEnv -> [BlockItem]
+ Language.C.Monad: [_items] :: CEnv -> [BlockItem]
+ Language.C.Monad: addItem :: MonadC m => BlockItem -> m ()
+ Language.C.Monad: finalItems :: Lens' CEnv [BlockItem]
+ Language.C.Monad: items :: Lens' CEnv [BlockItem]
+ Language.Embedded.Backend.C: class Default a
+ Language.Embedded.Backend.C: def :: Default a => a
+ Language.Embedded.Backend.C: instance Data.Default.Class.Default Language.Embedded.Backend.C.ExternalCompilerOpts
+ Language.Embedded.Backend.C: withCompiled :: (Interp instr CGen (Param2 exp pred), HFunctor instr) => Program instr (Param2 exp pred) a -> ((String -> IO String) -> IO b) -> IO b
+ Language.Embedded.Backend.C: withCompiled' :: (Interp instr CGen (Param2 exp pred), HFunctor instr) => ExternalCompilerOpts -> Program instr (Param2 exp pred) a -> ((String -> IO String) -> IO b) -> IO b
+ Language.Embedded.Backend.C.Expression: class CompTypeClass ct
+ Language.Embedded.Backend.C.Expression: compLit :: (CompTypeClass ct, ct a, MonadC m) => proxy ct -> a -> m Exp
+ Language.Embedded.Backend.C.Expression: compType :: (CompTypeClass ct, ct a, MonadC m) => proxy1 ct -> proxy2 a -> m Type
+ Language.Embedded.Backend.C.Expression: instance Language.Embedded.Backend.C.Expression.CompTypeClass Language.Embedded.Backend.C.Expression.CType
+ Language.Embedded.Backend.C.Expression: proxyPred :: cmd (Param3 p e pred) a -> Proxy pred
+ Language.Embedded.CExp: [ArrIx] :: (Integral i, Ix i) => IArr i a -> Sym (i :-> Full a)
+ Language.Embedded.CExp: [BiAdd] :: Num a => Binary (a -> a -> a)
+ Language.Embedded.CExp: [BiAnd] :: Binary (Bool -> Bool -> Bool)
+ Language.Embedded.CExp: [BiDiv] :: Fractional a => Binary (a -> a -> a)
+ Language.Embedded.CExp: [BiEq] :: CType a => Binary (a -> a -> Bool)
+ Language.Embedded.CExp: [BiGe] :: (Ord a, CType a) => Binary (a -> a -> Bool)
+ Language.Embedded.CExp: [BiGt] :: (Ord a, CType a) => Binary (a -> a -> Bool)
+ Language.Embedded.CExp: [BiLe] :: (Ord a, CType a) => Binary (a -> a -> Bool)
+ Language.Embedded.CExp: [BiLt] :: (Ord a, CType a) => Binary (a -> a -> Bool)
+ Language.Embedded.CExp: [BiMul] :: Num a => Binary (a -> a -> a)
+ Language.Embedded.CExp: [BiNEq] :: CType a => Binary (a -> a -> Bool)
+ Language.Embedded.CExp: [BiOr] :: Binary (Bool -> Bool -> Bool)
+ Language.Embedded.CExp: [BiQuot] :: Integral a => Binary (a -> a -> a)
+ Language.Embedded.CExp: [BiRem] :: Integral a => Binary (a -> a -> a)
+ Language.Embedded.CExp: [BiSub] :: Num a => Binary (a -> a -> a)
+ Language.Embedded.CExp: [Cast] :: (a -> b) -> Sym (a :-> Full b)
+ Language.Embedded.CExp: [Cond] :: Sym (Bool :-> (a :-> (a :-> Full a)))
+ Language.Embedded.CExp: [Const] :: String -> a -> Sym (Full a)
+ Language.Embedded.CExp: [Fun] :: Signature sig => String -> Denotation sig -> Sym sig
+ Language.Embedded.CExp: [Lit] :: String -> a -> Sym (Full a)
+ Language.Embedded.CExp: [Op] :: Binary (a -> b -> c) -> Sym (a :-> (b :-> Full c))
+ Language.Embedded.CExp: [T] :: CType (DenResult sig) => {unT :: Sym sig} -> T sig
+ Language.Embedded.CExp: [UOp] :: Unary (a -> b) -> Sym (a :-> Full b)
+ Language.Embedded.CExp: [UnNeg] :: Num a => Unary (a -> a)
+ Language.Embedded.CExp: [UnNot] :: Unary (Bool -> Bool)
+ Language.Embedded.CExp: [Var] :: VarId -> Sym (Full a)
+ Language.Embedded.CExp: [WithCode] :: SupportCode -> Sym (a :-> Full a)
+ Language.Embedded.CExp: infix 4 #>=
+ Language.Embedded.CExp: infixl 1 ?
+ Language.Embedded.CExp: withCode :: CType a => (forall m. MonadC m => m ()) -> CExp a -> CExp a
+ Language.Embedded.Concurrent: ChanRun :: (Chan Dynamic) -> Chan t a
+ Language.Embedded.Concurrent: TIDRun :: ThreadId -> (Flag ()) -> ThreadId
+ Language.Embedded.Concurrent: [OneSize] :: (pred a, Integral i) => proxy a -> exp i -> ChanSize exp pred i
+ Language.Embedded.Concurrent: [PlusSize] :: Integral i => ChanSize exp pred i -> ChanSize exp pred i -> ChanSize exp pred i
+ Language.Embedded.Concurrent: [TimesSize] :: Integral i => exp i -> ChanSize exp pred i -> ChanSize exp pred i
+ Language.Embedded.Concurrent: data ChanSize exp pred i
+ Language.Embedded.Concurrent: delayThread :: (Integral i, ThreadCMD :<: instr) => exp i -> ProgramT instr (Param2 exp pred) m ()
+ Language.Embedded.Concurrent: newChan' :: (Integral i, ChanCMD :<: instr) => ChanSize exp pred i -> ProgramT instr (Param2 exp pred) m (Chan Uncloseable a)
+ Language.Embedded.Concurrent: newCloseableChan' :: (Integral i, ChanCMD :<: instr) => ChanSize exp pred i -> ProgramT instr (Param2 exp pred) m (Chan Closeable a)
+ Language.Embedded.Concurrent: plusSize :: Integral i => ChanSize exp pred i -> ChanSize exp pred i -> ChanSize exp pred i
+ Language.Embedded.Concurrent: readChan' :: (Typeable a, pred a, FreeExp exp, FreePred exp a, ChanCMD :<: instr, Monad m) => Chan t c -> ProgramT instr (Param2 exp pred) m (exp a)
+ Language.Embedded.Concurrent: readChanBuf :: (Typeable a, pred a, Ix i, Integral i, FreeExp exp, FreePred exp Bool, ChanCMD :<: instr, Monad m) => Chan t a -> exp i -> exp i -> Arr i a -> ProgramT instr (Param2 exp pred) m (exp Bool)
+ Language.Embedded.Concurrent: readChanBuf' :: (Typeable a, pred a, Ix i, Integral i, FreeExp exp, FreePred exp Bool, ChanCMD :<: instr, Monad m) => Chan t c -> exp i -> exp i -> Arr i a -> ProgramT instr (Param2 exp pred) m (exp Bool)
+ Language.Embedded.Concurrent: timesSize :: Integral i => exp i -> ChanSize exp pred i -> ChanSize exp pred i
+ Language.Embedded.Concurrent: timesSizeOf :: (pred a, Integral i) => exp i -> proxy a -> ChanSize exp pred i
+ Language.Embedded.Concurrent: writeChan' :: (Typeable a, pred a, FreeExp exp, FreePred exp Bool, ChanCMD :<: instr, Monad m) => Chan t c -> exp a -> ProgramT instr (Param2 exp pred) m (exp Bool)
+ Language.Embedded.Concurrent: writeChanBuf :: (Typeable a, pred a, Ix i, Integral i, FreeExp exp, FreePred exp Bool, ChanCMD :<: instr, Monad m) => Chan t a -> exp i -> exp i -> Arr i a -> ProgramT instr (Param2 exp pred) m (exp Bool)
+ Language.Embedded.Concurrent: writeChanBuf' :: (Typeable a, pred a, Ix i, Integral i, FreeExp exp, FreePred exp Bool, ChanCMD :<: instr, Monad m) => Chan t c -> exp i -> exp i -> Arr i a -> ProgramT instr (Param2 exp pred) m (exp Bool)
+ Language.Embedded.Concurrent.CMD: ChanRun :: (Chan Dynamic) -> Chan t a
+ Language.Embedded.Concurrent.CMD: TIDRun :: ThreadId -> (Flag ()) -> ThreadId
+ Language.Embedded.Concurrent.CMD: [CloseChan] :: Chan Closeable c -> ChanCMD (Param3 prog exp pred) ()
+ Language.Embedded.Concurrent.CMD: [ForkWithId] :: (ThreadId -> prog ()) -> ThreadCMD (Param3 prog exp pred) ThreadId
+ Language.Embedded.Concurrent.CMD: [Kill] :: ThreadId -> ThreadCMD (Param3 prog exp pred) ()
+ Language.Embedded.Concurrent.CMD: [NewChan] :: ChanSize exp pred i -> ChanCMD (Param3 prog exp pred) (Chan t c)
+ Language.Embedded.Concurrent.CMD: [OneSize] :: (pred a, Integral i) => proxy a -> exp i -> ChanSize exp pred i
+ Language.Embedded.Concurrent.CMD: [PlusSize] :: Integral i => ChanSize exp pred i -> ChanSize exp pred i -> ChanSize exp pred i
+ Language.Embedded.Concurrent.CMD: [ReadChan] :: (Typeable a, pred a, Ix i, Integral i) => Chan t c -> exp i -> exp i -> Arr i a -> ChanCMD (Param3 prog exp pred) (Val Bool)
+ Language.Embedded.Concurrent.CMD: [ReadOK] :: Chan Closeable c -> ChanCMD (Param3 prog exp pred) (Val Bool)
+ Language.Embedded.Concurrent.CMD: [ReadOne] :: (Typeable a, pred a) => Chan t c -> ChanCMD (Param3 prog exp pred) (Val a)
+ Language.Embedded.Concurrent.CMD: [Sleep] :: Integral i => exp i -> ThreadCMD (Param3 prog exp pred) ()
+ Language.Embedded.Concurrent.CMD: [TimesSize] :: Integral i => exp i -> ChanSize exp pred i -> ChanSize exp pred i
+ Language.Embedded.Concurrent.CMD: [Wait] :: ThreadId -> ThreadCMD (Param3 prog exp pred) ()
+ Language.Embedded.Concurrent.CMD: [WriteChan] :: (Typeable a, pred a, Ix i, Integral i) => Chan t c -> exp i -> exp i -> Arr i a -> ChanCMD (Param3 prog exp pred) (Val Bool)
+ Language.Embedded.Concurrent.CMD: [WriteOne] :: (Typeable a, pred a) => Chan t c -> exp a -> ChanCMD (Param3 prog exp pred) (Val Bool)
+ Language.Embedded.Concurrent.CMD: data ChanSize exp pred i
+ Language.Embedded.Concurrent.CMD: instance (Language.Embedded.Concurrent.CMD.ChanCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Concurrent.CMD.ChanCMD instr env
+ Language.Embedded.Concurrent.CMD: instance Language.Embedded.Expression.FreeExp GHC.Types.IO
+ Language.Embedded.Concurrent.CMD: instance forall k (instr :: (* -> *, (* -> *, (k, *))) -> * -> *) env. (Language.Embedded.Concurrent.CMD.ThreadCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Concurrent.CMD.ThreadCMD instr env
+ Language.Embedded.Concurrent.CMD: instance forall k (pred :: k). Control.Monad.Operational.Higher.InterpBi Language.Embedded.Concurrent.CMD.ThreadCMD GHC.Types.IO (Data.ALaCarte.Param1 pred)
+ Language.Embedded.Concurrent.CMD: plusSize :: Integral i => ChanSize exp pred i -> ChanSize exp pred i -> ChanSize exp pred i
+ Language.Embedded.Concurrent.CMD: timesSize :: Integral i => exp i -> ChanSize exp pred i -> ChanSize exp pred i
+ Language.Embedded.Concurrent.CMD: timesSizeOf :: (pred a, Integral i) => exp i -> proxy a -> ChanSize exp pred i
+ Language.Embedded.Expression: ValRun :: a -> Val a
+ Language.Embedded.Expression: constExp :: (FreeExp exp, FreePred exp a) => a -> exp a
+ Language.Embedded.Expression: type family FreePred exp :: * -> Constraint;
+ Language.Embedded.Expression: }
+ Language.Embedded.Imperative: type family FreePred exp :: * -> Constraint;
+ Language.Embedded.Imperative: }
+ Language.Embedded.Imperative.Args: [ArrArg] :: pred a => Arr i a -> ArrArg pred
+ Language.Embedded.Imperative.Args: [ConstArg] :: {constArgType :: String, constArg :: String} -> ConstArg pred
+ Language.Embedded.Imperative.Args: [IArrArg] :: pred a => IArr i a -> IArrArg pred
+ Language.Embedded.Imperative.Args: [ObjArg] :: Object -> ObjArg pred
+ Language.Embedded.Imperative.Args: [PtrArg] :: pred a => Ptr a -> PtrArg pred
+ Language.Embedded.Imperative.Args: [RefArg] :: pred a => Ref a -> RefArg pred
+ Language.Embedded.Imperative.Args: [StrArg] :: String -> StrArg pred
+ Language.Embedded.Imperative.Args: data ConstArg pred
+ Language.Embedded.Imperative.Args: instance Language.Embedded.Backend.C.Expression.CompTypeClass ct => Language.Embedded.Imperative.CMD.Arg Language.Embedded.Imperative.Args.ArrArg ct
+ Language.Embedded.Imperative.Args: instance Language.Embedded.Backend.C.Expression.CompTypeClass ct => Language.Embedded.Imperative.CMD.Arg Language.Embedded.Imperative.Args.IArrArg ct
+ Language.Embedded.Imperative.Args: instance Language.Embedded.Backend.C.Expression.CompTypeClass ct => Language.Embedded.Imperative.CMD.Arg Language.Embedded.Imperative.Args.PtrArg ct
+ Language.Embedded.Imperative.Args: instance Language.Embedded.Backend.C.Expression.CompTypeClass ct => Language.Embedded.Imperative.CMD.Arg Language.Embedded.Imperative.Args.RefArg ct
+ Language.Embedded.Imperative.Args: instance forall k (pred :: k). Language.Embedded.Imperative.CMD.Arg Language.Embedded.Imperative.Args.ConstArg pred
+ Language.Embedded.Imperative.Args: instance forall k (pred :: k). Language.Embedded.Imperative.CMD.Arg Language.Embedded.Imperative.Args.ObjArg pred
+ Language.Embedded.Imperative.Args: instance forall k (pred :: k). Language.Embedded.Imperative.CMD.Arg Language.Embedded.Imperative.Args.StrArg pred
+ Language.Embedded.Imperative.CMD: ArrRun :: (IORef (IOArray i a)) -> Arr i a
+ Language.Embedded.Imperative.CMD: HandleRun :: Handle -> Handle
+ Language.Embedded.Imperative.CMD: IArrRun :: (Array i a) -> IArr i a
+ Language.Embedded.Imperative.CMD: RefRun :: (IORef a) -> Ref a
+ Language.Embedded.Imperative.CMD: [AddDefinition] :: Definition -> C_CMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [AddExternFun] :: pred res => String -> proxy res -> [FunArg exp pred] -> C_CMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [AddExternProc] :: String -> [FunArg exp pred] -> C_CMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [AddInclude] :: String -> C_CMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [AddrArg] :: FunArg exp pred -> FunArg exp pred
+ Language.Embedded.Imperative.CMD: [Assert] :: exp Bool -> String -> ControlCMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [Break] :: ControlCMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [CallFun] :: pred a => String -> [FunArg exp pred] -> C_CMD (Param3 prog exp pred) (Val a)
+ Language.Embedded.Imperative.CMD: [CallProc] :: Assignable obj => Maybe obj -> String -> [FunArg exp pred] -> C_CMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [CopyArr] :: (pred a, Integral i, Ix i) => (Arr i a, exp i) -> (Arr i a, exp i) -> exp i -> ArrCMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [DerefArg] :: FunArg exp pred -> FunArg exp pred
+ Language.Embedded.Imperative.CMD: [FClose] :: Handle -> FileCMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [FEof] :: Handle -> FileCMD (Param3 prog exp pred) (Val Bool)
+ Language.Embedded.Imperative.CMD: [FGet] :: (pred a, Formattable a) => Handle -> FileCMD (Param3 prog exp pred) (Val a)
+ Language.Embedded.Imperative.CMD: [FOpen] :: FilePath -> IOMode -> FileCMD (Param3 prog exp pred) Handle
+ Language.Embedded.Imperative.CMD: [FPrintf] :: Handle -> String -> [PrintfArg exp] -> FileCMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [For] :: (pred i, Integral i) => IxRange (exp i) -> (Val i -> prog ()) -> ControlCMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [FunArg] :: Arg arg pred => arg pred -> FunArg exp pred
+ Language.Embedded.Imperative.CMD: [GetArr] :: (pred a, Integral i, Ix i) => exp i -> Arr i a -> ArrCMD (Param3 prog exp pred) (Val a)
+ Language.Embedded.Imperative.CMD: [GetRef] :: pred a => Ref a -> RefCMD (Param3 prog exp pred) (Val a)
+ Language.Embedded.Imperative.CMD: [If] :: exp Bool -> prog () -> prog () -> ControlCMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [InModule] :: String -> prog () -> C_CMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [InitArr] :: (pred a, Integral i, Ix i) => String -> [a] -> ArrCMD (Param3 prog exp pred) (Arr i a)
+ Language.Embedded.Imperative.CMD: [InitCArr] :: (pred a, Integral i, Ix i) => String -> Maybe i -> [a] -> C_CMD (Param3 prog exp pred) (Arr i a)
+ Language.Embedded.Imperative.CMD: [InitRef] :: pred a => String -> exp a -> RefCMD (Param3 prog exp pred) (Ref a)
+ Language.Embedded.Imperative.CMD: [NewArr] :: (pred a, Integral i, Ix i) => String -> exp i -> ArrCMD (Param3 prog exp pred) (Arr i a)
+ Language.Embedded.Imperative.CMD: [NewCArr] :: (pred a, Integral i, Ix i) => String -> Maybe i -> exp i -> C_CMD (Param3 prog exp pred) (Arr i a)
+ Language.Embedded.Imperative.CMD: [NewObject] :: String -> String -> Bool -> C_CMD (Param3 prog exp pred) Object
+ Language.Embedded.Imperative.CMD: [NewPtr] :: pred a => String -> C_CMD (Param3 prog exp pred) (Ptr a)
+ Language.Embedded.Imperative.CMD: [NewRef] :: pred a => String -> RefCMD (Param3 prog exp pred) (Ref a)
+ Language.Embedded.Imperative.CMD: [OffsetArg] :: FunArg exp pred -> exp i -> FunArg exp pred
+ Language.Embedded.Imperative.CMD: [PrintfArg] :: PrintfArg a => exp a -> PrintfArg exp
+ Language.Embedded.Imperative.CMD: [PtrToArr] :: Ptr a -> C_CMD (Param3 prog exp pred) (Arr i a)
+ Language.Embedded.Imperative.CMD: [SetArr] :: (pred a, Integral i, Ix i) => exp i -> exp a -> Arr i a -> ArrCMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [SetRef] :: pred a => Ref a -> exp a -> RefCMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [SwapPtr] :: IsPointer a => a -> a -> PtrCMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: [UnsafeFreezeArr] :: (pred a, Integral i, Ix i) => Arr i a -> ArrCMD (Param3 prog exp pred) (IArr i a)
+ Language.Embedded.Imperative.CMD: [UnsafeFreezeRef] :: pred a => Ref a -> RefCMD (Param3 prog exp pred) (Val a)
+ Language.Embedded.Imperative.CMD: [UnsafeThawArr] :: (pred a, Integral i, Ix i) => IArr i a -> ArrCMD (Param3 prog exp pred) (Arr i a)
+ Language.Embedded.Imperative.CMD: [ValArg] :: pred a => exp a -> FunArg exp pred
+ Language.Embedded.Imperative.CMD: [While] :: prog (exp Bool) -> prog () -> ControlCMD (Param3 prog exp pred) ()
+ Language.Embedded.Imperative.CMD: formatSpecPrint :: Formattable a => Proxy a -> String
+ Language.Embedded.Imperative.CMD: formatSpecScan :: Formattable a => Proxy a -> String
+ Language.Embedded.Imperative.CMD: instance (GHC.Classes.Eq a, GHC.Arr.Ix i) => GHC.Classes.Eq (Language.Embedded.Imperative.CMD.IArr i a)
+ Language.Embedded.Imperative.CMD: instance (GHC.Show.Show a, GHC.Show.Show i, GHC.Arr.Ix i) => GHC.Show.Show (Language.Embedded.Imperative.CMD.IArr i a)
+ Language.Embedded.Imperative.CMD: instance (Language.Embedded.Backend.C.Expression.CompExp exp, Language.Embedded.Backend.C.Expression.CompTypeClass ct) => Language.Embedded.Imperative.CMD.Arg (Language.Embedded.Imperative.CMD.FunArg exp) ct
+ Language.Embedded.Imperative.CMD: instance (Language.Embedded.Imperative.CMD.ArrCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Imperative.CMD.ArrCMD instr env
+ Language.Embedded.Imperative.CMD: instance (Language.Embedded.Imperative.CMD.C_CMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Imperative.CMD.C_CMD instr env
+ Language.Embedded.Imperative.CMD: instance (Language.Embedded.Imperative.CMD.ControlCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Imperative.CMD.ControlCMD instr env
+ Language.Embedded.Imperative.CMD: instance (Language.Embedded.Imperative.CMD.FileCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Imperative.CMD.FileCMD instr env
+ Language.Embedded.Imperative.CMD: instance (Language.Embedded.Imperative.CMD.RefCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Imperative.CMD.RefCMD instr env
+ Language.Embedded.Imperative.CMD: instance GHC.Classes.Eq (Language.Embedded.Imperative.CMD.Ptr a)
+ Language.Embedded.Imperative.CMD: instance GHC.Show.Show (Language.Embedded.Imperative.CMD.Ptr a)
+ Language.Embedded.Imperative.CMD: instance forall k (pred :: k). Control.Monad.Operational.Higher.InterpBi Language.Embedded.Imperative.CMD.PtrCMD GHC.Types.IO (Data.ALaCarte.Param1 pred)
+ Language.Embedded.Imperative.CMD: instance forall k k1 (instr :: (* -> *, (k -> *, (k1, *))) -> * -> *) env. (Language.Embedded.Imperative.CMD.PtrCMD Data.ALaCarte.:<: instr) => Control.Monad.Operational.Higher.Reexpressible Language.Embedded.Imperative.CMD.PtrCMD instr env
+ Language.Embedded.Imperative.Frontend: constArg :: String -> String -> FunArg exp pred
+ Language.Embedded.Imperative.Frontend: offset :: Integral i => FunArg exp pred -> exp i -> FunArg exp pred
+ Language.Embedded.Imperative.Frontend: type family PrintfExp r :: * -> *;
+ Language.Embedded.Imperative.Frontend: }
+ Language.Embedded.Imperative.Frontend.General: [AddrArg] :: FunArg exp pred -> FunArg exp pred
+ Language.Embedded.Imperative.Frontend.General: [DerefArg] :: FunArg exp pred -> FunArg exp pred
+ Language.Embedded.Imperative.Frontend.General: [FunArg] :: Arg arg pred => arg pred -> FunArg exp pred
+ Language.Embedded.Imperative.Frontend.General: [OffsetArg] :: FunArg exp pred -> exp i -> FunArg exp pred
+ Language.Embedded.Imperative.Frontend.General: [ValArg] :: pred a => exp a -> FunArg exp pred
+ Language.Embedded.Signature: [Empty] :: Ann exp a
+ Language.Embedded.Signature: [Lam] :: pred a => Ann exp a -> (Val a -> Signature exp pred b) -> Signature exp pred (a -> b)
+ Language.Embedded.Signature: [Named] :: String -> Ann exp a
+ Language.Embedded.Signature: [Native] :: (FreePred exp a) => exp len -> Ann exp [a]
+ Language.Embedded.Signature: [Ptr] :: pred a => String -> exp a -> Signature exp pred a
+ Language.Embedded.Signature: [Ret] :: pred a => String -> exp a -> Signature exp pred a
+ Language.Embedded.Traversal: instance forall k (i1 :: (* -> *, k) -> * -> *) (i2 :: (* -> *, k) -> * -> *). (Language.Embedded.Traversal.DryInterp i1, Language.Embedded.Traversal.DryInterp i2) => Language.Embedded.Traversal.DryInterp (i1 Data.ALaCarte.:+: i2)
- Control.Monads: fresh :: MonadSupply m => m Integer
+ Control.Monads: fresh :: (MonadSupply m, m ~ t n, MonadTrans t, MonadSupply n) => m Integer
- Control.Monads: loc :: MonadTick m => m Loc
+ Control.Monads: loc :: (MonadTick m, m ~ t n, MonadTrans t, MonadTick n) => m Loc
- Control.Monads: tick :: MonadTick m => m ()
+ Control.Monads: tick :: (MonadTick m, m ~ t n, MonadTrans t, MonadTick n) => m ()
- Language.C.Monad: CEnv :: Flags -> !Integer -> Map String [Definition] -> Set String -> [Definition] -> [Definition] -> [Definition] -> Map Integer String -> [Param] -> [Exp] -> [InitGroup] -> [Stm] -> [Stm] -> Set Id -> Map String (Set Id) -> CEnv
+ Language.C.Monad: CEnv :: Flags -> !Integer -> Map String [Definition] -> Set String -> [Definition] -> [Definition] -> [Definition] -> Map Integer String -> [Param] -> [Exp] -> [InitGroup] -> [BlockItem] -> [BlockItem] -> Set Id -> Map String (Set Id) -> CEnv
- Language.Embedded.Backend.C.Expression: cLit :: (CType a, MonadC m) => a -> m Exp
+ Language.Embedded.Backend.C.Expression: cLit :: (CType a, ToExp a, MonadC m) => a -> m Exp
- Language.Embedded.Backend.C.Expression: freshVar :: (MonadC m, CType a) => m (Val a)
+ Language.Embedded.Backend.C.Expression: freshVar :: forall m ct proxy a. (MonadC m, CompTypeClass ct, ct a) => proxy ct -> m (Val a)
- Language.Embedded.CExp: castAST :: Typeable b => ASTF T a -> Maybe (ASTF T b)
+ Language.Embedded.CExp: castAST :: forall a b. Typeable b => ASTF T a -> Maybe (ASTF T b)
- Language.Embedded.CExp: compCExp :: MonadC m => CExp a -> m Exp
+ Language.Embedded.CExp: compCExp :: forall m a. MonadC m => CExp a -> m Exp
- Language.Embedded.CExp: constant :: CType a => SupportCode -> String -> a -> CExp a
+ Language.Embedded.CExp: constant :: CType a => String -> a -> CExp a
- Language.Embedded.CExp: isFloat :: CType a => CExp a -> Bool
+ Language.Embedded.CExp: isFloat :: forall a. CType a => CExp a -> Bool
- Language.Embedded.Concurrent: closeChan :: (ChanCMD :<: instr) => Chan Closeable a -> ProgramT instr (Param2 exp pred) m ()
+ Language.Embedded.Concurrent: closeChan :: (ChanCMD :<: instr) => Chan Closeable c -> ProgramT instr (Param2 exp pred) m ()
- Language.Embedded.Concurrent: lastChanReadOK :: (FreeExp exp, VarPred exp Bool, ChanCMD :<: instr, Monad m) => Chan Closeable a -> ProgramT instr (Param2 exp pred) m (exp Bool)
+ Language.Embedded.Concurrent: lastChanReadOK :: (FreeExp exp, FreePred exp Bool, ChanCMD :<: instr, Monad m) => Chan Closeable c -> ProgramT instr (Param2 exp pred) m (exp Bool)
- Language.Embedded.Concurrent: newChan :: (pred a, ChanCMD :<: instr) => exp ChanBound -> ProgramT instr (Param2 exp pred) m (Chan Uncloseable a)
+ Language.Embedded.Concurrent: newChan :: forall a i exp pred instr m. (pred a, Integral i, ChanCMD :<: instr) => exp i -> ProgramT instr (Param2 exp pred) m (Chan Uncloseable a)
- Language.Embedded.Concurrent: newCloseableChan :: (pred a, ChanCMD :<: instr) => exp ChanBound -> ProgramT instr (Param2 exp pred) m (Chan Closeable a)
+ Language.Embedded.Concurrent: newCloseableChan :: forall a i exp pred instr m. (pred a, Integral i, ChanCMD :<: instr) => exp i -> ProgramT instr (Param2 exp pred) m (Chan Closeable a)
- Language.Embedded.Concurrent: readChan :: (pred a, FreeExp exp, VarPred exp a, ChanCMD :<: instr, Monad m) => Chan t a -> ProgramT instr (Param2 exp pred) m (exp a)
+ Language.Embedded.Concurrent: readChan :: (Typeable a, pred a, FreeExp exp, FreePred exp a, ChanCMD :<: instr, Monad m) => Chan t a -> ProgramT instr (Param2 exp pred) m (exp a)
- Language.Embedded.Concurrent: writeChan :: (pred a, FreeExp exp, VarPred exp Bool, ChanCMD :<: instr, Monad m) => Chan t a -> exp a -> ProgramT instr (Param2 exp pred) m (exp Bool)
+ Language.Embedded.Concurrent: writeChan :: (Typeable a, pred a, FreeExp exp, FreePred exp Bool, ChanCMD :<: instr, Monad m) => Chan t a -> exp a -> ProgramT instr (Param2 exp pred) m (exp Bool)
- Language.Embedded.Expression: class FreeExp exp where type family VarPred exp :: * -> Constraint
+ Language.Embedded.Expression: class FreeExp exp where type FreePred exp :: * -> Constraint where {
- Language.Embedded.Expression: valToExp :: (VarPred exp a, FreeExp exp) => Val a -> exp a
+ Language.Embedded.Expression: valToExp :: (FreeExp exp, FreePred exp a) => Val a -> exp a
- Language.Embedded.Expression: varExp :: (FreeExp exp, VarPred exp a) => VarId -> exp a
+ Language.Embedded.Expression: varExp :: (FreeExp exp, FreePred exp a) => VarId -> exp a
- Language.Embedded.Imperative: class (:<:) (sub :: k -> k1 -> *) (sup :: k -> k1 -> *)
+ Language.Embedded.Imperative: class (:<:) k k1 (sub :: k1 -> k -> *) (sup :: k1 -> k -> *)
- Language.Embedded.Imperative: class FreeExp exp where type family VarPred exp :: * -> Constraint
+ Language.Embedded.Imperative: class FreeExp exp where type FreePred exp :: * -> Constraint where {
- Language.Embedded.Imperative: data (:+:) (h1 :: k -> k1 -> *) (h2 :: k -> k1 -> *) (fs :: k) (a :: k1) :: (k -> k1 -> *) -> (k -> k1 -> *) -> k -> k1 -> *
+ Language.Embedded.Imperative: data (:+:) k k1 (h1 :: k1 -> k -> *) (h2 :: k1 -> k -> *) (fs :: k1) (a :: k) :: forall k k1. (k1 -> k -> *) -> (k1 -> k -> *) -> k1 -> k -> *
- Language.Embedded.Imperative: data ProgramT (instr :: (,) (* -> *) k -> * -> *) (fs :: k) (m :: * -> *) a :: ((,) (* -> *) k -> * -> *) -> k -> (* -> *) -> * -> *
+ Language.Embedded.Imperative: data ProgramT k (instr :: (* -> *, k) -> * -> *) (fs :: k) (m :: * -> *) a :: forall k. ((* -> *, k) -> * -> *) -> k -> (* -> *) -> * -> *
- Language.Embedded.Imperative: interpret :: (Interp k * i m fs, HFunctor * * k i, Monad m) => Program k i fs a -> m a
+ Language.Embedded.Imperative: interpret :: (Interp * k i m fs, HFunctor * * k i, Monad m) => Program k i fs a -> m a
- Language.Embedded.Imperative: interpretBi :: (InterpBi k * i m fs, HBifunctor * * k i, Functor m, Monad m) => (forall b. exp b -> m b) -> Program ((,) (* -> *) k) i ((,) (* -> *) k exp fs) a -> m a
+ Language.Embedded.Imperative: interpretBi :: (InterpBi * k i m fs, HBifunctor * * k i, Functor m, Monad m) => (forall b. exp b -> m b) -> Program (* -> *, k) i ((,) (* -> *) k exp fs) a -> m a
- Language.Embedded.Imperative: interpretBiT :: (InterpBi k * i m fs, HBifunctor * * k i, Functor m, Monad m, Monad n) => (forall b. exp b -> m b) -> (forall b. n b -> m b) -> ProgramT ((,) (* -> *) k) i ((,) (* -> *) k exp fs) n a -> m a
+ Language.Embedded.Imperative: interpretBiT :: (InterpBi * k i m fs, HBifunctor * * k i, Functor m, Monad m, Monad n) => (forall b. exp b -> m b) -> (forall b. n b -> m b) -> ProgramT (* -> *, k) i ((,) (* -> *) k exp fs) n a -> m a
- Language.Embedded.Imperative: interpretT :: (Interp k * i m fs, HFunctor * * k i, Monad m) => (forall b. n b -> m b) -> ProgramT k i fs n a -> m a
+ Language.Embedded.Imperative: interpretT :: (Interp * k i m fs, HFunctor * * k i, Monad m) => (forall b. n b -> m b) -> ProgramT k i fs n a -> m a
- Language.Embedded.Imperative: type Param1 (a :: k) = (,) k * a Param0
+ Language.Embedded.Imperative: type Param1 k (a :: k) = (,) k * a Param0
- Language.Embedded.Imperative: type Param2 (a :: k) (b :: k1) = (,) k ((,) k1 *) a (Param1 k1 b)
+ Language.Embedded.Imperative: type Param2 k k1 (a :: k1) (b :: k) = (,) k1 (k, *) a (Param1 k b)
- Language.Embedded.Imperative: type Param3 (a :: k) (b :: k1) (c :: k2) = (,) k ((,) k1 ((,) k2 *)) a (Param2 k1 k2 b c)
+ Language.Embedded.Imperative: type Param3 k k1 k2 (a :: k2) (b :: k1) (c :: k) = (,) k2 (k1, (k, *)) a (Param2 k k1 b c)
- Language.Embedded.Imperative: type Program (instr :: (,) (* -> *) k -> * -> *) (fs :: k) = ProgramT k instr fs Identity
+ Language.Embedded.Imperative: type Program k (instr :: (* -> *, k) -> * -> *) (fs :: k) = ProgramT k instr fs Identity
- Language.Embedded.Imperative.CMD: class (Typeable a, Read a, PrintfArg a) => Formattable a
+ Language.Embedded.Imperative.CMD: class (Typeable a, Read a, PrintfArg a) => Formattable a where formatSpecScan = formatSpecPrint
- Language.Embedded.Imperative.Frontend: callFun :: (pred a, FreeExp exp, VarPred exp a, C_CMD :<: instr, Monad m) => String -> [FunArg exp pred] -> ProgramT instr (Param2 exp pred) m (exp a)
+ Language.Embedded.Imperative.Frontend: callFun :: (pred a, FreeExp exp, FreePred exp a, C_CMD :<: instr, Monad m) => String -> [FunArg exp pred] -> ProgramT instr (Param2 exp pred) m (exp a)
- Language.Embedded.Imperative.Frontend: class PrintfType r where type family PrintfExp r :: * -> *
+ Language.Embedded.Imperative.Frontend: class PrintfType r where type PrintfExp r :: * -> * where {
- Language.Embedded.Imperative.Frontend: copyArr :: (pred a, Integral i, Ix i, ArrCMD :<: instr) => Arr i a -> Arr i a -> exp i -> ProgramT instr (Param2 exp pred) m ()
+ Language.Embedded.Imperative.Frontend: copyArr :: (pred a, Integral i, Ix i, ArrCMD :<: instr) => (Arr i a, exp i) -> (Arr i a, exp i) -> exp i -> ProgramT instr (Param2 exp pred) m ()
- Language.Embedded.Imperative.Frontend: externFun :: (pred res, FreeExp exp, VarPred exp res, C_CMD :<: instr, Monad m) => String -> [FunArg exp pred] -> ProgramT instr (Param2 exp pred) m (exp res)
+ Language.Embedded.Imperative.Frontend: externFun :: forall instr m exp pred res. (pred res, FreeExp exp, FreePred exp res, C_CMD :<: instr, Monad m) => String -> [FunArg exp pred] -> ProgramT instr (Param2 exp pred) m (exp res)
- Language.Embedded.Imperative.Frontend: feof :: (FreeExp exp, VarPred exp Bool, FileCMD :<: instr, Monad m) => Handle -> ProgramT instr (Param2 exp pred) m (exp Bool)
+ Language.Embedded.Imperative.Frontend: feof :: (FreeExp exp, FreePred exp Bool, FileCMD :<: instr, Monad m) => Handle -> ProgramT instr (Param2 exp pred) m (exp Bool)
- Language.Embedded.Imperative.Frontend: fget :: (Formattable a, pred a, FreeExp exp, VarPred exp a, FileCMD :<: instr, Monad m) => Handle -> ProgramT instr (Param2 exp pred) m (exp a)
+ Language.Embedded.Imperative.Frontend: fget :: (Formattable a, pred a, FreeExp exp, FreePred exp a, FileCMD :<: instr, Monad m) => Handle -> ProgramT instr (Param2 exp pred) m (exp a)
- Language.Embedded.Imperative.Frontend: for :: (FreeExp exp, ControlCMD :<: instr, Integral n, pred n, VarPred exp n) => IxRange (exp n) -> (exp n -> ProgramT instr (Param2 exp pred) m ()) -> ProgramT instr (Param2 exp pred) m ()
+ Language.Embedded.Imperative.Frontend: for :: (FreeExp exp, ControlCMD :<: instr, Integral n, pred n, FreePred exp n) => IxRange (exp n) -> (exp n -> ProgramT instr (Param2 exp pred) m ()) -> ProgramT instr (Param2 exp pred) m ()
- Language.Embedded.Imperative.Frontend: fput :: (Formattable a, VarPred exp a, FileCMD :<: instr) => Handle -> String -> exp a -> String -> ProgramT instr (Param2 exp pred) m ()
+ Language.Embedded.Imperative.Frontend: fput :: forall instr exp pred a m. (Formattable a, FreePred exp a, FileCMD :<: instr) => Handle -> String -> exp a -> String -> ProgramT instr (Param2 exp pred) m ()
- Language.Embedded.Imperative.Frontend: freezeArr :: (pred a, Integral i, Ix i, ArrCMD :<: instr, Monad m) => Arr i a -> exp i -> ProgramT instr (Param2 exp pred) m (IArr i a)
+ Language.Embedded.Imperative.Frontend: freezeArr :: (pred a, Integral i, Ix i, Num (exp i), ArrCMD :<: instr, Monad m) => Arr i a -> exp i -> ProgramT instr (Param2 exp pred) m (IArr i a)
- Language.Embedded.Imperative.Frontend: getArr :: (pred a, FreeExp exp, VarPred exp a, Integral i, Ix i, ArrCMD :<: instr, Monad m) => exp i -> Arr i a -> ProgramT instr (Param2 exp pred) m (exp a)
+ Language.Embedded.Imperative.Frontend: getArr :: (pred a, FreeExp exp, FreePred exp a, Integral i, Ix i, ArrCMD :<: instr, Monad m) => exp i -> Arr i a -> ProgramT instr (Param2 exp pred) m (exp a)
- Language.Embedded.Imperative.Frontend: getRef :: (pred a, FreeExp exp, VarPred exp a, RefCMD :<: instr, Monad m) => Ref a -> ProgramT instr (Param2 exp pred) m (exp a)
+ Language.Embedded.Imperative.Frontend: getRef :: (pred a, FreeExp exp, FreePred exp a, RefCMD :<: instr, Monad m) => Ref a -> ProgramT instr (Param2 exp pred) m (exp a)
- Language.Embedded.Imperative.Frontend: getTime :: (pred Double, FreeExp exp, VarPred exp Double, C_CMD :<: instr, Monad m) => ProgramT instr (Param2 exp pred) m (exp Double)
+ Language.Embedded.Imperative.Frontend: getTime :: (pred Double, FreeExp exp, FreePred exp Double, C_CMD :<: instr, Monad m) => ProgramT instr (Param2 exp pred) m (exp Double)
- Language.Embedded.Imperative.Frontend: ifE :: (pred a, FreeExp exp, VarPred exp a, ControlCMD :<: instr, RefCMD :<: instr, Monad m) => exp Bool -> ProgramT instr (Param2 exp pred) m (exp a) -> ProgramT instr (Param2 exp pred) m (exp a) -> ProgramT instr (Param2 exp pred) m (exp a)
+ Language.Embedded.Imperative.Frontend: ifE :: (pred a, FreeExp exp, FreePred exp a, ControlCMD :<: instr, RefCMD :<: instr, Monad m) => exp Bool -> ProgramT instr (Param2 exp pred) m (exp a) -> ProgramT instr (Param2 exp pred) m (exp a) -> ProgramT instr (Param2 exp pred) m (exp a)
- Language.Embedded.Imperative.Frontend: modifyRef :: (pred a, FreeExp exp, VarPred exp a, RefCMD :<: instr, Monad m) => Ref a -> (exp a -> exp a) -> ProgramT instr (Param2 exp pred) m ()
+ Language.Embedded.Imperative.Frontend: modifyRef :: (pred a, FreeExp exp, FreePred exp a, RefCMD :<: instr, Monad m) => Ref a -> (exp a -> exp a) -> ProgramT instr (Param2 exp pred) m ()
- Language.Embedded.Imperative.Frontend: thawArr :: (pred a, Integral i, Ix i, ArrCMD :<: instr, Monad m) => IArr i a -> exp i -> ProgramT instr (Param2 exp pred) m (Arr i a)
+ Language.Embedded.Imperative.Frontend: thawArr :: (pred a, Integral i, Ix i, Num (exp i), ArrCMD :<: instr, Monad m) => IArr i a -> exp i -> ProgramT instr (Param2 exp pred) m (Arr i a)
- Language.Embedded.Imperative.Frontend: unsafeFreezeRef :: (pred a, FreeExp exp, VarPred exp a, RefCMD :<: instr, Monad m) => Ref a -> ProgramT instr (Param2 exp pred) m (exp a)
+ Language.Embedded.Imperative.Frontend: unsafeFreezeRef :: (pred a, FreeExp exp, FreePred exp a, RefCMD :<: instr, Monad m) => Ref a -> ProgramT instr (Param2 exp pred) m (exp a)
- Language.Embedded.Imperative.Frontend: veryUnsafeFreezeRef :: (FreeExp exp, VarPred exp a) => Ref a -> exp a
+ Language.Embedded.Imperative.Frontend: veryUnsafeFreezeRef :: (FreeExp exp, FreePred exp a) => Ref a -> exp a
- Language.Embedded.Imperative.Frontend.General: class (Typeable a, Read a, PrintfArg a) => Formattable a
+ Language.Embedded.Imperative.Frontend.General: class (Typeable a, Read a, PrintfArg a) => Formattable a where formatSpecScan = formatSpecPrint
- Language.Embedded.Signature: arg :: (pred a, FreeExp exp, VarPred exp a) => Ann exp a -> (exp a -> exp b) -> (exp b -> Signature exp pred c) -> Signature exp pred (a -> c)
+ Language.Embedded.Signature: arg :: (pred a, FreeExp exp, FreePred exp a) => Ann exp a -> (exp a -> exp b) -> (exp b -> Signature exp pred c) -> Signature exp pred (a -> c)
- Language.Embedded.Signature: lam :: (pred a, FreeExp exp, VarPred exp a) => (exp a -> Signature exp pred b) -> Signature exp pred (a -> b)
+ Language.Embedded.Signature: lam :: (pred a, FreeExp exp, FreePred exp a) => (exp a -> Signature exp pred b) -> Signature exp pred (a -> b)
- Language.Embedded.Signature: name :: (pred a, FreeExp exp, VarPred exp a) => String -> (exp a -> Signature exp pred b) -> Signature exp pred (a -> b)
+ Language.Embedded.Signature: name :: (pred a, FreeExp exp, FreePred exp a) => String -> (exp a -> Signature exp pred b) -> Signature exp pred (a -> b)
- Language.Embedded.Signature: translateFunction :: (MonadC m, CompExp exp) => Signature exp CType a -> m ()
+ Language.Embedded.Signature: translateFunction :: forall m exp a. (MonadC m, CompExp exp) => Signature exp CType a -> m ()
Files
- LICENSE +4/−2
- examples/C.hs +0/−35
- examples/Concurrent.hs +46/−9
- imperative-edsl.cabal +16/−18
- src/Control/Chan.hs +70/−0
- src/Language/C/Monad.hs +74/−81
- src/Language/Embedded/Backend/C.hs +80/−64
- src/Language/Embedded/Backend/C/Expression.hs +21/−43
- src/Language/Embedded/CExp.hs +41/−79
- src/Language/Embedded/Concurrent.hs +152/−38
- src/Language/Embedded/Concurrent/Backend/C.hs +51/−19
- src/Language/Embedded/Concurrent/CMD.hs +153/−65
- src/Language/Embedded/Expression.hs +16/−11
- src/Language/Embedded/Imperative.hs +1/−1
- src/Language/Embedded/Imperative/Args.hs +18/−10
- src/Language/Embedded/Imperative/Backend/C.hs +93/−65
- src/Language/Embedded/Imperative/CMD.hs +138/−87
- src/Language/Embedded/Imperative/Frontend.hs +43/−30
- src/Language/Embedded/Imperative/Frontend/General.hs +1/−1
- src/Language/Embedded/Signature.hs +5/−5
- tests/CExp.hs +0/−4
- tests/Imperative.hs +134/−39
LICENSE view
@@ -1,4 +1,6 @@-Copyright (c) 2015-2016, Anders Persson, Emil Axelsson, Markus Aronsson+Copyright (c) 2016 Emil Axelsson, Anton Ekblad, Máté Karácsony+Copyright (c) 2015 Anders Persson, Anton Ekblad, Emil Axelsson,+ Markus Aronsson, Josef Svenningsson All rights reserved. @@ -13,7 +15,7 @@ disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Anders Persson, Emil Axelsson, Markus Aronsson nor the names of other+ * Neither the names of the copyright holders nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission.
− examples/C.hs
@@ -1,35 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE TypeOperators #-}--module C where--import Prelude hiding (break)--import Language.C.Quote.C-import Language.Embedded.Imperative-import Language.Embedded.Concurrent-import Language.Embedded.Backend.C-import Language.Embedded.CExp--type L =- C_CMD CExp :+:- FileCMD CExp---- | Define a function in another module and call it.-multiModule :: Program L ()-multiModule = do- addInclude "<stdlib.h>"- addExternProc "func_in_other" []- inModule "other" $ do- addDefinition [cedecl|- void func_in_other(void) {- puts("Hello from the other module!");- } |]- addInclude "<stdio.h>"- callProc "func_in_other" []--------------------------------------------testAll = do- icompileAll multiModule
examples/Concurrent.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeOperators #-} module Concurrent where@@ -18,14 +19,15 @@ ThreadCMD :+: ChanCMD :+: ControlCMD :+:- FileCMD+ FileCMD :+:+ ArrCMD type Prog = Program CMD (Param2 CExp CType) -- | Deadlocks due to channel becoming full. deadlock :: Prog () deadlock = do- c <- newChan 1+ c <- newChan (1 :: CExp Word32) t <- fork $ readChan c >>= printf "%d\n" writeChan c (1 :: CExp Int32) writeChan c 2@@ -36,8 +38,8 @@ -- happen in separate threads. mapFile :: (CExp Float -> CExp Float) -> FilePath -> Prog () mapFile f i = do- c1 <- newCloseableChan 5- c2 <- newCloseableChan 5+ c1 <- newCloseableChan (5 :: CExp Word32)+ c2 <- newCloseableChan (5 :: CExp Word32) fi <- fopen i ReadMode t1 <- fork $ do@@ -49,12 +51,20 @@ (closeChan c2 >> break) t2 <- fork $ do- while (lastChanReadOK c2) $ do- readChan c2 >>= printf "%f\n"+ while (return true) $ do+ x <- readChan c2+ readOK <- lastChanReadOK c2+ iff readOK+ (printf "%f\n" x)+ (break) t3 <- fork $ do while (not_ <$> feof fi) $ do- fget fi >>= void . writeChan c1+ x <- fget fi+ eof <- feof fi+ iff eof+ (break)+ (void $ writeChan c1 x) fclose fi closeChan c1 waitThread t2@@ -77,13 +87,40 @@ printf "The thread is dead, long live the thread! %d\n" (0 :: CExp Int32) +-- | Primitive channel operations.+chanOps :: Prog ()+chanOps = do+ c <- newCloseableChan (2 :: CExp Word32)+ writeChan c (1337 :: CExp Int32)+ writeChan c 42+ a <- readChan c+ b <- readChan c+ printf "%d %d\n" a b + sent :: Arr Int8 Int32 <- initArr [ 12, 34 ]+ writeChanBuf c (0 :: CExp Int8) 2 sent+ received <- newArr (2 :: CExp Int8)+ readChanBuf c (0 :: CExp Int8) 2 received+ a <- getArr 0 received+ b <- getArr 1 received+ printf "%d %d\n" a b++ writeChan' c (67 :: CExp Word8)+ r :: CExp Word8 <- readChan' c+ printf "%d\n" r+ closeChan c+++ ---------------------------------------- testAll = do tag "waiting" >> compareCompiled' opts waiting (runIO waiting) "" tag "suicide" >> compareCompiled' opts suicide (runIO suicide) ""+ tag "chanOps" >> compareCompiled' opts chanOps (runIO chanOps) "" where tag str = putStrLn $ "---------------- examples/Concurrent.hs/" ++ str ++ "\n"- opts = defaultExtCompilerOpts {externalFlagsPost = ["-lpthread"]}-+ opts = def+ { externalFlagsPre = ["-Iinclude", "csrc/chan.c"]+ , externalFlagsPost = ["-lpthread"]+ }
imperative-edsl.cabal view
@@ -1,5 +1,5 @@ name: imperative-edsl-version: 0.5+version: 0.6 synopsis: Deep embedding of imperative programs with code generation description: Deep embedding of imperative programs with code generation. .@@ -13,7 +13,9 @@ license-file: LICENSE author: Anders Persson, Emil Axelsson, Markus Aronsson maintainer: emax@chalmers.se-copyright: Copyright (c) 2015-2016, Anders Persson, Emil Axelsson, Markus Aronsson+copyright: Copyright (c) 2016 Anton Ekblad, Emil Axelsson, Máté Karácsony+ Copyright (c) 2015 Anders Persson, Anton Ekblad, Emil Axelsson,+ Markus Aronsson, Josef Svenningsson homepage: https://github.com/emilaxelsson/imperative-edsl bug-reports: https://github.com/emilaxelsson/imperative-edsl/issues category: Language@@ -28,10 +30,6 @@ type: git location: git@github.com:emilaxelsson/imperative-edsl.git -Flag old-syntactic- Description: Use syntactic < 2- Default: False- library exposed-modules: Control.Monads@@ -55,6 +53,7 @@ Language.Embedded.Imperative.Backend.C Language.Embedded.Concurrent.Backend.C -- No need to export these since only the instances are interesting+ Control.Chan default-language: Haskell2010 @@ -90,29 +89,24 @@ array, base >=4 && <5, containers,+ data-default-class, deepseq, directory, exception-transformers, ghc-prim,- language-c-quote >= 0.11 && < 0.12,+ language-c-quote >= 0.11.5 && < 0.12, mainland-pretty >= 0.4 && < 0.5, microlens >= 0.3.0.0,- microlens-mtl,+ microlens-mtl >= 0.1.8, microlens-th, mtl, process,- operational-alacarte >= 0.2,+ operational-alacarte >= 0.3, BoundedChan, srcloc,- time >= 1.5.0.1-- if flag(old-syntactic)- build-depends:- syntactic < 2- else- build-depends:- open-typerep >= 0.4,- syntactic >= 3.2+ syntactic >= 3.2,+ time >= 1.5.0.1,+ stm >= 2.4 && < 2.5 hs-source-dirs: src @@ -127,7 +121,11 @@ build-depends: base,+ directory,+ filepath, imperative-edsl,+ process,+ random, syntactic, tasty-quickcheck, tasty-th
+ src/Control/Chan.hs view
@@ -0,0 +1,70 @@+-- | Multi-element channels, for the Haskell interpretation of+-- 'Language.Embedded.Concurrent'.+module Control.Chan where+import Control.Concurrent.STM++data ChanState = Open | Closed+ deriving Eq++newtype Chan a = Chan {unChan :: TVar (ChanGuts a)}++data ChanGuts a = ChanGuts+ { chanBuf :: [a]+ , chanBufLen :: Int+ , chanBound :: Int+ , chanState :: ChanState+ , chanLastReadOK :: Bool+ }++newChan :: Int -> IO (Chan a)+newChan len = fmap Chan . atomically . newTVar $ ChanGuts+ { chanBuf = []+ , chanBufLen = 0+ , chanBound = len+ , chanState = Open+ , chanLastReadOK = True+ }++readChan :: Chan a -> Int -> IO [a]+readChan (Chan chan) len = atomically $ do+ ch <- readTVar chan+ case chanState ch of+ Open -> do+ check (chanBufLen ch >= len)+ readAndUpdate ch True+ Closed+ | chanBufLen ch < len -> do+ return []+ | otherwise -> do+ readAndUpdate ch False+ where+ readAndUpdate ch success = do+ let (out, rest) = splitAt len (chanBuf ch)+ writeTVar chan $ ch+ { chanBuf = rest+ , chanBufLen = chanBufLen ch - len+ , chanLastReadOK = success+ }+ return out++writeChan :: Chan a -> [a] -> IO Bool+writeChan (Chan chan) xs = atomically $ do+ let len = length xs+ ch <- readTVar chan+ case chanState ch of+ Open -> do+ check (chanBound ch - chanBufLen ch >= len)+ writeTVar chan $ ch+ { chanBuf = chanBuf ch ++ xs+ , chanBufLen = chanBufLen ch + len+ }+ return True+ Closed -> do+ return False++closeChan :: Chan a -> IO ()+closeChan (Chan chan) = atomically $ do+ modifyTVar chan (\c -> c {chanState = Closed})++lastReadOK :: Chan a -> IO Bool+lastReadOK = fmap chanLastReadOK . atomically . readTVar . unChan
src/Language/C/Monad.hs view
@@ -1,52 +1,4 @@--- Copyright (c) 2009-2010--- The President and Fellows of Harvard College.------ Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions--- are met:--- 1. Redistributions of source code must retain the above copyright--- notice, this list of conditions and the following disclaimer.--- 2. Redistributions in binary form must reproduce the above copyright--- notice, this list of conditions and the following disclaimer in the--- documentation and/or other materials provided with the distribution.--- 3. Neither the name of the University nor the names of its contributors--- may be used to endorse or promote products derived from this software--- without specific prior written permission.------ THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND--- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE--- ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE--- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL--- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS--- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)--- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT--- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY--- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF--- SUCH DAMAGE.---- Copyright (c) 2011-2012, Geoffrey Mainland--- All rights reserved.------ Redistribution and use in source and binary forms, with or without modification,--- are permitted provided that the following conditions are met:--- 1. Redistributions of source code must retain the above copyright notice, this--- list of conditions and the following disclaimer.------ 2. Redistributions in binary form must reproduce the above copyright notice,--- this list of conditions and the following disclaimer in the documentation--- and/or other materials provided with the distribution.------ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND--- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED--- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE--- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR--- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES--- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;--- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON--- ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT--- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS--- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+-- Copyright (c) 2016 and after, see package copyright -- Copyright (c) 2015, Anders Persson --@@ -79,6 +31,56 @@ -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- Copyright (c) 2011-2012, Geoffrey Mainland+-- All rights reserved.+--+-- Redistribution and use in source and binary forms, with or without modification,+-- are permitted provided that the following conditions are met:+-- 1. Redistributions of source code must retain the above copyright notice, this+-- list of conditions and the following disclaimer.+--+-- 2. Redistributions in binary form must reproduce the above copyright notice,+-- this list of conditions and the following disclaimer in the documentation+-- and/or other materials provided with the distribution.+--+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND+-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+-- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR+-- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON+-- ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.++-- Copyright (c) 2009-2010+-- The President and Fellows of Harvard College.+--+-- Redistribution and use in source and binary forms, with or without+-- modification, are permitted provided that the following conditions+-- are met:+-- 1. Redistributions of source code must retain the above copyright+-- notice, this list of conditions and the following disclaimer.+-- 2. Redistributions in binary form must reproduce the above copyright+-- notice, this list of conditions and the following disclaimer in the+-- documentation and/or other materials provided with the distribution.+-- 3. Neither the name of the University nor the names of its contributors+-- may be used to endorse or promote products derived from this software+-- without specific prior written permission.+--+-- THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND+-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+-- ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE+-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+-- SUCH DAMAGE.+ {-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE QuasiQuotes #-}@@ -92,7 +94,6 @@ module Language.C.Monad where -import Lens.Micro import Lens.Micro.Mtl import Lens.Micro.TH #if __GLASGOW_HASKELL__ < 710@@ -130,8 +131,8 @@ , _params :: [C.Param] , _args :: [C.Exp] , _locals :: [C.InitGroup]- , _stms :: [C.Stm]- , _finalStms :: [C.Stm]+ , _items :: [C.BlockItem]+ , _finalItems :: [C.BlockItem] , _usedVars :: Set.Set C.Id , _funUsedVars :: Map.Map String (Set.Set C.Id)@@ -139,22 +140,6 @@ makeLenses ''CEnv --- | Reimplementation of @<<%=@ from the lens package-(<<%=) :: MonadState s m =>- (forall f . Functor f => LensLike' f s a) -> (a -> a) -> m a-l <<%= f = do- s <- get- l %= f- return (s ^. l)---- | Reimplementation of @<<.=@ from the lens package-(<<.=) :: MonadState s m =>- (forall f . Functor f => LensLike' f s a) -> a -> m a-l <<.= f = do- s <- get- l .= f- return (s ^. l)- -- | Default code generator state defaultCEnv :: Flags -> CEnv defaultCEnv fl = CEnv@@ -169,8 +154,8 @@ , _params = mempty , _args = mempty , _locals = mempty- , _stms = mempty- , _finalStms = mempty+ , _items = mempty+ , _finalItems = mempty , _usedVars = mempty , _funUsedVars = mempty }@@ -295,21 +280,29 @@ C.InitGroup _ _ is _ -> forM_ is $ \(C.Init id _ _ _ _ _) -> touchVar id _ -> return () +-- | Add an item (a declaration or a statement) to the current block+-- This functionality is necessary to declare C99 variable-length arrays+-- in the middle of a block, as other local delcarations are lifted to the+-- beginning of the block, and that makes the evaluation of the length+-- expression impossible.+addItem :: MonadC m => C.BlockItem -> m ()+addItem item = items %= (item:)+ -- | Add multiple local declarations addLocals :: MonadC m => [C.InitGroup] -> m () addLocals defs = mapM_ addLocal defs -- locals %= (reverse defs++) -- | Add a statement to the current block addStm :: MonadC m => C.Stm -> m ()-addStm stm = stms %= (stm:)+addStm stm = items %= ((C.BlockStm stm):) -- | Add a sequence of statements to the current block addStms :: MonadC m => [C.Stm] -> m ()-addStms ss = stms %= (reverse ss++)+addStms ss = items %= (reverse (map C.BlockStm ss)++) -- | Add a statement to the end of the current block addFinalStm :: MonadC m => C.Stm -> m ()-addFinalStm stm = finalStms %= (stm:)+addFinalStm stm = finalItems %= ((C.BlockStm stm):) -- | Run an action in a new block inBlock :: MonadC m => m a -> m a@@ -322,16 +315,16 @@ -- Does not place the items in an actual C block. inNewBlock :: MonadC m => m a -> m (a, [C.BlockItem]) inNewBlock ma = do- oldLocals <- locals <<.= mempty- oldStms <- stms <<.= mempty- oldFinalStms <- finalStms <<.= mempty+ oldLocals <- locals <<.= mempty+ oldItems <- items <<.= mempty+ oldFinalItems <- finalItems <<.= mempty x <- ma- ls <- reverse <$> (locals <<.= oldLocals)- ss <- reverse <$> (stms <<.= oldStms)- fss <- reverse <$> (finalStms <<.= oldFinalStms)+ ls <- reverse <$> (locals <<.= oldLocals)+ ss <- reverse <$> (items <<.= oldItems)+ fss <- reverse <$> (finalItems <<.= oldFinalItems) return (x, map C.BlockDecl ls ++- map C.BlockStm ss ++- map C.BlockStm fss+ ss +++ fss ) -- | Run an action as a block and capture the items.
src/Language/Embedded/Backend/C.hs view
@@ -6,6 +6,7 @@ module Language.Embedded.Backend.C ( module Language.Embedded.Backend.C.Expression , module Language.Embedded.Backend.C+ , Default (..) ) where @@ -19,8 +20,9 @@ import System.Directory (getTemporaryDirectory, removeFile) import System.Exit (ExitCode (..)) import System.IO-import System.Process (system)+import System.Process (system, readProcess) +import Data.Default.Class import Data.Loc (noLoc) import qualified Language.C.Syntax as C import Text.PrettyPrint.Mainland (pretty)@@ -62,41 +64,37 @@ -- * Code generation user interface -------------------------------------------------------------------------------- --- | Compile a program to C code represented as a string------ This function returns only the first (main) module.--- To get every C translation units, use `compileAll`.+-- | Compile a program to C code represented as a string. To compile the+-- resulting C code, use something like ----- For programs that make use of the primitives in--- "Language.Embedded.Concurrent", the resulting C code can be compiled as--- follows:+-- > cc -std=c99 YOURPROGRAM.c ----- > gcc -Iinclude csrc/chan.c -lpthread YOURPROGRAM.c+-- This function returns only the first (main) module. To get all C translation+-- unit, use 'compileAll'. compile :: (Interp instr CGen (Param2 exp pred), HFunctor instr) => Program instr (Param2 exp pred) a -> String compile = snd . head . compileAll +-- | Compile a program to C modules, each one represented as a pair of a name+-- and the code represented as a string. To compile the resulting C code, use+-- something like+--+-- > cc -std=c99 YOURPROGRAM.c compileAll :: (Interp instr CGen (Param2 exp pred), HFunctor instr) => Program instr (Param2 exp pred) a -> [(String, String)]-compileAll = map (("", pretty 80) <*>) . prettyCGen . liftSharedLocals . wrapMain . interpret+compileAll+ = map (("", pretty 80) <*>) . prettyCGen . liftSharedLocals+ . wrapMain . interpret --- | Compile a program to C code and print it on the screen------ This function returns only the first (main) module.--- To get every C translation units, use `icompileAll`.------ For programs that make use of the primitives in--- "Language.Embedded.Concurrent", the resulting C code can be compiled as--- follows:+-- | Compile a program to C code and print it on the screen. To compile the+-- resulting C code, use something like ----- > gcc -Iinclude csrc/chan.c -lpthread YOURPROGRAM.c+-- > cc -std=c99 YOURPROGRAM.c icompile :: (Interp instr CGen (Param2 exp pred), HFunctor instr) => Program instr (Param2 exp pred) a -> IO ()-icompile = putStrLn . compile--icompileAll :: (Interp instr CGen (Param2 exp pred), HFunctor instr) =>- Program instr (Param2 exp pred) a -> IO ()-icompileAll = mapM_ (\(n, m) -> putStrLn ("// module " ++ n) >> putStrLn m) . compileAll+icompile prog = case compileAll prog of+ [m] -> putStrLn $ snd m+ ms -> mapM_ (\(n, m) -> putStrLn ("// module " ++ n) >> putStrLn m) ms removeFileIfPossible :: FilePath -> IO () removeFileIfPossible file =@@ -109,29 +107,20 @@ , externalSilent :: Bool -- ^ Don't print anything besides what the program prints } -defaultExtCompilerOpts :: ExternalCompilerOpts-defaultExtCompilerOpts = ExternalCompilerOpts- { externalKeepFiles = False- , externalFlagsPre = []- , externalFlagsPost = []- , externalSilent = False- }--instance Monoid ExternalCompilerOpts+instance Default ExternalCompilerOpts where- mempty = defaultExtCompilerOpts- mappend- (ExternalCompilerOpts keep1 pre1 post1 silent1)- (ExternalCompilerOpts keep2 pre2 post2 silent2) =- ExternalCompilerOpts keep2 (pre1 ++ pre2) (post1 ++ post2) silent2+ def = ExternalCompilerOpts+ { externalKeepFiles = False+ , externalFlagsPre = []+ , externalFlagsPost = []+ , externalSilent = False+ } maybePutStrLn :: Bool -> String -> IO () maybePutStrLn False str = putStrLn str maybePutStrLn _ _ = return () --- TODO: it would be nice to have a version that compiles all modules of a program,--- as it currently compiles only the first (main) module.--- | Generate C code and use GCC to compile it+-- | Generate C code and use CC to compile it compileC :: (Interp instr CGen (Param2 exp pred), HFunctor instr) => ExternalCompilerOpts -> Program instr (Param2 exp pred) a -- ^ Program to compile@@ -146,7 +135,7 @@ when externalKeepFiles $ maybePutStrLn externalSilent $ "Created temporary file: " ++ cFile let compileCMD = unwords- $ ["gcc", "-std=c99"]+ $ ["cc", "-std=c99"] ++ externalFlagsPre ++ [cFile, "-o", exeFile] ++ externalFlagsPost@@ -160,7 +149,7 @@ where format = if externalKeepFiles then "%a-%H-%M-%S_" else "" --- | Generate C code and use GCC to check that it compiles (no linking)+-- | Generate C code and use CC to check that it compiles (no linking) compileAndCheck' :: (Interp instr CGen (Param2 exp pred), HFunctor instr) => ExternalCompilerOpts -> Program instr (Param2 exp pred) a -> IO () compileAndCheck' opts prog = do@@ -168,47 +157,74 @@ exe <- compileC opts' prog removeFileIfPossible exe --- | Generate C code and use GCC to check that it compiles (no linking)+-- | Generate C code and use CC to check that it compiles (no linking) compileAndCheck :: (Interp instr CGen (Param2 exp pred), HFunctor instr) => Program instr (Param2 exp pred) a -> IO ()-compileAndCheck = compileAndCheck' mempty+compileAndCheck = compileAndCheck' def --- | Generate C code, use GCC to compile it, and run the resulting executable+-- | Generate C code, use CC to compile it, and run the resulting executable runCompiled' :: (Interp instr CGen (Param2 exp pred), HFunctor instr) => ExternalCompilerOpts -> Program instr (Param2 exp pred) a -> IO ()-runCompiled' opts@(ExternalCompilerOpts {..}) prog = do- exe <- compileC opts prog- maybePutStrLn externalSilent ""- maybePutStrLn externalSilent "#### Running:"- system exe- removeFileIfPossible exe- return ()+runCompiled' opts@(ExternalCompilerOpts {..}) prog = bracket+ (compileC opts prog)+ removeFileIfPossible+ ( \exe -> do+ maybePutStrLn externalSilent ""+ maybePutStrLn externalSilent "#### Running:"+ system exe >> return ()+ ) --- | Generate C code, use GCC to compile it, and run the resulting executable+-- | Generate C code, use CC to compile it, and run the resulting executable runCompiled :: (Interp instr CGen (Param2 exp pred), HFunctor instr) => Program instr (Param2 exp pred) a -> IO ()-runCompiled = runCompiled' mempty+runCompiled = runCompiled' def +-- | Compile a program and make it available as an 'IO' function from 'String'+-- to 'String' (connected to @stdin@/@stdout@. respectively). Note that+-- compilation only happens once, even if the 'IO' function is used many times+-- in the body.+withCompiled' :: (Interp instr CGen (Param2 exp pred), HFunctor instr)+ => ExternalCompilerOpts+ -> Program instr (Param2 exp pred) a -- ^ Program to compile+ -> ((String -> IO String) -> IO b)+ -- ^ Function that has access to the compiled executable as a function+ -> IO b+withCompiled' opts prog body = bracket+ (compileC opts prog)+ removeFileIfPossible+ (\exe -> body $ readProcess exe [])++-- | Compile a program and make it available as an 'IO' function from 'String'+-- to 'String' (connected to @stdin@/@stdout@. respectively). Note that+-- compilation only happens once, even if the 'IO' function is used many times+-- in the body.+withCompiled :: (Interp instr CGen (Param2 exp pred), HFunctor instr)+ => Program instr (Param2 exp pred) a -- ^ Program to compile+ -> ((String -> IO String) -> IO b)+ -- ^ Function that has access to the compiled executable as a function+ -> IO b+withCompiled = withCompiled' def {externalSilent = True}+ -- | Like 'runCompiled'' but with explicit input/output connected to--- @stdin@/@stdout@+-- @stdin@/@stdout@. Note that the program will be compiled every time the+-- function is applied to a string. In order to compile once and run many times,+-- use the function 'withCompiled''. captureCompiled' :: (Interp instr CGen (Param2 exp pred), HFunctor instr) => ExternalCompilerOpts -> Program instr (Param2 exp pred) a -- ^ Program to run -> String -- ^ Input to send to @stdin@ -> IO String -- ^ Result from @stdout@-captureCompiled' opts prog inp = do- exe <- compileC opts prog- out <- fakeIO (system exe) inp- removeFileIfPossible exe- return out+captureCompiled' opts prog inp = withCompiled' opts prog ($ inp) -- | Like 'runCompiled' but with explicit input/output connected to--- @stdin@/@stdout@+-- @stdin@/@stdout@. Note that the program will be compiled every time the+-- function is applied to a string. In order to compile once and run many times,+-- use the function 'withCompiled'. captureCompiled :: (Interp instr CGen (Param2 exp pred), HFunctor instr) => Program instr (Param2 exp pred) a -- ^ Program to run -> String -- ^ Input to send to @stdin@ -> IO String -- ^ Result from @stdout@-captureCompiled = captureCompiled' defaultExtCompilerOpts+captureCompiled = captureCompiled' def -- | Compare the content written to @stdout@ from the reference program and from -- running the compiled C code@@ -237,5 +253,5 @@ -> IO a -- ^ Reference program -> String -- ^ Input to send to @stdin@ -> IO ()-compareCompiled = compareCompiled' defaultExtCompilerOpts+compareCompiled = compareCompiled' def
src/Language/Embedded/Backend/C/Expression.hs view
@@ -14,19 +14,13 @@ import Data.Monoid #endif -#if MIN_VERSION_syntactic(3,0,0)-import Data.TypeRep hiding (Typeable, gcast)-import Data.TypeRep.TH-import Data.TypeRep.Types.Basic-import Data.TypeRep.Types.Tuple-import Data.TypeRep.Types.IntWord-#endif- import Language.C.Monad import Language.C.Quote.C import Language.C.Syntax (Exp,Type) import qualified Language.C.Syntax as C +import Control.Monad.Operational.Higher+ import Language.Embedded.Expression @@ -39,16 +33,6 @@ -- | Compilation of expressions compExp :: MonadC m => exp a -> m Exp -instance ToExp Int8 where toExp = toExp . toInteger-instance ToExp Int16 where toExp = toExp . toInteger-instance ToExp Int32 where toExp = toExp . toInteger-instance ToExp Int64 where toExp = toExp . toInteger-instance ToExp Word8 where toExp = toExp . toInteger-instance ToExp Word16 where toExp = toExp . toInteger-instance ToExp Word32 where toExp = toExp . toInteger-instance ToExp Word64 where toExp = toExp . toInteger- -- See <https://github.com/mainland/language-c-quote/pull/63>- -- | Types supported by C class (Show a, Eq a, Typeable a) => CType a where@@ -79,38 +63,32 @@ instance CType Float where cType _ = return [cty| float |] instance CType Double where cType _ = return [cty| double |] -#if MIN_VERSION_syntactic(3,0,0)-instance ShowClass CType where showClass _ = "CType"--pCType :: Proxy CType-pCType = Proxy--deriveWitness ''CType ''BoolType-deriveWitness ''CType ''FloatType-deriveWitness ''CType ''DoubleType-deriveWitness ''CType ''IntWordType--derivePWitness ''CType ''BoolType-derivePWitness ''CType ''FloatType-derivePWitness ''CType ''DoubleType-derivePWitness ''CType ''IntWordType--instance PWitness CType CharType t-instance PWitness CType ListType t-instance PWitness CType TupleType t-instance PWitness CType FunType t-#endif- -- | Remove one layer of a nested proxy proxyArg :: proxy1 (proxy2 a) -> Proxy a proxyArg _ = Proxy +-- | Classes that support reification to C types+class CompTypeClass ct+ where+ compType :: (ct a, MonadC m) => proxy1 ct -> proxy2 a -> m Type+ compLit :: (ct a, MonadC m) => proxy ct -> a -> m Exp++instance CompTypeClass CType+ where+ compType _ = cType+ compLit _ = cLit++-- | Get the type predicate from an instruction type+proxyPred :: cmd (Param3 p e pred) a -> Proxy pred+proxyPred _ = Proxy+ -- | Create and declare a fresh variable-freshVar :: forall m a . (MonadC m, CType a) => m (Val a)-freshVar = do+freshVar :: forall m ct proxy a . (MonadC m, CompTypeClass ct, ct a) =>+ proxy ct -> m (Val a)+freshVar ct = do v <- gensym "v" touchVar v- t <- cType (Proxy :: Proxy a)+ t <- compType ct (Proxy :: Proxy a) case t of C.Type _ C.Ptr{} _ -> addLocal [cdecl| $ty:t $id:v = NULL; |] _ -> addLocal [cdecl| $ty:t $id:v; |]
src/Language/Embedded/CExp.hs view
@@ -21,13 +21,9 @@ #endif import Data.Typeable -#if MIN_VERSION_syntactic(3,0,0) import Language.Syntactic import Language.Syntactic.Functional (Denotation) import Language.Syntactic.TH-#else-import Language.Syntactic-#endif import Language.C.Quote.C import Language.C.Syntax (Type, UnOp (..), BinOp (..), Exp (UnOp, BinOp))@@ -106,21 +102,18 @@ binaryOp BiLe = Le binaryOp BiGe = Ge -type SupportCode = forall m . MonadC m => m ()- -- | Syntactic symbols for C data Sym sig where -- Literal Lit :: String -> a -> Sym (Full a) -- Predefined constant- Const :: SupportCode -> String -> a -> Sym (Full a)+ Const :: String -> a -> Sym (Full a)+ -- The difference between `Lit` and `Const` is that the latter gets turned+ -- into a variable in the C code. It is like `Var`, except that it can+ -- also be evaluated. -- Function call- Fun ::-#if MIN_VERSION_syntactic(3,0,0)- Signature sig =>-#endif- SupportCode -> String -> Denotation sig -> Sym sig+ Fun :: Signature sig => String -> Denotation sig -> Sym sig -- Unary operator UOp :: Unary (a -> b) -> Sym (a :-> Full b) -- Binary operator@@ -133,7 +126,13 @@ Var :: VarId -> Sym (Full a) -- Unsafe array indexing ArrIx :: (Integral i, Ix i) => IArr i a -> Sym (i :-> Full a)+ -- Attach extra code to an expression+ WithCode :: SupportCode -> Sym (a :-> Full a) +type SupportCode = forall m . MonadC m => m ()+ -- Only needed because GHC 7.8 can't represent tuple constraints (like+ -- `MonadC`) in Template Haskell.+ data T sig where T :: CType (DenResult sig) => { unT :: Sym sig } -> T sig@@ -149,14 +148,14 @@ sugar = CExp evalSym :: Sym sig -> Denotation sig-evalSym (Lit _ a) = a-evalSym (Const _ _ a) = a-evalSym (Fun _ _ f) = f-evalSym (UOp uop) = evalUnary uop-evalSym (Op bop) = evalBinary bop-evalSym (Cast f) = f-evalSym Cond = \c t f -> if c then t else f-evalSym (ArrIx (IArrEval arr)) = \i ->+evalSym (Lit _ a) = a+evalSym (Const _ a) = a+evalSym (Fun _ f) = f+evalSym (UOp uop) = evalUnary uop+evalSym (Op bop) = evalBinary bop+evalSym (Cast f) = f+evalSym Cond = \c t f -> if c then t else f+evalSym (ArrIx (IArrRun arr)) = \i -> if i<l || i>h then error $ "index " ++ show (toInteger i)@@ -165,6 +164,7 @@ else arr!i where (l,h) = bounds arr+evalSym (WithCode _) = id evalSym (Var v) = error $ "evalCExp: cannot evaluate variable " ++ v -- | Evaluate an expression@@ -177,8 +177,8 @@ instance FreeExp CExp where- type VarPred CExp = CType- valExp a = CExp $ Sym $ T $ Lit (show a) a+ type FreePred CExp = CType+ constExp a = CExp $ Sym $ T $ Lit (show a) a varExp = CExp . Sym . T . Var instance EvalExp CExp where evalExp = evalCExp@@ -197,12 +197,10 @@ go :: CType (DenResult sig) => Sym sig -> Args (AST T) sig -> m Exp go (Var v) Nil = touchVar v >> return [cexp| $id:v |] go (Lit _ a) Nil = cLit a- go (Const code const _) Nil = do- code+ go (Const const _) Nil = do touchVar const return [cexp| $id:const |]- go (Fun code fun _) args = do- code+ go (Fun fun _) args = do as <- sequence $ listArgs compCExp' args return [cexp| $id:fun($args:as) |] go (UOp uop) (a :* Nil) = do@@ -233,6 +231,7 @@ i' <- compCExp' i touchVar arr return [cexp| $id:arr[$i'] |]+ go (WithCode code) (a :* Nil) = code >> compCExp' a instance CompExp CExp where compExp = compCExp @@ -298,19 +297,21 @@ -- | Predefined constant constant :: CType a- => SupportCode -- ^ Supporting C code- -> String -- ^ Name of constant- -> a -- ^ Value of constant+ => String -- ^ Name of constant+ -> a -- ^ Value of constant -> CExp a-constant code const val = CExp $ Sym $ T $ Const code const val+constant const val = CExp $ Sym $ T $ Const const val -- | Create a named variable variable :: CType a => VarId -> CExp a variable = CExp . Sym . T . Var +withCode :: CType a => (forall m . MonadC m => m ()) -> CExp a -> CExp a+withCode code = CExp . smartSym' (T $ WithCode code) . unCExp+ true, false :: CExp Bool-true = constant (addInclude "<stdbool.h>") "true" True-false = constant (addInclude "<stdbool.h>") "false" False+true = withCode (addInclude "<stdbool.h>") $ constant "true" True+false = withCode (addInclude "<stdbool.h>") $ constant "false" False instance (Num a, Ord a, CType a) => Num (CExp a) where@@ -358,17 +359,6 @@ recip = error "recip not implemented for CExp" -instance (Floating a, Ord a, CType a) => Floating (CExp a)- where- pi = constant (addGlobal pi_def) "EDSL_PI" pi- where- pi_def = [cedecl|$esc:("#define EDSL_PI 3.141592653589793")|]- -- This is the value of `pi :: Double`.- -- Apparently there is no standard C99 definition of pi.- a ** b = constFold $ sugarSym (T $ Fun (addInclude "<math.h>") "pow" (**)) a b- sin a = constFold $ sugarSym (T $ Fun (addInclude "<math.h>") "sin" sin) a- cos a = constFold $ sugarSym (T $ Fun (addInclude "<math.h>") "cos" cos) a- -- | Integer division truncated toward zero quot_ :: (Integral a, CType a) => CExp a -> CExp a -> CExp a quot_ (LitP 0) b = 0@@ -386,9 +376,6 @@ a #% b | a == b = 0 a #% b = constFold $ sugarSym (T $ Op BiRem) a b -round_ :: (RealFrac a, Integral b, CType b) => CExp a -> CExp b-round_ = constFold . sugarSym (T $ Fun (addInclude "<math.h>") "lround" round)- -- | Integral type casting i2n :: (Integral a, Num b, CType b) => CExp a -> CExp b i2n a = constFold $ sugarSym (T $ Cast (fromInteger . toInteger)) a@@ -499,23 +486,20 @@ -- Instances -------------------------------------------------------------------------------- -#if MIN_VERSION_syntactic(3,0,0) deriveSymbol ''Sym-#endif instance Render Sym where- renderSym (Lit a _) = a- renderSym (Const _ a _) = a- renderSym (Fun _ name _) = name- renderSym (UOp op) = show $ unaryOp op- renderSym (Op op) = show $ binaryOp op- renderSym (Cast _) = "cast"- renderSym (Var v) = v+ renderSym (Lit a _) = a+ renderSym (Const a _) = a+ renderSym (Fun name _) = name+ renderSym (UOp op) = show $ unaryOp op+ renderSym (Op op) = show $ binaryOp op+ renderSym (Cast _) = "cast"+ renderSym (Var v) = v renderSym (ArrIx (IArrComp arr)) = "ArrIx " ++ arr renderSym (ArrIx _) = "ArrIx ..."--#if MIN_VERSION_syntactic(3,0,0)+ renderSym (WithCode _) = "WithCode ..." renderArgs = renderArgsSmart @@ -541,28 +525,6 @@ instance StringTree T where stringTreeSym as (T s) = stringTreeSym as s--#else--instance Semantic Sym- where- semantics s = Sem (renderSym s) (evalSym s)--instance Equality Sym- where- equal = equalDefault- exprHash = exprHashDefault--instance Semantic T- where- semantics (T s) = semantics s--instance Equality T- where- equal (T s) (T t) = equal s t- exprHash (T s) = exprHash s--#endif deriving instance Eq (CExp a) -- Must be placed here due to the sequential dependencies introduced by
src/Language/Embedded/Concurrent.hs view
@@ -1,20 +1,38 @@ -- | Basic concurrency primitives.-module Language.Embedded.Concurrent (- ThreadId (..),- ChanBound, Chan (..),- ThreadCMD,- ChanCMD,- Closeable, Uncloseable,- fork, forkWithId, asyncKillThread, killThread, waitThread,- newChan, newCloseableChan, readChan, writeChan,- closeChan, lastChanReadOK,+--+-- To compile the C code resulting from 'Language.Embedded.Backend.C.compile'+-- for programs with concurrency primitives, use something like+--+-- > cc -std=c99 -Iinclude csrc/chan.c -lpthread YOURPROGRAM.c+module Language.Embedded.Concurrent+ ( ThreadId (..)+ , Chan (..)+ , ChanSize (..)+ , ThreadCMD+ , ChanCMD+ , Closeable, Uncloseable+ , fork, forkWithId, asyncKillThread, killThread, waitThread, delayThread+ , timesSizeOf, timesSize, plusSize+ , newChan, newCloseableChan+ , readChan, writeChan+ , readChanBuf, writeChanBuf+ , closeChan, lastChanReadOK+ , newChan', newCloseableChan'+ , readChan', writeChan'+ , readChanBuf', writeChanBuf' ) where import Control.Monad.Operational.Higher-import Language.Embedded.Expression-import Language.Embedded.Concurrent.CMD+import Data.Ix+import Data.Typeable+ import Language.Embedded.Concurrent.Backend.C ()+import Language.Embedded.Concurrent.CMD+import Language.Embedded.Expression+import Language.Embedded.Imperative.CMD (Arr) ++ -- | Fork off a computation as a new thread. fork :: (ThreadCMD :<: instr) => ProgramT instr (Param2 exp pred) m ()@@ -44,50 +62,95 @@ => ThreadId -> ProgramT instr (Param2 exp pred) m () waitThread = singleton . inj . Wait --- | Create a new channel. Writing a reference type to a channel will copy the--- /reference/ into the queue, not its contents.------ We'll likely want to change this, actually copying arrays and the like--- into the queue instead of sharing them across threads.-newChan :: (pred a, ChanCMD :<: instr)- => exp ChanBound+-- | Sleep for a given amount of microseconds. Implemented with `usleep`.+-- A C compiler might require a feature test macro to be defined,+-- otherwise it emits a warning about an implicitly declared function.+-- For more details, see: http://man7.org/linux/man-pages/man3/usleep.3.html+delayThread :: (Integral i, ThreadCMD :<: instr)+ => exp i -> ProgramT instr (Param2 exp pred) m ()+delayThread = singleton . inj . Sleep+++--------------------------------------------------------------------------------+-- Channel frontend+--------------------------------------------------------------------------------++-- | Create a new channel. Writing a reference type to a channel will copy+-- contents into the channel, so modifying it post-write is completely+-- safe.+newChan :: forall a i exp pred instr m+ . (pred a, Integral i, ChanCMD :<: instr)+ => exp i -> ProgramT instr (Param2 exp pred) m (Chan Uncloseable a)-newChan = singleInj . NewChan+newChan n = newChan' $ n `timesSizeOf` (Proxy :: Proxy a) -newCloseableChan :: (pred a, ChanCMD :<: instr)- => exp ChanBound- -> ProgramT instr (Param2 exp pred) m (Chan Closeable a)-newCloseableChan = singleInj . NewChan+newCloseableChan :: forall a i exp pred instr m+ . (pred a, Integral i, ChanCMD :<: instr)+ => exp i+ -> ProgramT instr (Param2 exp pred) m (Chan Closeable a)+newCloseableChan n = newCloseableChan' $ n `timesSizeOf` (Proxy :: Proxy a) + -- | Read an element from a channel. If channel is empty, blocks until there -- is an item available. -- If 'closeChan' has been called on the channel *and* if the channel is -- empty, @readChan@ returns an undefined value immediately.-readChan :: (pred a, FreeExp exp, VarPred exp a, ChanCMD :<: instr, Monad m)+readChan :: ( Typeable a, pred a+ , FreeExp exp, FreePred exp a+ , ChanCMD :<: instr, Monad m ) => Chan t a -> ProgramT instr (Param2 exp pred) m (exp a)-readChan = fmap valToExp . singleInj . ReadChan+readChan = readChan' +-- | Read an arbitrary number of elements from a channel into an array.+-- The semantics are the same as for 'readChan', where "channel is empty"+-- is defined as "channel contains less data than requested".+-- Returns @False@ without reading any data if the channel is closed.+readChanBuf :: ( Typeable a, pred a+ , Ix i, Integral i+ , FreeExp exp, FreePred exp Bool+ , ChanCMD :<: instr, Monad m )+ => Chan t a+ -> exp i -- ^ Offset in array to start writing+ -> exp i -- ^ Elements to read+ -> Arr i a+ -> ProgramT instr (Param2 exp pred) m (exp Bool)+readChanBuf = readChanBuf'+ -- | Write a data element to a channel. -- If 'closeChan' has been called on the channel, all calls to @writeChan@ -- become non-blocking no-ops and return @False@, otherwise returns @True@.-writeChan :: (pred a,- FreeExp exp,- VarPred exp Bool,- ChanCMD :<: instr,- Monad m- )- => Chan t a- -> exp a- -> ProgramT instr (Param2 exp pred) m (exp Bool)-writeChan c = fmap valToExp . singleInj . WriteChan c+-- If the channel is full, this function blocks until there's space in the+-- queue.+writeChan :: ( Typeable a, pred a+ , FreeExp exp, FreePred exp Bool+ , ChanCMD :<: instr, Monad m )+ => Chan t a+ -> exp a+ -> ProgramT instr (Param2 exp pred) m (exp Bool)+writeChan = writeChan' +-- | Write an arbitrary number of elements from an array into an channel.+-- The semantics are the same as for 'writeChan', where "channel is full"+-- is defined as "channel has insufficient free space to store all written+-- data".+writeChanBuf :: ( Typeable a, pred a+ , Ix i, Integral i+ , FreeExp exp, FreePred exp Bool+ , ChanCMD :<: instr, Monad m )+ => Chan t a+ -> exp i -- ^ Offset in array to start reading+ -> exp i -- ^ Elements to write+ -> Arr i a+ -> ProgramT instr (Param2 exp pred) m (exp Bool)+writeChanBuf = writeChanBuf'+ -- | When 'readChan' was last called on the given channel, did the read -- succeed? -- Always returns @True@ unless 'closeChan' has been called on the channel. -- Always returns @True@ if the channel has never been read.-lastChanReadOK :: (FreeExp exp, VarPred exp Bool, ChanCMD :<: instr, Monad m)- => Chan Closeable a+lastChanReadOK :: (FreeExp exp, FreePred exp Bool, ChanCMD :<: instr, Monad m)+ => Chan Closeable c -> ProgramT instr (Param2 exp pred) m (exp Bool) lastChanReadOK = fmap valToExp . singleInj . ReadOK @@ -95,7 +158,58 @@ -- After the channel is drained, all subsequent read operations will be -- no-ops as well. closeChan :: (ChanCMD :<: instr)- => Chan Closeable a+ => Chan Closeable c -> ProgramT instr (Param2 exp pred) m () closeChan = singleInj . CloseChan ++--------------------------------------------------------------------------------+-- Unsafe channel primitives+--------------------------------------------------------------------------------++newChan' :: (Integral i, ChanCMD :<: instr)+ => ChanSize exp pred i+ -> ProgramT instr (Param2 exp pred) m (Chan Uncloseable a)+newChan' = singleInj . NewChan++newCloseableChan' :: (Integral i, ChanCMD :<: instr)+ => ChanSize exp pred i+ -> ProgramT instr (Param2 exp pred) m (Chan Closeable a)+newCloseableChan' = singleInj . NewChan++readChan' :: ( Typeable a, pred a+ , FreeExp exp, FreePred exp a+ , ChanCMD :<: instr, Monad m )+ => Chan t c+ -> ProgramT instr (Param2 exp pred) m (exp a)+readChan' = fmap valToExp . singleInj . ReadOne++readChanBuf' :: ( Typeable a, pred a+ , Ix i, Integral i+ , FreeExp exp, FreePred exp Bool+ , ChanCMD :<: instr, Monad m )+ => Chan t c+ -> exp i -- ^ Offset in array to start writing+ -> exp i -- ^ Elements to read+ -> Arr i a+ -> ProgramT instr (Param2 exp pred) m (exp Bool)+readChanBuf' ch off sz arr = fmap valToExp . singleInj $ ReadChan ch off sz arr++writeChan' :: ( Typeable a, pred a+ , FreeExp exp, FreePred exp Bool+ , ChanCMD :<: instr, Monad m )+ => Chan t c+ -> exp a+ -> ProgramT instr (Param2 exp pred) m (exp Bool)+writeChan' c = fmap valToExp . singleInj . WriteOne c++writeChanBuf' :: ( Typeable a, pred a+ , Ix i, Integral i+ , FreeExp exp, FreePred exp Bool+ , ChanCMD :<: instr, Monad m )+ => Chan t c+ -> exp i -- ^ Offset in array to start reading+ -> exp i -- ^ Elements to write+ -> Arr i a+ -> ProgramT instr (Param2 exp pred) m (exp Bool)+writeChanBuf' ch off sz arr = fmap valToExp . singleInj $ WriteChan ch off sz arr
src/Language/Embedded/Concurrent/Backend/C.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE UndecidableInstances #-} module Language.Embedded.Concurrent.Backend.C where @@ -9,8 +10,10 @@ import Control.Applicative #endif import Control.Monad.Operational.Higher+import Data.Typeable import Language.Embedded.Expression import Language.Embedded.Concurrent.CMD+import Language.Embedded.Imperative.CMD import Language.Embedded.Backend.C.Expression import Language.C.Quote.C import Language.C.Monad@@ -29,7 +32,7 @@ -- | Compile `ThreadCMD`. -- TODO: sharing for threads with the same body-compThreadCMD :: ThreadCMD (Param3 CGen exp pred) a -> CGen a+compThreadCMD :: CompExp exp => ThreadCMD (Param3 CGen exp pred) a -> CGen a compThreadCMD (ForkWithId body) = do tid <- TIDComp <$> gensym "t" let funName = threadFun tid@@ -48,39 +51,68 @@ compThreadCMD (Wait tid) = do touchVar tid addStm [cstm| pthread_join($id:tid, NULL); |]+compThreadCMD (Sleep us) = do+ us' <- compExp us+ addSystemInclude "unistd.h"+ addStm [cstm| usleep($us'); |] -- | Compile `ChanCMD`.-compChanCMD :: CompExp exp- => ChanCMD (Param3 CGen exp CType) a+compChanCMD :: (CompExp exp, CompTypeClass ct, ct Bool)+ => ChanCMD (Param3 CGen exp ct) a -> CGen a compChanCMD cmd@(NewChan sz) = do addLocalInclude "chan.h"- t <- cType (proxyArg cmd)- sz' <- compExp sz+ sz' <-compChanSize sz c <- ChanComp <$> gensym "chan" addGlobal [cedecl| typename chan_t $id:c; |]- addStm [cstm| $id:c = chan_new(sizeof($ty:t), $sz'); |]+ addStm [cstm| $id:c = chan_new($sz'); |] return c-compChanCMD (WriteChan c (x :: exp a)) = do+compChanCMD cmd@(WriteOne c (x :: exp a)) = do x' <- compExp x- v :: Val a <- freshVar- ok <- freshVar+ v :: Val a <- freshVar (proxyPred cmd)+ ok <- freshVar (proxyPred cmd) addStm [cstm| $id:v = $x'; |]- addStm [cstm| $id:ok = chan_write($id:c, &$id:v); |]+ addStm [cstm| $id:ok = chan_write($id:c, sizeof($id:v), &$id:v); |] return ok-compChanCMD (ReadChan c) = do- var <- freshVar- addStm [cstm| chan_read($id:c, &$id:var); |]- return var+compChanCMD cmd@(WriteChan c from to (ArrComp arr)) = do+ from' <- compExp from+ to' <- compExp to+ ok <- freshVar (proxyPred cmd)+ addStm [cstm| $id:ok = chan_write($id:c, sizeof(*$id:arr)*(($to')-($from')), &$id:arr[$from']); |]+ return ok+compChanCMD cmd@(ReadOne c) = do+ v <- freshVar (proxyPred cmd)+ addStm [cstm| chan_read($id:c, sizeof($id:v), &$id:v); |]+ return v+compChanCMD cmd@(ReadChan c from to (ArrComp arr)) = do+ ok <- freshVar (proxyPred cmd)+ from' <- compExp from+ to' <- compExp to+ addStm [cstm| chan_read($id:c, sizeof(*$id:arr)*(($to')-($from')), &$id:arr[$from']); |]+ addStm [cstm| $id:ok = chan_last_read_ok($id:c); |]+ return ok compChanCMD (CloseChan c) = do addStm [cstm| chan_close($id:c); |]-compChanCMD (ReadOK c) = do- var <- freshVar+compChanCMD cmd@(ReadOK c) = do+ var <- freshVar (proxyPred cmd) addStm [cstm| $id:var = chan_last_read_ok($id:c); |] return var -instance Interp ThreadCMD CGen (Param2 exp pred) where+compChanSize :: forall exp ct i. (CompExp exp, CompTypeClass ct) => ChanSize exp ct i -> CGen C.Exp+compChanSize (OneSize t sz) = do+ t' <- compType (Proxy :: Proxy ct) t+ sz' <- compExp sz+ return [cexp| $sz' * sizeof($ty:t') |]+compChanSize (TimesSize n sz) = do+ n' <- compExp n+ sz' <- compChanSize sz+ return [cexp| $n' * $sz' |]+compChanSize (PlusSize a b) = do+ a' <- compChanSize a+ b' <- compChanSize b+ return [cexp| $a' + $b' |]++instance CompExp exp => Interp ThreadCMD CGen (Param2 exp pred) where interp = compThreadCMD-instance CompExp exp => Interp ChanCMD CGen (Param2 exp CType) where+instance (CompExp exp, CompTypeClass ct, ct Bool) => Interp ChanCMD CGen (Param2 exp ct) where interp = compChanCMD-
src/Language/Embedded/Concurrent/CMD.hs view
@@ -1,9 +1,12 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE TupleSections #-} {-# LANGUAGE UndecidableInstances #-} module Language.Embedded.Concurrent.CMD ( TID, ThreadId (..),- CID, ChanBound, Chan (..),+ CID, Chan (..),+ ChanSize (..),+ timesSizeOf, timesSize, plusSize, ThreadCMD (..), ChanCMD (..), Closeable, Uncloseable@@ -13,21 +16,23 @@ #if __GLASGOW_HASKELL__ < 710 import Control.Applicative+import Data.Typeable #endif+import qualified Control.Chan as Chan+import qualified Control.Concurrent as CC import Control.Monad.Operational.Higher import Control.Monad.Reader+import Data.Dynamic import Data.IORef-import Data.Typeable+import Data.Ix (Ix)+import Data.Maybe (fromMaybe)+ import Language.Embedded.Expression-import qualified Control.Concurrent as CC-import qualified Control.Concurrent.BoundedChan as Bounded-import Data.Word (Word16)+import Language.Embedded.Imperative.CMD+import Language.Embedded.Imperative (getArr, setArr) --- | Maximum number of elements in some bounded channel.-type ChanBound = Word16- type TID = VarId type CID = VarId @@ -56,119 +61,202 @@ waitFlag (Flag _ var) = CC.withMVar var return data ThreadId- = TIDEval CC.ThreadId (Flag ())+ = TIDRun CC.ThreadId (Flag ()) | TIDComp TID deriving (Typeable) instance Show ThreadId where- show (TIDEval tid _) = show tid- show (TIDComp tid) = tid+ show (TIDRun tid _) = show tid+ show (TIDComp tid) = tid data Closeable data Uncloseable -- | A bounded channel. data Chan t a- = ChanEval (Bounded.BoundedChan a) (IORef Bool) (IORef Bool)+ = ChanRun (Chan.Chan Dynamic) | ChanComp CID +-- | Channel size specification. For each possible element type, it shows how+-- many elements of them could be stored in the given channel at once.+data ChanSize exp pred i where+ OneSize :: (pred a, Integral i) => proxy a -> exp i -> ChanSize exp pred i+ TimesSize :: Integral i => exp i -> ChanSize exp pred i -> ChanSize exp pred i+ PlusSize :: Integral i => ChanSize exp pred i -> ChanSize exp pred i -> ChanSize exp pred i++mapSizeExp :: (exp i -> exp' i) -> ChanSize exp pred i -> ChanSize exp' pred i+mapSizeExp f (OneSize t sz) = OneSize t (f sz)+mapSizeExp f (TimesSize n sz) = TimesSize (f n) (mapSizeExp f sz)+mapSizeExp f (PlusSize a b) = PlusSize (mapSizeExp f a) (mapSizeExp f b)++mapSizeExpA :: (Functor m, Monad m)+ => (exp i -> m (exp' i))+ -> ChanSize exp pred i+ -> m (ChanSize exp' pred i)+mapSizeExpA f (OneSize t sz) = OneSize t <$> f sz+mapSizeExpA f (TimesSize n sz) = do+ n' <- f n+ sz' <- mapSizeExpA f sz+ return $ TimesSize n' sz'+mapSizeExpA f (PlusSize a b) = do+ a' <- mapSizeExpA f a+ b' <- mapSizeExpA f b+ return $ PlusSize a' b'++-- | Takes 'n' times the size of type refered by proxy.+timesSizeOf :: (pred a, Integral i) => exp i -> proxy a -> ChanSize exp pred i+timesSizeOf = flip OneSize++-- | Multiplies a channel size specification with a scalar.+timesSize :: Integral i => exp i -> ChanSize exp pred i -> ChanSize exp pred i+timesSize = TimesSize++-- | Adds two channel size specifications together.+plusSize :: Integral i => ChanSize exp pred i -> ChanSize exp pred i -> ChanSize exp pred i+plusSize = PlusSize+ data ThreadCMD fs a where ForkWithId :: (ThreadId -> prog ()) -> ThreadCMD (Param3 prog exp pred) ThreadId Kill :: ThreadId -> ThreadCMD (Param3 prog exp pred) () Wait :: ThreadId -> ThreadCMD (Param3 prog exp pred) ()+ Sleep :: Integral i => exp i -> ThreadCMD (Param3 prog exp pred) () data ChanCMD fs a where- NewChan :: pred a => exp ChanBound -> ChanCMD (Param3 prog exp pred) (Chan t a)- ReadChan :: pred a => Chan t a -> ChanCMD (Param3 prog exp pred) (Val a)- WriteChan :: pred a- => Chan t a -> exp a -> ChanCMD (Param3 prog exp pred) (Val Bool)- CloseChan :: Chan Closeable a -> ChanCMD (Param3 prog exp pred) ()- ReadOK :: Chan Closeable a -> ChanCMD (Param3 prog exp pred) (Val Bool)+ NewChan :: ChanSize exp pred i -> ChanCMD (Param3 prog exp pred) (Chan t c)+ CloseChan :: Chan Closeable c -> ChanCMD (Param3 prog exp pred) ()+ ReadOK :: Chan Closeable c -> ChanCMD (Param3 prog exp pred) (Val Bool) + ReadOne :: (Typeable a, pred a)+ => Chan t c -> ChanCMD (Param3 prog exp pred) (Val a)+ WriteOne :: (Typeable a, pred a)+ => Chan t c -> exp a -> ChanCMD (Param3 prog exp pred) (Val Bool)++ ReadChan :: (Typeable a, pred a, Ix i, Integral i)+ => Chan t c -> exp i -> exp i+ -> Arr i a -> ChanCMD (Param3 prog exp pred) (Val Bool)+ WriteChan :: (Typeable a, pred a, Ix i, Integral i)+ => Chan t c -> exp i -> exp i+ -> Arr i a -> ChanCMD (Param3 prog exp pred) (Val Bool)+ instance HFunctor ThreadCMD where hfmap f (ForkWithId p) = ForkWithId $ f . p hfmap _ (Kill tid) = Kill tid hfmap _ (Wait tid) = Wait tid+ hfmap _ (Sleep tid) = Sleep tid instance HBifunctor ThreadCMD where hbimap f _ (ForkWithId p) = ForkWithId $ f . p hbimap _ _ (Kill tid) = Kill tid hbimap _ _ (Wait tid) = Wait tid+ hbimap _ g (Sleep us) = Sleep $ g us -instance (ThreadCMD :<: instr) => Reexpressible ThreadCMD instr where+instance (ThreadCMD :<: instr) => Reexpressible ThreadCMD instr env where reexpressInstrEnv reexp (ForkWithId p) = ReaderT $ \env -> singleInj $ ForkWithId (flip runReaderT env . p) reexpressInstrEnv reexp (Kill tid) = lift $ singleInj $ Kill tid reexpressInstrEnv reexp (Wait tid) = lift $ singleInj $ Wait tid+ reexpressInstrEnv reexp (Sleep us) = (lift . singleInj . Sleep) =<< reexp us instance HFunctor ChanCMD where- hfmap _ (NewChan sz) = NewChan sz- hfmap _ (ReadChan c) = ReadChan c- hfmap _ (WriteChan c x) = WriteChan c x- hfmap _ (CloseChan c) = CloseChan c- hfmap _ (ReadOK c) = ReadOK c+ hfmap _ (NewChan sz) = NewChan sz+ hfmap _ (ReadOne c) = ReadOne c+ hfmap _ (ReadChan c f t a) = ReadChan c f t a+ hfmap _ (WriteOne c x) = WriteOne c x+ hfmap _ (WriteChan c f t a) = WriteChan c f t a+ hfmap _ (CloseChan c) = CloseChan c+ hfmap _ (ReadOK c) = ReadOK c instance HBifunctor ChanCMD where- hbimap _ f (NewChan sz) = NewChan (f sz)- hbimap _ _ (ReadChan c) = ReadChan c- hbimap _ f (WriteChan c x) = WriteChan c (f x)- hbimap _ _ (CloseChan c) = CloseChan c- hbimap _ _ (ReadOK c) = ReadOK c+ hbimap _ f (NewChan sz) = NewChan (mapSizeExp f sz)+ hbimap _ _ (ReadOne c) = ReadOne c+ hbimap _ f (ReadChan c n n' a) = ReadChan c (f n) (f n') a+ hbimap _ f (WriteOne c x) = WriteOne c (f x)+ hbimap _ f (WriteChan c n n' a) = WriteChan c (f n) (f n') a+ hbimap _ _ (CloseChan c ) = CloseChan c+ hbimap _ _ (ReadOK c) = ReadOK c -instance (ChanCMD :<: instr) => Reexpressible ChanCMD instr where- reexpressInstrEnv reexp (NewChan sz) = lift . singleInj . NewChan =<< reexp sz- reexpressInstrEnv reexp (ReadChan c) = lift $ singleInj $ ReadChan c- reexpressInstrEnv reexp (WriteChan c x) = lift . singleInj . WriteChan c =<< reexp x+instance (ChanCMD :<: instr) => Reexpressible ChanCMD instr env where+ reexpressInstrEnv reexp (NewChan sz) =+ lift . singleInj . NewChan =<< mapSizeExpA reexp sz+ reexpressInstrEnv reexp (ReadOne c) = lift $ singleInj $ ReadOne c+ reexpressInstrEnv reexp (ReadChan c f t a) = do+ rf <- reexp f+ rt <- reexp t+ lift $ singleInj $ ReadChan c rf rt a+ reexpressInstrEnv reexp (WriteOne c x) = lift . singleInj . WriteOne c =<< reexp x+ reexpressInstrEnv reexp (WriteChan c f t a) = do+ rf <- reexp f+ rt <- reexp t+ lift $ singleInj $ WriteChan c rf rt a reexpressInstrEnv reexp (CloseChan c) = lift $ singleInj $ CloseChan c reexpressInstrEnv reexp (ReadOK c) = lift $ singleInj $ ReadOK c -runThreadCMD :: ThreadCMD (Param3 IO exp pred) a- -> IO a+runThreadCMD :: ThreadCMD (Param3 IO IO pred) a -> IO a runThreadCMD (ForkWithId p) = do f <- newFlag tidvar <- CC.newEmptyMVar cctid <- CC.forkIO . void $ CC.takeMVar tidvar >>= p >> setFlag f ()- let tid = TIDEval cctid f+ let tid = TIDRun cctid f CC.putMVar tidvar tid return tid-runThreadCMD (Kill (TIDEval t f)) = do+runThreadCMD (Kill (TIDRun t f)) = do setFlag f () CC.killThread t return ()-runThreadCMD (Wait (TIDEval _ f)) = do+runThreadCMD (Wait (TIDRun _ f)) = do waitFlag f+runThreadCMD (Sleep us) = do+ us' <- us+ CC.threadDelay $ fromIntegral us' -runChanCMD :: ChanCMD (Param3 IO IO pred) a -> IO a+runChanCMD :: forall pred a. ChanCMD (Param3 IO IO pred) a -> IO a runChanCMD (NewChan sz) = do- sz' <- sz- ChanEval <$> Bounded.newBoundedChan (fromIntegral sz')- <*> newIORef False- <*> newIORef True-runChanCMD (ReadChan (ChanEval c closedref lastread)) = do- closed <- readIORef closedref- mval <- Bounded.tryReadChan c- case mval of- Just x -> do- return $ ValEval x- Nothing- | closed -> do- writeIORef lastread False- return undefined- | otherwise -> do- ValEval <$> Bounded.readChan c-runChanCMD (WriteChan (ChanEval c closedref _) x) = do- closed <- readIORef closedref- x' <- x- if closed- then return (ValEval False)- else Bounded.writeChan c x' >> return (ValEval True)-runChanCMD (CloseChan (ChanEval _ closedref _)) = do- writeIORef closedref True-runChanCMD (ReadOK (ChanEval _ _ lastread)) = do- ValEval <$> readIORef lastread+ sz' <- evalChanSize sz+ ChanRun <$> Chan.newChan sz'+runChanCMD (ReadOne (ChanRun c)) =+ ValRun . convertDynamic . head <$> Chan.readChan c 1+runChanCMD (ReadChan (ChanRun c) off len arr) = do+ off' <- off+ len' <- len+ xs <- Chan.readChan c $ fromIntegral (len' - off')+ let xs' = map convertDynamic xs+ interpretBi id $ forM_ (zip [off' .. ] xs') $ \(i, x) -> do+ setArr (return i) (return x) arr :: Program ArrCMD (Param2 IO pred) ()+ ValRun <$> Chan.lastReadOK c+runChanCMD (WriteOne (ChanRun c) x) =+ ValRun <$> (Chan.writeChan c . return . toDyn =<< x)+runChanCMD (WriteChan (ChanRun c) off len (arr :: Arr ix el)) = do+ off' <- off+ len' <- len+ xs <- interpretBi id $ forM [off' .. off' + len' - 1] $ \i -> do+ getArr (return i) arr :: Program ArrCMD (Param2 IO pred) (IO el)+ ValRun <$> (Chan.writeChan c =<< map toDyn <$> sequence xs)+runChanCMD (CloseChan (ChanRun c)) = Chan.closeChan c+runChanCMD (ReadOK (ChanRun c)) = ValRun <$> Chan.lastReadOK c instance InterpBi ThreadCMD IO (Param1 pred) where interpBi = runThreadCMD instance InterpBi ChanCMD IO (Param1 pred) where interpBi = runChanCMD +evalChanSize :: ChanSize IO pred i -> IO Int+evalChanSize (OneSize _ sz) = do+ sz' <- sz+ return $ fromIntegral sz'+evalChanSize (TimesSize n sz) = do+ n' <- n+ sz' <- evalChanSize sz+ return $ fromIntegral n' * sz'+evalChanSize (PlusSize a b) = do+ a' <- evalChanSize a+ b' <- evalChanSize b+ return $ a' + b'++convertDynamic :: Typeable a => Dynamic -> a+convertDynamic = fromMaybe (error "readChan: unknown element") . fromDynamic++instance FreeExp IO+ where+ type FreePred IO = Typeable+ constExp = return+ varExp = error "varExp: unimplemented over IO"
src/Language/Embedded/Expression.hs view
@@ -8,7 +8,11 @@ import Data.Typeable +#if __GLASGOW_HASKELL__ >= 800+import GHC.Types (Constraint)+#else import GHC.Prim (Constraint)+#endif import Language.C.Quote.C (ToIdent (..)) @@ -17,36 +21,37 @@ -- | Variable identifier type VarId = String --- | Expressions that support injection of values and named variables+-- | Expressions that support injection of constants and named variables class FreeExp exp where- -- | Constraint on the types of values and variables in an expression+ -- | Constraint on the types of constants and variables in an expression -- language- type VarPred exp :: * -> Constraint+ type FreePred exp :: * -> Constraint - -- | Construct a value expression- valExp :: VarPred exp a => a -> exp a+ -- | Inject a constant value+ constExp :: FreePred exp a => a -> exp a - -- | Construct a named variable expression- varExp :: VarPred exp a => VarId -> exp a+ -- | Inject a named variable+ varExp :: FreePred exp a => VarId -> exp a -- | Value data Val a = ValComp VarId -- ^ Symbolic value- | ValEval a -- ^ Concrete value+ | ValRun a -- ^ Concrete value deriving Typeable instance ToIdent (Val a) where toIdent (ValComp r) = toIdent r -- | Convert a value to an expression-valToExp :: (VarPred exp a, FreeExp exp) => Val a -> exp a+valToExp :: (FreeExp exp, FreePred exp a) => Val a -> exp a valToExp (ValComp v) = varExp v-valToExp (ValEval a) = valExp a+valToExp (ValRun a) = constExp a -- | Expressions that support evaluation class FreeExp exp => EvalExp exp -- The super class is motivated by the fact that evaluation of functions- -- `exp a -> exp b` can be done by constructing an argument using `valExp`.+ -- `exp a -> exp b` can be done by constructing an argument using+ -- `constExp`. where -- | Evaluation of a closed expression evalExp :: exp a -> a
src/Language/Embedded/Imperative.hs view
@@ -36,7 +36,7 @@ , (:<:) -- * Interface for expression types , FreeExp- , VarPred+ , FreePred , EvalExp , CompExp -- * Front end
src/Language/Embedded/Imperative/Args.hs view
@@ -7,7 +7,6 @@ import Data.Proxy import Language.C.Quote.C-import Language.C.Syntax hiding (Deref) import Language.C.Monad import Language.Embedded.Imperative.CMD@@ -17,40 +16,40 @@ data RefArg pred where RefArg :: pred a => Ref a -> RefArg pred -instance Arg RefArg CType where+instance CompTypeClass ct => Arg RefArg ct where mkArg (RefArg r) = touchVar r >> return [cexp| &$id:r |] mkParam (RefArg (r :: Ref a)) = do- t <- cType (Proxy :: Proxy a)+ t <- compType (Proxy :: Proxy ct) (Proxy :: Proxy a) return [cparam| $ty:t* |] -- | Mutable array argument data ArrArg pred where ArrArg :: pred a => Arr i a -> ArrArg pred -instance Arg ArrArg CType where+instance CompTypeClass ct => Arg ArrArg ct where mkArg (ArrArg a) = touchVar a >> return [cexp| $id:a |] mkParam (ArrArg (_ :: Arr i a)) = do- t <- cType (Proxy :: Proxy a)+ t <- compType (Proxy :: Proxy ct) (Proxy :: Proxy a) return [cparam| $ty:t* |] -- | Immutable array argument data IArrArg pred where IArrArg :: pred a => IArr i a -> IArrArg pred -instance Arg IArrArg CType where+instance CompTypeClass ct => Arg IArrArg ct where mkArg (IArrArg a) = touchVar a >> return [cexp| $id:a |] mkParam (IArrArg (_ :: IArr i a)) = do- t <- cType (Proxy :: Proxy a)+ t <- compType (Proxy :: Proxy ct) (Proxy :: Proxy a) return [cparam| $ty:t* |] -- | Pointer argument data PtrArg pred where PtrArg :: pred a => Ptr a -> PtrArg pred -instance Arg PtrArg CType where+instance CompTypeClass ct => Arg PtrArg ct where mkArg (PtrArg p) = touchVar p >> return [cexp| $id:p |] mkParam (PtrArg (_ :: Ptr a)) = do- t <- cType (Proxy :: Proxy a)+ t <- compType (Proxy :: Proxy ct) (Proxy :: Proxy a) return [cparam| $ty:t* |] -- | Abstract object argument@@ -70,6 +69,15 @@ StrArg :: String -> StrArg pred instance Arg StrArg pred where- mkArg (StrArg s) = return [cexp| $string:s |]+ mkArg (StrArg s) = return [cexp| $s |] mkParam (StrArg s) = return [cparam| const char* |]++data ConstArg pred where+ ConstArg :: { constArgType :: String, constArg :: String } -> ConstArg pred++instance Arg ConstArg pred where+ mkArg (ConstArg _ n) = return [cexp| $id:n |]+ mkParam (ConstArg t _) = return [cparam| $ty:t' |]+ where+ t' = namedType t
src/Language/Embedded/Imperative/Backend/C.hs view
@@ -14,7 +14,7 @@ import Control.Monad.State import Data.Proxy -import Language.C.Quote.C+import Language.C.Quote.GCC import qualified Language.C.Syntax as C import Control.Monad.Operational.Higher@@ -27,23 +27,24 @@ -- | Compile `RefCMD`-compRefCMD :: CompExp exp => RefCMD (Param3 prog exp CType) a -> CGen a+compRefCMD :: (CompExp exp, CompTypeClass ct) =>+ RefCMD (Param3 prog exp ct) a -> CGen a compRefCMD cmd@(NewRef base) = do- t <- cType (proxyArg cmd)+ t <- compType (proxyPred cmd) (proxyArg cmd) r <- RefComp <$> gensym base addLocal $ case t of C.Type _ C.Ptr{} _ -> [cdecl| $ty:t $id:r = NULL; |] _ -> [cdecl| $ty:t $id:r; |] return r-compRefCMD (InitRef base exp) = do- t <- cType exp+compRefCMD cmd@(InitRef base exp) = do+ t <- compType (proxyPred cmd) exp r <- RefComp <$> gensym base e <- compExp exp addLocal [cdecl| $ty:t $id:r; |] addStm [cstm| $id:r = $e; |] return r-compRefCMD (GetRef ref) = do- v <- freshVar+compRefCMD cmd@(GetRef ref) = do+ v <- freshVar (proxyPred cmd) touchVar ref addStm [cstm| $id:v = $id:ref; |] return v@@ -63,40 +64,28 @@ -- int _a[] = {0,1,2,3,4,5,6,7,8,9}; -- int * a = _a; ----- This extra pointer is not needed when using `alloca` since then the array is--- a pointer anyway. One option might be to use `alloca` for all arrays, but--- that doesn't permit defining constant arrays using a literal as above.+-- The declaration of a variable-sized array could only be done where its size+-- expression can be evaluated. This is why the declaration of variable-sized+-- arrays is done with `addItem` insted of `addLocal`: it preserves the position+-- of the declaration in the block, as it would be a statement. -- -- Pointers that are used between multiple functions will be lifted to shared globals. -- To ensure the correctness of the resulting program the underlying arrays must also -- be lifted, hence the extra `touchVar` application on their symbols. +-- | Generates the symbol name as an identifier for a given array.+newtype BaseArrOf i a = BaseArrOf (Arr i a)++instance ToIdent (BaseArrOf i a)+ where toIdent (BaseArrOf (ArrComp sym)) = toIdent $ '_':sym+ -- | Compile `ArrCMD`-compArrCMD :: CompExp exp => ArrCMD (Param3 prog exp CType) a -> CGen a-compArrCMD cmd@(NewArr base size) = do- sym <- gensym base- let sym' = '_':sym- n <- compExp size- t <- cType (proxyArg cmd)- case n of- C.Const _ _ -> do- addLocal [cdecl| $ty:t $id:sym'[ $n ]; |]- addLocal [cdecl| $ty:t * $id:sym = $id:sym'; |] -- explanation above- _ -> do- addInclude "<alloca.h>"- addLocal [cdecl| $ty:t * $id:sym; |]- addStm [cstm| $id:sym = alloca($n * sizeof($ty:t)); |]- return $ ArrComp sym-compArrCMD cmd@(InitArr base as) = do- sym <- gensym base- let sym' = '_':sym- t <- cType (proxyArg cmd)- as' <- mapM cLit as- addLocal [cdecl| $ty:t $id:sym'[] = $init:(arrayInit as');|]- addLocal [cdecl| $ty:t * $id:sym = $id:sym'; |] -- explanation above- return $ ArrComp sym-compArrCMD (GetArr expi arr) = do- v <- freshVar+compArrCMD :: forall exp ct a. (CompExp exp, CompTypeClass ct) =>+ ArrCMD (Param3 CGen exp ct) a -> CGen a+compArrCMD cmd@(NewArr base size) = compC_CMD (NewCArr base Nothing size :: C_CMD (Param3 CGen exp ct) a)+compArrCMD cmd@(InitArr base as) = compC_CMD (InitCArr base Nothing as :: C_CMD (Param3 CGen exp ct) a)+compArrCMD cmd@(GetArr expi arr) = do+ v <- freshVar (proxyPred cmd) i <- compExp expi touchVar $ BaseArrOf arr -- explanation above touchVar arr@@ -108,24 +97,28 @@ touchVar $ BaseArrOf arr -- explanation above touchVar arr addStm [cstm| $id:arr[ $i ] = $v; |]-compArrCMD cmd@(CopyArr arr1 arr2 expl) = do+compArrCMD cmd@(CopyArr (arr1,expo1) (arr2,expo2) expl) = do addInclude "<string.h>"- mapM_ touchVar [BaseArrOf arr1,BaseArrOf arr2] -- explanation above+ mapM_ touchVar [BaseArrOf arr1, BaseArrOf arr2] -- explanation above mapM_ touchVar [arr1,arr2]- l <- compExp expl- t <- cType arr1- addStm [cstm| memcpy($id:arr1, $id:arr2, $l * sizeof($ty:t)); |]+ o1 <- compExp expo1+ o2 <- compExp expo2+ l <- compExp expl+ t <- compType (proxyPred cmd) arr1+ let a1 = case o1 of+ C.Const (C.IntConst _ _ 0 _) _ -> [cexp| $id:arr1 |]+ _ -> [cexp| $id:arr1 + $o1 |]+ let a2 = case o2 of+ C.Const (C.IntConst _ _ 0 _) _ -> [cexp| $id:arr2 |]+ _ -> [cexp| $id:arr2 + $o2 |]+ addStm [cstm| memcpy($a1, $a2, $l * sizeof($ty:t)); |] compArrCMD (UnsafeFreezeArr (ArrComp arr)) = return $ IArrComp arr compArrCMD (UnsafeThawArr (IArrComp arr)) = return $ ArrComp arr --- | Generates the symbol name as an identifier for a given array.-newtype BaseArrOf i a = BaseArrOf (Arr i a)-instance ToIdent (BaseArrOf i a)- where toIdent (BaseArrOf (ArrComp sym)) = toIdent $ '_':sym - -- | Compile `ControlCMD`-compControlCMD :: CompExp exp => ControlCMD (Param3 CGen exp CType) a -> CGen a+compControlCMD :: (CompExp exp, CompTypeClass ct) =>+ ControlCMD (Param3 CGen exp ct) a -> CGen a compControlCMD (If c t f) = do cc <- compExp c ct <- inNewBlock_ t@@ -154,10 +147,10 @@ _ -> addStm [cstm| if (! $contc) {break;} |] body when (not noop) $ addStm [cstm| while (1) {$items:bodyc} |]-compControlCMD (For (lo,step,hi) body) = do+compControlCMD cmd@(For (lo,step,hi) body) = do loe <- compExp lo hie <- compExp $ borderVal hi- i <- freshVar+ i <- freshVar (proxyPred cmd) bodyc <- inNewBlock_ (body i) let incl = borderIncl hi let conte@@ -193,7 +186,8 @@ compIOMode ReadWriteMode = "r+" -- | Compile `FileCMD`-compFileCMD :: CompExp exp => FileCMD (Param3 prog exp CType) a -> CGen a+compFileCMD :: (CompExp exp, CompTypeClass ct, ct Bool) =>+ FileCMD (Param3 prog exp ct) a -> CGen a compFileCMD (FOpen path mode) = do addInclude "<stdio.h>" addInclude "<stdlib.h>"@@ -218,25 +212,59 @@ addStm [cstm| fprintf($args:as'); |] compFileCMD cmd@(FGet h) = do addInclude "<stdio.h>"- v <- freshVar+ v <- freshVar (proxyPred cmd) touchVar h let mkProxy = (\_ -> Proxy) :: FileCMD (Param3 prog exp pred) (Val a) -> Proxy a- form = formatSpecifier (mkProxy cmd)+ form = formatSpecScan (mkProxy cmd) addStm [cstm| fscanf($id:h, $string:form, &$id:v); |] return v-compFileCMD (FEof h) = do+compFileCMD cmd@(FEof h) = do addInclude "<stdbool.h>" addInclude "<stdio.h>"- v <- freshVar+ v <- freshVar (proxyPred cmd) touchVar h addStm [cstm| $id:v = feof($id:h); |] return v -compC_CMD :: CompExp exp => C_CMD (Param3 CGen exp CType) a -> CGen a+compC_CMD :: (CompExp exp, CompTypeClass ct) =>+ C_CMD (Param3 CGen exp ct) a -> CGen a+compC_CMD cmd@(NewCArr base align size) = do+ sym <- gensym base+ let sym' = '_':sym+ n <- compExp size+ t <- compType (proxyPred cmd) (proxyArg cmd)+ case n of+ C.Const _ _ -> do+ case align of+ Just a -> do+ let a' = fromIntegral a :: Int+ addLocal [cdecl| $ty:t $id:sym'[ $n ] __attribute__((aligned($a'))); |]+ _ -> addLocal [cdecl| $ty:t $id:sym'[ $n ]; |]+ addLocal [cdecl| $ty:t * $id:sym = $id:sym'; |] -- explanation at 'compArrCMD'+ _ -> do+ case align of+ Just a -> do+ let a' = fromIntegral a :: Int+ addItem [citem| $ty:t $id:sym'[ $n ] __attribute__((aligned($a'))); |]+ _ -> addItem [citem| $ty:t $id:sym'[ $n ]; |]+ addItem [citem| $ty:t * $id:sym = $id:sym'; |] -- explanation at 'compArrCMD'+ return $ ArrComp sym+compC_CMD cmd@(InitCArr base align as) = do+ sym <- gensym base+ let sym' = '_':sym+ t <- compType (proxyPred cmd) (proxyArg cmd)+ as' <- mapM (compLit (proxyPred cmd)) as+ case align of+ Just a -> do+ let a' = fromIntegral a :: Int+ addLocal [cdecl| $ty:t $id:sym'[] __attribute__((aligned($a'))) = $init:(arrayInit as'); |]+ _ -> addLocal [cdecl| $ty:t $id:sym'[] = $init:(arrayInit as');|]+ addLocal [cdecl| $ty:t * $id:sym = $id:sym'; |] -- explanation at 'compArrCMD'+ return $ ArrComp sym compC_CMD cmd@(NewPtr base) = do addInclude "<stddef.h>" p <- PtrComp <$> gensym base- t <- cType (proxyArg cmd)+ t <- compType (proxyPred cmd) (proxyArg cmd) addLocal [cdecl| $ty:t * $id:p = NULL; |] return p compC_CMD (PtrToArr (PtrComp p)) = return $ ArrComp p@@ -249,16 +277,16 @@ return o compC_CMD (AddInclude inc) = addInclude inc compC_CMD (AddDefinition def) = addGlobal def-compC_CMD (AddExternFun fun res args) = do- tres <- cType res+compC_CMD cmd@(AddExternFun fun res args) = do+ tres <- compType (proxyPred cmd) res targs <- mapM mkParam args addGlobal [cedecl| extern $ty:tres $id:fun($params:targs); |] compC_CMD (AddExternProc proc args) = do targs <- mapM mkParam args addGlobal [cedecl| extern void $id:proc($params:targs); |]-compC_CMD (CallFun fun as) = do+compC_CMD cmd@(CallFun fun as) = do as' <- mapM mkArg as- v <- freshVar+ v <- freshVar (proxyPred cmd) addStm [cstm| $id:v = $id:fun($args:as'); |] return v compC_CMD (CallProc obj fun as) = do@@ -268,10 +296,10 @@ Just o -> addStm [cstm| $id:o = $id:fun($args:as'); |] compC_CMD (InModule mod prog) = inModule mod prog -instance CompExp exp => Interp RefCMD CGen (Param2 exp CType) where interp = compRefCMD-instance CompExp exp => Interp ArrCMD CGen (Param2 exp CType) where interp = compArrCMD-instance CompExp exp => Interp ControlCMD CGen (Param2 exp CType) where interp = compControlCMD-instance Interp PtrCMD CGen (Param2 exp pred) where interp = compPtrCMD-instance CompExp exp => Interp FileCMD CGen (Param2 exp CType) where interp = compFileCMD-instance CompExp exp => Interp C_CMD CGen (Param2 exp CType) where interp = compC_CMD+instance (CompExp exp, CompTypeClass ct) => Interp RefCMD CGen (Param2 exp ct) where interp = compRefCMD+instance (CompExp exp, CompTypeClass ct) => Interp ArrCMD CGen (Param2 exp ct) where interp = compArrCMD+instance (CompExp exp, CompTypeClass ct) => Interp ControlCMD CGen (Param2 exp ct) where interp = compControlCMD+instance Interp PtrCMD CGen (Param2 exp ct) where interp = compPtrCMD+instance (CompExp exp, CompTypeClass ct, ct Bool) => Interp FileCMD CGen (Param2 exp ct) where interp = compFileCMD+instance (CompExp exp, CompTypeClass ct) => Interp C_CMD CGen (Param2 exp ct) where interp = compC_CMD
src/Language/Embedded/Imperative/CMD.hs view
@@ -22,7 +22,7 @@ , borderIncl , IxRange , ControlCMD (..)- -- * Pointers+ -- * Generic pointer manipulation , IsPointer (..) , PtrCMD (..) -- * File handling@@ -87,7 +87,7 @@ -- | Mutable reference data Ref a = RefComp VarId- | RefEval (IORef a)+ | RefRun (IORef a) deriving Typeable instance ToIdent (Ref a) where toIdent (RefComp r) = C.Id r@@ -125,7 +125,7 @@ hbimap _ f (SetRef r a) = SetRef r (f a) hbimap _ _ (UnsafeFreezeRef r) = UnsafeFreezeRef r -instance (RefCMD :<: instr) => Reexpressible RefCMD instr+instance (RefCMD :<: instr) => Reexpressible RefCMD instr env where reexpressInstrEnv reexp (NewRef base) = lift $ singleInj $ NewRef base reexpressInstrEnv reexp (InitRef base a) = lift . singleInj . InitRef base =<< reexp a@@ -150,25 +150,24 @@ -- | Mutable array data Arr i a = ArrComp VarId- | ArrEval (IORef (IOArray i a))+ | ArrRun (IORef (IOArray i a)) -- The `IORef` is needed in order to make the `IsPointer` instance deriving Typeable -- | Immutable array data IArr i a = IArrComp VarId- | IArrEval (Array i a)- -- The `IORef` is needed in order to make the `IsPointer` instance- deriving Typeable+ | IArrRun (Array i a)+ deriving (Eq, Show, Typeable) -- In a way, it's not terribly useful to have `Arr` parameterized on the index -- type, since it's required to be an integer type, and it doesn't really matter -- which integer type is used since we can always cast between them. -- -- Another option would be to remove the parameter and allow any integer type--- when indexing (and use e.g. `IOArray Word32` for evaluation). However this--- has the big downside of losing type inference. E.g. the statement--- `getArr arr 0` would be ambiguously typed.+-- when indexing (and use e.g. `IOArray Word32` for running). However this has+-- the big downside of losing type inference. E.g. the statement `getArr arr 0`+-- would be ambiguously typed. -- -- Yet another option is to hard-code a specific index type. But this would -- limit the use of arrays to specific platforms.@@ -187,7 +186,8 @@ InitArr :: (pred a, Integral i, Ix i) => String -> [a] -> ArrCMD (Param3 prog exp pred) (Arr i a) GetArr :: (pred a, Integral i, Ix i) => exp i -> Arr i a -> ArrCMD (Param3 prog exp pred) (Val a) SetArr :: (pred a, Integral i, Ix i) => exp i -> exp a -> Arr i a -> ArrCMD (Param3 prog exp pred) ()- CopyArr :: (pred a, Integral i, Ix i) => Arr i a -> Arr i a -> exp i -> ArrCMD (Param3 prog exp pred) ()+ CopyArr :: (pred a, Integral i, Ix i) => (Arr i a, exp i) -> (Arr i a, exp i) -> exp i -> ArrCMD (Param3 prog exp pred) ()+ -- The arrays are paired with their offset UnsafeFreezeArr :: (pred a, Integral i, Ix i) => Arr i a -> ArrCMD (Param3 prog exp pred) (IArr i a) UnsafeThawArr :: (pred a, Integral i, Ix i) => IArr i a -> ArrCMD (Param3 prog exp pred) (Arr i a) #if __GLASGOW_HASKELL__>=708@@ -208,23 +208,27 @@ instance HBifunctor ArrCMD where- hbimap _ f (NewArr base n) = NewArr base (f n)- hbimap _ _ (InitArr base as) = InitArr base as- hbimap _ f (GetArr i arr) = GetArr (f i) arr- hbimap _ f (SetArr i a arr) = SetArr (f i) (f a) arr- hbimap _ f (CopyArr a1 a2 l) = CopyArr a1 a2 (f l)- hbimap _ _ (UnsafeFreezeArr arr) = UnsafeFreezeArr arr- hbimap _ _ (UnsafeThawArr arr) = UnsafeThawArr arr+ hbimap _ f (NewArr base n) = NewArr base (f n)+ hbimap _ _ (InitArr base as) = InitArr base as+ hbimap _ f (GetArr i arr) = GetArr (f i) arr+ hbimap _ f (SetArr i a arr) = SetArr (f i) (f a) arr+ hbimap _ f (CopyArr (a1,o1) (a2,o2) l) = CopyArr (a1, f o1) (a2, f o2) (f l)+ hbimap _ _ (UnsafeFreezeArr arr) = UnsafeFreezeArr arr+ hbimap _ _ (UnsafeThawArr arr) = UnsafeThawArr arr -instance (ArrCMD :<: instr) => Reexpressible ArrCMD instr+instance (ArrCMD :<: instr) => Reexpressible ArrCMD instr env where reexpressInstrEnv reexp (NewArr base n) = lift . singleInj . NewArr base =<< reexp n reexpressInstrEnv reexp (InitArr base as) = lift $ singleInj $ InitArr base as reexpressInstrEnv reexp (GetArr i arr) = lift . singleInj . flip GetArr arr =<< reexp i reexpressInstrEnv reexp (SetArr i a arr) = do i' <- reexp i; a' <- reexp a; lift $ singleInj $ SetArr i' a' arr- reexpressInstrEnv reexp (CopyArr a1 a2 l) = lift . singleInj . CopyArr a1 a2 =<< reexp l reexpressInstrEnv reexp (UnsafeFreezeArr arr) = lift $ singleInj $ UnsafeFreezeArr arr reexpressInstrEnv reexp (UnsafeThawArr arr) = lift $ singleInj $ UnsafeThawArr arr+ reexpressInstrEnv reexp (CopyArr (a1,o1) (a2,o2) l) = do+ o1' <- reexp o1+ o2' <- reexp o2+ l' <- reexp l+ lift $ singleInj $ CopyArr (a1,o1') (a2,o2') l' instance DryInterp ArrCMD where@@ -295,7 +299,7 @@ hbimap _ _ Break = Break hbimap _ g (Assert cond msg) = Assert (g cond) msg -instance (ControlCMD :<: instr) => Reexpressible ControlCMD instr+instance (ControlCMD :<: instr) => Reexpressible ControlCMD instr env where reexpressInstrEnv reexp (If c thn els) = do c' <- reexp c@@ -324,7 +328,7 @@ ----------------------------------------------------------------------------------- * Pointers+-- * Generic pointer manipulation -------------------------------------------------------------------------------- -- The reason for not implementing `SwapPtr` using the `Ptr` type is that it's@@ -337,7 +341,7 @@ instance IsPointer (Arr i a) where- runSwapPtr (ArrEval arr1) (ArrEval arr2) = do+ runSwapPtr (ArrRun arr1) (ArrRun arr2) = do arr1' <- readIORef arr1 arr2' <- readIORef arr2 writeIORef arr1 arr2'@@ -350,7 +354,7 @@ instance HFunctor PtrCMD where hfmap _ (SwapPtr a b) = SwapPtr a b instance HBifunctor PtrCMD where hbimap _ _ (SwapPtr a b) = SwapPtr a b -instance (PtrCMD :<: instr) => Reexpressible PtrCMD instr+instance (PtrCMD :<: instr) => Reexpressible PtrCMD instr env where reexpressInstrEnv reexp (SwapPtr a b) = lift $ singleInj (SwapPtr a b) @@ -367,7 +371,7 @@ -- | File handle data Handle = HandleComp VarId- | HandleEval IO.Handle+ | HandleRun IO.Handle deriving Typeable instance ToIdent Handle where toIdent (HandleComp h) = C.Id h@@ -397,21 +401,36 @@ -- | Values that can be printed\/scanned using @printf@\/@scanf@ class (Typeable a, Read a, Printf.PrintfArg a) => Formattable a where- formatSpecifier :: Proxy a -> String+ -- | Format specifier for `printf`+ formatSpecPrint :: Proxy a -> String+ -- | Format specifier for `scanf`+ formatSpecScan :: Proxy a -> String+ formatSpecScan = formatSpecPrint -instance Formattable Int where formatSpecifier _ = "%d"-instance Formattable Int8 where formatSpecifier _ = "%d"-instance Formattable Int16 where formatSpecifier _ = "%d"-instance Formattable Int32 where formatSpecifier _ = "%d"-instance Formattable Int64 where formatSpecifier _ = "%d"-instance Formattable Word where formatSpecifier _ = "%u"-instance Formattable Word8 where formatSpecifier _ = "%u"-instance Formattable Word16 where formatSpecifier _ = "%u"-instance Formattable Word32 where formatSpecifier _ = "%u"-instance Formattable Word64 where formatSpecifier _ = "%u"-instance Formattable Float where formatSpecifier _ = "%f"-instance Formattable Double where formatSpecifier _ = "%f"+instance Formattable Int where formatSpecPrint _ = "%d"+instance Formattable Int8 where formatSpecPrint _ = "%hhd"+instance Formattable Int16 where formatSpecPrint _ = "%hd"+instance Formattable Int32 where formatSpecPrint _ = "%d"+instance Formattable Int64 where formatSpecPrint _ = "%ld"+instance Formattable Word where formatSpecPrint _ = "%u"+instance Formattable Word8 where formatSpecPrint _ = "%hhu"+instance Formattable Word16 where formatSpecPrint _ = "%hu"+instance Formattable Word32 where formatSpecPrint _ = "%u"+instance Formattable Word64 where formatSpecPrint _ = "%lu" +instance Formattable Float+ where+ formatSpecPrint _ = "%.9g"+ -- See <http://stackoverflow.com/a/21162120/1105347>+ formatSpecScan _ = "%g"++instance Formattable Double+ where+ formatSpecPrint _ = "%.17g"+ -- See <http://stackoverflow.com/a/21162120/1105347>+ formatSpecScan _ = "%lg"+ -- See <http://stackoverflow.com/q/210590/1105347>+ data FileCMD fs a where FOpen :: FilePath -> IOMode -> FileCMD (Param3 prog exp pred) Handle@@ -436,7 +455,7 @@ hbimap _ _ (FGet hdl) = FGet hdl hbimap _ _ (FEof hdl) = FEof hdl -instance (FileCMD :<: instr) => Reexpressible FileCMD instr+instance (FileCMD :<: instr) => Reexpressible FileCMD instr env where reexpressInstrEnv reexp (FOpen file mode) = lift $ singleInj $ FOpen file mode reexpressInstrEnv reexp (FClose h) = lift $ singleInj $ FClose h@@ -460,7 +479,7 @@ -- | Pointer newtype Ptr (a :: *) = PtrComp {ptrId :: VarId}- deriving Typeable+ deriving (Eq, Show, Typeable) instance ToIdent (Ptr a) where toIdent = C.Id . ptrId @@ -481,12 +500,13 @@ data FunArg exp pred where- ValArg :: pred a => exp a -> FunArg exp pred- AddrArg :: FunArg exp pred -> FunArg exp pred- DerefArg :: FunArg exp pred -> FunArg exp pred- FunArg :: Arg arg pred => arg pred -> FunArg exp pred+ ValArg :: pred a => exp a -> FunArg exp pred+ AddrArg :: FunArg exp pred -> FunArg exp pred+ DerefArg :: FunArg exp pred -> FunArg exp pred+ OffsetArg :: FunArg exp pred -> exp i -> FunArg exp pred+ FunArg :: Arg arg pred => arg pred -> FunArg exp pred -instance CompExp exp => Arg (FunArg exp) CType+instance (CompExp exp, CompTypeClass ct) => Arg (FunArg exp) ct where mkArg (ValArg a) = compExp a mkArg (AddrArg arg) = do@@ -495,10 +515,17 @@ mkArg (DerefArg arg) = do e <- mkArg arg return [cexp| *$e |]+ mkArg (OffsetArg arg i) = do+ e <- mkArg arg+ i' <- compExp i+ return $ case i' of+ (C.Const (C.IntConst _ _ 0 _) _) -> e+ (C.Const (C.IntConst _ _ c _) _) | c < 0 -> [cexp| $e - $(negate c) |]+ _ -> [cexp| $e + $i' |] mkArg (FunArg a) = mkArg a mkParam (ValArg (a :: exp a)) = do- t <- cType (Proxy :: Proxy a)+ t <- compType (Proxy :: Proxy ct) (Proxy :: Proxy a) return [cparam| $ty:t |] mkParam (AddrArg arg) = do p <- mkParam arg@@ -511,23 +538,26 @@ C.Param mid spec (C.Ptr [] decl _) loc -> return $ C.Param mid spec decl loc C.Param _ _ _ _ -> error "mkParam for Deref: cannot dereference non-pointer parameter" _ -> error "mkParam for Deref: cannot deal with antiquotes"- mkParam (FunArg a) = mkParam a+ mkParam (OffsetArg a _) = mkParam a+ mkParam (FunArg a) = mkParam a mapFunArg :: (forall a . exp1 a -> exp2 a) -> FunArg exp1 pred -> FunArg exp2 pred-mapFunArg f (ValArg a) = ValArg (f a)-mapFunArg f (AddrArg a) = AddrArg $ mapFunArg f a-mapFunArg f (DerefArg a) = DerefArg $ mapFunArg f a-mapFunArg f (FunArg a) = FunArg a+mapFunArg f (ValArg a) = ValArg (f a)+mapFunArg f (AddrArg a) = AddrArg $ mapFunArg f a+mapFunArg f (OffsetArg a i) = OffsetArg (mapFunArg f a) (f i)+mapFunArg f (DerefArg a) = DerefArg $ mapFunArg f a+mapFunArg f (FunArg a) = FunArg a mapFunArgM :: Monad m => (forall a . exp1 a -> m (exp2 a)) -> FunArg exp1 pred -> m (FunArg exp2 pred)-mapFunArgM f (ValArg a) = liftM ValArg (f a)-mapFunArgM f (AddrArg a) = liftM AddrArg $ mapFunArgM f a-mapFunArgM f (DerefArg a) = liftM DerefArg $ mapFunArgM f a-mapFunArgM f (FunArg a) = return (FunArg a)+mapFunArgM f (ValArg a) = liftM ValArg (f a)+mapFunArgM f (AddrArg a) = liftM AddrArg $ mapFunArgM f a+mapFunArgM f (OffsetArg a i) = do a' <- mapFunArgM f a; i' <- f i; return $ OffsetArg a' i'+mapFunArgM f (DerefArg a) = liftM DerefArg $ mapFunArgM f a+mapFunArgM f (FunArg a) = return (FunArg a) class ToIdent obj => Assignable obj @@ -539,6 +569,8 @@ data C_CMD fs a where+ NewCArr :: (pred a, Integral i, Ix i) => String -> Maybe i -> exp i -> C_CMD (Param3 prog exp pred) (Arr i a)+ InitCArr :: (pred a, Integral i, Ix i) => String -> Maybe i -> [a] -> C_CMD (Param3 prog exp pred) (Arr i a) NewPtr :: pred a => String -> C_CMD (Param3 prog exp pred) (Ptr a) PtrToArr :: Ptr a -> C_CMD (Param3 prog exp pred) (Arr i a) NewObject@@ -556,6 +588,8 @@ instance HFunctor C_CMD where+ hfmap _ (NewCArr base al n) = NewCArr base al n+ hfmap _ (InitCArr base al as) = InitCArr base al as hfmap _ (NewPtr base) = NewPtr base hfmap _ (PtrToArr p) = PtrToArr p hfmap _ (NewObject base p t) = NewObject base p t@@ -569,6 +603,8 @@ instance HBifunctor C_CMD where+ hbimap _ f (NewCArr base al n) = NewCArr base al (f n)+ hbimap _ _ (InitCArr base al as) = InitCArr base al as hbimap _ _ (NewPtr base) = NewPtr base hbimap _ _ (PtrToArr p) = PtrToArr p hbimap _ _ (NewObject base p t) = NewObject base p t@@ -580,8 +616,10 @@ hbimap _ f (CallProc obj proc args) = CallProc obj proc (map (mapFunArg f) args) hbimap f _ (InModule mod prog) = InModule mod (f prog) -instance (C_CMD :<: instr) => Reexpressible C_CMD instr+instance (C_CMD :<: instr) => Reexpressible C_CMD instr env where+ reexpressInstrEnv reexp (NewCArr base al n) = lift . singleInj . NewCArr base al =<< reexp n+ reexpressInstrEnv reexp (InitCArr base al as) = lift $ singleInj $ InitCArr base al as reexpressInstrEnv reexp (NewPtr base) = lift $ singleInj $ NewPtr base reexpressInstrEnv reexp (PtrToArr p) = lift $ singleInj $ PtrToArr p reexpressInstrEnv reexp (NewObject base p t) = lift $ singleInj $ NewObject base p t@@ -595,6 +633,8 @@ instance DryInterp C_CMD where+ dryInterp (NewCArr base _ _) = liftM ArrComp $ freshStr base+ dryInterp (InitCArr base _ _) = liftM ArrComp $ freshStr base dryInterp (NewPtr base) = liftM PtrComp $ freshStr base dryInterp (PtrToArr (PtrComp p)) = return $ ArrComp p dryInterp (NewObject base t p) = liftM (Object p t) $ freshStr base@@ -613,19 +653,20 @@ -------------------------------------------------------------------------------- runRefCMD :: RefCMD (Param3 IO IO pred) a -> IO a-runRefCMD (NewRef _) = fmap RefEval $ newIORef $ error "reading uninitialized reference"-runRefCMD (InitRef _ a) = fmap RefEval . newIORef =<< a-runRefCMD (SetRef (RefEval r) a) = writeIORef r =<< a-runRefCMD (GetRef (RefEval r)) = ValEval <$> readIORef r+runRefCMD (NewRef _) = fmap RefRun $ newIORef $ error "reading uninitialized reference"+runRefCMD (InitRef _ a) = fmap RefRun . newIORef =<< a+runRefCMD (SetRef (RefRun r) a) = writeIORef r =<< a+runRefCMD (GetRef (RefRun r)) = ValRun <$> readIORef r runRefCMD cmd@(UnsafeFreezeRef r) = runRefCMD (GetRef r `asTypeOf` cmd) runArrCMD :: ArrCMD (Param3 IO IO pred) a -> IO a runArrCMD (NewArr _ n) = do n' <- n arr <- newArray_ (0, fromIntegral n'-1)- ArrEval <$> newIORef arr-runArrCMD (InitArr _ as) = fmap ArrEval . newIORef =<< newListArray (0, genericLength as - 1) as-runArrCMD (GetArr i (ArrEval arr)) = do+ ArrRun <$> newIORef arr+runArrCMD (InitArr _ as) =+ fmap ArrRun . newIORef =<< newListArray (0, genericLength as - 1) as+runArrCMD (GetArr i (ArrRun arr)) = do arr' <- readIORef arr i' <- i (l,h) <- getBounds arr'@@ -634,8 +675,8 @@ ++ show (toInteger i') ++ " out of bounds " ++ show (toInteger l, toInteger h)- else ValEval <$> readArray arr' i'-runArrCMD (SetArr i a (ArrEval arr)) = do+ else ValRun <$> readArray arr' i'+runArrCMD (SetArr i a (ArrRun arr)) = do arr' <- readIORef arr i' <- i a' <- a@@ -646,30 +687,38 @@ ++ " out of bounds " ++ show (toInteger l, toInteger h) else writeArray arr' (fromIntegral i') a'-runArrCMD (CopyArr (ArrEval arr1) (ArrEval arr2) l) = do+runArrCMD (CopyArr (ArrRun arr1, o1) (ArrRun arr2, o2) l) = do arr1' <- readIORef arr1 arr2' <- readIORef arr2+ o1' <- o1+ o2' <- o2 l' <- l (0,h1) <- getBounds arr1' (0,h2) <- getBounds arr2'- if l'>h2+1+ let l1 = h1+1-o1'+ l2 = h2+1-o2'+ if l'>l2 then error $ "copyArr: cannot copy " ++ show (toInteger l') ++ " elements from array with "- ++ show (toInteger (h2+1))+ ++ show (toInteger l2) ++ " allocated elements"- else if l'>h1+1+ else if l'>l1 then error $ "copyArr: cannot copy " ++ show (toInteger l') ++ " elements to array with "- ++ show (toInteger (h1+1))+ ++ show (toInteger l1) ++ " allocated elements" else sequence_- [ readArray arr2' i >>= writeArray arr1' i | i <- genericTake l' [0..] ]-runArrCMD (UnsafeFreezeArr (ArrEval arr)) =- fmap IArrEval . freeze =<< readIORef arr-runArrCMD (UnsafeThawArr (IArrEval arr)) =- fmap ArrEval . newIORef =<< thaw arr+ [ readArray arr2' (i+o2') >>= writeArray arr1' (i+o1')+ | i <- genericTake l' [0..]+ ]+runArrCMD (UnsafeFreezeArr (ArrRun arr)) =+ fmap IArrRun . freeze =<< readIORef arr+runArrCMD (UnsafeThawArr (IArrRun arr)) =+ fmap ArrRun . newIORef =<< thaw arr+ -- Could use `unsafeFreeze` and `unsafeThaw` here. The downside would be that+ -- incorrect use could lead to crash of the Haskell runtime (I think). runControlCMD :: ControlCMD (Param3 IO IO pred) a -> IO a runControlCMD (If c t f) = c >>= \c' -> if c' then t else f@@ -689,7 +738,7 @@ | step >= 0 = i < h | step < 0 = i > h loop i h- | cont i h = body (ValEval i) >> loop (i + fromIntegral step) h+ | cont i h = body (ValRun i) >> loop (i + fromIntegral step) h | otherwise = return () runControlCMD Break = error "cannot run programs involving break" runControlCMD (Assert cond msg) = do@@ -699,10 +748,10 @@ runPtrCMD :: PtrCMD (Param3 IO IO pred) a -> IO a runPtrCMD (SwapPtr a b) = runSwapPtr a b -evalHandle :: Handle -> IO.Handle-evalHandle (HandleEval h) = h-evalHandle (HandleComp "stdin") = IO.stdin-evalHandle (HandleComp "stdout") = IO.stdout+runHandle :: Handle -> IO.Handle+runHandle (HandleRun h) = h+runHandle (HandleComp "stdin") = IO.stdin+runHandle (HandleComp "stdout") = IO.stdout readWord :: IO.Handle -> IO String readWord h = do@@ -722,19 +771,21 @@ runFPrintf (PrintfArg a:as) pf = a >>= \a' -> runFPrintf as (pf a') runFileCMD :: FileCMD (Param3 IO IO pred) a -> IO a-runFileCMD (FOpen file mode) = HandleEval <$> IO.openFile file mode-runFileCMD (FClose (HandleEval h)) = IO.hClose h+runFileCMD (FOpen file mode) = HandleRun <$> IO.openFile file mode+runFileCMD (FClose (HandleRun h)) = IO.hClose h runFileCMD (FClose (HandleComp "stdin")) = return () runFileCMD (FClose (HandleComp "stdout")) = return ()-runFileCMD (FPrintf h format as) = runFPrintf as (Printf.hPrintf (evalHandle h) format)+runFileCMD (FPrintf h format as) = runFPrintf as (Printf.hPrintf (runHandle h) format) runFileCMD (FGet h) = do- w <- readWord $ evalHandle h+ w <- readWord $ runHandle h case reads w of- [(f,"")] -> return $ ValEval f+ [(f,"")] -> return $ ValRun f _ -> error $ "fget: no parse (input " ++ show w ++ ")"-runFileCMD (FEof h) = fmap ValEval $ IO.hIsEOF $ evalHandle h+runFileCMD (FEof h) = fmap ValRun $ IO.hIsEOF $ runHandle h -runC_CMD :: C_CMD (Param3 IO IO pred) a -> IO a+runC_CMD :: forall pred a. C_CMD (Param3 IO IO pred) a -> IO a+runC_CMD (NewCArr base _ n) = runArrCMD (NewArr base n :: ArrCMD (Param3 IO IO pred) a)+runC_CMD (InitCArr base _ as) = runArrCMD (InitArr base as :: ArrCMD (Param3 IO IO pred) a) runC_CMD (NewPtr base) = error $ "cannot run programs involving newPtr (base name " ++ base ++ ")" runC_CMD (PtrToArr p) = error "cannot run programs involving ptrToArr" runC_CMD (NewObject base _ _) = error $ "cannot run programs involving newObject (base name " ++ base ++ ")"
src/Language/Embedded/Imperative/Frontend.hs view
@@ -59,7 +59,7 @@ initNamedRef base a = singleInj (InitRef base a) -- | Get the contents of a reference-getRef :: (pred a, FreeExp exp, VarPred exp a, RefCMD :<: instr, Monad m) =>+getRef :: (pred a, FreeExp exp, FreePred exp a, RefCMD :<: instr, Monad m) => Ref a -> ProgramT instr (Param2 exp pred) m (exp a) getRef = fmap valToExp . singleInj . GetRef @@ -69,14 +69,14 @@ setRef r = singleInj . SetRef r -- | Modify the contents of reference-modifyRef :: (pred a, FreeExp exp, VarPred exp a, RefCMD :<: instr, Monad m) =>+modifyRef :: (pred a, FreeExp exp, FreePred exp a, RefCMD :<: instr, Monad m) => Ref a -> (exp a -> exp a) -> ProgramT instr (Param2 exp pred) m () modifyRef r f = setRef r . f =<< unsafeFreezeRef r -- | Freeze the contents of reference (only safe if the reference is not updated -- as long as the resulting value is alive) unsafeFreezeRef- :: (pred a, FreeExp exp, VarPred exp a, RefCMD :<: instr, Monad m)+ :: (pred a, FreeExp exp, FreePred exp a, RefCMD :<: instr, Monad m) => Ref a -> ProgramT instr (Param2 exp pred) m (exp a) unsafeFreezeRef = fmap valToExp . singleInj . UnsafeFreezeRef @@ -86,11 +86,11 @@ -- It is almost always better to use 'unsafeFreezeRef' instead. -- -- 'veryUnsafeFreezeRef' behaves predictably when doing code generation, but it--- can give strange results when evaluating in 'IO', as explained here:+-- can give strange results when running in 'IO', as explained here: -- -- <http://fun-discoveries.blogspot.se/2015/09/strictness-can-fix-non-termination.html>-veryUnsafeFreezeRef :: (FreeExp exp, VarPred exp a) => Ref a -> exp a-veryUnsafeFreezeRef (RefEval r) = valExp $! unsafePerformIO $! readIORef r+veryUnsafeFreezeRef :: (FreeExp exp, FreePred exp a) => Ref a -> exp a+veryUnsafeFreezeRef (RefRun r) = constExp $! unsafePerformIO $! readIORef r veryUnsafeFreezeRef (RefComp v) = varExp v @@ -135,7 +135,7 @@ getArr :: ( pred a , FreeExp exp- , VarPred exp a+ , FreePred exp a , Integral i , Ix i , ArrCMD :<: instr@@ -153,21 +153,21 @@ -- copy must not be greater than the number of allocated elements in either -- array. copyArr :: (pred a, Integral i, Ix i, ArrCMD :<: instr)- => Arr i a -- ^ Destination- -> Arr i a -- ^ Source- -> exp i -- ^ Number of elements+ => (Arr i a, exp i) -- ^ (destination,offset)+ -> (Arr i a, exp i) -- ^ (source,offset+ -> exp i -- ^ Number of elements -> ProgramT instr (Param2 exp pred) m () copyArr arr1 arr2 len = singleInj $ CopyArr arr1 arr2 len -- | Freeze a mutable array to an immutable one. This involves copying the array -- to a newly allocated one.-freezeArr :: (pred a, Integral i, Ix i, ArrCMD :<: instr, Monad m)+freezeArr :: (pred a, Integral i, Ix i, Num (exp i), ArrCMD :<: instr, Monad m) => Arr i a -> exp i -- ^ Length of new array -> ProgramT instr (Param2 exp pred) m (IArr i a) freezeArr arr n = do arr2 <- newArr n- copyArr arr2 arr n+ copyArr (arr2,0) (arr,0) n unsafeFreezeArr arr2 -- | Freeze a mutable array to an immutable one without making a copy. This is@@ -179,14 +179,14 @@ -- | Thaw an immutable array to a mutable one. This involves copying the array -- to a newly allocated one.-thawArr :: (pred a, Integral i, Ix i, ArrCMD :<: instr, Monad m)+thawArr :: (pred a, Integral i, Ix i, Num (exp i), ArrCMD :<: instr, Monad m) => IArr i a -> exp i -- ^ Number of elements to copy -> ProgramT instr (Param2 exp pred) m (Arr i a) thawArr arr n = do arr2 <- unsafeThawArr arr arr3 <- newArr n- copyArr arr3 arr2 n+ copyArr (arr3,0) (arr2,0) n return arr3 -- | Thaw an immutable array to a mutable one without making a copy. This is@@ -219,7 +219,7 @@ ifE :: ( pred a , FreeExp exp- , VarPred exp a+ , FreePred exp a , ControlCMD :<: instr , RefCMD :<: instr , Monad m@@ -246,7 +246,7 @@ , ControlCMD :<: instr , Integral n , pred n- , VarPred exp n+ , FreePred exp n ) => IxRange (exp n) -- ^ Index range -> (exp n -> ProgramT instr (Param2 exp pred) m ()) -- ^ Loop body@@ -297,7 +297,7 @@ fclose = singleInj . FClose -- | Check for end of file-feof :: (FreeExp exp, VarPred exp Bool, FileCMD :<: instr, Monad m) =>+feof :: (FreeExp exp, FreePred exp Bool, FileCMD :<: instr, Monad m) => Handle -> ProgramT instr (Param2 exp pred) m (exp Bool) feof = fmap valToExp . singleInj . FEof @@ -324,21 +324,21 @@ -- | Put a single value to a handle fput :: forall instr exp pred a m- . (Formattable a, VarPred exp a, FileCMD :<: instr)+ . (Formattable a, FreePred exp a, FileCMD :<: instr) => Handle -> String -- ^ Prefix -> exp a -- ^ Expression to print -> String -- ^ Suffix -> ProgramT instr (Param2 exp pred) m () fput hdl prefix a suffix =- fprintf hdl (prefix ++ formatSpecifier (Proxy :: Proxy a) ++ suffix) a+ fprintf hdl (prefix ++ formatSpecPrint (Proxy :: Proxy a) ++ suffix) a -- | Get a single value from a handle fget :: ( Formattable a , pred a , FreeExp exp- , VarPred exp a+ , FreePred exp a , FileCMD :<: instr , Monad m )@@ -392,13 +392,6 @@ -> ProgramT instr (Param2 exp pred) m Object newNamedObject base t p = singleInj $ NewObject base t p --- | Generate code into another translation unit-inModule :: (C_CMD :<: instr)- => String- -> ProgramT instr (Param2 exp pred) m ()- -> ProgramT instr (Param2 exp pred) m ()-inModule mod prog = singleInj $ InModule mod prog- -- | Add an @#include@ statement to the generated code addInclude :: (C_CMD :<: instr) => String -> ProgramT instr (Param2 exp pred) m () addInclude = singleInj . AddInclude@@ -443,7 +436,7 @@ addExternProc proc args = singleInj $ AddExternProc proc args -- | Call a function-callFun :: (pred a, FreeExp exp, VarPred exp a, C_CMD :<: instr, Monad m)+callFun :: (pred a, FreeExp exp, FreePred exp a, C_CMD :<: instr, Monad m) => String -- ^ Function name -> [FunArg exp pred] -- ^ Arguments -> ProgramT instr (Param2 exp pred) m (exp a)@@ -469,7 +462,7 @@ -- | Declare and call an external function externFun :: forall instr m exp pred res- . (pred res, FreeExp exp, VarPred exp res, C_CMD :<: instr, Monad m)+ . (pred res, FreeExp exp, FreePred exp res, C_CMD :<: instr, Monad m) => String -- ^ Function name -> [FunArg exp pred] -- ^ Arguments -> ProgramT instr (Param2 exp pred) m (exp res)@@ -486,9 +479,16 @@ addExternProc proc args callProc proc args +-- | Generate code into another translation unit+inModule :: (C_CMD :<: instr)+ => String+ -> ProgramT instr (Param2 exp pred) m ()+ -> ProgramT instr (Param2 exp pred) m ()+inModule mod prog = singleInj $ InModule mod prog+ -- | Get current time as number of seconds passed today getTime- :: (pred Double, FreeExp exp, VarPred exp Double, C_CMD :<: instr, Monad m)+ :: (pred Double, FreeExp exp, FreePred exp Double, C_CMD :<: instr, Monad m) => ProgramT instr (Param2 exp pred) m (exp Double) getTime = do addInclude "<sys/time.h>"@@ -537,6 +537,13 @@ strArg :: String -> FunArg exp pred strArg = FunArg . StrArg +-- | Named constant argument+constArg+ :: String -- ^ Type+ -> String -- ^ Named constant+ -> FunArg exp pred+constArg t n = FunArg $ ConstArg t n+ -- | Modifier that takes the address of another argument addr :: FunArg exp pred -> FunArg exp pred addr = AddrArg@@ -544,6 +551,12 @@ -- | Modifier that dereferences another argument deref :: FunArg exp pred -> FunArg exp pred deref = DerefArg++-- | Add an offset to another argument+offset :: Integral i => FunArg exp pred -> exp i -> FunArg exp pred+offset = OffsetArg+ -- The `Integral` constraint isn't needed, but it makes sense, since the+ -- intention of `offset` is to add an offset to a pointer.
src/Language/Embedded/Imperative/Frontend/General.hs view
@@ -32,5 +32,5 @@ import Language.Embedded.Imperative.CMD import Language.C.Syntax-import Language.C.Quote.C+import Language.C.Quote.GCC
src/Language/Embedded/Signature.hs view
@@ -19,7 +19,7 @@ -- | Signature annotations data Ann exp a where Empty :: Ann exp a- Native :: (VarPred exp a) => exp len -> Ann exp [a]+ Native :: (FreePred exp a) => exp len -> Ann exp [a] Named :: String -> Ann exp a -- | Signatures@@ -32,11 +32,11 @@ -- * Combinators -lam :: (pred a, FreeExp exp, VarPred exp a)+lam :: (pred a, FreeExp exp, FreePred exp a) => (exp a -> Signature exp pred b) -> Signature exp pred (a -> b) lam f = Lam Empty $ \x -> f (valToExp x) -name :: (pred a, FreeExp exp, VarPred exp a)+name :: (pred a, FreeExp exp, FreePred exp a) => String -> (exp a -> Signature exp pred b) -> Signature exp pred (a -> b) name s f = Lam (Named s) $ \x -> f (valToExp x) @@ -45,7 +45,7 @@ ret = Ret ptr = Ptr -arg :: (pred a, FreeExp exp, VarPred exp a)+arg :: (pred a, FreeExp exp, FreePred exp a) => Ann exp a -> (exp a -> exp b) -> (exp b -> Signature exp pred c)@@ -77,7 +77,7 @@ addStm [cstm| *out = $e; |] go fun@(Lam Empty f) prelude = do t <- cType (argProxy fun)- v <- freshVar+ v <- freshVar (Proxy :: Proxy CType) go (f v) $ prelude >> addParam [cparam| $ty:t $id:v |] go fun@(Lam n@(Native l) f) prelude = do t <- cType n
tests/CExp.hs view
@@ -13,11 +13,7 @@ import Test.Tasty.TH import Language.Syntactic (AST (..), DenResult)-#if MIN_VERSION_syntactic(3,0,0) import Language.Syntactic.Functional (Denotation)-#else-import Language.Syntactic (Denotation)-#endif import Language.Embedded.Imperative import Language.Embedded.Backend.C
tests/Imperative.hs view
@@ -10,6 +10,10 @@ import Data.Int import Data.Word+import System.Directory+import System.FilePath+import System.Process+import System.Random import Language.Embedded.Imperative import Language.Embedded.Backend.C@@ -59,8 +63,7 @@ testCExp = do a :: CExp Int32 <- fget stdin let b = a#==10 ? a*3 $ a-5+8- let c = sin (i2n a) :: CExp Double- let d = c/23+ let c = i2n a/23 :: CExp Double printf "%d " b printf "%d " (not_ (a#==10) ? a*3 $ a-5+8) printf "%d " (a `quot_` b)@@ -68,12 +71,7 @@ printf "%d " (cond (i2b a) a b) printf "%d " (b2i (not_ (a#==10)) * a) printf "%.3f " c- printf "%.3f " d printf "%.3f " (i2n a :: CExp Float)- printf "%ld " (round_ (c*1000) :: CExp Int32)- printf "%d " (round_ (11.5 :: CExp Float) :: CExp Int32)- printf "%d " (round_ (-11.5 :: CExp Float) :: CExp Int32)- printf "%.3f " (c**d) testRef :: Prog () testRef = do@@ -85,15 +83,24 @@ b <- unsafeFreezeRef r2 printf "%d %d\n" a b -testArr1 :: Prog ()-testArr1 = do+testCopyArr1 :: Prog ()+testCopyArr1 = do arr1 :: Arr Word32 Int32 <- newArr (10 :: CExp Word32) arr2 :: Arr Word32 Int32 <- newArr (10 :: CExp Word32) sequence_ [setArr i (i2n i+10) arr1 | i' <- [0..9], let i = fromInteger i']- copyArr arr2 arr1 10+ copyArr (arr2,0) (arr1,0) 10 sequence_ [getArr i arr2 >>= printf "%d " . (*3) | i' <- [0..9], let i = fromInteger i'] printf "\n" +testCopyArr2 :: Prog ()+testCopyArr2 = do+ arr1 :: Arr Word32 Int32 <- newArr (20 :: CExp Word32)+ arr2 :: Arr Word32 Int32 <- newArr (20 :: CExp Word32)+ sequence_ [setArr i (i2n i+10) arr1 | i' <- [0..19], let i = fromInteger i']+ copyArr (arr2,10) (arr1,5) 10+ sequence_ [getArr i arr2 >>= printf "%d " . (*3) | i' <- [10..19], let i = fromInteger i']+ printf "\n"+ testArr2 :: Prog () testArr2 = do n <- fget stdin@@ -153,7 +160,7 @@ arr1 :: Arr Word32 Int32 <- initArr [1,2,3,4] n <- fget stdin arr2 :: Arr Word32 Int32 <- newArr n- copyArr arr2 arr1 4+ copyArr (arr2,0) (arr1,0) 4 setArr 2 22 arr2 unsafeSwap arr1 arr2 sequence_ [getArr i arr1 >>= printf "%d " | i <- map fromInteger [0..3]]@@ -202,6 +209,12 @@ assert (inp #> 0) "input too small" printf "past assertion\n" +-- This tests that `formatSpecifier` works as it should for different types+testPrintScan :: (Formattable a, CType a) => CExp a -> Prog ()+testPrintScan a = do+ i <- fget stdin+ fput stdout "" (i `asTypeOf` a) ""+ testPtr :: Prog () testPtr = do addInclude "<stdlib.h>"@@ -219,6 +232,7 @@ testArgs :: Prog () testArgs = do addInclude "<stdio.h>"+ addInclude "<stdbool.h>" addDefinition setPtr_def addDefinition ret_def let v = 55 :: CExp Int32@@ -232,14 +246,17 @@ callProcAssign o "ret" [valArg v] callProcAssign op "setPtr" [refArg r] callProc "printf"- [ strArg "%d %d %d %d %d %d %d\n"+ [ strArg "%d %d %d %d %d %d %d %d %d %d\n" , valArg v , deref (refArg r) , deref (arrArg a) , deref (iarrArg ia) , deref (ptrArg p)+ , deref (offset (iarrArg ia) (3 :: CExp Word32))+ , deref (offset (ptrArg p) (0 :: CExp Word32)) , objArg o , deref (objArg op)+ , constArg "bool" "true" ] where setPtr_def = [cedecl|@@ -255,8 +272,12 @@ testExternArgs :: Prog () testExternArgs = do+ addInclude "<stdbool.h>" let v = 55 :: CExp Int32- externProc "val_proc" [valArg v]+ externProc "val_proc1" [valArg v]+ externProc "val_proc2" [offset3 $ valArg v]+ -- Normal integer addition (slight misuse of `offset`)+ _ :: CExp Int32 <- externFun "val_fun" [valArg v] r <- initRef v externProc "ref_proc1" [refArg r] externProc "ref_proc2" [deref $ refArg r] -- TODO Simplify@@ -264,6 +285,9 @@ externProc "arr_proc1" [arrArg a] externProc "arr_proc2" [addr $ arrArg a] externProc "arr_proc3" [deref $ arrArg a]+ externProc "arr_proc4" [offset3 $ arrArg a]+ externProc "arr_proc5" [deref $ offset3 $ arrArg a]+ externProc "arr_proc6" [offsetMinus $ arrArg a] p :: Ptr Int32 <- newPtr externProc "ptr_proc1" [ptrArg p] externProc "ptr_proc2" [addr $ ptrArg p]@@ -275,13 +299,57 @@ externProc "obj_proc3" [objArg op] externProc "obj_proc4" [addr $ objArg op] externProc "obj_proc5" [deref $ objArg op]+ externProc "obj_proc6" [offset3 $ objArg op] let s = "apa"- externProc "str_proc1" [strArg s]- externProc "str_proc2" [deref $ strArg s]+ externProc "str_proc1" [strArg s]+ externProc "str_proc2" [deref $ strArg s]+ externProc "const_proc" [constArg "bool" "true"] return ()+ where+ offset3 = flip offset (3 :: CExp Int32)+ offsetMinus = flip offset (-3 :: CExp Int32) . offset3 +testCallFun :: Prog ()+testCallFun = do+ addInclude "<math.h>"+ i :: CExp Int32 <- fget stdin+ a <- callFun "sin" [valArg (i2n i :: CExp Double)]+ printf "%.3f\n" (a :: CExp Double) +multiModule :: Prog ()+multiModule = do+ addInclude "<stdlib.h>"+ addExternProc "func_in_other" []+ inModule "other" $ do+ addDefinition [cedecl|+ void func_in_other(void) {+ puts("Hello from the other module!");+ } |]+ addInclude "<stdio.h>"+ callProc "func_in_other" [] +testMultiModule :: IO ()+testMultiModule = do+ tmp <- getTemporaryDirectory+ rand <- randomRIO (1, maxBound :: Int)+ let temp = tmp </> "imperative-edsl_" ++ show rand+ exists <- doesDirectoryExist temp+ when exists $ removeDirectoryRecursive temp+ createDirectory temp+ let ms = compileAll multiModule+ files = [temp </> "imperative-edsl_" ++ m ++ ".c" | (m,_) <- ms]+ exe = temp </> "imperative-edsl"+ cmd = unwords $ ("cc -o" : exe : files)+ zipWithM_ writeFile files (map snd ms)+ putStrLn cmd+ system cmd+ putStrLn exe+ system exe+ exists <- doesDirectoryExist temp+ when exists $ removeDirectoryRecursive temp+++ ---------------------------------------- -- It would be nice to be able to run these tests using Tests.Tasty.HUnit, but@@ -290,30 +358,57 @@ -- secondly, the tests would always fail when running a second time. testAll = do- tag "testTypes" >> compareCompiled testTypes (runIO testTypes) "0\n"- tag "testCExp" >> compareCompiledM testCExp (runIO testCExp) "44\n"- tag "testRef" >> compareCompiled testRef (runIO testRef) ""- tag "testArr1" >> compareCompiled testArr1 (runIO testArr1) ""- tag "testArr2" >> compareCompiled testArr2 (runIO testArr2) "20\n"- tag "testArr3" >> compareCompiled testArr3 (runIO testArr3) ""- tag "testArr4" >> compareCompiled testArr4 (runIO testArr4) ""- tag "testArr5" >> compareCompiled testArr5 (runIO testArr5) ""- tag "testArr6" >> compareCompiled testArr6 (runIO testArr6) ""- tag "testArr7" >> compareCompiled testArr7 (runIO testArr6) ""- tag "testArr7" >> compareCompiled testArr7 (runIO testArr7) ""- tag "testSwap1" >> compareCompiled testSwap1 (runIO testSwap1) ""- tag "testSwap2" >> compareCompiled testSwap2 (runIO testSwap2) "45\n"- tag "testIf1" >> compareCompiled testIf1 (runIO testIf1) "12\n"- tag "testIf2" >> compareCompiled testIf2 (runIO testIf2) "12\n"- tag "testFor1" >> compareCompiled testFor1 (runIO testFor1) ""- tag "testFor2" >> compareCompiled testFor2 (runIO testFor2) ""- tag "testFor3" >> compareCompiled testFor3 (runIO testFor3) ""- tag "testAssert" >> compareCompiled testAssert (runIO testAssert) "45"- tag "testPtr" >> compareCompiled testPtr (putStrLn "34" >> putStrLn "sum: 280") ""- tag "testArgs" >> compareCompiled testArgs (putStrLn "55 66 234 234 66 55 66") ""- tag "testExternArgs" >> compileAndCheck testExternArgs+ tag "testTypes" >> compareCompiled testTypes (runIO testTypes) "0\n"+ tag "testCExp" >> compareCompiledM testCExp (runIO testCExp) "44\n"+ tag "testRef" >> compareCompiled testRef (runIO testRef) ""+ tag "testCopyArr1" >> compareCompiled testCopyArr1 (runIO testCopyArr1) ""+ tag "testCopyArr2" >> compareCompiled testCopyArr2 (runIO testCopyArr2) ""+ tag "testArr2" >> compareCompiled testArr2 (runIO testArr2) "20\n"+ tag "testArr3" >> compareCompiled testArr3 (runIO testArr3) ""+ tag "testArr4" >> compareCompiled testArr4 (runIO testArr4) ""+ tag "testArr5" >> compareCompiled testArr5 (runIO testArr5) ""+ tag "testArr6" >> compareCompiled testArr6 (runIO testArr6) ""+ tag "testArr7" >> compareCompiled testArr7 (runIO testArr6) ""+ tag "testArr7" >> compareCompiled testArr7 (runIO testArr7) ""+ tag "testSwap1" >> compareCompiled testSwap1 (runIO testSwap1) ""+ tag "testSwap2" >> compareCompiled testSwap2 (runIO testSwap2) "45\n"+ tag "testIf1" >> compareCompiled testIf1 (runIO testIf1) "12\n"+ tag "testIf2" >> compareCompiled testIf2 (runIO testIf2) "12\n"+ tag "testFor1" >> compareCompiled testFor1 (runIO testFor1) ""+ tag "testFor2" >> compareCompiled testFor2 (runIO testFor2) ""+ tag "testFor3" >> compareCompiled testFor3 (runIO testFor3) ""+ tag "testAssert" >> compareCompiled testAssert (runIO testAssert) "45"+ tag "testPtr" >> compareCompiled testPtr (putStrLn "34" >> putStrLn "sum: 280") ""+ tag "testArgs" >> compareCompiled testArgs (putStrLn "55 66 234 234 66 237 66 55 66 1") ""++ tag "testPrintScan_Int8" >> compareCompiled (testPrintScan int8) (runIO (testPrintScan int8)) "45"+ tag "testPrintScan_Int16" >> compareCompiled (testPrintScan int16) (runIO (testPrintScan int16)) "45"+ tag "testPrintScan_Int32" >> compareCompiled (testPrintScan int32) (runIO (testPrintScan int32)) "45"+ tag "testPrintScan_Int64" >> compareCompiled (testPrintScan int64) (runIO (testPrintScan int64)) "45"+ tag "testPrintScan_Word8" >> compareCompiled (testPrintScan word8) (runIO (testPrintScan word8)) "45"+ tag "testPrintScan_Word16" >> compareCompiled (testPrintScan word16) (runIO (testPrintScan word16)) "45"+ tag "testPrintScan_Word32" >> compareCompiled (testPrintScan word32) (runIO (testPrintScan word32)) "45"+ tag "testPrintScan_Word64" >> compareCompiled (testPrintScan word64) (runIO (testPrintScan word64)) "45"+ tag "testPrintScan_Float" >> captureCompiled (testPrintScan float) "45"+ tag "testPrintScan_Double" >> captureCompiled (testPrintScan double) "45"+ -- `testPrintScan` for floating point types can't be compared to `runIO`,+ -- becuase different number of digits are printed++ tag "testExternArgs" >> compileAndCheck testExternArgs+ tag "testCallFun" >> compareCompiledM testCallFun (putStrLn "-0.757") "4"+ tag "multiModule" >> testMultiModule where tag str = putStrLn $ "---------------- tests/Imperative.hs/" ++ str ++ "\n"- compareCompiledM = compareCompiled'- defaultExtCompilerOpts {externalFlagsPost = ["-lm"]}+ compareCompiledM = compareCompiled' def {externalFlagsPost = ["-lm"]}++ int8 = 0 :: CExp Int8+ int16 = 0 :: CExp Int16+ int32 = 0 :: CExp Int32+ int64 = 0 :: CExp Int64+ word8 = 0 :: CExp Word8+ word16 = 0 :: CExp Word16+ word32 = 0 :: CExp Word32+ word64 = 0 :: CExp Word64+ float = 0 :: CExp Float+ double = 0 :: CExp Double