1
1
mirror of https://github.com/anoma/juvix.git synced 2024-11-30 14:13:27 +03:00

Properly handle confluent imports (#2915)

- Fixes #2914
This commit is contained in:
Jan Mas Rovira 2024-07-23 19:56:30 +02:00 committed by GitHub
parent 11425aa8e5
commit a5479d0718
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 67 additions and 12 deletions

View File

@ -711,9 +711,9 @@ lookupQualifiedSymbol ::
forall r. forall r.
(Members '[State Scope, State ScoperState] r) => (Members '[State Scope, State ScoperState] r) =>
([Symbol], Symbol) -> ([Symbol], Symbol) ->
Sem r ([PreSymbolEntry], [ModuleSymbolEntry], [FixitySymbolEntry]) Sem r (HashSet PreSymbolEntry, HashSet ModuleSymbolEntry, HashSet FixitySymbolEntry)
lookupQualifiedSymbol sms = do lookupQualifiedSymbol sms = do
(es, (ms, fs)) <- runOutputList . runOutputList . execOutputList $ go sms (es, (ms, fs)) <- runOutputHashSet . runOutputHashSet . execOutputHashSet $ go sms
return (es, ms, fs) return (es, ms, fs)
where where
go :: go ::
@ -758,7 +758,10 @@ lookupQualifiedSymbol sms = do
normalizePreSymbolEntry :: (Members '[State ScoperState] r) => PreSymbolEntry -> Sem r SymbolEntry normalizePreSymbolEntry :: (Members '[State ScoperState] r) => PreSymbolEntry -> Sem r SymbolEntry
normalizePreSymbolEntry = \case normalizePreSymbolEntry = \case
PreSymbolFinal a -> return a PreSymbolFinal a -> return a
PreSymbolAlias a -> gets (^?! scoperAlias . at (a ^. aliasName . S.nameId) . _Just) >>= normalizePreSymbolEntry PreSymbolAlias a -> gets (^. scoperAlias . at (a ^. aliasName . S.nameId)) >>= normalizePreSymbolEntry . fromMaybe err
where
err :: forall a. a
err = impossibleError ("The alias " <> ppTrace (a ^. aliasName) <> " was not found in the ScoperState ")
checkQualifiedName :: checkQualifiedName ::
(Members '[Error ScoperError, State Scope, State ScoperState, InfoTableBuilder, Reader InfoTable] r) => (Members '[Error ScoperError, State Scope, State ScoperState, InfoTableBuilder, Reader InfoTable] r) =>
@ -766,10 +769,10 @@ checkQualifiedName ::
Sem r PreSymbolEntry Sem r PreSymbolEntry
checkQualifiedName q@(QualifiedName (SymbolPath p) sym) = do checkQualifiedName q@(QualifiedName (SymbolPath p) sym) = do
es <- fst3 <$> lookupQualifiedSymbol (toList p, sym) es <- fst3 <$> lookupQualifiedSymbol (toList p, sym)
case es of case toList es of
[] -> notInScope [] -> notInScope
[e] -> return e [e] -> return e
_ -> throw (ErrAmbiguousSym (AmbiguousSym q' es)) _ -> throw (ErrAmbiguousSym (AmbiguousSym q' (toList es)))
where where
q' = NameQualified q q' = NameQualified q
notInScope = throw (ErrQualSymNotInScope (QualSymNotInScope q)) notInScope = throw (ErrQualSymNotInScope (QualSymNotInScope q))
@ -1820,7 +1823,7 @@ lookupModuleSymbol ::
Sem r ScopedModule Sem r ScopedModule
lookupModuleSymbol n = do lookupModuleSymbol n = do
es <- snd3 <$> lookupQualifiedSymbol (path, sym) es <- snd3 <$> lookupQualifiedSymbol (path, sym)
case nonEmpty (resolveShadowing es) of case nonEmpty (resolveShadowing (toList es)) of
Nothing -> notInScope Nothing -> notInScope
Just (x :| []) -> getModule x n Just (x :| []) -> getModule x n
Just more -> throw (ErrAmbiguousModuleSym (AmbiguousModuleSym n more)) Just more -> throw (ErrAmbiguousModuleSym (AmbiguousModuleSym n more))
@ -2384,7 +2387,7 @@ checkUnqualifiedName s = do
scope <- get scope <- get
-- Lookup at the global scope -- Lookup at the global scope
entries <- fst3 <$> lookupQualifiedSymbol ([], s) entries <- fst3 <$> lookupQualifiedSymbol ([], s)
case resolveShadowing entries of case resolveShadowing (toList entries) of
[] -> throw (ErrSymNotInScope (NotInScope s scope)) [] -> throw (ErrSymNotInScope (NotInScope s scope))
[x] -> return x [x] -> return x
es -> throw (ErrAmbiguousSym (AmbiguousSym n es)) es -> throw (ErrAmbiguousSym (AmbiguousSym n es))
@ -2399,7 +2402,7 @@ checkFixitySymbol s = do
scope <- get scope <- get
-- Lookup at the global scope -- Lookup at the global scope
entries <- thd3 <$> lookupQualifiedSymbol ([], s) entries <- thd3 <$> lookupQualifiedSymbol ([], s)
case resolveShadowing entries of case resolveShadowing (toList entries) of
[] -> throw (ErrSymNotInScope (NotInScope s scope)) [] -> throw (ErrSymNotInScope (NotInScope s scope))
[x] -> do [x] -> do
let res = entryToSymbol x s let res = entryToSymbol x s
@ -2473,13 +2476,14 @@ lookupNameOfKind ::
Name -> Name ->
Sem r (Maybe ScopedIden) Sem r (Maybe ScopedIden)
lookupNameOfKind nameKind n = do lookupNameOfKind nameKind n = do
entries <- lookupQualifiedSymbol (path, sym) >>= mapMaybeM filterEntry . fst3 entries <- lookupQualifiedSymbol (path, sym) >>= mapMaybeM filterEntry . toList . fst3
case entries of case entries of
[] -> return Nothing [] -> return Nothing
[(_, s)] -> return (Just s) -- There is one constructor with such a name [(_, s)] -> return (Just s) -- There is one constructor with such a name
es -> throw (ErrAmbiguousSym (AmbiguousSym n (map fst es))) es -> throw (ErrAmbiguousSym (AmbiguousSym n (map fst es)))
where where
(path, sym) = splitName n (path, sym) = splitName n
filterEntry :: PreSymbolEntry -> Sem r (Maybe (PreSymbolEntry, ScopedIden)) filterEntry :: PreSymbolEntry -> Sem r (Maybe (PreSymbolEntry, ScopedIden))
filterEntry e = do filterEntry e = do
e' <- entryToScopedIden n e e' <- entryToScopedIden n e

View File

@ -14,6 +14,8 @@ instance Serialize Alias
instance NFData Alias instance NFData Alias
instance Hashable Alias
-- | Either an alias or a symbol entry. -- | Either an alias or a symbol entry.
data PreSymbolEntry data PreSymbolEntry
= PreSymbolAlias Alias = PreSymbolAlias Alias
@ -24,6 +26,8 @@ instance Serialize PreSymbolEntry
instance NFData PreSymbolEntry instance NFData PreSymbolEntry
instance Hashable PreSymbolEntry
-- | A symbol which is not an alias. -- | A symbol which is not an alias.
newtype SymbolEntry = SymbolEntry newtype SymbolEntry = SymbolEntry
{ _symbolEntry :: S.Name { _symbolEntry :: S.Name
@ -45,6 +49,8 @@ instance Serialize ModuleSymbolEntry
instance NFData ModuleSymbolEntry instance NFData ModuleSymbolEntry
instance Hashable ModuleSymbolEntry
newtype FixitySymbolEntry = FixitySymbolEntry newtype FixitySymbolEntry = FixitySymbolEntry
{ _fixityEntry :: S.Name { _fixityEntry :: S.Name
} }
@ -54,6 +60,8 @@ instance Serialize FixitySymbolEntry
instance NFData FixitySymbolEntry instance NFData FixitySymbolEntry
instance Hashable FixitySymbolEntry
makeLenses ''Alias makeLenses ''Alias
makeLenses ''SymbolEntry makeLenses ''SymbolEntry
makeLenses ''ModuleSymbolEntry makeLenses ''ModuleSymbolEntry

View File

@ -477,6 +477,9 @@ undefined = Err.error "undefined"
impossible :: (HasCallStack) => a impossible :: (HasCallStack) => a
impossible = Err.error "impossible" impossible = Err.error "impossible"
impossibleError :: (HasCallStack) => Text -> a
impossibleError msg = Err.error ("impossible: " <> unpack msg)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
infixl 7 <+?> infixl 7 <+?>

View File

@ -1,6 +1,7 @@
module Juvix.Prelude.Effects.Accum module Juvix.Prelude.Effects.Accum
( Accum, ( Accum,
runAccumList, runAccumList,
runAccumListReverse,
execAccumList, execAccumList,
ignoreAccum, ignoreAccum,
accum, accum,
@ -21,10 +22,13 @@ newtype instance StaticRep (Accum o) = Accum
accum :: (Member (Accum o) r) => o -> Sem r () accum :: (Member (Accum o) r) => o -> Sem r ()
accum o = overStaticRep (\(Accum l) -> Accum (o : l)) accum o = overStaticRep (\(Accum l) -> Accum (o : l))
runAccumList :: Sem (Accum o ': r) a -> Sem r ([o], a) runAccumListReverse :: Sem (Accum o ': r) a -> Sem r ([o], a)
runAccumList m = do runAccumListReverse m = do
(a, Accum s) <- runStaticRep (Accum mempty) m (a, Accum s) <- runStaticRep (Accum mempty) m
return (reverse s, a) return (s, a)
runAccumList :: Sem (Accum o ': r) a -> Sem r ([o], a)
runAccumList m = first reverse <$> runAccumListReverse m
execAccumList :: Sem (Accum o ': r) a -> Sem r [o] execAccumList :: Sem (Accum o ': r) a -> Sem r [o]
execAccumList = fmap fst . runAccumList execAccumList = fmap fst . runAccumList

View File

@ -27,10 +27,22 @@ runOutputSem handle =
interpret $ \case interpret $ \case
Output x -> handle x Output x -> handle x
runOutputHashSet :: (Hashable o) => Sem (Output o ': r) a -> Sem r (HashSet o, a)
runOutputHashSet =
fmap (first hashSet)
. reinterpret
runAccumListReverse
( \case
Output x -> accum x
)
runOutputList :: Sem (Output o ': r) a -> Sem r ([o], a) runOutputList :: Sem (Output o ': r) a -> Sem r ([o], a)
runOutputList = reinterpret runAccumList $ \case runOutputList = reinterpret runAccumList $ \case
Output x -> accum x Output x -> accum x
execOutputHashSet :: (Hashable o) => Sem (Output o ': r) a -> Sem r (HashSet o)
execOutputHashSet = fmap fst . runOutputHashSet
execOutputList :: Sem (Output o ': r) a -> Sem r [o] execOutputList :: Sem (Output o ': r) a -> Sem r [o]
execOutputList = fmap fst . runOutputList execOutputList = fmap fst . runOutputList

View File

@ -250,6 +250,10 @@ tests =
"Named argument puns" "Named argument puns"
$(mkRelDir ".") $(mkRelDir ".")
$(mkRelFile "Puns.juvix"), $(mkRelFile "Puns.juvix"),
posTest
"Confluent imports"
$(mkRelDir "ConfluentScoping")
$(mkRelFile "Main.juvix"),
posTest posTest
"Record field iterator" "Record field iterator"
$(mkRelDir ".") $(mkRelDir ".")

View File

@ -0,0 +1,3 @@
module A;
import B public;

View File

@ -0,0 +1,3 @@
module B;
axiom Axiom : Type;

View File

@ -0,0 +1,6 @@
module Main;
import A open;
import B;
axiom X : B.Axiom;

View File

@ -0,0 +1,8 @@
module Package;
import PackageDescription.V2 open;
package : Package :=
defaultPackage@?{
name := "confluentscoping"
};