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 22 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
10 changes: 5 additions & 5 deletions codebase2/codebase-sqlite/U/Codebase/Sqlite/Queries.hs
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ 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)
import Unison.NameSegment (NameSegment (NameSegment))
import Unison.NameSegment qualified as NameSegment
import Unison.Prelude
import Unison.Sqlite
Expand Down Expand Up @@ -658,7 +658,7 @@ saveNameSegment =

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

saveHashObject :: HashId -> ObjectId -> HashVersion -> Transaction ()
saveHashObject hId oId version =
Expand Down Expand Up @@ -4243,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 @@ -4252,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
82 changes: 31 additions & 51 deletions codebase2/core/Unison/NameSegment.hs
Original file line number Diff line number Diff line change
@@ -1,77 +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)

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

instance Show NameSegment where
show = show . toUnescapedText
instance IsString NameSegment where
fromString =
NameSegment . Text.pack

-- | Convert a text to a name segment, when the text is known to be a valid name segment.
--
-- For example, to make a name segment containing the text ".~", use @unsafeFromUnescapedText ".~"@, even if that
-- operator would need to be escaped (e.g. "`.~`") when written by a user.
unsafeFromUnescapedText :: Text -> NameSegment
unsafeFromUnescapedText =
UnsafeNameSegment
instance Show NameSegment where
show =
Text.unpack . toUnescapedText

-- | Convert a name segment to unescaped text.
--
-- 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

-- 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:
--
-- 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 =
coerce Text.null

isPrefixOf :: NameSegment -> NameSegment -> Bool
isPrefixOf =
coerce Text.isPrefixOf

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

docSegment :: NameSegment
docSegment =
"doc"

libSegment :: NameSegment
libSegment =
unsafeFromUnescapedText "lib"
"lib"
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
13 changes: 5 additions & 8 deletions parser-typechecker/src/Unison/Codebase/Execute.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PartialTypeSignatures #-}

-- | Execute a computation of type '{IO} () that has been previously added to
-- the codebase, without setting up an interactive environment.
--
Expand All @@ -20,14 +16,15 @@ import Unison.Codebase.Runtime (Runtime)
import Unison.Codebase.Runtime qualified as Runtime
import Unison.Names qualified as Names
import Unison.Parser.Ann (Ann)
import Unison.Prelude
import Unison.PrettyPrintEnv qualified as PPE
import Unison.Symbol (Symbol)
import Unison.Util.Pretty qualified as P

execute ::
Codebase.Codebase IO Symbol Ann ->
Runtime Symbol ->
String ->
Text ->
IO (Either Runtime.Error ())
execute codebase runtime mainName =
(`finally` Runtime.terminate runtime) . runExceptT $ do
Expand All @@ -37,9 +34,9 @@ execute codebase runtime mainName =
let mainType = Runtime.mainType runtime
mt <- liftIO $ Codebase.runTransaction codebase $ getMainTerm loadTypeOfTerm parseNames mainName mainType
case mt of
MainTerm.NotAFunctionName s -> throwError ("Not a function name: " <> P.string s)
MainTerm.NotFound s -> throwError ("Not found: " <> P.string s)
MainTerm.BadType s _ -> throwError (P.string s <> " is not of type '{IO} ()")
MainTerm.NotAFunctionName s -> throwError ("Not a function name: " <> P.text s)
MainTerm.NotFound s -> throwError ("Not found: " <> P.text s)
MainTerm.BadType s _ -> throwError (P.text s <> " is not of type '{IO} ()")
MainTerm.Success _ tm _ -> do
let codeLookup = Codebase.toCodeLookup codebase
ppe = PPE.empty
Expand Down
12 changes: 6 additions & 6 deletions parser-typechecker/src/Unison/Codebase/MainTerm.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Unison.Parser.Ann qualified as Parser.Ann
import Unison.Prelude
import Unison.Reference (Reference)
import Unison.Referent qualified as Referent
import Unison.Syntax.HashQualified qualified as HQ (fromString)
import Unison.Syntax.HashQualified qualified as HQ (parseText)
import Unison.Term (Term)
import Unison.Term qualified as Term
import Unison.Type (Type)
Expand All @@ -26,20 +26,20 @@ import Unison.Var (Var)
import Unison.Var qualified as Var

