Skip to content

Commit

Permalink
⅄ term-name-resolution-change → type-name-resolution-change
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchellwrosen committed Aug 26, 2024
2 parents a0662ff + 9892658 commit 7d7df0e
Show file tree
Hide file tree
Showing 42 changed files with 591 additions and 671 deletions.
4 changes: 2 additions & 2 deletions parser-typechecker/src/Unison/Hashing/V2/Convert.hs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ h2mReferent getCT = \case
hashDataDecls ::
(Var v) =>
Map v (Memory.DD.DataDeclaration v a) ->
ResolutionResult v a [(v, Memory.Reference.Id, Memory.DD.DataDeclaration v a)]
ResolutionResult a [(v, Memory.Reference.Id, Memory.DD.DataDeclaration v a)]
hashDataDecls memDecls = do
let hashingDecls = fmap m2hDecl memDecls
hashingResult <- Hashing.hashDecls Name.unsafeParseVar hashingDecls
Expand All @@ -239,7 +239,7 @@ hashDataDecls memDecls = do
hashDecls ::
(Var v) =>
Map v (Memory.DD.Decl v a) ->
ResolutionResult v a [(v, Memory.Reference.Id, Memory.DD.Decl v a)]
ResolutionResult a [(v, Memory.Reference.Id, Memory.DD.Decl v a)]
hashDecls memDecls = do
-- want to unwrap the decl before doing the rehashing, and then wrap it back up the same way
let howToReassemble =
Expand Down
3 changes: 2 additions & 1 deletion parser-typechecker/src/Unison/Parsers.hs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ unsafeParseFileBuiltinsOnly =
Parser.ParsingEnv
{ uniqueNames = mempty,
uniqueTypeGuid = \_ -> pure Nothing,
names = Builtin.names
names = Builtin.names,
maybeNamespace = Nothing
}

unsafeParseFile :: (Monad m) => String -> Parser.ParsingEnv m -> m (UnisonFile Symbol Ann)
Expand Down
21 changes: 21 additions & 0 deletions parser-typechecker/src/Unison/PrettyPrintEnv/Names.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module Unison.PrettyPrintEnv.Names
dontSuffixify,
suffixifyByHash,
suffixifyByName,
suffixifyByHashWithUnhashedTermsInScope,

-- * Pretty-print env
makePPE,
Expand All @@ -23,11 +24,14 @@ import Unison.Name (Name)
import Unison.Name qualified as Name
import Unison.Names (Names)
import Unison.Names qualified as Names
import Unison.Names.ResolvesTo (ResolvesTo (..))
import Unison.NamesWithHistory qualified as Names
import Unison.Prelude
import Unison.PrettyPrintEnv (PrettyPrintEnv (PrettyPrintEnv))
import Unison.Reference (TypeReference)
import Unison.Referent (Referent)
import Unison.Util.Relation (Relation)
import Unison.Util.Relation qualified as Relation

------------------------------------------------------------------------------------------------------------------------
-- Namer
Expand Down Expand Up @@ -84,6 +88,23 @@ suffixifyByHash names =
suffixifyType = \name -> Name.suffixifyByHash name (Names.types names)
}

suffixifyByHashWithUnhashedTermsInScope :: Set Name -> Names -> Suffixifier
suffixifyByHashWithUnhashedTermsInScope localTermNames namespaceNames =
Suffixifier
{ suffixifyTerm = \name ->
Name.suffixifyByHash
name
terms, -- (Relation.mapRanMonotonic ResolvesToNamespace (Names.terms names)),
suffixifyType = \name -> Name.suffixifyByHash name (Names.types namespaceNames)
}
where
terms :: Relation Name (ResolvesTo Referent)
terms =
Names.terms namespaceNames
& Relation.subtractDom localTermNames
& Relation.mapRan ResolvesToNamespace
& Relation.union (Relation.fromList (map (\name -> (name, ResolvesToLocal name)) (Set.toList localTermNames)))

------------------------------------------------------------------------------------------------------------------------
-- Pretty-print env

