summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Language/Fiddle/Compiler.hs59
-rw-r--r--src/Language/Fiddle/Compiler/ConsistencyCheck.hs2
-rw-r--r--src/Language/Fiddle/Compiler/Expansion.hs2
-rw-r--r--src/Language/Fiddle/Compiler/ImportResolution.hs41
-rw-r--r--src/Main.hs89
5 files changed, 109 insertions, 84 deletions
diff --git a/src/Language/Fiddle/Compiler.hs b/src/Language/Fiddle/Compiler.hs
index 0fe277f..5be6355 100644
--- a/src/Language/Fiddle/Compiler.hs
+++ b/src/Language/Fiddle/Compiler.hs
@@ -1,18 +1,5 @@
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
--- Compilation monad. Has diagnostics. Optionally produces a value.
--- newtype Compile s a = Compile (s -> (s, [Diagnostic], Maybe a))
--- Runs a sub-compilation routine with the given state, but discards the
--- resulting state in favor of the original state.
--- mapMaybeT (mapRWS (\(a, _, w) -> (a, s', w))) mtrws
--- Saves the state, runs the routine, then restores the state.
--- Runs a compilation routine. It produces diagnostics and maybe a result.
--- Generally if the diagnostics contain an error, the result will be Nothing,
--- but if only Warnings are generated, then Just something will be returned.
---
--- Note that there is no actual type-level mechanism restricting this function
--- from returning something even if the diagnostics contain errors, but it
--- generally wouldn't make much sense for this to be the case.
{-# LANGUAGE RankNTypes #-}
module Language.Fiddle.Compiler where
@@ -26,6 +13,7 @@ import Control.Monad.Writer
import Data.Default
import Language.Fiddle.Ast
import Language.Fiddle.Types
+import Options.Applicative
import System.IO (hPutStrLn, stderr)
import Text.Parsec (SourcePos, sourceColumn, sourceLine, sourceName)
@@ -114,13 +102,15 @@ fromMayberOrFail _ _ (Just a) = return a
-- 'FiddleUnit' from the current stage to the next.
data CompilationPhase stageFrom stageTo where
CompilationPhase ::
- forall privateState stageFrom stageTo.
+ forall privateFlags privateState stageFrom stageTo.
(CompilationStage stageFrom) =>
- { -- | 'ioAction' is an IO operation that runs after the ast is parsed. It
+ { 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
-- returning a private state that is passed to 'nextStage'. This is the
-- only time a side effect may be performed.
ioAction ::
+ privateFlags ->
FiddleUnit Parsed (StageFunctor Parsed) (StageAnnotation Parsed) ->
IO privateState,
-- | 'nextStage' is the function that transforms a 'FiddleUnit' from
@@ -128,6 +118,7 @@ data CompilationPhase stageFrom stageTo where
-- uses the private state obtained from 'ioAction' and outputs a
-- potentially updated 'FiddleUnit' in the compilation pipeline.
nextStage ::
+ privateFlags ->
privateState ->
FiddleUnit
stageFrom
@@ -150,13 +141,14 @@ thenPhase ::
CompilationPhase stage2 stage3 ->
CompilationPhase stage1 stage3
thenPhase
- (CompilationPhase ioAction1 compile1)
- (CompilationPhase ioAction2 compile2) =
+ (CompilationPhase optParse1 ioAction1 compile1)
+ (CompilationPhase optParse2 ioAction2 compile2) =
CompilationPhase
- (\unit -> (,) <$> ioAction1 unit <*> ioAction2 unit)
- ( \(s1, s2) firstStage -> do
- secondStage <- compile1 s1 firstStage
- compile2 s2 secondStage
+ ((,) <$> optParse1 <*> optParse2)
+ (\(f1, f2) unit -> (,) <$> ioAction1 f1 unit <*> ioAction2 f2 unit)
+ ( \(f1, f2) (s1, s2) firstStage -> do
+ secondStage <- compile1 f1 s1 firstStage
+ compile2 f2 s2 secondStage
)
-- | Infix operator for 'thenPhase' to chain compilation phases.
@@ -167,15 +159,22 @@ thenPhase
-- from the 'Parsed' phase. It performs the IO action of the first phase and
-- then invokes the compilation function for the remaining stages. It returns
-- a tuple containing diagnostics and an optional final 'FiddleUnit'.
-execCompilationPipeline ::
+execCompilationPipelineWithCmdline ::
CompilationPhase Parsed s' ->
- FiddleUnit Parsed (StageFunctor Parsed) (StageAnnotation Parsed) ->
- IO
- ( [Diagnostic],
- Maybe
- ( FiddleUnit s' (StageFunctor s') (StageAnnotation s')
+ Parser
+ ( FiddleUnit Parsed (StageFunctor Parsed) (StageAnnotation Parsed) ->
+ IO
+ ( [Diagnostic],
+ Maybe
+ ( FiddleUnit s' (StageFunctor s') (StageAnnotation s')
+ )
)
)
-execCompilationPipeline (CompilationPhase ioAction rest) ast = do
- s <- ioAction ast
- return $ compile_ $ rest s ast
+execCompilationPipelineWithCmdline
+ (CompilationPhase flagsParser ioAction rest) = do
+ fmap
+ ( \opts ast -> do
+ s <- ioAction opts ast
+ return $ compile_ $ rest opts s ast
+ )
+ flagsParser
diff --git a/src/Language/Fiddle/Compiler/ConsistencyCheck.hs b/src/Language/Fiddle/Compiler/ConsistencyCheck.hs
index 4c708f7..5c7b399 100644
--- a/src/Language/Fiddle/Compiler/ConsistencyCheck.hs
+++ b/src/Language/Fiddle/Compiler/ConsistencyCheck.hs
@@ -54,7 +54,7 @@ type SizeBytes = Word32
consistencyCheckPhase ::
CompilationPhase Expanded Checked
consistencyCheckPhase =
- CompilationPhase (const $ return ()) (\() -> checkConsistency)
+ CompilationPhase (pure ()) (\_ _ -> return ()) (\_ _ -> checkConsistency)
checkConsistency ::
FiddleUnit Expanded I Annot ->
diff --git a/src/Language/Fiddle/Compiler/Expansion.hs b/src/Language/Fiddle/Compiler/Expansion.hs
index 77ccf6c..7201686 100644
--- a/src/Language/Fiddle/Compiler/Expansion.hs
+++ b/src/Language/Fiddle/Compiler/Expansion.hs
@@ -39,7 +39,7 @@ expandAst :: FiddleUnit CurrentStage I Annot -> Compile () (FiddleUnit Expanded
expandAst = fmap snd . subCompile (State [] []) . advanceStage (Path mempty)
expansionPhase :: CompilationPhase CurrentStage Expanded
-expansionPhase = CompilationPhase (const $ return ()) (\() -> expandAst)
+expansionPhase = CompilationPhase (pure ()) (\_ _ -> return ()) (\_ _ -> expandAst)
-- Shorthand for Identity
type I = Identity
diff --git a/src/Language/Fiddle/Compiler/ImportResolution.hs b/src/Language/Fiddle/Compiler/ImportResolution.hs
index b4c5293..90a11d5 100644
--- a/src/Language/Fiddle/Compiler/ImportResolution.hs
+++ b/src/Language/Fiddle/Compiler/ImportResolution.hs
@@ -1,7 +1,6 @@
module Language.Fiddle.Compiler.ImportResolution
( resolveImports,
getImportResolutionState,
- ImportResolutionOptions (..),
importResolutionPhase,
)
where
@@ -18,8 +17,30 @@ import Language.Fiddle.Compiler
import Language.Fiddle.Compiler.Expansion
import Language.Fiddle.Internal.UnitInterface
import Language.Fiddle.Types
+import Options.Applicative
import Text.Printf (printf)
+newtype Flags = Flags
+ { importDirectories :: [FilePath]
+ }
+
+parseFlags :: Parser Flags
+parseFlags =
+ Flags
+ <$> many
+ ( strOption
+ ( long "import"
+ <> short 'I'
+ <> metavar "DIRECTORY"
+ <> help "Directory to add to the import search path"
+ )
+ )
+
+importResolutionPhase ::
+ CompilationPhase CurrentStage ImportsResolved
+importResolutionPhase =
+ CompilationPhase parseFlags getImportResolutionState resolveImports
+
type GlobalState = ()
type LocalState = ResolvedImports
@@ -46,19 +67,12 @@ instance CompilationStage CurrentStage where
type StageFunctor CurrentStage = Identity
type StageAnnotation CurrentStage = Annot
-importResolutionPhase ::
- ImportResolutionOptions ->
- CompilationPhase CurrentStage ImportsResolved
-importResolutionPhase opts =
- CompilationPhase
- (getImportResolutionState opts)
- resolveImports
-
resolveImports ::
+ Flags ->
ResolvedImports ->
FiddleUnit CurrentStage I Annot ->
Compile () (FiddleUnit ImportsResolved I Annot)
-resolveImports = advanceStage
+resolveImports _ = advanceStage
deriving instance AdvanceStage CurrentStage ObjTypeBody
@@ -111,13 +125,8 @@ instance AdvanceStage CurrentStage ImportStatement where
return $ ImportStatement path list v a
-newtype ImportResolutionOptions
- = ImportResolutionOptions
- { searchPath :: [FilePath]
- }
-
getImportResolutionState ::
- ImportResolutionOptions ->
+ Flags ->
FiddleUnit CurrentStage Identity Annot ->
IO ResolvedImports
getImportResolutionState _ _ = return (ResolvedImports mempty)
diff --git a/src/Main.hs b/src/Main.hs
index f643320..352a8cc 100644
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -19,51 +19,68 @@ import Language.Fiddle.Compiler.Stage0
import Language.Fiddle.GenericTree (GenericSyntaxTree (..), ToGenericSyntaxTree (toGenericSyntaxTree), alterGenericSyntaxTree)
import qualified Language.Fiddle.Parser
import qualified Language.Fiddle.Tokenizer
+import Options.Applicative
import qualified System.Environment as System
import System.Exit (exitWith)
-phases res =
- importResolutionPhase res >>> expansionPhase >>> consistencyCheckPhase
+compilationPipeline =
+ importResolutionPhase >>> expansionPhase >>> consistencyCheckPhase
+
+newtype GlobalFlags
+ = GlobalFlags
+ { flagsInputFile :: String
+ }
+
+parseGlobalFlags :: Parser GlobalFlags
+parseGlobalFlags =
+ GlobalFlags
+ <$> argument str (metavar "INPUT" <> help "Input file")
main :: IO ()
main = do
- argv <- System.getArgs
- let opts = ImportResolutionOptions ["."]
+ (globalFlags, compilationPipelineAction) <-
+ execParser $
+ info
+ ( ( (,)
+ <$> parseGlobalFlags
+ <*> execCompilationPipelineWithCmdline compilationPipeline
+ )
+ <**> helper
+ )
+ ( fullDesc
+ <> progDesc "Compile Fiddle Files"
+ <> header "fiddlec - A compiler for fiddle files"
+ )
- case argv of
- [filePath] -> do
- text <- Data.Text.IO.readFile filePath
- let maybeParsedAst = compile_ $ toStage0 filePath text >>= toStage1
+ let filePath = flagsInputFile globalFlags
+ text <- Data.Text.IO.readFile filePath
- case maybeParsedAst of
- (priorDiags, Just ast) -> do
- ((priorDiags ++) -> diags, ma) <-
- execCompilationPipeline (phases opts) ast
- ec <-
- case ma of
- Just ast -> do
- putStrLn $
- BL.unpack $
- encode $
- alterGenericSyntaxTree cleanupIdentifiers $
- toGenericSyntaxTree $
- fmap
- (const (Nothing :: Maybe Value))
- ast
- return ExitSuccess
- Nothing -> do
- putStrLn "\x1b[1;31mCompilation Failed\x1b[0m"
- return (ExitFailure 1)
+ let maybeParsedAst = compile_ $ toStage0 filePath text >>= toStage1
+ case maybeParsedAst of
+ (priorDiags, Just ast) -> do
+ ((priorDiags ++) -> diags, ma) <- compilationPipelineAction ast
+ ec <-
+ case ma of
+ Just ast -> do
+ putStrLn $
+ BL.unpack $
+ encode $
+ alterGenericSyntaxTree cleanupIdentifiers $
+ toGenericSyntaxTree $
+ fmap
+ (const (Nothing :: Maybe Value))
+ ast
+ return ExitSuccess
+ Nothing -> do
+ putStrLn "\x1b[1;31mCompilation Failed\x1b[0m"
+ return (ExitFailure 1)
- forM_ diags printDiagnostic
- exitWith ec
- (diags, _) -> do
- putStrLn "\x1b[1;31mParsing Failed\x1b[0m"
- forM_ diags printDiagnostic
- exitWith (ExitFailure 1)
- _ -> do
- putStrLn "Wrong Args"
- exitWith (ExitFailure 2)
+ forM_ diags printDiagnostic
+ exitWith ec
+ (diags, _) -> do
+ putStrLn "\x1b[1;31mParsing Failed\x1b[0m"
+ forM_ diags printDiagnostic
+ exitWith (ExitFailure 1)
cleanupIdentifiers :: GenericSyntaxTree Identity a -> Maybe (GenericSyntaxTree Identity a)
cleanupIdentifiers (SyntaxTreeObject _ _ _ tr)