summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-10-19 01:05:10 -0600
committerJosh Rahm <joshuarahm@gmail.com>2024-10-19 01:05:10 -0600
commite9ed9fe9aae2c0ac913cf1d175166e983e0a1b30 (patch)
tree77ef1aaccd3527c06edff1c3120147150829bf3f
parente753d874458dce4ad480caba97fde8b73d703821 (diff)
downloadfiddle-e9ed9fe9aae2c0ac913cf1d175166e983e0a1b30.tar.gz
fiddle-e9ed9fe9aae2c0ac913cf1d175166e983e0a1b30.tar.bz2
fiddle-e9ed9fe9aae2c0ac913cf1d175166e983e0a1b30.zip
Provide more data during qualification about how a path is qualified.
Now it includes information about the package a symobl is in. The object its in and the register its in. This allows better code generation in the backend that's somewhat more organized.
-rw-r--r--src/Language/Fiddle/Ast/Internal/SyntaxTree.hs8
-rw-r--r--src/Language/Fiddle/Ast/Internal/Util.hs2
-rw-r--r--src/Language/Fiddle/Compiler/Backend/C.hs104
-rw-r--r--src/Language/Fiddle/Compiler/Backend/Internal.hs18
-rw-r--r--src/Language/Fiddle/Compiler/ConsistencyCheck.hs3
-rw-r--r--src/Language/Fiddle/Compiler/Qualification.hs170
-rw-r--r--src/Language/Fiddle/GenericTree.hs2
-rw-r--r--src/Language/Fiddle/Internal/UnitInterface.hs60
-rw-r--r--src/Language/Fiddle/Parser.hs7
9 files changed, 276 insertions, 98 deletions
diff --git a/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs b/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs
index 613dae4..063913b 100644
--- a/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs
+++ b/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs
@@ -96,7 +96,7 @@ data QRegMetadata (checkStage :: Bool) where
-- emit getters and setters.
regIsUnnamed :: Bool,
-- | Full path to the register.
- regFullPath :: NonEmpty String
+ regFullPath :: QualifiedPath String
} ->
QRegMetadata checkStage
deriving (Generic, ToJSON)
@@ -108,7 +108,7 @@ deriving instance
data QBitsMetadata (checkStage :: Bool) where
QBitsMetadata ::
{ bitsSpan :: When checkStage (FieldSpan Bits),
- bitsFullPath :: NonEmpty String
+ bitsFullPath :: QualifiedPath String
} ->
QBitsMetadata checkStage
deriving (Generic, ToJSON)
@@ -619,7 +619,7 @@ data RegisterBitsDecl stage f a where
qBitsMetadata :: When (stage .>= Qualified) (QBitsMetadata (stage .>= Checked)),
-- | Bit declarations.
-- | Optional modifier for the bits.
- definedBitsModifier :: Maybe (Modifier f a),
+ definedBitsModifier :: Guaranteed (stage .>= Qualified) (Modifier f a),
-- | Identifier for the bits.
definedBitsIdent :: Identifier f a,
-- | Type reference for the bits.
@@ -676,7 +676,7 @@ data RegisterBitsTypeRef stage f a where
-- | A direct specification of bits as an expression.
RegisterBitsJustBits ::
{ -- | Expression for the bits.
- justBitsExpr :: Expression Bits stage f a,
+ justBitsExpr :: ConstExpression Bits stage f a,
-- | Annotation for the bits.
justBitsAnnot :: a
} ->
diff --git a/src/Language/Fiddle/Ast/Internal/Util.hs b/src/Language/Fiddle/Ast/Internal/Util.hs
index 87fca96..d2be0c3 100644
--- a/src/Language/Fiddle/Ast/Internal/Util.hs
+++ b/src/Language/Fiddle/Ast/Internal/Util.hs
@@ -52,7 +52,7 @@ identToString = Text.unpack . identifierName
directiveToMetadata ::
(Annotated (t s)) =>
Directed t s Identity (Commented SourceSpan) ->
- NonEmpty String ->
+ QualifiedPath String ->
Metadata
directiveToMetadata (Directed directives t a) qualifiedPath =
Metadata
diff --git a/src/Language/Fiddle/Compiler/Backend/C.hs b/src/Language/Fiddle/Compiler/Backend/C.hs
index df31c8c..f4132c6 100644
--- a/src/Language/Fiddle/Compiler/Backend/C.hs
+++ b/src/Language/Fiddle/Compiler/Backend/C.hs
@@ -26,6 +26,7 @@ import Data.Text (Text)
import qualified Data.Text as Text
import Language.Fiddle.Ast
import Language.Fiddle.Compiler.Backend
+import Language.Fiddle.Compiler.Backend.Internal
import Language.Fiddle.Compiler.Backend.Internal.FormattedWriter
import qualified Language.Fiddle.Compiler.Backend.Internal.FragTree as FragTree
import Language.Fiddle.Compiler.Backend.Internal.Writer
@@ -174,8 +175,8 @@ instance IsText String where
instance IsText Text where
toText = id
-qualifiedPathToIdentifier :: (Foldable f, IsText t) => f t -> Text
-qualifiedPathToIdentifier = Text.intercalate "_" . map toText . toList
+qualifiedPathToIdentifier :: QualifiedPath String -> Text
+qualifiedPathToIdentifier = Text.pack . qualifiedPathToString "__" "_"
pad :: M () -> M ()
pad f = text "\n" *> f <* text "\n"
@@ -219,9 +220,9 @@ writeRegGet
regFullPath = fullPath
}
) = do
- let fnName = "get_" <> qualifiedPathToIdentifier fullPath
+ let fnName = qualifiedPathToIdentifier fullPath <> "__get"
returnType = sizeToType size
- fieldName = NonEmpty.last fullPath
+ fieldName = basenamePart fullPath
case returnType of
Just rt -> do
@@ -257,16 +258,16 @@ writeRegSet
regFullPath = fullPath
}
) = do
- let fnName = "set_" <> qualifiedPathToIdentifier fullPath
+ let fnName = qualifiedPathToIdentifier fullPath <> "__set"
setType = sizeToType size
- fieldName = NonEmpty.last fullPath
+ fieldName = basenamePart fullPath
case setType of
Just rt -> do
textM $ do
tell $
Text.pack $
- printf "static inline void %s(%s* o, %s v) {\n" fnName structType rt
+ printf "static inline void %s(struct %s* o, %s v) {\n" fnName structType rt
tell $ Text.pack $ printf " o->%s = v;\n" fieldName
tell "}\n\n"
Nothing ->
@@ -275,7 +276,7 @@ writeRegSet
tell $
Text.pack $
printf
- "static inline void %s(%s* o, const uint8_t in[%d]) {\n"
+ "static inline void %s(struct %s* o, const uint8_t in[%d]) {\n"
fnName
structType
size
@@ -283,8 +284,8 @@ writeRegSet
tell $ Text.pack $ printf " o->%s[%d] = in[%d];\n" fieldName i i
tell "}\n\n"
-pattern DefinedBitsP :: String -> NonEmpty String -> N Bits -> RegisterBitsTypeRef Checked f a -> RegisterBitsDecl Checked f a
-pattern DefinedBitsP bitsName bitsFullPath offset typeRef <-
+pattern DefinedBitsP :: Modifier f a -> String -> QualifiedPath String -> N Bits -> RegisterBitsTypeRef Checked f a -> RegisterBitsDecl Checked f a
+pattern DefinedBitsP modifier bitsName bitsFullPath offset typeRef <-
( DefinedBits
{ qBitsMetadata =
Present
@@ -294,12 +295,68 @@ pattern DefinedBitsP bitsName bitsFullPath offset typeRef <-
FieldSpan
{ offset = offset
},
- bitsFullPath = (NonEmpty.last &&& id -> (bitsName, bitsFullPath))
+ bitsFullPath = (basenamePart &&& id -> (bitsName, bitsFullPath))
},
- definedBitsTypeRef = typeRef
+ definedBitsTypeRef = typeRef,
+ definedBitsModifier = (Guaranteed modifier)
}
)
+writeBitsGet ::
+ StructName ->
+ String ->
+ QualifiedPath String ->
+ N Bits ->
+ RegisterBitsTypeRef 'Checked I A ->
+ M ()
+writeBitsGet _ _ _ _ _ = return ()
+
+writeBitsSet ::
+ StructName ->
+ String ->
+ QualifiedPath String ->
+ N Bits ->
+ RegisterBitsTypeRef 'Checked I A ->
+ M ()
+writeBitsSet structName bitsNam fullPath offset typeRef = do
+ text "inline static void "
+ text (qualifiedPathToIdentifier fullPath)
+ text "__set(\n struct "
+ text structName
+ text " *o,\n "
+ typeRefToArgs typeRef
+ text ") {\n"
+ text "}\n\n"
+
+typeRefToArgs :: RegisterBitsTypeRef 'Checked I A -> M ()
+typeRefToArgs reg =
+ text
+ $ Text.intercalate ",\n "
+ $ zipWith
+ (\n t -> t <> " " <> n)
+ setterArgumentNames
+ $ typeRefToArgs' reg
+ where
+ typeRefToArgs'
+ ( RegisterBitsJustBits
+ { justBitsExpr = ConstExpression (LeftV v) _
+ }
+ ) = [typeForBits v]
+ typeRefToArgs'
+ ( RegisterBitsReference
+ { bitsRefQualificationMetadata = (Identity (Present md))
+ }
+ ) = [qualifiedPathToIdentifier $ metadataFullyQualifiedPath $ getMetadata md]
+ typeRefToArgs' (RegisterBitsArray tr (ConstExpression (LeftV _) _) _) =
+ typeRefToArgs' tr ++ ["int"]
+
+ typeForBits = \case
+ 64 -> "uint64_t"
+ 32 -> "uint32_t"
+ 16 -> "uint16_t"
+ 8 -> "uint8_t"
+ _ -> "unsigend"
+
-- | Decomposes a type ref into a type name (String) and a list of dimensions
-- (in the case of being an array)
-- decomposeBitsTypeRef :: RegisterBitsTypeRef Checked I A -> (String, [N Unitless])
@@ -310,14 +367,21 @@ writeRegisterBody structName regmeta = walk_ registerWalk
registerWalk :: forall t. (Walk t, Typeable t) => t I A -> M ()
registerWalk t = case () of
()
- | (Just (DefinedBitsP bitsName fullPath offset typeRef)) <- castTS t ->
- text $
- Text.pack $
- printf
- "// Emit bits %s (%s) at %d\n"
- bitsName
- (qualifiedPathToIdentifier fullPath)
- offset
+ | (Just (DefinedBitsP modifier bitsName fullPath offset typeRef)) <- castTS t -> do
+ sequence_ $
+ selectByModifier
+ modifier
+ ( writeBitsGet structName bitsName fullPath offset typeRef,
+ writeBitsSet structName bitsName fullPath offset typeRef
+ )
+
+ -- text $
+ -- Text.pack $
+ -- printf
+ -- "// Emit bits %s (%s) at %d\n"
+ -- bitsName
+ -- (qualifiedPathToIdentifier fullPath)
+ -- offset
_ -> return ()
castTS ::
diff --git a/src/Language/Fiddle/Compiler/Backend/Internal.hs b/src/Language/Fiddle/Compiler/Backend/Internal.hs
new file mode 100644
index 0000000..4e513f1
--- /dev/null
+++ b/src/Language/Fiddle/Compiler/Backend/Internal.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Language.Fiddle.Compiler.Backend.Internal where
+
+import qualified Data.Text
+
+-- | An infinite list of common setter argument names to use.
+setterArgumentNames :: [Data.Text.Text]
+setterArgumentNames =
+ ["value", "i", "j", "k"]
+ ++ map (("i" <>) . Data.Text.pack . show) [(0 :: Int) ..]
+
+-- | An infinite list of common getter argument names to use. A getter will have
+-- an argument for each index into an array for bit arrays.
+getterArgumentNames :: [Data.Text.Text]
+getterArgumentNames =
+ ["i", "j", "k"]
+ ++ map (("i" <>) . Data.Text.pack . show) [(0 :: Int) ..]
diff --git a/src/Language/Fiddle/Compiler/ConsistencyCheck.hs b/src/Language/Fiddle/Compiler/ConsistencyCheck.hs
index 6a3b5d9..a8d9758 100644
--- a/src/Language/Fiddle/Compiler/ConsistencyCheck.hs
+++ b/src/Language/Fiddle/Compiler/ConsistencyCheck.hs
@@ -266,8 +266,7 @@ bitsTypeSize
QMdP (ExportedBitsDecl {exportedBitsDeclSizeBits = sz})
} = return sz
bitsTypeSize (RegisterBitsReference {}) = error "should be exhaustive"
-bitsTypeSize (RegisterBitsJustBits expr _) =
- expressionToIntM expr
+bitsTypeSize (RegisterBitsJustBits expr _) = return $ trueValue expr
checkSizeMismatch :: (NamedUnit u) => A -> N u -> N u -> Compile s ()
checkSizeMismatch _ a b | a == b = return ()
diff --git a/src/Language/Fiddle/Compiler/Qualification.hs b/src/Language/Fiddle/Compiler/Qualification.hs
index 56f1122..1307c2a 100644
--- a/src/Language/Fiddle/Compiler/Qualification.hs
+++ b/src/Language/Fiddle/Compiler/Qualification.hs
@@ -37,6 +37,8 @@ data GlobalState = GlobalState
data LocalState = LocalState
{ currentScopePath :: ScopePath String,
+ -- | Current qualified path, used for building metadata.
+ currentQualifiedPath :: QualifiedPath (),
ephemeralScope :: Scope String (Metadata, ExportedDecl)
}
@@ -62,29 +64,62 @@ instance CompilationStage Expanded where
type StageFunctor Expanded = F
type StageAnnotation Expanded = A
+pushPackage :: NonEmpty String -> LocalState -> (QualifiedPath String, LocalState)
+pushPackage pk ls =
+ let q = currentQualifiedPath ls
+ in ( qualifyPackage pk,
+ ls
+ { currentScopePath = pushScope pk (currentScopePath ls),
+ currentQualifiedPath =
+ q
+ { packagePart = packagePart q ++ NonEmpty.toList pk
+ }
+ }
+ )
+ where
+ qualifyPackage :: NonEmpty String -> QualifiedPath String
+ qualifyPackage (NonEmpty.reverse -> (l :| (reverse -> h))) =
+ let q = currentQualifiedPath ls
+ in q {packagePart = packagePart q ++ h, basenamePart = l}
+
+pushObject :: String -> LocalState -> (QualifiedPath String, LocalState)
+pushObject objName ls =
+ let q = currentQualifiedPath ls
+ in ( fmap (const objName) q,
+ ls
+ { currentScopePath = pushScope (NonEmpty.singleton objName) (currentScopePath ls),
+ currentQualifiedPath =
+ q
+ { objectPart = Just objName
+ }
+ }
+ )
+
+pushRegister :: String -> LocalState -> (QualifiedPath String, LocalState)
+pushRegister regName ls =
+ let q = currentQualifiedPath ls
+ in ( fmap (const regName) q,
+ ls
+ { currentScopePath = pushScope (NonEmpty.singleton regName) (currentScopePath ls),
+ currentQualifiedPath =
+ q
+ { registerPart = registerPart q ++ [regName]
+ }
+ }
+ )
+
qualificationPhase :: CompilationPhase Expanded Qualified
qualificationPhase =
- pureCompilationPhase $ \t -> do
- raw <-
- fmap snd $
- subCompile (GlobalState mempty 0) $
- advanceStage
- (LocalState mempty mempty)
- (soakA t)
-
- squeezeDiagnostics raw
-
-pushIdent :: Identifier f a -> LocalState -> LocalState
-pushIdent i = pushIdents [i]
-
-pushIdents :: (Foldable t) => t (Identifier f a) -> LocalState -> LocalState
-pushIdents =
- ( \case
- [] -> id
- (i : is) ->
- modifyCurrentScopePath (pushScope $ fmap identToString (i :| is))
- )
- . toList
+ let initialQualifiedPath = QualifiedPath [] Nothing [] ()
+ in pureCompilationPhase $ \t -> do
+ raw <-
+ fmap snd $
+ subCompile (GlobalState mempty 0) $
+ advanceStage
+ (LocalState mempty initialQualifiedPath mempty)
+ (soakA t)
+
+ squeezeDiagnostics raw
instance
StageConvertible
@@ -98,7 +133,7 @@ instance AdvanceStage S (ConstExpression u) where
advanceStage ls (ConstExpression (RightV exp) a) =
case exp of
Var var _ -> do
- (_, ExportedLocationDecl _ v) <- resolveOrFail =<< resolveName var ls
+ (ExportedLocationDecl _ v) <- resolveOrFail =<< resolveName var ls
return $ ConstExpression (LeftV $ fromIntegral v) a
LitNum (RightV v) _ -> return $ ConstExpression (LeftV v) a
@@ -127,15 +162,13 @@ instance AdvanceStage S RegisterBitsDecl where
<*> pure name
<*> pure an
DefinedBits _ mod ident typ an -> do
- let qMeta =
+ let (path, _) = pushObject (identToString ident) localState
+ qMeta =
QBitsMetadata
{ bitsSpan = Vacant,
- bitsFullPath =
- qualifyPath
- (currentScopePath localState)
- (NonEmpty.singleton (identToString ident))
+ bitsFullPath = path
}
- DefinedBits (Present qMeta) mod ident
+ DefinedBits (Present qMeta) (guarantee (ModifierKeyword Rw an) mod) ident
<$> advanceStage localState typ
<*> pure an
@@ -145,38 +178,39 @@ instance AdvanceStage S ObjTypeDecl where
AssertPosStatement d <$> advanceStage localState e <*> pure a
RegisterDecl _ mod ident size bod ann -> do
ident' <- guaranteeM (uniqueIdentifier "reg" ann) ident
- let localState' = pushIdents ident localState
+
+ let (qualified, localState') =
+ pushRegister (identToString $ unwrap ident') localState
+ -- Avoid pushing the anonymized name onto the stack.
+ localState'' =
+ if isNothing (toMaybe ident) then localState else localState'
let qRegMeta =
QRegMetadata
{ regSpan = Vacant,
regIsPadding = False,
regIsUnnamed = isNothing (toMaybe ident),
- regFullPath =
- qualifyPath
- (currentScopePath localState)
- (NonEmpty.singleton (identToString (unwrap ident')))
+ regFullPath = qualified
}
RegisterDecl
(Present qRegMeta)
(guarantee (ModifierKeyword Rw ann) mod)
ident'
- <$> advanceStage localState' size
- <*> mapM (advanceStage localState') bod
+ <$> advanceStage localState'' size
+ <*> mapM (advanceStage localState'') bod
<*> pure ann
ReservedDecl _ expr ann -> do
ident <- uniqueIdentifier "reserved" ann
+ let (q, _) = pushRegister (identToString ident) localState
+
let qRegMeta =
QRegMetadata
{ regSpan = Vacant,
regIsPadding = True,
regIsUnnamed = True,
- regFullPath =
- qualifyPath
- (currentScopePath localState)
- (NonEmpty.singleton (identToString ident))
+ regFullPath = q
}
RegisterDecl
@@ -187,7 +221,11 @@ instance AdvanceStage S ObjTypeDecl where
<*> pure Nothing
<*> pure ann
TypeSubStructure bod name an -> do
- let localState' = pushIdents name localState
+ let localState' =
+ maybe
+ localState
+ (\n -> snd $ pushRegister (identToString n) localState)
+ name
TypeSubStructure
<$> mapM (advanceStage localState') bod
<*> pure name
@@ -207,7 +245,7 @@ instance AdvanceStage S RegisterBitsTypeRef where
<$> advanceStage localState a
<*> pure b
RegisterBitsReference _ name a -> do
- v <- fmap (Present . snd) <$> resolveName name localState
+ v <- fmap Present <$> resolveName name localState
return $ RegisterBitsReference v name a
instance AdvanceStage S ObjType where
@@ -218,7 +256,7 @@ instance AdvanceStage S ObjType where
<*> advanceStage localState b
<*> pure c
ReferencedObjType _ name a -> do
- v <- fmap (Present . snd) <$> resolveName name localState
+ v <- fmap Present <$> resolveName name localState
return $ ReferencedObjType v name a
deriving instance (AdvanceStage S t) => AdvanceStage S (Directed t)
@@ -246,13 +284,13 @@ modifyCurrentScopePath ::
modifyCurrentScopePath fn ls@LocalState {currentScopePath = cs} =
ls {currentScopePath = fn cs}
-resolveIdent :: (ExportableDecl d, Functor f) => Identifier f A -> LocalState -> M (F ([String], d))
+resolveIdent :: (ExportableDecl d, Functor f) => Identifier f A -> LocalState -> M (F d)
resolveIdent i = resolveSymbol (annot i) [identToString i]
-resolveName :: (ExportableDecl d, Functor f) => Name f A -> LocalState -> M (F ([String], d))
+resolveName :: (ExportableDecl d, Functor f) => Name f A -> LocalState -> M (F d)
resolveName n = resolveSymbol (annot n) (toList $ nameToList n)
-resolveSymbol :: (ExportableDecl d) => A -> [String] -> LocalState -> M (F ([String], d))
+resolveSymbol :: (ExportableDecl d) => A -> [String] -> LocalState -> M (F d)
resolveSymbol a (p : ps) (LocalState {ephemeralScope = ephemeralScope, currentScopePath = currentPath}) = do
GlobalState {unitInterface = UnitInterface {rootScope = rootScope}} <- get
@@ -265,7 +303,7 @@ resolveSymbol a (p : ps) (LocalState {ephemeralScope = ephemeralScope, currentSc
return $
case matches of
- [(p, (_, e))] -> Right (toList p, e)
+ [(_, (_, e))] -> Right e
[] ->
Left
[ Diagnostic
@@ -307,7 +345,7 @@ advanceFiddleDecls localState decls = fmap (reverse . fst) $ do
M ([Directed FiddleDecl Qualified F A], LocalState)
doReturn v = return (Directed directives v dann : declsRet, localState')
doReturnWith s v = return (Directed directives v dann : declsRet, s)
- qualify = qualifyPath (currentScopePath localState')
+
metadata = directiveToMetadata d
in case t of
UsingDecl {usingName = name} ->
@@ -320,8 +358,10 @@ advanceFiddleDecls localState decls = fmap (reverse . fst) $ do
<$> advanceStage localState'' st
<*> pure a
PackageDecl _ name body ann ->
- let qualifiedName = qualify (nameToList name)
- localState'' = modifyCurrentScopePath (pushScope (nameToList name)) localState'
+ let (qualifiedName, localState'') =
+ pushPackage
+ (nameToList name)
+ localState'
decl = ExportedPackageDecl (metadata qualifiedName)
in do
insertDecl decl
@@ -332,7 +372,10 @@ advanceFiddleDecls localState decls = fmap (reverse . fst) $ do
<$> mapM (advanceStage localState'') body
<*> pure ann
LocationDecl _ ident expr ann ->
- let qualifiedName = qualify (NonEmpty.singleton (identToString ident))
+ let qualifiedName =
+ fmap
+ (const $ identToString ident)
+ (currentQualifiedPath localState')
in do
expr' <- advanceStage localState' expr
let decl =
@@ -347,7 +390,10 @@ advanceFiddleDecls localState decls = fmap (reverse . fst) $ do
<$> advanceStage localState' expr
<*> pure ann
BitsDecl _ ident typ ann ->
- let qualifiedName = qualify (NonEmpty.singleton (identToString ident))
+ let qualifiedName =
+ fmap
+ (const $ identToString ident)
+ (currentQualifiedPath localState)
in do
sizeBits <- getBitTypeDeclaredSize typ
let decl =
@@ -362,11 +408,10 @@ advanceFiddleDecls localState decls = fmap (reverse . fst) $ do
<$> advanceStage localState' typ
<*> pure ann
ObjTypeDecl _ ident body ann ->
- let qualifiedName = qualify (NonEmpty.singleton (identToString ident))
- localState'' =
- modifyCurrentScopePath
- (pushScope (NonEmpty.singleton $ identToString ident))
- localState'
+ let (qualifiedName, localState'') =
+ pushObject
+ (identToString ident)
+ localState
in do
typeSize <- calculateTypeSize =<< resolveOrFail body
let decl =
@@ -381,7 +426,10 @@ advanceFiddleDecls localState decls = fmap (reverse . fst) $ do
<$> mapM (advanceStage localState'') body
<*> pure ann
ObjectDecl _ ident loc typ ann ->
- let qualifiedName = qualify (NonEmpty.singleton (identToString ident))
+ let qualifiedName =
+ fmap
+ (const $ identToString ident)
+ (currentQualifiedPath localState)
in do
location <- resolveLocationExpression localState' loc
typ' <- advanceStage localState' typ
@@ -414,10 +462,8 @@ objTypeToExport ls = \case
<$> objTypeToExport ls objType
<*> pure (trueValue size)
ReferencedObjType {refName = n} -> do
- (full, _ :: ExportedTypeDecl) <- resolveOrFail =<< resolveName n ls
- case full of
- (f : fs) -> return $ ReferencedObjectType (f :| fs)
- _ -> compilationFailure
+ (td :: ExportedTypeDecl) <- resolveOrFail =<< resolveName n ls
+ return $ ReferencedObjectType (metadataFullyQualifiedPath $ getMetadata td)
calculateTypeSize :: ObjTypeBody Expanded F A -> M (N Bytes)
calculateTypeSize (ObjTypeBody bodyType decls _) =
@@ -446,7 +492,7 @@ resolveLocationExpression ::
Expression u stage F A ->
M (N u)
resolveLocationExpression ls (Var var _) = do
- (_, ExportedLocationDecl _ v) <- resolveOrFail =<< resolveName var ls
+ (ExportedLocationDecl _ v) <- resolveOrFail =<< resolveName var ls
return (fromIntegral v)
resolveLocationExpression _ e = expressionToIntM e
diff --git a/src/Language/Fiddle/GenericTree.hs b/src/Language/Fiddle/GenericTree.hs
index 9b3089b..7e8d79b 100644
--- a/src/Language/Fiddle/GenericTree.hs
+++ b/src/Language/Fiddle/GenericTree.hs
@@ -276,4 +276,6 @@ deriving instance (Context stage) => (ToGenericSyntaxTree (ConstExpression Unitl
deriving instance (Context stage) => (ToGenericSyntaxTree (ConstExpression Address stage))
+deriving instance (Context stage) => (ToGenericSyntaxTree (ConstExpression Bits stage))
+
deriving instance (Context stage) => (ToGenericSyntaxTree (Expression u stage))
diff --git a/src/Language/Fiddle/Internal/UnitInterface.hs b/src/Language/Fiddle/Internal/UnitInterface.hs
index 42ce810..1302e40 100644
--- a/src/Language/Fiddle/Internal/UnitInterface.hs
+++ b/src/Language/Fiddle/Internal/UnitInterface.hs
@@ -1,14 +1,20 @@
+{-# LANGUAGE DeriveFoldable #-}
+{-# LANGUAGE DeriveTraversable #-}
+
module Language.Fiddle.Internal.UnitInterface where
import Data.Aeson
+import Data.List (intercalate)
import Data.List.NonEmpty (NonEmpty)
-import Data.Text
+import qualified Data.List.NonEmpty as NonEmpty
+import Data.Maybe (fromMaybe, maybeToList)
+import qualified Data.Text
import Data.Word
import GHC.Generics
import Language.Fiddle.Internal.Scopes (Scope)
import qualified Language.Fiddle.Internal.Scopes as Scopes
-import Language.Fiddle.Types (SourceSpan)
import Language.Fiddle.Internal.UnitNumbers
+import Language.Fiddle.Types (SourceSpan)
data InternalDirectiveExpression
= InternalDirectiveExpressionNumber String
@@ -31,16 +37,45 @@ data InternalDirective = InternalDirective
}
deriving (Generic, ToJSON, FromJSON, Show, Eq, Ord)
+data QualifiedPath a = QualifiedPath
+ { -- | The part of the qualified path that belongs to the package.
+ packagePart :: [String],
+ -- | The part of the qualified path that belongs to the object.
+ objectPart :: Maybe String,
+ -- | The part of the qualified path that belongs to a register.
+ registerPart :: [String],
+ -- | The basename (unqualified path)
+ basenamePart :: a
+ }
+ deriving (Generic, ToJSON, FromJSON, Show, Eq, Ord, Functor)
+
+qualifiedPathToString :: String -> String -> QualifiedPath String -> String
+qualifiedPathToString majorSeparator minorSeparator qp =
+ intercalate majorSeparator $
+ map (intercalate minorSeparator) $
+ filter
+ (not . null)
+ [ packagePart qp,
+ maybeToList (objectPart qp),
+ registerPart qp,
+ [basenamePart qp]
+ ]
+
+-- | Turn a QualifiedPath with a string to a String list for scope lookups.
+qualifiedPathToList :: QualifiedPath String -> NonEmpty String
+qualifiedPathToList (QualifiedPath package obj reg base) =
+ NonEmpty.prependList (package ++ maybeToList obj ++ reg) (NonEmpty.singleton base)
+
-- | Metadata about an exported value. This includes things like the source
-- location, doc comments and compiler directives associated with the exported
-- symbol.
data Metadata = Metadata
{ -- | Fully-qualified path the the element.
- metadataFullyQualifiedPath :: NonEmpty String,
+ metadataFullyQualifiedPath :: QualifiedPath String,
-- | Source location for the exported symbol.
metadataSourceSpan :: SourceSpan,
-- | Doc comment associated with the symbol.
- metadataDocComment :: Text,
+ metadataDocComment :: Data.Text.Text,
-- | List of directives associated with this exported symbol.
metadataDirectives :: [InternalDirective]
}
@@ -61,12 +96,12 @@ data UnitInterface where
insert :: (ExportableDecl d) => d -> UnitInterface -> UnitInterface
insert decl (UnitInterface sc deps) =
let metadata = getMetadata decl
- path = metadataFullyQualifiedPath metadata
+ path = qualifiedPathToList (metadataFullyQualifiedPath metadata)
in UnitInterface (Scopes.insertScope path (metadata, toExportedDecl decl) sc) deps
singleton :: (ExportableDecl d) => d -> UnitInterface
singleton decl =
- let path = metadataFullyQualifiedPath (getMetadata decl)
+ let path = qualifiedPathToList (metadataFullyQualifiedPath (getMetadata decl))
metadata = getMetadata decl
in UnitInterface (Scopes.singleton path (metadata, toExportedDecl decl)) []
@@ -125,7 +160,7 @@ data ExportedTypeDecl where
data ReferencedObjectType where
ReferencedObjectType ::
- {objectTypeReference :: NonEmpty String} -> ReferencedObjectType
+ {objectTypeReference :: QualifiedPath String} -> ReferencedObjectType
ArrayObjectType ::
{ arrayObjectTypeType :: ReferencedObjectType,
arrayObjectTypeNumber :: N Unitless
@@ -192,6 +227,17 @@ instance ExportableDecl ExportedObjectDecl where
_ -> Nothing
getMetadata = exportedObjectDeclMetadata
+instance ExportableDecl ExportedDecl where
+ toExportedDecl = id
+ fromExportedDecl = Just
+ getMetadata =
+ \case
+ ExportedPackage e -> getMetadata e
+ ExportedLocation e -> getMetadata e
+ ExportedBits e -> getMetadata e
+ ExportedType e -> getMetadata e
+ ExportedObject e -> getMetadata e
+
-- | A generalized representation of different exported declarations.
-- This data type allows for a uniform way to handle various exportable
-- syntax tree elements (e.g., packages, locations, bits, types, objects).
diff --git a/src/Language/Fiddle/Parser.hs b/src/Language/Fiddle/Parser.hs
index dea2dd5..7ef5ac4 100644
--- a/src/Language/Fiddle/Parser.hs
+++ b/src/Language/Fiddle/Parser.hs
@@ -190,6 +190,9 @@ objTypeP = do
AnonymousObjType Witness <$> defer body (objTypeBodyP t)
)
+asConstP :: Pa (Expression u) -> Pa (ConstExpression u)
+asConstP fn = withMeta $ ConstExpression . RightV <$> fn
+
exprInParenP :: Pa (Expression u)
exprInParenP = tok TokLParen *> expressionP <* tok TokRParen
@@ -258,7 +261,7 @@ registerBitsDeclP =
tok KWReserved >> ReservedBits <$> exprInParenP
)
<|> (BitsSubStructure <$> registerBodyP <*> optionMaybe ident)
- <|> ( DefinedBits Vacant
+ <|> ( DefinedBits Vacant . Perhaps
<$> optionMaybe modifierP
<*> ident
<*> (tok TokColon >> registerBitsTypeRefP)
@@ -282,7 +285,7 @@ registerBitsTypeRefP = do
baseTypeRef =
withMeta $
- (RegisterBitsJustBits <$> exprInParenP)
+ (RegisterBitsJustBits <$> asConstP exprInParenP)
<|> (RegisterBitsAnonymousType Witness <$> anonymousBitsTypeP)
<|> (RegisterBitsReference noQMd <$> name)