diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-09-22 00:26:39 -0600 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-09-22 00:26:39 -0600 |
commit | 0d2095b5d42989639c1861d7213c182abd064672 (patch) | |
tree | e7d43320521f6bfb57d214cb949db8c8674c18c5 | |
parent | f0c4da33e9576d2509b8c6330b1663e044e2dff3 (diff) | |
download | fiddle-0d2095b5d42989639c1861d7213c182abd064672.tar.gz fiddle-0d2095b5d42989639c1861d7213c182abd064672.tar.bz2 fiddle-0d2095b5d42989639c1861d7213c182abd064672.zip |
More major changes to the grammer.
Added annotation sublanguage for defining compiler directives. Also
added the syntax for import statements. Imports are not implemented, but
I'm currently working on that.
-rw-r--r-- | goal.fiddle | 29 | ||||
-rw-r--r-- | src/Language/Fiddle/Ast.hs | 154 | ||||
-rw-r--r-- | src/Language/Fiddle/Compiler/Stage1.hs | 15 | ||||
-rw-r--r-- | src/Language/Fiddle/Compiler/Stage2.hs | 39 | ||||
-rw-r--r-- | src/Language/Fiddle/GenericTree.hs | 23 | ||||
-rw-r--r-- | src/Language/Fiddle/Parser.hs | 89 | ||||
-rw-r--r-- | src/Language/Fiddle/Tokenizer.hs | 47 | ||||
-rw-r--r-- | vim/syntax/fiddle.vim | 15 |
8 files changed, 349 insertions, 62 deletions
diff --git a/goal.fiddle b/goal.fiddle index b59acb4..c35e172 100644 --- a/goal.fiddle +++ b/goal.fiddle @@ -1,24 +1,31 @@ +option board stm32l432; option endian little; +option processor arm_cortex_m4; +option align 32; -// package for the GPIO system. +import "./types.fdl" (data_t); +[[ search = ".local/fiddle/libs" ]] +import "./stm32l432.fdl"; + +[[ cpp: namespace = "stm32l432::gpio" ]] +[[ rust: package = "Stm32l432.Gpio" ]] +[[ zig: package = "stm32l432.gpio" ]] +[[ c: prefix = "stm32l432_gpio_" ]] package gpio { location gpio_a_base = 0x4800_0000; location gpio_b_base = 0x4800_0400; location gpio_c_base = 0x4800_0800; - /** IO Data. This is just an expressive boolean. */ bits data_t : enum(1) { - low = 0, - high = 1, + high = 0b1, + low = 0b0, }; /** * Structure of the GPIO port on an stm32l432 - */ - type gpio_t : struct { - assert_pos(0); + reg (32) : struct { /** The mode for each pin. */ mode_r : enum(2) { @@ -45,7 +52,8 @@ package gpio { * The output type. */ assert_pos(0x04); - reg ocfg_reg(32) : struct { + [[ noexport ]] + reg ocfg_r(32) : struct { otype_r : enum(1) { /** * The GPIO pin is capable of sinking to ground (for LOW) or providing @@ -67,6 +75,8 @@ package gpio { * Sets the speed of the provided GPIO pin. */ assert_pos(0x08); + + [[ noexport ]] reg (32) : struct { ospeed_r : enum(2) { low = 0, @@ -80,6 +90,7 @@ package gpio { * Pullup/Pulldown type */ assert_pos(0x0c); + [[ noexport ]] wo reg (32) : struct { union { pupd_r : enum(2) { @@ -112,6 +123,7 @@ package gpio { assert_pos(0x10); ro reg (32) : struct { id_r : data_t[16]; + reserved(16); }; @@ -202,6 +214,7 @@ package gpio { */ reg(32) : struct { asc_r : (16); + reserved (16); }; }; diff --git a/src/Language/Fiddle/Ast.hs b/src/Language/Fiddle/Ast.hs index 8352975..bb6605e 100644 --- a/src/Language/Fiddle/Ast.hs +++ b/src/Language/Fiddle/Ast.hs @@ -18,13 +18,79 @@ import Data.Typeable import GHC.Generics import GHC.TypeLits --- The type of a number at each stage in compilation. Numbers should be parsed --- in Stage2. -type family NumberType (a :: Stage) where +-- 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 + +-- [[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 @@ -32,8 +98,10 @@ data Stage = Stage1 | Stage2 | Stage3 -- Root of the parse tree. Just contains a list of declarations. data FiddleUnit (stage :: Stage) (f :: Type -> Type) a where - FiddleUnit :: [FiddleDecl stage f a] -> a -> FiddleUnit stage f a - deriving (Generic, Annotated, Alter, Typeable) + 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 @@ -45,6 +113,24 @@ data Expression stage f a where 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 {- @@ -56,6 +142,10 @@ data FiddleDecl (stage :: Stage) (f :: Type -> Type) a where Identifier f a -> a -> FiddleDecl stage f a + ImportDecl :: + ImportType stage f a -> + a -> + FiddleDecl stage f a {- Package Statement. Package Name, Package body -} PackageDecl :: Identifier f a -> @@ -87,10 +177,16 @@ data FiddleDecl (stage :: Stage) (f :: Type -> Type) a where ObjType stage f a -> a -> FiddleDecl stage f a - deriving (Generic, Annotated, Alter, Typeable) + 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 -> [ObjTypeDecl stage f a] -> a -> ObjTypeBody stage f a + 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 @@ -139,7 +235,7 @@ data ModifierKeyword = Rw | Ro | Wo deriving (Eq, Ord, Show, Read, Typeable) data DeferredRegisterBody stage f a where DeferredRegisterBody :: - [RegisterBitsDecl stage f a] -> + [Directed (RegisterBitsDecl stage) f a] -> a -> DeferredRegisterBody stage f a deriving (Generic, Annotated, Alter, Typeable) @@ -150,7 +246,11 @@ data BodyType (f :: Type -> Type) a where 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 + 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 @@ -207,7 +307,8 @@ instance Annotated (Expression stage) where instance Alter (ObjTypeDecl stage) where alter ffn fn = \case - (AssertPosStatement expr a) -> AssertPosStatement <$> alter ffn fn expr <*> fn a + (AssertPosStatement expr a) -> + AssertPosStatement <$> alter ffn fn expr <*> fn a (RegisterDecl mMod mIdent expr mBody a) -> RegisterDecl <$> mapM (alter ffn fn) mMod @@ -285,20 +386,29 @@ data BitType (stage :: Stage) (f :: Type -> Type) a where data EnumBody (stage :: Stage) (f :: Type -> Type) a where -- <decl>, - EnumBody :: [EnumConstantDecl stage f a] -> a -> EnumBody stage f a + 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 + 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 + 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 :: [FiddleDecl stage f a] -> a -> PackageBody stage f a - deriving (Generic, Annotated, Alter, Typeable) + 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) @@ -315,7 +425,7 @@ data PackageBody (stage :: Stage) (f :: Type -> Type) a where proxyOf :: t f a -> Proxy t proxyOf _ = Proxy -class Annotated (t :: (Type -> Type) -> Type -> Type) where +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) @@ -336,7 +446,7 @@ instance (GAnnot a r, GAnnot a l) => GAnnot a (l :+: r) where instance (GAnnot a r) => GAnnot a (M1 i c r) where gannot (M1 a) = gannot a -class Alter (t :: (Type -> Type) -> Type -> Type) where +class Alter (t :: SynTreeKind) where alter :: forall f1 f2 a1 a2 m. (Monad m, Traversable f1) => @@ -384,13 +494,19 @@ 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 +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 +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) diff --git a/src/Language/Fiddle/Compiler/Stage1.hs b/src/Language/Fiddle/Compiler/Stage1.hs index 25ee66b..2e3acbc 100644 --- a/src/Language/Fiddle/Compiler/Stage1.hs +++ b/src/Language/Fiddle/Compiler/Stage1.hs @@ -68,7 +68,7 @@ toStage2 (FiddleUnit decls annot) = do FiddleUnit <$> reconfigureFiddleDecls (Path []) decls <*> pure annot return a -reconfigureFiddleDecls :: Path -> [FiddleDecl Stage1 I Annot] -> M Annot [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 -- put (Stage2CompilerState [] []) @@ -76,13 +76,13 @@ reconfigureFiddleDecls p decls = do lastState <- get put (Stage2CompilerState [] []) - decls <- mapM (fiddleDeclToStage2 p) decls + decls <- mapM (mapDirectedM $ fiddleDeclToStage2 p) decls (Stage2CompilerState anonymousObjTypes anonymousBitsTypes) <- get put lastState return $ - map resolveAnonymousObjType anonymousObjTypes - ++ map resolveAnonymousBitsType anonymousBitsTypes + map (asDirected . resolveAnonymousObjType) anonymousObjTypes + ++ map (asDirected . resolveAnonymousBitsType) anonymousBitsTypes ++ decls where resolveAnonymousObjType (Linkage linkage, objTypeBody) = @@ -104,6 +104,7 @@ fiddleDeclToStage2 path decl = do (LocationDecl i expr a) -> LocationDecl i <$> toStage2Expr expr <*> pure a (BitsDecl i typ a) -> BitsDecl i <$> bitsTypeToStage2 (pushId i path) typ <*> pure a (ObjTypeDecl i body a) -> ObjTypeDecl i <$> mapM (objTypeBodyToStage2 (pushId i path)) body <*> pure a + (ImportDecl importStatement a) -> return $ ImportDecl importStatement a (ObjectDecl i expr typ a) -> ObjectDecl i <$> toStage2Expr expr <*> objectTypeToStage2 (pushId i path) typ <*> pure a @@ -115,7 +116,7 @@ bitsTypeToStage2 path = \case enumBodyToStage2 :: Path -> EnumBody Stage1 I Annot -> M Annot (EnumBody Stage2 I Annot) enumBodyToStage2 path = \case - EnumBody constants a -> EnumBody <$> mapM (enumConstantToStage2 path) constants <*> pure a + EnumBody constants a -> EnumBody <$> mapM (mapDirectedM (enumConstantToStage2 path)) constants <*> pure a enumConstantToStage2 :: Path -> EnumConstantDecl Stage1 I Annot -> M Annot (EnumConstantDecl Stage2 I Annot) enumConstantToStage2 path = \case @@ -124,7 +125,7 @@ enumConstantToStage2 path = \case objTypeBodyToStage2 :: Path -> ObjTypeBody Stage1 I Annot -> M Annot (ObjTypeBody Stage2 I Annot) objTypeBodyToStage2 path (ObjTypeBody bodyType decls annot) = - ObjTypeBody bodyType <$> mapM (objTypeDeclToStage2 path) decls <*> pure annot + ObjTypeBody bodyType <$> mapM (mapDirectedM $ objTypeDeclToStage2 path) decls <*> pure annot objTypeDeclToStage2 :: Path -> ObjTypeDecl Stage1 I Annot -> M Annot (ObjTypeDecl Stage2 I Annot) objTypeDeclToStage2 path = \case @@ -150,7 +151,7 @@ registerBodyToStage2 :: Path -> RegisterBody Stage1 I Annot -> M Annot (Register registerBodyToStage2 path (RegisterBody bodyType (Identity (DeferredRegisterBody registerBitsDecl a1)) a2) = RegisterBody bodyType . Identity <$> ( DeferredRegisterBody - <$> mapM (registerBitsDeclToStage2 path) registerBitsDecl + <$> mapM (mapDirectedM $ registerBitsDeclToStage2 path) registerBitsDecl <*> pure a1 ) <*> pure a2 diff --git a/src/Language/Fiddle/Compiler/Stage2.hs b/src/Language/Fiddle/Compiler/Stage2.hs index 727f153..431fc76 100644 --- a/src/Language/Fiddle/Compiler/Stage2.hs +++ b/src/Language/Fiddle/Compiler/Stage2.hs @@ -72,7 +72,7 @@ toStage3 (FiddleUnit decls a) = snd <$> subCompile emptyState - ( FiddleUnit <$> mapM fiddleDeclToStage3 decls <*> pure a + ( FiddleUnit <$> mapM (mapDirectedM fiddleDeclToStage3) decls <*> pure a ) exprToSize :: @@ -94,7 +94,7 @@ getTypeSize (EnumBitType expr (Identity (EnumBody constants _)) ann) = do when (declaredSize <= 4) $ do imap <- foldlM - ( \imap enumConst -> do + ( \imap (undirected -> enumConst) -> do number <- case enumConst of EnumConstantDecl _ expr _ -> exprToSize expr EnumConstantReserved expr _ -> exprToSize expr @@ -137,6 +137,7 @@ fiddleDeclToStage3 = \case BitsDecl id <$> bitTypeToStage3 typ <*> pure a ObjTypeDecl ident body 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 @@ -162,10 +163,10 @@ registerBodyToStage3 (RegisterBody bodyType (Identity deferredRegisterBody) a') (cur, returned) <- foldlM ( \(cursor, returned) decl -> - case decl of + case undirected decl of ReservedBits expr a -> do size <- fromIntegral <$> exprToSize expr - let s3 = ReservedBits (expressionToStage3 expr) a + let s3 = mapDirected (const $ ReservedBits (expressionToStage3 expr) a) decl if isUnion then checkUnion cursor size (s3 : returned) a else @@ -174,7 +175,7 @@ registerBodyToStage3 (RegisterBody bodyType (Identity deferredRegisterBody) a') checkBitsSubStructure registerBody maybeIdent annot (newBody, subsize) <- registerBodyToStage3 registerBody - let s3 = BitsSubStructure newBody maybeIdent annot + let s3 = mapDirected (const $ BitsSubStructure newBody maybeIdent annot) decl if isUnion then checkUnion cursor subsize (s3 : returned) a @@ -182,7 +183,7 @@ registerBodyToStage3 (RegisterBody bodyType (Identity deferredRegisterBody) a') return (cursor + subsize, s3 : returned) DefinedBits modifier identifier typeref a -> do (s3TypeRef, size) <- registerBitsTypeRefToStage3 typeref - let s3 = DefinedBits modifier identifier s3TypeRef a + let s3 = mapDirected (const $ DefinedBits modifier identifier s3TypeRef a) decl if isUnion then checkUnion cursor size (s3 : returned) a @@ -265,18 +266,22 @@ objTypeBodyToStage3 (ObjTypeBody bodyType decls a) startOff = do (cur, returned) <- foldlM ( \(cursor, returned) decl -> - case decl of + case undirected decl of RegisterDecl mMod mIdent expr mBody a -> do (s3RegisterBody, mCalculatedSize) <- fUnzip <$> mapM registerBodyToStage3 mBody let s3 = - RegisterDecl - mMod - mIdent - (expressionToStage3 expr) - s3RegisterBody - a + mapDirected + ( const $ + RegisterDecl + mMod + mIdent + (expressionToStage3 expr) + s3RegisterBody + a + ) + decl declaredSizeBits <- fromIntegral <$> exprToSize expr @@ -320,7 +325,7 @@ objTypeBodyToStage3 (ObjTypeBody bodyType decls a) startOff = do subBody ( if isUnion then startOff else cursor ) - let s3 = TypeSubStructure (Identity newBody) maybeIdent annot + let s3 = mapDirected (const $ TypeSubStructure (Identity newBody) maybeIdent annot) decl checkTypesSubStructure subBody maybeIdent annot if isUnion @@ -338,7 +343,7 @@ objTypeBodyToStage3 (ObjTypeBody bodyType decls a) startOff = do (unCommented a) ] let size = size' `div` 8 - let s3 = ReservedDecl (expressionToStage3 expr) annot + let s3 = mapDirected (const $ ReservedDecl (expressionToStage3 expr) annot) decl if isUnion then checkUnion cursor size (s3 : returned) a @@ -406,7 +411,7 @@ bitTypeToStage3 (EnumBitType expr body a) = enumBodyToStage3 :: EnumBody Stage2 I Annot -> Compile Stage3State (EnumBody Stage3 I Annot) enumBodyToStage3 (EnumBody constants a) = - EnumBody <$> mapM enumConstantDeclToStage3 constants <*> pure a + EnumBody <$> mapM (mapDirectedM enumConstantDeclToStage3) constants <*> pure a enumConstantDeclToStage3 :: EnumConstantDecl Stage2 I Annot -> Compile Stage3State (EnumConstantDecl Stage3 I Annot) enumConstantDeclToStage3 = \case @@ -415,4 +420,4 @@ enumConstantDeclToStage3 = \case packageBodyToStage3 :: PackageBody Stage2 I Annot -> Compile Stage3State (PackageBody Stage3 I Annot) packageBodyToStage3 (PackageBody decls a) = - PackageBody <$> mapM fiddleDeclToStage3 decls <*> pure a + PackageBody <$> mapM (mapDirectedM fiddleDeclToStage3) decls <*> pure a diff --git a/src/Language/Fiddle/GenericTree.hs b/src/Language/Fiddle/GenericTree.hs index 00824ed..46c0594 100644 --- a/src/Language/Fiddle/GenericTree.hs +++ b/src/Language/Fiddle/GenericTree.hs @@ -28,7 +28,12 @@ import Language.Fiddle.Types import Text.Parsec.Pos import Text.Printf (printf) -type Context stage = (Show (NumberType stage), Typeable stage) +type Context stage = + ( Show (NumberType stage), + Typeable stage, + ToGenericSyntaxTree (ImportType stage), + Typeable (ImportType stage) + ) data GenericSyntaxTree f a where {- GenericSyntaxtTree with a name and children. -} @@ -94,7 +99,7 @@ instance ToGenericSyntaxTreeValue Data.Text.Text where type GenericContext t f a = (Traversable f, ToGenericSyntaxTree t, Typeable t, Typeable f, Typeable a) -class ToGenericSyntaxTree (t :: (Type -> Type) -> Type -> Type) where +class ToGenericSyntaxTree (t :: SynTreeKind) 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)) => @@ -176,6 +181,20 @@ deriving instance (ToGenericSyntaxTree Identifier) deriving instance (ToGenericSyntaxTree BodyType) +deriving instance (ToGenericSyntaxTree Directive) + +deriving instance (ToGenericSyntaxTree DirectiveBody) + +deriving instance (ToGenericSyntaxTree DirectiveElement) + +deriving instance (ToGenericSyntaxTree DirectiveExpression) + +deriving instance (ToGenericSyntaxTree ImportList) + +deriving instance (ToGenericSyntaxTree ImportStatement) + +deriving instance (ToGenericSyntaxTree t, Typeable t) => (ToGenericSyntaxTree (Directed t)) + deriving instance (Context stage) => (ToGenericSyntaxTree (FiddleUnit stage)) deriving instance (Context stage) => (ToGenericSyntaxTree (FiddleDecl stage)) diff --git a/src/Language/Fiddle/Parser.hs b/src/Language/Fiddle/Parser.hs index 7eed0f2..f3ad744 100644 --- a/src/Language/Fiddle/Parser.hs +++ b/src/Language/Fiddle/Parser.hs @@ -7,6 +7,7 @@ module Language.Fiddle.Parser ) where +import Control.Monad (void) import Data.Functor.Identity import Data.Kind (Type) import Data.Text (Text) @@ -50,25 +51,89 @@ isComment (Token t _) = stripTrailingComments :: [Token s] -> [Token s] stripTrailingComments = reverse . dropWhile isComment . reverse +directed :: Pa t -> PaS (Directed (t 'Stage1)) +directed subparser = withMeta $ do + Directed <$> many directive <*> subparser + +directive :: PaS Directive +directive = + withMeta $ + Directive <$> defer directiveBodyTokens directiveBody + +directiveBody :: PaS DirectiveBody +directiveBody = withMeta $ do + DirectiveBody <$> many (directiveElement <* (void (tok TokComma) <|> eof)) + +directiveElement :: PaS DirectiveElement +directiveElement = withMeta $ do + identifier1 <- nextText + choice + [ do + tok TokColon + let backend = identifier1 + key <- nextText + choice + [ do + tok TokEq + DirectiveElementKeyValue (Just backend) key <$> directiveExpression, + do + return (DirectiveElementKey (Just backend) key) + ], + do + tok TokEq + let key = identifier1 + DirectiveElementKeyValue Nothing key <$> directiveExpression, + return $ DirectiveElementKey Nothing identifier1 + ] + +nextText :: PaS Identifier +nextText = withMeta $ Identifier <$> token textOf + +directiveExpression :: PaS DirectiveExpression +directiveExpression = withMeta $ do + choice + [ do + token $ \case + (TokString str) -> Just $ DirectiveString str + (TokLitNum num) -> Just $ DirectiveNumber num + _ -> Nothing + ] + fiddleUnit :: Pa FiddleUnit fiddleUnit = do withMeta - ( FiddleUnit <$> many1 (fiddleDecl <* tok TokSemi) + ( FiddleUnit <$> many1 (directed fiddleDecl <* tok TokSemi) ) <* many comment +stringToken :: P Text +stringToken = token (\case + (TokString str) -> Just str + _ -> Nothing) + +importList :: PaS ImportList +importList = withMeta $ do + tok TokLParen + ImportList <$> many (ident <* (tok TokComma <|> lookAhead (tok TokRParen))) + <* tok TokRParen + +importStatement :: PaS ImportStatement +importStatement = withMeta $ + ImportStatement <$> stringToken <*> optionMaybe importList + fiddleDecl :: Pa FiddleDecl fiddleDecl = do withMeta $ do t <- tokenType <$> anyToken case t of - KWOption -> OptionDecl <$> ident <*> ident + KWOption -> OptionDecl <$> nextText <*> nextText KWPackage -> PackageDecl <$> ident <*> defer body packageBody KWLocation -> LocationDecl <$> ident <*> (tok TokEq >> expression) KWBits -> BitsDecl <$> ident <*> (tok TokColon >> bitType) + KWImport -> ImportDecl <$> importStatement KWType -> ObjTypeDecl <$> ident @@ -132,7 +197,7 @@ exprInParen = tok TokLParen *> expression <* tok TokRParen objTypeBody :: BodyType F (Commented SourceSpan) -> Pa ObjTypeBody objTypeBody bt = withMeta $ - ObjTypeBody bt <$> many (objTypeDecl <* tok TokSemi) + ObjTypeBody bt <$> many (directed objTypeDecl <* tok TokSemi) objTypeDecl :: Pa ObjTypeDecl objTypeDecl = @@ -185,7 +250,7 @@ registerBody = withMeta $ RegisterBody <$> bitBodyType <*> defer body deferredRe deferredRegisterBody :: Pa DeferredRegisterBody deferredRegisterBody = withMeta $ - DeferredRegisterBody <$> many (registerBitsDecl <* tok TokSemi) + DeferredRegisterBody <$> many (directed registerBitsDecl <* tok TokSemi) registerBitsDecl :: Pa RegisterBitsDecl registerBitsDecl = @@ -239,7 +304,7 @@ bitType = withMeta $ rawBits <|> enumType enumBody :: Pa EnumBody enumBody = withMeta $ - EnumBody <$> many (enumConstantDecl <* tok TokComma) + EnumBody <$> many (directed enumConstantDecl <* tok TokComma) enumConstantDecl :: Pa EnumConstantDecl enumConstantDecl = @@ -260,6 +325,13 @@ body = do (_, b, _) <- body' return b +directiveBodyTokens :: P [Token SourceSpan] +directiveBodyTokens = do + tokKeepComment TokDirectiveStart + ret <- concat <$> manyTill ((: []) <$> anyToken) (lookAhead $ tokKeepComment TokDirectiveEnd) + tokKeepComment TokDirectiveEnd + return ret + body' :: P (Token SourceSpan, [Token SourceSpan], Token SourceSpan) body' = do l <- tokKeepComment TokLBrace @@ -299,9 +371,10 @@ packageBody = withMeta $ PackageBody <$> many - ( fiddleDecl - <* ( tok TokSemi <|> fail "Expected ';'" - ) + ( directed $ + fiddleDecl + <* ( tok TokSemi <|> fail "Expected ';'" + ) ) printNext :: P () diff --git a/src/Language/Fiddle/Tokenizer.hs b/src/Language/Fiddle/Tokenizer.hs index 08f5649..87f119f 100644 --- a/src/Language/Fiddle/Tokenizer.hs +++ b/src/Language/Fiddle/Tokenizer.hs @@ -27,6 +27,7 @@ data T | KWType | KWUnion | KWWo + | KWImport | TokColon | TokComma | TokComment !Text @@ -41,8 +42,35 @@ data T | TokRBracket | TokRParen | TokSemi + | TokString !Text + | TokDirectiveStart -- [[ + | TokDirectiveEnd -- ]] deriving (Eq, Ord, Show, Read) +textOf :: T -> Maybe Text +textOf t = do + case t of + KWAssertPos -> Just "assert_pos" + KWAt -> Just "at" + KWBits -> Just "bits" + KWEnum -> Just "enum" + KWInstance -> Just "instance" + KWLocation -> Just "location" + KWOption -> Just "option" + KWPackage -> Just "package" + KWReg -> Just "reg" + KWReserved -> Just "reserved" + KWRo -> Just "ro" + KWRw -> Just "rw" + KWStruct -> Just "struct" + KWType -> Just "type" + KWUnion -> Just "union" + KWWo -> Just "wo" + KWImport -> Just "import" + TokIdent i -> Just i + TokLitNum n -> Just n + _ -> Nothing + data Token a = Token !T a deriving (Eq, Ord, Show, Functor) @@ -66,6 +94,7 @@ parseToken = spaces *> tok parseToken' <* spaces "type" -> KWType "option" -> KWOption "package" -> KWPackage + "import" -> KWImport "reg" -> KWReg "ro" -> KWRo "wo" -> KWWo @@ -77,6 +106,19 @@ parseToken = spaces *> tok parseToken' <* spaces (Data.Text.head -> h) | isDigit h -> TokLitNum str ident -> TokIdent ident + parseString = fmap (TokString . Data.Text.pack . concat) $ do + char '"' + manyTill + ( do + c <- anyChar + if c == '\\' + then do + c2 <- anyChar + return [c, c2] + else return [c] + ) + (char '"') + parseComment = try ( do @@ -91,7 +133,9 @@ parseToken = spaces *> tok parseToken' <* spaces parseSymbol = choice - [ char ':' $> TokColon, + [ try (string "[[" $> TokDirectiveStart), + try (string "]]" $> TokDirectiveEnd), + char ':' $> TokColon, char ',' $> TokComma, char '=' $> TokEq, char '{' $> TokLBrace, @@ -107,6 +151,7 @@ parseToken = spaces *> tok parseToken' <* spaces parseToken' = fmap (parseAlNumTok . Data.Text.pack) (many1 (alphaNum <|> char '_')) + <|> parseString <|> parseComment <|> parseSymbol diff --git a/vim/syntax/fiddle.vim b/vim/syntax/fiddle.vim index 7d36e93..70a3f26 100644 --- a/vim/syntax/fiddle.vim +++ b/vim/syntax/fiddle.vim @@ -13,9 +13,24 @@ syn match FiddleIdent +[A-Za-z0-9_]\++ contained syn match FiddleComment +\/\/.*$+ syn region FiddleDocComment start=+/\*\*+ end=+*/+ +syn region FiddleString start=+"+ end=+"+ skip=+\\.+ + +syn region FiddleDirective start=+\[\[+ end=+\]\]+ contains=FiddleString syn match FiddleNumber +\<[0-9_]\+\([xb]\)\@!\|0x[0-9A-Fa-f][0-9A-Fa-f_]*\|0b[01]\+\>+ +syn match FiddleImport +import+ nextgroup=FiddleImportString skipwhite +syn region FiddleImportString start=+"+ end=+"+ skip=+\\.+ skipwhite nextgroup=FiddleImportList contained +syn region FiddleImportList start=+(+ end=+)+ skipwhite contained contains=FiddleImportValue +syn match FiddleImportValue +[a-zA-Z0-9_]\++ contained + +hi! link FiddleImportString FiddleString +hi! link FiddleImportList PreProc +hi! link FiddleImportValue Type +hi! link FiddleImport FiddleStorageClass + +hi! link FiddleString String +hi! link FiddleDirective PreProc hi! link FiddleContainedType Type hi! link FiddleModifier StorageClass hi! link FiddleBuiltin Function |