mirror of
https://github.com/unisonweb/unison.git
synced 2024-08-15 13:30:27 +03:00
Merge branch 'trunk' into cp/project-root
# Conflicts: # unison-cli-integration/integration-tests/IntegrationTests/transcript.output.md # unison-src/transcripts-round-trip/main.output.md # unison-src/transcripts/add-run.output.md # unison-src/transcripts/bug-strange-closure.output.md # unison-src/transcripts/cycle-update-5.output.md # unison-src/transcripts/delete.output.md # unison-src/transcripts/diff-namespace.output.md # unison-src/transcripts/move-namespace.output.md # unison-src/transcripts/name-selection.output.md # unison-src/transcripts/names.output.md # unison-src/transcripts/namespace-dependencies.output.md # unison-src/transcripts/propagate.output.md # unison-src/transcripts/reflog.output.md # unison-src/transcripts/reset.output.md # unison-src/transcripts/tab-completion.output.md # unison-src/transcripts/transcript-parser-commands.output.md
This commit is contained in:
commit
0cd3cd1cff
@ -178,6 +178,7 @@ invertDomain =
|
||||
g x acc y =
|
||||
Map.insert y x acc
|
||||
|
||||
-- | Construct a left-unique relation from a mapping from its right-elements to its left-elements.
|
||||
fromRange :: (Ord a, Ord b) => Map b a -> BiMultimap a b
|
||||
fromRange m =
|
||||
BiMultimap (Map.foldlWithKey' f Map.empty m) m
|
||||
|
@ -139,6 +139,7 @@ import Unison.NameSegment (NameSegment)
|
||||
import Unison.NameSegment qualified as NameSegment
|
||||
import Unison.Prelude hiding (empty)
|
||||
import Unison.Reference (TermReference, TermReferenceId, TypeReference, TypeReferenceId)
|
||||
import Unison.Reference qualified as Reference
|
||||
import Unison.Referent (Referent)
|
||||
import Unison.Referent qualified as Referent
|
||||
import Unison.Util.List qualified as List
|
||||
@ -148,7 +149,6 @@ import Unison.Util.Set qualified as Set
|
||||
import Unison.Util.Star2 qualified as Star2
|
||||
import Witherable (FilterableWithIndex (imapMaybe))
|
||||
import Prelude hiding (head, read, subtract)
|
||||
import qualified Unison.Reference as Reference
|
||||
|
||||
instance AsEmpty (Branch m) where
|
||||
_Empty = prism' (const empty) matchEmpty
|
||||
@ -215,7 +215,6 @@ deepTypeReferenceIds :: Branch0 m -> Set TypeReferenceId
|
||||
deepTypeReferenceIds =
|
||||
Set.mapMaybe Reference.toId . deepTypeReferences
|
||||
|
||||
|
||||
namespaceStats :: Branch0 m -> NamespaceStats
|
||||
namespaceStats b =
|
||||
NamespaceStats
|
||||
|
@ -1,7 +1,7 @@
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
|
||||
module Unison.Codebase.Causal
|
||||
( Causal (currentHash, head, tail, tails),
|
||||
( Causal (currentHash, valueHash, head, tail, tails),
|
||||
pattern One,
|
||||
pattern Cons,
|
||||
pattern Merge,
|
||||
@ -40,7 +40,8 @@ import Unison.Codebase.Causal.Type
|
||||
currentHash,
|
||||
head,
|
||||
tail,
|
||||
tails
|
||||
tails,
|
||||
valueHash
|
||||
),
|
||||
before,
|
||||
lca,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Integration test: transcript
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
use lib.builtins
|
||||
|
||||
unique type MyBool = MyTrue | MyFalse
|
||||
@ -27,7 +27,7 @@ main = do
|
||||
_ -> ()
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -43,7 +43,7 @@ main = do
|
||||
resume : Request {g, Break} x -> x
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -19,6 +19,7 @@ dependencies:
|
||||
- base
|
||||
- bytes
|
||||
- bytestring
|
||||
- cmark
|
||||
- co-log-core
|
||||
- code-page
|
||||
- concurrent-output
|
||||
|
@ -9,6 +9,9 @@ module Unison.Codebase.Editor.HandleInput.Merge2
|
||||
LcaMergeInfo (..),
|
||||
doMerge,
|
||||
doMergeLocalBranch,
|
||||
|
||||
-- * API exported for @todo@
|
||||
hasDefnsInLib,
|
||||
)
|
||||
where
|
||||
|
||||
@ -241,11 +244,7 @@ doMerge info = do
|
||||
|
||||
-- Assert that neither Alice nor Bob have defns in lib
|
||||
for_ [(mergeTarget, branches.alice), (mergeSource, branches.bob)] \(who, branch) -> do
|
||||
libdeps <-
|
||||
case Map.lookup NameSegment.libSegment branch.children of
|
||||
Nothing -> pure V2.Branch.empty
|
||||
Just libdeps -> Cli.runTransaction libdeps.value
|
||||
when (not (Map.null libdeps.terms) || not (Map.null libdeps.types)) do
|
||||
whenM (Cli.runTransaction (hasDefnsInLib branch)) do
|
||||
done (Output.MergeDefnsInLib who)
|
||||
|
||||
-- Load Alice/Bob/LCA definitions and decl name lookups
|
||||
@ -487,6 +486,17 @@ loadLibdeps branches = do
|
||||
libdepsBranch <- libdepsCausal.value
|
||||
pure libdepsBranch.children
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
-- Merge precondition violation checks
|
||||
|
||||
hasDefnsInLib :: Applicative m => V2.Branch m -> m Bool
|
||||
hasDefnsInLib branch = do
|
||||
libdeps <-
|
||||
case Map.lookup NameSegment.libSegment branch.children of
|
||||
Nothing -> pure V2.Branch.empty
|
||||
Just libdeps -> libdeps.value
|
||||
pure (not (Map.null libdeps.terms) || not (Map.null libdeps.types))
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
-- Creating Unison files
|
||||
|
||||
|
@ -4,7 +4,9 @@ module Unison.Codebase.Editor.HandleInput.Todo
|
||||
)
|
||||
where
|
||||
|
||||
import Data.Either qualified as Either
|
||||
import Data.Set qualified as Set
|
||||
import U.Codebase.HashTags (BranchHash (..))
|
||||
import U.Codebase.Sqlite.Operations qualified as Operations
|
||||
import Unison.Builtin qualified as Builtin
|
||||
import Unison.Cli.Monad (Cli)
|
||||
@ -14,7 +16,11 @@ import Unison.Cli.PrettyPrintUtils qualified as Cli
|
||||
import Unison.Codebase qualified as Codebase
|
||||
import Unison.Codebase.Branch qualified as Branch
|
||||
import Unison.Codebase.Branch.Names qualified as Branch
|
||||
import Unison.Codebase.Causal qualified as Causal
|
||||
import Unison.Codebase.Editor.HandleInput.Merge2 (hasDefnsInLib)
|
||||
import Unison.Codebase.Editor.Output
|
||||
import Unison.Hash (HashFor (..))
|
||||
import Unison.Merge.DeclCoherencyCheck (IncoherentDeclReasons (..), checkAllDeclCoherency)
|
||||
import Unison.Names qualified as Names
|
||||
import Unison.Prelude
|
||||
import Unison.Reference (TermReference)
|
||||
@ -26,11 +32,22 @@ handleTodo :: Cli ()
|
||||
handleTodo = do
|
||||
-- For now, we don't go through any great trouble to seek out the root of the project branch. Just assume the current
|
||||
-- namespace is the root, which will be the case unless the user uses `deprecated.cd`.
|
||||
currentNamespace <- Cli.getCurrentBranch0
|
||||
currentCausal <- Cli.getCurrentBranch
|
||||
let currentNamespace = Branch.head currentCausal
|
||||
let currentNamespaceWithoutLibdeps = Branch.deleteLibdeps currentNamespace
|
||||
|
||||
(dependentsOfTodo, directDependencies, hashLen) <-
|
||||
(defnsInLib, dependentsOfTodo, directDependencies, hashLen, incoherentDeclReasons) <-
|
||||
Cli.runTransaction do
|
||||
-- We call a shared `hasDefnsLib` helper even though we could easily duplicate the logic with the branch in hand
|
||||
defnsInLib <- do
|
||||
branch <-
|
||||
currentCausal
|
||||
& Branch._history
|
||||
& Causal.valueHash
|
||||
& coerce @_ @BranchHash
|
||||
& Operations.expectBranchByBranchHash
|
||||
hasDefnsInLib branch
|
||||
|
||||
let todoReference :: TermReference
|
||||
todoReference =
|
||||
Set.asSingleton (Names.refTermsNamed Builtin.names (Name.unsafeParseText "todo"))
|
||||
@ -51,20 +68,28 @@ handleTodo = do
|
||||
|
||||
hashLen <- Codebase.hashLength
|
||||
|
||||
pure (dependentsOfTodo.terms, directDependencies, hashLen)
|
||||
incoherentDeclReasons <-
|
||||
fmap (Either.fromLeft (IncoherentDeclReasons [] [] [] [])) $
|
||||
checkAllDeclCoherency
|
||||
Operations.expectDeclNumConstructors
|
||||
(Names.lenientToNametree (Branch.toNames currentNamespaceWithoutLibdeps))
|
||||
|
||||
pure (defnsInLib, dependentsOfTodo.terms, directDependencies, hashLen, incoherentDeclReasons)
|
||||
|
||||
ppe <- Cli.currentPrettyPrintEnvDecl
|
||||
|
||||
Cli.respondNumbered $
|
||||
Output'Todo
|
||||
TodoOutput
|
||||
{ hashLen,
|
||||
{ defnsInLib,
|
||||
dependentsOfTodo,
|
||||
directDependenciesWithoutNames =
|
||||
Defns
|
||||
{ terms = Set.difference directDependencies.terms (Branch.deepTermReferences currentNamespace),
|
||||
types = Set.difference directDependencies.types (Branch.deepTypeReferences currentNamespace)
|
||||
},
|
||||
hashLen,
|
||||
incoherentDeclReasons,
|
||||
nameConflicts = Names.conflicts (Branch.toNames currentNamespaceWithoutLibdeps),
|
||||
ppe
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ import Unison.Hash (Hash)
|
||||
import Unison.HashQualified qualified as HQ
|
||||
import Unison.HashQualified' qualified as HQ'
|
||||
import Unison.LabeledDependency (LabeledDependency)
|
||||
import Unison.Merge.DeclCoherencyCheck (IncoherentDeclReasons (..))
|
||||
import Unison.Name (Name)
|
||||
import Unison.NameSegment (NameSegment)
|
||||
import Unison.Names (Names)
|
||||
@ -161,9 +162,11 @@ data NumberedOutput
|
||||
[ProjectReflog.Entry Project ProjectBranch (CausalHash, SCH.ShortCausalHash)]
|
||||
|
||||
data TodoOutput = TodoOutput
|
||||
{ dependentsOfTodo :: !(Set TermReferenceId),
|
||||
{ defnsInLib :: !Bool,
|
||||
dependentsOfTodo :: !(Set TermReferenceId),
|
||||
directDependenciesWithoutNames :: !(DefnsF Set TermReference TypeReference),
|
||||
hashLen :: !Int,
|
||||
incoherentDeclReasons :: !IncoherentDeclReasons,
|
||||
nameConflicts :: !Names,
|
||||
ppe :: !PrettyPrintEnvDecl
|
||||
}
|
||||
@ -173,6 +176,8 @@ todoOutputIsEmpty todo =
|
||||
Set.null todo.dependentsOfTodo
|
||||
&& defnsAreEmpty todo.directDependenciesWithoutNames
|
||||
&& Names.isEmpty todo.nameConflicts
|
||||
&& not todo.defnsInLib
|
||||
&& todo.incoherentDeclReasons == IncoherentDeclReasons [] [] [] []
|
||||
|
||||
data AmbiguousReset'Argument
|
||||
= AmbiguousReset'Hash
|
||||
|
@ -18,6 +18,7 @@ module Unison.Codebase.TranscriptParser
|
||||
)
|
||||
where
|
||||
|
||||
import CMark qualified
|
||||
import Control.Lens (use, (?~))
|
||||
import Crypto.Random qualified as Random
|
||||
import Data.Aeson qualified as Aeson
|
||||
@ -118,12 +119,14 @@ instance Show APIRequest where
|
||||
show (GetRequest txt) = "GET " <> Text.unpack txt
|
||||
show (APIComment txt) = "-- " <> Text.unpack txt
|
||||
|
||||
pattern CMarkCodeBlock :: (Maybe CMark.PosInfo) -> Text -> Text -> CMark.Node
|
||||
pattern CMarkCodeBlock pos info body = CMark.Node pos (CMark.CODE_BLOCK info body) []
|
||||
|
||||
data Stanza
|
||||
= Ucm Hidden ExpectingError [UcmLine]
|
||||
| Unison Hidden ExpectingError (Maybe ScratchFileName) Text
|
||||
| API [APIRequest]
|
||||
| UnprocessedFence FenceType Text
|
||||
| Unfenced Text
|
||||
| UnprocessedBlock CMark.Node
|
||||
|
||||
instance Show UcmLine where
|
||||
show = \case
|
||||
@ -133,43 +136,34 @@ instance Show UcmLine where
|
||||
showContext (UcmContextProject projectAndBranch) = Text.unpack (into @Text projectAndBranch)
|
||||
|
||||
instance Show Stanza where
|
||||
show s = case s of
|
||||
show s = (<> "\n") . Text.unpack . CMark.nodeToCommonmark [] Nothing $ stanzaToNode s
|
||||
|
||||
stanzaToNode :: Stanza -> CMark.Node
|
||||
stanzaToNode =
|
||||
\case
|
||||
Ucm _ _ cmds ->
|
||||
unlines
|
||||
[ "```ucm",
|
||||
foldl (\x y -> x ++ show y) "" cmds,
|
||||
"```"
|
||||
]
|
||||
CMarkCodeBlock Nothing "ucm" . Text.pack $
|
||||
foldl (\x y -> x ++ show y) "" cmds
|
||||
Unison _hide _ fname txt ->
|
||||
unlines
|
||||
[ "```unison",
|
||||
case fname of
|
||||
Nothing -> Text.unpack txt <> "```\n"
|
||||
Just fname ->
|
||||
unlines
|
||||
[ "---",
|
||||
"title: " <> Text.unpack fname,
|
||||
"---",
|
||||
Text.unpack txt,
|
||||
"```",
|
||||
""
|
||||
]
|
||||
]
|
||||
CMarkCodeBlock Nothing "unison" . Text.pack $
|
||||
unlines
|
||||
[ case fname of
|
||||
Nothing -> Text.unpack txt
|
||||
Just fname ->
|
||||
unlines
|
||||
[ "---",
|
||||
"title: " <> Text.unpack fname,
|
||||
"---",
|
||||
Text.unpack txt
|
||||
]
|
||||
]
|
||||
API apiRequests ->
|
||||
"```api\n"
|
||||
<> ( apiRequests
|
||||
& fmap show
|
||||
& unlines
|
||||
)
|
||||
<> "```\n"
|
||||
UnprocessedFence typ txt ->
|
||||
unlines
|
||||
[ "```" <> Text.unpack typ,
|
||||
Text.unpack txt,
|
||||
"```",
|
||||
""
|
||||
]
|
||||
Unfenced txt -> Text.unpack txt
|
||||
CMarkCodeBlock Nothing "api" . Text.pack $
|
||||
( apiRequests
|
||||
& fmap show
|
||||
& unlines
|
||||
)
|
||||
UnprocessedBlock node -> node
|
||||
|
||||
parseFile :: FilePath -> IO (Either TranscriptError [Stanza])
|
||||
parseFile filePath = do
|
||||
@ -181,7 +175,7 @@ parseFile filePath = do
|
||||
else pure . Left . TranscriptParseError . Text.pack $ filePath <> " does not exist"
|
||||
|
||||
parse :: String -> Text -> Either TranscriptError [Stanza]
|
||||
parse srcName txt = case P.parse (stanzas <* P.eof) srcName txt of
|
||||
parse srcName txt = case stanzas srcName txt of
|
||||
Right a -> Right a
|
||||
Left e -> Left . TranscriptParseError . Text.pack . P.errorBundlePretty $ e
|
||||
|
||||
@ -333,7 +327,7 @@ run isTest verbosity dir stanzas codebase runtime sbRuntime nRuntime config ucmV
|
||||
for (reverse scratchFileUpdates) \(fp, contents) -> do
|
||||
let fenceDescription = "unison:added-by-ucm " <> fp
|
||||
-- Output blocks for any scratch file updates the ucm block triggered.
|
||||
Q.undequeue inputQueue (UnprocessedFence fenceDescription contents, Nothing)
|
||||
Q.undequeue inputQueue (UnprocessedBlock $ CMarkCodeBlock Nothing fenceDescription contents, Nothing)
|
||||
awaitInput
|
||||
-- ucm command to run
|
||||
Just (Just ucmLine) -> do
|
||||
@ -414,10 +408,7 @@ run isTest verbosity dir stanzas codebase runtime sbRuntime nRuntime config ucmV
|
||||
++ "."
|
||||
IO.hFlush IO.stdout
|
||||
case s of
|
||||
Unfenced _ -> do
|
||||
liftIO (output $ show s)
|
||||
awaitInput
|
||||
UnprocessedFence _ _ -> do
|
||||
UnprocessedBlock _ -> do
|
||||
liftIO (output $ show s)
|
||||
awaitInput
|
||||
Unison hide errOk filename txt -> do
|
||||
@ -426,22 +417,22 @@ run isTest verbosity dir stanzas codebase runtime sbRuntime nRuntime config ucmV
|
||||
liftIO (writeIORef allowErrors errOk)
|
||||
-- Open a ucm block which will contain the output from UCM
|
||||
-- after processing the UnisonFileChanged event.
|
||||
liftIO (output "```ucm\n")
|
||||
liftIO (output "``` ucm\n")
|
||||
-- Close the ucm block after processing the UnisonFileChanged event.
|
||||
atomically . Q.enqueue cmdQueue $ Nothing
|
||||
let sourceName = fromMaybe "scratch.u" filename
|
||||
liftIO $ updateVirtualFile sourceName txt
|
||||
pure $ Left (UnisonFileChanged sourceName txt)
|
||||
API apiRequests -> do
|
||||
liftIO (output "```api\n")
|
||||
liftIO (output "``` api\n")
|
||||
liftIO (for_ apiRequests apiRequest)
|
||||
liftIO (output "```")
|
||||
liftIO (output "```\n\n")
|
||||
awaitInput
|
||||
Ucm hide errOk cmds -> do
|
||||
liftIO (writeIORef hidden hide)
|
||||
liftIO (writeIORef allowErrors errOk)
|
||||
liftIO (writeIORef hasErrors False)
|
||||
liftIO (output "```ucm")
|
||||
liftIO (output "``` ucm")
|
||||
traverse_ (atomically . Q.enqueue cmdQueue . Just) cmds
|
||||
atomically . Q.enqueue cmdQueue $ Nothing
|
||||
awaitInput
|
||||
@ -588,8 +579,12 @@ transcriptFailure out msg = do
|
||||
|
||||
type P = P.Parsec Void Text
|
||||
|
||||
stanzas :: P [Stanza]
|
||||
stanzas = P.many (fenced <|> unfenced)
|
||||
stanzas :: String -> Text -> Either (P.ParseErrorBundle Text Void) [Stanza]
|
||||
stanzas srcName = (\(CMark.Node _ _DOCUMENT blocks) -> traverse stanzaFromBlock blocks) . CMark.commonmarkToNode []
|
||||
where
|
||||
stanzaFromBlock block = case block of
|
||||
CMarkCodeBlock _ info body -> fromMaybe (UnprocessedBlock block) <$> P.parse (fenced info) srcName body
|
||||
_ -> pure $ UnprocessedBlock block
|
||||
|
||||
ucmLine :: P UcmLine
|
||||
ucmLine = ucmCommand <|> ucmComment
|
||||
@ -630,18 +625,21 @@ apiRequest = do
|
||||
spaces
|
||||
pure (APIComment comment)
|
||||
|
||||
fenced :: P Stanza
|
||||
fenced = do
|
||||
fence
|
||||
-- | Produce the correct parser for the code block based on the provided info string.
|
||||
fenced :: Text -> P (Maybe Stanza)
|
||||
fenced info = do
|
||||
body <- P.getInput
|
||||
P.setInput info
|
||||
fenceType <- lineToken (word "ucm" <|> word "unison" <|> word "api" <|> language)
|
||||
stanza <-
|
||||
case fenceType of
|
||||
"ucm" -> do
|
||||
hide <- hidden
|
||||
err <- expectingError
|
||||
P.setInput body
|
||||
_ <- spaces
|
||||
cmds <- many ucmLine
|
||||
pure $ Ucm hide err cmds
|
||||
pure . pure $ Ucm hide err cmds
|
||||
"unison" ->
|
||||
do
|
||||
-- todo: this has to be more interesting
|
||||
@ -651,44 +649,17 @@ fenced = do
|
||||
hide <- lineToken hidden
|
||||
err <- lineToken expectingError
|
||||
fileName <- optional untilSpace1
|
||||
blob <- spaces *> untilFence
|
||||
pure $ Unison hide err fileName blob
|
||||
P.setInput body
|
||||
blob <- spaces *> (Text.init <$> P.getInput)
|
||||
pure . pure $ Unison hide err fileName blob
|
||||
"api" -> do
|
||||
P.setInput body
|
||||
_ <- spaces
|
||||
apiRequests <- many apiRequest
|
||||
pure $ API apiRequests
|
||||
_ -> UnprocessedFence fenceType <$> untilFence
|
||||
fence
|
||||
pure . pure $ API apiRequests
|
||||
_ -> pure Nothing
|
||||
pure stanza
|
||||
|
||||
-- Three backticks, consumes trailing spaces too
|
||||
-- ```
|
||||
fence :: P ()
|
||||
fence = P.try $ do void (word "```"); spaces
|
||||
|
||||
-- Parses up until next fence
|
||||
unfenced :: P Stanza
|
||||
unfenced = Unfenced <$> untilFence
|
||||
|
||||
untilFence :: P Text
|
||||
untilFence = do
|
||||
_ <- P.lookAhead (P.takeP Nothing 1)
|
||||
go mempty
|
||||
where
|
||||
go :: Seq Text -> P Text
|
||||
go !acc = do
|
||||
f <- P.lookAhead (P.optional fence)
|
||||
case f of
|
||||
Nothing -> do
|
||||
oneOrTwoBackticks <- optional (word' "``" <|> word' "`")
|
||||
let start = fromMaybe "" oneOrTwoBackticks
|
||||
txt <- P.takeWhileP (Just "unfenced") (/= '`')
|
||||
eof <- P.lookAhead (P.optional P.eof)
|
||||
case eof of
|
||||
Just _ -> pure $ fold (acc <> pure txt)
|
||||
Nothing -> go (acc <> pure start <> pure txt)
|
||||
Just _ -> pure $ fold acc
|
||||
|
||||
word' :: Text -> P Text
|
||||
word' txt = P.try $ do
|
||||
chs <- P.takeP (Just $ show txt) (Text.length txt)
|
||||
|
@ -85,6 +85,7 @@ import Unison.Hash32 (Hash32)
|
||||
import Unison.HashQualified qualified as HQ
|
||||
import Unison.HashQualified' qualified as HQ'
|
||||
import Unison.LabeledDependency as LD
|
||||
import Unison.Merge.DeclCoherencyCheck (IncoherentDeclReasons (..))
|
||||
import Unison.Name (Name)
|
||||
import Unison.Name qualified as Name
|
||||
import Unison.NameSegment qualified as NameSegment
|
||||
@ -1405,6 +1406,7 @@ notifyUser dir = \case
|
||||
<> "the same on both branches, or making neither of them a builtin, and then try the merge again."
|
||||
)
|
||||
]
|
||||
-- Note [ConstructorAliasMessage] If you change this, also change the other similar one
|
||||
MergeConstructorAlias aliceOrBob typeName conName1 conName2 ->
|
||||
pure . P.lines $
|
||||
[ P.wrap "Sorry, I wasn't able to perform the merge:",
|
||||
@ -1420,6 +1422,7 @@ notifyUser dir = \case
|
||||
"",
|
||||
P.wrap "Please delete all but one name for each constructor, and then try merging again."
|
||||
]
|
||||
-- Note [DefnsInLibMessage] If you change this, also change the other similar one
|
||||
MergeDefnsInLib aliceOrBob ->
|
||||
pure . P.lines $
|
||||
[ P.wrap "Sorry, I wasn't able to perform the merge:",
|
||||
@ -1432,6 +1435,7 @@ notifyUser dir = \case
|
||||
"",
|
||||
P.wrap "Please move or remove it and then try merging again."
|
||||
]
|
||||
-- Note [MissingConstructorNameMessage] If you change this, also change the other similar one
|
||||
MergeMissingConstructorName aliceOrBob name ->
|
||||
pure . P.lines $
|
||||
[ P.wrap "Sorry, I wasn't able to perform the merge:",
|
||||
@ -1450,6 +1454,7 @@ notifyUser dir = \case
|
||||
<> IP.makeExample IP.aliasTerm ["<hash>", prettyName name <> ".<ConstructorName>"]
|
||||
<> "to give names to each unnamed constructor, and then try the merge again."
|
||||
]
|
||||
-- Note [NestedDeclAliasMessage] If you change this, also change the other similar one
|
||||
MergeNestedDeclAlias aliceOrBob shorterName longerName ->
|
||||
pure . P.wrap $
|
||||
"On"
|
||||
@ -1460,6 +1465,7 @@ notifyUser dir = \case
|
||||
<> P.group (prettyName shorterName <> ".")
|
||||
<> "I'm not able to perform a merge when a type exists nested under an alias of itself. Please separate them or"
|
||||
<> "delete one copy, and then try merging again."
|
||||
-- Note [StrayConstructorMessage] If you change this, also change the other similar one
|
||||
MergeStrayConstructor aliceOrBob name ->
|
||||
pure . P.lines $
|
||||
[ P.wrap $
|
||||
@ -2523,20 +2529,20 @@ unsafePrettyTermResultSig' ppe = \case
|
||||
head (TypePrinter.prettySignaturesCT ppe [(r, name, typ)])
|
||||
_ -> error "Don't pass Nothing"
|
||||
|
||||
renderNameConflicts :: PPE.PrettyPrintEnv -> Names -> Numbered Pretty
|
||||
renderNameConflicts ppe conflictedNames = do
|
||||
renderNameConflicts :: Int -> Names -> Numbered Pretty
|
||||
renderNameConflicts hashLen conflictedNames = do
|
||||
let conflictedTypeNames :: Map Name [HQ.HashQualified Name]
|
||||
conflictedTypeNames =
|
||||
conflictedNames
|
||||
& Names.types
|
||||
& R.domain
|
||||
& fmap (foldMap (pure @[] . PPE.typeName ppe))
|
||||
& Map.mapWithKey \name -> map (HQ.take hashLen . HQ.HashQualified name . Reference.toShortHash) . Set.toList
|
||||
let conflictedTermNames :: Map Name [HQ.HashQualified Name]
|
||||
conflictedTermNames =
|
||||
conflictedNames
|
||||
& Names.terms
|
||||
& R.domain
|
||||
& fmap (foldMap (pure @[] . PPE.termName ppe))
|
||||
& Map.mapWithKey \name -> map (HQ.take hashLen . HQ.HashQualified name . Referent.toShortHash) . Set.toList
|
||||
let allConflictedNames :: [Name]
|
||||
allConflictedNames = Set.toList (Map.keysSet conflictedTermNames <> Map.keysSet conflictedTypeNames)
|
||||
prettyConflictedTypes <- showConflictedNames "type" conflictedTypeNames
|
||||
@ -2569,13 +2575,14 @@ renderNameConflicts ppe conflictedNames = do
|
||||
prettyConflicts <- for hashes \hash -> do
|
||||
n <- addNumberedArg $ SA.HashQualified hash
|
||||
pure $ formatNum n <> (P.blue . P.syntaxToColor . prettyHashQualified $ hash)
|
||||
pure . P.wrap $
|
||||
( "The "
|
||||
<> thingKind
|
||||
<> " "
|
||||
<> P.green (prettyName name)
|
||||
<> " has conflicting definitions:"
|
||||
)
|
||||
pure $
|
||||
P.wrap
|
||||
( "The "
|
||||
<> thingKind
|
||||
<> " "
|
||||
<> P.green (prettyName name)
|
||||
<> " has conflicting definitions:"
|
||||
)
|
||||
<> P.newline
|
||||
<> P.newline
|
||||
<> P.indentN 2 (P.lines prettyConflicts)
|
||||
@ -2601,11 +2608,6 @@ handleTodoOutput :: TodoOutput -> Numbered Pretty
|
||||
handleTodoOutput todo
|
||||
| todoOutputIsEmpty todo = pure "You have no pending todo items. Good work! ✅"
|
||||
| otherwise = do
|
||||
prettyConflicts <-
|
||||
if todo.nameConflicts == mempty
|
||||
then pure mempty
|
||||
else renderNameConflicts todo.ppe.unsuffixifiedPPE todo.nameConflicts
|
||||
|
||||
prettyDependentsOfTodo <- do
|
||||
if Set.null todo.dependentsOfTodo
|
||||
then pure mempty
|
||||
@ -2654,11 +2656,159 @@ handleTodoOutput todo
|
||||
<> P.newline
|
||||
<> P.indentN 2 (P.lines types)
|
||||
|
||||
prettyConflicts <-
|
||||
if todo.nameConflicts == mempty
|
||||
then pure mempty
|
||||
else renderNameConflicts todo.hashLen todo.nameConflicts
|
||||
|
||||
let prettyDefnsInLib =
|
||||
if todo.defnsInLib
|
||||
then
|
||||
P.wrap $
|
||||
-- Note [DefnsInLibMessage] If you change this, also change the other similar one
|
||||
"There's a type or term at the top level of the `lib` namespace, where I only expect to find"
|
||||
<> "subnamespaces representing library dependencies. Please move or remove it."
|
||||
else mempty
|
||||
|
||||
prettyConstructorAliases <-
|
||||
let -- We want to filter out constructor aliases whose types are part of a "nested decl alias" problem, because
|
||||
-- otherwise we'd essentially be reporting those issues twice.
|
||||
--
|
||||
-- That is, if we have two nested aliases like
|
||||
--
|
||||
-- Foo = #XYZ
|
||||
-- Foo.Bar = #XYZ#0
|
||||
--
|
||||
-- Foo.inner.Alias = #XYZ
|
||||
-- Foo.inner.Alias.Constructor = #XYZ#0
|
||||
--
|
||||
-- then we'd prefer to say "oh no Foo and Foo.inner.Alias are aliases" but *not* additionally say "oh no
|
||||
-- Foo.Bar and Foo.inner.Alias.Constructor are aliases".
|
||||
notNestedDeclAlias (typeName, _, _) =
|
||||
foldr
|
||||
(\(short, long) acc -> typeName /= short && typeName /= long && acc)
|
||||
True
|
||||
todo.incoherentDeclReasons.nestedDeclAliases
|
||||
in case filter notNestedDeclAlias todo.incoherentDeclReasons.constructorAliases of
|
||||
[] -> pure mempty
|
||||
aliases -> do
|
||||
things <-
|
||||
for aliases \(typeName, conName1, conName2) -> do
|
||||
n1 <- addNumberedArg (SA.Name conName1)
|
||||
n2 <- addNumberedArg (SA.Name conName2)
|
||||
pure (typeName, formatNum n1 <> prettyName conName1, formatNum n2 <> prettyName conName2)
|
||||
pure $
|
||||
things
|
||||
& map
|
||||
( \(typeName, prettyCon1, prettyCon2) ->
|
||||
-- Note [ConstructorAliasMessage] If you change this, also change the other similar one
|
||||
P.wrap ("The type" <> prettyName typeName <> "has a constructor with multiple names.")
|
||||
<> P.newline
|
||||
<> P.newline
|
||||
<> P.indentN 2 (P.lines [prettyCon1, prettyCon2])
|
||||
<> P.newline
|
||||
<> P.newline
|
||||
<> P.wrap "Please delete all but one name for each constructor."
|
||||
)
|
||||
& P.sep "\n\n"
|
||||
|
||||
prettyMissingConstructorNames <-
|
||||
case NEList.nonEmpty todo.incoherentDeclReasons.missingConstructorNames of
|
||||
Nothing -> pure mempty
|
||||
Just types0 -> do
|
||||
stuff <-
|
||||
for types0 \typ -> do
|
||||
n <- addNumberedArg (SA.Name typ)
|
||||
pure (n, typ)
|
||||
-- Note [MissingConstructorNameMessage] If you change this, also change the other similar one
|
||||
pure $
|
||||
P.wrap
|
||||
"These types have some constructors with missing names."
|
||||
<> P.newline
|
||||
<> P.newline
|
||||
<> P.indentN 2 (P.lines (fmap (\(n, typ) -> formatNum n <> prettyName typ) stuff))
|
||||
<> P.newline
|
||||
<> P.newline
|
||||
<> P.wrap
|
||||
( "You can use"
|
||||
<> IP.makeExample
|
||||
IP.view
|
||||
[ let firstNum = fst (NEList.head stuff)
|
||||
lastNum = fst (NEList.last stuff)
|
||||
in if firstNum == lastNum
|
||||
then P.string (show firstNum)
|
||||
else P.string (show firstNum) <> "-" <> P.string (show lastNum)
|
||||
]
|
||||
<> "and"
|
||||
<> IP.makeExample IP.aliasTerm ["<hash>", "<TypeName>.<ConstructorName>"]
|
||||
<> "to give names to each unnamed constructor."
|
||||
)
|
||||
|
||||
prettyNestedDeclAliases <-
|
||||
case todo.incoherentDeclReasons.nestedDeclAliases of
|
||||
[] -> pure mempty
|
||||
aliases0 -> do
|
||||
aliases1 <-
|
||||
for aliases0 \(short, long) -> do
|
||||
n1 <- addNumberedArg (SA.Name short)
|
||||
n2 <- addNumberedArg (SA.Name long)
|
||||
pure (formatNum n1 <> prettyName short, formatNum n2 <> prettyName long)
|
||||
-- Note [NestedDeclAliasMessage] If you change this, also change the other similar one
|
||||
pure $
|
||||
aliases1
|
||||
& map
|
||||
( \(short, long) ->
|
||||
P.wrap
|
||||
( "These types are aliases, but one is nested under the other. Please separate them or delete"
|
||||
<> "one copy."
|
||||
)
|
||||
<> P.newline
|
||||
<> P.newline
|
||||
<> P.indentN 2 (P.lines [short, long])
|
||||
)
|
||||
& P.sep "\n\n"
|
||||
|
||||
prettyStrayConstructors <-
|
||||
case todo.incoherentDeclReasons.strayConstructors of
|
||||
[] -> pure mempty
|
||||
constructors -> do
|
||||
nums <-
|
||||
for constructors \constructor -> do
|
||||
addNumberedArg (SA.Name constructor)
|
||||
-- Note [StrayConstructorMessage] If you change this, also change the other similar one
|
||||
pure $
|
||||
P.wrap "These constructors are not nested beneath their corresponding type names:"
|
||||
<> P.newline
|
||||
<> P.newline
|
||||
<> P.indentN
|
||||
2
|
||||
( P.lines
|
||||
( zipWith
|
||||
(\n constructor -> formatNum n <> prettyName constructor)
|
||||
nums
|
||||
constructors
|
||||
)
|
||||
)
|
||||
<> P.newline
|
||||
<> P.newline
|
||||
<> P.wrap
|
||||
( "For each one, please either use"
|
||||
<> IP.makeExample' IP.moveAll
|
||||
<> "to move if, or if it's an extra copy, you can simply"
|
||||
<> IP.makeExample' IP.delete
|
||||
<> "it."
|
||||
)
|
||||
|
||||
(pure . P.sep "\n\n" . P.nonEmpty)
|
||||
[ prettyDependentsOfTodo,
|
||||
prettyDirectTermDependenciesWithoutNames,
|
||||
prettyDirectTypeDependenciesWithoutNames,
|
||||
prettyConflicts
|
||||
prettyConflicts,
|
||||
prettyDefnsInLib,
|
||||
prettyConstructorAliases,
|
||||
prettyMissingConstructorNames,
|
||||
prettyNestedDeclAliases,
|
||||
prettyStrayConstructors
|
||||
]
|
||||
|
||||
listOfDefinitions ::
|
||||
|
@ -197,6 +197,7 @@ library
|
||||
, base
|
||||
, bytes
|
||||
, bytestring
|
||||
, cmark
|
||||
, co-log-core
|
||||
, code-page
|
||||
, concurrent-output
|
||||
@ -338,6 +339,7 @@ executable transcripts
|
||||
, base
|
||||
, bytes
|
||||
, bytestring
|
||||
, cmark
|
||||
, co-log-core
|
||||
, code-page
|
||||
, concurrent-output
|
||||
@ -486,6 +488,7 @@ test-suite cli-tests
|
||||
, base
|
||||
, bytes
|
||||
, bytestring
|
||||
, cmark
|
||||
, co-log-core
|
||||
, code-page
|
||||
, concurrent-output
|
||||
|
@ -66,6 +66,7 @@ default-extensions:
|
||||
- DerivingStrategies
|
||||
- DerivingVia
|
||||
- DoAndIfThenElse
|
||||
- DuplicateRecordFields
|
||||
- FlexibleContexts
|
||||
- FlexibleInstances
|
||||
- GADTs
|
||||
|
@ -49,12 +49,15 @@ module Unison.Names
|
||||
hashQualifyTypesRelation,
|
||||
hashQualifyTermsRelation,
|
||||
fromTermsAndTypes,
|
||||
lenientToNametree,
|
||||
)
|
||||
where
|
||||
|
||||
import Data.Map qualified as Map
|
||||
import Data.Semialign (alignWith)
|
||||
import Data.Set qualified as Set
|
||||
import Data.Text qualified as Text
|
||||
import Data.These (These (..))
|
||||
import Text.FuzzyFind qualified as FZF
|
||||
import Unison.ConstructorReference (GConstructorReference (..))
|
||||
import Unison.ConstructorType qualified as CT
|
||||
@ -64,6 +67,7 @@ import Unison.LabeledDependency (LabeledDependency)
|
||||
import Unison.LabeledDependency qualified as LD
|
||||
import Unison.Name (Name)
|
||||
import Unison.Name qualified as Name
|
||||
import Unison.NameSegment (NameSegment)
|
||||
import Unison.Prelude
|
||||
import Unison.Reference (Reference, TermReference, TypeReference)
|
||||
import Unison.Reference qualified as Reference
|
||||
@ -71,6 +75,10 @@ import Unison.Referent (Referent)
|
||||
import Unison.Referent qualified as Referent
|
||||
import Unison.ShortHash (ShortHash)
|
||||
import Unison.ShortHash qualified as SH
|
||||
import Unison.Util.BiMultimap (BiMultimap)
|
||||
import Unison.Util.BiMultimap qualified as BiMultimap
|
||||
import Unison.Util.Defns (Defns (..), DefnsF)
|
||||
import Unison.Util.Nametree (Nametree, unflattenNametree)
|
||||
import Unison.Util.Relation (Relation)
|
||||
import Unison.Util.Relation qualified as R
|
||||
import Unison.Util.Relation qualified as Relation
|
||||
@ -95,7 +103,7 @@ instance Monoid (Names) where
|
||||
mempty = Names mempty mempty
|
||||
|
||||
isEmpty :: Names -> Bool
|
||||
isEmpty n = R.null (terms n) && R.null (types n)
|
||||
isEmpty n = R.null n.terms && R.null n.types
|
||||
|
||||
map :: (Name -> Name) -> Names -> Names
|
||||
map f (Names {terms, types}) = Names terms' types'
|
||||
@ -122,8 +130,8 @@ fuzzyFind nameToText query names =
|
||||
. Prelude.filter prefilter
|
||||
. Map.toList
|
||||
-- `mapMonotonic` is safe here and saves a log n factor
|
||||
$ (Set.mapMonotonic Left <$> R.toMultimap (terms names))
|
||||
<> (Set.mapMonotonic Right <$> R.toMultimap (types names))
|
||||
$ (Set.mapMonotonic Left <$> R.toMultimap names.terms)
|
||||
<> (Set.mapMonotonic Right <$> R.toMultimap names.types)
|
||||
where
|
||||
lowerqueryt = Text.toLower . Text.pack <$> query
|
||||
-- For performance, case-insensitive substring matching as a pre-filter
|
||||
@ -250,8 +258,8 @@ unionLeft' ::
|
||||
Names
|
||||
unionLeft' shouldOmit a b = Names terms' types'
|
||||
where
|
||||
terms' = foldl' go (terms a) (R.toList $ terms b)
|
||||
types' = foldl' go (types a) (R.toList $ types b)
|
||||
terms' = foldl' go a.terms (R.toList b.terms)
|
||||
types' = foldl' go a.types (R.toList b.types)
|
||||
go :: (Ord a, Ord b) => Relation a b -> (a, b) -> Relation a b
|
||||
go acc (n, r) = if shouldOmit n r acc then acc else R.insert n r acc
|
||||
|
||||
@ -260,7 +268,7 @@ numHashChars :: Int
|
||||
numHashChars = 3
|
||||
|
||||
termsNamed :: Names -> Name -> Set Referent
|
||||
termsNamed = flip R.lookupDom . terms
|
||||
termsNamed = flip R.lookupDom . (.terms)
|
||||
|
||||
-- | Get all terms with a specific name.
|
||||
refTermsNamed :: Names -> Name -> Set TermReference
|
||||
@ -281,13 +289,13 @@ refTermsHQNamed names = \case
|
||||
in Set.mapMaybe f (termsNamed names name)
|
||||
|
||||
typesNamed :: Names -> Name -> Set TypeReference
|
||||
typesNamed = flip R.lookupDom . types
|
||||
typesNamed = flip R.lookupDom . (.types)
|
||||
|
||||
namesForReferent :: Names -> Referent -> Set Name
|
||||
namesForReferent names r = R.lookupRan r (terms names)
|
||||
namesForReferent names r = R.lookupRan r names.terms
|
||||
|
||||
namesForReference :: Names -> TypeReference -> Set Name
|
||||
namesForReference names r = R.lookupRan r (types names)
|
||||
namesForReference names r = R.lookupRan r names.types
|
||||
|
||||
termAliases :: Names -> Name -> Referent -> Set Name
|
||||
termAliases names n r = Set.delete n $ namesForReferent names r
|
||||
@ -422,20 +430,20 @@ filterTypes f (Names terms types) = Names terms (R.filterDom f types)
|
||||
difference :: Names -> Names -> Names
|
||||
difference a b =
|
||||
Names
|
||||
(R.difference (terms a) (terms b))
|
||||
(R.difference (types a) (types b))
|
||||
(R.difference a.terms b.terms)
|
||||
(R.difference a.types b.types)
|
||||
|
||||
contains :: Names -> Reference -> Bool
|
||||
contains names =
|
||||
-- We want to compute `termsReferences` only once, if `contains` is partially applied to a `Names`, and called over
|
||||
-- and over for different references. GHC would probably float `termsReferences` out without the explicit lambda, but
|
||||
-- it's written like this just to be sure.
|
||||
\r -> Set.member r termsReferences || R.memberRan r (types names)
|
||||
\r -> Set.member r termsReferences || R.memberRan r names.types
|
||||
where
|
||||
-- this check makes `contains` O(n) instead of O(log n)
|
||||
termsReferences :: Set TermReference
|
||||
termsReferences =
|
||||
Set.map Referent.toReference (R.ran (terms names))
|
||||
Set.map Referent.toReference (R.ran names.terms)
|
||||
|
||||
-- | filters out everything from the domain except what's conflicted
|
||||
conflicts :: Names -> Names
|
||||
@ -448,9 +456,9 @@ conflicts Names {..} = Names (R.filterManyDom terms) (R.filterManyDom types)
|
||||
-- See usage in `FileParser` for handling precendence of symbol
|
||||
-- resolution where local names are preferred to codebase names.
|
||||
shadowTerms :: [Name] -> Names -> Names
|
||||
shadowTerms ns n0 = Names terms' (types n0)
|
||||
shadowTerms ns n0 = Names terms' n0.types
|
||||
where
|
||||
terms' = foldl' go (terms n0) ns
|
||||
terms' = foldl' go n0.terms ns
|
||||
go ts name = R.deleteDom name ts
|
||||
|
||||
-- | Given a mapping from name to qualified name, update a `Names`,
|
||||
@ -461,8 +469,8 @@ shadowTerms ns n0 = Names terms' (types n0)
|
||||
importing :: [(Name, Name)] -> Names -> Names
|
||||
importing shortToLongName ns =
|
||||
Names
|
||||
(foldl' go (terms ns) shortToLongName)
|
||||
(foldl' go (types ns) shortToLongName)
|
||||
(foldl' go ns.terms shortToLongName)
|
||||
(foldl' go ns.types shortToLongName)
|
||||
where
|
||||
go :: (Ord r) => Relation Name r -> (Name, Name) -> Relation Name r
|
||||
go m (shortname, qname) = case Name.searchByRankedSuffix qname m of
|
||||
@ -476,8 +484,8 @@ importing shortToLongName ns =
|
||||
-- `[(foo, io.foo), (bar, io.bar)]`.
|
||||
expandWildcardImport :: Name -> Names -> [(Name, Name)]
|
||||
expandWildcardImport prefix ns =
|
||||
[(suffix, full) | Just (suffix, full) <- go <$> R.toList (terms ns)]
|
||||
<> [(suffix, full) | Just (suffix, full) <- go <$> R.toList (types ns)]
|
||||
[(suffix, full) | Just (suffix, full) <- go <$> R.toList ns.terms]
|
||||
<> [(suffix, full) | Just (suffix, full) <- go <$> R.toList ns.types]
|
||||
where
|
||||
go :: (Name, a) -> Maybe (Name, Name)
|
||||
go (full, _) = do
|
||||
@ -498,7 +506,7 @@ constructorsForType r ns =
|
||||
possibleDatas = [Referent.Con (ConstructorReference r cid) CT.Data | cid <- [0 ..]]
|
||||
possibleEffects = [Referent.Con (ConstructorReference r cid) CT.Effect | cid <- [0 ..]]
|
||||
trim [] = []
|
||||
trim (h : t) = case R.lookupRan h (terms ns) of
|
||||
trim (h : t) = case R.lookupRan h ns.terms of
|
||||
s
|
||||
| Set.null s -> []
|
||||
| otherwise -> [(n, h) | n <- toList s] ++ trim t
|
||||
@ -517,3 +525,29 @@ hashQualifyRelation fromNamedRef rel = R.map go rel
|
||||
if Set.size (R.lookupDom n rel) > 1
|
||||
then (HQ.take numHashChars $ fromNamedRef n r, r)
|
||||
else (HQ.NameOnly n, r)
|
||||
|
||||
-- | "Leniently" view a Names as a NameTree
|
||||
--
|
||||
-- This function is "lenient" in the sense that it does not handle conflicted names with any smarts whatsoever. The
|
||||
-- resulting nametree will simply contain one of the associated references of a conflicted name - we don't specify
|
||||
-- which.
|
||||
lenientToNametree :: Names -> Nametree (DefnsF (Map NameSegment) Referent TypeReference)
|
||||
lenientToNametree names =
|
||||
alignWith
|
||||
( \case
|
||||
This terms -> Defns {terms, types = Map.empty}
|
||||
That types -> Defns {terms = Map.empty, types}
|
||||
These terms types -> Defns {terms, types}
|
||||
)
|
||||
(lenientRelationToNametree names.terms)
|
||||
(lenientRelationToNametree names.types)
|
||||
where
|
||||
lenientRelationToNametree :: Ord a => Relation Name a -> Nametree (Map NameSegment a)
|
||||
lenientRelationToNametree =
|
||||
unflattenNametree . lenientRelationToLeftUniqueRelation
|
||||
|
||||
lenientRelationToLeftUniqueRelation :: (Ord a, Ord b) => Relation a b -> BiMultimap b a
|
||||
lenientRelationToLeftUniqueRelation =
|
||||
-- The partial `Set.findMin` are fine here because Relation.domain only has non-empty Set values. A NESet would be
|
||||
-- better.
|
||||
BiMultimap.fromRange . Map.map Set.findMin . Relation.domain
|
||||
|
@ -72,6 +72,7 @@ library
|
||||
DerivingStrategies
|
||||
DerivingVia
|
||||
DoAndIfThenElse
|
||||
DuplicateRecordFields
|
||||
FlexibleContexts
|
||||
FlexibleInstances
|
||||
GADTs
|
||||
@ -140,6 +141,7 @@ test-suite tests
|
||||
DerivingStrategies
|
||||
DerivingVia
|
||||
DoAndIfThenElse
|
||||
DuplicateRecordFields
|
||||
FlexibleContexts
|
||||
FlexibleInstances
|
||||
GADTs
|
||||
|
@ -83,15 +83,17 @@ module Unison.Merge.DeclCoherencyCheck
|
||||
( IncoherentDeclReason (..),
|
||||
checkDeclCoherency,
|
||||
lenientCheckDeclCoherency,
|
||||
|
||||
-- * Getting all failures rather than just the first
|
||||
IncoherentDeclReasons (..),
|
||||
checkAllDeclCoherency,
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Lens ((%=), (.=), _2)
|
||||
import Control.Monad.Except (ExceptT)
|
||||
import Control.Monad.Except qualified as Except
|
||||
import Control.Monad.State.Strict (StateT)
|
||||
import Control.Monad.State.Strict qualified as State
|
||||
import Control.Monad.Trans.Except qualified as Except (except)
|
||||
import Data.Functor.Compose (Compose (..))
|
||||
import Data.IntMap.Strict (IntMap)
|
||||
import Data.IntMap.Strict qualified as IntMap
|
||||
@ -136,87 +138,190 @@ checkDeclCoherency ::
|
||||
(TypeReferenceId -> m Int) ->
|
||||
Nametree (DefnsF (Map NameSegment) Referent TypeReference) ->
|
||||
m (Either IncoherentDeclReason DeclNameLookup)
|
||||
checkDeclCoherency loadDeclNumConstructors =
|
||||
checkDeclCoherency loadDeclNumConstructors nametree =
|
||||
Except.runExceptT
|
||||
. fmap (view #declNameLookup)
|
||||
( checkDeclCoherencyWith
|
||||
(lift . loadDeclNumConstructors)
|
||||
OnIncoherentDeclReasons
|
||||
{ onConstructorAlias = \x y z -> Except.throwError (IncoherentDeclReason'ConstructorAlias x y z), -- :: Name -> Name -> Name -> m (),
|
||||
onMissingConstructorName = \x -> Except.throwError (IncoherentDeclReason'MissingConstructorName x), -- :: Name -> m (),
|
||||
onNestedDeclAlias = \x y -> Except.throwError (IncoherentDeclReason'NestedDeclAlias x y), -- :: Name -> Name -> m (),
|
||||
onStrayConstructor = \x -> Except.throwError (IncoherentDeclReason'StrayConstructor x) -- :: Name -> m ()
|
||||
}
|
||||
nametree
|
||||
)
|
||||
|
||||
data IncoherentDeclReasons = IncoherentDeclReasons
|
||||
{ constructorAliases :: ![(Name, Name, Name)],
|
||||
missingConstructorNames :: ![Name],
|
||||
nestedDeclAliases :: ![(Name, Name)],
|
||||
strayConstructors :: ![Name]
|
||||
}
|
||||
deriving stock (Eq, Generic)
|
||||
|
||||
-- | Like 'checkDeclCoherency', but returns info about all of the incoherent decls found, not just the first.
|
||||
checkAllDeclCoherency ::
|
||||
forall m.
|
||||
Monad m =>
|
||||
(TypeReferenceId -> m Int) ->
|
||||
Nametree (DefnsF (Map NameSegment) Referent TypeReference) ->
|
||||
m (Either IncoherentDeclReasons DeclNameLookup)
|
||||
checkAllDeclCoherency loadDeclNumConstructors nametree = do
|
||||
State.runStateT doCheck emptyReasons <&> \(declNameLookup, reasons) ->
|
||||
if reasons == emptyReasons
|
||||
then Right declNameLookup
|
||||
else Left (reverseReasons reasons)
|
||||
where
|
||||
doCheck :: StateT IncoherentDeclReasons m DeclNameLookup
|
||||
doCheck =
|
||||
checkDeclCoherencyWith
|
||||
(lift . loadDeclNumConstructors)
|
||||
( OnIncoherentDeclReasons
|
||||
{ onConstructorAlias = \x y z -> #constructorAliases %= ((x, y, z) :),
|
||||
onMissingConstructorName = \x -> #missingConstructorNames %= (x :),
|
||||
onNestedDeclAlias = \x y -> #nestedDeclAliases %= ((x, y) :),
|
||||
onStrayConstructor = \x -> #strayConstructors %= (x :)
|
||||
}
|
||||
)
|
||||
nametree
|
||||
|
||||
emptyReasons :: IncoherentDeclReasons
|
||||
emptyReasons =
|
||||
IncoherentDeclReasons [] [] [] []
|
||||
|
||||
reverseReasons :: IncoherentDeclReasons -> IncoherentDeclReasons
|
||||
reverseReasons reasons =
|
||||
IncoherentDeclReasons
|
||||
{ constructorAliases = reverse reasons.constructorAliases,
|
||||
missingConstructorNames = reverse reasons.missingConstructorNames,
|
||||
nestedDeclAliases = reverse reasons.nestedDeclAliases,
|
||||
strayConstructors = reverse reasons.strayConstructors
|
||||
}
|
||||
|
||||
data OnIncoherentDeclReasons m = OnIncoherentDeclReasons
|
||||
{ onConstructorAlias :: Name -> Name -> Name -> m (),
|
||||
onMissingConstructorName :: Name -> m (),
|
||||
onNestedDeclAlias :: Name -> Name -> m (),
|
||||
onStrayConstructor :: Name -> m ()
|
||||
}
|
||||
|
||||
checkDeclCoherencyWith ::
|
||||
forall m.
|
||||
Monad m =>
|
||||
(TypeReferenceId -> m Int) ->
|
||||
OnIncoherentDeclReasons m ->
|
||||
Nametree (DefnsF (Map NameSegment) Referent TypeReference) ->
|
||||
m DeclNameLookup
|
||||
checkDeclCoherencyWith loadDeclNumConstructors callbacks =
|
||||
fmap (view #declNameLookup)
|
||||
. (`State.execStateT` DeclCoherencyCheckState Map.empty (DeclNameLookup Map.empty Map.empty))
|
||||
. go []
|
||||
where
|
||||
go ::
|
||||
[NameSegment] ->
|
||||
(Nametree (DefnsF (Map NameSegment) Referent TypeReference)) ->
|
||||
StateT DeclCoherencyCheckState (ExceptT IncoherentDeclReason m) ()
|
||||
StateT DeclCoherencyCheckState m ()
|
||||
go prefix (Nametree defns children) = do
|
||||
for_ (Map.toList defns.terms) \case
|
||||
(_, Referent.Ref _) -> pure ()
|
||||
(_, Referent.Con (ConstructorReference (ReferenceBuiltin _) _) _) -> pure ()
|
||||
(name, Referent.Con (ConstructorReference (ReferenceDerived typeRef) conId) _) -> do
|
||||
DeclCoherencyCheckState {expectedConstructors} <- State.get
|
||||
expectedConstructors1 <- lift (Except.except (Map.upsertF f typeRef expectedConstructors))
|
||||
#expectedConstructors .= expectedConstructors1
|
||||
where
|
||||
f ::
|
||||
Maybe (Name, ConstructorNames) ->
|
||||
Either IncoherentDeclReason (Name, ConstructorNames)
|
||||
f = \case
|
||||
Nothing -> Left (IncoherentDeclReason'StrayConstructor name1)
|
||||
Just (typeName, expected) ->
|
||||
case recordConstructorName conId name1 expected of
|
||||
Left existingName -> Left (IncoherentDeclReason'ConstructorAlias typeName existingName name1)
|
||||
Right expected1 -> Right (typeName, expected1)
|
||||
where
|
||||
name1 = fullName name
|
||||
|
||||
for_ (Map.toList defns.terms) (checkDeclCoherencyWith_DoTerms callbacks prefix)
|
||||
childrenWeWentInto <-
|
||||
forMaybe (Map.toList defns.types) \case
|
||||
(_, ReferenceBuiltin _) -> pure Nothing
|
||||
(name, ReferenceDerived typeRef) -> do
|
||||
DeclCoherencyCheckState {expectedConstructors} <- State.get
|
||||
whatHappened <- do
|
||||
let recordNewDecl ::
|
||||
Maybe (Name, ConstructorNames) ->
|
||||
Compose (ExceptT IncoherentDeclReason m) WhatHappened (Name, ConstructorNames)
|
||||
recordNewDecl =
|
||||
Compose . \case
|
||||
Just (shorterTypeName, _) -> Except.throwError (IncoherentDeclReason'NestedDeclAlias shorterTypeName typeName)
|
||||
Nothing ->
|
||||
lift (loadDeclNumConstructors typeRef) <&> \case
|
||||
0 -> UninhabitedDecl
|
||||
n -> InhabitedDecl (typeName, emptyConstructorNames n)
|
||||
lift (getCompose (Map.upsertF recordNewDecl typeRef expectedConstructors))
|
||||
case whatHappened of
|
||||
UninhabitedDecl -> do
|
||||
#declNameLookup . #declToConstructors %= Map.insert typeName []
|
||||
pure Nothing
|
||||
InhabitedDecl expectedConstructors1 -> do
|
||||
child <-
|
||||
Map.lookup name children & onNothing do
|
||||
Except.throwError (IncoherentDeclReason'MissingConstructorName typeName)
|
||||
#expectedConstructors .= expectedConstructors1
|
||||
go (name : prefix) child
|
||||
DeclCoherencyCheckState {expectedConstructors} <- State.get
|
||||
-- fromJust is safe here because we upserted `typeRef` key above
|
||||
let (fromJust -> (_typeName, maybeConstructorNames), expectedConstructors1) =
|
||||
Map.deleteLookup typeRef expectedConstructors
|
||||
constructorNames <-
|
||||
sequence (IntMap.elems maybeConstructorNames) & onNothing do
|
||||
Except.throwError (IncoherentDeclReason'MissingConstructorName typeName)
|
||||
#expectedConstructors .= expectedConstructors1
|
||||
forMaybe
|
||||
(Map.toList defns.types)
|
||||
(checkDeclCoherencyWith_DoTypes loadDeclNumConstructors callbacks go prefix children)
|
||||
let childrenWeHaventGoneInto = children `Map.withoutKeys` Set.fromList childrenWeWentInto
|
||||
for_ (Map.toList childrenWeHaventGoneInto) \(name, child) -> go (name : prefix) child
|
||||
|
||||
checkDeclCoherencyWith_DoTerms ::
|
||||
forall m.
|
||||
Monad m =>
|
||||
OnIncoherentDeclReasons m ->
|
||||
[NameSegment] ->
|
||||
(NameSegment, Referent) ->
|
||||
StateT DeclCoherencyCheckState m ()
|
||||
checkDeclCoherencyWith_DoTerms callbacks prefix = \case
|
||||
(_, Referent.Ref _) -> pure ()
|
||||
(_, Referent.Con (ConstructorReference (ReferenceBuiltin _) _) _) -> pure ()
|
||||
(name, Referent.Con (ConstructorReference (ReferenceDerived typeRef) conId) _) -> do
|
||||
state <- State.get
|
||||
whenJustM (lift (runMaybeT (Map.upsertF f typeRef state.expectedConstructors))) \expectedConstructors1 ->
|
||||
#expectedConstructors .= expectedConstructors1
|
||||
where
|
||||
f :: Maybe (Name, ConstructorNames) -> MaybeT m (Name, ConstructorNames)
|
||||
f = \case
|
||||
Nothing -> do
|
||||
lift (callbacks.onStrayConstructor name1)
|
||||
MaybeT (pure Nothing)
|
||||
Just (typeName, expected) ->
|
||||
case recordConstructorName conId name1 expected of
|
||||
Left existingName -> do
|
||||
lift (callbacks.onConstructorAlias typeName existingName name1)
|
||||
MaybeT (pure Nothing)
|
||||
Right expected1 -> pure (typeName, expected1)
|
||||
where
|
||||
name1 =
|
||||
Name.fromReverseSegments (name :| prefix)
|
||||
|
||||
checkDeclCoherencyWith_DoTypes ::
|
||||
forall m.
|
||||
Monad m =>
|
||||
(TypeReferenceId -> m Int) ->
|
||||
OnIncoherentDeclReasons m ->
|
||||
( [NameSegment] ->
|
||||
(Nametree (DefnsF (Map NameSegment) Referent TypeReference)) ->
|
||||
StateT DeclCoherencyCheckState m ()
|
||||
) ->
|
||||
[NameSegment] ->
|
||||
Map NameSegment (Nametree (DefnsF (Map NameSegment) Referent TypeReference)) ->
|
||||
(NameSegment, TypeReference) ->
|
||||
StateT DeclCoherencyCheckState m (Maybe NameSegment)
|
||||
checkDeclCoherencyWith_DoTypes loadDeclNumConstructors callbacks go prefix children = \case
|
||||
(_, ReferenceBuiltin _) -> pure Nothing
|
||||
(name, ReferenceDerived typeRef) -> do
|
||||
state <- State.get
|
||||
maybeWhatHappened <- do
|
||||
let recordNewDecl ::
|
||||
Maybe (Name, ConstructorNames) ->
|
||||
Compose (MaybeT m) WhatHappened (Name, ConstructorNames)
|
||||
recordNewDecl =
|
||||
Compose . \case
|
||||
Just (shorterTypeName, _) -> do
|
||||
lift (callbacks.onNestedDeclAlias shorterTypeName typeName)
|
||||
MaybeT (pure Nothing)
|
||||
Nothing ->
|
||||
lift (loadDeclNumConstructors typeRef) <&> \case
|
||||
0 -> UninhabitedDecl
|
||||
n -> InhabitedDecl (typeName, emptyConstructorNames n)
|
||||
lift (runMaybeT (getCompose (Map.upsertF recordNewDecl typeRef state.expectedConstructors)))
|
||||
case maybeWhatHappened of
|
||||
Nothing -> pure Nothing
|
||||
Just UninhabitedDecl -> do
|
||||
#declNameLookup . #declToConstructors %= Map.insert typeName []
|
||||
pure Nothing
|
||||
Just (InhabitedDecl expectedConstructors1) -> do
|
||||
case Map.lookup name children of
|
||||
Nothing -> do
|
||||
lift (callbacks.onMissingConstructorName typeName)
|
||||
pure Nothing
|
||||
Just child -> do
|
||||
#expectedConstructors .= expectedConstructors1
|
||||
go (name : prefix) child
|
||||
state <- State.get
|
||||
-- fromJust is safe here because we upserted `typeRef` key above
|
||||
let (fromJust -> (_typeName, maybeConstructorNames), expectedConstructors1) =
|
||||
Map.deleteLookup typeRef state.expectedConstructors
|
||||
#expectedConstructors .= expectedConstructors1
|
||||
case sequence (IntMap.elems maybeConstructorNames) of
|
||||
Nothing -> lift (callbacks.onMissingConstructorName typeName)
|
||||
Just constructorNames -> do
|
||||
#declNameLookup . #constructorToDecl %= \constructorToDecl ->
|
||||
List.foldl'
|
||||
(\acc constructorName -> Map.insert constructorName typeName acc)
|
||||
constructorToDecl
|
||||
constructorNames
|
||||
#declNameLookup . #declToConstructors %= Map.insert typeName constructorNames
|
||||
pure (Just name)
|
||||
where
|
||||
typeName = fullName name
|
||||
|
||||
let childrenWeHaventGoneInto = children `Map.withoutKeys` Set.fromList childrenWeWentInto
|
||||
for_ (Map.toList childrenWeHaventGoneInto) \(name, child) -> go (name : prefix) child
|
||||
where
|
||||
fullName name =
|
||||
Name.fromReverseSegments (name :| prefix)
|
||||
pure (Just name)
|
||||
where
|
||||
typeName =
|
||||
Name.fromReverseSegments (name :| prefix)
|
||||
|
||||
-- | A lenient variant of 'checkDeclCoherency' - so lenient it can't even fail! It returns partial decl name lookup,
|
||||
-- which doesn't require a name for every constructor, and allows a constructor with a nameless decl.
|
||||
|
@ -4,7 +4,7 @@ If you want to add or update tests, you can create a branch of that project, and
|
||||
|
||||
Before merging the PR on Github, we'll merge your branch on Share and restore `runtime_tests_version` to /main or maybe a release.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
runtime-tests/selected> run tests
|
||||
|
||||
()
|
||||
|
@ -4,7 +4,7 @@ If you want to add or update tests, you can create a branch of that project, and
|
||||
|
||||
Before merging the PR on Github, we'll merge your branch on Share and restore `runtime_tests_version` to /main or maybe a release.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
runtime-tests/selected> run.native tests
|
||||
|
||||
()
|
||||
@ -17,7 +17,8 @@ runtime-tests/selected> run.native tests.jit.only
|
||||
Per Dan:
|
||||
It's testing a flaw in how we were sending code from a scratch file to the native runtime, when that happened multiple times.
|
||||
Related to the verifiable refs and recursive functions.
|
||||
```unison
|
||||
|
||||
``` unison
|
||||
foo = do
|
||||
go : Nat ->{Exception} ()
|
||||
go = cases
|
||||
@ -26,20 +27,20 @@ foo = do
|
||||
go 1000
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
I found and typechecked these definitions in scratch.u. If you
|
||||
do an `add` or `update`, here's how your codebase would
|
||||
change:
|
||||
|
||||
|
||||
⍟ These new definitions are ok to `add`:
|
||||
|
||||
|
||||
foo : '{Exception} ()
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> run.native foo
|
||||
|
||||
()
|
||||
@ -53,14 +54,14 @@ This can also only be tested by separately running this test, because
|
||||
it is exercising the protocol that ucm uses to talk to the jit during
|
||||
an exception.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
runtime-tests/selected> run.native testBug
|
||||
|
||||
💔💥
|
||||
|
||||
|
||||
I've encountered a call to builtin.bug with the following
|
||||
value:
|
||||
|
||||
|
||||
"testing"
|
||||
|
||||
```
|
||||
|
@ -1,10 +1,10 @@
|
||||
```ucm
|
||||
``` ucm
|
||||
test-html-docs/main> builtins.mergeio lib.builtins
|
||||
|
||||
Done.
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
{{A doc directly in the namespace.}}
|
||||
some.ns.direct = 1
|
||||
|
||||
@ -15,7 +15,7 @@ some.ns.pretty.deeply.nested = 2
|
||||
some.outside = 3
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -33,7 +33,7 @@ some.outside = 3
|
||||
some.outside.doc : Doc2
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
test-html-docs/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,9 +1,8 @@
|
||||
|
||||
## Structural find and replace
|
||||
|
||||
Here's a scratch file with some rewrite rules:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex1 = List.map (x -> x + 1) [1,2,3,4,5,6,7]
|
||||
|
||||
eitherToOptional e a =
|
||||
@ -30,7 +29,7 @@ rule2 x = @rewrite signature Optional ==> Optional2
|
||||
|
||||
Let's rewrite these:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> rewrite rule1
|
||||
|
||||
☝️
|
||||
@ -49,7 +48,7 @@ scratch/main> rewrite eitherToOptional
|
||||
The rewritten file has been added to the top of scratch.u
|
||||
|
||||
```
|
||||
```unison:added-by-ucm scratch.u
|
||||
``` unison:added-by-ucm scratch.u
|
||||
-- | Rewrote using:
|
||||
-- | Modified definition(s): ex1
|
||||
|
||||
@ -79,7 +78,7 @@ type Optional2 a = Some2 a | None2
|
||||
rule2 x = @rewrite signature Optional ==> Optional2
|
||||
```
|
||||
|
||||
```unison:added-by-ucm scratch.u
|
||||
``` unison:added-by-ucm scratch.u
|
||||
-- | Rewrote using:
|
||||
-- | Modified definition(s): Either.mapRight
|
||||
|
||||
@ -111,7 +110,7 @@ rule2 x = @rewrite signature Optional ==> Optional2
|
||||
|
||||
After adding to the codebase, here's the rewritten source:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> view ex1 Either.mapRight rule1
|
||||
|
||||
Either.mapRight : (a ->{g} b) -> Optional a ->{g} Optional b
|
||||
@ -137,7 +136,7 @@ scratch/main> view ex1 Either.mapRight rule1
|
||||
```
|
||||
Another example, showing that we can rewrite to definitions that only exist in the file:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
unique ability Woot1 where woot1 : () -> Nat
|
||||
unique ability Woot2 where woot2 : () -> Nat
|
||||
|
||||
@ -157,7 +156,7 @@ blah2 = 456
|
||||
|
||||
Let's apply the rewrite `woot1to2`:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> rewrite woot1to2
|
||||
|
||||
☝️
|
||||
@ -167,7 +166,7 @@ scratch/main> rewrite woot1to2
|
||||
The rewritten file has been added to the top of scratch.u
|
||||
|
||||
```
|
||||
```unison:added-by-ucm scratch.u
|
||||
``` unison:added-by-ucm scratch.u
|
||||
-- | Rewrote using:
|
||||
-- | Modified definition(s): wootEx
|
||||
|
||||
@ -193,7 +192,7 @@ blah2 = 456
|
||||
|
||||
After adding the rewritten form to the codebase, here's the rewritten `Woot1` to `Woot2`:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> view wootEx
|
||||
|
||||
wootEx : Nat ->{Woot2} Nat
|
||||
@ -204,7 +203,7 @@ scratch/main> view wootEx
|
||||
```
|
||||
This example shows that rewrite rules can to refer to term definitions that only exist in the file:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
foo1 =
|
||||
b = "b"
|
||||
123
|
||||
@ -225,7 +224,7 @@ sameFileEx =
|
||||
|
||||
After adding the rewritten form to the codebase, here's the rewritten definitions:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> view foo1 foo2 sameFileEx
|
||||
|
||||
foo1 : Nat
|
||||
@ -246,7 +245,7 @@ scratch/main> view foo1 foo2 sameFileEx
|
||||
```
|
||||
## Capture avoidance
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
bar1 =
|
||||
b = "bar"
|
||||
123
|
||||
@ -266,7 +265,7 @@ sameFileEx =
|
||||
|
||||
In the above example, `bar2` is locally bound by the rule, so when applied, it should not refer to the `bar2` top level binding.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> rewrite rule
|
||||
|
||||
☝️
|
||||
@ -276,7 +275,7 @@ scratch/main> rewrite rule
|
||||
The rewritten file has been added to the top of scratch.u
|
||||
|
||||
```
|
||||
```unison:added-by-ucm scratch.u
|
||||
``` unison:added-by-ucm scratch.u
|
||||
-- | Rewrote using:
|
||||
-- | Modified definition(s): sameFileEx
|
||||
|
||||
@ -300,7 +299,7 @@ sameFileEx =
|
||||
|
||||
Instead, it should be an unbound free variable, which doesn't typecheck:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> load
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
@ -321,7 +320,7 @@ scratch/main> load
|
||||
```
|
||||
In this example, the `a` is locally bound by the rule, so it shouldn't capture the `a = 39494` binding which is in scope at the point of the replacement:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
bar2 =
|
||||
a = 39494
|
||||
233
|
||||
@ -331,7 +330,7 @@ rule a = @rewrite
|
||||
term 233 ==> a
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> rewrite rule
|
||||
|
||||
☝️
|
||||
@ -341,7 +340,7 @@ scratch/main> rewrite rule
|
||||
The rewritten file has been added to the top of scratch.u
|
||||
|
||||
```
|
||||
```unison:added-by-ucm scratch.u
|
||||
``` unison:added-by-ucm scratch.u
|
||||
-- | Rewrote using:
|
||||
-- | Modified definition(s): bar2
|
||||
|
||||
@ -357,7 +356,7 @@ rule a =
|
||||
|
||||
The `a` introduced will be freshened to not capture the `a` in scope, so it remains as an unbound variable and is a type error:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> load
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
@ -378,16 +377,16 @@ scratch/main> load
|
||||
```
|
||||
## Structural find
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
eitherEx = Left ("hello", "there")
|
||||
```
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
findEitherEx x = @rewrite term Left ("hello", x) ==> Left ("hello" Text.++ x)
|
||||
findEitherFailure = @rewrite signature a . Either Failure a ==> ()
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> sfind findEitherEx
|
||||
|
||||
🔎
|
||||
|
@ -1,10 +1,10 @@
|
||||
This transcript verifies that the pretty-printer produces code that can be successfully parsed, for a variety of examples. Terms or types that fail to round-trip can be added to either `reparses-with-same-hash.u` or `reparses.u` as regression tests.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
x = ()
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -19,7 +19,7 @@ x = ()
|
||||
```
|
||||
So we can see the pretty-printed output:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/a1> edit 1-1000
|
||||
|
||||
☝️
|
||||
@ -30,7 +30,7 @@ scratch/a1> edit 1-1000
|
||||
definitions currently in this namespace.
|
||||
|
||||
```
|
||||
```unison:added-by-ucm scratch.u
|
||||
````` unison:added-by-ucm scratch.u
|
||||
structural ability Abort where abort : {Abort} a
|
||||
|
||||
structural ability Ask a where ask : {Ask a} a
|
||||
@ -766,11 +766,11 @@ UUID.randomUUIDBytes = do
|
||||
|
||||
(|>) : a -> (a ->{e} b) ->{e} b
|
||||
a |> f = f a
|
||||
```
|
||||
`````
|
||||
|
||||
This diff should be empty if the two namespaces are equivalent. If it's nonempty, the diff will show us the hashes that differ.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> diff.namespace /a1:. /a2:.
|
||||
|
||||
The namespaces are identical.
|
||||
@ -780,11 +780,11 @@ Now check that definitions in 'reparses.u' at least parse on round trip:
|
||||
|
||||
This just makes 'roundtrip.u' the latest scratch file.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
x = ()
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/a3> edit 1-5000
|
||||
|
||||
☝️
|
||||
@ -795,7 +795,7 @@ scratch/a3> edit 1-5000
|
||||
definitions currently in this namespace.
|
||||
|
||||
```
|
||||
```unison:added-by-ucm scratch.u
|
||||
```` unison:added-by-ucm scratch.u
|
||||
explanationOfThisFile : Text
|
||||
explanationOfThisFile =
|
||||
"""
|
||||
@ -815,11 +815,11 @@ sloppyDocEval =
|
||||
1 + 1
|
||||
```
|
||||
}}
|
||||
```
|
||||
````
|
||||
|
||||
These are currently all expected to have different hashes on round trip.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> diff.namespace /a3_new:. /a3:.
|
||||
|
||||
Updates:
|
||||
@ -835,7 +835,7 @@ scratch/main> diff.namespace /a3_new:. /a3:.
|
||||
|
||||
Regression test for https://github.com/unisonweb/unison/pull/3548
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/regressions> alias.term ##Nat.+ plus
|
||||
|
||||
Done.
|
||||
@ -856,7 +856,7 @@ scratch/regressions> load
|
||||
I loaded scratch.u and didn't find anything.
|
||||
|
||||
```
|
||||
```unison:added-by-ucm scratch.u
|
||||
``` unison:added-by-ucm scratch.u
|
||||
-- builtin plus : ##Nat -> ##Nat -> ##Nat
|
||||
```
|
||||
|
||||
|
@ -11,7 +11,7 @@ transcripts which contain less boilerplate.
|
||||
|
||||
The test shows that `hex (fromHex str) == str` as expected.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
test> hex.tests.ex1 = checks let
|
||||
s = "3984af9b"
|
||||
[hex (fromHex s) == s]
|
||||
@ -20,7 +20,7 @@ test> hex.tests.ex1 = checks let
|
||||
Lets do some basic testing of our test harness to make sure its
|
||||
working.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
testAutoClean : '{io2.IO}[Result]
|
||||
testAutoClean _ =
|
||||
go: '{Stream Result, Exception, io2.IO, TempDirs} Text
|
||||
@ -39,7 +39,7 @@ testAutoClean _ =
|
||||
Left (Failure _ t _) -> results :+ (Fail t)
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -52,7 +52,7 @@ testAutoClean _ =
|
||||
testAutoClean : '{IO} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,6 +1,6 @@
|
||||
This transcript is intended to make visible accidental changes to the hashing algorithm.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> find.verbose
|
||||
|
||||
1. -- #sgesq8035ut22q779pl1g4gqsg8c81894jjonmrq1bjltphkath225up841hk8dku59tnnc4laj9nggbofamgei4klof0ldc20uj2oo
|
||||
|
@ -1,4 +1,4 @@
|
||||
```unison
|
||||
``` unison
|
||||
unique type EncDec = EncDec Text (Nat -> Bytes) (Bytes -> Optional (Nat, Bytes))
|
||||
|
||||
BE64 = EncDec "64 bit Big Endian" encodeNat64be decodeNat64be
|
||||
@ -53,7 +53,7 @@ testABunchOfNats _ =
|
||||
(runTest (testNat 0))
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -75,7 +75,7 @@ testABunchOfNats _ =
|
||||
testRoundTrip : Nat -> EncDec ->{IO, Stream Result} ()
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,10 +1,9 @@
|
||||
|
||||
Test for code serialization operations.
|
||||
|
||||
Define a function, serialize it, then deserialize it back to an actual
|
||||
function. Also ask for its dependencies for display later.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
save : a -> Bytes
|
||||
save x = Value.serialize (Value.value x)
|
||||
|
||||
@ -152,7 +151,7 @@ swapped name link =
|
||||
rejected ("swapped " ++ name) rco
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -199,7 +198,7 @@ swapped name link =
|
||||
->{Throw Text} ()
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -241,7 +240,7 @@ scratch/main> add
|
||||
->{Throw Text} ()
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
structural ability Zap where
|
||||
zap : Three Nat Nat Nat
|
||||
|
||||
@ -316,7 +315,7 @@ badLoad _ =
|
||||
Left _ -> [Fail "Exception"]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -343,7 +342,7 @@ This simply runs some functions to make sure there isn't a crash. Once
|
||||
we gain the ability to capture output in a transcript, it can be modified
|
||||
to actual show that the serialization works.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -393,7 +392,7 @@ scratch/main> io.test badLoad
|
||||
Tip: Use view 1 to view the source of a test.
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
codeTests : '{io2.IO} [Result]
|
||||
codeTests =
|
||||
'[ idempotence "idem f" (termLink f)
|
||||
@ -429,7 +428,7 @@ codeTests =
|
||||
]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -442,7 +441,7 @@ codeTests =
|
||||
codeTests : '{IO} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -489,7 +488,7 @@ scratch/main> io.test codeTests
|
||||
Tip: Use view 1 to view the source of a test.
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
validateTest : Link.Term ->{IO} Result
|
||||
validateTest l = match Code.lookup l with
|
||||
None -> Fail "Couldn't look up link"
|
||||
@ -515,7 +514,7 @@ vtests _ =
|
||||
]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -529,7 +528,7 @@ vtests _ =
|
||||
vtests : '{IO} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -2,18 +2,18 @@
|
||||
|
||||
Unison documentation is written in Unison and has some neat features:
|
||||
|
||||
* The documentation type provides a rich vocabulary of elements that go beyond markdown, including asides, callouts, tooltips, and more.
|
||||
* Docs may contain Unison code which is parsed and typechecked to ensure validity. No more out of date examples that don't compile or assume a bunch of implicit context!
|
||||
* Embeded examples are live and can show the results of evaluation. This uses the same evaluation cache as Unison's scratch files, allowing Unison docs to function like well-commented spreadsheets or notebooks.
|
||||
* Links to other definitions are typechecked to ensure they point to valid definitions. The links are resolved to hashes and won't be broken by name changes or moving definitions around.
|
||||
* Docs can be included in other docs and you can assemble documentation programmatically, using Unison code.
|
||||
* There's a powerful textual syntax for all of the above, which we'll introduce next.
|
||||
- The documentation type provides a rich vocabulary of elements that go beyond markdown, including asides, callouts, tooltips, and more.
|
||||
- Docs may contain Unison code which is parsed and typechecked to ensure validity. No more out of date examples that don't compile or assume a bunch of implicit context\!
|
||||
- Embeded examples are live and can show the results of evaluation. This uses the same evaluation cache as Unison's scratch files, allowing Unison docs to function like well-commented spreadsheets or notebooks.
|
||||
- Links to other definitions are typechecked to ensure they point to valid definitions. The links are resolved to hashes and won't be broken by name changes or moving definitions around.
|
||||
- Docs can be included in other docs and you can assemble documentation programmatically, using Unison code.
|
||||
- There's a powerful textual syntax for all of the above, which we'll introduce next.
|
||||
|
||||
## Introduction
|
||||
|
||||
Documentation blocks start with `{{` and end with a matching `}}`. You can introduce doc blocks anywhere you'd use an expression, and you can also have anonymous documentation blocks immediately before a top-level term or type.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
name = {{Alice}}
|
||||
d1 = {{ Hello there {{name}}! }}
|
||||
|
||||
@ -28,7 +28,7 @@ The 7 days of the week, defined as:
|
||||
unique type time.DayOfWeek = Sun | Mon | Tue | Wed | Thu | Fri | Sat
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -50,7 +50,7 @@ Notice that an anonymous documentation block `{{ ... }}` before a definition `Im
|
||||
|
||||
You can preview what docs will look like when rendered to the console using the `display` or `docs` commands:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> display d1
|
||||
|
||||
Hello there Alice!
|
||||
@ -72,7 +72,7 @@ The `docs ImportantConstant` command will look for `ImportantConstant.doc` in th
|
||||
|
||||
First, we'll load the `syntax.u` file which has examples of all the syntax:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> load ./unison-src/transcripts-using-base/doc.md.files/syntax.u
|
||||
|
||||
Loading changes detected in
|
||||
@ -99,7 +99,7 @@ Now we can review different portions of the guide.
|
||||
we'll show both the pretty-printed source using `view`
|
||||
and the rendered output using `display`:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> view basicFormatting
|
||||
|
||||
basicFormatting : Doc2
|
||||
@ -548,7 +548,7 @@ scratch/main> display otherElements
|
||||
```
|
||||
Lastly, it's common to build longer documents including subdocuments via `{{ subdoc }}`. We can stitch together the full syntax guide in this way:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> view doc.guide
|
||||
|
||||
doc.guide : Doc2
|
||||
@ -769,3 +769,4 @@ scratch/main> display doc.guide
|
||||
|
||||
```
|
||||
🌻 THE END
|
||||
|
||||
|
@ -6,7 +6,7 @@ Exception ability directly, and the last is code validation. I don't
|
||||
have an easy way to test the last at the moment, but the other two are
|
||||
tested here.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
test1 : '{IO, Exception} [Result]
|
||||
test1 = do
|
||||
_ = fromUtf8 0xsee
|
||||
@ -18,7 +18,7 @@ test2 = do
|
||||
[Ok "test2"]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -32,7 +32,7 @@ test2 = do
|
||||
test2 : '{IO, Exception} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -41,7 +41,7 @@ scratch/main> add
|
||||
test2 : '{IO, Exception} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> io.test test1
|
||||
|
||||
💔💥
|
||||
@ -57,7 +57,7 @@ scratch/main> io.test test1
|
||||
##raise
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> io.test test2
|
||||
|
||||
💔💥
|
||||
|
@ -1,6 +1,6 @@
|
||||
This transcript tests an ability check failure regression.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
structural ability Async t g where
|
||||
fork : '{Async t g, g} a -> t a
|
||||
await : t a -> a
|
||||
@ -11,7 +11,7 @@ Async.parMap f as =
|
||||
List.map await tasks
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -36,6 +36,7 @@ some subtyping.
|
||||
|
||||
However, the ability handling was just processing rows in whatever
|
||||
order they occurred, and during inference it happened that `g`
|
||||
occurred in the row before `Async t g. Processing the stricter parts
|
||||
occurred in the row before `Async t g`. Processing the stricter parts
|
||||
first is better, becauase it can solve things more precisely and avoid
|
||||
ambiguities relating to subtyping.
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
This tests a case where a function was somehow discarding abilities.
|
||||
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
structural ability Trivial where
|
||||
trivial : ()
|
||||
|
||||
@ -25,7 +24,7 @@ wat = handleTrivial testAction -- Somehow this completely forgets about Excepti
|
||||
> handleTrivial testAction
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
|
||||
Tests a former error due to bad calling conventions on delay.impl
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
timingApp2 : '{IO, Exception} ()
|
||||
timingApp2 _ =
|
||||
printLine "Hello"
|
||||
@ -9,7 +8,7 @@ timingApp2 _ =
|
||||
printLine "World"
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -22,7 +21,7 @@ timingApp2 _ =
|
||||
timingApp2 : '{IO, Exception} ()
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> run timingApp2
|
||||
|
||||
()
|
||||
|
@ -1,7 +1,7 @@
|
||||
This file tests some obscure issues involved with abilities and over-applied
|
||||
functions.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
Stream.fromList : [a] -> '{Stream a} ()
|
||||
Stream.fromList l _ =
|
||||
_ = List.map (x -> emit x) l
|
||||
@ -31,7 +31,7 @@ increment n = 1 + n
|
||||
Stream.toList s2
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -62,7 +62,7 @@ increment n = 1 + n
|
||||
[100, 200, 300, 400]
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
structural ability E where
|
||||
eff : () -> ()
|
||||
|
||||
@ -82,7 +82,7 @@ foo _ =
|
||||
> h foo 337
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -105,7 +105,7 @@ foo _ =
|
||||
7
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
structural ability Over where
|
||||
over : Nat ->{Over} (Nat -> Nat)
|
||||
|
||||
@ -126,7 +126,7 @@ hmm =
|
||||
> hmm
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
```unison
|
||||
``` unison
|
||||
arrayList v n = do
|
||||
use ImmutableByteArray read8
|
||||
ma = Scope.bytearrayOf v n
|
||||
@ -13,7 +13,7 @@ arrayList v n = do
|
||||
> Scope.run '(catch (arrayList 7 8))
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
```unison
|
||||
``` unison
|
||||
{{
|
||||
A simple doc.
|
||||
}}
|
||||
meh = 9
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -19,7 +19,7 @@ meh = 9
|
||||
meh.doc : Doc2
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,7 +1,7 @@
|
||||
Test case for a variable capture problem during let floating. The
|
||||
encloser wasn't accounting for variables bound by matches.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ability Issue t where
|
||||
one : '{Issue t} () -> {Issue t} ()
|
||||
two : '{Issue t} () -> {Issue t} ()
|
||||
@ -35,7 +35,7 @@ run s =
|
||||
()
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
Checks for some bad type checking behavior. Some ability subtyping was
|
||||
too lenient when higher-order functions were involved.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
foreach : (a ->{g} ()) -> [a] ->{g} ()
|
||||
foreach f = cases
|
||||
[] -> ()
|
||||
@ -22,7 +22,7 @@ go = do
|
||||
foreach forkIt [thunk]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -38,9 +38,9 @@ go = do
|
||||
|
||||
|
||||
```
|
||||
This comes from issue #3513
|
||||
This comes from issue \#3513
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
(<<) : (b ->{e} c) -> (a ->{e} b) -> a ->{e} c
|
||||
(<<) f g x = f (g x)
|
||||
|
||||
@ -56,7 +56,7 @@ fancyTryEval : '{g, IO, Exception} a ->{g, IO, Exception} a
|
||||
fancyTryEval = reraise << catchAll.impl
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Unison has cryptographic builtins for hashing and computing [HMACs](https://en.wikipedia.org/wiki/HMAC) (hash-based message authentication codes). This transcript shows their usage and has some test cases.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> ls builtin.Bytes
|
||||
|
||||
1. ++ (Bytes -> Bytes -> Bytes)
|
||||
@ -45,7 +45,7 @@ Notice the `fromBase16` and `toBase16` functions. Here's some convenience functi
|
||||
|
||||
Here's a few usage examples:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex1 = fromHex "2947db"
|
||||
|> crypto.hashBytes Sha3_512
|
||||
|> hex
|
||||
@ -74,7 +74,7 @@ ex5 = crypto.hmac Sha2_256 mysecret f |> hex
|
||||
> ex5
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -119,7 +119,7 @@ ex5 = crypto.hmac Sha2_256 mysecret f |> hex
|
||||
```
|
||||
And here's the full API:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> find-in builtin.crypto
|
||||
|
||||
1. type CryptoFailure
|
||||
@ -155,11 +155,11 @@ scratch/main> find-in builtin.crypto
|
||||
```
|
||||
Note that the universal versions of `hash` and `hmac` are currently unimplemented and will bomb at runtime:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
> hash Sha3_256 (fromHex "3849238492")
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -177,9 +177,9 @@ Note that the universal versions of `hash` and `hmac` are currently unimplemente
|
||||
```
|
||||
## Hashing tests
|
||||
|
||||
Here are some test vectors (taken from [here](https://www.di-mgt.com.au/sha_testvectors.html) and [here](https://en.wikipedia.org/wiki/BLAKE_(hash_function))) for the various hashing algorithms:
|
||||
Here are some test vectors (taken from [here](https://www.di-mgt.com.au/sha_testvectors.html) and [here](https://en.wikipedia.org/wiki/BLAKE_\(hash_function\))) for the various hashing algorithms:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex alg input expected = checks [hashBytes alg (ascii input) == fromHex expected]
|
||||
|
||||
test> sha3_512.tests.ex1 =
|
||||
@ -311,7 +311,7 @@ test> crypto.hash.numTests =
|
||||
checks (List.map t (range 0 20))
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> test
|
||||
|
||||
Cached test results (`help testcache` to learn more)
|
||||
@ -351,7 +351,7 @@ scratch/main> test
|
||||
|
||||
These test vectors are taken from [RFC 4231](https://tools.ietf.org/html/rfc4231#section-4.3).
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex' alg secret msg expected = checks [hmacBytes alg (fromHex secret) (ascii msg) == fromHex expected]
|
||||
|
||||
test> hmac_sha2_256.tests.ex1 =
|
||||
@ -378,7 +378,7 @@ test> hmac_sha2_512.tests.ex2 =
|
||||
"164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737"
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -422,7 +422,7 @@ test> hmac_sha2_512.tests.ex2 =
|
||||
|
||||
Test vectors here pulled from [Wikipedia's writeup](https://en.wikipedia.org/wiki/MD5).
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex alg input expected = checks [hashBytes alg (ascii input) == fromHex expected]
|
||||
|
||||
test> md5.tests.ex1 =
|
||||
@ -441,7 +441,7 @@ test> md5.tests.ex3 =
|
||||
"e4d909c290d0fb1ca068ffaddf22cbd0"
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -473,7 +473,7 @@ test> md5.tests.ex3 =
|
||||
✅ Passed Passed
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> test
|
||||
|
||||
Cached test results (`help testcache` to learn more)
|
||||
|
@ -9,8 +9,7 @@ MVars are the building block on which many other concurrency
|
||||
primitives can be built, such as Futures, Run at most once initializer
|
||||
blocks, Queues, etc.
|
||||
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
eitherCk : (a -> Boolean) -> Either e a -> Boolean
|
||||
eitherCk f = cases
|
||||
Left _ -> false
|
||||
@ -51,7 +50,7 @@ testMvars _ =
|
||||
runTest test
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -65,7 +64,7 @@ testMvars _ =
|
||||
testMvars : '{IO} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,4 +1,4 @@
|
||||
```unison
|
||||
``` unison
|
||||
testNat: Nat -> Optional Int -> Optional Float -> {Stream Result}()
|
||||
testNat n expectInt expectFloat =
|
||||
float = Float.fromRepresentation n
|
||||
@ -31,7 +31,7 @@ test = 'let
|
||||
runTest testABunchOfNats
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -48,7 +48,7 @@ test = 'let
|
||||
->{Stream Result} ()
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,4 +1,4 @@
|
||||
```unison
|
||||
``` unison
|
||||
serverSocket = compose2 reraise IO.serverSocket.impl
|
||||
socketPort = compose reraise socketPort.impl
|
||||
listen = compose reraise listen.impl
|
||||
@ -16,14 +16,13 @@ socketAccept = compose reraise socketAccept.impl
|
||||
This section tests functions in the IO builtin related to binding to
|
||||
TCP server socket, as to be able to accept incoming TCP connections.
|
||||
|
||||
```builtin
|
||||
.io2.IO.serverSocket : Optional Text -> Text ->{io2.IO} Either Failure io2.Socket
|
||||
|
||||
```
|
||||
builtin.io2.IO.serverSocket : Optional Text -> Text ->{io2.IO} Either Failure io2.Socket
|
||||
```
|
||||
|
||||
This function takes two parameters, The first is the Hostname. If None
|
||||
is provided, We will attempt to bind to 0.0.0.0 (All ipv4
|
||||
addresses). We currently only support IPV4 (we should fix this!)
|
||||
addresses). We currently only support IPV4 (we should fix this\!)
|
||||
The second is the name of the port to bind to. This can be
|
||||
a decimal representation of a port number between 1-65535. This can be
|
||||
a named port like "ssh" (for port 22) or "kermit" (for port 1649),
|
||||
@ -34,11 +33,11 @@ stored in `/etc/services` and queried with the `getent` tool:
|
||||
# map number to name
|
||||
$ getent services 22
|
||||
ssh 22/tcp
|
||||
|
||||
|
||||
# map name to number
|
||||
$ getent services finger
|
||||
finger 79/tcp
|
||||
|
||||
|
||||
# get a list of all known names
|
||||
$ getent services | head
|
||||
tcpmux 1/tcp
|
||||
@ -54,7 +53,7 @@ stored in `/etc/services` and queried with the `getent` tool:
|
||||
|
||||
Below shows different examples of how we might specify the server coordinates.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
testExplicitHost : '{io2.IO} [Result]
|
||||
testExplicitHost _ =
|
||||
test = 'let
|
||||
@ -91,7 +90,7 @@ testDefaultPort _ =
|
||||
runTest test
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -106,7 +105,7 @@ testDefaultPort _ =
|
||||
testExplicitHost : '{IO} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -130,7 +129,7 @@ scratch/main> io.test testDefaultPort
|
||||
```
|
||||
This example demonstrates connecting a TCP client socket to a TCP server socket. A thread is started for both client and server. The server socket asks for any availalbe port (by passing "0" as the port number). The server thread then queries for the actual assigned port number, and puts that into an MVar which the client thread can read. The client thread then reads a string from the server and reports it back to the main thread via a different MVar.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
serverThread: MVar Nat -> Text -> '{io2.IO}()
|
||||
serverThread portVar toSend = 'let
|
||||
go : '{io2.IO, Exception}()
|
||||
@ -178,7 +177,7 @@ testTcpConnect = 'let
|
||||
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -193,7 +192,7 @@ testTcpConnect = 'let
|
||||
testTcpConnect : '{IO} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,4 +1,4 @@
|
||||
```unison
|
||||
``` unison
|
||||
directory = "unison-src/transcripts-using-base/serialized-cases/"
|
||||
|
||||
availableCases : '{IO,Exception} [Text]
|
||||
@ -55,7 +55,7 @@ serialTests = do
|
||||
List.map snd (bSort (List.map runTestCase cs))
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -73,7 +73,7 @@ serialTests = do
|
||||
shuffle : Nat -> [a] -> [a]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -3,7 +3,7 @@
|
||||
Ref support a CAS operation that can be used as a building block to
|
||||
change state atomically without locks.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
casTest: '{io2.IO} [Result]
|
||||
casTest = do
|
||||
test = do
|
||||
@ -18,7 +18,7 @@ casTest = do
|
||||
runTest test
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -31,7 +31,7 @@ casTest = do
|
||||
casTest : '{IO} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -52,7 +52,7 @@ scratch/main> io.test casTest
|
||||
```
|
||||
Promise is a simple one-shot awaitable condition.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
promiseSequentialTest : '{IO} [Result]
|
||||
promiseSequentialTest = do
|
||||
test = do
|
||||
@ -80,7 +80,7 @@ promiseConcurrentTest = do
|
||||
runTest test
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -94,7 +94,7 @@ promiseConcurrentTest = do
|
||||
promiseSequentialTest : '{IO} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -126,7 +126,7 @@ scratch/main> io.test promiseConcurrentTest
|
||||
```
|
||||
CAS can be used to write an atomic update function.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
atomicUpdate : Ref {IO} a -> (a -> a) ->{IO} ()
|
||||
atomicUpdate ref f =
|
||||
ticket = Ref.readForCas ref
|
||||
@ -134,7 +134,7 @@ atomicUpdate ref f =
|
||||
if Ref.cas ref ticket value then () else atomicUpdate ref f
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -147,7 +147,7 @@ atomicUpdate ref f =
|
||||
atomicUpdate : Ref {IO} a -> (a -> a) ->{IO} ()
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -158,7 +158,7 @@ scratch/main> add
|
||||
Promise can be used to write an operation that spawns N concurrent
|
||||
tasks and collects their results
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
spawnN : Nat -> '{IO} a ->{IO} [a]
|
||||
spawnN n fa =
|
||||
use Nat eq drop
|
||||
@ -173,7 +173,7 @@ spawnN n fa =
|
||||
map Promise.read (go n [])
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -186,7 +186,7 @@ spawnN n fa =
|
||||
spawnN : Nat -> '{IO} a ->{IO} [a]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -198,7 +198,7 @@ We can use these primitives to write a more interesting example, where
|
||||
multiple threads repeatedly update an atomic counter, we check that
|
||||
the value of the counter is correct after all threads are done.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
fullTest : '{IO} [Result]
|
||||
fullTest = do
|
||||
use Nat * + eq drop
|
||||
@ -222,7 +222,7 @@ fullTest = do
|
||||
runTest test
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -235,7 +235,7 @@ fullTest = do
|
||||
fullTest : '{IO} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,4 +1,4 @@
|
||||
```unison
|
||||
``` unison
|
||||
structural type Tree a = Leaf | Node (Tree a) a (Tree a)
|
||||
|
||||
foldMap : r -> (r -> r -> r) -> (a -> r) -> Tree a -> r
|
||||
@ -67,7 +67,7 @@ mkTestCase = do
|
||||
saveTestCase "case-00" "v4" f tup
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -94,7 +94,7 @@ mkTestCase = do
|
||||
tree3 : Tree Text
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,4 +1,4 @@
|
||||
```unison
|
||||
``` unison
|
||||
l1 = [1.0,2.0,3.0]
|
||||
l2 = [+1,+2,+3]
|
||||
l3 = [?a, ?b, ?c]
|
||||
@ -15,7 +15,7 @@ mkTestCase = do
|
||||
saveTestCase "case-01" "v4" combines (l1, l2, l3)
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -32,7 +32,7 @@ mkTestCase = do
|
||||
mkTestCase : '{IO, Exception} ()
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,4 +1,4 @@
|
||||
```unison
|
||||
``` unison
|
||||
structural ability Exit a where
|
||||
exit : a -> b
|
||||
|
||||
@ -29,7 +29,7 @@ mkTestCase = do
|
||||
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -48,7 +48,7 @@ mkTestCase = do
|
||||
products : ([Nat], [Nat], [Nat]) -> Text
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,4 +1,4 @@
|
||||
```unison
|
||||
``` unison
|
||||
structural ability DC r where
|
||||
shift : ((a -> r) -> r) -> a
|
||||
|
||||
@ -43,7 +43,7 @@ mkTestCase = do
|
||||
saveTestCase "case-03" "v4" finish trip
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -67,7 +67,7 @@ mkTestCase = do
|
||||
suspSum : [Nat] -> Delayed Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,4 +1,4 @@
|
||||
```unison
|
||||
``` unison
|
||||
mutual0 = cases
|
||||
0 -> "okay"
|
||||
n ->
|
||||
@ -12,7 +12,7 @@ mkTestCase = do
|
||||
saveTestCase "case-04" "v4" mutual1 5
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -27,7 +27,7 @@ mkTestCase = do
|
||||
mutual1 : Nat -> Text
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,6 +1,7 @@
|
||||
Loops that access a shared counter variable, accessed in transactions.
|
||||
Some thread delaying is just accomplished by counting in a loop.
|
||||
```unison
|
||||
|
||||
``` unison
|
||||
count : Nat -> ()
|
||||
count = cases
|
||||
0 -> ()
|
||||
@ -27,7 +28,7 @@ body k out v =
|
||||
atomically '(TVar.write out (Some n))
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -43,7 +44,7 @@ body k out v =
|
||||
loop : '{IO} Nat -> Nat -> Nat ->{IO} Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -56,7 +57,7 @@ scratch/main> add
|
||||
```
|
||||
Test case.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
spawn : Nat ->{io2.IO} Result
|
||||
spawn k = let
|
||||
out1 = TVar.newIO None
|
||||
@ -89,7 +90,7 @@ tests : '{io2.IO} [Result]
|
||||
tests = '(map spawn nats)
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -105,7 +106,7 @@ tests = '(map spawn nats)
|
||||
tests : '{IO} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -4,18 +4,18 @@ https://github.com/unisonweb/unison/issues/2195
|
||||
|
||||
We add a simple definition.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
x = 999
|
||||
```
|
||||
|
||||
Now, we update that definition and define a test-watch which depends on it.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
x = 1000
|
||||
test> mytest = checks [x + 1 == 1001]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -42,7 +42,7 @@ test> mytest = checks [x + 1 == 1001]
|
||||
```
|
||||
We expect this 'add' to fail because the test is blocked by the update to `x`.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
x These definitions failed:
|
||||
@ -54,14 +54,14 @@ scratch/main> add
|
||||
Tip: Use `help filestatus` to learn more.
|
||||
|
||||
```
|
||||
---
|
||||
-----
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
y = 42
|
||||
test> useY = checks [y + 1 == 43]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -84,7 +84,7 @@ test> useY = checks [y + 1 == 43]
|
||||
```
|
||||
This should correctly identify `y` as a dependency and add that too.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add useY
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,6 +1,6 @@
|
||||
Lets just make sure we can start a thread
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
otherThread : '{io2.IO}()
|
||||
otherThread = 'let
|
||||
watch "I'm the other Thread" ()
|
||||
@ -16,7 +16,7 @@ testBasicFork = 'let
|
||||
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -32,7 +32,7 @@ testBasicFork = 'let
|
||||
```
|
||||
See if we can get another thread to stuff a value into a MVar
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
thread1 : Nat -> MVar Nat -> '{io2.IO}()
|
||||
thread1 x mv = 'let
|
||||
go = 'let
|
||||
@ -56,7 +56,7 @@ testBasicMultiThreadMVar = 'let
|
||||
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -70,7 +70,7 @@ testBasicMultiThreadMVar = 'let
|
||||
thread1 : Nat -> MVar Nat -> '{IO} ()
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -89,7 +89,7 @@ scratch/main> io.test testBasicMultiThreadMVar
|
||||
Tip: Use view 1 to view the source of a test.
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
sendingThread: Nat -> MVar Nat -> '{io2.IO}()
|
||||
sendingThread toSend mv = 'let
|
||||
go = 'let
|
||||
@ -127,7 +127,7 @@ testTwoThreads = 'let
|
||||
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -143,7 +143,7 @@ testTwoThreads = 'let
|
||||
testTwoThreads : '{IO} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Tests for TLS builtins
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
-- generated with:
|
||||
-- openssl req -newkey rsa:2048 -subj '/CN=test.unison.cloud/O=Unison/C=US' -nodes -keyout key.pem -x509 -days 3650 -out cert.pem
|
||||
|
||||
@ -15,7 +15,7 @@ not_a_cert = "-----BEGIN SCHERMIFICATE-----\n-----END SCHERMIFICATE-----"
|
||||
|
||||
First lets make sure we can load our cert and private key
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
this_should_work=match (decodeCert.impl (toUtf8 self_signed_cert_pem2) with
|
||||
Left (Failure _ t _) -> [Fail t]
|
||||
Right _ -> [Ok "succesfully decoded self_signed_pem"]
|
||||
@ -27,7 +27,7 @@ this_should_not_work=match (decodeCert.impl (toUtf8 not_a_cert) with
|
||||
what_should_work _ = this_should_work ++ this_should_not_work
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -42,7 +42,7 @@ what_should_work _ = this_should_work ++ this_should_not_work
|
||||
what_should_work : ∀ _. _ -> [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -71,7 +71,7 @@ We'll create a server and a client, and start threads for each.
|
||||
The server will report the port it is bound to via a passed MVar which
|
||||
the client can read.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
serverThread: MVar Nat -> Text -> '{io2.IO}()
|
||||
serverThread portVar toSend = 'let
|
||||
go: '{io2.IO, Exception}()
|
||||
@ -217,7 +217,7 @@ testCNReject _ =
|
||||
runTest test
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -237,7 +237,7 @@ testCNReject _ =
|
||||
testConnectSelfSigned : '{IO} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,8 +1,8 @@
|
||||
Test for new Text -> Bytes conversions explicitly using UTF-8 as the encoding
|
||||
Test for new Text -\> Bytes conversions explicitly using UTF-8 as the encoding
|
||||
|
||||
Unison has function for converting between `Text` and a UTF-8 `Bytes` encoding of the Text.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> find Utf8
|
||||
|
||||
1. builtin.Text.toUtf8 : Text -> Bytes
|
||||
@ -13,7 +13,7 @@ scratch/main> find Utf8
|
||||
```
|
||||
ascii characters are encoded as single bytes (in the range 0-127).
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ascii: Text
|
||||
ascii = "ABCDE"
|
||||
|
||||
@ -21,7 +21,7 @@ ascii = "ABCDE"
|
||||
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -44,14 +44,14 @@ ascii = "ABCDE"
|
||||
```
|
||||
non-ascii characters are encoded as multiple bytes.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
greek: Text
|
||||
greek = "ΑΒΓΔΕ"
|
||||
|
||||
> toUtf8 greek
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -73,7 +73,7 @@ greek = "ΑΒΓΔΕ"
|
||||
```
|
||||
We can check that encoding and then decoding should give us back the same `Text` we started with
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
checkRoundTrip: Text -> [Result]
|
||||
checkRoundTrip t =
|
||||
bytes = toUtf8 t
|
||||
@ -86,7 +86,7 @@ greek = "ΑΒΓΔΕ"
|
||||
test> greekTest = checkRoundTrip greek
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -110,7 +110,7 @@ test> greekTest = checkRoundTrip greek
|
||||
```
|
||||
If we try to decode an invalid set of bytes, we get back `Text` explaining the decoding error:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
greek_bytes = Bytes.fromList [206, 145, 206, 146, 206, 147, 206, 148, 206]
|
||||
|
||||
|
||||
@ -121,7 +121,7 @@ greek_bytes = Bytes.fromList [206, 145, 206, 146, 206, 147, 206, 148, 206]
|
||||
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
|
||||
Some random ability stuff to ensure things work.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
unique ability A where
|
||||
one : Nat ->{A} Nat
|
||||
two : Nat -> Nat ->{A} Nat
|
||||
@ -17,7 +16,7 @@ ha = cases
|
||||
{ four i -> c } -> handle c (j k l -> i+j+k+l) with ha
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -31,7 +30,7 @@ ha = cases
|
||||
ha : Request {A} r -> r
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,6 +1,6 @@
|
||||
The order of a set of abilities is normalized before hashing.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
unique ability Foo where
|
||||
foo : ()
|
||||
|
||||
@ -14,7 +14,7 @@ term2 : () ->{Bar, Foo} ()
|
||||
term2 _ = ()
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -30,7 +30,7 @@ term2 _ = ()
|
||||
term2 : '{Bar, Foo} ()
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -5,12 +5,12 @@ https://github.com/unisonweb/unison/issues/2786
|
||||
First we add an ability to the codebase.
|
||||
Note that this will create the name `Channels.send` as an ability constructor.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
unique ability Channels where
|
||||
send : a -> {Channels} ()
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -23,7 +23,7 @@ unique ability Channels where
|
||||
ability Channels
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -31,11 +31,11 @@ scratch/main> add
|
||||
ability Channels
|
||||
|
||||
```
|
||||
Now we update the ability, changing the name of the constructor, _but_, we simultaneously
|
||||
Now we update the ability, changing the name of the constructor, *but*, we simultaneously
|
||||
add a new top-level term with the same name as the constructor which is being
|
||||
removed from Channels.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
unique ability Channels where
|
||||
sends : [a] -> {Channels} ()
|
||||
|
||||
@ -46,7 +46,7 @@ thing : '{Channels} ()
|
||||
thing _ = send 1
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -67,7 +67,7 @@ thing _ = send 1
|
||||
```
|
||||
These should fail with a term/ctor conflict since we exclude the ability from the update.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> update.old patch Channels.send
|
||||
|
||||
x These definitions failed:
|
||||
@ -89,9 +89,9 @@ scratch/main> update.old patch thing
|
||||
ability Channels
|
||||
|
||||
```
|
||||
If however, `Channels.send` and `thing` _depend_ on `Channels`, updating them should succeed since it pulls in the ability as a dependency.
|
||||
If however, `Channels.send` and `thing` *depend* on `Channels`, updating them should succeed since it pulls in the ability as a dependency.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
unique ability Channels where
|
||||
sends : [a] -> {Channels} ()
|
||||
|
||||
@ -102,7 +102,7 @@ thing : '{Channels} ()
|
||||
thing _ = send 1
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -121,7 +121,7 @@ thing _ = send 1
|
||||
```
|
||||
These updates should succeed since `Channels` is a dependency.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> update.old.preview patch Channels.send
|
||||
|
||||
I found and typechecked these definitions in scratch.u. If you
|
||||
@ -152,7 +152,7 @@ scratch/main> update.old.preview patch thing
|
||||
```
|
||||
We should also be able to successfully update the whole thing.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> update.old
|
||||
|
||||
⊡ Ignored previously added definitions: Channels
|
||||
@ -165,11 +165,11 @@ scratch/main> update.old
|
||||
```
|
||||
# Constructor-term conflict
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
X.x = 1
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -182,7 +182,7 @@ X.x = 1
|
||||
X.x : Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main2> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -190,12 +190,12 @@ scratch/main2> add
|
||||
X.x : Nat
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
structural ability X where
|
||||
x : ()
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -214,7 +214,7 @@ structural ability X where
|
||||
```
|
||||
This should fail with a ctor/term conflict.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main2> add
|
||||
|
||||
x These definitions failed:
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
## Basic usage
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
even : Nat -> Boolean
|
||||
even x = if x == 0 then true else odd (drop x 1)
|
||||
|
||||
@ -13,7 +13,7 @@ is2even : 'Boolean
|
||||
is2even = '(even 2)
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -30,7 +30,7 @@ is2even = '(even 2)
|
||||
```
|
||||
it errors if there isn't a previous run
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add.run foo
|
||||
|
||||
⚠️
|
||||
@ -39,7 +39,7 @@ scratch/main> add.run foo
|
||||
something before attempting to save it.
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> run is2even
|
||||
|
||||
true
|
||||
@ -47,7 +47,8 @@ scratch/main> run is2even
|
||||
```
|
||||
it errors if the desired result name conflicts with a name in the
|
||||
unison file
|
||||
```ucm
|
||||
|
||||
``` ucm
|
||||
scratch/main> add.run is2even
|
||||
|
||||
⚠️
|
||||
@ -57,7 +58,8 @@ scratch/main> add.run is2even
|
||||
|
||||
```
|
||||
otherwise, the result is successfully persisted
|
||||
```ucm
|
||||
|
||||
``` ucm
|
||||
scratch/main> add.run foo.bar.baz
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -65,7 +67,7 @@ scratch/main> add.run foo.bar.baz
|
||||
foo.bar.baz : Boolean
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> view foo.bar.baz
|
||||
|
||||
foo.bar.baz : Boolean
|
||||
@ -74,7 +76,7 @@ scratch/main> view foo.bar.baz
|
||||
```
|
||||
## It resolves references within the unison file
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
z b = b Nat.+ 12
|
||||
y a b = a Nat.+ b Nat.+ z 10
|
||||
|
||||
@ -85,7 +87,7 @@ main : '{IO, Exception} (Nat -> Nat -> Nat)
|
||||
main _ = y
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -100,7 +102,7 @@ main _ = y
|
||||
z : Nat -> Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> run main
|
||||
|
||||
a b -> a Nat.+ b Nat.+ z 10
|
||||
@ -115,12 +117,12 @@ scratch/main> add.run result
|
||||
```
|
||||
## It resolves references within the codebase
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
inc : Nat -> Nat
|
||||
inc x = x + 1
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -133,7 +135,7 @@ inc x = x + 1
|
||||
inc : Nat -> Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add inc
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -141,12 +143,12 @@ scratch/main> add inc
|
||||
inc : Nat -> Nat
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
main : '(Nat -> Nat)
|
||||
main _ x = inc x
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -159,7 +161,7 @@ main _ x = inc x
|
||||
main : '(Nat -> Nat)
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> run main
|
||||
|
||||
inc
|
||||
@ -178,13 +180,13 @@ scratch/main> view natfoo
|
||||
```
|
||||
## It captures scratch file dependencies at run time
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
x = 1
|
||||
y = x + x
|
||||
main = 'y
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -199,17 +201,17 @@ main = 'y
|
||||
y : Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> run main
|
||||
|
||||
2
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
x = 50
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -223,7 +225,8 @@ x = 50
|
||||
|
||||
```
|
||||
this saves 2 to xres, rather than 100
|
||||
```ucm
|
||||
|
||||
``` ucm
|
||||
scratch/main> add.run xres
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -238,11 +241,11 @@ scratch/main> view xres
|
||||
```
|
||||
## It fails with a message if add cannot complete cleanly
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
main = '5
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -255,7 +258,7 @@ main = '5
|
||||
main : 'Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> run main
|
||||
|
||||
5
|
||||
@ -272,11 +275,11 @@ scratch/main> add.run xres
|
||||
```
|
||||
## It works with absolute names
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
main = '5
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -289,7 +292,7 @@ main = '5
|
||||
main : 'Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> run main
|
||||
|
||||
5
|
||||
|
@ -1,11 +1,11 @@
|
||||
```unison
|
||||
``` unison
|
||||
test> foo : [Test.Result]
|
||||
foo = []
|
||||
```
|
||||
|
||||
Apparently when we add a test watch, we add a type annotation to it, even if it already has one. We don't want this to happen though!
|
||||
Apparently when we add a test watch, we add a type annotation to it, even if it already has one. We don't want this to happen though\!
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Let's set up some definitions to start:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
x = 1
|
||||
y = 2
|
||||
|
||||
@ -10,7 +10,7 @@ structural type X = One Nat
|
||||
structural type Y = Two Nat Nat
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -28,7 +28,7 @@ structural type Y = Two Nat Nat
|
||||
```
|
||||
Expected: `x` and `y`, `X`, and `Y` exist as above. UCM tells you this.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -41,13 +41,13 @@ scratch/main> add
|
||||
```
|
||||
Let's add an alias for `1` and `One`:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
z = 1
|
||||
|
||||
structural type Z = One Nat
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -66,7 +66,7 @@ structural type Z = One Nat
|
||||
Expected: `z` is now `1`. UCM tells you that this definition is also called `x`.
|
||||
Also, `Z` is an alias for `X`.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -79,12 +79,12 @@ scratch/main> add
|
||||
```
|
||||
Let's update something that has an alias (to a value that doesn't have a name already):
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
x = 3
|
||||
structural type X = Three Nat Nat Nat
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -103,7 +103,7 @@ structural type X = Three Nat Nat Nat
|
||||
```
|
||||
Expected: `x` is now `3` and `X` has constructor `Three`. UCM tells you the old definitions were also called `z` and `Z` and these names have also been updated.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> update
|
||||
|
||||
Okay, I'm searching the branch for code that needs to be
|
||||
@ -118,12 +118,12 @@ scratch/main> update
|
||||
```
|
||||
Update it to something that already exists with a different name:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
x = 2
|
||||
structural type X = Two Nat Nat
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -142,7 +142,7 @@ structural type X = Two Nat Nat
|
||||
```
|
||||
Expected: `x` is now `2` and `X` is `Two`. UCM says the old definition was also named `z/Z`, and was also updated. And it says the new definition is also named `y/Y`.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> update
|
||||
|
||||
Okay, I'm searching the branch for code that needs to be
|
||||
|
@ -1,19 +1,16 @@
|
||||
The `alias.many` command can be used to copy definitions from the current namespace into your curated one.
|
||||
The names that will be used in the target namespace are the names you specify, relative to the current namespace:
|
||||
|
||||
```scratch
|
||||
/main> help alias.many
|
||||
scratch/main> help alias.many
|
||||
|
||||
alias.many (or copy)
|
||||
`alias.many <relative1> [relative2...] <namespace>` creates aliases `relative1`, `relative2`, ...
|
||||
in the namespace `namespace`.
|
||||
`alias.many foo.foo bar.bar .quux` creates aliases `.quux.foo.foo` and `.quux.bar.bar`.
|
||||
|
||||
alias.many (or copy)
|
||||
`alias.many <relative1> [relative2...] <namespace>` creates aliases `relative1`, `relative2`, ...
|
||||
in the namespace `namespace`.
|
||||
`alias.many foo.foo bar.bar .quux` creates aliases `.quux.foo.foo` and `.quux.bar.bar`.
|
||||
Let's try it\!
|
||||
|
||||
```
|
||||
|
||||
Let's try it!
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> alias.many List.adjacentPairs List.all List.any List.chunk List.chunksOf List.dropWhile List.first List.init List.intersperse List.isEmpty List.last List.replicate List.splitAt List.tail List.takeWhile mylib
|
||||
|
||||
Here's what changed in mylib :
|
||||
@ -63,4 +60,5 @@ scratch/main> find-in mylib
|
||||
|
||||
|
||||
```
|
||||
Thanks, `alias.many!
|
||||
Thanks, `alias.many`\!
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
`alias.term` makes a new name for a term.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
project/main> alias.term lib.builtins.bug foo
|
||||
|
||||
Done.
|
||||
@ -13,7 +13,7 @@ project/main> ls
|
||||
```
|
||||
It won't create a conflicted name, though.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
project/main> alias.term lib.builtins.todo foo
|
||||
|
||||
⚠️
|
||||
@ -21,7 +21,7 @@ project/main> alias.term lib.builtins.todo foo
|
||||
A term by that name already exists.
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
project/main> ls
|
||||
|
||||
1. foo (a -> b)
|
||||
@ -30,7 +30,7 @@ project/main> ls
|
||||
```
|
||||
You can use `debug.alias.term.force` for that.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
project/main> debug.alias.term.force lib.builtins.todo foo
|
||||
|
||||
Done.
|
||||
|
@ -1,6 +1,6 @@
|
||||
`alias.type` makes a new name for a type.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
project/main> alias.type lib.builtins.Nat Foo
|
||||
|
||||
Done.
|
||||
@ -13,7 +13,7 @@ project/main> ls
|
||||
```
|
||||
It won't create a conflicted name, though.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
project/main> alias.type lib.builtins.Int Foo
|
||||
|
||||
⚠️
|
||||
@ -21,7 +21,7 @@ project/main> alias.type lib.builtins.Int Foo
|
||||
A type by that name already exists.
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
project/main> ls
|
||||
|
||||
1. Foo (builtin type)
|
||||
@ -30,7 +30,7 @@ project/main> ls
|
||||
```
|
||||
You can use `debug.alias.type.force` for that.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
project/main> debug.alias.type.force lib.builtins.Int Foo
|
||||
|
||||
Done.
|
||||
|
@ -1,15 +1,14 @@
|
||||
|
||||
This tests a variable related bug in the ANF compiler.
|
||||
|
||||
The nested let would get flattened out, resulting in:
|
||||
|
||||
bar = result
|
||||
|
||||
which would be handled by renaming. However, the _context_ portion of
|
||||
which would be handled by renaming. However, the *context* portion of
|
||||
the rest of the code was not being renamed correctly, so `bar` would
|
||||
remain in the definition of `baz`.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
foo _ =
|
||||
id x = x
|
||||
void x = ()
|
||||
@ -24,7 +23,7 @@ foo _ =
|
||||
> !foo
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -44,7 +43,7 @@ foo _ =
|
||||
5
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Any.unsafeExtract is a way to extract the value contained in an Any. This is unsafe because it allows the programmer to coerce a value into any type, which would cause undefined behaviour if used to coerce a value to the wrong type.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
test> Any.unsafeExtract.works =
|
||||
use Nat !=
|
||||
checks [1 == Any.unsafeExtract (Any 1),
|
||||
@ -11,7 +11,7 @@ test> Any.unsafeExtract.works =
|
||||
]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -31,7 +31,7 @@ test> Any.unsafeExtract.works =
|
||||
✅ Passed Passed
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Doc rendering
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
structural type Maybe a = Nothing | Just a
|
||||
otherTerm = "text"
|
||||
|
||||
@ -77,7 +77,7 @@ Transclusion/evaluation:
|
||||
term = 42
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> display term.doc
|
||||
|
||||
# Heading
|
||||
@ -146,7 +146,7 @@ scratch/main> display term.doc
|
||||
message
|
||||
|
||||
```
|
||||
```api
|
||||
``` api
|
||||
GET /api/projects/scratch/branches/main/getDefinition?names=term
|
||||
{
|
||||
"missingDefinitions": [],
|
||||
@ -940,4 +940,5 @@ GET /api/projects/scratch/branches/main/getDefinition?names=term
|
||||
},
|
||||
"typeDefinitions": {}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
# find api
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
rachel.filesystem.x = 42
|
||||
ross.httpClient.y = 43
|
||||
joey.httpServer.z = 44
|
||||
joey.yaml.zz = 45
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -23,7 +23,7 @@ joey.yaml.zz = 45
|
||||
ross.httpClient.y : ##Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -34,7 +34,7 @@ scratch/main> add
|
||||
ross.httpClient.y : ##Nat
|
||||
|
||||
```
|
||||
```api
|
||||
``` api
|
||||
-- Namespace segment prefix search
|
||||
GET /api/projects/scratch/branches/main/find?query=http
|
||||
[
|
||||
@ -252,4 +252,5 @@ GET /api/projects/scratch/branches/main/find?query=joey.http
|
||||
}
|
||||
]
|
||||
]
|
||||
```
|
||||
```
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
# Get Definitions Test
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
nested.names.x.doc = {{ Documentation }}
|
||||
nested.names.x = 42
|
||||
```
|
||||
|
||||
```api
|
||||
``` api
|
||||
-- Should NOT find names by suffix
|
||||
GET /api/projects/scratch/branches/main/getDefinition?names=x
|
||||
{
|
||||
@ -205,7 +205,9 @@ GET /api/projects/scratch/branches/main/getDefinition?names=%23qkhkl0n238&relati
|
||||
},
|
||||
"typeDefinitions": {}
|
||||
}
|
||||
``````unison
|
||||
```
|
||||
|
||||
``` unison
|
||||
doctest.thing.doc = {{ The correct docs for the thing }}
|
||||
doctest.thing = "A thing"
|
||||
doctest.thingalias.doc = {{ Docs for the alias, should not be displayed }}
|
||||
@ -216,7 +218,7 @@ doctest.otherstuff.thing = "A different thing"
|
||||
|
||||
Only docs for the term we request should be returned, even if there are other term docs with the same suffix.
|
||||
|
||||
```api
|
||||
``` api
|
||||
GET /api/projects/scratch/branches/main/getDefinition?names=thing&relativeTo=doctest
|
||||
{
|
||||
"missingDefinitions": [],
|
||||
@ -332,9 +334,11 @@ GET /api/projects/scratch/branches/main/getDefinition?names=thing&relativeTo=doc
|
||||
},
|
||||
"typeDefinitions": {}
|
||||
}
|
||||
```If we request a doc, the api should return the source, but also the rendered doc should appear in the 'termDocs' list.
|
||||
```
|
||||
|
||||
```api
|
||||
If we request a doc, the api should return the source, but also the rendered doc should appear in the 'termDocs' list.
|
||||
|
||||
``` api
|
||||
GET /api/projects/scratch/branches/main/getDefinition?names=thing.doc&relativeTo=doctest
|
||||
{
|
||||
"missingDefinitions": [],
|
||||
@ -507,4 +511,5 @@ GET /api/projects/scratch/branches/main/getDefinition?names=thing.doc&relativeTo
|
||||
},
|
||||
"typeDefinitions": {}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# List Projects And Branches Test
|
||||
|
||||
```api
|
||||
``` api
|
||||
-- Should list all projects
|
||||
GET /api/projects
|
||||
[
|
||||
@ -53,4 +53,5 @@ GET /api/projects/project-one/branches?prefix=branch-t
|
||||
"branchName": "branch-two"
|
||||
}
|
||||
]
|
||||
```
|
||||
```
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Namespace Details Test
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
{{ Documentation }}
|
||||
nested.names.x = 42
|
||||
|
||||
@ -9,7 +9,7 @@ Here's a *README*!
|
||||
}}
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -24,7 +24,7 @@ Here's a *README*!
|
||||
nested.names.x.doc : Doc2
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -34,7 +34,7 @@ scratch/main> add
|
||||
nested.names.x.doc : Doc2
|
||||
|
||||
```
|
||||
```api
|
||||
``` api
|
||||
-- Should find names by suffix
|
||||
GET /api/projects/scratch/branches/main/namespaces/nested.names
|
||||
{
|
||||
@ -78,4 +78,5 @@ GET /api/projects/scratch/branches/main/namespaces/nested.names
|
||||
"tag": "Paragraph"
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
# Namespace list api
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
{{ Documentation }}
|
||||
nested.names.x = 42
|
||||
|
||||
nested.names.readme = {{ I'm a readme! }}
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -22,7 +22,7 @@ nested.names.readme = {{ I'm a readme! }}
|
||||
nested.names.x.doc : Doc2
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -32,7 +32,7 @@ scratch/main> add
|
||||
nested.names.x.doc : Doc2
|
||||
|
||||
```
|
||||
```api
|
||||
``` api
|
||||
GET /api/projects/scratch/branches/main/list?namespace=nested.names
|
||||
{
|
||||
"namespaceListingChildren": [
|
||||
@ -131,4 +131,5 @@ GET /api/projects/scratch/branches/main/list?namespace=names&relativeTo=nested
|
||||
"namespaceListingFQN": "nested.names",
|
||||
"namespaceListingHash": "#oms19b4f9s3c8tb5skeb8jii95ij35n3hdg038pu6rv5b0fikqe4gd7lnu6a1i6aq5tdh2opdo4s0sfrupvk6vfkr9lf0n752gbl8o0"
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Definition Summary APIs
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
nat : Nat
|
||||
nat = 42
|
||||
doc : Doc2
|
||||
@ -21,7 +21,7 @@ structural ability Stream s where
|
||||
|
||||
## Term Summary APIs
|
||||
|
||||
```api
|
||||
``` api
|
||||
-- term
|
||||
GET /api/projects/scratch/branches/main/definitions/terms/by-hash/@qkhkl0n238s1eqibd1ecb8605sqj1m4hpoaag177cu572otqlaf1u28c8suuuqgljdtthsjtr07rv04np05o6oa27ml9105k7uas0t8/summary?name=nat
|
||||
{
|
||||
@ -667,9 +667,11 @@ GET /api/projects/scratch/branches/main/definitions/terms/by-hash/@@IO.putBytes.
|
||||
},
|
||||
"tag": "Plain"
|
||||
}
|
||||
```## Type Summary APIs
|
||||
```
|
||||
|
||||
```api
|
||||
## Type Summary APIs
|
||||
|
||||
``` api
|
||||
-- data
|
||||
GET /api/projects/scratch/branches/main/definitions/types/by-hash/@altimqs66j3dh94dpab5pg7j5adjrndq61n803j7fg0v0ohdiut6or66bu1fiongpd45s5euiuo8ru47b928aqv8osln1ikdeg05hq0/summary?name=Thing
|
||||
{
|
||||
@ -823,4 +825,5 @@ GET /api/projects/scratch/branches/main/definitions/types/by-hash/@@Nat/summary?
|
||||
},
|
||||
"tag": "Data"
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
|
@ -2,11 +2,11 @@
|
||||
|
||||
Should block an `add` if it requires an update on an in-file dependency.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
x = 1
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -19,7 +19,7 @@ x = 1
|
||||
x : Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -29,12 +29,12 @@ scratch/main> add
|
||||
```
|
||||
Update `x`, and add a new `y` which depends on the update
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
x = 10
|
||||
y = x + 1
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -54,7 +54,7 @@ y = x + 1
|
||||
```
|
||||
Try to add only the new `y`. This should fail because it requires an update to `x`, but we only ran an 'add'.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add y
|
||||
|
||||
x These definitions failed:
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
For example:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex thing =
|
||||
thing y = y
|
||||
-- refers to `thing` in this block
|
||||
@ -15,7 +15,7 @@ ex thing =
|
||||
> ex "hello"
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -39,7 +39,7 @@ ex thing =
|
||||
|
||||
The `thing` reference in `bar` refers to the one declared locally in the block that `bar` is part of. This is true even if the declaration which shadows the outer name appears later in the block, for instance:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex thing =
|
||||
bar x = thing x + 1
|
||||
thing y = y
|
||||
@ -48,7 +48,7 @@ ex thing =
|
||||
> ex "hello"
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -72,7 +72,7 @@ ex thing =
|
||||
|
||||
This is just the normal lexical scoping behavior. For example:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex thing =
|
||||
bar x = thing x + 1 -- references outer `thing`
|
||||
baz z =
|
||||
@ -83,7 +83,7 @@ ex thing =
|
||||
> ex (x -> x * 100)
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -103,9 +103,9 @@ ex thing =
|
||||
4201
|
||||
|
||||
```
|
||||
Here's another example, showing that bindings cannot reference bindings declared in blocks nested in the _body_ (the final expression) of a block:
|
||||
Here's another example, showing that bindings cannot reference bindings declared in blocks nested in the *body* (the final expression) of a block:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex thing =
|
||||
bar x = thing x + 1 -- refers to outer thing
|
||||
let
|
||||
@ -115,7 +115,7 @@ ex thing =
|
||||
> ex (x -> x * 100)
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -137,9 +137,9 @@ ex thing =
|
||||
```
|
||||
### Blocks can define one or more functions which are recursive or mutually recursive
|
||||
|
||||
We call these groups of definitions that reference each other in a block _cycles_. For instance:
|
||||
We call these groups of definitions that reference each other in a block *cycles*. For instance:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
sumTo n =
|
||||
-- A recursive function, defined inside a block
|
||||
go acc n =
|
||||
@ -154,7 +154,7 @@ ex n =
|
||||
ping 42
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -174,14 +174,14 @@ The `go` function is a one-element cycle (it reference itself), and `ping` and `
|
||||
|
||||
For instance, this works:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex n =
|
||||
ping x = pong + 1 + x
|
||||
pong = 42
|
||||
ping 0
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -198,14 +198,14 @@ Since the forward reference to `pong` appears inside `ping`.
|
||||
|
||||
This, however, will not compile:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex n =
|
||||
pong = ping + 1
|
||||
ping = 42
|
||||
pong
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -217,13 +217,13 @@ ex n =
|
||||
```
|
||||
This also won't compile; it's a cyclic reference that isn't guarded:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex n =
|
||||
loop = loop
|
||||
loop
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -234,13 +234,13 @@ ex n =
|
||||
```
|
||||
This, however, will compile. This also shows that `'expr` is another way of guarding a definition.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex n =
|
||||
loop = '(!loop)
|
||||
!loop
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -253,13 +253,13 @@ ex n =
|
||||
ex : n -> r
|
||||
|
||||
```
|
||||
Just don't try to run it as it's an infinite loop!
|
||||
Just don't try to run it as it's an infinite loop\!
|
||||
|
||||
### Cyclic definitions in a block don't have access to any abilities
|
||||
|
||||
The reason is it's unclear what the order should be of any requests that are made. It can also be viewed of a special case of the restriction that elements of a cycle must all be guarded. Here's an example:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
structural ability SpaceAttack where
|
||||
launchMissiles : Text -> Nat
|
||||
|
||||
@ -269,7 +269,7 @@ ex n =
|
||||
zap1
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -279,11 +279,11 @@ ex n =
|
||||
|
||||
|
||||
```
|
||||
### The _body_ of recursive functions can certainly access abilities
|
||||
### The *body* of recursive functions can certainly access abilities
|
||||
|
||||
For instance, this works fine:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
structural ability SpaceAttack where
|
||||
launchMissiles : Text -> Nat
|
||||
|
||||
@ -293,7 +293,7 @@ ex n =
|
||||
zap1 "pluto"
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -311,7 +311,7 @@ ex n =
|
||||
|
||||
For instance, `zap` here isn't considered part of the cycle (it doesn't reference `ping` or `pong`), so this typechecks fine:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
structural ability SpaceAttack where
|
||||
launchMissiles : Text -> Nat
|
||||
|
||||
@ -322,7 +322,7 @@ ex n =
|
||||
ping 42
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -338,7 +338,7 @@ ex n =
|
||||
```
|
||||
This is actually parsed as if you moved `zap` after the cycle it find itself a part of:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
structural ability SpaceAttack where
|
||||
launchMissiles : Text -> Nat
|
||||
|
||||
@ -349,7 +349,7 @@ ex n =
|
||||
ping 42
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
Regression test for https://github.com/unisonweb/unison/pull/2819
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
hangExample : Boolean
|
||||
hangExample =
|
||||
("a long piece of text to hang the line" == "")
|
||||
&& ("a long piece of text to hang the line" == "")
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -20,7 +20,7 @@ hangExample =
|
||||
hangExample : Boolean
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -2,11 +2,11 @@ The `branch` command creates a new branch.
|
||||
|
||||
First, we'll create a term to include in the branches.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
someterm = 18
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> builtins.merge lib.builtins
|
||||
|
||||
Done.
|
||||
@ -23,7 +23,7 @@ Now, the `branch` demo:
|
||||
`branch` can create a branch from a different branch in the same project, from a different branch in a different
|
||||
project. It can also create an empty branch.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
foo/main> branch topic1
|
||||
|
||||
Done. I've created the topic1 branch based off of main.
|
||||
@ -151,7 +151,7 @@ scratch/main> branch.empty foo/empty4
|
||||
```
|
||||
The `branch` command can create branches named `releases/drafts/*` (because why not).
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
foo/main> branch releases/drafts/1.2.3
|
||||
|
||||
Done. I've created the releases/drafts/1.2.3 branch based off
|
||||
@ -165,7 +165,7 @@ foo/main> switch /releases/drafts/1.2.3
|
||||
```
|
||||
The `branch` command can't create branches named `releases/*` nor `releases/drafts/*`.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
foo/main> branch releases/1.2.3
|
||||
|
||||
Branch names like releases/1.2.3 are reserved for releases.
|
||||
|
@ -1,9 +1,9 @@
|
||||
```unison
|
||||
``` unison
|
||||
foo = 5
|
||||
foo.bar = 1
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -17,7 +17,7 @@ foo.bar = 1
|
||||
foo.bar : ##Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
p0/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -26,12 +26,12 @@ p0/main> add
|
||||
foo.bar : ##Nat
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
bonk = 5
|
||||
donk.bonk = 1
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -47,7 +47,7 @@ donk.bonk = 1
|
||||
(also named foo.bar)
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
p1/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,4 +1,4 @@
|
||||
```unison
|
||||
``` unison
|
||||
bonk : forall a. a -> a
|
||||
bonk x =
|
||||
zonk : forall a. a -> a
|
||||
@ -8,7 +8,7 @@ bonk x =
|
||||
x
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
|
||||
We can display the guide before and after adding it to the codebase:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> display doc.guide
|
||||
|
||||
# Unison computable documentation
|
||||
@ -414,11 +413,11 @@ scratch/main> display doc.guide
|
||||
```
|
||||
But we can't display this due to a decompilation problem.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
rendered = Pretty.get (docFormatConsole doc.guide)
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -431,7 +430,7 @@ rendered = Pretty.get (docFormatConsole doc.guide)
|
||||
rendered : Annotated () (Either SpecialForm ConsoleText)
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> display rendered
|
||||
|
||||
# Unison computable documentation
|
||||
@ -845,13 +844,13 @@ scratch/main> undo
|
||||
```
|
||||
And then this sometimes generates a GHC crash "strange closure error" but doesn't seem deterministic.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
rendered = Pretty.get (docFormatConsole doc.guide)
|
||||
|
||||
> rendered
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
The `builtins.merge` command adds the known builtins to the specified subnamespace within the current namespace.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> builtins.merge builtins
|
||||
|
||||
Done.
|
||||
|
@ -4,7 +4,7 @@ This transcript defines unit tests for builtin functions. There's a single `scra
|
||||
|
||||
## `Int` functions
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
use Int
|
||||
|
||||
-- used for some take/drop tests later
|
||||
@ -83,7 +83,7 @@ test> Int.tests.conversions =
|
||||
|
||||
## `Nat` functions
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
use Nat
|
||||
|
||||
test> Nat.tests.arithmetic =
|
||||
@ -153,7 +153,8 @@ test> Nat.tests.conversions =
|
||||
```
|
||||
|
||||
## `Boolean` functions
|
||||
```unison
|
||||
|
||||
``` unison
|
||||
test> Boolean.tests.orTable =
|
||||
checks [
|
||||
true || true == true,
|
||||
@ -177,7 +178,7 @@ test> Boolean.tests.notTable =
|
||||
|
||||
## `Text` functions
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
test> Text.tests.takeDropAppend =
|
||||
checks [
|
||||
"yabba" ++ "dabba" == "yabbadabba",
|
||||
@ -271,7 +272,7 @@ test> Text.tests.indexOfEmoji =
|
||||
|
||||
## `Bytes` functions
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
test> Bytes.tests.at =
|
||||
bs = Bytes.fromList [77, 13, 12]
|
||||
checks [
|
||||
@ -331,7 +332,7 @@ test> Bytes.tests.indexOf =
|
||||
|
||||
## `List` comparison
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
test> checks [
|
||||
compare [] [1,2,3] == -1,
|
||||
compare [1,2,3] [1,2,3,4] == -1,
|
||||
@ -345,7 +346,8 @@ test> checks [
|
||||
```
|
||||
|
||||
Other list functions
|
||||
```unison
|
||||
|
||||
``` unison
|
||||
test> checks [
|
||||
List.take bigN [1,2,3] == [1,2,3],
|
||||
List.drop bigN [1,2,3] == []
|
||||
@ -354,14 +356,14 @@ test> checks [
|
||||
|
||||
## `Any` functions
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
> [Any "hi", Any (41 + 1)]
|
||||
|
||||
test> Any.test1 = checks [(Any "hi" == Any "hi")]
|
||||
test> Any.test2 = checks [(not (Any "hi" == Any 42))]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -392,7 +394,7 @@ test> Any.test2 = checks [(not (Any "hi" == Any 42))]
|
||||
```
|
||||
## Sandboxing functions
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
openFile1 t = openFile t
|
||||
openFile2 t = openFile1 t
|
||||
|
||||
@ -413,7 +415,7 @@ test> Sandbox.test3 = checks [validateSandboxed [termLink openFile.impl]
|
||||
openFile]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -453,7 +455,7 @@ openFile]
|
||||
✅ Passed Passed
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
openFilesIO = do
|
||||
checks
|
||||
[ not (validateSandboxedSimpl [] (value openFile))
|
||||
@ -466,7 +468,7 @@ openFilesIO = do
|
||||
]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -479,7 +481,7 @@ openFilesIO = do
|
||||
openFilesIO : '{IO} [Result]
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -501,12 +503,12 @@ scratch/main> io.test openFilesIO
|
||||
|
||||
Just exercises the function
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
> Universal.murmurHash 1
|
||||
test> Universal.murmurHash.tests = checks [Universal.murmurHash [1,2,3] == Universal.murmurHash [1,2,3]]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -534,7 +536,7 @@ test> Universal.murmurHash.tests = checks [Universal.murmurHash [1,2,3] == Unive
|
||||
|
||||
Now that all the tests have been added to the codebase, let's view the test report. This will fail the transcript (with a nice message) if any of the tests are failing.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> test
|
||||
|
||||
Cached test results (`help testcache` to learn more)
|
||||
|
@ -1,11 +1,10 @@
|
||||
|
||||
This should render as `Bytes.fromList [1,2,3,4]`, not `##Bytes.fromSequence [1,2,3,4]`:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
> Bytes.fromList [1,2,3,4]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
Regression test for https://github.com/unisonweb/unison/issues/763
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
(+-+) : Nat -> Nat -> Nat
|
||||
(+-+) x y = x * y
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -18,7 +18,7 @@ Regression test for https://github.com/unisonweb/unison/issues/763
|
||||
+-+ : Nat -> Nat -> Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,10 +1,10 @@
|
||||
See [this ticket](https://github.com/unisonweb/unison/issues/873); the point being, this shouldn't crash the runtime. :)
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
(-) = builtin.Nat.sub
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -17,7 +17,7 @@ See [this ticket](https://github.com/unisonweb/unison/issues/873); the point bei
|
||||
- : Nat -> Nat -> Int
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -25,11 +25,11 @@ scratch/main> add
|
||||
- : Nat -> Nat -> Int
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
baz x = x - 1
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
```unison
|
||||
``` unison
|
||||
structural type Zoink a b c = Zoink a b c
|
||||
|
||||
> Any ()
|
||||
> [ Zoink [0,1,2,3,4,5] [6,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,3] () ]
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
```unison
|
||||
``` unison
|
||||
f : (() -> a) -> Nat
|
||||
f x = 42
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
Demonstrating `create.author`:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> create.author alicecoder "Alice McGee"
|
||||
|
||||
Added definitions:
|
||||
|
@ -1,6 +1,6 @@
|
||||
Update a member of a cycle, but retain the cycle.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ping : 'Nat
|
||||
ping _ = !pong + 1
|
||||
|
||||
@ -8,7 +8,7 @@ pong : 'Nat
|
||||
pong _ = !ping + 2
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -22,7 +22,7 @@ pong _ = !ping + 2
|
||||
pong : 'Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -31,12 +31,12 @@ scratch/main> add
|
||||
pong : 'Nat
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
ping : 'Nat
|
||||
ping _ = !pong + 3
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -50,7 +50,7 @@ ping _ = !pong + 3
|
||||
ping : 'Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> update
|
||||
|
||||
Okay, I'm searching the branch for code that needs to be
|
||||
|
@ -1,6 +1,6 @@
|
||||
Update a member of a cycle with a type-preserving update, but sever the cycle.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ping : 'Nat
|
||||
ping _ = !pong + 1
|
||||
|
||||
@ -8,7 +8,7 @@ pong : 'Nat
|
||||
pong _ = !ping + 2
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -22,7 +22,7 @@ pong _ = !ping + 2
|
||||
pong : 'Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -31,12 +31,12 @@ scratch/main> add
|
||||
pong : 'Nat
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
ping : 'Nat
|
||||
ping _ = 3
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -50,7 +50,7 @@ ping _ = 3
|
||||
ping : 'Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> update
|
||||
|
||||
Okay, I'm searching the branch for code that needs to be
|
||||
|
@ -1,6 +1,6 @@
|
||||
Update a member of a cycle with a type-changing update, thus severing the cycle.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ping : 'Nat
|
||||
ping _ = !pong + 1
|
||||
|
||||
@ -8,7 +8,7 @@ pong : 'Nat
|
||||
pong _ = !ping + 2
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -22,7 +22,7 @@ pong _ = !ping + 2
|
||||
pong : 'Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -31,12 +31,12 @@ scratch/main> add
|
||||
pong : 'Nat
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
ping : Nat
|
||||
ping = 3
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -50,7 +50,7 @@ ping = 3
|
||||
ping : Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> update.old
|
||||
|
||||
⍟ I've updated these names to your new definition:
|
||||
|
@ -1,6 +1,6 @@
|
||||
`update` properly discovers and establishes new cycles.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ping : 'Nat
|
||||
ping _ = 1
|
||||
|
||||
@ -8,7 +8,7 @@ pong : 'Nat
|
||||
pong _ = !ping + 2
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -22,7 +22,7 @@ pong _ = !ping + 2
|
||||
pong : 'Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -31,7 +31,7 @@ scratch/main> add
|
||||
pong : 'Nat
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
ping : 'Nat
|
||||
ping _ = !clang + 1
|
||||
|
||||
@ -39,7 +39,7 @@ clang : 'Nat
|
||||
clang _ = !pong + 3
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -57,7 +57,7 @@ clang _ = !pong + 3
|
||||
ping : 'Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> update.old ping
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,4 +1,4 @@
|
||||
```unison
|
||||
``` unison
|
||||
x = 30
|
||||
|
||||
y : Nat
|
||||
@ -12,7 +12,7 @@ ability Ask a where
|
||||
ask : a
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,4 +1,4 @@
|
||||
```unison
|
||||
``` unison
|
||||
a.b.one = 1
|
||||
a.two = 2
|
||||
|
||||
@ -9,7 +9,7 @@ structural type a.x.Foo = Foo | Bar
|
||||
structural type a.b.Baz = Boo
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -27,7 +27,7 @@ structural type a.b.Baz = Boo
|
||||
a.x.three : ##Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,7 +1,8 @@
|
||||
First we'll set up two libraries, and then we'll use them in some projects and show what `names` are deep-loaded for them.
|
||||
|
||||
Our two "libraries":
|
||||
```unison
|
||||
|
||||
``` unison
|
||||
text.a = 1
|
||||
text.b = 2
|
||||
text.c = 3
|
||||
@ -12,7 +13,8 @@ http.z = 8
|
||||
```
|
||||
|
||||
Our `app1` project includes the text library twice and the http library twice as direct dependencies.
|
||||
```ucm
|
||||
|
||||
``` ucm
|
||||
scratch/app1> fork text lib.text_v1
|
||||
|
||||
Done.
|
||||
@ -39,7 +41,8 @@ scratch/app1> delete.namespace http
|
||||
|
||||
```
|
||||
As such, we see two copies of `a` and two copies of `x` via these direct dependencies.
|
||||
```ucm
|
||||
|
||||
``` ucm
|
||||
scratch/app1> names a
|
||||
|
||||
Term
|
||||
@ -59,7 +62,8 @@ scratch/app1> names x
|
||||
```
|
||||
Our `app2` project includes the `http` library twice as direct dependencies, and once as an indirect dependency via `webutil`.
|
||||
It also includes the `text` library twice as indirect dependencies via `webutil`
|
||||
```ucm
|
||||
|
||||
``` ucm
|
||||
scratch/app2> fork http lib.http_v1
|
||||
|
||||
Done.
|
||||
@ -91,7 +95,8 @@ scratch/app2> delete.namespace text
|
||||
```
|
||||
Now we see two copies of `x` via direct dependencies on `http`, and one copy of `a` via indirect dependency on `text` via `webutil`.
|
||||
We see neither the second indirect copy of `a` nor the indirect copy of `x` via webutil because we already have names for them.
|
||||
```ucm
|
||||
|
||||
``` ucm
|
||||
scratch/app2> names a
|
||||
|
||||
Term
|
||||
|
@ -1,10 +1,10 @@
|
||||
```ucm
|
||||
``` ucm
|
||||
diffs/main> builtins.merge
|
||||
|
||||
Done.
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
term =
|
||||
_ = "Here's some text"
|
||||
1 + 1
|
||||
@ -12,7 +12,7 @@ term =
|
||||
type Type = Type Nat
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -26,7 +26,7 @@ type Type = Type Nat
|
||||
term : Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
diffs/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -42,7 +42,7 @@ diffs/main> branch.create new
|
||||
`switch /main` then `merge /new`.
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
term =
|
||||
_ = "Here's some different text"
|
||||
1 + 2
|
||||
@ -50,7 +50,7 @@ term =
|
||||
type Type a = Type a Text
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -65,7 +65,7 @@ type Type a = Type a Text
|
||||
term : Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
diffs/new> update
|
||||
|
||||
Okay, I'm searching the branch for code that needs to be
|
||||
@ -76,7 +76,7 @@ diffs/new> update
|
||||
```
|
||||
Diff terms
|
||||
|
||||
```api
|
||||
``` api
|
||||
GET /api/projects/diffs/diff/terms?oldBranchRef=main&newBranchRef=new&oldTerm=term&newTerm=term
|
||||
{
|
||||
"diff": {
|
||||
@ -558,9 +558,11 @@ GET /api/projects/diffs/diff/terms?oldBranchRef=main&newBranchRef=new&oldTerm=te
|
||||
},
|
||||
"project": "diffs"
|
||||
}
|
||||
```Diff types
|
||||
```
|
||||
|
||||
```api
|
||||
Diff types
|
||||
|
||||
``` api
|
||||
GET /api/projects/diffs/diff/types?oldBranchRef=main&newBranchRef=new&oldType=Type&newType=Type
|
||||
{
|
||||
"diff": {
|
||||
@ -804,4 +806,5 @@ GET /api/projects/diffs/diff/types?oldBranchRef=main&newBranchRef=new&oldType=Ty
|
||||
},
|
||||
"project": "diffs"
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
|
@ -2,15 +2,15 @@
|
||||
|
||||
# Delete namespace dependents check
|
||||
|
||||
This is a regression test, previously `delete.namespace` allowed a delete as long as the deletions had a name _anywhere_ in your codebase, it should only check the current project branch.
|
||||
This is a regression test, previously `delete.namespace` allowed a delete as long as the deletions had a name *anywhere* in your codebase, it should only check the current project branch.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
sub.dependency = 123
|
||||
|
||||
dependent = dependency + 99
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -24,7 +24,7 @@ dependent = dependency + 99
|
||||
sub.dependency : Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
myproject/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,6 +1,6 @@
|
||||
# delete.namespace.force
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
no_dependencies.thing = "no dependents on this term"
|
||||
|
||||
dependencies.term1 = 1
|
||||
@ -12,7 +12,7 @@ dependents.usage2 = dependencies.term1 * dependencies.term2
|
||||
|
||||
Deleting a namespace with no external dependencies should succeed.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> delete.namespace no_dependencies
|
||||
|
||||
Done.
|
||||
@ -20,7 +20,7 @@ scratch/main> delete.namespace no_dependencies
|
||||
```
|
||||
Deleting a namespace with external dependencies should fail and list all dependents.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> delete.namespace dependencies
|
||||
|
||||
⚠️
|
||||
@ -41,7 +41,7 @@ scratch/main> delete.namespace dependencies
|
||||
```
|
||||
Deleting a namespace with external dependencies should succeed when using `delete.namespace.force`
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> delete.namespace.force dependencies
|
||||
|
||||
Done.
|
||||
@ -61,7 +61,7 @@ scratch/main> delete.namespace.force dependencies
|
||||
```
|
||||
I should be able to view an affected dependency by number
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> view 2
|
||||
|
||||
dependents.usage2 : Nat
|
||||
@ -72,7 +72,7 @@ scratch/main> view 2
|
||||
```
|
||||
Deleting the root namespace should require confirmation if not forced.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> delete.namespace .
|
||||
|
||||
⚠️
|
||||
@ -100,7 +100,7 @@ scratch/main> history .
|
||||
```
|
||||
Deleting the root namespace shouldn't require confirmation if forced.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> delete.namespace.force .
|
||||
|
||||
Okay, I deleted everything except the history. Use `undo` to
|
||||
|
@ -1,7 +1,7 @@
|
||||
Deleting the branch you are on takes you to its parent (though this is impossible to see in a transcript, since we set
|
||||
your working directory with each command).
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
foo/main> branch topic
|
||||
|
||||
Done. I've created the topic branch based off of main.
|
||||
@ -14,7 +14,7 @@ foo/topic> delete.branch /topic
|
||||
```
|
||||
A branch need not be preceded by a forward slash.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
foo/main> branch topic
|
||||
|
||||
Done. I've created the topic branch based off of main.
|
||||
@ -27,7 +27,7 @@ foo/topic> delete.branch topic
|
||||
```
|
||||
You can precede the branch name by a project name.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
foo/main> branch topic
|
||||
|
||||
Done. I've created the topic branch based off of main.
|
||||
@ -40,13 +40,13 @@ scratch/main> delete.branch foo/topic
|
||||
```
|
||||
You can delete the only branch in a project.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
foo/main> delete.branch /main
|
||||
|
||||
```
|
||||
You can delete the last branch in the project, a new one will be created.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> delete.branch scratch/main
|
||||
|
||||
scratch/main> branches
|
||||
@ -58,7 +58,7 @@ scratch/main> branches
|
||||
```
|
||||
If the the last branch isn't /main, then /main will be created.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main2> delete.branch /main
|
||||
|
||||
scratch/main2> delete.branch /main2
|
||||
|
@ -1,6 +1,6 @@
|
||||
# delete.project
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> project.create-empty foo
|
||||
|
||||
🎉 I've created the project foo.
|
||||
|
@ -1,4 +1,4 @@
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> delete foo
|
||||
|
||||
⚠️
|
||||
@ -7,12 +7,12 @@ scratch/main> delete foo
|
||||
foo
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
foo = 1
|
||||
structural type Foo = Foo ()
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -5,7 +5,7 @@ The delete command can delete both terms and types.
|
||||
First, let's make sure it complains when we try to delete a name that doesn't
|
||||
exist.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> delete.verbose foo
|
||||
|
||||
⚠️
|
||||
@ -17,12 +17,12 @@ scratch/main> delete.verbose foo
|
||||
Now for some easy cases. Deleting an unambiguous term, then deleting an
|
||||
unambiguous type.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
foo = 1
|
||||
structural type Foo = Foo ()
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -60,12 +60,12 @@ scratch/main> delete.verbose Foo.Foo
|
||||
```
|
||||
How about an ambiguous term?
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
a.foo = 1
|
||||
a.bar = 2
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -80,7 +80,7 @@ scratch/main> debug.alias.term.force a.bar a.foo
|
||||
```
|
||||
A delete should remove both versions of the term.
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> delete.verbose a.foo
|
||||
|
||||
Removed definitions:
|
||||
@ -103,12 +103,12 @@ scratch/main> ls a
|
||||
```
|
||||
Let's repeat all that on a type, for completeness.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
structural type a.Foo = Foo ()
|
||||
structural type a.Bar = Bar
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -149,12 +149,12 @@ scratch/main> delete.verbose a.Foo.Foo
|
||||
```
|
||||
Finally, let's try to delete a term and a type with the same name.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
foo = 1
|
||||
structural type foo = Foo ()
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -175,13 +175,13 @@ scratch/main> delete.verbose foo
|
||||
```
|
||||
We want to be able to delete multiple terms at once
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
a = "a"
|
||||
b = "b"
|
||||
c = "c"
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -204,14 +204,14 @@ scratch/main> delete.verbose a b c
|
||||
```
|
||||
We can delete terms and types in the same invocation of delete
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
structural type Foo = Foo ()
|
||||
a = "a"
|
||||
b = "b"
|
||||
c = "c"
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -247,11 +247,11 @@ scratch/main> delete.verbose Foo.Foo
|
||||
```
|
||||
We can delete a type and its constructors
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
structural type Foo = Foo ()
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -276,14 +276,14 @@ scratch/main> delete.verbose Foo Foo.Foo
|
||||
```
|
||||
You should not be able to delete terms which are referenced by other terms
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
a = 1
|
||||
b = 2
|
||||
c = 3
|
||||
d = a + b + c
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -309,14 +309,14 @@ scratch/main> delete.verbose a b c
|
||||
```
|
||||
But you should be able to delete all terms which reference each other in a single command
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
e = 11
|
||||
f = 12 + e
|
||||
g = 13 + f
|
||||
h = e + f + g
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -341,7 +341,7 @@ scratch/main> delete.verbose e f g h
|
||||
```
|
||||
You should be able to delete a type and all the functions that reference it in a single command
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
structural type Foo = Foo Nat
|
||||
|
||||
incrementFoo : Foo -> Nat
|
||||
@ -349,7 +349,7 @@ incrementFoo = cases
|
||||
(Foo n) -> n + 1
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -371,14 +371,14 @@ scratch/main> delete.verbose Foo Foo.Foo incrementFoo
|
||||
```
|
||||
If you mess up on one of the names of your command, delete short circuits
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
e = 11
|
||||
f = 12 + e
|
||||
g = 13 + f
|
||||
h = e + f + g
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -398,12 +398,12 @@ scratch/main> delete.verbose e f gg
|
||||
```
|
||||
Cyclical terms which are guarded by a lambda are allowed to be deleted
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ping _ = 1 Nat.+ !pong
|
||||
pong _ = 4 Nat.+ !ping
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,8 +1,10 @@
|
||||
### `debug.file`
|
||||
|
||||
I can use `debug.file` to see the hashes of the last typechecked file.
|
||||
|
||||
Given this .u file:
|
||||
```unison
|
||||
|
||||
``` unison
|
||||
structural type outside.A = A Nat outside.B
|
||||
structural type outside.B = B Int
|
||||
outside.c = 3
|
||||
@ -14,7 +16,7 @@ inside.q x = x + p * p
|
||||
inside.r = d
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> debug.file
|
||||
|
||||
type inside.M#h37a56c5ep
|
||||
@ -30,8 +32,10 @@ scratch/main> debug.file
|
||||
This will help me make progress in some situations when UCM is being deficient or broken.
|
||||
|
||||
### `dependents` / `dependencies`
|
||||
|
||||
But wait, there's more. I can check the dependencies and dependents of a definition:
|
||||
```ucm
|
||||
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -110,3 +114,4 @@ scratch/main> dependents d
|
||||
|
||||
```
|
||||
We don't have an index for dependents of constructors, but iirc if you ask for that, it will show you dependents of the structural type that provided the constructor.
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Here's a couple examples:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex0 : Nat -> Nat
|
||||
ex0 n =
|
||||
(a, _, (c,d)) = ("uno", "dos", (n, 7))
|
||||
@ -14,7 +14,7 @@ ex1 tup =
|
||||
c + d
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -28,7 +28,7 @@ ex1 tup =
|
||||
ex1 : (a, b, (Nat, Nat)) -> Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -52,13 +52,13 @@ Notice that `ex0` is printed using the `cases` syntax (but `ex1` is not). The pr
|
||||
|
||||
A destructuring bind is just syntax for a single branch pattern match. Notice that Unison detects this function as an alias of `ex1`:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex2 : (a,b,(Nat,Nat)) -> Nat
|
||||
ex2 tup = match tup with
|
||||
(a, b, (c,d)) -> c + d
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -76,13 +76,13 @@ ex2 tup = match tup with
|
||||
|
||||
Destructuring binds can't be recursive: the left-hand side bound variables aren't available on the right hand side. For instance, this doesn't typecheck:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex4 =
|
||||
(a,b) = (a Nat.+ b, 19)
|
||||
"Doesn't typecheck"
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -104,7 +104,7 @@ ex4 =
|
||||
```
|
||||
Even though the parser accepts any pattern on the LHS of a bind, it looks pretty weird to see things like `12 = x`, so we avoid showing a destructuring bind when the LHS is a "literal" pattern (like `42` or "hi"). Again these examples wouldn't compile with coverage checking.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex5 : 'Text
|
||||
ex5 _ = match 99 + 1 with
|
||||
12 -> "Hi"
|
||||
@ -116,7 +116,7 @@ ex5a _ = match (99 + 1, "hi") with
|
||||
_ -> "impossible"
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -130,7 +130,7 @@ ex5a _ = match (99 + 1, "hi") with
|
||||
ex5a : 'Text
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -155,14 +155,14 @@ Notice how it prints both an ordinary match.
|
||||
|
||||
Also, for clarity, the pretty-printer shows a single-branch match if the match shadows free variables of the scrutinee, for example:
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
ex6 x = match x with
|
||||
(x, y) -> x Nat.+ y
|
||||
```
|
||||
|
||||
For clarity, the pretty-printer leaves this alone, even though in theory it could be written `(x,y) = x; x + y`:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
@ -1,9 +1,9 @@
|
||||
```unison
|
||||
``` unison
|
||||
x = 23
|
||||
fslkdjflskdjflksjdf = 663
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/b1> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -12,13 +12,13 @@ scratch/b1> add
|
||||
x : Nat
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
x = 23
|
||||
fslkdjflskdjflksjdf = 23
|
||||
abc = 23
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/b2> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -32,7 +32,7 @@ scratch/b1> debug.alias.term.force .x .fslkdjflskdjflksjdf
|
||||
Done.
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> diff.namespace /b1: /b2:
|
||||
|
||||
Resolved name conflicts:
|
||||
@ -52,16 +52,16 @@ scratch/main> diff.namespace /b1: /b2:
|
||||
```
|
||||
Things we want to test:
|
||||
|
||||
* Diffing identical namespaces
|
||||
* Adds, removes, updates
|
||||
* Adds with multiple names
|
||||
* Moved and copied definitions
|
||||
* Moves that have more that 1 initial or final name
|
||||
* ... terms and types
|
||||
* New patches, modified patches, deleted patches, moved patches
|
||||
* With and without propagated updates
|
||||
- Diffing identical namespaces
|
||||
- Adds, removes, updates
|
||||
- Adds with multiple names
|
||||
- Moved and copied definitions
|
||||
- Moves that have more that 1 initial or final name
|
||||
- ... terms and types
|
||||
- New patches, modified patches, deleted patches, moved patches
|
||||
- With and without propagated updates
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
fromJust = 1
|
||||
b = 2
|
||||
bdependent = b
|
||||
@ -72,7 +72,7 @@ structural type A a = A ()
|
||||
structural ability X a1 a2 where x : ()
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/ns1> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -103,7 +103,7 @@ scratch/ns1> branch /ns2
|
||||
```
|
||||
Here's what we've done so far:
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> diff.namespace .nothing /ns1:
|
||||
|
||||
⚠️
|
||||
@ -111,17 +111,17 @@ scratch/main> diff.namespace .nothing /ns1:
|
||||
The namespace scratch/main:.nothing is empty. Was there a typo?
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> diff.namespace /ns1: /ns2:
|
||||
|
||||
The namespaces are identical.
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
junk = "asldkfjasldkfj"
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/ns1> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -137,7 +137,7 @@ scratch/ns1> delete.term junk
|
||||
Done.
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
fromJust = 99
|
||||
b = "oog"
|
||||
d = 4
|
||||
@ -146,7 +146,7 @@ f = 6
|
||||
unique type Y a b = Y a b
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/ns2> update.old
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -280,11 +280,11 @@ scratch/main> diff.namespace /ns3: /ns2:
|
||||
3. fromJust' ┘ 4. fromJust' (removed)
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
bdependent = "banana"
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/ns3> update.old
|
||||
|
||||
⍟ I've updated these names to your new definition:
|
||||
@ -313,14 +313,14 @@ scratch/main> diff.namespace /ns2: /ns3:
|
||||
Currently, the auto-propagated name-conflicted definitions are not explicitly
|
||||
shown, only their also-conflicted dependency is shown.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
a = 333
|
||||
b = a + 1
|
||||
|
||||
forconflicts = 777
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/nsx> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -344,11 +344,11 @@ scratch/nsx> branch /nsz
|
||||
`switch /nsx` then `merge /nsz`.
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
a = 444
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/nsy> update.old
|
||||
|
||||
⍟ I've updated these names to your new definition:
|
||||
@ -356,11 +356,11 @@ scratch/nsy> update.old
|
||||
a : Nat
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
a = 555
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/nsz> update.old
|
||||
|
||||
⍟ I've updated these names to your new definition:
|
||||
@ -383,7 +383,7 @@ scratch/nsw> debug.alias.term.force .forconflicts .b
|
||||
Done.
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/main> diff.namespace /nsx: /nsw:
|
||||
|
||||
New name conflicts:
|
||||
@ -429,11 +429,11 @@ scratch/nsw> view b
|
||||
```
|
||||
## Should be able to diff a namespace hash from history.
|
||||
|
||||
```unison
|
||||
``` unison
|
||||
x = 1
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -446,7 +446,7 @@ x = 1
|
||||
x : Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/hashdiff> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -454,11 +454,11 @@ scratch/hashdiff> add
|
||||
x : ##Nat
|
||||
|
||||
```
|
||||
```unison
|
||||
``` unison
|
||||
y = 2
|
||||
```
|
||||
|
||||
```ucm
|
||||
``` ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
@ -471,7 +471,7 @@ y = 2
|
||||
y : ##Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
``` ucm
|
||||
scratch/hashdiff> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -498,49 +498,50 @@ scratch/hashdiff> diff.namespace 2 1
|
||||
1. y : ##Nat
|
||||
|
||||
```
|
||||
##
|
||||
##
|
||||
|
||||
Updates: -- 1 to 1
|
||||
|
||||
New name conflicts: -- updates where RHS has multiple hashes (excluding when RHS=LHS)
|
||||
|
||||
1. foo#jk19sm5bf8 : Nat - do we want to force a hashqualified? Arya thinks so
|
||||
↓
|
||||
2. ┌ foo#0ja1qfpej6 : Nat
|
||||
3. └ foo#jk19sm5bf8 : Nat
|
||||
1. foo\#jk19sm5bf8 : Nat - do we want to force a hashqualified? Arya thinks so
|
||||
↓
|
||||
2. ┌ foo\#0ja1qfpej6 : Nat
|
||||
3. └ foo\#jk19sm5bf8 : Nat
|
||||
|
||||
Resolved name conflicts: -- updates where LHS had multiple hashes and RHS has one
|
||||
|
||||
4. ┌ bar#0ja1qfpej6 : Nat
|
||||
5. └ bar#jk19sm5bf8 : Nat
|
||||
↓
|
||||
6. bar#jk19sm5bf8 : Nat
|
||||
4. ┌ bar\#0ja1qfpej6 : Nat
|
||||
5. └ bar\#jk19sm5bf8 : Nat
|
||||
↓
|
||||
6. bar\#jk19sm5bf8 : Nat
|
||||
|
||||
## Display issues to fixup
|
||||
|
||||
- [d] Do we want to surface new edit conflicts in patches?
|
||||
- [t] two different auto-propagated changes creating a name conflict should show
|
||||
up somewhere besides the auto-propagate count
|
||||
- [t] Things look screwy when the type signature doesn't fit and has to get broken
|
||||
up into multiple lines. Maybe just disallow that?
|
||||
- [d] Delete blank line in between copies / renames entries if all entries are 1 to 1
|
||||
see todo in the code
|
||||
- [x] incorrectly calculated bracket alignment on hashqualified "Name changes" (delete.output.md)
|
||||
- [x] just handle deletion of isPropagated in propagate function, leave HandleInput alone (assuming this does the trick)
|
||||
- [x] might want unqualified names to be qualified sometimes:
|
||||
- [x] if a name is updated to a not-yet-named reference, it's shown as both an update and an add
|
||||
- [x] similarly, if a conflicted name is resolved by deleting the last name to
|
||||
a reference, I (arya) suspect it will show up as a Remove
|
||||
- [d] Maybe group and/or add headings to the types, constructors, terms
|
||||
- [x] add tagging of propagated updates to test propagated updates output
|
||||
- [x] missing old names in deletion ppe (delete.output.md) (superseded by \#1143)
|
||||
- [x] delete.term has some bonkers output
|
||||
- [x] Make a decision about how we want to show constructors in the diff
|
||||
- [x] 12.patch patch needs a space
|
||||
- [x] This looks like garbage
|
||||
- [x] Extra 2 blank lines at the end of the add section
|
||||
- [x] Fix alignment issues with buildTable, convert to column3M (to be written)
|
||||
- [x] adding an alias is showing up as an Add and a Copy; should just show as Copy
|
||||
- [x] removing one of multiple aliases appears in removes + moves + copies section
|
||||
- [x] some overlapping cases between Moves and Copies^
|
||||
- [x] Maybe don't list the type signature twice for aliases?
|
||||
- \[d\] Do we want to surface new edit conflicts in patches?
|
||||
- \[t\] two different auto-propagated changes creating a name conflict should show
|
||||
up somewhere besides the auto-propagate count
|
||||
- \[t\] Things look screwy when the type signature doesn't fit and has to get broken
|
||||
up into multiple lines. Maybe just disallow that?
|
||||
- \[d\] Delete blank line in between copies / renames entries if all entries are 1 to 1
|
||||
see todo in the code
|
||||
- \[x\] incorrectly calculated bracket alignment on hashqualified "Name changes" (delete.output.md)
|
||||
- \[x\] just handle deletion of isPropagated in propagate function, leave HandleInput alone (assuming this does the trick)
|
||||
- \[x\] might want unqualified names to be qualified sometimes:
|
||||
- \[x\] if a name is updated to a not-yet-named reference, it's shown as both an update and an add
|
||||
- \[x\] similarly, if a conflicted name is resolved by deleting the last name to
|
||||
a reference, I (arya) suspect it will show up as a Remove
|
||||
- \[d\] Maybe group and/or add headings to the types, constructors, terms
|
||||
- \[x\] add tagging of propagated updates to test propagated updates output
|
||||
- \[x\] missing old names in deletion ppe (delete.output.md) (superseded by \#1143)
|
||||
- \[x\] delete.term has some bonkers output
|
||||
- \[x\] Make a decision about how we want to show constructors in the diff
|
||||
- \[x\] 12.patch patch needs a space
|
||||
- \[x\] This looks like garbage
|
||||
- \[x\] Extra 2 blank lines at the end of the add section
|
||||
- \[x\] Fix alignment issues with buildTable, convert to column3M (to be written)
|
||||
- \[x\] adding an alias is showing up as an Add and a Copy; should just show as Copy
|
||||
- \[x\] removing one of multiple aliases appears in removes + moves + copies section
|
||||
- \[x\] some overlapping cases between Moves and Copies^
|
||||
- \[x\] Maybe don't list the type signature twice for aliases?
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user