summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-09-22 00:26:39 -0600
committerJosh Rahm <joshuarahm@gmail.com>2024-09-22 00:26:39 -0600
commit0d2095b5d42989639c1861d7213c182abd064672 (patch)
treee7d43320521f6bfb57d214cb949db8c8674c18c5
parentf0c4da33e9576d2509b8c6330b1663e044e2dff3 (diff)
downloadfiddle-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.fiddle29
-rw-r--r--src/Language/Fiddle/Ast.hs154
-rw-r--r--src/Language/Fiddle/Compiler/Stage1.hs15
-rw-r--r--src/Language/Fiddle/Compiler/Stage2.hs39
-rw-r--r--src/Language/Fiddle/GenericTree.hs23
-rw-r--r--src/Language/Fiddle/Parser.hs89
-rw-r--r--src/Language/Fiddle/Tokenizer.hs47
-rw-r--r--vim/syntax/fiddle.vim15
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