summaryrefslogtreecommitdiff
path: root/src/Language/Fiddle/Compiler/Backend/Internal
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-10-27 13:29:33 -0600
committerJosh Rahm <joshuarahm@gmail.com>2024-10-27 13:29:33 -0600
commit5d3f21123b585fb1c43da9d854b04c61678405df (patch)
tree955c07a1f6c78de943d3c87b4f29bab55d329dbc /src/Language/Fiddle/Compiler/Backend/Internal
parenta584a9ca11138bae15ebc1052d596af272b3fd79 (diff)
downloadfiddle-5d3f21123b585fb1c43da9d854b04c61678405df.tar.gz
fiddle-5d3f21123b585fb1c43da9d854b04c61678405df.tar.bz2
fiddle-5d3f21123b585fb1c43da9d854b04c61678405df.zip
Finish implementing alpha-version of the C-backend.
This produces valid C code in a header file and also provides an INTF macro which makes it much less obtuse to call the various functions to set and unset bitfields.
Diffstat (limited to 'src/Language/Fiddle/Compiler/Backend/Internal')
-rw-r--r--src/Language/Fiddle/Compiler/Backend/Internal/FormattedWriter.hs72
1 files changed, 46 insertions, 26 deletions
diff --git a/src/Language/Fiddle/Compiler/Backend/Internal/FormattedWriter.hs b/src/Language/Fiddle/Compiler/Backend/Internal/FormattedWriter.hs
index bde9ebe..000dfa4 100644
--- a/src/Language/Fiddle/Compiler/Backend/Internal/FormattedWriter.hs
+++ b/src/Language/Fiddle/Compiler/Backend/Internal/FormattedWriter.hs
@@ -3,21 +3,30 @@
{-# LANGUAGE OverloadedStrings #-}
-- | This module provides the 'FormattedWriter' monad, which extends a basic
--- "Writer" over 'Text' by allowing formatting features like indentation, line
--- breaks, and ensuring the output is well-structured for readability.
---
+-- "Writer" over 'Text' by allowing formatting features like indentation, line
+-- breaks, and ensuring the output is well-structured for readability.
+--
-- The 'FormattedWriter' is useful for generating pretty-printed output, such as
-- source code generation, where indentation and newline management are essential.
module Language.Fiddle.Compiler.Backend.Internal.FormattedWriter
( -- * Types
- FormattedWriter, -- | The main writer monad with formatting features.
+ FormattedWriter,
+ -- | The main writer monad with formatting features.
-- * Core Operations
- ensureNL, -- | Ensures that there is a newline at the end of the current line.
- flush, -- | Flushes any pending text (writes the pending line).
- incIndent, -- | Increases the indentation level.
- decIndent, -- | Decreases the indentation level.
- indented, -- | Performs an action with increased indentation.
- execFormattedWriter, -- | Runs the 'FormattedWriter' and produces the final formatted 'Text'.
+ ensureNL,
+ -- | Ensures that there is a newline at the end of the current line.
+ flush,
+ -- | Flushes any pending text (writes the pending line).
+ incIndent,
+ -- | Increases the indentation level.
+ decIndent,
+ -- | Decreases the indentation level.
+ indented,
+ -- | Performs an action with increased indentation.
+ execFormattedWriter,
+ -- | Runs the 'FormattedWriter' and produces the final formatted 'Text'.
+ cMacroModeStart,
+ cMacroModeStop,
)
where
@@ -27,12 +36,15 @@ import Data.Text (Text)
import qualified Data.Text as Text
-- | Internal state for the 'FormattedWriter' monad.
---
+--
-- * 'indentLevel': The current level of indentation.
-- * 'pendingLine': The current line that is being built but not yet written.
data Fmt = Fmt
- { indentLevel :: Int, -- ^ Current indentation level.
- pendingLine :: Text -- ^ Text that has been added but not yet written to the output.
+ { -- | Current indentation level.
+ indentLevel :: Int,
+ linePost :: Text,
+ -- | Text that has been added but not yet written to the output.
+ pendingLine :: Text
}
-- | The 'FormattedWriter' is a monad that provides functionality for writing
@@ -52,12 +64,14 @@ instance MonadWriter Text FormattedWriter where
-- For each line, write the indent, the pending line, and then the line itself.
forM_ (Prelude.init lines) $ \line -> do
pending <- gets pendingLine
- modify $ \s -> s {pendingLine = ""} -- Reset pending line
- tell indent -- Add indentation
+ lp <- gets linePost
+ modify $ \s -> s {pendingLine = ""} -- Reset pending line
+ tell indent -- Add indentation
tell pending -- Write any pending text
- tell line -- Write the actual line
- tell "\n" -- Add a newline after the line
- -- The last fragment is kept as the new pending line, to be written later.
+ tell line -- Write the actual line
+ tell lp
+ tell "\n" -- Add a newline after the line
+ -- The last fragment is kept as the new pending line, to be written later.
modify $ \s -> s {pendingLine = pendingLine s <> Prelude.last lines}
-- Allow listening to the written text within the 'FormattedWriter' context.
@@ -85,29 +99,35 @@ flush :: FormattedWriter ()
flush = do
p <- gets pendingLine
modify $ \s -> s {pendingLine = ""}
- tell p
+ lp <- gets linePost
+ tell (p <> lp)
-- | Increases the indentation level by one. This will affect all subsequent
-- lines written within the 'FormattedWriter' monad.
incIndent :: FormattedWriter ()
-incIndent = modify (\(Fmt id p) -> Fmt (id + 1) p)
+incIndent = modify (\f -> f {indentLevel = indentLevel f + 1})
-- | Decreases the indentation level by one. This will affect all subsequent
-- lines written within the 'FormattedWriter' monad.
decIndent :: FormattedWriter ()
-decIndent = modify (\(Fmt id p) -> Fmt (id - 1) p)
+decIndent = modify (\f -> f {indentLevel = indentLevel f - 1})
+
+cMacroModeStart :: FormattedWriter ()
+cMacroModeStart = modify (\f -> f { linePost = " \\" })
+
+cMacroModeStop :: FormattedWriter ()
+cMacroModeStop = modify (\f -> f { linePost = "" })
-- | Runs the given 'FormattedWriter' action with an additional indentation level.
-- Once the action completes, the indentation level is decreased.
indented :: FormattedWriter () -> FormattedWriter ()
indented fn = do
- incIndent -- Increase indentation level
- fn -- Run the action with the increased indentation
- decIndent -- Restore the original indentation level
+ incIndent -- Increase indentation level
+ fn -- Run the action with the increased indentation
+ decIndent -- Restore the original indentation level
-- | Runs a 'FormattedWriter' and returns the final formatted 'Text' output.
-- It ensures that any pending lines are flushed before returning the result.
execFormattedWriter :: FormattedWriter a -> Text
execFormattedWriter ((>> flush) -> FormattedWriter rws) =
- snd $ execRWS rws () (Fmt 0 "") -- Execute the RWS monad, starting with no indentation and no pending line.
-
+ snd $ execRWS rws () (Fmt 0 "" "") -- Execute the RWS monad, starting with no indentation and no pending line.