Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backticky symbol parsing #3525

Merged
merged 50 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
4fda3cc
delete unused Backticks lexeme
mitchellwrosen Oct 19, 2022
90f515e
Require backticks to parse a symbol with a "." anywhere in it
mitchellwrosen Oct 19, 2022
9cea1f7
move some lexers to the top level
mitchellwrosen Oct 19, 2022
6420602
begin fixing type errors
mitchellwrosen Oct 20, 2022
05b3cd5
⅄ 22-10-19-syntax-name → 22-10-18-backticky-parser
mitchellwrosen Nov 15, 2022
41b9894
⅄ trunk → 22-10-18-backticky-parser
mitchellwrosen Dec 21, 2022
c873ddf
⅄ trunk → 22-10-18-backticky-parser
mitchellwrosen Jan 17, 2024
d679b4d
remove unused prisms
mitchellwrosen Jan 17, 2024
8862951
begin building out a Unison.Syntax.NameSegment module
mitchellwrosen Jan 18, 2024
dd6c0d6
fix a bug in identifier parser
mitchellwrosen Jan 18, 2024
768df76
extract name parser out to share among lexer and path parser
mitchellwrosen Jan 18, 2024
81e4ebe
begin unifying name and path parsers
mitchellwrosen Jan 18, 2024
3677c6b
use name parser in parseSplit'
mitchellwrosen Jan 18, 2024
51b650b
unify name and path parsers
mitchellwrosen Jan 19, 2024
8871927
more path, name, and name segment work (doesn't build yet)
mitchellwrosen Jan 24, 2024
e4a2080
wip
mitchellwrosen Jan 26, 2024
374a641
more NameSegment to/from text
mitchellwrosen Jan 29, 2024
186843b
fix compiler errors in tests
mitchellwrosen Jan 30, 2024
acce2ea
⅄ trunk → 22-10-18-backticky-parser
mitchellwrosen Jan 30, 2024
80b528d
add export list to Unison.NameSegment
mitchellwrosen Jan 30, 2024
ab361b6
delete NameSegment.segments', implement Var.universallyQuantifyIfFree…
mitchellwrosen Jan 31, 2024
9299a19
remove NameSegment.reverseSegments'
mitchellwrosen Jan 31, 2024
7f93853
add instance IsString NameSegment
mitchellwrosen Jan 31, 2024
07078e9
UnsafeNameSegment -> NameSegment
mitchellwrosen Jan 31, 2024
914e367
implement NameSegment.toEscapedText
mitchellwrosen Jan 31, 2024
0504bca
⅄ trunk → 22-10-18-backticky-parser
mitchellwrosen Jan 31, 2024
3044255
sytax work
mitchellwrosen Feb 1, 2024
fb3104d
delete a couple unused imports
mitchellwrosen Feb 1, 2024
9799b4f
fix and move Var.namespaced
mitchellwrosen Feb 1, 2024
96ca5c7
⅄ trunk → 22-10-18-backticky-parser
mitchellwrosen Feb 1, 2024
17f7067
lexer fix
mitchellwrosen Feb 2, 2024
cf15f30
⅄ trunk → 22-10-18-backticky-parser
mitchellwrosen Feb 2, 2024
3f3860f
bugfix: term printer put too many use statements
mitchellwrosen Feb 2, 2024
609c47b
bugfix: Path.toText rendered an empty path as ".", not ""
mitchellwrosen Feb 2, 2024
34cc9c8
fix "." parsing in term parser
mitchellwrosen Feb 3, 2024
aa21079
⅄ trunk → 22-10-18-backticky-parser
mitchellwrosen Feb 20, 2024
fd74c51
commit transcript diff that fixes forall display bug
mitchellwrosen Feb 20, 2024
08ae88c
fix ancient bug in the local ui that reared its head at last
mitchellwrosen Feb 20, 2024
64757ef
fix another old-bug-rearing-head situation
mitchellwrosen Feb 21, 2024
ed88158
fix a few things, but oops completion is broken somehow
mitchellwrosen Feb 21, 2024
12a75f1
partially fix tab-completion
mitchellwrosen Feb 22, 2024
e31aba4
fix tab completion
mitchellwrosen Feb 22, 2024
d34522e
allow () escaped in backticks
mitchellwrosen Feb 22, 2024
19070ce
regenerate all-base-hashes output
mitchellwrosen Feb 22, 2024
5330261
regenerate serial-test-00 output
mitchellwrosen Feb 22, 2024
c614841
make deleteReplacements transcript work
mitchellwrosen Feb 22, 2024
d8a9f3e
⅄ trunk → 22-10-18-backticky-parser
mitchellwrosen Feb 23, 2024
5cb5469
allow reserved things between backticks
mitchellwrosen Feb 23, 2024
179e131
add transcript
mitchellwrosen Feb 26, 2024
581e2e1
add transcript
mitchellwrosen Feb 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ verifyDeclFormatHash (ComponentHash hash) (DeclFormat.Decl (DeclFormat.LocallyIn
& Map.toList
& fmap (\(_refId, (v, decl, ())) -> (v, either H2.toDataDecl id $ H2.v2ToH2Decl decl))
& Map.fromList
& H2.hashDecls Name.unsafeFromVar
& H2.hashDecls Name.unsafeParseVar
& \case
Left _err -> Just HH.DeclHashResolutionFailure
Right m ->
Expand Down
28 changes: 12 additions & 16 deletions codebase2/codebase-sqlite/U/Codebase/Sqlite/Operations.hs
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,7 @@ import U.Util.Base32Hex qualified as Base32Hex
import U.Util.Serialization qualified as S
import Unison.Hash qualified as H
import Unison.Hash32 qualified as Hash32
import Unison.NameSegment (NameSegment (NameSegment))
import Unison.NameSegment qualified as NameSegment
import Unison.NameSegment (NameSegment)
import Unison.Prelude
import Unison.ShortHash (ShortCausalHash (..), ShortNamespaceHash (..))
import Unison.Sqlite
Expand Down Expand Up @@ -577,7 +576,7 @@ s2cBranch (S.Branch.Full.Branch tms tps patches children) =
Transaction (Map NameSegment (Map C.Referent (Transaction C.Branch.MdValues)))
doTerms =
Map.bitraverse
(fmap NameSegment . Q.expectText)
Q.expectNameSegment
( Map.bitraverse s2cReferent \case
S.MetadataSet.Inline rs ->
pure $ C.Branch.MdValues <$> loadTypesForMetadata rs
Expand All @@ -587,22 +586,22 @@ s2cBranch (S.Branch.Full.Branch tms tps patches children) =
Transaction (Map NameSegment (Map C.Reference (Transaction C.Branch.MdValues)))
doTypes =
Map.bitraverse
(fmap NameSegment . Q.expectText)
Q.expectNameSegment
( Map.bitraverse s2cReference \case
S.MetadataSet.Inline rs ->
pure $ C.Branch.MdValues <$> loadTypesForMetadata rs
)
doPatches ::
Map Db.TextId Db.PatchObjectId ->
Transaction (Map NameSegment (PatchHash, Transaction C.Branch.Patch))
doPatches = Map.bitraverse (fmap NameSegment . Q.expectText) \patchId -> do
doPatches = Map.bitraverse Q.expectNameSegment \patchId -> do
h <- PatchHash <$> (Q.expectPrimaryHashByObjectId . Db.unPatchObjectId) patchId
pure (h, expectPatch patchId)

doChildren ::
Map Db.TextId (Db.BranchObjectId, Db.CausalHashId) ->
Transaction (Map NameSegment (C.Branch.CausalBranch Transaction))
doChildren = Map.bitraverse (fmap NameSegment . Q.expectText) \(boId, chId) ->
doChildren = Map.bitraverse Q.expectNameSegment \(boId, chId) ->
C.Causal
<$> Q.expectCausalHash chId
<*> expectValueHashByCausalHashId chId
Expand Down Expand Up @@ -718,15 +717,15 @@ saveNamespace hh bhId me = do
c2sBranch :: BranchV Transaction -> Transaction DbBranchV
c2sBranch = \case
BranchV2 branch -> do
terms <- Map.bitraverse saveNameSegment (Map.bitraverse c2sReferent c2sMetadata) (branch ^. #terms)
types <- Map.bitraverse saveNameSegment (Map.bitraverse c2sReference c2sMetadata) (branch ^. #types)
patches <- Map.bitraverse saveNameSegment savePatchObjectId (branch ^. #patches)
children <- Map.bitraverse saveNameSegment (saveBranch hh) (branch ^. #children)
terms <- Map.bitraverse Q.saveNameSegment (Map.bitraverse c2sReferent c2sMetadata) (branch ^. #terms)
types <- Map.bitraverse Q.saveNameSegment (Map.bitraverse c2sReference c2sMetadata) (branch ^. #types)
patches <- Map.bitraverse Q.saveNameSegment savePatchObjectId (branch ^. #patches)
children <- Map.bitraverse Q.saveNameSegment (saveBranch hh) (branch ^. #children)
pure (DbBranchV2 S.Branch {terms, types, patches, children})
BranchV3 branch -> do
children <- Map.bitraverse saveNameSegment (saveBranchV3 hh) (branch ^. #children)
terms <- Map.bitraverse saveNameSegment c2sReferent (branch ^. #terms)
types <- Map.bitraverse saveNameSegment c2sReference (branch ^. #types)
children <- Map.bitraverse Q.saveNameSegment (saveBranchV3 hh) (branch ^. #children)
terms <- Map.bitraverse Q.saveNameSegment c2sReferent (branch ^. #terms)
types <- Map.bitraverse Q.saveNameSegment c2sReference (branch ^. #types)
pure (DbBranchV3 S.BranchV3 {children, terms, types})

c2sMetadata :: Transaction C.Branch.MdValues -> Transaction S.Branch.Full.DbMetadataSet
Expand All @@ -740,9 +739,6 @@ saveNamespace hh bhId me = do
patch <- mp
savePatch hh h patch

saveNameSegment :: NameSegment -> Transaction Db.TextId
saveNameSegment = Q.saveText . NameSegment.toText

-- Save just the causal object (i.e. the `causal` row and its associated `causal_parents`). Internal helper shared by
-- `saveBranch` and `saveBranchV3`.
saveCausalObject ::
Expand Down
20 changes: 17 additions & 3 deletions codebase2/codebase-sqlite/U/Codebase/Sqlite/Queries.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ module U.Codebase.Sqlite.Queries
expectText,
expectTextCheck,

-- ** name segments
saveNameSegment,
expectNameSegment,

-- * hash table
saveHash,
saveHashes,
Expand Down Expand Up @@ -389,6 +393,8 @@ import Unison.Hash qualified as Hash
import Unison.Hash32 (Hash32)
import Unison.Hash32 qualified as Hash32
import Unison.Hash32.Orphans.Sqlite ()
import Unison.NameSegment (NameSegment (NameSegment))
import Unison.NameSegment qualified as NameSegment
import Unison.Prelude
import Unison.Sqlite
import Unison.Util.Alternative qualified as Alternative
Expand Down Expand Up @@ -646,6 +652,14 @@ loadTextSql h =
WHERE id = :h
|]

saveNameSegment :: NameSegment -> Transaction TextId
saveNameSegment =
saveText . NameSegment.toUnescapedText

expectNameSegment :: TextId -> Transaction NameSegment
expectNameSegment =
fmap NameSegment . expectText

saveHashObject :: HashId -> ObjectId -> HashVersion -> Transaction ()
saveHashObject hId oId version =
execute
Expand Down Expand Up @@ -4229,7 +4243,7 @@ data JsonParseFailure = JsonParseFailure
deriving anyclass (SqliteExceptionReason)

-- | Get the most recent namespace the user has visited.
expectMostRecentNamespace :: Transaction [Text]
expectMostRecentNamespace :: Transaction [NameSegment]
expectMostRecentNamespace =
queryOneColCheck
[sql|
Expand All @@ -4238,11 +4252,11 @@ expectMostRecentNamespace =
|]
check
where
check :: Text -> Either JsonParseFailure [Text]
check :: Text -> Either JsonParseFailure [NameSegment]
check bytes =
case Aeson.eitherDecodeStrict (Text.encodeUtf8 bytes) of
Left failure -> Left JsonParseFailure {bytes, failure = Text.pack failure}
Right namespace -> Right namespace
Right namespace -> Right (map NameSegment namespace)

-- | Set the most recent namespace the user has visited.
setMostRecentNamespace :: [Text] -> Transaction ()
Expand Down
94 changes: 44 additions & 50 deletions codebase2/core/Unison/NameSegment.hs
Original file line number Diff line number Diff line change
@@ -1,63 +1,57 @@
module Unison.NameSegment where
module Unison.NameSegment
( NameSegment (..),
toUnescapedText,
isPrefixOf,

-- * Sentinel name segments
defaultPatchSegment,
docSegment,
libSegment,
)
where

import Data.Text qualified as Text
import Data.Text.Lazy.Builder qualified as Text (Builder)
import Data.Text.Lazy.Builder qualified as Text.Builder
import Unison.Prelude
import Unison.Util.Alphabetical (Alphabetical, compareAlphabetical)
import Unison.Util.Alphabetical (Alphabetical)

-- Represents the parts of a name between the `.`s
newtype NameSegment = NameSegment {toText :: Text}
newtype NameSegment
= NameSegment Text
deriving stock (Eq, Ord, Generic)
deriving newtype (Alphabetical)

instance Alphabetical NameSegment where
compareAlphabetical n1 n2 = compareAlphabetical (toText n1) (toText n2)

-- Split text into segments. A smarter version of `Text.splitOn` that handles
-- the name `.` properly.
segments' :: Text -> [Text]
segments' n = go split
where
split = Text.splitOn "." n
go [] = []
go ("" : "" : z) = "." : go z
go ("" : z) = go z
go (x : y) = x : go y

-- Same as reverse . segments', but produces the output as a
-- lazy list, suitable for suffix-based ordering purposes or
-- building suffix tries. Examples:
instance IsString NameSegment where
fromString =
NameSegment . Text.pack

instance Show NameSegment where
show =
Text.unpack . toUnescapedText

-- | Convert a name segment to unescaped text.
--
-- reverseSegments' "foo.bar.baz" => ["baz","bar","foo"]
-- reverseSegments' ".foo.bar.baz" => ["baz","bar","foo"]
-- reverseSegments' ".." => ["."]
-- reverseSegments' "Nat.++" => ["++","Nat"]
-- reverseSegments' "Nat.++.zoo" => ["zoo","++","Nat"]
reverseSegments' :: Text -> [Text]
reverseSegments' = go
where
go "" = []
go t =
let seg0 = Text.takeWhileEnd (/= '.') t
seg = if Text.null seg0 then Text.takeEnd 1 t else seg0
rem = Text.dropEnd (Text.length seg + 1) t
in seg : go rem

isEmpty :: NameSegment -> Bool
isEmpty ns = toText ns == mempty
-- You might use this when storing a name segment as text in a database, where the literal name segment bytes are all
-- that matter. However, you wouldn't use this to display the name segment to a user - that depends on concrete syntax.
-- See Unison.Syntax.NameSegment (or indeed, some actual yet-built interface that abstracts concrete syntax) for that
-- kind of function.
--
-- > toUnescapedText (unsafeFromText ".~") = ".~"
toUnescapedText :: NameSegment -> Text
toUnescapedText =
coerce

isPrefixOf :: NameSegment -> NameSegment -> Bool
isPrefixOf n1 n2 = Text.isPrefixOf (toText n1) (toText n2)

toString :: NameSegment -> String
toString = Text.unpack . toText
isPrefixOf =
coerce Text.isPrefixOf

toTextBuilder :: NameSegment -> Text.Builder
toTextBuilder =
coerce Text.Builder.fromText
defaultPatchSegment :: NameSegment
defaultPatchSegment =
"patch"

instance IsString NameSegment where
fromString = NameSegment . Text.pack
docSegment :: NameSegment
docSegment =
"doc"

instance Show NameSegment where
show = show . toText
libSegment :: NameSegment
libSegment =
"lib"
2 changes: 0 additions & 2 deletions codebase2/core/Unison/ShortHash.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

module Unison.ShortHash
Expand Down
2 changes: 1 addition & 1 deletion parser-typechecker/src/U/Codebase/Projects.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import U.Codebase.Causal qualified as Causal
import U.Codebase.HashTags (BranchHash (..))
import Unison.Codebase.Path
import Unison.Codebase.Path qualified as Path
import Unison.Name (libSegment)
import Unison.NameSegment (libSegment)
import Unison.Prelude
import Unison.Sqlite qualified as Sqlite
import Unison.Util.Monoid (ifoldMapM)
Expand Down
14 changes: 7 additions & 7 deletions parser-typechecker/src/Unison/Builtin.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import Unison.Prelude
import Unison.Reference qualified as R
import Unison.Referent qualified as Referent
import Unison.Symbol (Symbol)
import Unison.Syntax.Name qualified as Name (unsafeFromText, unsafeFromVar)
import Unison.Syntax.Name qualified as Name (unsafeParseText, unsafeParseVar)
import Unison.Type qualified as Type
import Unison.Typechecker.TypeLookup qualified as TL
import Unison.Util.Relation qualified as Rel
Expand All @@ -56,24 +56,24 @@ names = Names terms types
terms =
Rel.mapRan Referent.Ref (Rel.fromMap termNameRefs)
<> Rel.fromList
[ (Name.unsafeFromVar vc, Referent.Con (ConstructorReference (R.DerivedId r) cid) ct)
[ (Name.unsafeParseVar vc, Referent.Con (ConstructorReference (R.DerivedId r) cid) ct)
| (ct, (_, (r, decl))) <-
((CT.Data,) <$> builtinDataDecls)
<> ((CT.Effect,) . (second . second) DD.toDataDecl <$> builtinEffectDecls),
((_, vc, _), cid) <- DD.constructors' decl `zip` [0 ..]
]
<> Rel.fromList
[ (Name.unsafeFromVar v, Referent.Ref (R.DerivedId i))
[ (Name.unsafeParseVar v, Referent.Ref (R.DerivedId i))
| (v, i) <- Map.toList TD.builtinTermsRef
]
types =
Rel.fromList builtinTypes
<> Rel.fromList
[ (Name.unsafeFromVar v, R.DerivedId r)
[ (Name.unsafeParseVar v, R.DerivedId r)
| (v, (r, _)) <- builtinDataDecls
]
<> Rel.fromList
[ (Name.unsafeFromVar v, R.DerivedId r)
[ (Name.unsafeParseVar v, R.DerivedId r)
| (v, (r, _)) <- builtinEffectDecls
]

Expand Down Expand Up @@ -147,7 +147,7 @@ builtinTypeDependentsOfComponent h0 = Rel.searchRan ord builtinDependencies
-- if we decide to change their names.
builtinTypes :: [(Name, R.Reference)]
builtinTypes =
Map.toList . Map.mapKeys Name.unsafeFromText $
Map.toList . Map.mapKeys Name.unsafeParseText $
foldl' go mempty builtinTypesSrc
where
go m = \case
Expand Down Expand Up @@ -286,7 +286,7 @@ instance Show BuiltinDSL where
show _ = ""

termNameRefs :: Map Name R.Reference
termNameRefs = Map.mapKeys Name.unsafeFromText $ foldl' go mempty (stripVersion builtinsSrc)
termNameRefs = Map.mapKeys Name.unsafeParseText $ foldl' go mempty (stripVersion builtinsSrc)
where
go m = \case
B r _tp -> Map.insert r (R.Builtin r) m
Expand Down
7 changes: 4 additions & 3 deletions parser-typechecker/src/Unison/Codebase/Branch.hs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ import Unison.Hashing.V2.Convert qualified as H
import Unison.Name (Name)
import Unison.Name qualified as Name
import Unison.NameSegment (NameSegment)
import Unison.NameSegment qualified as NameSegment
import Unison.Prelude hiding (empty)
import Unison.Reference (TermReference, TypeReference)
import Unison.Referent (Referent)
Expand Down Expand Up @@ -151,7 +152,7 @@ withoutLib Branch0 {..} =
_children
& imapMaybe
( \nameSegment child ->
if nameSegment == Name.libSegment
if nameSegment == NameSegment.libSegment
then Nothing
else Just (child & head_ %~ withoutLib)
)
Expand All @@ -165,7 +166,7 @@ withoutTransitiveLibs Branch0 {..} =
_children
& imapMaybe
( \nameSegment child ->
if nameSegment == Name.libSegment
if nameSegment == NameSegment.libSegment
then Just (child & head_ %~ withoutLib)
else Just (child & head_ %~ withoutTransitiveLibs)
)
Expand Down Expand Up @@ -348,7 +349,7 @@ deepChildrenHelper (reversePrefix, libDepth, b0) = do
pure
if isShallowDependency || isUnseenNamespace
then
let libDepth' = if ns == "lib" then libDepth + 1 else libDepth
let libDepth' = if ns == NameSegment.libSegment then libDepth + 1 else libDepth
in Seq.singleton (ns : reversePrefix, libDepth', head b)
else Seq.empty
State.modify' (Set.insert h)
Expand Down
3 changes: 2 additions & 1 deletion parser-typechecker/src/Unison/Codebase/Editor/RemoteRepo.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Unison.Prelude
import Unison.Project (ProjectAndBranch (..), ProjectBranchName, ProjectName)
import Unison.Share.Types
import Unison.Util.Monoid qualified as Monoid
import qualified Unison.NameSegment as NameSegment

data ReadRepo
= ReadRepoGit ReadGitRepo
Expand Down Expand Up @@ -131,7 +132,7 @@ data ReadShareLooseCode = ReadShareLooseCode
isPublic :: ReadShareLooseCode -> Bool
isPublic ReadShareLooseCode {path} =
case path of
("public" Path.:< _) -> True
((NameSegment.toUnescapedText -> "public") Path.:< _) -> True
_ -> False

data WriteRemoteNamespace a
Expand Down
Loading
Loading