summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package.yaml1
-rw-r--r--src/Language/Fiddle/Ast.hs43
-rw-r--r--src/Language/Fiddle/Compiler.hs3
-rw-r--r--src/Language/Fiddle/Compiler/Stage0.hs2
-rw-r--r--src/Language/Fiddle/Compiler/Stage1.hs49
-rw-r--r--src/Language/Fiddle/Compiler/Stage2.hs286
-rw-r--r--src/Language/Fiddle/GenericTree.hs8
-rw-r--r--src/Language/Fiddle/Parser.hs5
-rw-r--r--src/Main.hs21
9 files changed, 350 insertions, 68 deletions
diff --git a/package.yaml b/package.yaml
index 2f78def..f2394a7 100644
--- a/package.yaml
+++ b/package.yaml
@@ -34,3 +34,4 @@ dependencies:
- bytestring
- data-default
- transformers
+ - containers
diff --git a/src/Language/Fiddle/Ast.hs b/src/Language/Fiddle/Ast.hs
index 277ab24..d440a44 100644
--- a/src/Language/Fiddle/Ast.hs
+++ b/src/Language/Fiddle/Ast.hs
@@ -5,6 +5,7 @@
{-# LANGUAGE IncoherentInstances #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE ConstraintKinds #-}
module Language.Fiddle.Ast where
@@ -33,14 +34,14 @@ data FiddleUnit (stage :: Stage) (f :: Type -> Type) a where
deriving (Generic, Annotated, Alter, Typeable)
-- Just an identifier.
-data Identifier stage f a = Identifier !Text a
+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 stage f a -> a -> Expression stage f a
+ Var :: Identifier f a -> a -> Expression stage f a
-- Top-level declarations.
data FiddleDecl (stage :: Stage) (f :: Type -> Type) a where
@@ -49,37 +50,37 @@ data FiddleDecl (stage :: Stage) (f :: Type -> Type) a where
- option <ident> <ident>;
-}
OptionDecl ::
- Identifier stage f a ->
- Identifier stage f a ->
+ Identifier f a ->
+ Identifier f a ->
a ->
FiddleDecl stage f a
{- Package Statement. Package Name, Package body -}
PackageDecl ::
- Identifier stage f a ->
+ Identifier f a ->
f (PackageBody stage f a) ->
a ->
FiddleDecl stage f a
{- location <identifier> = <expr>. -}
LocationDecl ::
- Identifier stage f a ->
+ Identifier f a ->
Expression stage f a ->
a ->
FiddleDecl stage f a
{- bits <identifier> : <type> -}
BitsDecl ::
- Identifier stage f a ->
+ Identifier f a ->
BitType stage f a ->
a ->
FiddleDecl stage f a
{- objtype <identifier> : <type> -}
ObjTypeDecl ::
- Identifier stage f a ->
+ Identifier f a ->
f (ObjTypeBody stage f a) ->
a ->
FiddleDecl stage f a
{- object <ident> at <expr> : <type> -}
ObjectDecl ::
- Identifier stage f a ->
+ Identifier f a ->
Expression stage f a ->
ObjType stage f a ->
a ->
@@ -98,28 +99,30 @@ data ObjType stage f a where
-- <type>[<expr>]
ArrayObjType :: ObjType stage f a -> Expression stage f a -> a -> ObjType stage f a
-- <identifier>
- ReferencedObjType :: Identifier stage f a -> a -> ObjType stage f a
+ ReferencedObjType :: Identifier f a -> a -> ObjType stage f a
deriving (Typeable)
+type StageLessThan stage (n :: Natural) = (CmpNat (StageNumber stage) n ~ LT)
+
data ObjTypeDecl stage f a where
{- assert_pos(<expr>) -}
AssertPosStatement ::
- (CmpNat (StageNumber stage) 3 ~ LT) =>
+ (StageLessThan stage 3) =>
Expression stage f a ->
a ->
ObjTypeDecl stage f a
{- reg <ident>(<expr>) : <regtype> -}
RegisterDecl ::
- Maybe (Modifier stage f a) ->
- Maybe (Identifier stage f a) ->
+ Maybe (Modifier f a) ->
+ Maybe (Identifier f a) ->
Expression stage f a ->
Maybe (RegisterBody stage f a) ->
a ->
ObjTypeDecl stage f a
deriving (Typeable)
-data Modifier stage f a where
- ModifierKeyword :: ModifierKeyword -> a -> Modifier stage f a
+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)
@@ -140,8 +143,8 @@ data RegisterBitsDecl stage f a where
ReservedBits :: Expression stage f a -> a -> RegisterBitsDecl stage f a
-- <modifer> <ident> : <type>
DefinedBits ::
- Maybe (Modifier stage f a) ->
- Identifier stage f a ->
+ Maybe (Modifier f a) ->
+ Identifier f a ->
RegisterBitsTypeRef stage f a ->
a ->
RegisterBitsDecl stage f a
@@ -155,7 +158,7 @@ data RegisterBitsTypeRef stage f a where
a ->
RegisterBitsTypeRef stage f a
{- Reference to a type. -}
- RegisterBitsReference :: Identifier stage f a -> a -> RegisterBitsTypeRef stage f a
+ RegisterBitsReference :: Identifier f a -> a -> RegisterBitsTypeRef stage f a
{- enum(<expr>) { <body> }
Anonymous types are only allowed in stage1.
Stage2 should de-anonymize these type. -}
@@ -258,7 +261,7 @@ data EnumBody (stage :: Stage) (f :: Type -> Type) a where
data EnumConstantDecl stage f a where
-- <ident> = <expr>
- EnumConstantDecl :: Identifier stage 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
deriving (Generic, Annotated, Alter, Typeable)
@@ -271,7 +274,7 @@ data PackageBody (stage :: Stage) (f :: Type -> Type) a where
-- instance Alter (Modifier stage) where
-- alter _ fn (ModifierKeyword m a) = ModifierKeyword m (fn a)
--
--- instance Alter (Identifier stage) where
+-- instance Alter (Identifier) where
-- alter _ fn (Identifier i a) = Identifier i $ fn a
--
-- instance Alter (Expression stage) where
diff --git a/src/Language/Fiddle/Compiler.hs b/src/Language/Fiddle/Compiler.hs
index b523a78..768c569 100644
--- a/src/Language/Fiddle/Compiler.hs
+++ b/src/Language/Fiddle/Compiler.hs
@@ -9,6 +9,7 @@ import Data.Default
import Language.Fiddle.Ast
import Language.Fiddle.Types
import Text.Parsec (SourcePos, sourceColumn, sourceLine, sourceName)
+import System.IO (hPutStrLn, stderr)
data Level = Error | Warning | Info
@@ -96,7 +97,7 @@ diagnosticToString (DiagnosticFormat f) = f
printDiagnostic :: Diagnostic -> IO ()
printDiagnostic d =
- putStrLn (diagnosticToString coloredFormat d)
+ hPutStrLn stderr (diagnosticToString coloredFormat d)
fromMayberOrFail :: SourceSpan -> String -> Maybe a -> Compile s a
fromMayberOrFail sourceSpan err Nothing = do
diff --git a/src/Language/Fiddle/Compiler/Stage0.hs b/src/Language/Fiddle/Compiler/Stage0.hs
index 77c396e..fbc554b 100644
--- a/src/Language/Fiddle/Compiler/Stage0.hs
+++ b/src/Language/Fiddle/Compiler/Stage0.hs
@@ -55,7 +55,7 @@ parseErrorToDiagnostic pe =
"unknown"
"expecting"
"unexpected"
- "end of body or input (maybe a missing semicolon?)"
+ "end of body or input (maybe a missing semicolon or comma?)"
(errorMessages pe)
)
(SourceSpan (errorPos pe) (errorPos pe))
diff --git a/src/Language/Fiddle/Compiler/Stage1.hs b/src/Language/Fiddle/Compiler/Stage1.hs
index 7a048fa..3a97757 100644
--- a/src/Language/Fiddle/Compiler/Stage1.hs
+++ b/src/Language/Fiddle/Compiler/Stage1.hs
@@ -41,18 +41,9 @@ data Stage2CompilerState a
-- Anonymous enum bodies that need to be re-linked
![(Linkage, AnonymousBitsType Stage2 I a)]
-class EasyStage2 t where
- toS2 :: t s1 I a -> t s2 I a
-
-instance EasyStage2 Identifier where
- toS2 (Identifier t a) = Identifier t a
-
-instance EasyStage2 Modifier where
- toS2 (ModifierKeyword keyword annot) = ModifierKeyword keyword annot
-
type M a = Compile (Stage2CompilerState a)
-internObjType :: Path -> ObjTypeBody Stage2 I a -> M a (Identifier Stage2 I a)
+internObjType :: Path -> ObjTypeBody Stage2 I a -> M a (Identifier I a)
internObjType path body =
let str = Text.pack $ joinPath path
in do
@@ -60,7 +51,7 @@ internObjType path body =
Stage2CompilerState ((Linkage str, body) : objTypeBodies) a
return (Identifier str (annot body))
-internAnonymousBitsType :: Path -> AnonymousBitsType Stage2 I a -> M a (Identifier Stage2 I a)
+internAnonymousBitsType :: Path -> AnonymousBitsType Stage2 I a -> M a (Identifier I a)
internAnonymousBitsType path anonymousBitsType =
let str = Text.pack $ joinPath path
in do
@@ -68,12 +59,6 @@ internAnonymousBitsType path anonymousBitsType =
Stage2CompilerState a ((Linkage str, anonymousBitsType) : anonymousBitsTypes)
return (Identifier str (annot anonymousBitsType))
-traceState :: M a ()
-traceState = do
- (Stage2CompilerState anonymousObjTypes anonymousBitsTypes) <- get
- traceM $ printf "objtypes': %s\n" (show $ map fst anonymousObjTypes)
- traceM $ printf "bittypes': %s\n" (show $ map fst anonymousBitsTypes)
-
-- The second stage is a simplified version of the AST without anonymous
-- declarations.
toStage2 :: FiddleUnit Stage1 I Annot -> Compile () (FiddleUnit Stage2 I Annot)
@@ -106,21 +91,21 @@ reconfigureFiddleDecls p decls = do
resolveAnonymousBitsType (Linkage linkage, AnonymousEnumBody expr body a) =
BitsDecl (Identifier linkage a) (EnumBitType expr body a) a
-pushId :: Identifier stage f a -> Path -> Path
+pushId :: Identifier f a -> Path -> Path
pushId (Identifier str _) (Path lst) =
Path (PathExpression (Text.unpack str) : lst)
fiddleDeclToStage2 :: Path -> FiddleDecl Stage1 I Annot -> M Annot (FiddleDecl Stage2 I Annot)
fiddleDeclToStage2 path decl = do
case decl of
- (OptionDecl i1 i2 a) -> return $ OptionDecl (toS2 i1) (toS2 i2) a
+ (OptionDecl i1 i2 a) -> return $ OptionDecl i1 i2 a
(PackageDecl i (Identity body) a) -> do
- (PackageDecl (toS2 i) . Identity <$> packageBodyToStage2 (pushId i path) body) <*> pure a
- (LocationDecl i expr a) -> LocationDecl (toS2 i) <$> toStage2Expr expr <*> pure a
- (BitsDecl i typ a) -> BitsDecl (toS2 i) <$> bitsTypeToStage2 (pushId i path) typ <*> pure a
- (ObjTypeDecl i body a) -> ObjTypeDecl (toS2 i) <$> mapM (objTypeBodyToStage2 (pushId i path)) body <*> pure a
+ (PackageDecl i . Identity <$> packageBodyToStage2 (pushId i path) body) <*> pure a
+ (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
(ObjectDecl i expr typ a) ->
- ObjectDecl (toS2 i) <$> toStage2Expr expr <*> objectTypeToStage2 (pushId i path) typ <*> pure a
+ ObjectDecl i <$> toStage2Expr expr <*> objectTypeToStage2 (pushId i path) typ <*> pure a
bitsTypeToStage2 :: Path -> BitType Stage1 I Annot -> M Annot (BitType Stage2 I Annot)
bitsTypeToStage2 path = \case
@@ -134,7 +119,7 @@ enumBodyToStage2 path = \case
enumConstantToStage2 :: Path -> EnumConstantDecl Stage1 I Annot -> M Annot (EnumConstantDecl Stage2 I Annot)
enumConstantToStage2 path = \case
- EnumConstantDecl i e a -> EnumConstantDecl (toS2 i) <$> toStage2Expr e <*> pure a
+ EnumConstantDecl i e a -> EnumConstantDecl i <$> toStage2Expr e <*> pure a
EnumConstantReserved e a -> EnumConstantReserved <$> toStage2Expr e <*> pure a
objTypeBodyToStage2 :: Path -> ObjTypeBody Stage1 I Annot -> M Annot (ObjTypeBody Stage2 I Annot)
@@ -146,8 +131,8 @@ objTypeDeclToStage2 path = \case
(RegisterDecl maybeModifier maybeIdentifier expression maybeBody annot) ->
let path' = maybe path (`pushId` path) maybeIdentifier
in RegisterDecl
- (fmap toS2 maybeModifier)
- (fmap toS2 maybeIdentifier)
+ maybeModifier
+ maybeIdentifier
<$> toStage2Expr expression
<*> mapM (registerBodyToStage2 path') maybeBody
<*> pure annot
@@ -167,8 +152,8 @@ registerBitsDeclToStage2 path = \case
DefinedBits maybeModifier identifier registerBitsTyperef annot ->
let path' = pushId identifier path
in ( DefinedBits
- (fmap toS2 maybeModifier)
- (toS2 identifier)
+ maybeModifier
+ identifier
<$> registerBitsTypeRefToStage2 path' registerBitsTyperef
<*> pure annot
)
@@ -180,7 +165,7 @@ registerBitsTypeRefToStage2 path = \case
<$> registerBitsTypeRefToStage2 path typeref
<*> toStage2Expr expr
<*> pure annot
- RegisterBitsReference ident annot -> return (RegisterBitsReference (toS2 ident) annot)
+ RegisterBitsReference ident annot -> return (RegisterBitsReference ident annot)
RegisterBitsJustBits expr annot -> RegisterBitsJustBits <$> toStage2Expr expr <*> pure annot
RegisterBitsAnonymousType anonType annot -> do
ident <- internAnonymousBitsType path =<< anonymousBitsTypeToStage2 path anonType
@@ -200,7 +185,7 @@ objectTypeToStage2 path = \case
body' <- objTypeBodyToStage2 path body
identifier <- internObjType path body'
return (ReferencedObjType identifier annot)
- (ReferencedObjType ident annot) -> return $ ReferencedObjType (toS2 ident) annot
+ (ReferencedObjType ident annot) -> return $ ReferencedObjType ident annot
(ArrayObjType objType expr a) ->
ArrayObjType <$> objectTypeToStage2 path objType <*> toStage2Expr expr <*> pure a
@@ -210,7 +195,7 @@ packageBodyToStage2 p (PackageBody decls a) =
toStage2Expr :: Expression Stage1 I Annot -> M Annot (Expression Stage2 I Annot)
toStage2Expr = \case
- (Var i a) -> return $ Var (toS2 i) a
+ (Var i a) -> return $ Var i a
(LitNum t a) -> LitNum <$> parseNum (unCommented a) t <*> pure a
parseNum :: SourceSpan -> Text -> M a Integer
diff --git a/src/Language/Fiddle/Compiler/Stage2.hs b/src/Language/Fiddle/Compiler/Stage2.hs
new file mode 100644
index 0000000..baa61e3
--- /dev/null
+++ b/src/Language/Fiddle/Compiler/Stage2.hs
@@ -0,0 +1,286 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE IncoherentInstances #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+-- 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
+
+import Control.Monad (forM_, unless, when)
+import Control.Monad.RWS (MonadWriter (tell), gets, modify')
+import Data.Foldable (foldlM)
+import Data.Functor.Identity
+import qualified Data.IntMap as IntMap
+import Data.Kind (Type)
+import Data.List (intercalate)
+import Data.Map (Map)
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+import qualified Data.Text as Text
+import Data.Word
+import Language.Fiddle.Ast
+import Language.Fiddle.Compiler
+import Language.Fiddle.Types (Commented (unCommented), SourceSpan)
+import Text.Printf (printf)
+import Prelude hiding (unzip)
+
+type I = Identity
+
+type Annot = Commented SourceSpan
+
+type SizeBits = Word32
+
+type SizeBytes = Word32
+
+data Stage3State = Stage3State
+ { typeSizes :: Map String SizeBits,
+ objectSizes :: Map String SizeBytes,
+ cursorBytes :: Word32,
+ cursorBits :: Word32
+ }
+
+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 :: Identifier I Annot -> Compile Stage3State SizeBits
+lookupTypeSize (Identifier s a) = do
+ mSize <- gets $ Map.lookup (Text.unpack s) . typeSizes
+ case mSize of
+ Just sz -> return sz
+ Nothing -> do
+ tell
+ [ Diagnostic
+ Error
+ (printf "%s is not declared" s)
+ (unCommented a)
+ ]
+ 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 0 0
+
+toStage3 :: FiddleUnit Stage2 I Annot -> Compile () (FiddleUnit Stage3 I Annot)
+toStage3 (FiddleUnit decls a) =
+ snd
+ <$> subCompile
+ emptyState
+ ( FiddleUnit <$> mapM fiddleDeclToStage3 decls <*> pure a
+ )
+
+exprToSize ::
+ (NumberType stage ~ Integer) =>
+ Expression stage I Annot ->
+ Compile s Integer
+exprToSize (LitNum num _) = return num
+exprToSize e = do
+ tell [Diagnostic Error "Variables not allowed" (unCommented $ annot e)]
+ compilationFailure
+
+getTypeSize :: BitType Stage2 I Annot -> Compile s SizeBits
+getTypeSize (RawBits expr _) = fromIntegral <$> exprToSize expr
+getTypeSize (EnumBitType expr (Identity (EnumBody constants _)) ann) = do
+ declaredSize <- fromIntegral <$> exprToSize expr
+
+ -- If the declared size is less than or equal to 4, we'll enforce that the
+ -- enum is packed. This is to make sure the user has covered all bases.
+ when (declaredSize <= 4) $ do
+ imap <-
+ foldlM
+ ( \imap enumConst -> do
+ number <- case enumConst of
+ EnumConstantDecl _ expr _ -> exprToSize expr
+ EnumConstantReserved expr _ -> exprToSize expr
+
+ when (number >= 2 ^ declaredSize) $
+ tell
+ [ Diagnostic
+ Error
+ (printf "Enum constant too large. Max allowed %d\n" ((2 :: Int) ^ declaredSize))
+ (unCommented (annot enumConst))
+ ]
+
+ return $ IntMap.insert (fromIntegral number) True imap
+ )
+ IntMap.empty
+ constants
+ let missing = filter (not . (`IntMap.member` imap)) [0 .. 2 ^ declaredSize - 1]
+ unless (null missing) $
+ tell
+ [ Diagnostic
+ Warning
+ ( printf
+ "Missing enum constants %s. Please fully pack a small enum.\
+ \ Use 'reserved' if needed."
+ (intercalate ", " (map show missing))
+ )
+ (unCommented ann)
+ ]
+
+ return declaredSize
+
+fiddleDeclToStage3 :: FiddleDecl Stage2 I Annot -> Compile Stage3State (FiddleDecl Stage3 I Annot)
+fiddleDeclToStage3 = \case
+ OptionDecl i1 i2 a -> return $ OptionDecl i1 i2 a
+ PackageDecl id body a -> PackageDecl id <$> mapM packageBodyToStage3 body <*> pure a
+ LocationDecl id expr a -> return $ LocationDecl id (expressionToStage3 expr) a
+ BitsDecl id typ a -> do
+ typeSize <- getTypeSize typ
+ addTypeSize id typeSize
+ BitsDecl id <$> bitTypeToStage3 typ <*> pure a
+ ObjTypeDecl ident body a ->
+ ObjTypeDecl ident <$> mapM objTypeBodyToStage3 body <*> pure a
+ ObjectDecl ident expr typ a ->
+ ObjectDecl ident (expressionToStage3 expr) <$> objTypeToStage3 typ <*> pure a
+
+objTypeToStage3 :: ObjType Stage2 I Annot -> Compile Stage3State (ObjType Stage3 I Annot)
+objTypeToStage3 = \case
+ ArrayObjType objtype expr a ->
+ ArrayObjType
+ <$> objTypeToStage3 objtype
+ <*> pure (expressionToStage3 expr)
+ <*> pure a
+ ReferencedObjType ident a -> return $ ReferencedObjType ident a
+
+registerBodyToStage3 ::
+ RegisterBody Stage2 I Annot ->
+ Compile Stage3State (RegisterBody Stage3 I Annot, Word32)
+registerBodyToStage3 (RegisterBody (Identity deferredRegisterBody) a') =
+ case deferredRegisterBody of
+ DeferredRegisterBody decls a -> do
+ (cur, returned) <-
+ foldlM
+ ( \(cursor, returned) decl ->
+ case decl of
+ ReservedBits expr a -> do
+ size <- exprToSize expr
+ let s3 = ReservedBits (expressionToStage3 expr) a
+ return (cursor + fromIntegral size, s3 : returned)
+ DefinedBits modifier identifier typeref a -> do
+ (s3TypeRef, size) <- registerBitsTypeRefToStage3 typeref
+ return (cursor + size, DefinedBits modifier identifier s3TypeRef a : returned)
+ )
+ (0, [])
+ decls
+
+ return (RegisterBody (Identity (DeferredRegisterBody (reverse returned) a)) a', cur)
+
+registerBitsTypeRefToStage3 ::
+ RegisterBitsTypeRef Stage2 I Annot ->
+ Compile Stage3State (RegisterBitsTypeRef Stage3 I Annot, Word32)
+registerBitsTypeRefToStage3 = \case
+ RegisterBitsArray ref expr a -> do
+ (ref', size) <- registerBitsTypeRefToStage3 ref
+ multiplier <- exprToSize expr
+ return
+ ( RegisterBitsArray ref' (expressionToStage3 expr) a,
+ size * fromIntegral multiplier
+ )
+ RegisterBitsReference ident a ->
+ (RegisterBitsReference ident a,) <$> lookupTypeSize ident
+ RegisterBitsJustBits expr a ->
+ (RegisterBitsJustBits (expressionToStage3 expr) a,)
+ . fromIntegral
+ <$> exprToSize expr
+
+objTypeBodyToStage3 ::
+ ObjTypeBody Stage2 I Annot -> Compile Stage3State (ObjTypeBody Stage3 I Annot)
+objTypeBodyToStage3 (ObjTypeBody decls a) = do
+ (cur, returned) <-
+ foldlM
+ ( \(cursor, returned) decl ->
+ case decl of
+ RegisterDecl mMod mIdent expr mBody a -> do
+ (s3RegisterBody, mCalculatedSize) <-
+ fUnzip <$> mapM registerBodyToStage3 mBody
+
+ let s3 =
+ RegisterDecl
+ mMod
+ mIdent
+ (expressionToStage3 expr)
+ s3RegisterBody
+ a
+
+ declaredSizeBits <- exprToSize expr
+
+ when ((declaredSizeBits `mod` 8) /= 0) $
+ tell
+ [ Diagnostic
+ Error
+ "Register size is not a multiple of 8. Please pad register size to align with 8. "
+ (unCommented a)
+ ]
+
+ 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)
+ AssertPosStatement expr a -> do
+ declaredPos <- exprToSize expr
+ when (cursor /= declaredPos) $ do
+ tell
+ [ Diagnostic
+ Error
+ ( printf
+ "Position assertion failed. Asserted 0x%x, calculated 0x%x"
+ declaredPos
+ cursor
+ )
+ (unCommented a)
+ ]
+ return (cursor, returned)
+ )
+ (0 :: Integer, [])
+ decls
+
+ return $ ObjTypeBody (reverse returned) a
+ where
+ fUnzip xs = (fst <$> xs, snd <$> xs)
+ pushApply :: Maybe (a, b) -> (Maybe a, Maybe b)
+ 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 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 fiddleDeclToStage3 decls <*> pure a
diff --git a/src/Language/Fiddle/GenericTree.hs b/src/Language/Fiddle/GenericTree.hs
index b17954f..668c290 100644
--- a/src/Language/Fiddle/GenericTree.hs
+++ b/src/Language/Fiddle/GenericTree.hs
@@ -66,8 +66,8 @@ instance ToJSON SourcePos where
instance (Foldable f, ToJSON a) => ToJSON (GenericSyntaxTree f a) where
toJSON = \case
- (SyntaxTreeObject typ membs a t) ->
- object ["_type" .= show (typeOf t), "_con" .= typ, "_members" .= membs, "_annot" .= a]
+ (SyntaxTreeObject typ membs a _) ->
+ object ["_con" .= typ, "_members" .= membs, "_annot" .= a]
(SyntaxTreeList l) ->
Array $ Data.Vector.fromList $ map toJSON l
(SyntaxTreeDeferred fdef) ->
@@ -172,7 +172,7 @@ instance (GToGenericSyntaxTree r f a) => (GToGenericSyntaxTree (M1 i c r) f a) w
-- deriving instance (ToGenericSyntaxTree (Test stage))
-deriving instance (Context stage) => (ToGenericSyntaxTree (Identifier stage))
+deriving instance (ToGenericSyntaxTree Identifier)
deriving instance (Context stage) => (ToGenericSyntaxTree (FiddleUnit stage))
@@ -219,7 +219,7 @@ instance (Context stage) => (ToGenericSyntaxTree (ObjTypeDecl stage)) where
deriving instance (ToGenericSyntaxTreeValue ModifierKeyword)
-deriving instance (Context stage) => (ToGenericSyntaxTree (Modifier stage))
+deriving instance (ToGenericSyntaxTree Modifier)
deriving instance (Context stage) => (ToGenericSyntaxTree (DeferredRegisterBody stage))
diff --git a/src/Language/Fiddle/Parser.hs b/src/Language/Fiddle/Parser.hs
index dc479d1..37ef34e 100644
--- a/src/Language/Fiddle/Parser.hs
+++ b/src/Language/Fiddle/Parser.hs
@@ -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
comment =
@@ -139,7 +140,7 @@ objTypeDecl =
<*> optionMaybe (tok TokColon *> registerBody)
)
-modifier :: Pa Modifier
+modifier :: PaS Modifier
modifier =
withMeta $
ModifierKeyword
@@ -278,7 +279,7 @@ printNext = do
traceM $ "NextToken: " ++ show t
return ()
-ident :: Pa Identifier
+ident :: PaS Identifier
ident =
withMeta $
token $ \case
diff --git a/src/Main.hs b/src/Main.hs
index 9330df5..f92d6c6 100644
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -5,11 +5,12 @@ import Control.Monad.Writer
import Data.Aeson (encode)
import qualified Data.ByteString.Lazy.Char8 as BL
import qualified Data.Text.IO
-import GHC.IO.Exception (ExitCode (ExitFailure))
+import GHC.IO.Exception (ExitCode (ExitFailure, ExitSuccess))
import Language.Fiddle.Ast
import Language.Fiddle.Compiler (coloredFormat, compile_, printDiagnostic)
import Language.Fiddle.Compiler.Stage0
import Language.Fiddle.Compiler.Stage1
+import Language.Fiddle.Compiler.Stage2
import Language.Fiddle.GenericTree (ToGenericSyntaxTree (toGenericSyntaxTree))
import qualified Language.Fiddle.Parser
import qualified Language.Fiddle.Tokenizer
@@ -23,14 +24,18 @@ main = do
case argv of
[filePath] -> do
text <- Data.Text.IO.readFile filePath
- let (diags, ma) = compile_ $ toStage2 =<< toStage1 =<< toStage0 filePath text
+ let (diags, ma) = compile_ $ toStage3 =<< toStage2 =<< toStage1 =<< toStage0 filePath text
+ ec <-
+ case ma of
+ Just ast -> do
+ putStrLn $ BL.unpack $ encode $ toGenericSyntaxTree ast
+ return ExitSuccess
+ Nothing -> do
+ putStrLn "\x1b[1;31mCompilation Failed\x1b[0m"
+ return (ExitFailure 1)
+
forM_ diags printDiagnostic
- case ma of
- Just ast -> do
- putStrLn $ BL.unpack $ encode $ toGenericSyntaxTree ast
- Nothing -> do
- putStrLn "\x1b[1;31mCompilation Failed\x1b[0m"
- exitWith (ExitFailure 1)
+ exitWith ec
_ -> do
putStrLn "Wrong Args"
exitWith (ExitFailure 2)