@@ -10,7 +10,7 @@ module HsBindgen.Frontend.Analysis.DeclIndex (
1010 Usable (.. )
1111 , Unusable (.. )
1212 , Entry (.. )
13- , DeclIndex
13+ , DeclIndex -- opaque
1414 -- * Construction
1515 , fromParseResults
1616 -- * Query parse successes
@@ -40,8 +40,9 @@ import Prelude hiding (lookup)
4040import Control.Monad.State
4141import Data.Foldable qualified as Foldable
4242import Data.Function
43+ import Data.List.NonEmpty ((<|) )
44+ import Data.List.NonEmpty qualified as NonEmpty
4345import Data.Map.Strict qualified as Map
44- import Optics.Core (over )
4546
4647import Clang.HighLevel.Types
4748import Clang.Paths
@@ -82,13 +83,14 @@ data Usable =
8283-- (We avoid the term available, because it is overloaded with Clang's
8384-- CXAvailabilityKind).
8485data Unusable =
85- UnusableParseNotAttempted ParseNotAttempted
86+ UnusableParseNotAttempted ( NonEmpty ParseNotAttempted )
8687 | UnusableParseFailure ParseFailure
8788 | UnusableConflict ConflictingDeclarations
8889 | UnusableFailedMacro FailedMacro
8990 -- TODO https://github.com/well-typed/hs-bindgen/issues/1273: Attach
9091 -- information required to match the select predicate also to omitted
9192 -- declarations.
93+ -- | Omitted by prescriptive binding specifications
9294 | UnusableOmitted (C. QualName , SourcePath )
9395 deriving stock (Show , Generic )
9496
@@ -164,15 +166,15 @@ fromParseResults results = flip execState emptyIndex $ mapM_ aux results
164166 where
165167 aux :: ParseResult -> State DeclIndex ()
166168 aux new = modify' $
167- DeclIndex . Map. alter (handleDeclaration declId new) declId . unDeclIndex
169+ DeclIndex . Map. alter (Just . handleParseResult declId new) declId . unDeclIndex
168170 where
169171 declId :: C. QualPrelimDeclId
170- declId = getQualPrelimDeclId new
172+ declId = getParseResultDeclId new
171173
172- handleDeclaration ::
173- C. QualPrelimDeclId -> ParseResult -> Maybe Entry -> Maybe Entry
174- handleDeclaration declId new = \ case
175- Nothing -> Just $ parseResultToEntry new
174+ handleParseResult ::
175+ C. QualPrelimDeclId -> ParseResult -> Maybe Entry -> Entry
176+ handleParseResult declId new = \ case
177+ Nothing -> parseResultToEntry new
176178 -- We remove duplicates with /different/ values and store them as
177179 -- 'ConflictingDeclarations'. We could detect and handle some but not all
178180 -- of these duplicates; for now, we remove them all.
@@ -195,49 +197,36 @@ fromParseResults results = flip execState emptyIndex $ mapM_ aux results
195197 -- the @DeclIndex@ has been built (at this point the macro is merely a
196198 -- list of tokens). So whether the macro is something we can handle or not
197199 -- is irrelevant at this point.
198- Just oldDuplicate -> Just $ case oldDuplicate of
200+ Just old -> case old of
199201 UsableE oldUsable -> case oldUsable of
200202 UsableSuccess oldParseSuccess
201203 -- Redeclaration but with the same definition. This can happen, for
202- -- example for opaque structs. We stick with the first but add the
203- -- parse messages of the second.
204+ -- example for opaque structs. We stick with the first declaration.
204205 | ParseResultSuccess newParseSuccess <- new
205- , sameParseResult (ParseResultSuccess oldParseSuccess) new ->
206- UsableE $ UsableSuccess $ over # psAttachedMsgs
207- (++ newParseSuccess. psAttachedMsgs)
208- oldParseSuccess
206+ , sameDefinition oldParseSuccess. psDecl. declKind newParseSuccess. psDecl. declKind ->
207+ old
209208 | otherwise ->
210209 newConflict oldParseSuccess. psDecl. declInfo. declLoc
211- -- TODO_PR: Should not happen because we have no external entries yet.
212- -- Panic?
213- UsableExternal -> UsableE UsableExternal
210+ UsableExternal ->
211+ panicPure " handleParseResult: usable external"
214212 UnusableE oldUnusable -> case oldUnusable of
215- (UnusableParseNotAttempted r )
216- | sameParseResult ( ParseResultNotAttempted r) new ->
217- oldDuplicate
213+ (UnusableParseNotAttempted nasOld )
214+ | ParseResultNotAttempted naNew <- new ->
215+ UnusableE $ UnusableParseNotAttempted $ naNew <| nasOld
218216 | otherwise ->
219- newConflict (unParseNotAttempted r). loc
220- UnusableParseFailure r
221- | sameParseResult (ParseResultFailure r) new ->
222- oldDuplicate
223- | otherwise ->
224- newConflict (unParseFailure r). loc
225- UnusableConflict c -> addConflict c
226- -- TODO_PR: Should not happen because we have no failed macros yet.
227- -- Panic?
228- UnusableFailedMacro r -> UnusableE $ UnusableFailedMacro r
229- -- TODO_PR: Should not happen because we have no omitted entries yet.
230- -- Panic?
231- UnusableOmitted o -> UnusableE $ UnusableOmitted o
217+ parseResultToEntry new
218+ UnusableParseFailure _ -> old
219+ UnusableConflict c -> addConflicts c
220+ UnusableFailedMacro x ->
221+ panicPure $ " handleParseResult: unusable failed macro" <> show x
222+ UnusableOmitted x ->
223+ panicPure $ " handelParseResult: unusable omitted" <> show x
232224 where
233225 newLoc :: SingleLoc
234- newLoc = case new of
235- ParseResultSuccess ParseSuccess {psDecl} -> psDecl. declInfo. declLoc
236- ParseResultNotAttempted (ParseNotAttempted m) -> m. loc
237- ParseResultFailure (ParseFailure m) -> m. loc
226+ newLoc = getParseResultLoc new
238227
239- addConflict :: ConflictingDeclarations -> Entry
240- addConflict c =
228+ addConflicts :: ConflictingDeclarations -> Entry
229+ addConflicts c =
241230 UnusableE $ UnusableConflict $
242231 addConflictingLoc c newLoc
243232
@@ -248,28 +237,20 @@ fromParseResults results = flip execState emptyIndex $ mapM_ aux results
248237
249238 parseResultToEntry :: ParseResult -> Entry
250239 parseResultToEntry = \ case
251- ParseResultSuccess r -> UsableE $ UsableSuccess r
252- ParseResultNotAttempted r -> UnusableE $ UnusableParseNotAttempted r
253- ParseResultFailure r -> UnusableE $ UnusableParseFailure r
254-
255- sameParseResult :: ParseResult -> ParseResult -> Bool
256- sameParseResult a b = case (a, b) of
257- (ParseResultSuccess x1 , ParseResultSuccess x2) ->
258- sameDefinition x1. psDecl. declKind x2. psDecl. declKind
259- (ParseResultNotAttempted x1 , ParseResultNotAttempted x2) -> x1 == x2
260- (ParseResultFailure x1 , ParseResultFailure x2) -> x1 == x2
261- (_ , _) -> False
262-
263- sameDefinition :: C. DeclKind Parse -> C. DeclKind Parse -> Bool
264- sameDefinition a b =
265- case (a, b) of
266- (C. DeclMacro macroA, C. DeclMacro macroB) ->
267- sameMacro macroA macroB
268- _otherwise ->
269- a == b
270-
271- sameMacro :: UnparsedMacro -> UnparsedMacro -> Bool
272- sameMacro = (==) `on` (map tokenSpelling . unparsedTokens)
240+ ParseResultSuccess r -> UsableE $ UsableSuccess r
241+ ParseResultNotAttempted r -> UnusableE $ UnusableParseNotAttempted $ r :| []
242+ ParseResultFailure r -> UnusableE $ UnusableParseFailure r
243+
244+ sameDefinition :: C. DeclKind Parse -> C. DeclKind Parse -> Bool
245+ sameDefinition a b =
246+ case (a, b) of
247+ (C. DeclMacro macroA, C. DeclMacro macroB) ->
248+ sameMacro macroA macroB
249+ _otherwise ->
250+ a == b
251+
252+ sameMacro :: UnparsedMacro -> UnparsedMacro -> Bool
253+ sameMacro = (==) `on` (map tokenSpelling . unparsedTokens)
273254
274255{- ------------------------------------------------------------------------------
275256 Query parse successes
@@ -308,36 +289,30 @@ lookupEntry x = Map.lookup x . unDeclIndex
308289toList :: DeclIndex -> [(C. QualPrelimDeclId , Entry )]
309290toList = Map. toList . unDeclIndex
310291
311- -- | Get the source location of a declaration.
312- lookupLoc :: C. QualPrelimDeclId -> DeclIndex -> Maybe SingleLoc
292+ -- | Get the source locations of a declaration.
293+ lookupLoc :: C. QualPrelimDeclId -> DeclIndex -> [ SingleLoc ]
313294lookupLoc d (DeclIndex i) = case Map. lookup d i of
314- Nothing -> Nothing
295+ Nothing -> []
315296 Just (UsableE e) -> case e of
316- UsableSuccess x -> Just $ x. psDecl. declInfo. declLoc
317- UsableExternal -> Nothing
318- Just (UnusableE e) -> case e of
319- UnusableParseNotAttempted (ParseNotAttempted x) -> Just $ x. loc
320- UnusableParseFailure (ParseFailure x) -> Just $ x. loc
321- -- TODO_PR: What should we do for conflicting declarations? Return the
322- -- minimum location (relevant for sorting select messages), return all
323- -- locations, or return none? See also 'lookupUnusableLoc' below.
324- UnusableConflict x -> Just $ getMinimumLoc x
325- UnusableFailedMacro (FailedMacro x) -> Just $ x. loc
326- UnusableOmitted {} -> Nothing
327-
328- -- TODO_PR: We use this function when looking for missing declarations during
329- -- resolution of external binding specifications. Do we want to get all
330- -- locations for conflicting declarations here?
297+ UsableSuccess x -> [x. psDecl. declInfo. declLoc]
298+ UsableExternal -> []
299+ Just (UnusableE e) -> unusableToLoc e
300+
301+ -- | Get the source locations of an unusable declaration.
331302lookupUnusableLoc :: C. QualPrelimDeclId -> DeclIndex -> [SingleLoc ]
332303lookupUnusableLoc d (DeclIndex i) = case Map. lookup d i of
333304 Nothing -> []
334305 Just (UsableE _) -> []
335- Just (UnusableE e) -> case e of
336- UnusableParseNotAttempted (ParseNotAttempted x) -> [x. loc]
337- UnusableParseFailure (ParseFailure x) -> [x. loc]
338- UnusableConflict x -> getLocs x
339- UnusableFailedMacro (FailedMacro x) -> [x. loc]
340- UnusableOmitted {} -> []
306+ Just (UnusableE e) -> unusableToLoc e
307+
308+ unusableToLoc :: Unusable -> [SingleLoc ]
309+ unusableToLoc = \ case
310+ UnusableParseNotAttempted xs ->
311+ [x. loc | (ParseNotAttempted x) <- NonEmpty. toList xs]
312+ UnusableParseFailure (ParseFailure x) -> [x. loc]
313+ UnusableConflict x -> getLocs x
314+ UnusableFailedMacro (FailedMacro x) -> [x. loc]
315+ UnusableOmitted {} -> []
341316
342317-- | Get the identifiers of all declarations in the index.
343318keysSet :: DeclIndex -> Set C. QualPrelimDeclId
@@ -372,6 +347,8 @@ registerMacroFailures xs index = Foldable.foldl' insert index xs
372347-- Match function to find selection roots.
373348type Match = C. QualPrelimDeclId -> SingleLoc -> C. Availability -> Bool
374349
350+ -- | Limit the declaration index to those entries that match the select
351+ -- predicate. Do not include anything external nor omitted.
375352selectDeclIndex :: Match -> DeclIndex -> DeclIndex
376353selectDeclIndex p = DeclIndex . Map. filter matchEntry . unDeclIndex
377354 where
@@ -380,19 +357,17 @@ selectDeclIndex p = DeclIndex . Map.filter matchEntry . unDeclIndex
380357 UsableE e -> case e of
381358 UsableSuccess (ParseSuccess i d _) ->
382359 p i d. declInfo. declLoc d. declInfo. declAvailability
383- -- TODO_PR: We should match external declarations.
384360 UsableExternal ->
385361 False
386362 UnusableE e -> case e of
387- UnusableParseNotAttempted ( ParseNotAttempted m) ->
388- matchMsg m
363+ UnusableParseNotAttempted xs ->
364+ any ( matchMsg . unParseNotAttempted) xs
389365 UnusableParseFailure (ParseFailure m) ->
390366 matchMsg m
391367 UnusableConflict x ->
392368 or [p (getDeclId x) l C. Available | l <- getLocs x ]
393369 UnusableFailedMacro (FailedMacro m) ->
394370 matchMsg m
395- -- TODO_PR: We should match omitted declarations.
396371 UnusableOmitted {} ->
397372 False
398373
0 commit comments