diff options
Diffstat (limited to 'src/Language/Fiddle/Compiler')
-rw-r--r-- | src/Language/Fiddle/Compiler/Backend/C.hs | 73 | ||||
-rw-r--r-- | src/Language/Fiddle/Compiler/ConsistencyCheck.hs | 14 | ||||
-rw-r--r-- | src/Language/Fiddle/Compiler/Qualification.hs | 19 |
3 files changed, 86 insertions, 20 deletions
diff --git a/src/Language/Fiddle/Compiler/Backend/C.hs b/src/Language/Fiddle/Compiler/Backend/C.hs index 2e6421e..645fa85 100644 --- a/src/Language/Fiddle/Compiler/Backend/C.hs +++ b/src/Language/Fiddle/Compiler/Backend/C.hs @@ -6,10 +6,7 @@ module Language.Fiddle.Compiler.Backend.C (cBackend) where import Control.Arrow (Arrow (second)) -import Control.Exception (TypeError (TypeError)) -import Control.Monad.Identity (Identity (Identity)) import Control.Monad.RWS -import Control.Monad.Writer import Data.Char (isSpace) import Data.Data (Typeable, cast) import Data.Foldable (forM_, toList) @@ -33,13 +30,16 @@ data CBackendFlags = CBackendFlags cHeaderOut :: FilePath } -data FilePosition = FilePosition Int +newtype FilePosition = FilePosition Int deriving (Eq, Ord) +headerPos :: FilePosition headerPos = FilePosition 0 +middlePos :: FilePosition middlePos = FilePosition 50 +footerPos :: FilePosition footerPos = FilePosition 100 tellLn :: (MonadWriter Text m) => Text -> m () @@ -212,7 +212,54 @@ pad :: (IsString t, MonadWriter t m) => m a -> m a pad f = tell "\n" *> f <* tell "\n" structBody :: ObjTypeBody Checked I A -> FormattedWriter () -structBody _ = return () +structBody (ObjTypeBody _ decls _) = do + forM_ decls $ \(Directed _ decl _) -> + case decl of + RegisterDecl + { regSpan = Present (FieldSpan _ sz), + regIdent = Guaranteed (identToString -> i), + regAnnot = ann + } -> do + emitDocComments ann + tell (sizeToField i sz) + tell ";\n" + ReservedDecl + { regSpan = Present (FieldSpan _ sz), + reservedIdent = Present i, + reservedAnnot = ann + } -> do + emitDocComments ann + tell (sizeToField i sz) + tell ";\n" + TypeSubStructure + { subStructureBody = Identity bod, + subStructureName = mname + } -> do + tell $ case objBodyType bod of + Union {} -> "union " + Struct {} -> "struct " + + body $ structBody bod + + forM_ mname $ \name -> + tell (Text.pack $ identToString name) + + tell ";\n" + where + sizeToField (Text.pack -> f) = \case + 1 -> "volatile uint8_t " <> f + 2 -> "volatile uint16_t " <> f + 4 -> "volatile uint32_t " <> f + 8 -> "volatile uint64_t " <> f + n -> "volatile uint8_t " <> f <> "[" <> Text.pack (show n) <> "]" + +union :: Text -> FormattedWriter () -> FormattedWriter () +union identifier fn = do + tell "#pragma pack(push, 1)\n" + tell $ "union " <> identifier <> " " + body fn + tell ";\n" + tell "#pragma pack(pop)\n" struct :: Text -> FormattedWriter () -> FormattedWriter () struct identifier fn = do @@ -228,8 +275,8 @@ body f = tell "{\n" *> indented f <* (ensureNL >> tell "}") identifierFor :: (ExportableDecl d) => d -> Text identifierFor = qualifiedPathToIdentifier . metadataFullyQualifiedPath . getMetadata -emitDocComments :: (MonadWriter Text m) => A -> m () -emitDocComments (Commented comments _) = +emitDocComments :: A -> FormattedWriter () +emitDocComments (Commented comments _) = do mapM_ (\t -> tellLn $ "// " <> t) $ mapMaybe ( \case @@ -237,6 +284,7 @@ emitDocComments (Commented comments _) = _ -> Nothing ) comments + ensureNL where trimDocComment = Text.dropWhileEnd isSpace @@ -244,28 +292,31 @@ emitDocComments (Commented comments _) = . dropIf (== '*') . Text.dropWhile isSpace - dropIf fn t | Text.null t = mempty + dropIf _ t | Text.null t = mempty dropIf fn t = if fn (Text.head t) then Text.tail t else t transpileWalk :: Either ImplementationInHeader FilePath -> FilePath -> (forall t. (Walk t, Typeable t) => t I A -> () -> M (WalkContinuation ())) -transpileWalk sourceFile headerFile t _ = case () of +transpileWalk _ headerFile t _ = case () of () | Just ( ObjTypeDecl { objTypeQualificationMetadata = Identity metadata, - objTypeIdent = (identToString -> identifier), objTypeBody = Identity objTypeBody, objTypeAnnot = a } ) <- castTS t -> do + let structureType = case objBodyType objTypeBody of + Union {} -> union + Struct {} -> struct + withFileAt headerFile middlePos $ do pad $ do emitDocComments a - struct (identifierFor (unwrap metadata)) $ do + structureType (identifierFor (unwrap metadata)) $ do structBody objTypeBody return Stop _ -> return (Continue ()) diff --git a/src/Language/Fiddle/Compiler/ConsistencyCheck.hs b/src/Language/Fiddle/Compiler/ConsistencyCheck.hs index 552ea40..e0c7876 100644 --- a/src/Language/Fiddle/Compiler/ConsistencyCheck.hs +++ b/src/Language/Fiddle/Compiler/ConsistencyCheck.hs @@ -149,18 +149,21 @@ advanceObjTypeBody (ObjTypeBody us decls a) startOffset = do return (ret, offset) (RegisterDecl _ mod ident size Nothing a) -> do (sizeExpr, reifiedSize) <- advanceAndGetSize size - doReturn (RegisterDecl offset mod ident sizeExpr Nothing a) + let span = Present (FieldSpan (N offset) (N reifiedSize)) + doReturn (RegisterDecl span mod ident sizeExpr Nothing a) =<< checkBitsSizeMod8 a reifiedSize (RegisterDecl _ mod ident size (Just body) a) -> do declaredSize <- expressionToIntM size (actualSize, body') <- advanceRegisterBody body checkSizeMismatch a declaredSize actualSize (sizeExpr, reifiedSize) <- advanceAndGetSize size - doReturn (RegisterDecl offset mod ident sizeExpr (Just body') a) + let span = Present (FieldSpan (N offset) (N reifiedSize)) + doReturn (RegisterDecl span mod ident sizeExpr (Just body') a) =<< checkBitsSizeMod8 a reifiedSize - (ReservedDecl size a) -> do + (ReservedDecl _ i size a) -> do (sizeExpr, reifiedSize) <- advanceAndGetSize size - doReturn (ReservedDecl sizeExpr a) reifiedSize + let span = Present (FieldSpan (N offset) (N reifiedSize)) + doReturn (ReservedDecl span i sizeExpr a) reifiedSize (TypeSubStructure (Identity body) name a) -> do (size, body') <- advanceObjTypeBody body offset doReturn (TypeSubStructure (Identity body') name a) size @@ -231,8 +234,9 @@ advanceDecl offset = \case ) DefinedBits _ mod ident typ annot -> do size <- bitsTypeSize typ + let span = Present (FieldSpan (N offset) (N size)) (size,) - <$> (DefinedBits offset mod ident <$> advanceStage () typ <*> pure annot) + <$> (DefinedBits span mod ident <$> advanceStage () typ <*> pure annot) BitsSubStructure subBody subName ann -> do (sz, body') <- advanceRegisterBody subBody return (sz, BitsSubStructure body' subName ann) diff --git a/src/Language/Fiddle/Compiler/Qualification.hs b/src/Language/Fiddle/Compiler/Qualification.hs index e09725e..70378c3 100644 --- a/src/Language/Fiddle/Compiler/Qualification.hs +++ b/src/Language/Fiddle/Compiler/Qualification.hs @@ -45,14 +45,17 @@ type A = Commented SourceSpan type M = Compile GlobalState -uniqueString :: M String -uniqueString = do +uniqueString :: String -> M String +uniqueString prefix = do cnt <- gets uniqueCounter modify $ \g -> g {uniqueCounter = cnt + 1} - return $ "__anon" ++ show cnt + return $ "_" ++ prefix ++ show cnt uniqueIdentifier :: a -> M (Identifier F a) -uniqueIdentifier a = (\s -> Identifier (Data.Text.pack s) a) <$> uniqueString +uniqueIdentifier a = (\s -> Identifier (Data.Text.pack s) a) <$> uniqueString "ident" + +uniqueReservedIdentifier :: a -> M (Identifier F a) +uniqueReservedIdentifier a = (\s -> Identifier (Data.Text.pack s) a) <$> uniqueString "reserved" instance CompilationStage Expanded where type StageAfter Expanded = Qualified @@ -82,6 +85,14 @@ instance where convertInStage _ ann _ = guaranteeM (uniqueIdentifier ann) +instance + StageConvertible + Expanded + (When False String) + (When True String) + where + convertInStage _ _ _ _ = Present <$> uniqueString "reserved" + deriving instance AdvanceStage S ObjTypeBody deriving instance AdvanceStage S DeferredRegisterBody |