data MainTerm v
= NotAFunctionName String
| NotFound String
| BadType String (Maybe (Type v Ann))
= NotAFunctionName Text
| NotFound Text
| BadType Text (Maybe (Type v Ann))
| Success (HQ.HashQualified Name) (Term v Ann) (Type v Ann)

getMainTerm ::
(Monad m, Var v) =>
(Reference -> m (Maybe (Type v Ann))) ->
Names.Names ->
String ->
Text ->
Type.Type v Ann ->
m (MainTerm v)
getMainTerm loadTypeOfTerm parseNames mainName mainType =
case HQ.fromString mainName of
case HQ.parseText mainName of
Nothing -> pure (NotAFunctionName mainName)
Just hq -> do
let refs = Names.lookupHQTerm Names.IncludeSuffixes hq parseNames
Expand Down
30 changes: 15 additions & 15 deletions parser-typechecker/src/Unison/Codebase/Path.hs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ module Unison.Codebase.Path
fromName,
fromName',
fromPath',
fromText,
fromText',
unsafeParseText,
unsafeParseText',
toAbsoluteSplit,
toSplit',
toList,
Expand Down Expand Up @@ -93,7 +93,7 @@ import Unison.Name (Convert (..), Name, Parse)
import Unison.Name qualified as Name
import Unison.NameSegment (NameSegment)
import Unison.Prelude hiding (empty, toList)
import Unison.Syntax.Name qualified as Name (toText, unsafeFromText)
import Unison.Syntax.Name qualified as Name (toText, unsafeParseText)
import Unison.Util.List qualified as List

-- `Foo.Bar.baz` becomes ["Foo", "Bar", "baz"]
Expand Down Expand Up @@ -311,11 +311,13 @@ fromName' n
path = fromName n

unsafeToName :: Path -> Name
unsafeToName = Name.unsafeFromText . toText
unsafeToName =
fromMaybe (error "empty path") . toName

-- | Convert a Path' to a Name
unsafeToName' :: Path' -> Name
unsafeToName' = Name.unsafeFromText . toText'
unsafeToName' =
fromMaybe (error "empty path") . toName'

toName :: Path -> Maybe Name
toName = \case
Expand Down Expand Up @@ -348,15 +350,13 @@ instance Show Path where

-- | Note: This treats the path as relative.
toText :: Path -> Text
toText path =
case toName path of
Nothing -> "."
Just name -> Name.toText name
toText =
maybe Text.empty Name.toText . toName

fromText :: Text -> Path
fromText = \case
unsafeParseText :: Text -> Path
unsafeParseText = \case
"" -> empty
text -> fromName (Name.unsafeFromText text)
text -> fromName (Name.unsafeParseText text)

-- | Construct a Path' from a text
--
Expand All @@ -368,11 +368,11 @@ fromText = \case
--
-- >>> show $ fromText' ""
-- ""
fromText' :: Text -> Path'
fromText' = \case
unsafeParseText' :: Text -> Path'
unsafeParseText' = \case
"" -> RelativePath' (Relative mempty)
"." -> AbsolutePath' (Absolute mempty)
text -> fromName' (Name.unsafeFromText text)
text -> fromName' (Name.unsafeParseText text)

toText' :: Path' -> Text
toText' path =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import Unison.Reference qualified as Reference
import Unison.Referent (Referent)
import Unison.Referent qualified as Referent
import Unison.Result qualified as Result
import Unison.Syntax.Var qualified as Var (namespaced)
import Unison.Term qualified as Term
import Unison.Type qualified as Type
import Unison.Typechecker qualified as Typechecker
Expand Down Expand Up @@ -83,7 +84,7 @@ hashFieldAccessors ::
)
hashFieldAccessors ppe declName vars declRef dd = do
let accessors :: [(v, (), Term.Term v ())]
accessors = DD.generateRecordAccessors mempty (map (,()) vars) declName declRef
accessors = DD.generateRecordAccessors Var.namespaced mempty (map (,()) vars) declName declRef
let typeLookup :: TypeLookup v ()
typeLookup =
TypeLookup
Expand Down
Loading
Loading