diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-09-25 00:17:19 -0600 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-09-25 00:17:19 -0600 |
commit | fffe42ce4861f53dd86113ab8320e4754f2c570c (patch) | |
tree | d9fb492c4c821eec091b2012ffe626cda45f1bde | |
parent | 0c6ada2f5c8a3ac900fabd0384af558fb6bd334a (diff) | |
download | fiddle-fffe42ce4861f53dd86113ab8320e4754f2c570c.tar.gz fiddle-fffe42ce4861f53dd86113ab8320e4754f2c570c.tar.bz2 fiddle-fffe42ce4861f53dd86113ab8320e4754f2c570c.zip |
Split the Ast file into multiple sub files.
Make some more changes to the generic implementation of EasySwitchStage.
-rw-r--r-- | src/Language/Fiddle/Ast.hs | 566 | ||||
-rw-r--r-- | src/Language/Fiddle/Ast/FileInterface.hs | 33 | ||||
-rw-r--r-- | src/Language/Fiddle/Ast/Internal/Generic.hs | 5 | ||||
-rw-r--r-- | src/Language/Fiddle/Ast/Internal/Instances.hs | 228 | ||||
-rw-r--r-- | src/Language/Fiddle/Ast/Internal/Kinds.hs | 25 | ||||
-rw-r--r-- | src/Language/Fiddle/Ast/Internal/Stage.hs | 43 | ||||
-rw-r--r-- | src/Language/Fiddle/Ast/Internal/SyntaxTree.hs | 537 | ||||
-rw-r--r-- | src/Language/Fiddle/Ast/Internal/SyntaxTreeKinds.hs | 1 | ||||
-rw-r--r-- | src/Language/Fiddle/Compiler/Stage1.hs | 16 | ||||
-rw-r--r-- | src/Language/Fiddle/Compiler/Stage2.hs | 220 | ||||
-rw-r--r-- | src/Language/Fiddle/GenericTree.hs | 99 | ||||
-rw-r--r-- | src/Language/Fiddle/Parser.hs | 8 |
12 files changed, 1031 insertions, 750 deletions
diff --git a/src/Language/Fiddle/Ast.hs b/src/Language/Fiddle/Ast.hs index 8680790..7ef12da 100644 --- a/src/Language/Fiddle/Ast.hs +++ b/src/Language/Fiddle/Ast.hs @@ -1,570 +1,24 @@ {-# LANGUAGE ConstraintKinds #-} -{-# LANGUAGE DefaultSignatures #-} -{-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE IncoherentInstances #-} -{-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} -module Language.Fiddle.Ast where +module Language.Fiddle.Ast (module X) where +import Data.Coerce import Data.Functor.Identity import Data.Kind (Type) import Data.List.NonEmpty import Data.Proxy import Data.Text (Text) import Data.Traversable +import Data.Type.Bool +import Data.Type.Equality import Data.Typeable +import Data.Void (Void, absurd) import GHC.Generics +import qualified GHC.TypeError as TypeError import GHC.TypeLits - --- The Kind types should have for SyntaxTrees. --- --- A synatx tree kind should take as parameters, an applicative functor for the --- first argument. This applicative functor allows errors and warnings to be --- contained to their deferred regions during compilation, so more errors may be --- reported an once. --- --- The second argument is the annotation type. Every syntax tree element has an --- annotation. When initially parsing, this annotation is a list of comments --- that came before the element and the source position of the element. -type SynTreeKind = (Type -> Type) -> Type -> Type - --- 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. -type family NumberType (a :: Stage) :: Type where - NumberType Stage1 = Text - NumberType Stage2 = Integer - NumberType Stage3 = Integer - --- The type that represents an import statement. In the early stages of --- compilation, this is just a string representing the import path, but in later --- stages of compilation, this actually gets replaced by an abstract --- representation of the imported material. -type family ImportType (stage :: Stage) :: SynTreeKind where - ImportType Stage1 = ImportStatement - ImportType Stage2 = ImportStatement - ImportType Stage3 = ImportStatement - --- Type-level constraint to determine if a stage is less than some natural --- ordinal. Used to bound parts of the AST in multiple stages. -type StageLessThan stage (n :: Natural) = (CmpNat (StageNumber stage) n ~ LT) - --- A Name is multiple identifiers separated by dots. It's the way of namespaces --- to different packages. -data Name f a where - Name :: NonEmpty (Identifier f a) -> a -> Name f a - deriving (Generic, Annotated, Alter, Typeable) - --- [[packed, rust: name="field_name"]] -data Directive f a where - Directive :: f (DirectiveBody f a) -> a -> Directive f a - deriving (Generic, Annotated, Alter, Typeable) - -data DirectiveBody f a where - DirectiveBody :: [DirectiveElement f a] -> a -> DirectiveBody f a - deriving (Generic, Annotated, Alter, Typeable) - -data DirectiveElement f a where - -- <key> - DirectiveElementKey :: - Maybe (Identifier f a) -> Identifier f a -> a -> DirectiveElement f a - -- (<backend>:)? <key>=<value> - DirectiveElementKeyValue :: - Maybe (Identifier f a) -> - Identifier f a -> - DirectiveExpression f a -> - a -> - DirectiveElement f a - deriving (Generic, Annotated, Alter, Typeable) - -data DirectiveExpression f a where - DirectiveString :: Text -> a -> DirectiveExpression f a - DirectiveNumber :: Text -> a -> DirectiveExpression f a - deriving (Generic, Annotated, Alter, Typeable) - -data Directed t f a where - Directed :: [Directive f a] -> t f a -> a -> Directed t f a - deriving (Generic, Annotated, Alter, Typeable) - -mapDirected :: (t f a -> t' f a) -> Directed t f a -> Directed t' f a -mapDirected fn (Directed dr tfa a) = Directed dr (fn tfa) a - -mapDirectedM :: - (Monad m) => (t f a -> m (t' f a)) -> Directed t f a -> m (Directed t' f a) -mapDirectedM fn (Directed dr tfa a) = Directed dr <$> fn tfa <*> pure a - -asDirected :: (Annotated t) => t f a -> Directed t f a -asDirected tfa = Directed [] tfa (annot tfa) - -undirected :: Directed t f a -> t f a -undirected (Directed _ tfa _) = tfa - --- Stage of compilation. Parts of the AST maybe un unavailable with other stages --- as compilation simplifies the AST. -data Stage = Stage1 | Stage2 | Stage3 - deriving (Typeable) - --- Root of the parse tree. Just contains a list of declarations. -data FiddleUnit (stage :: Stage) (f :: Type -> Type) a where - FiddleUnit :: [Directed (FiddleDecl stage) f a] -> a -> FiddleUnit stage f a - deriving (Generic, Annotated, Typeable) - -deriving instance (Alter (ImportType stage)) => Alter (FiddleUnit stage) - --- Just an identifier. -data Identifier f a = Identifier !Text a - deriving (Generic, Annotated, Alter, Typeable) - --- Expression. -data Expression stage f a where - -- Just a string. Parsing the number comes in stage2. - LitNum :: NumberType stage -> a -> Expression stage f a - Var :: Identifier f a -> a -> Expression stage f a - --- Wrapper class because using a type family like "ImportType" means I cannot --- derive classes. I'd rather only derive for this class than have to derive for --- the whole PackageBody class. -data ImportTypeWrapper stage f a where - ImportTypeWrapper :: ImportType stage f a -> ImportTypeWrapper stage f a - -instance (Alter (ImportType stage)) => Alter (ImportTypeWrapper stage) where - alter ffn fn (ImportTypeWrapper st) = - ImportTypeWrapper <$> alter ffn fn st - -data ImportStatement f a where - ImportStatement :: Text -> Maybe (ImportList f a) -> a -> ImportStatement f a - deriving (Generic, Annotated, Alter, Typeable) - -data ImportList f a where - ImportList :: [Identifier f a] -> a -> ImportList f a - deriving (Generic, Annotated, Alter, Typeable) - --- Top-level declarations. -data FiddleDecl (stage :: Stage) (f :: Type -> Type) a where - {- - - An option is a key/value pair. - - option <ident> <ident>; - -} - OptionDecl :: - Identifier f a -> - Identifier f a -> - a -> - FiddleDecl stage f a - ImportDecl :: - ImportType stage f a -> - a -> - FiddleDecl stage f a - UsingDecl :: - Name f a -> a -> FiddleDecl stage f a - {- Package Statement. Package Name, Package body -} - PackageDecl :: - Name f a -> - f (PackageBody stage f a) -> - a -> - FiddleDecl stage f a - {- location <identifier> = <expr>. -} - LocationDecl :: - Identifier f a -> - Expression stage f a -> - a -> - FiddleDecl stage f a - {- bits <identifier> : <type> -} - BitsDecl :: - Identifier f a -> - BitType stage f a -> - a -> - FiddleDecl stage f a - {- objtype <identifier> : <type> -} - ObjTypeDecl :: - Identifier f a -> - f (ObjTypeBody stage f a) -> - a -> - FiddleDecl stage f a - {- object <ident> at <expr> : <type> -} - ObjectDecl :: - Identifier f a -> - Expression stage f a -> - ObjType stage f a -> - a -> - FiddleDecl stage f a - deriving (Generic, Annotated, Typeable) - -deriving instance (Alter (ImportType stage)) => Alter (FiddleDecl stage) - -data ObjTypeBody (stage :: Stage) (f :: Type -> Type) a where - ObjTypeBody :: - BodyType f a -> - [Directed (ObjTypeDecl stage) f a] -> - a -> - ObjTypeBody stage f a - deriving (Generic, Annotated, Alter, Typeable) - -data ObjType stage f a where - -- { <body> } - -- Anonymous types are only allowed in stage1. Stage2 should have them be - -- de-anonymized. - AnonymousObjType :: f (ObjTypeBody 'Stage1 f a) -> a -> ObjType 'Stage1 f a - -- <type>[<expr>] - ArrayObjType :: ObjType stage f a -> Expression stage f a -> a -> ObjType stage f a - -- <identifier> - ReferencedObjType :: Name f a -> a -> ObjType stage f a - deriving (Typeable) - -data ObjTypeDecl stage f a where - {- assert_pos(<expr>) -} - AssertPosStatement :: - (StageLessThan stage 3) => - Expression stage f a -> - a -> - ObjTypeDecl stage f a - {- reg <ident>(<expr>) : <regtype> -} - RegisterDecl :: - Maybe (Modifier f a) -> - Maybe (Identifier f a) -> - Expression stage f a -> - Maybe (RegisterBody stage f a) -> - a -> - ObjTypeDecl stage f a - {- reserved(n); -} - ReservedDecl :: Expression stage f a -> a -> ObjTypeDecl stage f a - {- <struct|union> { subfields } <name>; -} - TypeSubStructure :: - f (ObjTypeBody stage f a) -> - Maybe (Identifier f a) -> - a -> - ObjTypeDecl stage f a - deriving (Typeable) - -data Modifier f a where - ModifierKeyword :: ModifierKeyword -> a -> Modifier f a - deriving (Generic, Annotated, Alter, Typeable) - -data ModifierKeyword = Rw | Ro | Wo deriving (Eq, Ord, Show, Read, Typeable) - -data DeferredRegisterBody stage f a where - DeferredRegisterBody :: - [Directed (RegisterBitsDecl stage) f a] -> - a -> - DeferredRegisterBody stage f a - deriving (Generic, Annotated, Alter, Typeable) - -data BodyType (f :: Type -> Type) a where - Union :: a -> BodyType f a - Struct :: a -> BodyType f a - deriving (Generic, Annotated, Alter, Typeable) - -data RegisterBody stage f a where - RegisterBody :: - BodyType f a -> - f (DeferredRegisterBody stage f a) -> - a -> - RegisterBody stage f a - deriving (Generic, Annotated, Alter, Typeable) - -data RegisterBitsDecl stage f a where - -- reserved(<expr>) - ReservedBits :: Expression stage f a -> a -> RegisterBitsDecl stage f a - -- <modifer> <ident> : <type> - DefinedBits :: - Maybe (Modifier f a) -> - Identifier f a -> - RegisterBitsTypeRef stage f a -> - a -> - RegisterBitsDecl stage f a - BitsSubStructure :: - RegisterBody stage f a -> - Maybe (Identifier f a) -> - a -> - RegisterBitsDecl stage f a - deriving (Generic, Annotated, Alter, Typeable) - -data RegisterBitsTypeRef stage f a where - -- <type>[<expr>] - RegisterBitsArray :: - RegisterBitsTypeRef stage f a -> - Expression stage f a -> - a -> - RegisterBitsTypeRef stage f a - {- Reference to a type. -} - RegisterBitsReference :: Name f a -> a -> RegisterBitsTypeRef stage f a - {- enum(<expr>) { <body> } - Anonymous types are only allowed in stage1. - Stage2 should de-anonymize these type. -} - RegisterBitsAnonymousType :: - AnonymousBitsType Stage1 f a -> - a -> - RegisterBitsTypeRef 'Stage1 f a - {- (<expr>) - - - - The expression is just bits ... i.e. an integer. - -} - RegisterBitsJustBits :: - Expression stage f a -> - a -> - RegisterBitsTypeRef stage f a - -instance Alter (Expression stage) where - alter ffn fn = \case - LitNum t a -> LitNum t <$> fn a - Var i a -> Var <$> alter ffn fn i <*> fn a - -instance Annotated (Expression stage) where - annot = \case - LitNum _ a -> a - Var _ a -> a - -instance Alter (ObjTypeDecl stage) where - alter ffn fn = \case - (AssertPosStatement expr a) -> - AssertPosStatement <$> alter ffn fn expr <*> fn a - (RegisterDecl mMod mIdent expr mBody a) -> - RegisterDecl - <$> mapM (alter ffn fn) mMod - <*> mapM (alter ffn fn) mIdent - <*> alter ffn fn expr - <*> mapM (alter ffn fn) mBody - <*> fn a - (TypeSubStructure mBody mIdent a) -> - TypeSubStructure - <$> (ffn =<< mapM (alter ffn fn) mBody) - <*> mapM (alter ffn fn) mIdent - <*> fn a - (ReservedDecl expr a) -> - ReservedDecl - <$> alter ffn fn expr - <*> fn a - -instance Annotated (ObjTypeDecl stage) where - annot = \case - (AssertPosStatement _ a) -> a - (RegisterDecl _ _ _ _ a) -> a - -instance Alter (ObjType stage) where - alter ffn fn = \case - (AnonymousObjType b a) -> - AnonymousObjType <$> (ffn =<< mapM (alter ffn fn) b) <*> fn a - (ArrayObjType t e a) -> - ArrayObjType <$> alter ffn fn t <*> alter ffn fn e <*> fn a - (ReferencedObjType i a) -> - ReferencedObjType <$> alter ffn fn i <*> fn a - -instance Annotated (ObjType stage) where - annot = \case - (AnonymousObjType _ a) -> a - (ArrayObjType _ _ a) -> a - (ReferencedObjType _ a) -> a - -instance Alter (RegisterBitsTypeRef stage) where - alter ffn fn = \case - (RegisterBitsArray ref exp a) -> - RegisterBitsArray <$> alter ffn fn ref <*> alter ffn fn exp <*> fn a - (RegisterBitsReference i a) -> - RegisterBitsReference <$> alter ffn fn i <*> fn a - (RegisterBitsAnonymousType t a) -> - RegisterBitsAnonymousType <$> alter ffn fn t <*> fn a - (RegisterBitsJustBits e a) -> - RegisterBitsJustBits <$> alter ffn fn e <*> fn a - -instance Annotated (RegisterBitsTypeRef stage) where - annot = \case - (RegisterBitsArray _ _ a) -> a - (RegisterBitsReference _ a) -> a - (RegisterBitsAnonymousType _ a) -> a - (RegisterBitsJustBits _ a) -> a - -data AnonymousBitsType stage f a where - -- enum(<expr>) { <body> } - AnonymousEnumBody :: - Expression stage f a -> - f (EnumBody stage f a) -> - a -> - AnonymousBitsType stage f a - deriving (Generic, Annotated, Alter, Typeable) - -data BitType (stage :: Stage) (f :: Type -> Type) a where - -- enum(<expr>) { <body> } - EnumBitType :: - Expression stage f a -> - f (EnumBody stage f a) -> - a -> - BitType stage f a - -- (<expr>) - RawBits :: Expression stage f a -> a -> BitType stage f a - deriving (Generic, Annotated, Alter, Typeable) - -data EnumBody (stage :: Stage) (f :: Type -> Type) a where - -- <decl>, - EnumBody :: [Directed (EnumConstantDecl stage) f a] -> a -> EnumBody stage f a - deriving (Generic, Annotated, Alter, Typeable) - -data EnumConstantDecl stage f a where - -- <ident> = <expr> - EnumConstantDecl :: - Identifier f a -> - Expression stage f a -> - a -> - EnumConstantDecl stage f a - -- reserved = <expr> - EnumConstantReserved :: - Expression stage f a -> - a -> - EnumConstantDecl stage f a - deriving (Generic, Annotated, Alter, Typeable) - -data PackageBody (stage :: Stage) (f :: Type -> Type) a where - {- The body of a package -} - PackageBody :: [Directed (FiddleDecl stage) f a] -> a -> PackageBody stage f a - deriving (Generic, Annotated, Typeable) - -deriving instance (Alter (ImportType stage)) => Alter (PackageBody stage) - --- instance Alter (Modifier stage) where --- alter _ fn (ModifierKeyword m a) = ModifierKeyword m (fn a) --- --- instance Alter (Identifier) where --- alter _ fn (Identifier i a) = Identifier i $ fn a --- --- instance Alter (Expression stage) where --- alter ffn fn = \case --- (LitNum t a) -> LitNum t $ fn a --- (RealNum t a) -> RealNum t $ fn a --- (Var i a) -> Var (alter ffn fn i) $ fn a - -proxyOf :: t f a -> Proxy t -proxyOf _ = Proxy - -class Annotated (t :: SynTreeKind) where - annot :: t f a -> a - default annot :: (Generic (t f a), GAnnot a (Rep (t f a))) => t f a -> a - annot t = gannot (from t) - -class GAnnot a r where - gannot :: r x -> a - -instance GAnnot a (Rec0 a) where - gannot = unK1 - -instance (GAnnot a r) => GAnnot a (l :*: r) where - gannot (_ :*: r) = gannot r - -instance (GAnnot a r, GAnnot a l) => GAnnot a (l :+: r) where - gannot (R1 r) = gannot r - gannot (L1 l) = gannot l - -instance (GAnnot a r) => GAnnot a (M1 i c r) where - gannot (M1 a) = gannot a - -class Alter (t :: SynTreeKind) where - alter :: - forall f1 f2 a1 a2 m. - (Monad m, Traversable f1) => - (forall z. f1 z -> m (f2 z)) -> - (a1 -> m a2) -> - t f1 a1 -> - m (t f2 a2) - default alter :: - forall f1 f2 a1 a2 m. - ( Generic (t f1 a1), - Generic (t f2 a2), - Traversable f1, - GAlter t f1 f2 a1 a2 (Rep (t f1 a1)) (Rep (t f2 a2)), - Monad m - ) => - ( forall z. - f1 z -> - m (f2 z) - ) -> - (a1 -> m a2) -> - t f1 a1 -> - m (t f2 a2) - alter ffn fn t = to <$> galter (proxyOf t) ffn fn (from t) - -instance (Alter t, Traversable f) => Functor (t f) where - fmap f t = runIdentity (alter return (return . f) t) - -class GAlter t f1 f2 a1 a2 r1 r2 where - galter :: - forall proxy x m. - (Monad m, Traversable f1) => - proxy t -> - (forall z. f1 z -> m (f2 z)) -> - (a1 -> m a2) -> - r1 x -> - m (r2 x) - -{- Altering a record with type a1 will apply the mapping function and produce a - record with type a2 -} -instance GAlter t f1 f2 a1 a2 (Rec0 a1) (Rec0 a2) where - galter _ _ fn k1 = K1 <$> fn (unK1 k1) - -{- Base-Case. Altering unrelated leaf types will do nothing. -} -instance GAlter t f1 f2 a1 a2 (Rec0 u1) (Rec0 u1) where - galter _ _ _ = return - -{- Recursive case. Call alter on sub-structures. -} -instance - (Alter u) => - GAlter t f1 f2 a1 a2 (Rec0 (u f1 a1)) (Rec0 (u f2 a2)) - where - galter _ ffn fn k1 = - K1 <$> alter ffn fn (unK1 k1) - -{- Recursive case. Called when there are list of substructures that need to be - recused. -} -instance - (Alter u, Traversable l) => - GAlter t f1 f2 a1 a2 (Rec0 (l (u f1 a1))) (Rec0 (l (u f2 a2))) - where - galter _ ffn fn k1 = - K1 <$> mapM (alter ffn fn) (unK1 k1) - --- instance GAlter t f1 f2 a1 a2 (Rec0 (f1 z)) (Rec0 (f2 z)) where --- galter _ ffn _ k1 = K1 <$> ffn (unK1 k1) - -{- Generic altering. Descends into the function and alters whatever is inside - the functor and then transforms the functor using the ffn function. -} -instance - (Traversable f1, Alter u) => - GAlter t f1 f2 a1 a2 (Rec0 (f1 (u f1 a1))) (Rec0 (f2 (u f2 a2))) - where - galter proxy ffn fn k1 = do - newK <- mapM (alter ffn fn) (unK1 k1) - K1 <$> ffn newK - -instance - ( GAlter t f1 f2 a1 a2 l1 l2, - GAlter t f1 f2 a1 a2 r1 r2 - ) => - GAlter t f1 f2 a1 a2 (l1 :*: r1) (l2 :*: r2) - where - galter proxy ffn fn (a :*: b) = do - a' <- galter proxy ffn fn a - b' <- galter proxy ffn fn b - return (a' :*: b') - -instance - ( GAlter t f1 f2 a1 a2 l1 l2, - GAlter t f1 f2 a1 a2 r1 r2 - ) => - GAlter t f1 f2 a1 a2 (l1 :+: r1) (l2 :+: r2) - where - galter proxy ffn fn (R1 r) = R1 <$> galter proxy ffn fn r - galter proxy ffn fn (L1 l) = L1 <$> galter proxy ffn fn l - -instance - (GAlter t f1 f2 a1 a2 r1 r2) => - GAlter t f1 f2 a1 a2 (M1 i c r1) (M1 i c r2) - where - galter proxy ffn fn (M1 a) = M1 <$> galter proxy ffn fn a - -type family StageNumber (s :: Stage) :: Natural where - StageNumber Stage1 = 1 - StageNumber Stage2 = 2 - StageNumber Stage3 = 3 - -{--} -squeeze :: (Alter t, Traversable f, Monad f) => t f a -> f (t Identity a) -squeeze = alter (fmap Identity) return +import Language.Fiddle.Ast.Internal.Instances as X +import Language.Fiddle.Ast.Internal.Kinds as X +import Language.Fiddle.Ast.Internal.Stage as X +import Language.Fiddle.Ast.Internal.SyntaxTree as X diff --git a/src/Language/Fiddle/Ast/FileInterface.hs b/src/Language/Fiddle/Ast/FileInterface.hs new file mode 100644 index 0000000..d29fc9d --- /dev/null +++ b/src/Language/Fiddle/Ast/FileInterface.hs @@ -0,0 +1,33 @@ +module Language.Fiddle.Ast.FileInterface where + +-- Definitions for file interfaces. These interfaces contain an abstract +-- representation of the symbols and information exported by a fiddle file. +-- These interfaces are also serializable, and when compiling a fiddle file, all +-- the import statements should supply an fdi (fiddle interface) file to speed +-- up subsequent compilations. + +-- import Data.Text +-- +-- data ObjectType = ObjectType +-- { objectTypeSize :: Word32 +-- } +-- +-- data Metatype +-- = Object +-- { objectLocation :: Word64, +-- objectType :: Text +-- } +-- | Type +-- { typeSizeBytes :: Word32 +-- } +-- +-- data Element a = Element +-- { elementFullyQualifiedSymbol :: Text, +-- elementDocumentation :: Maybe Text, +-- elementMetatype :: Metatype, +-- elementAnnotation :: a +-- } +-- +-- data FileInterface a = FiddleInterface +-- { exportedElements :: [Element a] +-- } diff --git a/src/Language/Fiddle/Ast/Internal/Generic.hs b/src/Language/Fiddle/Ast/Internal/Generic.hs new file mode 100644 index 0000000..cb075cc --- /dev/null +++ b/src/Language/Fiddle/Ast/Internal/Generic.hs @@ -0,0 +1,5 @@ +{-# LANGUAGE TypeOperators #-} +module Language.Fiddle.Ast.Internal.Generic where + +import GHC.Generics +import GHC.TypeError as TypeError diff --git a/src/Language/Fiddle/Ast/Internal/Instances.hs b/src/Language/Fiddle/Ast/Internal/Instances.hs new file mode 100644 index 0000000..c8c606c --- /dev/null +++ b/src/Language/Fiddle/Ast/Internal/Instances.hs @@ -0,0 +1,228 @@ +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE DefaultSignatures #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE IncoherentInstances #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE UndecidableInstances #-} + +module Language.Fiddle.Ast.Internal.Instances where + +import Data.Functor.Identity +import Data.Kind (Type) +import Data.Typeable +import GHC.Generics +import GHC.TypeError as TypeError +import Language.Fiddle.Ast.Internal.Kinds +import Language.Fiddle.Ast.Internal.Stage + +-- Type class to easily switch between stages if there is no difference in the +-- syntax tree structure between these stages. Can make things much cleaner and +-- avoids the boilerplate and bugprone-ness of needing to rote copy everything. +class + (Functor f) => + EasySwitchStage + (t :: Stage -> SynTree) + (f :: Type -> Type) + (fromStage :: Stage) + (toStage :: Stage) + where + switchStage :: t fromStage f a -> t toStage f a + default switchStage :: + ( Generic (t fromStage f a), + Generic (t toStage f a), + GEasySwitchStage (Rep (t fromStage f a)) (Rep (t toStage f a)) + ) => + t fromStage f a -> + t toStage f a + switchStage t = to $ gSwitchStage (from t) + +-- Class for walking a syntax tree under the context of a monad and modifying +-- the different parts of the SynTree type.. +class Alter (t :: SynTree) where + alter :: + forall f1 f2 a1 a2 m. + (Monad m, Traversable f1) => + (forall z. f1 z -> m (f2 z)) -> + (a1 -> m a2) -> + t f1 a1 -> + m (t f2 a2) + default alter :: + forall f1 f2 a1 a2 m. + ( Generic (t f1 a1), + Generic (t f2 a2), + Traversable f1, + GAlter t f1 f2 a1 a2 (Rep (t f1 a1)) (Rep (t f2 a2)), + Monad m + ) => + ( forall z. + f1 z -> + m (f2 z) + ) -> + (a1 -> m a2) -> + t f1 a1 -> + m (t f2 a2) + alter ffn fn t = to <$> galter (proxyOf t) ffn fn (from t) + +-- A syntax tree object is annotated if it has an annotation 'a' as the last +-- element. +class Annotated (t :: SynTree) where + annot :: t f a -> a + default annot :: (Generic (t f a), GAnnot a (Rep (t f a))) => t f a -> a + annot t = gannot (from t) + +-- Generic implementations of common typeclass for SyntaxTrees. +-- +-- This is where we try to hide the pig behind the curtain. +-- +-- +-- --------------------------------------------------------------- +-- +-- +-- +class GAlter t f1 f2 a1 a2 r1 r2 where + galter :: + forall proxy x m. + (Monad m, Traversable f1) => + proxy t -> + (forall z. f1 z -> m (f2 z)) -> + (a1 -> m a2) -> + r1 x -> + m (r2 x) + +{- Altering a record with type a1 will apply the mapping function and produce a + record with type a2 -} +instance GAlter t f1 f2 a1 a2 (Rec0 a1) (Rec0 a2) where + galter _ _ fn k1 = K1 <$> fn (unK1 k1) + +{- Base-Case. Altering unrelated leaf types will do nothing. -} +instance GAlter t f1 f2 a1 a2 (Rec0 u1) (Rec0 u1) where + galter _ _ _ = return + +{- Recursive case. Call alter on sub-structures. -} +instance + (Alter u) => + GAlter t f1 f2 a1 a2 (Rec0 (u f1 a1)) (Rec0 (u f2 a2)) + where + galter _ ffn fn k1 = + K1 <$> alter ffn fn (unK1 k1) + +{- Recursive case. Called when there are list of substructures that need to be + recused. -} +instance + (Alter u, Traversable l) => + GAlter t f1 f2 a1 a2 (Rec0 (l (u f1 a1))) (Rec0 (l (u f2 a2))) + where + galter _ ffn fn k1 = + K1 <$> mapM (alter ffn fn) (unK1 k1) + +-- instance GAlter t f1 f2 a1 a2 (Rec0 (f1 z)) (Rec0 (f2 z)) where +-- galter _ ffn _ k1 = K1 <$> ffn (unK1 k1) + +{- Generic altering. Descends into the function and alters whatever is inside + the functor and then transforms the functor using the ffn function. -} +instance + (Traversable f1, Alter u) => + GAlter t f1 f2 a1 a2 (Rec0 (f1 (u f1 a1))) (Rec0 (f2 (u f2 a2))) + where + galter proxy ffn fn k1 = do + newK <- mapM (alter ffn fn) (unK1 k1) + K1 <$> ffn newK + +instance + ( GAlter t f1 f2 a1 a2 l1 l2, + GAlter t f1 f2 a1 a2 r1 r2 + ) => + GAlter t f1 f2 a1 a2 (l1 :*: r1) (l2 :*: r2) + where + galter proxy ffn fn (a :*: b) = do + a' <- galter proxy ffn fn a + b' <- galter proxy ffn fn b + return (a' :*: b') + +instance + ( GAlter t f1 f2 a1 a2 l1 l2, + GAlter t f1 f2 a1 a2 r1 r2 + ) => + GAlter t f1 f2 a1 a2 (l1 :+: r1) (l2 :+: r2) + where + galter proxy ffn fn (R1 r) = R1 <$> galter proxy ffn fn r + galter proxy ffn fn (L1 l) = L1 <$> galter proxy ffn fn l + +instance + (GAlter t f1 f2 a1 a2 r1 r2) => + GAlter t f1 f2 a1 a2 (M1 i c r1) (M1 i c r2) + where + galter proxy ffn fn (M1 a) = M1 <$> galter proxy ffn fn a + +class GAnnot a r where + gannot :: r x -> a + +instance GAnnot a (Rec0 a) where + gannot = unK1 + +instance (GAnnot a r) => GAnnot a (l :*: r) where + gannot (_ :*: r) = gannot r + +instance (GAnnot a r, GAnnot a l) => GAnnot a (l :+: r) where + gannot (R1 r) = gannot r + gannot (L1 l) = gannot l + +instance (GAnnot a r) => GAnnot a (M1 i c r) where + gannot (M1 a) = gannot a + +instance + (GEasySwitchStage s1 s2) => + GEasySwitchStage (M1 i c s1) (M1 i c s2) + where + gSwitchStage (M1 a) = M1 (gSwitchStage a) + +instance + (GEasySwitchStage l1 l2, GEasySwitchStage r1 r2) => + GEasySwitchStage (l1 :+: r1) (l2 :+: r2) + where + gSwitchStage (R1 r) = R1 $ gSwitchStage r + gSwitchStage (L1 l) = L1 $ gSwitchStage l + +instance + (GEasySwitchStage l1 l2, GEasySwitchStage r1 r2) => + (GEasySwitchStage (l1 :*: r1) (l2 :*: r2)) + where + gSwitchStage (l :*: r) = gSwitchStage l :*: gSwitchStage r + +instance + (EasySwitchStage t f fs ts) => + (GEasySwitchStage (Rec0 (t fs f a)) (Rec0 (t ts f a))) + where + gSwitchStage (K1 val) = K1 (switchStage val) + +instance + ( EasySwitchStage t f fs ts, + Functor func + ) => + (GEasySwitchStage (Rec0 (func (t fs f a))) (Rec0 (func (t ts f a)))) + where + gSwitchStage (K1 val) = K1 (switchStage <$> val) + +instance (GEasySwitchStage (Rec0 a) (Rec0 a)) where + gSwitchStage = id + +instance + ( TypeError + ( TypeError.Text "Unable to match type " + :<>: TypeError.ShowType a + :<>: TypeError.Text " with " + :<>: TypeError.ShowType b + ) + ) => + (GEasySwitchStage (Rec0 a) (Rec0 b)) + where + gSwitchStage = error "Cannot be called" + +class GEasySwitchStage r1 r2 where + gSwitchStage :: r1 x -> r2 x + +proxyOf :: t f a -> Proxy t +proxyOf _ = Proxy + +instance (Alter t, Traversable f) => Functor (t f) where + fmap f t = runIdentity (alter return (return . f) t) diff --git a/src/Language/Fiddle/Ast/Internal/Kinds.hs b/src/Language/Fiddle/Ast/Internal/Kinds.hs new file mode 100644 index 0000000..1368c84 --- /dev/null +++ b/src/Language/Fiddle/Ast/Internal/Kinds.hs @@ -0,0 +1,25 @@ + +module Language.Fiddle.Ast.Internal.Kinds where + +import Data.Kind (Type) +import Language.Fiddle.Ast.Internal.Stage + +-- The Kind types should have for SyntaxTrees. +-- +-- A synatx tree kind should take as parameters, an applicative functor for the +-- first argument. This applicative functor allows errors and warnings to be +-- contained to their deferred regions during compilation, so more errors may be +-- reported an once. +-- +-- The second argument is the annotation type. Every syntax tree element has an +-- annotation. When initially parsing, this annotation is a list of comments +-- that came before the element and the source position of the element. +-- +-- SynTree types are not dependent on the compilation stage. They're the same +-- regardless of the compilation stage. +type SynTree = (Type -> Type) -> Type -> Type + +-- A syntax tree which is dependent on the stage in compilation. As compilations +-- progress through stages, types in the syntax tree may change as things become +-- more and more machine readable. +type StagedSynTree = Stage -> SynTree diff --git a/src/Language/Fiddle/Ast/Internal/Stage.hs b/src/Language/Fiddle/Ast/Internal/Stage.hs new file mode 100644 index 0000000..cfcd0e6 --- /dev/null +++ b/src/Language/Fiddle/Ast/Internal/Stage.hs @@ -0,0 +1,43 @@ +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE IncoherentInstances #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE UndecidableInstances #-} +module Language.Fiddle.Ast.Internal.Stage where + +import Data.Type.Bool +import Data.Type.Equality +import Data.Typeable +import qualified GHC.TypeError as TypeError +import GHC.TypeLits + +-- Stage of compilation. Parts of the AST maybe un unavailable with other stages +-- as compilation simplifies the AST. +data Stage = Stage1 | Stage2 | Stage3 + deriving (Typeable) + +-- Returns the stage before the given stage. +type family PreviousStage (s :: Stage) :: Stage where + PreviousStage Stage1 = TypeError (TypeError.Text "No Prior stage to Stage1") + PreviousStage s = NumberToStage (StageToNumber s - 1) + +-- Returns the stage after the give stage. +type family NextStage (s :: Stage) :: Stage where + NextStage s = NumberToStage (StageToNumber s + 1) + +-- Converts a stage to a number. +type family StageToNumber (s :: Stage) :: Natural where + StageToNumber Stage1 = 1 + StageToNumber Stage2 = 2 + StageToNumber Stage3 = 3 + +-- Converts a number to a stage. +type family NumberToStage (n :: Natural) :: Stage where + NumberToStage 1 = Stage1 + NumberToStage 2 = Stage2 + NumberToStage 3 = Stage3 + NumberToStage n = TypeError (TypeError.Text "Number in NumberToStage.") + +-- Type-level constraint to determine if a stage is less than some natural +-- ordinal. Used to bound parts of the AST in multiple stages. +type StageLessThan stage (n :: Natural) = (CmpNat (StageToNumber stage) n == LT) diff --git a/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs b/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs new file mode 100644 index 0000000..48852ee --- /dev/null +++ b/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs @@ -0,0 +1,537 @@ +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE IncoherentInstances #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE UndecidableInstances #-} + +module Language.Fiddle.Ast.Internal.SyntaxTree + ( -- Type Families + NumberType, + ImportType, + -- Witness Types + Witness (..), + WitnessType, + -- AST Types + Name (..), + Directive (..), + DirectiveBody (..), + DirectiveElement (..), + DirectiveExpression (..), + Directed (..), + FiddleUnit (..), + Identifier (..), + Expression (..), + ImportStatement (..), + ImportList (..), + FiddleDecl (..), + ObjTypeBody (..), + ObjType (..), + ObjTypeDecl (..), + Modifier (..), + ModifierKeyword (..), + DeferredRegisterBody (..), + BodyType (..), + RegisterBody (..), + RegisterBitsDecl (..), + RegisterBitsTypeRef (..), + AnonymousBitsType (..), + BitType (..), + EnumBody (..), + EnumConstantDecl (..), + PackageBody (..), + -- Helper Functions + mapDirected, + mapDirectedM, + asDirected, + undirected, + -- Utility Functions + squeeze, + ) +where + +import Data.Coerce +import Data.Functor.Identity +import Data.Kind (Type) +import Data.List.NonEmpty +import Data.Proxy +import Data.Text (Text) +import Data.Traversable +import Data.Type.Bool +import Data.Type.Equality +import Data.Typeable +import Data.Void (Void, absurd) +import GHC.Generics +import GHC.TypeLits +import Language.Fiddle.Ast.Internal.Generic +import Language.Fiddle.Ast.Internal.Instances +import Language.Fiddle.Ast.Internal.Kinds +import Language.Fiddle.Ast.Internal.Stage + +-- 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. +type family NumberType (a :: Stage) :: Type where + NumberType Stage1 = Text + NumberType Stage2 = Integer + NumberType s = NumberType (PreviousStage s) + +-- The type that represents an import statement. In the early stages of +-- compilation, this is just a string representing the import path, but in later +-- stages of compilation, this actually gets replaced by an abstract +-- representation of the imported material. +type family ImportType (stage :: Stage) :: SynTree where + ImportType Stage1 = ImportStatement + ImportType Stage2 = ImportStatement + ImportType Stage3 = ImportStatement + +-- A way to disable or enable a subtree type based on a type-level boolean. +-- +-- This is used over GADT's specific parameterization to allow for deriving +-- generics and reduce boilerplate. +-- +-- This is a wrapper type to allow defining instances. +data Witness (s :: Bool) where + Witness :: (WitnessType s) -> Witness s + +-- | If the type level expression is true, the witness type is the Unit type, if +-- it is false, the witness type is Void, thus making whatever it touches +-- uninhabitable. This is how parts of the AST is enabled or disabled during +-- compilation. +type family WitnessType (s :: Bool) where + WitnessType True = () + WitnessType False = Void + +-- A Name is multiple identifiers separated by dots. It's the way of namespaces +-- to different packages. +data Name :: SynTree where + Name :: NonEmpty (Identifier f a) -> a -> Name f a + deriving (Generic, Annotated, Alter, Typeable) + +-- Syntax tree fo the directive sublanguage. Directives can be on many elements +-- and provide the compiler with additional information about the emitted code. +-- +-- The directive subtree by design does not depend on the compilation stage. +-- This is because the directive sublanguage should pass directly to the backend +-- compilation stage. +data Directive :: SynTree where + Directive :: f (DirectiveBody f a) -> a -> Directive f a + deriving (Generic, Annotated, Alter, Typeable) + +-- A directive body has multiple directive elements. +data DirectiveBody :: SynTree where + DirectiveBody :: [DirectiveElement f a] -> a -> DirectiveBody f a + deriving (Generic, Annotated, Alter, Typeable) + +-- Element in the directive. +data DirectiveElement :: SynTree where + -- A directive can just be a key. Where the mere presence of the key has + -- semantic value. + DirectiveElementKey :: + -- Which backend is this directive intended for? + Maybe (Identifier f a) -> + Identifier f a -> + a -> + DirectiveElement f a + -- A directive can be more complex too. It can have an optional backend + -- specificer, a key and a value. + DirectiveElementKeyValue :: + -- Which backend is this directive intendend for? + Maybe (Identifier f a) -> + -- The key for this directive. + Identifier f a -> + -- The value for this directive. + DirectiveExpression f a -> + a -> + DirectiveElement f a + deriving (Generic, Annotated, Alter, Typeable) + +-- Expressions which can be found in the directive. +data DirectiveExpression f a where + DirectiveString :: Text -> a -> DirectiveExpression f a + DirectiveNumber :: Text -> a -> DirectiveExpression f a + deriving (Generic, Annotated, Alter, Typeable) + +-- A type, which wraps another syntax tree, but tacks on an array of directives. +-- that apply to the subtree. +data Directed t stage f a where + Directed :: [Directive f a] -> t stage f a -> a -> Directed t stage f a + deriving (Generic, Annotated, Alter, Typeable) + +-- 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 + +-- Apply a monadic function to the underlying subtree in a Directed type. +mapDirectedM :: + (Monad m) => (t s f a -> m (t' s' f a)) -> Directed t s f a -> m (Directed t' s' f a) +mapDirectedM fn (Directed dr tfa a) = Directed dr <$> fn tfa <*> pure a + +asDirected :: (Annotated (t s)) => t s f a -> Directed t s f a +asDirected tfa = Directed [] tfa (annot tfa) + +undirected :: Directed t s f a -> t s f a +undirected (Directed _ tfa _) = tfa + +-- Root of the parse tree. Just contains a list of declarations. +data FiddleUnit (stage :: Stage) (f :: Type -> Type) a where + FiddleUnit :: [Directed FiddleDecl stage f a] -> a -> FiddleUnit stage f a + deriving (Generic, Annotated, Typeable) + +deriving instance (Alter (ImportType stage)) => Alter (FiddleUnit stage) + +-- Just an identifier. +data Identifier f a = Identifier !Text a + deriving (Generic, Annotated, Alter, Typeable) + +-- Expression. +data Expression (s :: Stage) :: SynTree where + -- Just a string. Parsing the number comes in stage2. + LitNum :: NumberType stage -> a -> Expression stage f a + Var :: Identifier f a -> a -> Expression stage f a + deriving (Generic, Annotated, Alter, Typeable) + +data ImportStatement f a where + ImportStatement :: Text -> Maybe (ImportList f a) -> a -> ImportStatement f a + deriving (Generic, Annotated, Alter, Typeable) + +data ImportList f a where + ImportList :: [Identifier f a] -> a -> ImportList f a + deriving (Generic, Annotated, Alter, Typeable) + +-- Top-level declarations. +data FiddleDecl :: StagedSynTree where + {- + - An option is a key/value pair. + - option <ident> <ident>; + -} + OptionDecl :: + Identifier f a -> + Identifier f a -> + a -> + FiddleDecl stage f a + ImportDecl :: + ImportType stage f a -> + a -> + FiddleDecl stage f a + UsingDecl :: + Name f a -> a -> FiddleDecl stage f a + {- Package Statement. Package Name, Package body -} + PackageDecl :: + Name f a -> + f (PackageBody stage f a) -> + a -> + FiddleDecl stage f a + {- location <identifier> = <expr>. -} + LocationDecl :: + Identifier f a -> + Expression stage f a -> + a -> + FiddleDecl stage f a + {- bits <identifier> : <type> -} + BitsDecl :: + Identifier f a -> + BitType stage f a -> + a -> + FiddleDecl stage f a + {- objtype <identifier> : <type> -} + ObjTypeDecl :: + Identifier f a -> + f (ObjTypeBody stage f a) -> + a -> + FiddleDecl stage f a + {- object <ident> at <expr> : <type> -} + ObjectDecl :: + Identifier f a -> + Expression stage f a -> + ObjType stage f a -> + a -> + FiddleDecl stage f a + deriving (Generic, Annotated, Typeable) + +deriving instance (Alter (ImportType stage)) => Alter (FiddleDecl stage) + +data ObjTypeBody (stage :: Stage) (f :: Type -> Type) a where + ObjTypeBody :: + BodyType f a -> + [Directed ObjTypeDecl stage f a] -> + a -> + ObjTypeBody stage f a + deriving (Generic, Annotated, Alter, Typeable) + +data ObjType stage f a where + -- { <body> } + -- Anonymous types are only allowed in stage1. Stage2 should have them be + -- de-anonymized. + AnonymousObjType :: + (Witness (stage == Stage1)) -> + f (ObjTypeBody stage f a) -> + a -> + ObjType stage f a + -- <type>[<expr>] + ArrayObjType :: ObjType stage f a -> Expression stage f a -> a -> ObjType stage f a + -- <identifier> + ReferencedObjType :: Name f a -> a -> ObjType stage f a + deriving (Typeable, Generic, Alter, Annotated, Typeable) + +data ObjTypeDecl stage f a where + {- assert_pos(<expr>) -} + AssertPosStatement :: + Witness (StageLessThan stage 3) -> + Expression stage f a -> + a -> + ObjTypeDecl stage f a + {- reg <ident>(<expr>) : <regtype> -} + RegisterDecl :: + Maybe (Modifier f a) -> + Maybe (Identifier f a) -> + Expression stage f a -> + Maybe (RegisterBody stage f a) -> + a -> + ObjTypeDecl stage f a + {- reserved(n); -} + ReservedDecl :: Expression stage f a -> a -> ObjTypeDecl stage f a + {- <struct|union> { subfields } <name>; -} + TypeSubStructure :: + f (ObjTypeBody stage f a) -> + Maybe (Identifier f a) -> + a -> + ObjTypeDecl stage f a + deriving (Generic, Annotated, Alter, Typeable) + +data Modifier f a where + ModifierKeyword :: ModifierKeyword -> a -> Modifier f a + deriving (Generic, Annotated, Alter, Typeable) + +data ModifierKeyword = Rw | Ro | Wo deriving (Eq, Ord, Show, Read, Typeable) + +data DeferredRegisterBody stage f a where + DeferredRegisterBody :: + [Directed RegisterBitsDecl stage f a] -> + a -> + DeferredRegisterBody stage f a + deriving (Generic, Annotated, Alter, Typeable) + +data BodyType (f :: Type -> Type) a where + Union :: a -> BodyType f a + Struct :: a -> BodyType f a + deriving (Generic, Annotated, Alter, Typeable) + +data RegisterBody stage f a where + RegisterBody :: + BodyType f a -> + f (DeferredRegisterBody stage f a) -> + a -> + RegisterBody stage f a + deriving (Generic, Annotated, Alter, Typeable) + +data RegisterBitsDecl stage f a where + -- reserved(<expr>) + ReservedBits :: Expression stage f a -> a -> RegisterBitsDecl stage f a + -- <modifer> <ident> : <type> + DefinedBits :: + Maybe (Modifier f a) -> + Identifier f a -> + RegisterBitsTypeRef stage f a -> + a -> + RegisterBitsDecl stage f a + BitsSubStructure :: + RegisterBody stage f a -> + Maybe (Identifier f a) -> + a -> + RegisterBitsDecl stage f a + deriving (Generic, Annotated, Alter, Typeable) + +data RegisterBitsTypeRef stage f a where + -- <type>[<expr>] + RegisterBitsArray :: + RegisterBitsTypeRef stage f a -> + Expression stage f a -> + a -> + RegisterBitsTypeRef stage f a + {- Reference to a type. -} + RegisterBitsReference :: Name f a -> a -> RegisterBitsTypeRef stage f a + {- enum(<expr>) { <body> } + Anonymous types are only allowed in stage1. + Stage2 should de-anonymize these type. -} + RegisterBitsAnonymousType :: + Witness (stage == Stage1) -> + AnonymousBitsType stage f a -> + a -> + RegisterBitsTypeRef stage f a + {- (<expr>) + - + - The expression is just bits ... i.e. an integer. + -} + RegisterBitsJustBits :: + Expression stage f a -> + a -> + RegisterBitsTypeRef stage f a + deriving (Generic, Annotated, Alter, Typeable) + +data AnonymousBitsType stage f a where + -- enum(<expr>) { <body> } + AnonymousEnumBody :: + Expression stage f a -> + f (EnumBody stage f a) -> + a -> + AnonymousBitsType stage f a + deriving (Generic, Annotated, Alter, Typeable) + +data BitType (stage :: Stage) (f :: Type -> Type) a where + -- enum(<expr>) { <body> } + EnumBitType :: + Expression stage f a -> + f (EnumBody stage f a) -> + a -> + BitType stage f a + -- (<expr>) + RawBits :: Expression stage f a -> a -> BitType stage f a + deriving (Generic, Annotated, Alter, Typeable) + +data EnumBody (stage :: Stage) (f :: Type -> Type) a where + -- <decl>, + EnumBody :: [Directed EnumConstantDecl stage f a] -> a -> EnumBody stage f a + deriving (Generic, Annotated, Alter, Typeable) + +data EnumConstantDecl stage f a where + -- <ident> = <expr> + EnumConstantDecl :: + Identifier f a -> + Expression stage f a -> + a -> + EnumConstantDecl stage f a + -- reserved = <expr> + EnumConstantReserved :: + Expression stage f a -> + a -> + EnumConstantDecl stage f a + deriving (Generic, Annotated, Alter, Typeable) + +data PackageBody (stage :: Stage) (f :: Type -> Type) a where + {- The body of a package -} + PackageBody :: [Directed FiddleDecl stage f a] -> a -> PackageBody stage f a + deriving (Generic, Annotated, Typeable) + +deriving instance (Alter (ImportType stage)) => Alter (PackageBody stage) + +squeeze :: (Alter t, Traversable f, Monad f) => t f a -> f (t Identity a) +squeeze = alter (fmap Identity) return + +-- Expression involves NumberType, so we add the constraint: +deriving instance (Functor f, NumberType s ~ NumberType s') => EasySwitchStage Expression f s s' + +-- FiddleDecl includes both NumberType and ImportType, so we need both constraints: +deriving instance + ( Functor f, + StageLessThan s 3 ~ StageLessThan s' 3, + (s == Stage1) ~ (s' == Stage1), + NumberType s ~ NumberType s', + ImportType s ~ ImportType s' + ) => + EasySwitchStage FiddleDecl f s s' + +-- ObjType includes NumberType, so we add the constraint: +deriving instance + ( Functor f, + StageLessThan s 3 ~ StageLessThan s' 3, + (s == Stage1) ~ (s' == Stage1), + NumberType s ~ NumberType s' + ) => + EasySwitchStage ObjType f s s' + +-- ObjTypeBody doesn't have any special type families, so no additional constraints: +deriving instance + ( Functor f, + StageLessThan s 3 ~ StageLessThan s' 3, + (s == Stage1) ~ (s' == Stage1), + NumberType s ~ NumberType s' + ) => + EasySwitchStage ObjTypeBody f s s' + +-- ObjTypeDecl doesn't have special type families, so no additional constraints: +deriving instance + ( Functor f, + StageLessThan s 3 ~ StageLessThan s' 3, + (s == Stage1) ~ (s' == Stage1), + NumberType s ~ NumberType s' + ) => + EasySwitchStage ObjTypeDecl f s s' + +-- DeferredRegisterBody doesn't have special type families: +deriving instance + ( Functor f, + (s == Stage1) ~ (s' == Stage1), + NumberType s ~ NumberType s' + ) => + EasySwitchStage DeferredRegisterBody f s s' + +-- RegisterBody depends on NumberType, so we add that constraint: +deriving instance + ( Functor f, + (s == Stage1) ~ (s' == Stage1), + NumberType s ~ NumberType s' + ) => + EasySwitchStage RegisterBody f s s' + +-- RegisterBitsDecl depends on NumberType: +deriving instance + ( Functor f, + (s == Stage1) ~ (s' == Stage1), + NumberType s ~ NumberType s' + ) => + EasySwitchStage RegisterBitsDecl f s s' + +-- RegisterBitsTypeRef depends on NumberType: +deriving instance + ( Functor f, + (s == Stage1) ~ (s' == Stage1), + NumberType s ~ NumberType s' + ) => + EasySwitchStage RegisterBitsTypeRef f s s' + +-- AnonymousBitsType depends on NumberType: +deriving instance + (Functor f, NumberType s ~ NumberType s') => + EasySwitchStage AnonymousBitsType f s s' + +-- BitType depends on NumberType: +deriving instance + (Functor f, NumberType s ~ NumberType s') => + EasySwitchStage BitType f s s' + +-- EnumBody doesn't depend on any type families: +deriving instance + (Functor f, NumberType s ~ NumberType s') => + EasySwitchStage EnumBody f s s' + +-- EnumConstantDecl depends on NumberType: +deriving instance + (Functor f, NumberType s ~ NumberType s') => + EasySwitchStage EnumConstantDecl f s s' + +-- PackageBody includes both NumberType and ImportType: +deriving instance + ( Functor f, + StageLessThan s 3 ~ StageLessThan s' 3, + (s == Stage1) ~ (s' == Stage1), + NumberType s ~ NumberType s', + ImportType s ~ ImportType s' + ) => + EasySwitchStage PackageBody f s s' + +-- FiddleUnit includes NumberType and ImportType, so we need both constraints: +deriving instance + ( Functor f, + StageLessThan s 3 ~ StageLessThan s' 3, + (s == Stage1) ~ (s' == Stage1), + NumberType s ~ NumberType s', + ImportType s ~ ImportType s' + ) => + EasySwitchStage FiddleUnit f s s' + +-- Directed depends on its underlying AST type: +deriving instance + (EasySwitchStage t f s s') => + EasySwitchStage (Directed t) f s s' diff --git a/src/Language/Fiddle/Ast/Internal/SyntaxTreeKinds.hs b/src/Language/Fiddle/Ast/Internal/SyntaxTreeKinds.hs new file mode 100644 index 0000000..bfdfb13 --- /dev/null +++ b/src/Language/Fiddle/Ast/Internal/SyntaxTreeKinds.hs @@ -0,0 +1 @@ +module Language.Fiddle.Ast.Internal.SyntaxTreeKinds where diff --git a/src/Language/Fiddle/Compiler/Stage1.hs b/src/Language/Fiddle/Compiler/Stage1.hs index a17afa1..d2fe885 100644 --- a/src/Language/Fiddle/Compiler/Stage1.hs +++ b/src/Language/Fiddle/Compiler/Stage1.hs @@ -5,11 +5,11 @@ module Language.Fiddle.Compiler.Stage1 (toStage2) where -import qualified Data.List.NonEmpty as NonEmpty import Control.Monad.Identity (Identity (..)) import Control.Monad.State (get, gets, modify, put) import qualified Data.Char as Char import Data.List (intercalate) +import qualified Data.List.NonEmpty as NonEmpty import Data.Text (Text) import qualified Data.Text as Text import Data.Type.Bool @@ -69,9 +69,9 @@ toStage2 (FiddleUnit decls annot) = do FiddleUnit <$> reconfigureFiddleDecls (Path []) decls <*> pure annot return a -reconfigureFiddleDecls :: Path -> [Directed (FiddleDecl Stage1) I Annot] -> M Annot [Directed (FiddleDecl Stage2) I Annot] +reconfigureFiddleDecls :: Path -> [Directed FiddleDecl Stage1 I Annot] -> M Annot [Directed FiddleDecl Stage2 I Annot] reconfigureFiddleDecls p decls = do - -- (Stage2CompilerState anonymousObjTypes anonymousBitsTypes, decls) <- pushState $ do + -- Stage2CompilerState anonymousObjTypes anonymousBitsTypes, decls <- pushState $ do -- put (Stage2CompilerState [] []) -- gets (,) <*> mapM (fiddleDeclToStage2 p) decls @@ -95,6 +95,7 @@ reconfigureFiddleDecls p decls = do pushId :: Identifier f a -> Path -> Path pushId (Identifier str _) (Path lst) = Path (PathExpression (Text.unpack str) : lst) + pushName :: Name f a -> Path -> Path pushName (Name idents _) path = foldl (flip pushId) path idents @@ -134,7 +135,10 @@ objTypeBodyToStage2 path (ObjTypeBody bodyType decls annot) = objTypeDeclToStage2 :: Path -> ObjTypeDecl Stage1 I Annot -> M Annot (ObjTypeDecl Stage2 I Annot) objTypeDeclToStage2 path = \case - (AssertPosStatement expr annot) -> AssertPosStatement <$> toStage2Expr expr <*> pure annot + (AssertPosStatement w expr annot) -> + AssertPosStatement w + <$> toStage2Expr expr + <*> pure annot (TypeSubStructure (Identity deferredBody) maybeIdent annot) -> let path' = maybe path (`pushId` path) maybeIdent in TypeSubStructure . Identity @@ -185,7 +189,7 @@ registerBitsTypeRefToStage2 path = \case <*> pure annot RegisterBitsReference name annot -> return (RegisterBitsReference name annot) RegisterBitsJustBits expr annot -> RegisterBitsJustBits <$> toStage2Expr expr <*> pure annot - RegisterBitsAnonymousType anonType annot -> do + RegisterBitsAnonymousType _ anonType annot -> do ident <- internAnonymousBitsType path =<< anonymousBitsTypeToStage2 path anonType return $ RegisterBitsReference (identToName ident) annot @@ -202,7 +206,7 @@ anonymousBitsTypeToStage2 path = \case objectTypeToStage2 :: Path -> ObjType Stage1 I Annot -> M Annot (ObjType Stage2 I Annot) objectTypeToStage2 path = \case - (AnonymousObjType (Identity body) annot) -> do + (AnonymousObjType _ (Identity body) annot) -> do body' <- objTypeBodyToStage2 path body identifier <- internObjType path body' return (ReferencedObjType (identToName identifier) annot) diff --git a/src/Language/Fiddle/Compiler/Stage2.hs b/src/Language/Fiddle/Compiler/Stage2.hs index 57b0b55..2035e3d 100644 --- a/src/Language/Fiddle/Compiler/Stage2.hs +++ b/src/Language/Fiddle/Compiler/Stage2.hs @@ -5,11 +5,11 @@ -- Stage3 doesn't change much from Stage2. Stage3 primarily removes the assert -- statements and checks that they are consistent with the calculations. -module Language.Fiddle.Compiler.Stage2 where +module Language.Fiddle.Compiler.Stage2 (toStage3) where import Control.Monad (forM, forM_, unless, when) import Control.Monad.RWS (MonadState (get), MonadWriter (tell), gets, modify') -import Data.Foldable (foldlM, Foldable (toList)) +import Data.Foldable (Foldable (toList), foldlM) import Data.Functor.Identity import qualified Data.IntMap as IntMap import Data.Kind (Type) @@ -110,12 +110,6 @@ insertTypeSize (Identifier s _) size = do insertScope fullName (Right size) (inScope stage3State) } --- addTypeSize :: Identifier f a -> SizeBits -> Compile Stage3State () --- addTypeSize (Identifier s _) size = do --- modify' $ --- \stage3State -> --- stage3State {typeSizes = Map.insert (Text.unpack s) size (typeSizes stage3State)} - lookupTypeSize :: Name I Annot -> Compile Stage3State SizeBits lookupTypeSize (Name idents a) = do let path = fmap (\(Identifier s _) -> Text.unpack s) idents @@ -135,11 +129,6 @@ lookupTypeSize (Name idents a) = do ] compilationFailure -expressionToStage3 :: Expression Stage2 f Annot -> Expression Stage3 f Annot -expressionToStage3 = \case - LitNum n a -> LitNum n a - Var i a -> Var i a - emptyState = Stage3State mempty mempty toStage3 :: FiddleUnit Stage2 I Annot -> Compile () (FiddleUnit Stage3 I Annot) @@ -178,7 +167,10 @@ getTypeSize (EnumBitType expr (Identity (EnumBody constants _)) ann) = do tell [ Diagnostic Error - (printf "Enum constant too large. Max allowed %d\n" ((2 :: Int) ^ declaredSize)) + ( printf + "Enum constant too large. Max allowed %d\n" + ((2 :: Int) ^ declaredSize) + ) (unCommented (annot enumConst)) ] @@ -186,7 +178,8 @@ getTypeSize (EnumBitType expr (Identity (EnumBody constants _)) ann) = do ) IntMap.empty constants - let missing = filter (not . (`IntMap.member` imap)) [0 .. 2 ^ declaredSize - 1] + let missing = + filter (not . (`IntMap.member` imap)) [0 .. 2 ^ declaredSize - 1] unless (null missing) $ tell [ Diagnostic @@ -206,7 +199,8 @@ addCurrentScope s = do modify' $ \st@(Stage3State {scopePath = (ScopePath current others)}) -> st {scopePath = ScopePath (current ++ s) others} -fiddleDeclToStage3 :: FiddleDecl Stage2 I Annot -> Compile Stage3State (FiddleDecl Stage3 I Annot) +fiddleDeclToStage3 :: + FiddleDecl Stage2 I Annot -> Compile Stage3State (FiddleDecl Stage3 I Annot) fiddleDeclToStage3 = \case OptionDecl i1 i2 a -> return $ OptionDecl i1 i2 a PackageDecl n@(Name idents _) body a -> do @@ -227,97 +221,120 @@ fiddleDeclToStage3 = \case } ) return $ UsingDecl n a - LocationDecl id expr a -> return $ LocationDecl id (expressionToStage3 expr) a + LocationDecl id expr a -> return $ LocationDecl id (switchStage expr) a BitsDecl id typ a -> do typeSize <- getTypeSize typ insertTypeSize id typeSize - BitsDecl id <$> bitTypeToStage3 typ <*> pure a + return $ BitsDecl id (switchStage typ) a ObjTypeDecl ident body a -> - ObjTypeDecl ident <$> mapM (\bt -> fst <$> objTypeBodyToStage3 bt 0) body <*> pure a + ObjTypeDecl ident + <$> mapM (\bt -> fst <$> objTypeBodyToStage3 bt 0) body + <*> pure a ImportDecl importStatement a -> return $ ImportDecl importStatement a ObjectDecl ident expr typ a -> - ObjectDecl ident (expressionToStage3 expr) <$> objTypeToStage3 typ <*> pure a + ObjectDecl + ident + (switchStage expr) + <$> objTypeToStage3 typ + <*> pure a -objTypeToStage3 :: ObjType Stage2 I Annot -> Compile Stage3State (ObjType Stage3 I Annot) +objTypeToStage3 :: + ObjType Stage2 I Annot -> Compile Stage3State (ObjType Stage3 I Annot) objTypeToStage3 = \case ArrayObjType objtype expr a -> ArrayObjType <$> objTypeToStage3 objtype - <*> pure (expressionToStage3 expr) + <*> pure (switchStage expr) <*> pure a ReferencedObjType ident a -> return $ ReferencedObjType ident a registerBodyToStage3 :: RegisterBody Stage2 I Annot -> Compile Stage3State (RegisterBody Stage3 I Annot, Word32) -registerBodyToStage3 (RegisterBody bodyType (Identity deferredRegisterBody) a') = do - let isUnion = case bodyType of - Union {} -> True - _ -> False - - case deferredRegisterBody of - DeferredRegisterBody decls a -> do - (cur, returned) <- - foldlM - ( \(cursor, returned) decl -> - case undirected decl of - ReservedBits expr a -> do - size <- fromIntegral <$> exprToSize expr - let s3 = mapDirected (const $ ReservedBits (expressionToStage3 expr) a) decl - if isUnion - then checkUnion cursor size (s3 : returned) a - else - return (cursor + size, s3 : returned) - BitsSubStructure registerBody maybeIdent annot -> do - checkBitsSubStructure registerBody maybeIdent annot - - (newBody, subsize) <- registerBodyToStage3 registerBody - let s3 = mapDirected (const $ BitsSubStructure newBody maybeIdent annot) decl - - if isUnion - then checkUnion cursor subsize (s3 : returned) a - else - return (cursor + subsize, s3 : returned) - DefinedBits modifier identifier typeref a -> do - (s3TypeRef, size) <- registerBitsTypeRefToStage3 typeref - let s3 = mapDirected (const $ DefinedBits modifier identifier s3TypeRef a) decl - - if isUnion - then checkUnion cursor size (s3 : returned) a - else - return (cursor + size, s3 : returned) +registerBodyToStage3 + (RegisterBody bodyType (Identity deferredRegisterBody) a') = do + let isUnion = case bodyType of + Union {} -> True + _ -> False + + case deferredRegisterBody of + DeferredRegisterBody decls a -> do + (cur, returned) <- + foldlM + ( \(cursor, returned) decl -> + case undirected decl of + ReservedBits expr a -> do + size <- fromIntegral <$> exprToSize expr + let s3 = + mapDirected + (const $ ReservedBits (switchStage expr) a) + decl + if isUnion + then checkUnion cursor size (s3 : returned) a + else + return (cursor + size, s3 : returned) + BitsSubStructure registerBody maybeIdent annot -> do + checkBitsSubStructure registerBody maybeIdent annot + + (newBody, subsize) <- registerBodyToStage3 registerBody + let s3 = + mapDirected + (const $ BitsSubStructure newBody maybeIdent annot) + decl + + if isUnion + then checkUnion cursor subsize (s3 : returned) a + else + return (cursor + subsize, s3 : returned) + DefinedBits modifier identifier typeref a -> do + (s3TypeRef, size) <- registerBitsTypeRefToStage3 typeref + let s3 = + mapDirected + (const $ DefinedBits modifier identifier s3TypeRef a) + decl + + if isUnion + then checkUnion cursor size (s3 : returned) a + else + return (cursor + size, s3 : returned) + ) + (0, []) + decls + + return + ( RegisterBody + bodyType + (Identity (DeferredRegisterBody (reverse returned) a)) + a', + cur ) - (0, []) - decls - - return (RegisterBody bodyType (Identity (DeferredRegisterBody (reverse returned) a)) a', cur) - where - checkBitsSubStructure - (RegisterBody bodyType (Identity (DeferredRegisterBody decls _)) _) - maybeIdent - annot = - let emitWarning s = tell [Diagnostic Warning s (unCommented annot)] - in case () of - () - | [_] <- decls, - (Union {}) <- bodyType -> - emitWarning "Union with a single field. Should this be a struct?" - () - | [_] <- decls, - (Struct {}) <- bodyType, - Nothing <- maybeIdent -> - emitWarning "Anonymous sub-struct with single field is superfluous." - () - | [] <- decls -> - emitWarning - ( printf - "Empty sub-%s is superfluous." - ( case bodyType of - Union {} -> "union" - Struct {} -> "struct" - ) - ) - _ -> return () + where + checkBitsSubStructure + (RegisterBody bodyType (Identity (DeferredRegisterBody decls _)) _) + maybeIdent + annot = + let emitWarning s = tell [Diagnostic Warning s (unCommented annot)] + in case () of + () + | [_] <- decls, + (Union {}) <- bodyType -> + emitWarning "Union with a single field. Should this be a struct?" + () + | [_] <- decls, + (Struct {}) <- bodyType, + Nothing <- maybeIdent -> + emitWarning "Anonymous sub-struct with single field is superfluous." + () + | [] <- decls -> + emitWarning + ( printf + "Empty sub-%s is superfluous." + ( case bodyType of + Union {} -> "union" + Struct {} -> "struct" + ) + ) + _ -> return () checkUnion :: Word32 -> Word32 -> b -> Commented SourceSpan -> Compile Stage3State (Word32, b) checkUnion cursor subsize ret a = do @@ -344,13 +361,13 @@ registerBitsTypeRefToStage3 = \case (ref', size) <- registerBitsTypeRefToStage3 ref multiplier <- exprToSize expr return - ( RegisterBitsArray ref' (expressionToStage3 expr) a, + ( RegisterBitsArray ref' (switchStage expr) a, size * fromIntegral multiplier ) RegisterBitsReference name a -> (RegisterBitsReference name a,) <$> lookupTypeSize name RegisterBitsJustBits expr a -> - (RegisterBitsJustBits (expressionToStage3 expr) a,) + (RegisterBitsJustBits (switchStage expr) a,) . fromIntegral <$> exprToSize expr @@ -374,7 +391,7 @@ objTypeBodyToStage3 (ObjTypeBody bodyType decls a) startOff = do RegisterDecl mMod mIdent - (expressionToStage3 expr) + (switchStage expr) s3RegisterBody a ) @@ -440,13 +457,13 @@ objTypeBodyToStage3 (ObjTypeBody bodyType decls a) startOff = do (unCommented a) ] let size = size' `div` 8 - let s3 = mapDirected (const $ ReservedDecl (expressionToStage3 expr) annot) decl + let s3 = mapDirected (const $ ReservedDecl (switchStage expr) annot) decl if isUnion then checkUnion cursor size (s3 : returned) a else return (cursor + size, s3 : returned) - AssertPosStatement expr a -> do + AssertPosStatement _ expr a -> do declaredPos <- fromIntegral <$> exprToSize expr let expectedPos = if isUnion then startOff else cursor + startOff @@ -500,21 +517,6 @@ objTypeBodyToStage3 (ObjTypeBody bodyType decls a) startOff = do pushApply (Just (a, b)) = (Just a, Just b) pushApply Nothing = (Nothing, Nothing) -bitTypeToStage3 :: BitType Stage2 I Annot -> Compile Stage3State (BitType Stage3 I Annot) -bitTypeToStage3 (EnumBitType expr body a) = - EnumBitType (expressionToStage3 expr) - <$> mapM enumBodyToStage3 body - <*> pure a - -enumBodyToStage3 :: EnumBody Stage2 I Annot -> Compile Stage3State (EnumBody Stage3 I Annot) -enumBodyToStage3 (EnumBody constants a) = - EnumBody <$> mapM (mapDirectedM enumConstantDeclToStage3) constants <*> pure a - -enumConstantDeclToStage3 :: EnumConstantDecl Stage2 I Annot -> Compile Stage3State (EnumConstantDecl Stage3 I Annot) -enumConstantDeclToStage3 = \case - EnumConstantDecl ident expr a -> return $ EnumConstantDecl ident (expressionToStage3 expr) a - EnumConstantReserved expr a -> return $ EnumConstantReserved (expressionToStage3 expr) a - packageBodyToStage3 :: PackageBody Stage2 I Annot -> Compile Stage3State (PackageBody Stage3 I Annot) packageBodyToStage3 (PackageBody decls a) = PackageBody <$> mapM (mapDirectedM fiddleDeclToStage3) decls <*> pure a diff --git a/src/Language/Fiddle/GenericTree.hs b/src/Language/Fiddle/GenericTree.hs index 598336a..59db6aa 100644 --- a/src/Language/Fiddle/GenericTree.hs +++ b/src/Language/Fiddle/GenericTree.hs @@ -14,6 +14,7 @@ import Control.Monad.Writer (execWriter, tell) import Data.Aeson (Value (..), foldable, object, toEncoding, toJSON) import Data.Aeson.Encoding (text) import Data.Aeson.Types as Aeson +import Data.Foldable (Foldable (toList)) import qualified Data.Foldable import Data.Functor.Classes (Show1, liftShowsPrec) import Data.Kind (Type) @@ -32,7 +33,8 @@ type Context stage = ( Show (NumberType stage), Typeable stage, ToGenericSyntaxTree (ImportType stage), - Typeable (ImportType stage) + Typeable (ImportType stage), + ToGenericSyntaxTreeValue (NumberType stage) ) data GenericSyntaxTree f a where @@ -89,17 +91,25 @@ instance (Foldable f, ToJSON a) => ToJSON (GenericSyntaxTree f a) where (SyntaxTreeValue s) -> text (Data.Text.pack s) class ToGenericSyntaxTreeValue v where - toGenericSyntaxTreeValue :: forall f a. v -> GenericSyntaxTree f a + toGenericSyntaxTreeValue :: forall f a. v -> Maybe (GenericSyntaxTree f a) default toGenericSyntaxTreeValue :: - forall f a. (Show v) => v -> GenericSyntaxTree f a - toGenericSyntaxTreeValue = SyntaxTreeValue . show + forall f a. (Show v) => v -> Maybe (GenericSyntaxTree f a) + toGenericSyntaxTreeValue = Just . SyntaxTreeValue . show instance ToGenericSyntaxTreeValue Data.Text.Text where - toGenericSyntaxTreeValue = SyntaxTreeValue . Data.Text.unpack + toGenericSyntaxTreeValue = Just . SyntaxTreeValue . Data.Text.unpack + +instance (Show s, Num s) => ToGenericSyntaxTreeValue s where + toGenericSyntaxTreeValue = Just . SyntaxTreeValue . show + +-- Witnesses exist just for type level meta programming, don't return anything +-- if we don't need it. +instance ToGenericSyntaxTreeValue (Witness b) where + toGenericSyntaxTreeValue _ = Nothing type GenericContext t f a = (Traversable f, ToGenericSyntaxTree t, Typeable t, Typeable f, Typeable a) -class ToGenericSyntaxTree (t :: SynTreeKind) where +class ToGenericSyntaxTree (t :: SynTree) where toGenericSyntaxTree :: (Traversable f, Typeable f, Typeable t, Typeable a) => t f a -> GenericSyntaxTree f a default toGenericSyntaxTree :: (GenericContext t f a, Generic (t f a), (GToGenericSyntaxTree (Rep (t f a)) f a)) => @@ -114,7 +124,7 @@ class GToMemberList r f a where gToMemberList :: Int -> r x -> [GenericSyntaxTree f a] instance (ToGenericSyntaxTreeValue v) => GToMemberList (Rec0 v) f a where - gToMemberList _ = (: []) . toGenericSyntaxTreeValue . unK1 + gToMemberList _ = toList . toGenericSyntaxTreeValue . unK1 instance (GenericContext r f a) => @@ -195,64 +205,19 @@ deriving instance (ToGenericSyntaxTree ImportList) deriving instance (ToGenericSyntaxTree ImportStatement) -deriving instance (ToGenericSyntaxTree t, Typeable t) => (ToGenericSyntaxTree (Directed t)) +deriving instance + (Context stage, ToGenericSyntaxTree (t stage), Typeable t) => + (ToGenericSyntaxTree (Directed t stage)) deriving instance (Context stage) => (ToGenericSyntaxTree (FiddleUnit stage)) deriving instance (Context stage) => (ToGenericSyntaxTree (FiddleDecl stage)) -instance (Context stage) => ToGenericSyntaxTree (ObjType stage) where - toGenericSyntaxTree t = case t of - (AnonymousObjType body annot) -> - SyntaxTreeDeferred $ - fmap - ( \body' -> - SyntaxTreeObject - "AnonymousObjType" - [toGenericSyntaxTree body'] - annot - body' - ) - body - (ArrayObjType arr expr annot) -> - SyntaxTreeObject - "ArrayObjType" - [toGenericSyntaxTree arr, toGenericSyntaxTree expr] - annot - t - (ReferencedObjType ident a) -> - SyntaxTreeObject "ReferencedObjType" [toGenericSyntaxTree ident] a t +deriving instance (Context stage) => ToGenericSyntaxTree (ObjType stage) deriving instance (Context stage) => (ToGenericSyntaxTree (ObjTypeBody stage)) -instance (Context stage) => (ToGenericSyntaxTree (ObjTypeDecl stage)) where - toGenericSyntaxTree t = case t of - (AssertPosStatement expr a) -> - SyntaxTreeObject "AssertPosStatement" [toGenericSyntaxTree expr] a t - (TypeSubStructure body mIdent a) -> - SyntaxTreeObject - "TypeSubStructure" - ( Data.Foldable.toList (toGenericSyntaxTree <$> body) - ++ Data.Foldable.toList (toGenericSyntaxTree <$> mIdent) - ) - a - t - (ReservedDecl expr a) -> - SyntaxTreeObject - "ReservedDecl" - [toGenericSyntaxTree expr] - a - t - (RegisterDecl mMod mIdent expr mBody a) -> - SyntaxTreeObject - "RegisterDecl" - ( Data.Foldable.toList (toGenericSyntaxTree <$> mMod) - ++ Data.Foldable.toList (toGenericSyntaxTree <$> mIdent) - ++ [toGenericSyntaxTree expr] - ++ Data.Foldable.toList (toGenericSyntaxTree <$> mBody) - ) - a - t +deriving instance (Context stage) => (ToGenericSyntaxTree (ObjTypeDecl stage)) deriving instance (ToGenericSyntaxTreeValue ModifierKeyword) @@ -264,20 +229,7 @@ deriving instance (Context stage) => (ToGenericSyntaxTree (RegisterBody stage)) deriving instance (Context stage) => (ToGenericSyntaxTree (RegisterBitsDecl stage)) -instance (Context stage) => ToGenericSyntaxTree (RegisterBitsTypeRef stage) where - toGenericSyntaxTree t = case t of - (RegisterBitsArray ref exp a) -> - SyntaxTreeObject - "RegisterBitsArray" - [toGenericSyntaxTree ref, toGenericSyntaxTree exp] - a - t - (RegisterBitsReference i a) -> - SyntaxTreeObject "RegisterBitsReference" [toGenericSyntaxTree i] a t - (RegisterBitsAnonymousType t a) -> - SyntaxTreeObject "RegisterBitsAnonymousType " [toGenericSyntaxTree t] a t - (RegisterBitsJustBits t a) -> - SyntaxTreeObject "RegisterBitsJustBits " [toGenericSyntaxTree t] a t +deriving instance (Context stage) => ToGenericSyntaxTree (RegisterBitsTypeRef stage) deriving instance (Context stage) => (ToGenericSyntaxTree (AnonymousBitsType stage)) @@ -289,7 +241,4 @@ deriving instance (Context stage) => (ToGenericSyntaxTree (EnumConstantDecl stag deriving instance (Context stage) => (ToGenericSyntaxTree (PackageBody stage)) -instance (Context stage) => (ToGenericSyntaxTree (Expression stage)) where - toGenericSyntaxTree tr = case tr of - LitNum t a -> SyntaxTreeObject "LitNum" [SyntaxTreeValue (show t)] a tr - Var t a -> SyntaxTreeObject "LitNum" [toGenericSyntaxTree t] a tr +deriving instance (Context stage) => (ToGenericSyntaxTree (Expression stage)) diff --git a/src/Language/Fiddle/Parser.hs b/src/Language/Fiddle/Parser.hs index b44a9a1..85ae65e 100644 --- a/src/Language/Fiddle/Parser.hs +++ b/src/Language/Fiddle/Parser.hs @@ -52,7 +52,7 @@ isComment (Token t _) = stripTrailingComments :: [Token s] -> [Token s] stripTrailingComments = reverse . dropWhile isComment . reverse -directed :: Pa t -> PaS (Directed (t 'Stage1)) +directed :: Pa t -> PaS (Directed t 'Stage1) directed subparser = withMeta $ do Directed <$> many directive <*> subparser @@ -195,7 +195,7 @@ objType = do (ReferencedObjType <$> name) <|> ( do t <- bodyType - AnonymousObjType <$> defer body (objTypeBody t) + AnonymousObjType (Witness ()) <$> defer body (objTypeBody t) ) exprInParen :: Pa Expression @@ -211,7 +211,7 @@ objTypeDecl = withMeta $ ( do tok KWAssertPos - AssertPosStatement <$> exprInParen + AssertPosStatement (Witness ()) <$> exprInParen ) <|> ( do tok KWReserved @@ -291,7 +291,7 @@ registerBitsTypeRef = do baseTypeRef = withMeta $ (RegisterBitsJustBits <$> exprInParen) - <|> (RegisterBitsAnonymousType <$> anonymousBitsType) + <|> (RegisterBitsAnonymousType (Witness ()) <$> anonymousBitsType) <|> (RegisterBitsReference <$> name) anonymousBitsType :: Pa AnonymousBitsType |