summaryrefslogtreecommitdiff
path: root/src/Language/Fiddle/Compiler.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Language/Fiddle/Compiler.hs')
-rw-r--r--src/Language/Fiddle/Compiler.hs64
1 files changed, 46 insertions, 18 deletions
diff --git a/src/Language/Fiddle/Compiler.hs b/src/Language/Fiddle/Compiler.hs
index 049d533..812d4f6 100644
--- a/src/Language/Fiddle/Compiler.hs
+++ b/src/Language/Fiddle/Compiler.hs
@@ -11,16 +11,25 @@ import Control.Monad.RWS
import Control.Monad.Trans.Maybe
import Control.Monad.Writer
import Data.Default
+import Data.Typeable
import Language.Fiddle.Ast
import Language.Fiddle.Types
import Options.Applicative
import System.IO (hPutStrLn, stderr)
+import qualified Data.ByteString.Lazy.Char8 as BL
import Text.Parsec (sourceColumn, sourceLine, sourceName)
+import Data.Aeson (FromJSON, ToJSON (toJSON), encode)
+import GHC.Generics (Generic)
data Level = Error | Warning | Info
- deriving (Eq, Ord, Show, Read, Enum)
+ deriving (Eq, Ord, Show, Read, Enum, ToJSON, FromJSON, Generic)
-data Diagnostic = Diagnostic Level String SourceSpan
+data Diagnostic = Diagnostic {
+ diagnosticLevel :: Level,
+ diagnosticMesasge :: String,
+ diagnosticLocation :: SourceSpan
+ }
+ deriving (Generic, ToJSON, FromJSON, Typeable)
emitDiagnosticError :: String -> Commented SourceSpan -> Compile a ()
emitDiagnosticError str a = tell [Diagnostic Error str (unCommented a)]
@@ -31,16 +40,21 @@ emitDiagnosticWarning str a = tell [Diagnostic Warning str (unCommented a)]
emitDiagnosticInfo :: String -> Commented SourceSpan -> Compile a ()
emitDiagnosticInfo str a = tell [Diagnostic Info str (unCommented a)]
-newtype Compile s a = Compile (MaybeT (RWS () [Diagnostic] s) a)
+data Artifact where
+ Artifact :: forall t. (Typeable t) => t -> Artifact
+
+newtype Compile s a = Compile (MaybeT (RWS () ([Diagnostic], [Artifact]) s) a)
deriving newtype (Functor, Applicative, Monad)
compilationFailure :: Compile s a
compilationFailure = Compile $ MaybeT (return Nothing)
instance MonadWriter [Diagnostic] (Compile s) where
- tell = Compile . tell
- listen (Compile fn) = Compile $ listen fn
- pass (Compile fn) = Compile $ pass fn
+ tell t = Compile $ tell (t, [])
+ listen (Compile fn) = Compile $ do
+ (a, (ds, _)) <- listen fn
+ return (a, ds)
+ pass (Compile mfun) = Compile $ pass (second first <$> mfun)
instance MonadState s (Compile s) where
get = Compile get
@@ -53,28 +67,34 @@ subCompile s' (Compile mtrws) = Compile $ do
tell w
MaybeT $ return $ fmap (s,) a
+emitArtifact :: Artifact -> Compile s ()
+emitArtifact art = Compile $ tell ([], [art])
+
pushState :: Compile s a -> Compile s a
pushState cp = do
s <- get
snd <$> subCompile s cp
-compile :: Compile s a -> s -> ([Diagnostic], Maybe a)
+compile :: Compile s a -> s -> ([Diagnostic], [Artifact], Maybe a)
compile (Compile fn) initState = do
- let (a, _, w) = runRWS (runMaybeT fn) () initState
- in if hasError w then (w, Nothing) else (w, a)
+ let (a, _, (w, as)) = runRWS (runMaybeT fn) () initState
+ in if hasError w then (w, as, Nothing) else (w, as, a)
where
hasError = any (\(Diagnostic e _ _) -> e == Error)
-compile_ :: (Default s) => Compile s a -> ([Diagnostic], Maybe a)
+compile_ :: (Default s) => Compile s a -> ([Diagnostic], [Artifact], Maybe a)
compile_ c = compile c def
hoistMaybe :: Maybe a -> Compile s a
hoistMaybe = Compile . MaybeT . return
-newtype DiagnosticFormat = DiagnosticFormat (Diagnostic -> String)
+newtype DiagnosticFormat = DiagnosticFormat ([Diagnostic] -> String)
+
+jsonFormat :: DiagnosticFormat
+jsonFormat = DiagnosticFormat $ BL.unpack . encode . toJSON
coloredFormat :: DiagnosticFormat
-coloredFormat = DiagnosticFormat $ \(Diagnostic level message (SourceSpan pos1 pos2)) ->
+coloredFormat = DiagnosticFormat $ \diags -> unlines $ map (\(Diagnostic level message (SourceSpan pos1 pos2)) ->
execWriter $ do
case level of
Error -> tell "\x1b[01;31mError "
@@ -90,18 +110,22 @@ coloredFormat = DiagnosticFormat $ \(Diagnostic level message (SourceSpan pos1 p
tellPos pos2
tell "): "
tell (unwords $ words message)
+ ) diags
where
tellPos pos = do
tell (show $ sourceLine pos)
tell ":"
tell (show $ sourceColumn pos)
-diagnosticToString :: DiagnosticFormat -> Diagnostic -> String
-diagnosticToString (DiagnosticFormat f) = f
+diagnosticsToString :: DiagnosticFormat -> [Diagnostic] -> String
+diagnosticsToString (DiagnosticFormat f) = f
+
+printDiagnostics :: DiagnosticFormat -> [Diagnostic] -> IO ()
+printDiagnostics fmt d = hPutStrLn stderr (diagnosticsToString fmt d)
printDiagnostic :: Diagnostic -> IO ()
printDiagnostic d =
- hPutStrLn stderr (diagnosticToString coloredFormat d)
+ hPutStrLn stderr (diagnosticsToString coloredFormat [d])
fromMayberOrFail :: SourceSpan -> String -> Maybe a -> Compile s a
fromMayberOrFail sourceSpan err Nothing = do
@@ -127,6 +151,9 @@ pureCompilationPhase ::
pureCompilationPhase fn =
CompilationPhase (pure ()) (\_ _ -> return ([], Just ())) (\_ _ -> fn)
+emitArtifacts :: [Artifact] -> Compile s ()
+emitArtifacts arts = Compile $ tell ([], arts)
+
-- data IOActionExtraData = IOActionExtraData
-- { parseFile :: FilePath -> IO (TreeType FiddleUnit Parsed),
-- stage3Compile :: TreeType FiddleUnit Parsed ->
@@ -140,7 +167,7 @@ pureCompilationPhase fn =
data CompilationPhase stageFrom stageTo where
CompilationPhase ::
forall privateFlags privateState stageFrom stageTo.
- (CompilationStage stageFrom) =>
+ -- (CompilationStage stageFrom) =>
{ optionsParser :: Parser privateFlags,
-- | 'ioAction' is an IO operation that runs after the ast is parsed. It
-- takes the parsed 'FiddleUnit' and performs some side effect
@@ -211,6 +238,7 @@ execCompilationPipelineWithCmdline ::
( FiddleUnit Parsed Identity (StageAnnotation Parsed) ->
IO
( [Diagnostic],
+ [Artifact],
Maybe
( FiddleUnit s' Identity (StageAnnotation s')
)
@@ -222,8 +250,8 @@ execCompilationPipelineWithCmdline
( \opts ast -> do
(diags, ms) <- ioAct opts ast
case ms of
- Just s -> return $ first (diags ++) $ compile_ $ rest opts s ast
- Nothing -> return (diags, Nothing)
+ Just s -> return $ (\(a, b, c) -> (diags ++ a, b, c)) $ compile_ $ rest opts s ast
+ Nothing -> return (diags, [], Nothing)
)
flagsParser