summaryrefslogtreecommitdiff
path: root/src/Language/Fiddle/Compiler/Qualification.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Language/Fiddle/Compiler/Qualification.hs')
-rw-r--r--src/Language/Fiddle/Compiler/Qualification.hs170
1 files changed, 108 insertions, 62 deletions
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