summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-09-20 10:43:43 -0600
committerJosh Rahm <joshuarahm@gmail.com>2024-09-20 10:43:43 -0600
commitf0c4da33e9576d2509b8c6330b1663e044e2dff3 (patch)
tree15120a7b0ca3795fc7b35478f708d54c1c988ec5
parentf1128c7c60809d1e96009eaed98c0756831fe29f (diff)
downloadfiddle-f0c4da33e9576d2509b8c6330b1663e044e2dff3.tar.gz
fiddle-f0c4da33e9576d2509b8c6330b1663e044e2dff3.tar.bz2
fiddle-f0c4da33e9576d2509b8c6330b1663e044e2dff3.zip
Some major changes to the structure of the language.
Added structures and unions to better define the layout and model overlapping concerns. renamed objtype -> type and object -> instance. added reserved statements for types.
-rw-r--r--goal.fiddle92
-rw-r--r--package.yaml1
-rw-r--r--src/Language/Fiddle/Ast.hs35
-rw-r--r--src/Language/Fiddle/Compiler/Stage1.hs18
-rw-r--r--src/Language/Fiddle/Compiler/Stage2.hs202
-rw-r--r--src/Language/Fiddle/GenericTree.hs16
-rw-r--r--src/Language/Fiddle/Parser.hs51
-rw-r--r--src/Language/Fiddle/Tokenizer.hs22
-rw-r--r--vim/syntax/fiddle.vim8
9 files changed, 354 insertions, 91 deletions
diff --git a/goal.fiddle b/goal.fiddle
index b87f0e9..b59acb4 100644
--- a/goal.fiddle
+++ b/goal.fiddle
@@ -1,6 +1,7 @@
option endian little;
// package for the GPIO system.
+
package gpio {
location gpio_a_base = 0x4800_0000;
@@ -16,9 +17,9 @@ package gpio {
/**
* Structure of the GPIO port on an stm32l432
*/
- objtype gpio_t : {
+ type gpio_t : struct {
assert_pos(0);
- reg (32) : {
+ reg (32) : struct {
/** The mode for each pin. */
mode_r : enum(2) {
/** The GPIO pin is used for input. */
@@ -44,7 +45,7 @@ package gpio {
* The output type.
*/
assert_pos(0x04);
- reg ocfg_reg(32) : {
+ reg ocfg_reg(32) : struct {
otype_r : enum(1) {
/**
* The GPIO pin is capable of sinking to ground (for LOW) or providing
@@ -66,7 +67,7 @@ package gpio {
* Sets the speed of the provided GPIO pin.
*/
assert_pos(0x08);
- reg (32) : {
+ reg (32) : struct {
ospeed_r : enum(2) {
low = 0,
medium = 1,
@@ -79,16 +80,26 @@ package gpio {
* Pullup/Pulldown type
*/
assert_pos(0x0c);
- wo reg (32) : {
- pupd_r : enum(2) {
- none = 0b0,
- // Compiles to Gpio::PupdR::PullUp
- pull_up = 0b1,
- // Compiles to Gpio::PupdR::PullDown
- pull_down = 0b10,
- // Not used, but has to be included to fill out the enum.
- reserved = 0b11,
- } [16];
+ wo reg (32) : struct {
+ union {
+ pupd_r : enum(2) {
+ none = 0b0,
+ // Compiles to Gpio::PupdR::PullUp
+ pull_up = 0b1,
+ // Compiles to Gpio::PupdR::PullDown
+ pull_down = 0b10,
+ // Not used, but has to be included to fill out the enum.
+ reserved = 0b11,
+ } [16];
+
+ struct {
+ alternate : enum(1) {
+ enabled = 0,
+ disabled = 1,
+ } [16];
+ reserved(16);
+ };
+ };
};
/**
@@ -97,11 +108,26 @@ package gpio {
* Reading form the provided pin will yield high if the pin is on, or low if
* the pin is low.
*/
- assert_pos(0x10);
- ro reg (32) : {
- id_r : data_t[16];
- reserved(16);
+ union {
+ assert_pos(0x10);
+ ro reg (32) : struct {
+ id_r : data_t[16];
+ reserved(16);
+ };
+
+ // Additinoal values .
+ assert_pos(0x10);
+ struct {
+ assert_pos(0x10);
+ wo reg alt_r1(16);
+
+ assert_pos(0x12);
+ wo reg alt_r2(8);
+ reserved(8);
+ };
};
+ assert_pos(0x14);
+
/**
* Output data register.
@@ -109,8 +135,18 @@ package gpio {
* Writing to this register sets the appropriate register to low/high.
*/
assert_pos(0x14);
- wo reg (32) : {
- rw od_r : data_t[16];
+ wo reg (32) : struct {
+ union {
+ rw od_r : data_t[16];
+
+ struct {
+ rw osp_v : (15);
+ // Without the reserved bit, the compiler will complain about jagged
+ // unions.
+ reserved(1);
+ };
+ };
+
reserved(16);
};
@@ -118,7 +154,7 @@ package gpio {
* The GPIO port bit set/reset register.
*/
assert_pos(0x18);
- reg bsr_r(32) : {
+ reg bsr_r(32) : struct {
/**
* Sets the pins associated with the bits. Like od_r, but can be used to
* turn on multiple pins at once.
@@ -132,7 +168,7 @@ package gpio {
};
assert_pos(0x1c);
- reg(32) : {
+ reg(32) : struct {
lock : enum(1) {
unlocked = 0,
locked = 1,
@@ -148,7 +184,7 @@ package gpio {
* Each nybble refers to a pin.
*/
assert_pos(0x20);
- reg(64) : {
+ reg(64) : struct {
afn : (4)[16];
};
@@ -156,7 +192,7 @@ package gpio {
* The bit reset register.
*/
assert_pos(0x28);
- reg(32) : {
+ reg(32) : struct {
wo br_r : (16);
reserved (16);
};
@@ -164,13 +200,13 @@ package gpio {
/**
* Analog switch control for the pin.
*/
- reg(32) : {
+ reg(32) : struct {
asc_r : (16);
reserved (16);
};
};
- object gpio_a at gpio_a_base : gpio_t;
- object gpio_b at gpio_b_base : gpio_t;
- object gpio_c at gpio_c_base : gpio_t;
+ instance gpio_a at gpio_a_base : gpio_t;
+ instance gpio_b at gpio_b_base : gpio_t;
+ instance gpio_c at gpio_c_base : gpio_t;
};
diff --git a/package.yaml b/package.yaml
index f2394a7..56f6ffd 100644
--- a/package.yaml
+++ b/package.yaml
@@ -35,3 +35,4 @@ dependencies:
- data-default
- transformers
- containers
+ - optparse-applicative
diff --git a/src/Language/Fiddle/Ast.hs b/src/Language/Fiddle/Ast.hs
index d440a44..8352975 100644
--- a/src/Language/Fiddle/Ast.hs
+++ b/src/Language/Fiddle/Ast.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
@@ -5,7 +6,6 @@
{-# LANGUAGE IncoherentInstances #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE ConstraintKinds #-}
module Language.Fiddle.Ast where
@@ -18,6 +18,8 @@ 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
NumberType Stage1 = Text
NumberType Stage2 = Integer
@@ -88,7 +90,7 @@ data FiddleDecl (stage :: Stage) (f :: Type -> Type) a where
deriving (Generic, Annotated, Alter, Typeable)
data ObjTypeBody (stage :: Stage) (f :: Type -> Type) a where
- ObjTypeBody :: [ObjTypeDecl stage f a] -> a -> ObjTypeBody stage f a
+ ObjTypeBody :: BodyType f a -> [ObjTypeDecl stage f a] -> a -> ObjTypeBody stage f a
deriving (Generic, Annotated, Alter, Typeable)
data ObjType stage f a where
@@ -119,6 +121,14 @@ data ObjTypeDecl stage f a where
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
@@ -134,8 +144,13 @@ data DeferredRegisterBody stage f a where
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 :: 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
@@ -148,6 +163,11 @@ data RegisterBitsDecl stage f a where
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
@@ -195,6 +215,15 @@ instance Alter (ObjTypeDecl stage) where
<*> 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
diff --git a/src/Language/Fiddle/Compiler/Stage1.hs b/src/Language/Fiddle/Compiler/Stage1.hs
index 3a97757..25ee66b 100644
--- a/src/Language/Fiddle/Compiler/Stage1.hs
+++ b/src/Language/Fiddle/Compiler/Stage1.hs
@@ -123,11 +123,20 @@ enumConstantToStage2 path = \case
EnumConstantReserved e a -> EnumConstantReserved <$> toStage2Expr e <*> pure a
objTypeBodyToStage2 :: Path -> ObjTypeBody Stage1 I Annot -> M Annot (ObjTypeBody Stage2 I Annot)
-objTypeBodyToStage2 path (ObjTypeBody decls annot) = ObjTypeBody <$> mapM (objTypeDeclToStage2 path) decls <*> pure annot
+objTypeBodyToStage2 path (ObjTypeBody bodyType decls annot) =
+ ObjTypeBody bodyType <$> mapM (objTypeDeclToStage2 path) decls <*> pure annot
objTypeDeclToStage2 :: Path -> ObjTypeDecl Stage1 I Annot -> M Annot (ObjTypeDecl Stage2 I Annot)
objTypeDeclToStage2 path = \case
(AssertPosStatement expr annot) -> AssertPosStatement <$> toStage2Expr expr <*> pure annot
+ (TypeSubStructure (Identity deferredBody) maybeIdent annot) ->
+ let path' = maybe path (`pushId` path) maybeIdent
+ in TypeSubStructure . Identity
+ <$> objTypeBodyToStage2 path' deferredBody
+ <*> pure maybeIdent
+ <*> pure annot
+ (ReservedDecl expr a) ->
+ ReservedDecl <$> toStage2Expr expr <*> pure a
(RegisterDecl maybeModifier maybeIdentifier expression maybeBody annot) ->
let path' = maybe path (`pushId` path) maybeIdentifier
in RegisterDecl
@@ -138,8 +147,8 @@ objTypeDeclToStage2 path = \case
<*> pure annot
registerBodyToStage2 :: Path -> RegisterBody Stage1 I Annot -> M Annot (RegisterBody Stage2 I Annot)
-registerBodyToStage2 path (RegisterBody (Identity (DeferredRegisterBody registerBitsDecl a1)) a2) =
- RegisterBody . Identity
+registerBodyToStage2 path (RegisterBody bodyType (Identity (DeferredRegisterBody registerBitsDecl a1)) a2) =
+ RegisterBody bodyType . Identity
<$> ( DeferredRegisterBody
<$> mapM (registerBitsDeclToStage2 path) registerBitsDecl
<*> pure a1
@@ -149,6 +158,9 @@ registerBodyToStage2 path (RegisterBody (Identity (DeferredRegisterBody register
registerBitsDeclToStage2 :: Path -> RegisterBitsDecl Stage1 I Annot -> M Annot (RegisterBitsDecl Stage2 I Annot)
registerBitsDeclToStage2 path = \case
ReservedBits expr a -> ReservedBits <$> toStage2Expr expr <*> pure a
+ BitsSubStructure registerBody maybeIdent annot ->
+ let path' = maybe path (`pushId` path) maybeIdent
+ in BitsSubStructure <$> registerBodyToStage2 path' registerBody <*> pure maybeIdent <*> pure annot
DefinedBits maybeModifier identifier registerBitsTyperef annot ->
let path' = pushId identifier path
in ( DefinedBits
diff --git a/src/Language/Fiddle/Compiler/Stage2.hs b/src/Language/Fiddle/Compiler/Stage2.hs
index baa61e3..727f153 100644
--- a/src/Language/Fiddle/Compiler/Stage2.hs
+++ b/src/Language/Fiddle/Compiler/Stage2.hs
@@ -117,8 +117,8 @@ getTypeSize (EnumBitType expr (Identity (EnumBody constants _)) ann) = do
[ Diagnostic
Warning
( printf
- "Missing enum constants %s. Please fully pack a small enum.\
- \ Use 'reserved' if needed."
+ "Missing enum constants %s. Small enums should be fully \
+ \ populated. Use 'reserved' if needed."
(intercalate ", " (map show missing))
)
(unCommented ann)
@@ -136,7 +136,7 @@ fiddleDeclToStage3 = \case
addTypeSize id typeSize
BitsDecl id <$> bitTypeToStage3 typ <*> pure a
ObjTypeDecl ident body a ->
- ObjTypeDecl ident <$> mapM objTypeBodyToStage3 body <*> pure a
+ ObjTypeDecl ident <$> mapM (\bt -> fst <$> objTypeBodyToStage3 bt 0) body <*> pure a
ObjectDecl ident expr typ a ->
ObjectDecl ident (expressionToStage3 expr) <$> objTypeToStage3 typ <*> pure a
@@ -152,7 +152,11 @@ objTypeToStage3 = \case
registerBodyToStage3 ::
RegisterBody Stage2 I Annot ->
Compile Stage3State (RegisterBody Stage3 I Annot, Word32)
-registerBodyToStage3 (RegisterBody (Identity deferredRegisterBody) a') =
+registerBodyToStage3 (RegisterBody bodyType (Identity deferredRegisterBody) a') = do
+ let isUnion = case bodyType of
+ Union {} -> True
+ _ -> False
+
case deferredRegisterBody of
DeferredRegisterBody decls a -> do
(cur, returned) <-
@@ -160,17 +164,79 @@ registerBodyToStage3 (RegisterBody (Identity deferredRegisterBody) a') =
( \(cursor, returned) decl ->
case decl of
ReservedBits expr a -> do
- size <- exprToSize expr
+ size <- fromIntegral <$> exprToSize expr
let s3 = ReservedBits (expressionToStage3 expr) a
- return (cursor + fromIntegral size, s3 : returned)
+ 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 = BitsSubStructure newBody maybeIdent annot
+
+ 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
- return (cursor + size, DefinedBits modifier identifier s3TypeRef a : returned)
+ let s3 = DefinedBits modifier identifier s3TypeRef a
+
+ if isUnion
+ then checkUnion cursor size (s3 : returned) a
+ else
+ return (cursor + size, s3 : returned)
)
(0, [])
decls
- return (RegisterBody (Identity (DeferredRegisterBody (reverse returned) a)) a', cur)
+ 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 ()
+
+checkUnion :: Word32 -> Word32 -> b -> Commented SourceSpan -> Compile Stage3State (Word32, b)
+checkUnion cursor subsize ret a = do
+ when (cursor /= 0 && subsize /= cursor) $ do
+ tell
+ [ Diagnostic
+ Warning
+ ( printf
+ "Jagged union found. Found size %d, expected %d.\n \
+ \ Please wrap smaller fields in a struct with padding so all \
+ \ fields are the same size?"
+ subsize
+ cursor
+ )
+ (unCommented a)
+ ]
+ return (max cursor subsize, ret)
registerBitsTypeRefToStage3 ::
RegisterBitsTypeRef Stage2 I Annot ->
@@ -191,8 +257,11 @@ registerBitsTypeRefToStage3 = \case
<$> exprToSize expr
objTypeBodyToStage3 ::
- ObjTypeBody Stage2 I Annot -> Compile Stage3State (ObjTypeBody Stage3 I Annot)
-objTypeBodyToStage3 (ObjTypeBody decls a) = do
+ ObjTypeBody Stage2 I Annot -> Word32 -> Compile Stage3State (ObjTypeBody Stage3 I Annot, Word32)
+objTypeBodyToStage3 (ObjTypeBody bodyType decls a) startOff = do
+ let isUnion = case bodyType of
+ Union {} -> True
+ _ -> False
(cur, returned) <-
foldlM
( \(cursor, returned) decl ->
@@ -209,7 +278,7 @@ objTypeBodyToStage3 (ObjTypeBody decls a) = do
s3RegisterBody
a
- declaredSizeBits <- exprToSize expr
+ declaredSizeBits <- fromIntegral <$> exprToSize expr
when ((declaredSizeBits `mod` 8) /= 0) $
tell
@@ -222,45 +291,108 @@ objTypeBodyToStage3 (ObjTypeBody decls a) = do
forM_ mCalculatedSize $ \(fromIntegral -> calculatedSize) ->
unless (calculatedSize == declaredSizeBits) $
let helpful =
- if calculatedSize < declaredSizeBits then
- printf "\nPerhaps you should add 'reserved(%d)' to the end of your register declaration?"
- (declaredSizeBits - calculatedSize)
- else ""
- in
-
- tell
- [ Diagnostic
- Error
- ( printf
- "Calculated size %d does not match declared size %d.%s"
- calculatedSize
- declaredSizeBits
- helpful
- )
- (unCommented a)
- ]
-
- return (cursor + declaredSizeBits `div` 8, s3 : returned)
+ if calculatedSize < declaredSizeBits
+ then
+ printf
+ "\nPerhaps you should add 'reserved(%d)' to the end of your register declaration?"
+ (declaredSizeBits - calculatedSize)
+ else ""
+ in tell
+ [ Diagnostic
+ Error
+ ( printf
+ "Calculated size %d does not match declared size %d.%s"
+ calculatedSize
+ declaredSizeBits
+ helpful
+ )
+ (unCommented a)
+ ]
+
+ if isUnion
+ then
+ checkUnion cursor (declaredSizeBits `div` 8) (s3 : returned) a
+ else
+ return (cursor + declaredSizeBits `div` 8, s3 : returned)
+ TypeSubStructure (Identity subBody) maybeIdent annot -> do
+ (newBody, size) <-
+ objTypeBodyToStage3
+ subBody
+ ( if isUnion then startOff else cursor
+ )
+ let s3 = TypeSubStructure (Identity newBody) maybeIdent annot
+
+ checkTypesSubStructure subBody maybeIdent annot
+ if isUnion
+ then
+ checkUnion cursor size (s3 : returned) a
+ else
+ return (cursor + size, s3 : returned)
+ ReservedDecl expr annot -> do
+ size' <- fromIntegral <$> exprToSize expr
+ when ((size' `mod` 8) /= 0) $
+ tell
+ [ Diagnostic
+ Error
+ "Can only reserve a multiple of 8 bits in this context."
+ (unCommented a)
+ ]
+ let size = size' `div` 8
+ let s3 = ReservedDecl (expressionToStage3 expr) annot
+ if isUnion
+ then
+ checkUnion cursor size (s3 : returned) a
+ else
+ return (cursor + size, s3 : returned)
AssertPosStatement expr a -> do
- declaredPos <- exprToSize expr
- when (cursor /= declaredPos) $ do
+ declaredPos <- fromIntegral <$> exprToSize expr
+
+ let expectedPos = if isUnion then startOff else cursor + startOff
+
+ when (expectedPos /= declaredPos) $ do
tell
[ Diagnostic
Error
( printf
"Position assertion failed. Asserted 0x%x, calculated 0x%x"
declaredPos
- cursor
+ expectedPos
)
(unCommented a)
]
return (cursor, returned)
)
- (0 :: Integer, [])
+ (0, [])
decls
- return $ ObjTypeBody (reverse returned) a
+ return (ObjTypeBody bodyType (reverse returned) a, cur)
where
+ checkTypesSubStructure
+ (ObjTypeBody bodyType 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 ()
fUnzip xs = (fst <$> xs, snd <$> xs)
pushApply :: Maybe (a, b) -> (Maybe a, Maybe b)
pushApply (Just (a, b)) = (Just a, Just b)
diff --git a/src/Language/Fiddle/GenericTree.hs b/src/Language/Fiddle/GenericTree.hs
index 668c290..00824ed 100644
--- a/src/Language/Fiddle/GenericTree.hs
+++ b/src/Language/Fiddle/GenericTree.hs
@@ -174,6 +174,8 @@ instance (GToGenericSyntaxTree r f a) => (GToGenericSyntaxTree (M1 i c r) f a) w
deriving instance (ToGenericSyntaxTree Identifier)
+deriving instance (ToGenericSyntaxTree BodyType)
+
deriving instance (Context stage) => (ToGenericSyntaxTree (FiddleUnit stage))
deriving instance (Context stage) => (ToGenericSyntaxTree (FiddleDecl stage))
@@ -206,6 +208,20 @@ 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"
diff --git a/src/Language/Fiddle/Parser.hs b/src/Language/Fiddle/Parser.hs
index 37ef34e..7eed0f2 100644
--- a/src/Language/Fiddle/Parser.hs
+++ b/src/Language/Fiddle/Parser.hs
@@ -7,8 +7,8 @@ module Language.Fiddle.Parser
)
where
-import Data.Kind (Type)
import Data.Functor.Identity
+import Data.Kind (Type)
import Data.Text (Text)
import qualified Data.Text
import Debug.Trace
@@ -28,6 +28,7 @@ type P = ParsecT S () Identity
type A = Commented SourceSpan
type Pa (a :: Stage -> (Type -> Type) -> Type -> Type) = P (a 'Stage1 F (Commented SourceSpan))
+
type PaS (a :: (Type -> Type) -> Type -> Type) = P (a F (Commented SourceSpan))
comment :: P Comment
@@ -68,9 +69,15 @@ fiddleDecl = do
<*> defer body packageBody
KWLocation -> LocationDecl <$> ident <*> (tok TokEq >> expression)
KWBits -> BitsDecl <$> ident <*> (tok TokColon >> bitType)
- KWObjtype ->
- ObjTypeDecl <$> ident <*> (tok TokColon >> defer body objTypeBody)
- KWObject ->
+ KWType ->
+ ObjTypeDecl
+ <$> ident
+ <*> ( do
+ tok TokColon
+ bt <- bodyType
+ defer body (objTypeBody bt)
+ )
+ KWInstance ->
ObjectDecl
<$> ident
<*> (tok KWAt *> expression)
@@ -114,15 +121,18 @@ objType = do
baseObj :: P (A -> ObjType Stage1 F A)
baseObj =
(ReferencedObjType <$> ident)
- <|> (AnonymousObjType <$> defer body objTypeBody)
+ <|> ( do
+ t <- bodyType
+ AnonymousObjType <$> defer body (objTypeBody t)
+ )
exprInParen :: Pa Expression
exprInParen = tok TokLParen *> expression <* tok TokRParen
-objTypeBody :: Pa ObjTypeBody
-objTypeBody =
+objTypeBody :: BodyType F (Commented SourceSpan) -> Pa ObjTypeBody
+objTypeBody bt =
withMeta $
- ObjTypeBody <$> many (objTypeDecl <* tok TokSemi)
+ ObjTypeBody bt <$> many (objTypeDecl <* tok TokSemi)
objTypeDecl :: Pa ObjTypeDecl
objTypeDecl =
@@ -132,6 +142,14 @@ objTypeDecl =
AssertPosStatement <$> exprInParen
)
<|> ( do
+ tok KWReserved
+ ReservedDecl <$> exprInParen
+ )
+ <|> ( do
+ bt <- bodyType
+ TypeSubStructure <$> defer body (objTypeBody bt) <*> optionMaybe ident
+ )
+ <|> ( do
mod <- optionMaybe modifier
tok KWReg
RegisterDecl mod
@@ -150,8 +168,19 @@ modifier =
tok KWWo >> return Wo
]
+bitBodyType :: PaS BodyType
+bitBodyType =
+ withMeta $
+ (tok KWStruct >> return Struct)
+ <|> (tok KWUnion >> return Union)
+
+bodyType :: PaS BodyType
+bodyType =
+ withMeta $
+ (tok KWStruct >> return Struct) <|> (tok KWUnion >> return Union)
+
registerBody :: Pa RegisterBody
-registerBody = withMeta $ RegisterBody <$> defer body deferredRegisterBody
+registerBody = withMeta $ RegisterBody <$> bitBodyType <*> defer body deferredRegisterBody
deferredRegisterBody :: Pa DeferredRegisterBody
deferredRegisterBody =
@@ -164,7 +193,9 @@ registerBitsDecl =
( do
tok KWReserved >> ReservedBits <$> exprInParen
)
- <|> ( DefinedBits <$> optionMaybe modifier
+ <|> (BitsSubStructure <$> registerBody <*> optionMaybe ident)
+ <|> ( DefinedBits
+ <$> optionMaybe modifier
<*> ident
<*> (tok TokColon >> registerBitsTypeRef)
)
diff --git a/src/Language/Fiddle/Tokenizer.hs b/src/Language/Fiddle/Tokenizer.hs
index 4e06b92..08f5649 100644
--- a/src/Language/Fiddle/Tokenizer.hs
+++ b/src/Language/Fiddle/Tokenizer.hs
@@ -12,29 +12,31 @@ import qualified Text.Parsec
data T
= KWAssertPos
- | TokIdent !Text
| KWAt
| KWBits
| KWEnum
- | TokComment !Text
- | TokDocComment !Text
+ | KWInstance
| KWLocation
- | KWObject
- | KWObjtype
| KWOption
| KWPackage
| KWReg
| KWReserved
| KWRo
- | KWWo
| KWRw
- | TokLitNum !Text
+ | KWStruct
+ | KWType
+ | KWUnion
+ | KWWo
| TokColon
| TokComma
+ | TokComment !Text
+ | TokDocComment !Text
| TokEq
+ | TokIdent !Text
| TokLBrace
| TokLBracket
| TokLParen
+ | TokLitNum !Text
| TokRBrace
| TokRBracket
| TokRParen
@@ -60,8 +62,8 @@ parseToken = spaces *> tok parseToken' <* spaces
"bits" -> KWBits
"enum" -> KWEnum
"location" -> KWLocation
- "object" -> KWObject
- "objtype" -> KWObjtype
+ "instance" -> KWInstance
+ "type" -> KWType
"option" -> KWOption
"package" -> KWPackage
"reg" -> KWReg
@@ -69,6 +71,8 @@ parseToken = spaces *> tok parseToken' <* spaces
"wo" -> KWWo
"rw" -> KWRw
"reserved" -> KWReserved
+ "union" -> KWUnion
+ "struct" -> KWStruct
"assert_pos" -> KWAssertPos
(Data.Text.head -> h) | isDigit h -> TokLitNum str
ident -> TokIdent ident
diff --git a/vim/syntax/fiddle.vim b/vim/syntax/fiddle.vim
index 22341a5..7d36e93 100644
--- a/vim/syntax/fiddle.vim
+++ b/vim/syntax/fiddle.vim
@@ -1,9 +1,10 @@
syn keyword FiddlePackage option package nextgroup=FiddleIdent skipwhite
-syn keyword FiddleDecl reg object at location reserved nextgroup=FiddleIdent skipwhite
-syn keyword FiddleTypeDecl objtype regtype bits nextgroup=FiddleIdent skipwhite
+syn keyword FiddleDecl reg instance at location reserved nextgroup=FiddleIdent skipwhite
+syn keyword FiddleTypeDecl type regtype bits nextgroup=FiddleIdent skipwhite
syn keyword FiddleEnum enum
syn keyword FiddleBuiltin assert_pos
syn keyword FiddleModifier wo ro rw
+syn keyword FiddleStorageClass struct union bitstruct bitunion
syn match FiddleColon +:+ skipwhite nextgroup=FiddleContainedType
syn match FiddleContainedType +[a-zA-Z0-9_]\++ contained
@@ -13,12 +14,13 @@ syn match FiddleIdent +[A-Za-z0-9_]\++ contained
syn match FiddleComment +\/\/.*$+
syn region FiddleDocComment start=+/\*\*+ end=+*/+
-syn match FiddleNumber +[0-9_]\+\([xb]\)\@!\|0x[0-9A-Fa-f][0-9A-Fa-f_]*\|0b[01]\++
+syn match FiddleNumber +\<[0-9_]\+\([xb]\)\@!\|0x[0-9A-Fa-f][0-9A-Fa-f_]*\|0b[01]\+\>+
hi! link FiddleContainedType Type
hi! link FiddleModifier StorageClass
hi! link FiddleBuiltin Function
hi! link FiddleEnum StorageClass
+hi! link FiddleStorageClass FiddleEnum
hi! link FiddleDecl Type
hi! link FiddleNumber Number
hi! link FiddleDocComment Comment