Expand Down
54 changes: 17 additions & 37 deletions parser-typechecker/src/Unison/PrintError.hs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import Text.Megaparsec qualified as P
import Unison.ABT qualified as ABT
import Unison.Builtin.Decls (unitRef, pattern TupleType')
import Unison.ConstructorReference (ConstructorReference, GConstructorReference (..))
import Unison.HashQualified (HashQualified)
import Unison.HashQualified qualified as HQ
import Unison.HashQualifiedPrime qualified as HQ'
import Unison.Kind (Kind)
import Unison.Kind qualified as Kind
Expand Down Expand Up @@ -1783,8 +1783,6 @@ renderParseErrors s = \case
annotatedAsErrorSite s tok
]
in (msg, maybeToList $ rangeForAnnotated tok)
go (Parser.UnknownAbilityConstructor tok _referents) = (unknownConstructor "ability" tok, [rangeForToken tok])
go (Parser.UnknownDataConstructor tok _referents) = (unknownConstructor "data" tok, [rangeForToken tok])
go (Parser.UnknownId tok referents references) =
let msg =
Pr.lines
Expand Down Expand Up @@ -1856,24 +1854,6 @@ renderParseErrors s = \case
]
in (msg, [rangeForToken tok])

unknownConstructor ::
String -> L.Token (HashQualified Name) -> Pretty ColorText
unknownConstructor ctorType tok =
Pr.lines
[ (Pr.wrap . mconcat)
[ "I don't know about any ",
fromString ctorType,
" constructor named ",
Pr.group
( stylePretty ErrorSite (prettyHashQualified0 (L.payload tok))
<> "."
),
"Maybe make sure it's correctly spelled and that you've imported it:"
],
"",
tokenAsErrorSite s tok
]

annotatedAsErrorSite ::
(Annotated a) => String -> a -> Pretty ColorText
annotatedAsErrorSite = annotatedAsStyle ErrorSite
Expand Down Expand Up @@ -1954,11 +1934,11 @@ intLiteralSyntaxTip term expectedType = case (term, expectedType) of
-- | Pretty prints resolution failure annotations, including a table of disambiguation
-- suggestions.
prettyResolutionFailures ::
forall v a.
(Annotated a, Var v, Ord a) =>
forall a.
(Annotated a, Ord a) =>
-- | src
String ->
[Names.ResolutionFailure v a] ->
[Names.ResolutionFailure a] ->
Pretty ColorText
prettyResolutionFailures s allFailures =
Pr.callout "" $
Expand All @@ -1973,39 +1953,39 @@ prettyResolutionFailures s allFailures =
where
-- Collapses identical failures which may have multiple annotations into a single failure.
-- uniqueFailures
ambiguitiesToTable :: [Names.ResolutionFailure v a] -> Pretty ColorText
ambiguitiesToTable :: [Names.ResolutionFailure a] -> Pretty ColorText
ambiguitiesToTable failures =
let pairs :: ([(v, Maybe (NESet String))])
let pairs :: ([(HQ.HashQualified Name, Maybe (NESet String))])
pairs = nubOrd . fmap toAmbiguityPair $ failures
spacerRow = ("", "")
in Pr.column2Header "Symbol" "Suggestions" $ spacerRow : (intercalateMap [spacerRow] prettyRow pairs)

