packages feed

copilot-c99 3.4 → 3.5

raw patch · 12 files changed

+242/−147 lines, 12 filesdep ~copilot-corePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: copilot-core

API changes (from Hackage documentation)

+ Copilot.Compile.C99: CSettings :: String -> CSettings
+ Copilot.Compile.C99: [cSettingsStepFunctionName] :: CSettings -> String
+ Copilot.Compile.C99: compileWith :: CSettings -> String -> Spec -> IO ()
+ Copilot.Compile.C99: data CSettings
+ Copilot.Compile.C99: mkDefaultCSettings :: CSettings
+ Copilot.Compile.C99.CodeGen: mkaccessdecln :: Id -> Type a -> [a] -> FunDef
+ Copilot.Compile.C99.Compile: CSettings :: String -> CSettings
+ Copilot.Compile.C99.Compile: [cSettingsStepFunctionName] :: CSettings -> String
+ Copilot.Compile.C99.Compile: compileWith :: CSettings -> String -> Spec -> IO ()
+ Copilot.Compile.C99.Compile: data CSettings
+ Copilot.Compile.C99.Compile: mkDefaultCSettings :: CSettings
+ Copilot.Compile.C99.Settings: CSettings :: String -> CSettings
+ Copilot.Compile.C99.Settings: [cSettingsStepFunctionName] :: CSettings -> String
+ Copilot.Compile.C99.Settings: data CSettings
+ Copilot.Compile.C99.Settings: mkDefaultCSettings :: CSettings
+ Copilot.Compile.C99.Util: streamaccessorname :: Id -> String
- Copilot.Compile.C99.CodeGen: mkstep :: [Stream] -> [Trigger] -> [External] -> FunDef
+ Copilot.Compile.C99.CodeGen: mkstep :: CSettings -> [Stream] -> [Trigger] -> [External] -> FunDef
- Copilot.Compile.C99.Util: type FunEnv = ([Decln], [Ident])
+ Copilot.Compile.C99.Util: type FunEnv = [Decln]

Files

