From 759ae4ae64bd786b9c0d4e533dc3d852cff2b247 Mon Sep 17 00:00:00 2001 From: Jan Mas Rovira Date: Wed, 23 Aug 2023 23:58:24 +0200 Subject: [PATCH] fix loop and add test --- .../FromParsed/Analysis/Scoping.hs | 39 ++++++++++--------- test/Scope/Negative.hs | 7 ++++ tests/negative/AliasCycle.juvix | 5 +++ 3 files changed, 32 insertions(+), 19 deletions(-) create mode 100644 tests/negative/AliasCycle.juvix diff --git a/src/Juvix/Compiler/Concrete/Translation/FromParsed/Analysis/Scoping.hs b/src/Juvix/Compiler/Concrete/Translation/FromParsed/Analysis/Scoping.hs index 9093c29660..3d3a3fade9 100644 --- a/src/Juvix/Compiler/Concrete/Translation/FromParsed/Analysis/Scoping.hs +++ b/src/Juvix/Compiler/Concrete/Translation/FromParsed/Analysis/Scoping.hs @@ -528,22 +528,17 @@ normalizePreSymbolEntry = \case checkQualifiedName :: (Members '[Error ScoperError, State Scope, State ScoperState, InfoTableBuilder] r) => QualifiedName -> - Sem r ScopedIden + Sem r PreSymbolEntry checkQualifiedName q@(QualifiedName (SymbolPath p) sym) = do es <- fst3 <$> lookupQualifiedSymbol (toList p, sym) case es of [] -> notInScope - [e] -> entryToScopedIden q' e + [e] -> return e _ -> throw (ErrAmbiguousSym (AmbiguousSym q' es)) where q' = NameQualified q notInScope = throw (ErrQualSymNotInScope (QualSymNotInScope q)) -scopedIdenToPreSymbolEntry :: ScopedIden -> PreSymbolEntry -scopedIdenToPreSymbolEntry s = case s ^. scopedIdenAlias of - Just a -> PreSymbolAlias (Alias (S.unConcrete a)) - Nothing -> PreSymbolFinal (SymbolEntry (S.unConcrete (s ^. scopedIden))) - entryToScopedIden :: Members '[InfoTableBuilder, State ScoperState] r => Name -> @@ -1174,7 +1169,7 @@ checkSections sec = do scanAlias :: AliasDef 'Parsed -> Sem r' () scanAlias a = do aliasId <- gets (^?! scopeLocalSymbols . at (a ^. aliasDefName) . _Just . S.nameId) - asName <- scopedIdenToPreSymbolEntry <$> checkName (a ^. aliasDefAsName) + asName <- checkName (a ^. aliasDefAsName) modify' (set (scoperAlias . at aliasId) (Just asName)) checkLoop aliasId where @@ -1931,17 +1926,17 @@ scopedFunction fref n = do registerName scoped return scoped -checkUnqualified :: +checkUnqualifiedName :: (Members '[Error ScoperError, State Scope, State ScoperState, InfoTableBuilder] r) => Symbol -> - Sem r ScopedIden -checkUnqualified s = do + Sem r PreSymbolEntry +checkUnqualifiedName s = do scope <- get -- Lookup at the global scope entries <- fst3 <$> lookupQualifiedSymbol ([], s) case resolveShadowing entries of [] -> throw (ErrSymNotInScope (NotInScope s scope)) - [x] -> entryToScopedIden n x + [x] -> return x es -> throw (ErrAmbiguousSym (AmbiguousSym n es)) where n = NameUnqualified s @@ -2079,17 +2074,23 @@ checkPatternAtom = \case checkName :: (Members '[Error ScoperError, State Scope, State ScoperState, InfoTableBuilder] r) => Name -> - Sem r ScopedIden + Sem r PreSymbolEntry checkName n = case n of NameQualified q -> checkQualifiedName q - NameUnqualified s -> checkUnqualified s + NameUnqualified s -> checkUnqualifiedName s + +checkScopedIden :: + (Members '[Error ScoperError, State Scope, State ScoperState, InfoTableBuilder] r) => + Name -> + Sem r ScopedIden +checkScopedIden n = checkName n >>= entryToScopedIden n checkExpressionAtom :: Members '[Reader ScopeParameters, Error ScoperError, State Scope, State ScoperState, InfoTableBuilder, NameIdGen] r => ExpressionAtom 'Parsed -> Sem r (NonEmpty (ExpressionAtom 'Scoped)) checkExpressionAtom e = case e of - AtomIdentifier n -> pure . AtomIdentifier <$> checkName n + AtomIdentifier n -> pure . AtomIdentifier <$> checkScopedIden n AtomLambda lam -> pure . AtomLambda <$> checkLambda lam AtomCase c -> pure . AtomCase <$> checkCase c AtomLet letBlock -> pure . AtomLet <$> checkLet letBlock @@ -2150,7 +2151,7 @@ checkNamedApplication :: NamedApplication 'Parsed -> Sem r (NamedApplication 'Scoped) checkNamedApplication napp = do - _namedAppName <- checkName (napp ^. namedAppName) + _namedAppName <- checkScopedIden (napp ^. namedAppName) _namedAppSignature <- Irrelevant <$> getNameSignature _namedAppName _namedAppArgs <- mapM checkArgumentBlock (napp ^. namedAppArgs) return NamedApplication {..} @@ -2195,7 +2196,7 @@ checkIterator :: Iterator 'Parsed -> Sem r (Iterator 'Scoped) checkIterator iter = do - _iteratorName <- checkName (iter ^. iteratorName) + _iteratorName <- checkScopedIden (iter ^. iteratorName) case _iteratorName ^. scopedIden . S.nameIterator of Just IteratorAttribs {..} -> do case _iteratorAttribsInitNum of @@ -2278,7 +2279,7 @@ checkParens :: checkParens e@(ExpressionAtoms as _) = case as of p :| [] -> case p of AtomIdentifier s -> do - scopedId <- checkName s + scopedId <- checkScopedIden s let scopedIdenNoFix = over scopedIden (set S.nameFixity Nothing) scopedId return (ExpressionParensIdentifier scopedIdenNoFix) AtomIterator i -> ExpressionIterator . set iteratorParens True <$> checkIterator i @@ -2365,7 +2366,7 @@ checkAliasDef :: Sem r (AliasDef 'Scoped) checkAliasDef AliasDef {..} = do aliasName' :: S.Symbol <- gets (^?! scopeLocalSymbols . at _aliasDefName . _Just) - asName' <- checkName _aliasDefAsName + asName' <- checkScopedIden _aliasDefAsName return AliasDef { _aliasDefName = aliasName', diff --git a/test/Scope/Negative.hs b/test/Scope/Negative.hs index cb5062f84f..8237b2bfef 100644 --- a/test/Scope/Negative.hs +++ b/test/Scope/Negative.hs @@ -350,5 +350,12 @@ scoperErrorTests = $(mkRelFile "IncomparablePrecedences.juvix") $ \case ErrIncomparablePrecedences {} -> Nothing + _ -> wrongError, + NegTest + "Alias cycle" + $(mkRelDir ".") + $(mkRelFile "AliasCycle.juvix") + $ \case + ErrAliasCycle {} -> Nothing _ -> wrongError ] diff --git a/tests/negative/AliasCycle.juvix b/tests/negative/AliasCycle.juvix new file mode 100644 index 0000000000..2e6ce0838a --- /dev/null +++ b/tests/negative/AliasCycle.juvix @@ -0,0 +1,5 @@ +module AliasCycle; + +syntax alias x1 := x2; +syntax alias x2 := x3; +syntax alias x3 := x1;