diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-09-28 17:23:32 -0600 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-09-28 17:23:32 -0600 |
commit | 719c8f8ed3d1e6337f27d3b9d5a033a4b63726b8 (patch) | |
tree | 80008d173d549ff3a347b1614d41adfb12e3e8bf | |
parent | 35b7ae9561b3dc312b857cadb3e99e14594d29a6 (diff) | |
download | fiddle-719c8f8ed3d1e6337f27d3b9d5a033a4b63726b8.tar.gz fiddle-719c8f8ed3d1e6337f27d3b9d5a033a4b63726b8.tar.bz2 fiddle-719c8f8ed3d1e6337f27d3b9d5a033a4b63726b8.zip |
wip
-rw-r--r-- | goal.fiddle | 2 | ||||
-rw-r--r-- | src/Language/Fiddle/Ast/Internal/Instances.hs | 18 | ||||
-rw-r--r-- | src/Language/Fiddle/Ast/Internal/Instances/Walk.hs | 78 | ||||
-rw-r--r-- | src/Language/Fiddle/Ast/Internal/SyntaxTree.hs | 74 | ||||
-rw-r--r-- | src/Language/Fiddle/Compiler/ConsistencyCheck.hs | 19 | ||||
-rw-r--r-- | src/Language/Fiddle/Compiler/ImportResolution.hs | 30 | ||||
-rw-r--r-- | src/Language/Fiddle/Internal/Scopes.hs | 7 |
7 files changed, 180 insertions, 48 deletions
diff --git a/goal.fiddle b/goal.fiddle index 708a44d..e6e6a28 100644 --- a/goal.fiddle +++ b/goal.fiddle @@ -22,6 +22,8 @@ package stm32l4.gpio { location gpio_b_base = 0x4800_0400; location gpio_c_base = 0x4800_0800; + import "/usr/fiddle/import/other_import.fdl"; + using stm32l432; /** diff --git a/src/Language/Fiddle/Ast/Internal/Instances.hs b/src/Language/Fiddle/Ast/Internal/Instances.hs index b8f6072..c9c3455 100644 --- a/src/Language/Fiddle/Ast/Internal/Instances.hs +++ b/src/Language/Fiddle/Ast/Internal/Instances.hs @@ -1,6 +1,14 @@ {-# LANGUAGE FunctionalDependencies #-} -module Language.Fiddle.Ast.Internal.Instances where +module Language.Fiddle.Ast.Internal.Instances + ( module X, + Alter (..), + AdvanceStage (..), + CompilationStage (..), + Annotated (..), + GAnnot (..) + ) +where import Data.Functor.Identity import Data.Kind @@ -10,6 +18,7 @@ import Data.Typeable import GHC.Generics import GHC.TypeError as TypeError import GHC.TypeLits +import Language.Fiddle.Ast.Internal.Instances.Walk as X import Language.Fiddle.Ast.Internal.Kinds import Language.Fiddle.Ast.Internal.Stage @@ -40,13 +49,6 @@ class Alter (t :: SynTree) where m (t f2 a2) alter ffn fn t = to <$> galter (proxyOf t) ffn fn (from t) -class (Typeable t) => Visit (t :: SynTree) where - visit :: - (Typeable f, Typeable a, Monad m) => - (forall t'. (Typeable t') => t' f a -> m ()) -> - t f a -> - m () - -- | 'CompilationStage' is a type class representing a stage in the compiler -- pipeline. Each 'stage' has associated types that define how it transforms -- syntax trees, manages state, and handles annotations. diff --git a/src/Language/Fiddle/Ast/Internal/Instances/Walk.hs b/src/Language/Fiddle/Ast/Internal/Instances/Walk.hs new file mode 100644 index 0000000..6feaff3 --- /dev/null +++ b/src/Language/Fiddle/Ast/Internal/Instances/Walk.hs @@ -0,0 +1,78 @@ +module Language.Fiddle.Ast.Internal.Instances.Walk (Walk (..), GWalk (..)) where + +import Data.Foldable (foldlM) +import Data.Typeable +import GHC.Generics + +class (Typeable t) => Walk t where + walk :: + (Monad m, Traversable f, Typeable f, Typeable a) => + (forall t'. (Walk t', Typeable t', Typeable f, Typeable a) => t' f a -> s -> m s) -> + t f a -> + s -> + m () + default walk :: + (GWalk (Rep (t f a)) f a, Generic (t f a), Monad m, Traversable f, Typeable f, Typeable a) => + (forall t'. (Walk t', Typeable t', Typeable f, Typeable a) => t' f a -> s -> m s) -> + t f a -> + s -> + m () + walk fn = gwalk fn . from + +class GWalk r f a where + gwalk :: + (Monad m, Typeable f, Typeable a, Traversable f) => + (forall t'. (Walk t', Typeable t') => t' f a -> s -> m s) -> + r x -> + s -> + m () + +instance (Traversable f, GWalk t f a) => (GWalk (M1 i c t) f a) where + gwalk fn (M1 a) = gwalk fn a + +instance + ( Traversable f, + GWalk l f a, + GWalk r f a + ) => + (GWalk (l :+: r) f a) + where + gwalk fn (L1 l) = gwalk fn l + gwalk fn (R1 l) = gwalk fn l + +instance + ( Traversable f, + GWalk l f a, + GWalk r f a + ) => + (GWalk (l :*: r) f a) + where + gwalk fn (l :*: r) s = gwalk fn l s >> gwalk fn r s + +instance + ( Traversable f, + Walk t + ) => + GWalk (Rec0 (t f a)) f a + where + gwalk fn (K1 k) s = do + s' <- fn k s + walk fn k s' + +instance + ( Traversable f, + Traversable func, + Walk t + ) => + GWalk (Rec0 (func (t f a))) f a + where + gwalk fn (K1 fk) s = do + mapM_ + ( \tfa -> do + s' <- fn tfa s + walk fn tfa s' + ) + fk + +instance GWalk (Rec0 q) f a where + gwalk _ _ _ = return () diff --git a/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs b/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs index c37be87..706a178 100644 --- a/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs +++ b/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs @@ -51,6 +51,7 @@ module Language.Fiddle.Ast.Internal.SyntaxTree ) where +import Control.Monad (forM_) import Data.Coerce import Data.Functor.Identity import Data.Kind (Type) @@ -70,6 +71,9 @@ import Language.Fiddle.Ast.Internal.Kinds import Language.Fiddle.Ast.Internal.Stage import Language.Fiddle.Internal.UnitInterface (UnitInterface) +type family FiddleUnitInterface (s :: Stage) :: Type where + FiddleUnitInterface s = If (s < Checked) () UnitInterface + -- | The Type of number during each stage of compilation. When in the first stage, -- numbers are just strings like anything else. In later stages, numbers get -- parsed into actual integers. This makes it easier to process later. @@ -103,7 +107,7 @@ type family WitnessType (s :: Bool) where -- to different packages. data Name :: SynTree where Name :: NonEmpty (Identifier f a) -> a -> Name f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents a directive in the Fiddle language. A directive provides -- additional metadata or instructions that the compiler can use during @@ -117,7 +121,7 @@ data Directive :: SynTree where directiveAnnot :: a } -> Directive f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents the body of a directive, which consists of multiple elements. data DirectiveBody :: SynTree where @@ -128,7 +132,7 @@ data DirectiveBody :: SynTree where directiveBodyAnnot :: a } -> DirectiveBody f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents an element in a directive. Can be either a key or a key-value -- pair. @@ -157,7 +161,7 @@ data DirectiveElement :: SynTree where directiveKeyValueAnnot :: a } -> DirectiveElement f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents expressions that can be used within a directive, either a -- string or a number. @@ -176,7 +180,7 @@ data DirectiveExpression f a where directiveNumberAnnot :: a } -> DirectiveExpression f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | A type that wraps another syntax tree and applies a list of directives to -- it. @@ -192,6 +196,18 @@ data Directed t stage f a where Directed t stage f a deriving (Generic, Annotated, Alter, Typeable) +instance + (Typeable (Directed t stage), Walk (t stage)) => + Walk (Directed t stage) + where + walk fn (Directed directives subtree _) s = do + s' <- fn subtree s + walk fn subtree s' + + forM_ directives $ \d -> do + s' <- fn d s + walk fn d s' + -- | Apply a function to the underlying subtree in a 'Directed' type. mapDirected :: (t s f a -> t' s' f a) -> Directed t s f a -> Directed t' s' f a mapDirected fn (Directed dr tfa a) = Directed dr (fn tfa) a @@ -219,11 +235,14 @@ data FiddleUnit (stage :: Stage) (f :: Type -> Type) a where FiddleUnit :: { -- | List of declarations. fiddleDecls :: [Directed FiddleDecl stage f a], + -- | The interface for this FiddleUnit. Early on, this is just () because + -- not enough information is provided to determine the interface.. + fiddleUnitInterface :: FiddleUnitInterface stage, -- | Annotation for the 'FiddleUnit'. fiddleUnitAnnot :: a } -> FiddleUnit stage f a - deriving (Generic, Annotated, Typeable, Alter) + deriving (Generic, Annotated, Typeable, Alter, Walk) -- | Represents an identifier with an associated annotation. data Identifier f a = Identifier @@ -232,7 +251,7 @@ data Identifier f a = Identifier -- | Annotation for the identifier. identifierAnnot :: a } - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Expressions used within Fiddle, including literals and variables. data Expression (s :: Stage) :: SynTree where @@ -252,7 +271,7 @@ data Expression (s :: Stage) :: SynTree where varAnnot :: a } -> Expression stage f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents an import statement in the Fiddle language. data ImportStatement stage f a where @@ -261,14 +280,12 @@ data ImportStatement stage f a where importPath :: Text, -- | Optional list of imported items. importList :: Maybe (ImportList f a), - importInterface :: ImportInterface stage, - -- | Annotation for the import statement. importStatementAnnot :: a } -> ImportStatement stage f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | A list of imported identifiers. data ImportList f a where @@ -279,7 +296,7 @@ data ImportList f a where importListAnnot :: a } -> ImportList f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents top-level declarations in Fiddle. data FiddleDecl :: StagedSynTree where @@ -297,12 +314,11 @@ data FiddleDecl :: StagedSynTree where ImportDecl :: { -- | The imported type. importStatement :: ImportStatement stage f a, + -- \| Annotation for the import declaration. -- | The interface for this imported file. This type depends on the stage -- of compilation. Initially it's just '()', but will eventually be resolved -- into a 'UnitInterface'. - - -- | Annotation for the import declaration. importDeclAnnot :: a } -> FiddleDecl stage f a @@ -366,7 +382,7 @@ data FiddleDecl :: StagedSynTree where objectAnnot :: a } -> FiddleDecl stage f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents the body of an object type, containing a body type (struct or -- union), a list of object declarations, and an annotation. @@ -380,7 +396,7 @@ data ObjTypeBody (stage :: Stage) (f :: Type -> Type) a where objBodyAnnot :: a } -> ObjTypeBody stage f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents an object type, which can be anonymous, an array, or a -- reference to another type. @@ -413,7 +429,7 @@ data ObjType stage f a where refAnnot :: a } -> ObjType stage f a - deriving (Typeable, Generic, Alter, Annotated, Typeable) + deriving (Typeable, Generic, Alter, Annotated, Typeable, Walk) -- | Represents a declaration inside an object type, such as a register, an -- assertion, or a substructure. @@ -460,7 +476,7 @@ data ObjTypeDecl stage f a where subStructureAnnot :: a } -> ObjTypeDecl stage f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents a modifier for registers (e.g., read-only, read-write). data Modifier f a where @@ -471,7 +487,7 @@ data Modifier f a where modifierAnnot :: a } -> Modifier f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Enumerates the different types of register modifiers. data ModifierKeyword = Rw | Ro | Wo @@ -487,7 +503,7 @@ data DeferredRegisterBody stage f a where deferredAnnot :: a } -> DeferredRegisterBody stage f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents the body type (struct or union) in an object. data BodyType (f :: Type -> Type) a where @@ -501,7 +517,7 @@ data BodyType (f :: Type -> Type) a where structAnnot :: a } -> BodyType f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents a register body with a body type and deferred bit declarations. data RegisterBody stage f a where @@ -514,7 +530,7 @@ data RegisterBody stage f a where regBodyAnnot :: a } -> RegisterBody stage f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents declarations within a register, such as defined bits, -- reserved bits, or substructures. @@ -549,7 +565,7 @@ data RegisterBitsDecl stage f a where bitsSubAnnot :: a } -> RegisterBitsDecl stage f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents different ways to refer to register bits, either as an array, -- a reference to a type, an anonymous type, or just bits. @@ -590,7 +606,7 @@ data RegisterBitsTypeRef stage f a where justBitsAnnot :: a } -> RegisterBitsTypeRef stage f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents an anonymous bit type, such as an enum, used in Parsed. data AnonymousBitsType stage f a where @@ -603,7 +619,7 @@ data AnonymousBitsType stage f a where anonEnumAnnot :: a } -> AnonymousBitsType stage f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents a bit type, either an enumeration or raw bits. data BitType (stage :: Stage) (f :: Type -> Type) a where @@ -625,7 +641,7 @@ data BitType (stage :: Stage) (f :: Type -> Type) a where rawBitsAnnot :: a } -> BitType stage f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents the body of an enumeration. data EnumBody (stage :: Stage) (f :: Type -> Type) a where @@ -636,7 +652,7 @@ data EnumBody (stage :: Stage) (f :: Type -> Type) a where enumBodyAnnot :: a } -> EnumBody stage f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents a declaration for an enumeration constant. data EnumConstantDecl stage f a where @@ -658,7 +674,7 @@ data EnumConstantDecl stage f a where enumReservedAnnot :: a } -> EnumConstantDecl stage f a - deriving (Generic, Annotated, Alter, Typeable) + deriving (Generic, Annotated, Alter, Typeable, Walk) -- | Represents the body of a package, containing a list of declarations. data PackageBody (stage :: Stage) (f :: Type -> Type) a where @@ -669,7 +685,7 @@ data PackageBody (stage :: Stage) (f :: Type -> Type) a where packageBodyAnnot :: a } -> PackageBody stage f a - deriving (Generic, Annotated, Typeable, Alter) + deriving (Generic, Annotated, Typeable, Alter, Walk) squeeze :: (Alter t, Traversable f, Monad f) => t f a -> f (t Identity a) squeeze = alter (fmap Identity) return diff --git a/src/Language/Fiddle/Compiler/ConsistencyCheck.hs b/src/Language/Fiddle/Compiler/ConsistencyCheck.hs index 5c7b399..908db52 100644 --- a/src/Language/Fiddle/Compiler/ConsistencyCheck.hs +++ b/src/Language/Fiddle/Compiler/ConsistencyCheck.hs @@ -33,12 +33,15 @@ import GHC.TypeLits import Language.Fiddle.Ast import Language.Fiddle.Compiler import Language.Fiddle.Internal.Scopes +import Language.Fiddle.Internal.UnitInterface import Language.Fiddle.Types (Commented (unCommented), SourceSpan) import Text.Printf (printf) import Prelude hiding (unzip) -newtype GlobalState = GlobalState - { globalScope :: Scope String (Either SizeBits SizeBytes) +data GlobalState = GlobalState + { globalScope :: Scope String (Either SizeBits SizeBytes), + fileDependencies :: [FilePath], + unitInterface :: UnitInterface } newtype LocalState = LocalState (ScopePath String) @@ -61,7 +64,7 @@ checkConsistency :: Compile () (FiddleUnit Checked I Annot) checkConsistency = fmap snd - . subCompile (GlobalState mempty) + . subCompile (GlobalState mempty mempty) . advanceStage (LocalState mempty) instance CompilationStage Checked where @@ -78,7 +81,11 @@ instance CompilationStage Expanded where type StageFunctor Expanded = Identity type StageAnnotation Expanded = Commented SourceSpan -deriving instance AdvanceStage Expanded FiddleUnit +instance AdvanceStage Expanded FiddleUnit + +-- advanceStage localState (FiddleUnit decls _ annot) = do + +-- decls' <- mapM (advanceStage localState) decls deriving instance AdvanceStage Expanded Expression @@ -528,7 +535,7 @@ insertTypeSize :: Compile GlobalState () insertTypeSize (LocalState scopePath) (Identifier s annot) size = do modifyM $ - \(GlobalState globalScope) -> + \state@GlobalState {globalScope = globalScope} -> let fullName = NonEmpty.prependList (currentScope scopePath) @@ -537,7 +544,7 @@ insertTypeSize (LocalState scopePath) (Identifier s annot) size = do (Just _, _) -> do diagnosticError (printf "Duplicate type %s" s) annot compilationFailure - (Nothing, n) -> return $ GlobalState n + (Nothing, n) -> return $ state {globalScope = n} where modifyM fn = do s <- get diff --git a/src/Language/Fiddle/Compiler/ImportResolution.hs b/src/Language/Fiddle/Compiler/ImportResolution.hs index 90a11d5..47eec72 100644 --- a/src/Language/Fiddle/Compiler/ImportResolution.hs +++ b/src/Language/Fiddle/Compiler/ImportResolution.hs @@ -1,3 +1,6 @@ +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE GeneralisedNewtypeDeriving #-} + module Language.Fiddle.Compiler.ImportResolution ( resolveImports, getImportResolutionState, @@ -6,11 +9,12 @@ module Language.Fiddle.Compiler.ImportResolution where import Control.Monad.Identity (Identity) -import Control.Monad.Writer.Lazy (MonadWriter (tell)) +import Control.Monad.Writer.Lazy (MonadTrans (lift), MonadWriter (tell), WriterT (WriterT), execWriterT) import Data.Map (Map) import qualified Data.Map as Map import Data.Text (Text) import qualified Data.Text as Text +import Data.Typeable import Language.Fiddle.Ast import Language.Fiddle.Ast.FileInterface (ResolvedImport) import Language.Fiddle.Compiler @@ -18,6 +22,7 @@ import Language.Fiddle.Compiler.Expansion import Language.Fiddle.Internal.UnitInterface import Language.Fiddle.Types import Options.Applicative +import System.IO (hPutStrLn, stderr) import Text.Printf (printf) newtype Flags = Flags @@ -55,6 +60,7 @@ data ImportError = ImportError Text (Maybe SourceSpan) newtype ResolvedImports = ResolvedImports { importMap :: Map Text (Either ImportError UnitInterface) } + deriving newtype (Semigroup, Monoid) type CurrentStage = Parsed @@ -129,4 +135,24 @@ getImportResolutionState :: Flags -> FiddleUnit CurrentStage Identity Annot -> IO ResolvedImports -getImportResolutionState _ _ = return (ResolvedImports mempty) +getImportResolutionState flags unit = + execWriterT $ + walk doWalk unit () + where + -- doWalk :: forall t'. (Walk t', Typeable t') => t' Identity Annot -> () -> WriterT ResolvedImports IO () + doWalk u () = + case () of + () | Just (ImportStatement {importPath = path}) <- castTS u -> do + lift $ hPutStrLn stderr $ "Import path: " ++ show path + (return () :: WriterT ResolvedImports IO ()) + _ -> return () + + castTS :: + ( Typeable t', + Typeable t, + Typeable f, + Typeable a + ) => + t' f a -> + Maybe (t CurrentStage f a) + castTS = cast diff --git a/src/Language/Fiddle/Internal/Scopes.hs b/src/Language/Fiddle/Internal/Scopes.hs index 83ea144..eea4c6f 100644 --- a/src/Language/Fiddle/Internal/Scopes.hs +++ b/src/Language/Fiddle/Internal/Scopes.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE DeriveFoldable #-} + module Language.Fiddle.Internal.Scopes where import Control.Monad (forM) @@ -14,7 +16,7 @@ data Scope k v = Scope { subScopes :: Map k (Scope k v), -- Nested sub-scopes scopeValues :: Map k v -- Values stored in the current scope } - deriving (Eq, Ord, Show, Read) + deriving (Eq, Ord, Show, Read, Functor, Foldable) -- | 'ScopePath' keeps track of the current scope path as a list of keys, -- and also includes any additional paths (like imported modules or @@ -50,7 +52,7 @@ instance Monoid (ScopePath k) where -- final key is replaced, and the original value is returned in the result. -- If the key path does not exist, it is created. The function returns a tuple -- containing the previous value (if any) and the updated scope. --- +-- -- This function effectively performs an "insert-or-update" operation, allowing -- you to upsert values into nested scopes while tracking any existing value -- that was replaced. @@ -65,7 +67,6 @@ upsertScope (s :| (a : as)) v (Scope ss sv) = -- insertScope :: (Ord k) => NonEmpty k -> t -> Scope k t -> Scope k t -- insertScope a b = snd . upsertScope a b - -- | 'lookupScope' performs a lookup of a value in the scope using a key path -- ('NonEmpty k'). It traverses through sub-scopes as defined by the path. lookupScope :: (Ord k) => NonEmpty k -> Scope k t -> Maybe t |