CHANGELOG view
@@ -1,3 +1,14 @@+2021-08-19+        * Version bump (3.5). (#247)+        * Update travis domain in README. (#222)+        * Remove second element of pair FunEnv. (#170)+        * Allow customizing name of step function. (#64)+        * Update official maintainer. (#236)+        * Deprecate internal modules. (#237, #242)+        * Update source repo location. (#241)+        * Fix out-of-bounds array access. (#238)+        * Add I. Perez to author list. (#243)+ 2021-07-07         * Version bump (3.4). (#231)         * Remove broken test. (#232)
README.md view
@@ -1,4 +1,4 @@-[![Build Status](https://travis-ci.org/Copilot-Language/copilot-c99.svg?branch=master)](https://travis-ci.org/Copilot-Language/copilot-core)+[![Build Status](https://travis-ci.com/Copilot-Language/copilot-c99.svg?branch=master)](https://travis-ci.com/Copilot-Language/copilot-core)  # Copilot: a stream DSL Copilot-c99 implements a C99 backend for Copilot, producing high quality code
copilot-c99.cabal view
@@ -1,6 +1,6 @@ cabal-version             : >= 1.10 name                      : copilot-c99-version                   : 3.4+version                   : 3.5 synopsis                  : A compiler for Copilot targeting C99. description               :   This package is a back-end from Copilot to C.@@ -14,7 +14,7 @@  license                   : BSD3 license-file              : LICENSE-maintainer                : Frank Dedden <dev@dedden.net>+maintainer                : Ivan Perez <ivan.perezdominguez@nasa.gov> homepage                  : https://copilot-language.github.io bug-reports               : https://github.com/Copilot-Language/copilot/issues stability                 : Experimental@@ -25,15 +25,22 @@  author                    : Frank Dedden                           , Alwyn Goodloe+                          , Ivan Perez  source-repository head     type:       git-    location:   git://github.com/Copilot-Language/copilot-c99.git+    location:   git://github.com/Copilot-Language/copilot.git+    subdir:     lib/copilot-c99  library   default-language        : Haskell2010   hs-source-dirs          : src-  ghc-options             : -Wall -fwarn-tabs++  -- The following -Wno-deprecations is temprary and related to issue+  -- https://github.com/Copilot-Language/copilot/issues/237+  -- It should be removed in a future version, when this library hides+  -- internal modules.+  ghc-options             : -Wall -fwarn-tabs -Wno-deprecations   build-depends           : base                >= 4.9 && < 5                           , containers          >= 0.4 && < 0.7                           , directory           >= 1.3 && < 1.4@@ -41,7 +48,7 @@                           , mtl                 >= 2.2 && < 2.3                           , pretty              >= 1.1 && < 1.2 -                          , copilot-core        >= 3.4   && < 3.5+                          , copilot-core        >= 3.5   && < 3.6                           , language-c99        >= 0.1.1 && < 0.2                           , language-c99-util   >= 0.1.1 && < 0.2                           , language-c99-simple >= 0.1.1 && < 0.2@@ -52,3 +59,7 @@                           , Copilot.Compile.C99.CodeGen                           , Copilot.Compile.C99.External                           , Copilot.Compile.C99.Compile+                          , Copilot.Compile.C99.Settings++  other-modules          : Copilot.Compile.C99.Compile.Internal+                         , Copilot.Compile.C99.Settings.Internal
src/Copilot/Compile/C99.hs view
@@ -1,6 +1,10 @@ -- | Compile Copilot specifications to C99 code. module Copilot.Compile.C99   ( compile+  , compileWith+  , CSettings(..)+  , mkDefaultCSettings   ) where -import Copilot.Compile.C99.Compile+import Copilot.Compile.C99.Compile.Internal+import Copilot.Compile.C99.Settings.Internal
src/Copilot/Compile/C99/CodeGen.hs view
@@ -2,7 +2,9 @@ {-# LANGUAGE ScopedTypeVariables #-}  -- | High-level translation of Copilot Core into C99.-module Copilot.Compile.C99.CodeGen where+module Copilot.Compile.C99.CodeGen+  {-# DEPRECATED "This module will be hidden in future versions." #-}+  where  import Control.Monad.State  (runState) import Data.List            (union, unzip4)@@ -13,6 +15,7 @@ import Copilot.Core import Copilot.Compile.C99.Util import Copilot.Compile.C99.External+import Copilot.Compile.C99.Settings import Copilot.Compile.C99.Translate  -- | Write a declaration for a generator function.@@ -24,7 +27,7 @@ genfun :: String -> Expr a -> Type a -> C.FunDef genfun name expr ty = C.FunDef cty name [] cvars [C.Return $ Just cexpr] where   cty = C.decay $ transtype ty-  (cexpr, (cvars, _)) = runState (transexpr expr) mempty+  (cexpr, cvars) = runState (transexpr expr) mempty  -- | Make a extern declaration of a variable. mkextdecln :: External -> C.Decln@@ -53,9 +56,22 @@   cty     = C.TypeSpec $ C.TypedefName "size_t"   initval = Just $ C.InitExpr $ C.LitInt 0 +-- | Define an accessor functions for the ring buffer associated with a stream+mkaccessdecln :: Id -> Type a -> [a] -> C.FunDef+mkaccessdecln sid ty xs = C.FunDef cty name params [] [C.Return (Just expr)]+  where+    cty        = C.decay $ transtype ty+    name       = streamaccessorname sid+    bufflength = C.LitInt $ fromIntegral $ length xs+    params     = [C.Param (C.TypeSpec $ C.TypedefName "size_t") "x"]+    index      = (C.Ident (indexname sid) C..+ C.Ident "x") C..% bufflength+    expr       = C.Index (C.Ident (streamname sid)) index+ -- | Writes the step function, that updates all streams.-mkstep :: [Stream] -> [Trigger] -> [External] -> C.FunDef-mkstep streams triggers exts = C.FunDef void "step" [] declns stmts where+mkstep :: CSettings -> [Stream] -> [Trigger] -> [External] -> C.FunDef+mkstep cSettings streams triggers exts =+  C.FunDef void (cSettingsStepFunctionName cSettings) [] declns stmts where+   void = C.TypeSpec C.Void   stmts  =  map mkexcopy exts          ++ map mktriggercheck triggers
src/Copilot/Compile/C99/Compile.hs view
@@ -1,130 +1,11 @@ -- | Compile Copilot specifications to C99 code. module Copilot.Compile.C99.Compile+  {-# DEPRECATED "This module will be hidden in future versions." #-}   ( compile+  , compileWith+  , CSettings(..)+  , mkDefaultCSettings   ) where -import Text.PrettyPrint     (render)-import Data.List            (nub)-import Data.Maybe           (catMaybes)--import Language.C99.Pretty  (pretty)-import qualified Language.C99.Simple as C--import Copilot.Core-import Copilot.Compile.C99.Util-import Copilot.Compile.C99.External-import Copilot.Compile.C99.Translate-import Copilot.Compile.C99.CodeGen---- | Compile a specification to a .h and a .c file.------ The first argument is used as prefix for the .h and .c files generated.-compile :: String -> Spec -> IO ()-compile prefix spec = do-  let cfile = render $ pretty $ C.translate $ compilec spec-      hfile = render $ pretty $ C.translate $ compileh spec--      -- TODO: find a nicer solution using annotated AST's-      -- Should figure out exactly which headers are needed, based on what-      -- is used.-      cmacros = unlines [ "#include <stdint.h>"-                        , "#include <stdbool.h>"-                        , "#include <string.h>"-                        , "#include <stdlib.h>"-                        , "#include <math.h>"-                        , ""-                        , "#include \"" ++ prefix ++ ".h\""-                        , ""-                        ]--  writeFile (prefix ++ ".c") $ cmacros ++ cfile-  writeFile (prefix ++ ".h") hfile---- | Generate the .c file from a 'Spec'.------ The generated C file has the following structure:------ * Include .h file.--- * Declarations of global buffers and indices.--- * Generator functions for streams, guards and trigger arguments.--- * Declaration of the @step()@ function.-compilec :: Spec -> C.TransUnit-compilec spec = C.TransUnit declns funs where-  streams  = specStreams spec-  triggers = specTriggers spec-  exts     = gatherexts streams triggers-  exprs    = gatherexprs streams triggers--  declns = mkstructdeclns exprs ++ mkexts exts ++ mkglobals streams-  funs   = genfuns streams triggers ++ [mkstep streams triggers exts]--  -- Write struct datatypes-  mkstructdeclns :: [UExpr] -> [C.Decln]-  mkstructdeclns es = catMaybes $ map mkdecln utypes where-    mkdecln (UType ty) = case ty of-      Struct x -> Just $ mkstructdecln ty-      _        -> Nothing--    utypes = nub $ concatMap (\(UExpr _ e) -> exprtypes e) es--  -- Make declarations for copies of external variables.-  mkexts :: [External] -> [C.Decln]-  mkexts exts = map mkextcpydecln exts--  -- Make buffer and index declarations for streams.-  mkglobals :: [Stream] -> [C.Decln]-  mkglobals streams = map buffdecln streams ++ map indexdecln streams where-    buffdecln  (Stream sid buff _ ty) = mkbuffdecln  sid ty buff-    indexdecln (Stream sid _    _ _ ) = mkindexdecln sid--  -- Make generator functions, including trigger arguments.-  genfuns :: [Stream] -> [Trigger] -> [C.FunDef]-  genfuns streams triggers =  map streamgen streams-                           ++ concatMap triggergen triggers where-    streamgen :: Stream -> C.FunDef-    streamgen (Stream sid _ expr ty) = genfun (generatorname sid) expr ty--    triggergen :: Trigger -> [C.FunDef]-    triggergen (Trigger name guard args) = guarddef : argdefs where-      guarddef = genfun (guardname name) guard Bool-      argdefs  = map arggen (zip (argnames name) args)--      arggen :: (String, UExpr) -> C.FunDef-      arggen (argname, UExpr ty expr) = genfun argname expr ty---- | Generate the .h file from a 'Spec'.-compileh :: Spec -> C.TransUnit-compileh spec = C.TransUnit declns [] where-  streams  = specStreams spec-  triggers = specTriggers spec-  exts     = gatherexts streams triggers-  exprs    = gatherexprs streams triggers--  declns =  mkstructforwdeclns exprs-         ++ mkexts exts-         ++ extfundeclns triggers-         ++ [stepdecln]--  mkstructforwdeclns :: [UExpr] -> [C.Decln]-  mkstructforwdeclns es = catMaybes $ map mkdecln utypes where-    mkdecln (UType ty) = case ty of-      Struct x -> Just $ mkstructforwdecln ty-      _        -> Nothing--    utypes = nub $ concatMap (\(UExpr _ e) -> exprtypes e) es--  -- Make declarations for external variables.-  mkexts :: [External] -> [C.Decln]-  mkexts = map mkextdecln--  extfundeclns :: [Trigger] -> [C.Decln]-  extfundeclns triggers = map extfundecln triggers where-    extfundecln :: Trigger -> C.Decln-    extfundecln (Trigger name _ args) = C.FunDecln Nothing cty name params where-        cty    = C.TypeSpec C.Void-        params = map mkparam $ zip (argnames name) args-        mkparam (name, UExpr ty _) = C.Param (transtype ty) name--  -- Declaration for the step function.-  stepdecln :: C.Decln-  stepdecln = C.FunDecln Nothing (C.TypeSpec C.Void) "step" []+import Copilot.Compile.C99.Compile.Internal+import Copilot.Compile.C99.Settings.Internal
+ src/Copilot/Compile/C99/Compile/Internal.hs view
@@ -0,0 +1,146 @@+-- | Compile Copilot specifications to C99 code.+module Copilot.Compile.C99.Compile.Internal+  ( compile+  , compileWith+  ) where++import Text.PrettyPrint     (render)+import Data.List            (nub)+import Data.Maybe           (catMaybes)++import Language.C99.Pretty  (pretty)+import qualified Language.C99.Simple as C++import Copilot.Core+import Copilot.Compile.C99.Util+import Copilot.Compile.C99.External+import Copilot.Compile.C99.Settings.Internal+import Copilot.Compile.C99.Translate+import Copilot.Compile.C99.CodeGen++-- | Compile a specification to a .h and a .c file.+--+-- The first argument is the settings for the C code generated.+--+-- The second argument is used as prefix for the .h and .c files generated.+compileWith :: CSettings -> String -> Spec -> IO ()+compileWith cSettings prefix spec = do+  let cfile = render $ pretty $ C.translate $ compilec cSettings spec+      hfile = render $ pretty $ C.translate $ compileh cSettings spec++      -- TODO: find a nicer solution using annotated AST's+      -- Should figure out exactly which headers are needed, based on what+      -- is used.+      cmacros = unlines [ "#include <stdint.h>"+                        , "#include <stdbool.h>"+                        , "#include <string.h>"+                        , "#include <stdlib.h>"+                        , "#include <math.h>"+                        , ""+                        , "#include \"" ++ prefix ++ ".h\""+                        , ""+                        ]++  writeFile (prefix ++ ".c") $ cmacros ++ cfile+  writeFile (prefix ++ ".h") hfile++-- | Compile a specification to a .h and a .c file.+--+-- The first argument is used as prefix for the .h and .c files generated.+compile :: String -> Spec -> IO ()+compile = compileWith mkDefaultCSettings++-- | Generate the .c file from a 'Spec'.+--+-- The generated C file has the following structure:+--+-- * Include .h file.+-- * Declarations of global buffers and indices.+-- * Generator functions for streams, guards and trigger arguments.+-- * Declaration of the @step()@ function.+compilec :: CSettings -> Spec -> C.TransUnit+compilec cSettings spec = C.TransUnit declns funs where+  streams  = specStreams spec+  triggers = specTriggers spec+  exts     = gatherexts streams triggers+  exprs    = gatherexprs streams triggers++  declns = mkstructdeclns exprs ++ mkexts exts ++ mkglobals streams+  funs   = genfuns streams triggers ++ [mkstep cSettings streams triggers exts]++  -- Write struct datatypes+  mkstructdeclns :: [UExpr] -> [C.Decln]+  mkstructdeclns es = catMaybes $ map mkdecln utypes where+    mkdecln (UType ty) = case ty of+      Struct x -> Just $ mkstructdecln ty+      _        -> Nothing++    utypes = nub $ concatMap (\(UExpr _ e) -> exprtypes e) es++  -- Make declarations for copies of external variables.+  mkexts :: [External] -> [C.Decln]+  mkexts exts = map mkextcpydecln exts++  -- Make buffer and index declarations for streams.+  mkglobals :: [Stream] -> [C.Decln]+  mkglobals streams = map buffdecln streams ++ map indexdecln streams where+    buffdecln  (Stream sid buff _ ty) = mkbuffdecln  sid ty buff+    indexdecln (Stream sid _    _ _ ) = mkindexdecln sid++  -- Make generator functions, including trigger arguments.+  genfuns :: [Stream] -> [Trigger] -> [C.FunDef]+  genfuns streams triggers =  map accessdecln streams+                           ++ map streamgen streams+                           ++ concatMap triggergen triggers where++    accessdecln :: Stream -> C.FunDef+    accessdecln (Stream sid buff _ ty) = mkaccessdecln sid ty buff++    streamgen :: Stream -> C.FunDef+    streamgen (Stream sid _ expr ty) = genfun (generatorname sid) expr ty++    triggergen :: Trigger -> [C.FunDef]+    triggergen (Trigger name guard args) = guarddef : argdefs where+      guarddef = genfun (guardname name) guard Bool+      argdefs  = map arggen (zip (argnames name) args)++      arggen :: (String, UExpr) -> C.FunDef+      arggen (argname, UExpr ty expr) = genfun argname expr ty++-- | Generate the .h file from a 'Spec'.+compileh :: CSettings -> Spec -> C.TransUnit+compileh cSettings spec = C.TransUnit declns [] where+  streams  = specStreams spec+  triggers = specTriggers spec+  exts     = gatherexts streams triggers+  exprs    = gatherexprs streams triggers++  declns =  mkstructforwdeclns exprs+         ++ mkexts exts+         ++ extfundeclns triggers+         ++ [stepdecln]++  mkstructforwdeclns :: [UExpr] -> [C.Decln]+  mkstructforwdeclns es = catMaybes $ map mkdecln utypes where+    mkdecln (UType ty) = case ty of+      Struct x -> Just $ mkstructforwdecln ty+      _        -> Nothing++    utypes = nub $ concatMap (\(UExpr _ e) -> exprtypes e) es++  -- Make declarations for external variables.+  mkexts :: [External] -> [C.Decln]+  mkexts = map mkextdecln++  extfundeclns :: [Trigger] -> [C.Decln]+  extfundeclns triggers = map extfundecln triggers where+    extfundecln :: Trigger -> C.Decln+    extfundecln (Trigger name _ args) = C.FunDecln Nothing cty name params where+        cty    = C.TypeSpec C.Void+        params = map mkparam $ zip (argnames name) args+        mkparam (name, UExpr ty _) = C.Param (transtype ty) name++  -- Declaration for the step function.+  stepdecln :: C.Decln+  stepdecln = C.FunDecln Nothing (C.TypeSpec C.Void)+                  (cSettingsStepFunctionName cSettings) []
src/Copilot/Compile/C99/External.hs view
@@ -2,7 +2,9 @@  -- | Represent information about externs needed in the generation of C99 code -- for stream declarations and triggers.-module Copilot.Compile.C99.External where+module Copilot.Compile.C99.External+  {-# DEPRECATED "This module will be hidden in future versions." #-}+  where  import Data.List  (unionBy) 
+ src/Copilot/Compile/C99/Settings.hs view
@@ -0,0 +1,8 @@+-- | Settings used by the code generator to customize the code.+module Copilot.Compile.C99.Settings+  {-# DEPRECATED "This module will be hidden in future versions." #-}+  (module Copilot.Compile.C99.Settings.Internal)+ where++import Copilot.Compile.C99.Settings.Internal+
+ src/Copilot/Compile/C99/Settings/Internal.hs view
@@ -0,0 +1,11 @@+-- | Settings used by the code generator to customize the code.+module Copilot.Compile.C99.Settings.Internal where++-- | Settings used to customize the code generated.+data CSettings = CSettings+  { cSettingsStepFunctionName :: String+  }++-- | Default settings with a step function called @step@.+mkDefaultCSettings :: CSettings+mkDefaultCSettings = CSettings "step"
src/Copilot/Compile/C99/Translate.hs view
@@ -1,7 +1,9 @@ {-# LANGUAGE GADTs #-}  -- | Translate Copilot Core expressions and operators to C99.-module Copilot.Compile.C99.Translate where+module Copilot.Compile.C99.Translate+  {-# DEPRECATED "This module will be hidden in future versions." #-}+  where  import Control.Monad.State @@ -18,19 +20,16 @@   e1' <- transexpr e1   let cty1 = transtype ty1       init = Just $ C.InitExpr e1'-  statetell ([C.VarDecln Nothing cty1 name init], [])+  statetell [C.VarDecln Nothing cty1 name init]    transexpr e2  transexpr (Var _ n) = return $ C.Ident n  transexpr (Drop _ amount sid) = do-  let var    = streamname sid-      indexvar = indexname sid-      index  = case amount of-        0 -> C.Ident indexvar-        n -> C.Ident indexvar C..+ C.LitInt (fromIntegral n)-  return $ C.Index (C.Ident var) index+  let accessvar = streamaccessorname sid+      index     = C.LitInt (fromIntegral amount)+  return $ funcall accessvar [index]  transexpr (ExternVar _ name _) = return $ C.Ident (excpyname name) 
src/Copilot/Compile/C99/Util.hs view
@@ -1,5 +1,7 @@ -- | Auxiliary helper functions to generate C99 code.-module Copilot.Compile.C99.Util where+module Copilot.Compile.C99.Util+  {-# DEPRECATED "This module will be hidden in future versions." #-}+  where  import Control.Monad.State @@ -9,7 +11,7 @@ -- | Auxiliary type used to collect all the declarations of all the variables -- used in a function to be generated, since variable declarations are always -- listed first at the top of the function body.-type FunEnv = ([C.Decln], [C.Ident])+type FunEnv = [C.Decln]  -- | `tell` equivalent for `State`. statetell :: Monoid m => m -> State m ()@@ -32,6 +34,10 @@ -- | Turn a stream id into the global varname for indices. indexname :: Id -> String indexname sid = streamname sid ++ "_idx"++-- | Turn a stream id into the name of its accessor function+streamaccessorname :: Id -> String+streamaccessorname sid = streamname sid ++ "_get"  -- | Add a postfix for copies of external variables the name. excpyname :: String -> String