toAmbiguityPair :: Names.ResolutionFailure v annotation -> (v, Maybe (NESet String))
toAmbiguityPair :: Names.ResolutionFailure annotation -> (HQ.HashQualified Name, Maybe (NESet String))
toAmbiguityPair = \case
(Names.TermResolutionFailure v _ (Names.Ambiguous names refs localNames)) -> do
(Names.TermResolutionFailure name _ (Names.Ambiguous names refs localNames)) -> do
let ppe = ppeFromNames names
in ( v,
in ( name,
Just $
NES.unsafeFromSet
(Set.map (showTermRef ppe) refs <> Set.map (Text.unpack . Name.toText) localNames)
)
(Names.TypeResolutionFailure v _ (Names.Ambiguous names refs localNames)) -> do
(Names.TypeResolutionFailure name _ (Names.Ambiguous names refs localNames)) -> do
let ppe = ppeFromNames names
in ( v,
in ( name,
Just $
NES.unsafeFromSet (Set.map (showTypeRef ppe) refs <> Set.map (Text.unpack . Name.toText) localNames)
)
(Names.TermResolutionFailure v _ Names.NotFound) -> (v, Nothing)
(Names.TypeResolutionFailure v _ Names.NotFound) -> (v, Nothing)
(Names.TermResolutionFailure name _ Names.NotFound) -> (name, Nothing)
(Names.TypeResolutionFailure name _ Names.NotFound) -> (name, Nothing)

ppeFromNames :: Names.Names -> PPE.PrettyPrintEnv
ppeFromNames names =
PPE.makePPE (PPE.hqNamer PPE.todoHashLength names) PPE.dontSuffixify

prettyRow :: (v, Maybe (NESet String)) -> [(Pretty ColorText, Pretty ColorText)]
prettyRow (v, mSet) = case mSet of
Nothing -> [(prettyVar v, Pr.hiBlack "No matches")]
Just suggestions -> zip ([prettyVar v] ++ repeat "") (Pr.string <$> toList suggestions)
prettyRow :: (HQ.HashQualified Name, Maybe (NESet String)) -> [(Pretty ColorText, Pretty ColorText)]
prettyRow (name, mSet) = case mSet of
Nothing -> [(prettyHashQualified0 name, Pr.hiBlack "No matches")]
Just suggestions -> zip ([prettyHashQualified0 name] ++ repeat "") (Pr.string <$> toList suggestions)

useExamples :: Pretty ColorText
useExamples =
Expand Down
2 changes: 1 addition & 1 deletion parser-typechecker/src/Unison/Result.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type ResultT notes f = MaybeT (WriterT notes f)

data Note v loc
= Parsing (Parser.Err v)
| NameResolutionFailures [Names.ResolutionFailure v loc]
| NameResolutionFailures [Names.ResolutionFailure loc]
| UnknownSymbol v loc
| TypeError (Context.ErrorNote v loc)
| TypeInfo (Context.InfoNote v loc)
Expand Down
7 changes: 4 additions & 3 deletions parser-typechecker/src/Unison/Runtime/IOSource.hs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ parsingEnv =
Parser.ParsingEnv
{ uniqueNames = mempty,
uniqueTypeGuid = \_ -> pure Nothing,
names = Builtin.names
names = Builtin.names,
maybeNamespace = Nothing
}

typecheckingEnv :: Typechecker.Env Symbol Ann
Expand Down Expand Up @@ -543,8 +544,8 @@ d1 Doc.++ d2 =
use Doc2
match (d1,d2) with
(Join ds, Join ds2) -> Join (ds List.++ ds2)
(Join ds, _) -> Join (List.snoc ds d2)
(_, Join ds) -> Join (List.cons d1 ds)
(Join ds, _) -> Join (ds List.:+ d2)
(_, Join ds) -> Join (d1 List.+: ds)
_ -> Join [d1,d2]

unique[q1905679b27a97a4098bc965574da880c1074183a2c55ff1d481619c7fb8a1e1] type
Expand Down
53 changes: 16 additions & 37 deletions parser-typechecker/src/Unison/Syntax/FileParser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,19 @@ import Unison.WatchKind (WatchKind)
import Unison.WatchKind qualified as UF
import Prelude hiding (readFile)

resolutionFailures :: (Ord v) => [Names.ResolutionFailure v Ann] -> P v m x
resolutionFailures :: (Ord v) => [Names.ResolutionFailure Ann] -> P v m x
resolutionFailures es = P.customFailure (ResolutionFailures es)

file :: forall m v. (Monad m, Var v) => P v m (UnisonFile v Ann)
file = do
_ <- openBlock

-- Parse an optional directive like "namespace foo.bar"
maybeNamespace :: Maybe v <-
maybeNamespace :: Maybe Name.Name <-
optional (reserved "namespace") >>= \case
Nothing -> pure Nothing
Just _ -> Just . Name.toVar . L.payload <$> (importWordyId <|> importSymbolyId)
Just _ -> Just . L.payload <$> (importWordyId <|> importSymbolyId)
let maybeNamespaceVar = Name.toVar <$> maybeNamespace

-- The file may optionally contain top-level imports,
-- which are parsed and applied to the type decls and term stanzas
Expand All @@ -65,7 +66,7 @@ file = do
env <-
let applyNamespaceToDecls :: forall decl. Iso' decl (DataDeclaration v Ann) -> Map v decl -> Map v decl
applyNamespaceToDecls dataDeclL =
case maybeNamespace of
case maybeNamespaceVar of
Nothing -> id
Just namespace -> Map.fromList . map f . Map.toList
where
Expand All @@ -90,7 +91,7 @@ file = do
(typ, fields) <- parsedAccessors
-- The parsed accessor has an un-namespaced type, so apply the namespace directive (if necessary) before
-- looking up in the environment computed by `environmentFor`.
let typ1 = maybe id Var.namespaced2 maybeNamespace (L.payload typ)
let typ1 = maybe id Var.namespaced2 maybeNamespaceVar (L.payload typ)
Just (r, _) <- [Map.lookup typ1 (UF.datas env)]
-- Generate the record accessors with *un-namespaced* names (passing `typ` rather than `typ1`) below, because we
-- need to know these names in order to perform rewriting. As an example,
Expand All @@ -107,26 +108,19 @@ file = do
let accessors :: [(v, Ann, Term v Ann)]
accessors =
unNamespacedAccessors
& case maybeNamespace of
& case maybeNamespaceVar of
Nothing -> id
Just namespace -> over (mapped . _1) (Var.namespaced2 namespace)
let importNames = [(Name.unsafeParseVar v, Name.unsafeParseVar v2) | (v, v2) <- imports]
let locals = Names.importing importNames (UF.names env)
-- At this stage of the file parser, we've parsed all the type and ability
-- declarations. The `push locals` here has the effect
-- of making suffix-based name resolution prefer type and constructor names coming
-- from the local file.
--
-- There's some more complicated logic below to have suffix-based name resolution
-- make use of _terms_ from the local file.
local (\e -> e {names = Names.push locals namesStart}) do
-- declarations.
local (\e -> e {names = Names.shadowing (UF.names env) namesStart, maybeNamespace}) do
names <- asks names
stanzas <- do
unNamespacedStanzas0 <- sepBy semi stanza
let unNamespacedStanzas = fmap (TermParser.substImports names imports) <$> unNamespacedStanzas0
pure $
unNamespacedStanzas
& case maybeNamespace of
& case maybeNamespaceVar of
Nothing -> id
Just namespace ->
let unNamespacedTermNamespaceNames :: Set v
Expand Down Expand Up @@ -155,27 +149,12 @@ file = do
-- [foo.alice, bar.alice, zonk.bob]
fqLocalTerms :: [v]
fqLocalTerms = (stanzas >>= getVars) <> (view _1 <$> accessors)
-- suffixified local term bindings shadow any same-named thing from the outer codebase scope
-- example: `foo.bar` in local file scope will shadow `foo.bar` and `bar` in codebase scope
let (curNames, resolveLocals) =
( Names.shadowTerms locals names,
resolveLocals
)
where
-- Each unique suffix mapped to its fully qualified name
canonicalVars :: Map v v
canonicalVars = UFN.variableCanonicalizer fqLocalTerms

-- All unique local term name suffixes - these we want to
-- avoid resolving to a term that's in the codebase
locals :: [Name.Name]
locals = (Name.unsafeParseVar <$> Map.keys canonicalVars)

-- A function to replace unique local term suffixes with their
-- fully qualified name
replacements = [(v, Term.var () v2) | (v, v2) <- Map.toList canonicalVars, v /= v2]
resolveLocals = ABT.substsInheritAnnotation replacements
let bindNames = Term.bindSomeNames Name.unsafeParseVar (Set.fromList fqLocalTerms) curNames . resolveLocals
let bindNames =
Term.bindNames
Name.unsafeParseVar
Name.toVar
(Set.fromList fqLocalTerms)
(Names.shadowTerms (map Name.unsafeParseVar fqLocalTerms) names)
terms <- case List.validate (traverseOf _3 bindNames) terms of
Left es -> resolutionFailures (toList es)
Right terms -> pure terms
Expand Down
Loading

0 comments on commit 7d7df0e

Please sign in to comment.