diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-10-27 13:29:33 -0600 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-10-27 13:29:33 -0600 |
commit | 5d3f21123b585fb1c43da9d854b04c61678405df (patch) | |
tree | 955c07a1f6c78de943d3c87b4f29bab55d329dbc /src/Language/Fiddle/Compiler/Backend/Internal | |
parent | a584a9ca11138bae15ebc1052d596af272b3fd79 (diff) | |
download | fiddle-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.hs | 72 |
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. |