Merge remote-tracking branch 'origin/trunk' into topic/hash-module-v1b

# Conflicts:
#	parser-typechecker/src/Unison/Codebase.hs
#	unison-core/src/Unison/Type.hs
This commit is contained in:
Arya Irani 2021-09-24 14:08:54 -04:00
commit c2f8fbe803
57 changed files with 1894 additions and 752 deletions

View File

@ -21,6 +21,7 @@ On startup, Unison prints a url for the codebase UI. If you did step 3 above, th
* `stack exec tests` runs the tests
* `stack exec transcripts` runs all the integration tests, found in `unison-src/transcripts`. You can add more tests to this directory.
* `stack exec tests -- prefix-of-test` and `stack exec transcripts -- prefix-of-test` only run tests with a matching prefix.
* `stack exec unison -- transcript unison-src/transcripts-round-trip/main.md` runs the pretty-printing round trip tests
### What if you want a profiled build?

BIN
parser-typechecker/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -144,6 +144,7 @@ executables:
- unison-parser-typechecker
- unison-codebase-sync
- uri-encode
- unliftio
when:
- condition: '!os(windows)'
dependencies: unix

View File

@ -256,7 +256,8 @@ typeOf a f r = maybe a f (Map.lookup r termRefTypes)
builtinsSrc :: Var v => [BuiltinDSL v]
builtinsSrc =
[ B "Int.+" $ int --> int --> int
[ B "Any.unsafeExtract" $ forall1 "a" (\a -> anyt --> a)
, B "Int.+" $ int --> int --> int
, B "Int.-" $ int --> int --> int
, B "Int.*" $ int --> int --> int
, B "Int./" $ int --> int --> int
@ -634,13 +635,16 @@ codeBuiltins =
, ("Code.serialize", code --> bytes)
, ("Code.deserialize", bytes --> eithert text code)
, ("Code.cache_", list (tuple [termLink,code]) --> io (list termLink))
, ("Code.validate", list (tuple [termLink,code]) --> io (optionalt failure))
, ("Code.lookup", termLink --> io (optionalt code))
, ("Code.display", text --> code --> text)
, ("Value.dependencies", value --> list termLink)
, ("Value.serialize", value --> bytes)
, ("Value.deserialize", bytes --> eithert text value)
, ("Value.value", forall1 "a" $ \a -> a --> value)
, ("Value.load"
, forall1 "a" $ \a -> value --> io (eithert (list termLink) a))
, ("Link.Term.toText", termLink --> text)
]
stmBuiltins :: forall v. Var v => [(Text, Type v)]

View File

@ -8,6 +8,7 @@ module Unison.Codebase
GetRootBranchError (..),
getBranchForHash,
getCodebaseDir,
isBlank,
SyncToDir,
addDefsToCodebase,
installUcmDependencies,
@ -27,6 +28,7 @@ module Unison.Codebase
)
where
import Control.Error (rightMay)
import Control.Error.Util (hush)
import Control.Monad.Except (ExceptT (ExceptT), runExceptT)
import Data.List as List
@ -208,6 +210,11 @@ isType c r = case r of
Reference.Builtin{} -> pure $ Builtin.isBuiltinType r
Reference.DerivedId r -> isJust <$> getTypeDeclaration c r
isBlank :: Applicative m => Codebase m v a -> m Bool
isBlank codebase = do
root <- fromMaybe Branch.empty . rightMay <$> getRootBranch codebase
pure (root == Branch.empty)
-- * Git stuff
-- | Sync elements as needed from a remote codebase into the local one.

View File

@ -12,12 +12,12 @@ import qualified Unison.Codebase.Path as Path
import Data.Void (Void)
-- |"release/M1j.2" -> "releases._M1j"
-- "devel/*" -> "trunk"
-- "latest-*" -> "trunk"
defaultBaseLib :: Parsec Void Text ReadRemoteNamespace
defaultBaseLib = fmap makeNS $ devel <|> release
defaultBaseLib = fmap makeNS $ latest <|> release
where
devel, release, version :: Parsec Void Text Text
devel = "devel/" *> many anyChar *> eof $> "trunk"
latest, release, version :: Parsec Void Text Text
latest = "latest-" *> many anyChar *> eof $> "trunk"
release = fmap ("releases._" <>) $ "release/" *> version <* eof
version = fmap Text.pack $
try (someTill anyChar "." <* many anyChar) <|> many anyChar

View File

@ -5,14 +5,14 @@ module Unison.Codebase.Init
( Init (..),
DebugName,
InitError (..),
CodebaseDir (..),
CodebaseInitOptions (..),
InitResult (..),
SpecifiedCodebase (..),
Pretty,
createCodebase,
initCodebaseAndExit,
openOrCreateCodebase,
openNewUcmCodebaseOrExit,
homeOrSpecifiedDir
)
where
@ -25,21 +25,23 @@ import Unison.Prelude
import qualified Unison.PrettyTerminal as PT
import Unison.Symbol (Symbol)
import qualified Unison.Util.Pretty as P
import UnliftIO.Directory (canonicalizePath, getHomeDirectory)
import UnliftIO.Directory (canonicalizePath)
import Unison.Codebase.Init.CreateCodebaseError
-- CodebaseDir is used to help pass around a Home directory that isn't the
-- CodebaseInitOptions is used to help pass around a Home directory that isn't the
-- actual home directory of the user. Useful in tests.
data CodebaseDir = Home CodebasePath | Specified CodebasePath
data CodebaseInitOptions
= Home CodebasePath
| Specified SpecifiedCodebase
homeOrSpecifiedDir :: Maybe CodebasePath -> IO CodebaseDir
homeOrSpecifiedDir specifiedDir = do
homeDir <- getHomeDirectory
pure $ maybe (Home homeDir) Specified specifiedDir
data SpecifiedCodebase
= CreateWhenMissing CodebasePath
| DontCreateWhenMissing CodebasePath
codebaseDirToCodebasePath :: CodebaseDir -> CodebasePath
codebaseDirToCodebasePath (Home dir) = dir
codebaseDirToCodebasePath (Specified dir) = dir
initOptionsToDir :: CodebaseInitOptions -> CodebasePath
initOptionsToDir (Home dir ) = dir
initOptionsToDir (Specified (CreateWhenMissing dir)) = dir
initOptionsToDir (Specified (DontCreateWhenMissing dir)) = dir
type DebugName = String
@ -65,28 +67,42 @@ data InitResult m v a
| CreatedCodebase CodebasePath (FinalizerAndCodebase m v a)
| Error CodebasePath InitError
openOrCreateCodebase :: MonadIO m => Init m v a -> DebugName -> CodebaseDir -> m (InitResult m v a)
openOrCreateCodebase cbInit debugName codebaseDir = do
let resolvedPath = (codebaseDirToCodebasePath codebaseDir)
createCodebaseWithResult :: MonadIO m => Init m v a -> DebugName -> CodebasePath -> m (InitResult m v a)
createCodebaseWithResult cbInit debugName dir =
createCodebase cbInit debugName dir >>= \case
Left errorMessage -> do
pure (Error dir (CouldntCreateCodebase errorMessage))
Right cb -> do
pure (CreatedCodebase dir cb)
whenNoV1Codebase :: MonadIO m => CodebasePath -> m (InitResult m v a) -> m (InitResult m v a )
whenNoV1Codebase dir initResult =
ifM (FCC.codebaseExists dir)
(pure (Error dir FoundV1Codebase))
initResult
openOrCreateCodebase :: MonadIO m => Init m v a -> DebugName -> CodebaseInitOptions -> m (InitResult m v a)
openOrCreateCodebase cbInit debugName initOptions = do
let resolvedPath = initOptionsToDir initOptions
openCodebase cbInit debugName resolvedPath >>= \case
Right cb -> pure (OpenedCodebase resolvedPath cb)
Left _ ->
case codebaseDir of
case initOptions of
Home homeDir -> do
ifM (FCC.codebaseExists homeDir)
(do pure (Error homeDir FoundV1Codebase))
(do
-- Create V2 codebase if neither a V1 or V2 exists
createCodebase cbInit debugName homeDir >>= \case
Left errorMessage -> do
pure (Error homeDir (CouldntCreateCodebase errorMessage))
Right cb -> do
pure (CreatedCodebase homeDir cb)
createCodebaseWithResult cbInit debugName homeDir
)
Specified specifiedDir -> do
ifM (FCC.codebaseExists specifiedDir)
(pure (Error specifiedDir FoundV1Codebase))
(pure (Error specifiedDir NoCodebaseFoundAtSpecifiedDir))
Specified specified ->
whenNoV1Codebase resolvedPath $ do
case specified of
DontCreateWhenMissing dir ->
pure (Error dir NoCodebaseFoundAtSpecifiedDir)
CreateWhenMissing dir ->
createCodebaseWithResult cbInit debugName dir
createCodebase :: MonadIO m => Init m v a -> DebugName -> CodebasePath -> m (Either Pretty (m (), Codebase m v a))
createCodebase cbInit debugName path = do
@ -123,6 +139,6 @@ openNewUcmCodebaseOrExit cbInit debugName path = do
pure x
-- | try to init a codebase where none exists and then exit regardless (i.e. `ucm -codebase dir init`)
initCodebaseAndExit :: MonadIO m => Init m Symbol Ann -> DebugName -> Maybe CodebasePath -> m ()
initCodebaseAndExit :: MonadIO m => Init m Symbol Ann -> DebugName -> Maybe CodebasePath -> m () -- RLM : or could change here
initCodebaseAndExit i debugName mdir =
void $ openNewUcmCodebaseOrExit i debugName =<< Codebase.getCodebaseDir mdir

View File

@ -29,7 +29,8 @@ import Unison.Parser.Ann (Ann)
import Unison.Prelude
import Unison.PrettyTerminal
import Unison.Symbol (Symbol)
import Unison.CommandLine.Main (asciiartUnison, expandNumber)
import Unison.CommandLine.Main (expandNumber)
import Unison.CommandLine.Welcome (asciiartUnison)
import qualified Data.Char as Char
import qualified Data.Map as Map
import qualified Data.Text as Text

View File

@ -312,7 +312,7 @@ displayDoc pped terms typeOf evaluated types = go
Referent.Con r _ _ -> prettyType r
prettyType r = let ppe = PPE.declarationPPE pped r in types r >>= \case
Nothing -> pure $ "😶 Missing type source for: " <> typeName ppe r
Just ty -> pure . P.syntaxToColor $ P.group $ DP.prettyDecl ppe r (PPE.typeName ppe r) ty
Just ty -> pure . P.syntaxToColor $ P.group $ DP.prettyDecl pped r (PPE.typeName ppe r) ty
termName :: PPE.PrettyPrintEnv -> Referent -> Pretty
termName ppe r = P.syntaxToColor $

View File

@ -11,7 +11,6 @@ import Control.Exception (finally, catch, AsyncException(UserInterrupt), asyncEx
import Control.Monad.State (runStateT)
import Data.Configurator.Types (Config)
import Data.IORef
import Data.Tuple.Extra (uncurry3)
import Prelude hiding (readFile, writeFile)
import System.IO.Error (isDoesNotExistError)
import Unison.Codebase.Branch (Branch)
@ -21,13 +20,12 @@ import qualified Unison.Server.CodebaseServer as Server
import qualified Unison.Codebase.Editor.HandleInput as HandleInput
import qualified Unison.Codebase.Editor.HandleCommand as HandleCommand
import Unison.Codebase.Editor.Command (LoadSourceResult(..))
import Unison.Codebase.Editor.RemoteRepo (ReadRemoteNamespace, printNamespace)
import Unison.Codebase (Codebase)
import Unison.CommandLine
import Unison.PrettyTerminal
import Unison.CommandLine.InputPattern (ArgumentType (suggestions), InputPattern (aliases, patternName))
import Unison.CommandLine.InputPatterns (validInputs)
import Unison.CommandLine.OutputMessages (notifyUser, notifyNumbered, shortenDirectory)
import Unison.CommandLine.OutputMessages (notifyUser, notifyNumbered)
import Unison.Parser.Ann (Ann)
import Unison.Symbol (Symbol)
import qualified Control.Concurrent.Async as Async
@ -42,6 +40,7 @@ import qualified Unison.Codebase as Codebase
import qualified Unison.CommandLine.InputPattern as IP
import qualified Unison.Util.Pretty as P
import qualified Unison.Util.TQueue as Q
import qualified Unison.CommandLine.Welcome as Welcome
import Text.Regex.TDFA
import Control.Lens (view)
import Control.Error (rightMay)
@ -104,77 +103,26 @@ getUserInput patterns codebase branch currentPath numberedArgs = Line.runInputT
pure $ suggestions argType word codebase branch currentPath
_ -> pure []
asciiartUnison :: P.Pretty P.ColorText
asciiartUnison =
P.red " _____"
<> P.hiYellow " _ "
<> P.newline
<> P.red "| | |"
<> P.hiRed "___"
<> P.hiYellow "|_|"
<> P.hiGreen "___ "
<> P.cyan "___ "
<> P.purple "___ "
<> P.newline
<> P.red "| | | "
<> P.hiYellow "| |"
<> P.hiGreen "_ -"
<> P.cyan "| . |"
<> P.purple " |"
<> P.newline
<> P.red "|_____|"
<> P.hiRed "_|_"
<> P.hiYellow "|_|"
<> P.hiGreen "___"
<> P.cyan "|___|"
<> P.purple "_|_|"
welcomeMessage :: FilePath -> String -> P.Pretty P.ColorText
welcomeMessage dir version =
asciiartUnison
<> P.newline
<> P.newline
<> P.linesSpaced
[ P.wrap "Welcome to Unison!"
, P.wrap ("You are running version: " <> P.string version)
, P.wrap
( "I'm currently watching for changes to .u files under "
<> (P.group . P.blue $ fromString dir)
)
, P.wrap ("Type " <> P.hiBlue "help" <> " to get help. 😎")
]
hintFreshCodebase :: ReadRemoteNamespace -> P.Pretty P.ColorText
hintFreshCodebase ns =
P.wrap $ "Enter "
<> (P.hiBlue . P.group)
("pull " <> P.text (uncurry3 printNamespace ns) <> " .base")
<> "to set up the default base library. 🏗"
main
:: FilePath
-> Maybe ReadRemoteNamespace
-> Welcome.Welcome
-> Path.Absolute
-> (Config, IO ())
-> [Either Event Input]
-> Runtime.Runtime Symbol
-> Codebase IO Symbol Ann
-> String
-> Maybe Server.BaseUrl
-> IO ()
main dir defaultBaseLib initialPath (config, cancelConfig) initialInputs runtime codebase version serverBaseUrl = do
dir' <- shortenDirectory dir
main dir welcome initialPath (config, cancelConfig) initialInputs runtime codebase serverBaseUrl = do
root <- fromMaybe Branch.empty . rightMay <$> Codebase.getRootBranch codebase
putPrettyLn $ case defaultBaseLib of
Just ns | Branch.isOne root ->
welcomeMessage dir' version <> P.newline <> P.newline <> hintFreshCodebase ns
_ -> welcomeMessage dir' version
(welcomeCmds, welcomeMsg) <- Welcome.welcome codebase welcome
putPrettyLn welcomeMsg
eventQueue <- Q.newIO
do
-- we watch for root branch tip changes, but want to ignore ones we expect.
rootRef <- newIORef root
pathRef <- newIORef initialPath
initialInputsRef <- newIORef initialInputs
initialInputsRef <- newIORef (welcomeCmds ++ initialInputs)
numberedArgsRef <- newIORef []
pageOutput <- newIORef True
cancelFileSystemWatch <- watchFileSystem eventQueue dir

View File

@ -1150,7 +1150,7 @@ displayDefinitions' ppe0 types terms = P.syntaxToColor $ P.sep "\n\n" (prettyTyp
BuiltinObject _ -> builtin n
UserObject decl -> case decl of
Left d -> DeclPrinter.prettyEffectDecl (ppeBody r) r n d
Right d -> DeclPrinter.prettyDataDecl (ppeBody r) r n d
Right d -> DeclPrinter.prettyDataDecl (PPE.declarationPPEDecl ppe0 r) r n d
builtin n = P.wrap $ "--" <> prettyHashQualified n <> " is built-in."
missing n r = P.wrap (
"-- The name " <> prettyHashQualified n <> " is assigned to the "

View File

@ -0,0 +1,111 @@
{-# LANGUAGE OverloadedStrings #-}
module Unison.CommandLine.Welcome where
import Unison.Prelude
import Unison.Codebase (Codebase)
import qualified Unison.Codebase as Codebase
import Prelude hiding (readFile, writeFile)
import qualified Unison.Util.Pretty as P
import System.Random (randomRIO)
import qualified Unison.Codebase.Path as Path
import qualified Unison.Codebase.SyncMode as SyncMode
import Unison.Codebase.Editor.Input (Input (..), Event)
import Data.Sequence (singleton)
import Unison.NameSegment (NameSegment(NameSegment))
import Unison.Codebase.Editor.RemoteRepo (ReadRemoteNamespace)
-- Should Welcome include whether or not the codebase was created just now?
data DownloadBase = DownloadBase ReadRemoteNamespace | DontDownloadBase
data Welcome = Welcome
{ downloadBase :: DownloadBase
, watchDir :: FilePath
, unisonVersion :: String
}
welcome :: Codebase IO v a -> Welcome -> IO ([Either Event Input], P.Pretty P.ColorText)
welcome codebase welcome' = do
let Welcome{downloadBase=downloadBase, watchDir=dir, unisonVersion=version} = welcome'
welcomeMsg <- welcomeMessage dir version
isBlankCodebase <- Codebase.isBlank codebase
pure $ case downloadBase of
DownloadBase ns@(_, _, path) | isBlankCodebase ->
let
cmd =
Right (pullBase ns)
baseVersion =
P.string (show path)
downloadMsg =
P.lines [ P.newline <> P.newline
, P.wrap ("🕐 Downloading"
<> P.blue baseVersion
<> "of the"
<> P.bold "base library"
<> "into"
<> P.group (P.blue ".base" <> ", this may take a minute..."))
]
in
([cmd], welcomeMsg <> downloadMsg)
_ ->
([], welcomeMsg)
welcomeMessage :: FilePath -> String -> IO (P.Pretty P.ColorText)
welcomeMessage dir version = do
earth <- (["🌎", "🌍", "🌏"] !!) <$> randomRIO (0, 2)
pure $
asciiartUnison
<> P.newline
<> P.newline
<> P.linesSpaced
[ P.wrap "👋 Welcome to Unison!",
P.wrap ("You are running version: " <> P.bold (P.string version)) <> P.newline,
P.wrap "Get started:",
P.indentN
2
( P.column2
[ ("📖", "Type " <> P.hiBlue "help" <> " to list all commands, or " <> P.hiBlue "help <cmd>" <> " to view help for one command"),
("🎨", "Type " <> P.hiBlue "ui" <> " to open the Codebase UI in your default browser"),
("📚", "Read the official docs at " <> P.blue "https://unisonweb.org/docs"),
(earth, "Visit Unison Share at " <> P.blue "https://share.unison-lang.org" <> " to discover libraries"),
("👀", "I'm watching for changes to " <> P.bold ".u" <> " files under " <> (P.group . P.blue $ P.string dir))
]
)
]
pullBase :: ReadRemoteNamespace -> Input
pullBase ns = do
let
seg = NameSegment "base"
rootPath = Path.Path { Path.toSeq = singleton seg }
abs = Path.Absolute {Path.unabsolute = rootPath}
PullRemoteBranchI (Just ns) (Path.Path' {Path.unPath' = Left abs}) SyncMode.Complete
asciiartUnison :: P.Pretty P.ColorText
asciiartUnison =
P.red " _____"
<> P.hiYellow " _ "
<> P.newline
<> P.red "| | |"
<> P.hiRed "___"
<> P.hiYellow "|_|"
<> P.hiGreen "___ "
<> P.cyan "___ "
<> P.purple "___ "
<> P.newline
<> P.red "| | | "
<> P.hiYellow "| |"
<> P.hiGreen "_ -"
<> P.cyan "| . |"
<> P.purple " |"
<> P.newline
<> P.red "|_____|"
<> P.hiRed "_|_"
<> P.hiYellow "|_|"
<> P.hiGreen "___"
<> P.cyan "|___|"
<> P.purple "_|_|"

View File

@ -20,6 +20,7 @@ import qualified Unison.Name as Name
import Unison.Name ( Name )
import Unison.NamePrinter ( styleHashQualified'' )
import Unison.PrettyPrintEnv ( PrettyPrintEnv )
import Unison.PrettyPrintEnvDecl ( PrettyPrintEnvDecl(..) )
import qualified Unison.PrettyPrintEnv as PPE
import qualified Unison.Referent as Referent
import Unison.Reference ( Reference(DerivedId) )
@ -35,13 +36,13 @@ type SyntaxText = S.SyntaxText' Reference
prettyDecl
:: Var v
=> PrettyPrintEnv
=> PrettyPrintEnvDecl
-> Reference
-> HashQualified Name
-> DD.Decl v a
-> Pretty SyntaxText
prettyDecl ppe r hq d = case d of
Left e -> prettyEffectDecl ppe r hq e
prettyDecl ppe@(PrettyPrintEnvDecl unsuffixifiedPPE _) r hq d = case d of
Left e -> prettyEffectDecl unsuffixifiedPPE r hq e
Right dd -> prettyDataDecl ppe r hq dd
prettyEffectDecl
@ -88,12 +89,12 @@ prettyPattern env ctorType ref namespace cid = styleHashQualified''
prettyDataDecl
:: Var v
=> PrettyPrintEnv
=> PrettyPrintEnvDecl
-> Reference
-> HashQualified Name
-> DataDeclaration v a
-> Pretty SyntaxText
prettyDataDecl env r name dd =
prettyDataDecl (PrettyPrintEnvDecl unsuffixifiedPPE suffixifiedPPE) r name dd =
(header <>) . P.sep (fmt S.DelimiterChar (" | " `P.orElse` "\n | ")) $ constructor <$> zip
[0 ..]
(DD.constructors' dd)
@ -101,16 +102,16 @@ prettyDataDecl env r name dd =
constructor (n, (_, _, (Type.ForallsNamed' _ t))) = constructor' n t
constructor (n, (_, _, t) ) = constructor' n t
constructor' n t = case Type.unArrows t of
Nothing -> prettyPattern env CT.Data r name n
Just ts -> case fieldNames env r name dd of
Nothing -> P.group . P.hang' (prettyPattern env CT.Data r name n) " "
$ P.spaced (TypePrinter.prettyRaw env Map.empty 10 <$> init ts)
Nothing -> prettyPattern suffixifiedPPE CT.Data r name n
Just ts -> case fieldNames unsuffixifiedPPE r name dd of
Nothing -> P.group . P.hang' (prettyPattern suffixifiedPPE CT.Data r name n) " "
$ P.spaced (TypePrinter.prettyRaw suffixifiedPPE Map.empty 10 <$> init ts)
Just fs -> P.group $ (fmt S.DelimiterChar "{ ")
<> P.sep ((fmt S.DelimiterChar ",") <> " " `P.orElse` "\n ")
(field <$> zip fs (init ts))
<> (fmt S.DelimiterChar " }")
field (fname, typ) = P.group $ styleHashQualified'' (fmt (S.Reference r)) fname <>
(fmt S.TypeAscriptionColon " :") `P.hang` TypePrinter.prettyRaw env Map.empty (-1) typ
(fmt S.TypeAscriptionColon " :") `P.hang` TypePrinter.prettyRaw suffixifiedPPE Map.empty (-1) typ
header = prettyDataHeader name dd <> (fmt S.DelimiterChar (" = " `P.orElse` "\n = "))
-- Comes up with field names for a data declaration which has the form of a
@ -145,7 +146,6 @@ fieldNames env r name dd = case DD.constructors dd of
[ (r, f) | (r, n) <- names
, typename <- pure (HQ.toString name)
, typename `isPrefixOf` n
-- drop the typename and the following '.'
, rest <- pure $ drop (length typename + 1) n
, (f, rest) <- pure $ span (/= '.') rest
, rest `elem` ["",".set",".modify"] ]

View File

@ -230,7 +230,7 @@ modifier = do
unique = do
tok <- openBlockWith "unique"
uid <- do
o <- optional (reserved "[" *> wordyIdString <* reserved "]")
o <- optional (openBlockWith "[" *> wordyIdString <* closeBlock)
case o of
Nothing -> uniqueName 32
Just uid -> pure (fromString . L.payload $ uid)

View File

@ -90,6 +90,7 @@ data Err
| InvalidEscapeCharacter Char
| LayoutError
| CloseWithoutMatchingOpen String String -- open, close
| UnexpectedDelimiter String
| Opaque String -- Catch-all failure type, generally these will be
-- automatically generated errors coming from megaparsec
-- Try to avoid this for common errors a user is likely to see.
@ -214,7 +215,8 @@ token'' tok p = do
topHasClosePair :: Layout -> Bool
topHasClosePair [] = False
topHasClosePair ((name,_):_) = name `elem` ["{", "(", "handle", "match", "if", "then"]
topHasClosePair ((name,_):_) =
name `elem` ["{", "(", "[", "handle", "match", "if", "then"]
lexer0' :: String -> String -> [Token Lexeme]
lexer0' scope rem =
@ -340,22 +342,24 @@ lexemes' eof = P.optional space >> do
isPrefixOf "}}" word ||
all (== '#') word
wordy ok = wrap "syntax.docWord" . tok . fmap Textual . P.try $ do
let end = P.lookAhead $ void docClose
<|> void docOpen
<|> void (CP.satisfy isSpace)
<|> void (CP.satisfy (not . ok))
word <- P.someTill (CP.satisfy (\ch -> not (isSpace ch) && ok ch)) end
guard (not $ reserved word)
wordy closing = wrap "syntax.docWord" . tok . fmap Textual . P.try $ do
let end =
P.lookAhead
$ void docClose
<|> void docOpen
<|> void (CP.satisfy isSpace)
<|> void closing
word <- P.manyTill (CP.satisfy (\ch -> not (isSpace ch))) end
guard (not $ reserved word || null word)
pure word
leafy ok = groupy ok gs
where
gs = link <|> externalLink <|> exampleInline <|> expr
<|> boldOrItalicOrStrikethrough ok <|> verbatim
<|> atDoc <|> wordy ok
leafy closing = groupy closing gs
where
gs = link <|> externalLink <|> exampleInline <|> expr
<|> boldOrItalicOrStrikethrough closing <|> verbatim
<|> atDoc <|> wordy closing
leaf = leafy (const True)
leaf = leafy mzero
atDoc = src <|> evalInline <|> signature <|> signatureInline
where
@ -401,9 +405,9 @@ lexemes' eof = P.optional space >> do
signatureLink = wrap "syntax.docEmbedSignatureLink" $
tok (symbolyId <|> wordyId) <* CP.space
groupy ok p = do
groupy closing p = do
(start,p,stop) <- positioned p
after <- P.optional . P.try $ leafy ok
after <- P.optional . P.try $ leafy closing
pure $ case after of
Nothing -> p
Just after ->
@ -484,28 +488,30 @@ lexemes' eof = P.optional space >> do
verbatim <- tok $ Textual . trim <$> P.someTill CP.anyChar ([] <$ lit fence)
pure (name <> verbatim)
boldOrItalicOrStrikethrough ok = do
let start = some (CP.satisfy (== '*')) <|> some (CP.satisfy (== '_')) <|> some (CP.satisfy (== '~'))
name s = if take 1 s == "~" then "syntax.docStrikethrough"
else if length s > 1 then "syntax.docBold"
else "syntax.docItalic"
(end,ch) <- P.try $ do
end@(ch:_) <- start
boldOrItalicOrStrikethrough closing = do
let start =
some (CP.satisfy (== '*')) <|> some (CP.satisfy (== '_')) <|> some
(CP.satisfy (== '~'))
name s = if take 1 s == "~"
then "syntax.docStrikethrough"
else if take 1 s == "*" then "syntax.docBold" else "syntax.docItalic"
end <- P.try $ do
end <- start
P.lookAhead (CP.satisfy (not . isSpace))
pure (end,ch)
wrap (name end) . wrap "syntax.docParagraph" $
join <$> P.someTill (leafy (\c -> ok c && c /= ch) <* nonNewlineSpaces)
(lit end)
pure end
wrap (name end) . wrap "syntax.docParagraph" $ join <$> P.someTill
(leafy (closing <|> (void $ lit end)) <* nonNewlineSpaces)
(lit end)
externalLink =
P.label "hyperlink (example: [link name](https://destination.com))" $
wrap "syntax.docNamedLink" $ do
_ <- lit "["
p <- leafies (/= ']')
p <- leafies (void $ char ']')
_ <- lit "]"
_ <- lit "("
target <- wrap "syntax.docGroup" . wrap "syntax.docJoin" $
link <|> fmap join (P.some (expr <|> wordy (/= ')')))
link <|> fmap join (P.some (expr <|> wordy (char ')')))
_ <- lit ")"
pure (p <> target)
@ -771,13 +777,29 @@ lexemes' eof = P.optional space >> do
reserved :: P [Token Lexeme]
reserved =
token' (\ts _ _ -> ts) $
braces <|> parens <|> delim <|> delayOrForce <|> keywords <|> layoutKeywords
where
keywords = symbolyKw ":" <|> symbolyKw "@" <|> symbolyKw "||" <|> symbolyKw "|" <|> symbolyKw "&&"
<|> wordyKw "true" <|> wordyKw "false"
<|> wordyKw "use" <|> wordyKw "forall" <|> wordyKw ""
<|> wordyKw "termLink" <|> wordyKw "typeLink"
token' (\ts _ _ -> ts)
$ braces
<|> parens
<|> brackets
<|> commaSeparator
<|> delim
<|> delayOrForce
<|> keywords
<|> layoutKeywords
where
keywords =
symbolyKw ":"
<|> symbolyKw "@"
<|> symbolyKw "||"
<|> symbolyKw "|"
<|> symbolyKw "&&"
<|> wordyKw "true"
<|> wordyKw "false"
<|> wordyKw "use"
<|> wordyKw "forall"
<|> wordyKw ""
<|> wordyKw "termLink"
<|> wordyKw "typeLink"
wordyKw s = separated wordySep (kw s)
symbolyKw s = separated (not . symbolyIdChar) (kw s)
@ -809,12 +831,12 @@ lexemes' eof = P.optional space >> do
let opens = [Token (Open "with") pos1 pos2]
pure $ replicate n (Token Close pos1 pos2) ++ opens
-- In `structural/unique type` and `structural/unique ability`,
-- In `structural/unique type` and `structural/unique ability`,
-- only the `structural` or `unique` opens a layout block,
-- and `ability` and `type` are just keywords.
openTypeKw1 t = do
b <- S.gets (topBlockName . layout)
case b of
case b of
Just mod | Set.member mod typeModifiers -> wordyKw t
_ -> openKw1 wordySep t
@ -840,7 +862,7 @@ lexemes' eof = P.optional space >> do
env <- S.get
-- -> introduces a layout block if we're inside a `match with` or `cases`
case topBlockName (layout env) of
Just match | match == "match-with" || match == "cases" -> do
Just match | match `elem` matchWithBlocks -> do
S.put (env { opening = Just "->" })
pure [Token (Open "->") start end]
_ -> pure [Token (Reserved "->") start end]
@ -854,7 +876,20 @@ lexemes' eof = P.optional space >> do
inLayout <- S.gets inLayout
when (not inLayout) $ void $ P.lookAhead (CP.satisfy (/= '}'))
pure l
matchWithBlocks = ["match-with", "cases"]
parens = open "(" <|> close ["("] (lit ")")
brackets = open "[" <|> close ["["] (lit "]")
-- `allowCommaToClose` determines if a comma should close inner blocks.
-- Currently there is a set of blocks where `,` is not treated specially
-- and it just emits a Reserved ",". There are currently only three:
-- `cases`, `match-with`, and `{`
allowCommaToClose match = not $ match `elem` ("{" : matchWithBlocks)
commaSeparator = do
env <- S.get
case topBlockName (layout env) of
Just match | allowCommaToClose match ->
blockDelimiter ["[", "("] (lit ",")
_ -> fail "this comma is a pattern separator"
delim = P.try $ do
ch <- CP.satisfy (\ch -> ch /= ';' && Set.member ch delimiters)
@ -882,6 +917,18 @@ lexemes' eof = P.optional space >> do
close = close' Nothing
blockDelimiter :: [String] -> P String -> P [Token Lexeme]
blockDelimiter open closeP = do
(pos1, close, pos2) <- positioned $ closeP
env <- S.get
case findClose open (layout env) of
Nothing -> err pos1 (UnexpectedDelimiter (quote close))
where quote s = "'" <> s <> "'"
Just (_, n) -> do
S.put (env { layout = drop (n-1) (layout env) })
let delims = [Token (Reserved close) pos1 pos2]
pure $ replicate (n-1) (Token Close pos1 pos2) ++ delims
close' :: Maybe String -> [String] -> P String -> P [Token Lexeme]
close' reopenBlockname open closeP = do
(pos1, close, pos2) <- positioned $ closeP
@ -1086,7 +1133,7 @@ symbolyIdChars = Set.fromList "!$%^&*-=+<>.~\\/|:"
keywords :: Set String
keywords = Set.fromList [
"if", "then", "else", "forall", "",
"handle", "with",
"handle", "with",
"where", "use",
"true", "false",
"alias", "typeLink", "termLink",

View File

@ -406,24 +406,22 @@ string = queryToken getString
getString _ = Nothing
tupleOrParenthesized :: Ord v => P v a -> (Ann -> a) -> (a -> a -> a) -> P v a
tupleOrParenthesized p unit pair = do
open <- openBlockWith "("
es <- sepBy (reserved "," *> optional semi) p
close <- optional semi *> closeBlock
pure $ go es open close
where
go [t] _ _ = t
go as s e = foldr pair (unit (ann s <> ann e)) as
tupleOrParenthesized p unit pair = seq' "(" go p
where
go _ [t] = t
go a xs = foldr pair (unit a) xs
seq :: Ord v => (Ann -> [a] -> a) -> P v a -> P v a
seq f p = f' <$> leading <*> elements <*> trailing
where
f' open elems close = f (ann open <> ann close) elems
redundant = P.skipMany (P.eitherP (reserved ",") semi)
leading = reserved "[" <* redundant
trailing = redundant *> reserved "]"
sep = P.try $ optional semi *> reserved "," <* redundant
elements = sepEndBy sep p
seq = seq' "["
seq' :: Ord v => String -> (Ann -> [a] -> a) -> P v a -> P v a
seq' openStr f p = do
open <- openBlockWith openStr <* redundant
es <- sepEndBy (P.try $ optional semi *> reserved "," <* redundant) p
close <- redundant *> closeBlock
pure $ go open es close
where go open elems close = f (ann open <> ann close) elems
redundant = P.skipMany (P.eitherP (reserved ",") semi)
chainr1 :: Ord v => P v a -> P v (a -> a -> a) -> P v a
chainr1 p op = go1 where

View File

@ -1,6 +1,6 @@
{-# LANGUAGE OverloadedStrings #-}
module Unison.PrettyPrintEnv.Util (declarationPPE) where
module Unison.PrettyPrintEnv.Util (declarationPPE, declarationPPEDecl) where
import qualified Data.Set as Set
import Unison.PrettyPrintEnv (PrettyPrintEnv (..))
@ -29,3 +29,8 @@ declarationPPE ppe rd = PrettyPrintEnv tm ty
if Set.member r comp
then types (unsuffixifiedPPE ppe) r
else types (suffixifiedPPE ppe) r
-- The suffixed names uses the fully-qualified name for `r`
declarationPPEDecl :: PrettyPrintEnvDecl -> Reference -> PrettyPrintEnvDecl
declarationPPEDecl ppe r =
ppe { suffixifiedPPE = declarationPPE ppe r }

View File

@ -2,7 +2,7 @@
module Unison.PrettyPrintEnvDecl (PrettyPrintEnvDecl(..)) where
import Unison.PrettyPrintEnv (PrettyPrintEnv)
import Unison.PrettyPrintEnv (PrettyPrintEnv(..))
-- A pair of PrettyPrintEnvs:
-- - suffixifiedPPE uses the shortest unique suffix
@ -16,3 +16,4 @@ data PrettyPrintEnvDecl = PrettyPrintEnvDecl {
unsuffixifiedPPE :: PrettyPrintEnv,
suffixifiedPPE :: PrettyPrintEnv
} deriving Show

View File

@ -1031,6 +1031,10 @@ prettyParseError s = \case
where
excerpt = showSource s ((\t -> (rangeForToken t, ErrorSite)) <$> ts)
go = \case
L.UnexpectedDelimiter s ->
"I found a " <> style ErrorSite (fromString s) <>
" here, but I didn't see a list or tuple that it might be a separator for.\n\n" <>
excerpt
L.CloseWithoutMatchingOpen open close ->
"I found a closing " <> style ErrorSite (fromString close) <>
" here without a matching " <> style ErrorSite (fromString open) <> ".\n\n" <>

View File

@ -101,7 +101,7 @@ import Unison.Typechecker.Components (minimize')
import Unison.Pattern (SeqOp(..))
import qualified Unison.Pattern as P
import Unison.Reference (Reference(..))
import Unison.Referent (Referent, pattern Ref, pattern Con)
import Unison.Referent (Referent)
-- For internal errors
data CompileExn = CE CallStack (Pretty.Pretty Pretty.ColorText)
@ -751,7 +751,8 @@ data POp
| EQLU | CMPU | EROR
-- Code
| MISS | CACH | LKUP | LOAD -- isMissing,cache_,lookup,load
| VALU -- value
| CVLD -- validate
| VALU | TLTT -- value, Term.Link.toText
-- Debug
| PRNT | INFO
-- STM
@ -1205,12 +1206,8 @@ contLinks f (Mark ps de k)
contLinks _ KE = mempty
litLinks :: Monoid a => (Bool -> Reference -> a) -> BLit -> a
litLinks _ (Text _) = mempty
litLinks _ (Bytes _) = mempty
litLinks f (List s) = foldMap (valueLinks f) s
litLinks f (TmLink (Ref r)) = f False r
litLinks f (TmLink (Con r _ _)) = f True r
litLinks f (TyLink r) = f True r
litLinks _ _ = mempty
groupTermLinks :: SuperGroup v -> [Reference]
groupTermLinks = Set.toList . groupLinks f

View File

@ -528,7 +528,7 @@ getCase ctx frsh0 = do
let l = length ccs
frsh = frsh0 + fromIntegral l
us = getFresh <$> take l [frsh0..]
(,) ccs <$> getNormal (us++ctx) frsh
(,) ccs . TAbss us <$> getNormal (us++ctx) frsh
putCTag :: MonadPut m => CTag -> m ()
putCTag c = serialize (VarInt $ fromEnum c)

View File

@ -738,6 +738,24 @@ code'lookup
, (1, ([BX], TAbs r $ TCon Ty.optionalRef 1 [r]))
]
code'validate :: Var v => SuperNormal v
code'validate
= unop0 5 $ \[item, t, ref, msg, extra, fail]
-> TLetD t UN (TPrm CVLD [item])
. TMatch t . MatchSum
$ mapFromList
[ (1, ([BX, BX, BX],)
. TAbss [ref, msg, extra]
. TLetD fail BX (TCon Ty.failureRef 0 [ref, msg, extra])
$ TCon Ty.optionalRef 1 [fail])
, (0, ([],)
$ TCon Ty.optionalRef 0 [])
]
term'link'to'text :: Var v => SuperNormal v
term'link'to'text
= unop0 0 $ \[link] -> TPrm TLTT [link]
value'load :: Var v => SuperNormal v
value'load
= unop0 2 $ \[vlu,t,r]
@ -771,6 +789,17 @@ standard'handle instr
where
(h0,h) = fresh2
any'construct :: Var v => SuperNormal v
any'construct
= unop0 0 $ \[v]
-> TCon Ty.anyRef 0 [v]
any'extract :: Var v => SuperNormal v
any'extract
= unop0 1
$ \[v,v1] -> TMatch v
$ MatchData Ty.anyRef (mapSingleton 0 $ ([BX], TAbs v1 (TVar v1))) Nothing
seek'handle :: ForeignOp
seek'handle instr
= ([BX,BX,BX],)
@ -1451,9 +1480,12 @@ builtinLookup
, ("Code.isMissing", code'missing)
, ("Code.cache_", code'cache)
, ("Code.lookup", code'lookup)
, ("Code.validate", code'validate)
, ("Value.load", value'load)
, ("Value.value", value'create)
, ("Any.Any", any'construct)
, ("Any.unsafeExtract", any'extract)
, ("Link.Term.toText", term'link'to'text)
, ("STM.atomically", stm'atomic)
] ++ foreignWrappers
@ -1789,6 +1821,8 @@ declareForeigns = do
-> pure . Bytes.fromArray $ serializeGroup sg
declareForeign "Code.deserialize" boxToEBoxBox
. mkForeign $ pure . deserializeGroup @Symbol . Bytes.toArray
declareForeign "Code.display" boxBoxDirect . mkForeign
$ \(nm,sg) -> pure $ prettyGroup @Symbol (Text.unpack nm) sg ""
declareForeign "Value.dependencies" boxDirect
. mkForeign $
pure . fmap (Wrap Ty.termLinkRef . Ref) . valueTermLinks
@ -1796,10 +1830,6 @@ declareForeigns = do
. mkForeign $ pure . Bytes.fromArray . serializeValue
declareForeign "Value.deserialize" boxToEBoxBox
. mkForeign $ pure . deserializeValue . Bytes.toArray
declareForeign "Any.Any" boxDirect . mkForeign $ \(a :: Closure) ->
pure $ Closure.DataB1 Ty.anyRef 0 a
-- Hashing functions
let declareHashAlgorithm :: forall v alg . Var v => Hash.HashAlgorithm alg => Text -> alg -> FDecl v ()
declareHashAlgorithm txt alg = do

View File

@ -330,7 +330,8 @@ data BPrim1
| FLTB -- flatten
-- code
| MISS | CACH | LKUP | LOAD -- isMissing,cache_,lookup,load
| VALU -- value
| CVLD -- validate
| VALU | TLTT -- value, Term.Link.toText
deriving (Show, Eq, Ord)
data BPrim2
@ -741,7 +742,7 @@ emitSection rns grpn rec ctx (TMatch v bs)
| Just (i,BX) <- ctxResolve ctx v
, MatchData r cs df <- bs
= Ins (Unpack (Just r) i)
<$> emitDataMatching rns grpn rec ctx cs df
<$> emitDataMatching r rns grpn rec ctx cs df
| Just (i,BX) <- ctxResolve ctx v
, MatchRequest hs0 df <- bs
, hs <- mapFromList $ first (dnum rns) <$> M.toList hs0
@ -1057,6 +1058,8 @@ emitPOp ANF.CMPU = emitBP2 CMPU
emitPOp ANF.MISS = emitBP1 MISS
emitPOp ANF.CACH = emitBP1 CACH
emitPOp ANF.LKUP = emitBP1 LKUP
emitPOp ANF.TLTT = emitBP1 TLTT
emitPOp ANF.CVLD = emitBP1 CVLD
emitPOp ANF.LOAD = emitBP1 LOAD
emitPOp ANF.VALU = emitBP1 VALU
@ -1121,21 +1124,22 @@ emitBP2 p a
emitDataMatching
:: Var v
=> RefNums
=> Reference
-> RefNums
-> Word64
-> RCtx v
-> Ctx v
-> EnumMap CTag ([Mem], ANormal v)
-> Maybe (ANormal v)
-> Emit Section
emitDataMatching rns grpn rec ctx cs df
emitDataMatching r rns grpn rec ctx cs df
= MatchW 0 <$> edf <*> traverse (emitCase rns grpn rec ctx) (coerce cs)
where
-- Note: this is not really accurate. A default data case needs
-- stack space corresponding to the actual data that shows up there.
-- However, we currently don't use default cases for data.
edf | Just co <- df = emitSection rns grpn rec ctx co
| otherwise = countCtx ctx $ Die "missing data case"
| otherwise = countCtx ctx $ Die ("missing data case for hash " <> show r)
-- Emits code corresponding to an unboxed sum match.
-- The match is against a tag on the stack, and cases introduce

View File

@ -15,7 +15,7 @@ import GHC.Conc as STM (unsafeIOToSTM)
import Data.Maybe (fromMaybe)
import Data.Bits
import Data.Foldable (toList)
import Data.Foldable (toList, traverse_)
import Data.Traversable
import Data.Word (Word64)
@ -33,13 +33,14 @@ import qualified Data.Primitive.PrimArray as PA
import Text.Read (readMaybe)
import Unison.Builtin.Decls (exceptionRef)
import Unison.Reference (Reference(Builtin))
import Unison.Builtin.Decls (exceptionRef, ioFailureRef)
import Unison.Reference (Reference(Builtin), toShortHash)
import Unison.Referent (pattern Ref)
import qualified Unison.ShortHash as SH
import Unison.Symbol (Symbol)
import Unison.Runtime.ANF
as ANF (Mem(..), SuperGroup, valueLinks, groupLinks)
as ANF (Mem(..), CompileExn(..), SuperGroup, valueLinks, groupLinks)
import qualified Unison.Runtime.ANF as ANF
import Unison.Runtime.Builtin
import Unison.Runtime.Exception
@ -51,6 +52,7 @@ import Unison.Runtime.MCode
import qualified Unison.Type as Rf
import qualified Unison.Util.Bytes as By
import Unison.Util.Pretty (toPlainUnbroken)
import Unison.Util.EnumContainers as EC
type Tag = Word64
@ -216,8 +218,25 @@ exec !env !denv !ustk !bstk !k (BPrim1 CACH i) = do
unknown <- cacheAdd news env
bstk <- bump bstk
pokeS bstk
(Sq.fromList $ Foreign . Wrap Rf.typeLinkRef . Ref <$> unknown)
(Sq.fromList $ Foreign . Wrap Rf.termLinkRef . Ref <$> unknown)
pure (denv, ustk, bstk, k)
exec !env !denv !ustk !bstk !k (BPrim1 CVLD i) = do
arg <- peekOffS bstk i
news <- decodeCacheArgument arg
codeValidate news env >>= \case
Nothing -> do
ustk <- bump ustk
poke ustk 0
pure (denv, ustk, bstk, k)
Just (Failure ref msg clo) -> do
ustk <- bump ustk
bstk <- bumpn bstk 3
poke ustk 1
poke bstk (Foreign $ Wrap Rf.typeLinkRef ref)
pokeOffBi bstk 1 msg
pokeOff bstk 2 clo
pure (denv, ustk, bstk, k)
exec !env !denv !ustk !bstk !k (BPrim1 LKUP i) = do
clink <- peekOff bstk i
let Ref link = unwrapForeign $ marshalToForeign clink
@ -230,6 +249,13 @@ exec !env !denv !ustk !bstk !k (BPrim1 LKUP i) = do
bstk <- bump bstk
bstk <$ pokeBi bstk sg
pure (denv, ustk, bstk, k)
exec !_ !denv !ustk !bstk !k (BPrim1 TLTT i) = do
clink <- peekOff bstk i
let Ref link = unwrapForeign $ marshalToForeign clink
let sh = SH.toText $ toShortHash link
bstk <- bump bstk
pokeBi bstk sh
pure (denv, ustk, bstk, k)
exec !env !denv !ustk !bstk !k (BPrim1 LOAD i) = do
v <- peekOffBi bstk i
ustk <- bump ustk
@ -1179,6 +1205,8 @@ bprim1 !ustk !bstk FLTB i = do
bprim1 !ustk !bstk MISS _ = pure (ustk, bstk)
bprim1 !ustk !bstk CACH _ = pure (ustk, bstk)
bprim1 !ustk !bstk LKUP _ = pure (ustk, bstk)
bprim1 !ustk !bstk CVLD _ = pure (ustk, bstk)
bprim1 !ustk !bstk TLTT _ = pure (ustk, bstk)
bprim1 !ustk !bstk LOAD _ = pure (ustk, bstk)
bprim1 !ustk !bstk VALU _ = pure (ustk, bstk)
{-# inline bprim1 #-}
@ -1449,7 +1477,9 @@ decodeCacheArgument
:: Sq.Seq Closure -> IO [(Reference, SuperGroup Symbol)]
decodeCacheArgument s = for (toList s) $ \case
DataB2 _ _ (Foreign x) (DataB2 _ _ (Foreign y) _)
-> pure (unwrapForeign x, unwrapForeign y)
-> case unwrapForeign x of
Ref r -> pure (r, unwrapForeign y)
_ -> die "decodeCacheArgument: Con reference"
_ -> die "decodeCacheArgument: unrecognized value"
addRefs
@ -1470,6 +1500,30 @@ addRefs vfrsh vfrom vto rs = do
modifyTVar vto (nto <>)
pure from
codeValidate
:: [(Reference, SuperGroup Symbol)]
-> CCache
-> IO (Maybe (Failure Closure))
codeValidate tml cc = do
rty0 <- readTVarIO (refTy cc)
fty <- readTVarIO (freshTy cc)
let f b r | b, M.notMember r rty0 = S.singleton r
| otherwise = mempty
ntys0 = (foldMap.foldMap) (groupLinks f) tml
ntys = M.fromList $ zip (S.toList ntys0) [fty..]
rty = ntys <> rty0
ftm <- readTVarIO (freshTm cc)
rtm0 <- readTVarIO (refTm cc)
let (rs, gs) = unzip tml
rtm = rtm0 `M.withoutKeys` S.fromList rs
rns = RN (refLookup "ty" rty) (refLookup "tm" rtm)
combinate (n, g) = evaluate $ emitCombs rns n g
(Nothing <$ traverse_ combinate (zip [ftm..] gs))
`catch` \(CE cs perr) -> let
msg = Tx.pack $ toPlainUnbroken perr
extra = Foreign . Wrap Rf.textRef . Tx.pack $ show cs in
pure . Just $ Failure ioFailureRef msg extra
cacheAdd0
:: S.Set Reference
-> [(Reference, SuperGroup Symbol)]
@ -1480,6 +1534,7 @@ cacheAdd0 ntys0 tml cc = atomically $ do
let new = M.difference toAdd have
sz = fromIntegral $ M.size new
(rs,gs) = unzip $ M.toList new
int <- writeTVar (intermed cc) (have <> new)
rty <- addRefs (freshTy cc) (refTy cc) (tagRefs cc) ntys0
ntm <- stateTVar (freshTm cc) $ \i -> (i, i+sz)
rtm <- updateMap (M.fromList $ zip rs [ntm..]) (refTm cc)
@ -1488,7 +1543,7 @@ cacheAdd0 ntys0 tml cc = atomically $ do
combinate n g = (n, emitCombs rns n g)
nrs <- updateMap (mapFromList $ zip [ntm..] rs) (combRefs cc)
ncs <- updateMap (mapFromList $ zipWith combinate [ntm..] gs) (combs cc)
pure $ rtm `seq` nrs `seq` ncs `seq` ()
pure $ int `seq` rtm `seq` nrs `seq` ncs `seq` ()
where
toAdd = M.fromList tml
@ -1552,7 +1607,7 @@ reflectValue rty = goV
= pure (ANF.TmLink l)
| Just l <- maybeUnwrapForeign Rf.typeLinkRef f
= pure (ANF.TyLink l)
| otherwise = die $ err "foreign value"
| otherwise = die $ err $ "foreign value: " <> (show f)
reifyValue :: CCache -> ANF.Value -> IO (Either [Reference] Closure)

View File

@ -324,7 +324,7 @@ typeListEntry codebase r n = do
pure $ case decl of
Just (Left _) -> Ability
_ -> Data
_ -> pure Data
_ -> pure (if Set.member r Type.builtinAbilities then Ability else Data)
pure $ TypeEntry r n tag
typeDeclHeader
@ -891,9 +891,6 @@ typesToSyntax suff width ppe0 types =
(first (PPE.typeName ppeDecl) . dupe)
types
where
ppeBody r = if suffixified suff
then PPE.suffixifiedPPE ppe0
else PPE.declarationPPE ppe0 r
ppeDecl = if suffixified suff
then PPE.suffixifiedPPE ppe0
else PPE.unsuffixifiedPPE ppe0
@ -901,7 +898,7 @@ typesToSyntax suff width ppe0 types =
BuiltinObject _ -> BuiltinObject (formatTypeName' ppeDecl r)
MissingObject sh -> MissingObject sh
UserObject d -> UserObject . Pretty.render width $
DeclPrinter.prettyDecl (ppeBody r) r n d
DeclPrinter.prettyDecl (PPE.declarationPPEDecl ppe0 r) r n d
loadSearchResults
:: (Var v, Applicative m)

View File

@ -244,7 +244,7 @@ renderDoc pped terms typeOf eval types tm = eval tm >>= \case
Just decl ->
pure $ DO.UserObject (Src folded full)
where
full = formatPretty (DeclPrinter.prettyDecl ppe r (PPE.typeName ppe r) decl)
full = formatPretty (DeclPrinter.prettyDecl pped r (PPE.typeName ppe r) decl)
folded = formatPretty (DeclPrinter.prettyDeclHeader (PPE.typeName ppe r) decl)
go :: (Set.Set Reference, [Ref (UnisonHash, DisplayObject SyntaxText Src)])

View File

@ -406,21 +406,24 @@ pretty0
-- produce any backticks. We build the result out from the right,
-- starting at `f2`.
binaryApps
:: Var v => [(Term3 v PrintAnnotation, Term3 v PrintAnnotation)]
-> Pretty SyntaxText
-> Pretty SyntaxText
:: Var v
=> [(Term3 v PrintAnnotation, Term3 v PrintAnnotation)]
-> Pretty SyntaxText
-> Pretty SyntaxText
binaryApps xs last = unbroken `PP.orElse` broken
-- todo: use `PP.column2` in the case where we need to break
where
unbroken = PP.spaced (ps ++ [last])
broken = PP.column2 (psCols $ [""] ++ ps ++ [last])
broken = PP.hang (head ps) . PP.column2 . psCols $ (tail ps ++ [last])
psCols ps = case take 2 ps of
[x,y] -> (x,y) : psCols (drop 2 ps)
[] -> []
_ -> error "??"
ps = join $ [r a f | (a, f) <- reverse xs ]
r a f = [pretty0 n (ac 3 Normal im doc) a,
pretty0 n (AmbientContext 10 Normal Infix im doc False) f]
[x, y] -> (x, y) : psCols (drop 2 ps)
[x] -> [(x, "")]
[] -> []
_ -> undefined
ps = join $ [ r a f | (a, f) <- reverse xs ]
r a f =
[ pretty0 n (ac 3 Normal im doc) a
, pretty0 n (AmbientContext 10 Normal Infix im doc False) f
]
prettyPattern
:: forall v loc . Var v
@ -493,9 +496,9 @@ prettyPattern n c@(AmbientContext { imports = im }) p vs patt = case patt of
(pr, rvs) = prettyPattern n c (p + 1) lvs r
f i s = (paren (p >= i) (pl <> " " <> (fmt (S.Op op) s) <> " " <> pr), rvs)
in case op of
Pattern.Cons -> f 9 "+:"
Pattern.Snoc -> f 9 ":+"
Pattern.Concat -> f 9 "++"
Pattern.Cons -> f 0 "+:"
Pattern.Snoc -> f 0 ":+"
Pattern.Concat -> f 0 "++"
where
l :: IsString s => String -> s
l = fromString
@ -1308,6 +1311,16 @@ prettyDoc2 ppe ac tm = case tm of
S.DocDelimiter
"}}"
bail tm = brace (pretty0 ppe ac tm)
-- Finds the longest run of a character and return a run one longer than that
oneMore c inner = replicate num c
where
num =
case
filter (\s -> take 2 s == "__")
$ group (PP.toPlainUnbroken $ PP.syntaxToColor inner)
of
[] -> 2
x -> 1 + (maximum $ map length x)
go :: Width -> Term3 v PrintAnnotation -> Pretty SyntaxText
go hdr = \case
(toDocTransclude ppe -> Just d) ->
@ -1333,15 +1346,23 @@ prettyDoc2 ppe ac tm = case tm of
(toDocWord ppe -> Just t) ->
PP.text t
(toDocCode ppe -> Just d) ->
PP.group ("''" <> rec d <> "''")
let inner = rec d
quotes = oneMore '\'' inner
in PP.group $ PP.string quotes <> inner <> PP.string quotes
(toDocJoin ppe -> Just ds) ->
foldMap rec ds
(toDocItalic ppe -> Just d) ->
PP.group $ "*" <> rec d <> "*"
let inner = rec d
underscores = oneMore '_' inner
in PP.group $ PP.string underscores <> inner <> PP.string underscores
(toDocBold ppe -> Just d) ->
PP.group $ "__" <> rec d <> "__"
let inner = rec d
stars = oneMore '*' inner
in PP.group $ PP.string stars <> inner <> PP.string stars
(toDocStrikethrough ppe -> Just d) ->
PP.group $ "~~" <> rec d <> "~~"
let inner = rec d
quotes = oneMore '~' inner
in PP.group $ PP.string quotes <> inner <> PP.string quotes
(toDocGroup ppe -> Just d) ->
PP.group $ rec d
(toDocColumn ppe -> Just ds) ->

View File

@ -84,9 +84,9 @@ effectList = do
sequenceTyp :: Var v => TypeP v
sequenceTyp = do
open <- reserved "["
open <- openBlockWith "["
t <- valueType
close <- reserved "]"
close <- closeBlock
let a = ann open <> ann close
pure $ Type.app a (Type.list a) t

View File

@ -104,11 +104,13 @@ prettyRaw n im p tp = go n im p tp
in (fmt S.TypeOperator "" <> vformatted <> fmt S.TypeOperator ".")
`PP.hang` go n im (-1) body
t@(Arrow' _ _) -> case t of
EffectfulArrows' (Ref' DD.UnitRef) rest -> arrows True True rest
EffectfulArrows' (Ref' DD.UnitRef) rest ->
PP.parenthesizeIf (p >= 10) $ arrows True True rest
EffectfulArrows' fst rest ->
case fst of
Var' v | Var.name v == "()"
-> fmt S.DelayForceChar "'" <> arrows False True rest
Var' v | Var.name v == "()" ->
PP.parenthesizeIf (p >= 10) $
fmt S.DelayForceChar "'" <> arrows False True rest
_ -> PP.parenthesizeIf (p >= 0) $
go n im 0 fst <> arrows False False rest
_ -> "error"

View File

@ -7,6 +7,10 @@ module Unison.Test.CodebaseInit where
import EasyTest
import qualified Unison.Codebase.Init as CI
import Unison.Codebase.Init
( CodebaseInitOptions(..)
, Init(..)
, SpecifiedCodebase(..)
)
import qualified System.IO.Temp as Temp
-- keep it off for CI, since the random temp dirs it generates show up in the
@ -28,7 +32,7 @@ test = scope "Codebase.Init" $ tests
, scope "a v2 codebase should be created when one does not exist" do
tmp <- io (Temp.getCanonicalTemporaryDirectory >>= flip Temp.createTempDirectory "ucm-test")
cbInit <- io initMockWithoutCodebase
res <- io (CI.openOrCreateCodebase cbInit "ucm-test" (Home tmp) )
res <- io (CI.openOrCreateCodebase cbInit "ucm-test" (Home tmp))
case res of
CI.CreatedCodebase _ _ -> expect True
_ -> expect False
@ -37,18 +41,35 @@ test = scope "Codebase.Init" $ tests
[ scope "a v2 codebase should be opened" do
tmp <- io (Temp.getCanonicalTemporaryDirectory >>= flip Temp.createTempDirectory "ucm-test")
cbInit <- io initMockWithCodebase
res <- io (CI.openOrCreateCodebase cbInit "ucm-test" (Specified tmp))
res <- io (CI.openOrCreateCodebase cbInit "ucm-test" (Specified (DontCreateWhenMissing tmp)))
case res of
CI.OpenedCodebase _ _ -> expect True
_ -> expect False
, scope "a v2 codebase should be *not* created when one does not exist at the Specified dir" do
tmp <- io (Temp.getCanonicalTemporaryDirectory >>= flip Temp.createTempDirectory "ucm-test")
cbInit <- io initMockWithoutCodebase
res <- io (CI.openOrCreateCodebase cbInit "ucm-test" (Specified tmp) )
res <- io (CI.openOrCreateCodebase cbInit "ucm-test" (Specified (DontCreateWhenMissing tmp)))
case res of
CI.Error _ CI.NoCodebaseFoundAtSpecifiedDir -> expect True
_ -> expect False
]
, scope "*with* a --codebase-create flag" $ tests
[ scope "a v2 codebase should be created when one does not exist at the Specified dir" do
tmp <- io (Temp.getCanonicalTemporaryDirectory >>= flip Temp.createTempDirectory "ucm-test")
cbInit <- io initMockWithoutCodebase
res <- io (CI.openOrCreateCodebase cbInit "ucm-test" (Specified (CreateWhenMissing tmp)))
case res of
CI.CreatedCodebase _ _ -> expect True
_ -> expect False
,
scope "a v2 codebase should be opened when one exists" do
tmp <- io (Temp.getCanonicalTemporaryDirectory >>= flip Temp.createTempDirectory "ucm-test")
cbInit <- io initMockWithCodebase
res <- io (CI.openOrCreateCodebase cbInit "ucm-test" (Specified (CreateWhenMissing tmp)))
case res of
CI.OpenedCodebase _ _ -> expect True
_ -> expect False
]
]
-- Test helpers
@ -58,9 +79,9 @@ initMockWithCodebase = do
let codebase = error "did we /actually/ need a Codebase?"
pure $ Init {
-- DebugName -> CodebasePath -> m (Either Pretty (m (), Codebase m v a)),
openCodebase = (\_ _ -> pure ( Right (pure (), codebase))),
openCodebase = \_ _ -> pure ( Right (pure (), codebase)),
-- DebugName -> CodebasePath -> m (Either CreateCodebaseError (m (), Codebase m v a)),
createCodebase' = (\_ _ -> pure (Right (pure (), codebase))),
createCodebase' = \_ _ -> pure (Right (pure (), codebase)),
-- CodebasePath -> CodebasePath
codebasePath = id
}
@ -70,9 +91,9 @@ initMockWithoutCodebase = do
let codebase = error "did we /actually/ need a Codebase?"
pure $ Init {
-- DebugName -> CodebasePath -> m (Either Pretty (m (), Codebase m v a)),
openCodebase = (\_ _ -> pure (Left "no codebase found")),
openCodebase = \_ _ -> pure (Left "no codebase found"),
-- DebugName -> CodebasePath -> m (Either CreateCodebaseError (m (), Codebase m v a)),
createCodebase' = (\_ _ -> pure (Right (pure (), codebase))),
createCodebase' = \_ _ -> pure (Right (pure (), codebase)),
-- CodebasePath -> CodebasePath
codebasePath = id
}

View File

@ -64,10 +64,10 @@ test =
, t "woot;(woot)" [simpleWordyId "woot", Semi False, Open "(", simpleWordyId "woot", Close]
, t
"[+1,+1]"
[Reserved "[", Numeric "+1", Reserved ",", Numeric "+1", Reserved "]"]
[Open "[", Numeric "+1", Reserved ",", Numeric "+1", Close ]
, t
"[ +1 , +1 ]"
[Reserved "[", Numeric "+1", Reserved ",", Numeric "+1", Reserved "]"]
[Open "[", Numeric "+1", Reserved ",", Numeric "+1", Close ]
, t "-- a comment 1.0" []
, t "\"woot\" -- a comment 1.0" [Textual "woot"]
, t "0:Int" [Numeric "0", Reserved ":", simpleWordyId "Int"]

View File

@ -134,8 +134,7 @@ test = scope "typeprinter" . tests $
, tc "'{e} a"
, tc "'{e} (a -> b)"
, tc "'{e} (a ->{f} b)"
, pending $ tc "Pair a '{e} b" -- parser hits unexpected '
, tc_diff_rtt False "Pair a ('{e} b)" "Pair a '{e} b" 80 -- no RTT due to the above
, tc "Pair a ('{e} b)"
, tc "'(a -> 'a)"
, tc "'()"
, tc "'('a)"

View File

@ -13,7 +13,7 @@ test :: Test ()
test = scope "versionparser" . tests . fmap makeTest $
[ ("release/M1j", "releases._M1j")
, ("release/M1j.2", "releases._M1j")
, ("devel/M1k", "trunk")
, ("latest-abc", "trunk")
]
makeTest :: (Text, Text) -> Test ()

View File

@ -89,6 +89,7 @@ library
Unison.CommandLine.InputPatterns
Unison.CommandLine.Main
Unison.CommandLine.OutputMessages
Unison.CommandLine.Welcome
Unison.DeclPrinter
Unison.FileParser
Unison.FileParsers
@ -495,6 +496,7 @@ executable unison
, unison-codebase-sync
, unison-core1
, unison-parser-typechecker
, unliftio
, uri-encode
if flag(optimized)
ghc-options: -funbox-strict-fields -O2

View File

@ -69,11 +69,21 @@ data ShouldForkCodebase
| DontFork
deriving (Show, Eq)
data ShouldDownloadBase
= ShouldDownloadBase
| ShouldNotDownloadBase
deriving (Show, Eq)
data ShouldSaveCodebase
= SaveCodebase
| DontSaveCodebase
deriving (Show, Eq)
data CodebasePathOption
= CreateCodebaseWhenMissing FilePath
| DontCreateCodebaseWhenMissing FilePath
deriving (Show, Eq)
data IsHeadless = Headless | WithCLI
deriving (Show, Eq)
@ -82,8 +92,9 @@ data IsHeadless = Headless | WithCLI
-- Note that this is not one-to-one with command-parsers since some are simple variants.
-- E.g. run, run.file, run.pipe
data Command
= Launch IsHeadless CodebaseServerOpts
= Launch IsHeadless CodebaseServerOpts ShouldDownloadBase
| PrintVersion
-- @deprecated in trunk after M2g. Remove the Init command completely after M2h has been released
| Init
| Run RunSource
| Transcript ShouldForkCodebase ShouldSaveCodebase (NonEmpty FilePath )
@ -91,7 +102,7 @@ data Command
-- | Options shared by sufficiently many subcommands.
data GlobalOptions = GlobalOptions
{ codebasePath :: Maybe FilePath
{ codebasePathOption :: Maybe CodebasePathOption
} deriving (Show, Eq)
-- | The root-level 'ParserInfo'.
@ -138,7 +149,8 @@ versionCommand = command "version" (info versionParser (fullDesc <> progDesc "Pr
initCommand :: Mod CommandFields Command
initCommand = command "init" (info initParser (progDesc initHelp))
where
initHelp = "Initialise a unison codebase"
initHelp =
"This command is has been removed. Use --codebase-create instead to create a codebase in the specified directory when starting the UCM."
runSymbolCommand :: Mod CommandFields Command
runSymbolCommand =
@ -190,18 +202,28 @@ commandParser envOpts =
, transcriptForkCommand
, launchHeadlessCommand envOpts
]
globalOptionsParser :: Parser GlobalOptions
globalOptionsParser = do -- ApplicativeDo
codebasePath <- codebasePathParser
pure GlobalOptions{..}
codebasePathOption <- codebasePathParser <|> codebaseCreateParser
codebasePathParser :: Parser (Maybe FilePath)
codebasePathParser =
optional . strOption $
pure GlobalOptions{codebasePathOption = codebasePathOption}
codebasePathParser :: Parser (Maybe CodebasePathOption)
codebasePathParser = do
optString <- optional . strOption $
long "codebase"
<> metavar "path/to/codebase"
<> help "The path to the codebase, defaults to the home directory"
<> metavar "codebase/path"
<> help "The path to an existing codebase"
pure (fmap DontCreateCodebaseWhenMissing optString)
codebaseCreateParser :: Parser (Maybe CodebasePathOption)
codebaseCreateParser = do
path <- optional . strOption $
long "codebase-create"
<> metavar "codebase/path"
<> help "The path to a new or existing codebase (one will be created if there isn't one)"
pure (fmap CreateCodebaseWhenMissing path)
launchHeadlessCommand :: CodebaseServerOpts -> Mod CommandFields Command
launchHeadlessCommand envOpts =
@ -246,10 +268,11 @@ codebaseServerOptsParser envOpts = do -- ApplicativeDo
launchParser :: CodebaseServerOpts -> IsHeadless -> Parser Command
launchParser envOpts isHeadless = do -- ApplicativeDo
codebaseServerOpts <- codebaseServerOptsParser envOpts
pure (Launch isHeadless codebaseServerOpts)
downloadBase <- downloadBaseFlag
pure (Launch isHeadless codebaseServerOpts downloadBase)
initParser :: Parser Command
initParser = pure Init
initParser = pure Init
versionParser :: Parser Command
versionParser = pure PrintVersion
@ -273,6 +296,11 @@ saveCodebaseFlag = flag DontSaveCodebase SaveCodebase (long "save-codebase" <> h
where
saveHelp = "if set the resulting codebase will be saved to a new directory, otherwise it will be deleted"
downloadBaseFlag :: Parser ShouldDownloadBase
downloadBaseFlag = flag ShouldDownloadBase ShouldNotDownloadBase (long "no-base" <> help downloadBaseHelp)
where
downloadBaseHelp = "if set, a new codebase will be created without downloading the base library, otherwise the new codebase will download base"
fileArgument :: String -> Parser FilePath
fileArgument varName =
strArgument ( metavar varName

View File

@ -22,7 +22,7 @@ import qualified System.IO.Temp as Temp
import qualified System.Path as Path
import Text.Megaparsec (runParser)
import qualified Unison.Codebase as Codebase
import Unison.Codebase.Init (InitResult(..), InitError(..))
import Unison.Codebase.Init (InitResult(..), InitError(..), CodebaseInitOptions(..), SpecifiedCodebase(..))
import qualified Unison.Codebase.Init as CodebaseInit
import qualified Unison.Codebase.Editor.Input as Input
import Unison.Codebase.Editor.RemoteRepo (ReadRemoteNamespace)
@ -32,6 +32,7 @@ import qualified Unison.Codebase.Path as Path
import qualified Unison.Codebase.SqliteCodebase as SC
import qualified Unison.Codebase.TranscriptParser as TR
import Unison.CommandLine (plural', watchConfig)
import qualified Unison.CommandLine.Welcome as Welcome
import qualified Unison.CommandLine.Main as CommandLine
import Unison.Parser.Ann (Ann)
import Unison.Prelude
@ -42,14 +43,17 @@ import qualified Unison.Server.CodebaseServer as Server
import Unison.Symbol (Symbol)
import qualified Unison.Util.Pretty as P
import qualified Version
import UnliftIO.Directory ( getHomeDirectory )
import Compat ( installSignalHandlers )
import ArgParse
( UsageRenderer,
GlobalOptions(GlobalOptions, codebasePath),
GlobalOptions(GlobalOptions, codebasePathOption),
Command(Launch, PrintVersion, Init, Run, Transcript),
IsHeadless(WithCLI, Headless),
ShouldSaveCodebase(..),
ShouldForkCodebase(..),
ShouldDownloadBase (..),
CodebasePathOption(..),
RunSource(RunFromPipe, RunFromSymbol, RunFromFile),
parseCLIArgs )
import Data.List.NonEmpty (NonEmpty)
@ -62,8 +66,9 @@ main = do
void installSignalHandlers
(renderUsageInfo, globalOptions, command) <- parseCLIArgs progName Version.gitDescribe
let GlobalOptions{codebasePath=mcodepath} = globalOptions
let cbInit = SC.init
let GlobalOptions{codebasePathOption=mCodePathOption} = globalOptions
let mcodepath = fmap codebasePathOptionToPath mCodePathOption
currentDir <- getCurrentDirectory
configFilePath <- getConfigFilePath mcodepath
config <-
@ -72,10 +77,21 @@ main = do
case command of
PrintVersion ->
putStrLn $ progName ++ " version: " ++ Version.gitDescribe
Init ->
CodebaseInit.initCodebaseAndExit cbInit "main.init" mcodepath
Init -> do
PT.putPrettyLn $
P.callout
"⚠️"
(P.lines ["The Init command has been removed"
, P.newline
, P.wrap "Use --codebase-create to create a codebase at a specified location and open it:"
, P.indentN 2 (P.hiBlue "$ ucm --codebase-create myNewCodebase")
, "Running UCM without the --codebase-create flag: "
, P.indentN 2 (P.hiBlue "$ ucm")
, P.wrap ("will " <> P.bold "always" <> " create a codebase in your home directory if one does not already exist.")
])
Run (RunFromSymbol mainName) -> do
(closeCodebase, theCodebase) <- getCodebaseOrExit mcodepath
(closeCodebase, theCodebase) <- getCodebaseOrExit mCodePathOption
runtime <- RTI.startRuntime
execute theCodebase runtime mainName
closeCodebase
@ -86,36 +102,41 @@ main = do
case e of
Left _ -> PT.putPrettyLn $ P.callout "⚠️" "I couldn't find that file or it is for some reason unreadable."
Right contents -> do
(closeCodebase, theCodebase) <- getCodebaseOrExit mcodepath
(closeCodebase, theCodebase) <- getCodebaseOrExit mCodePathOption
rt <- RTI.startRuntime
let fileEvent = Input.UnisonFileChanged (Text.pack file) contents
launch currentDir config rt theCodebase [Left fileEvent, Right $ Input.ExecuteI mainName, Right Input.QuitI] Nothing
launch currentDir config rt theCodebase [Left fileEvent, Right $ Input.ExecuteI mainName, Right Input.QuitI] Nothing ShouldNotDownloadBase
closeCodebase
Run (RunFromPipe mainName) -> do
e <- safeReadUtf8StdIn
case e of
Left _ -> PT.putPrettyLn $ P.callout "⚠️" "I had trouble reading this input."
Right contents -> do
(closeCodebase, theCodebase) <- getCodebaseOrExit mcodepath
(closeCodebase, theCodebase) <- getCodebaseOrExit mCodePathOption
rt <- RTI.startRuntime
let fileEvent = Input.UnisonFileChanged (Text.pack "<standard input>") contents
launch
currentDir config rt theCodebase
[Left fileEvent, Right $ Input.ExecuteI mainName, Right Input.QuitI]
Nothing
ShouldNotDownloadBase
closeCodebase
Transcript shouldFork shouldSaveCodebase transcriptFiles ->
runTranscripts renderUsageInfo shouldFork shouldSaveCodebase mcodepath transcriptFiles
Launch isHeadless codebaseServerOpts -> do
(closeCodebase, theCodebase) <- getCodebaseOrExit mcodepath
runTranscripts renderUsageInfo shouldFork shouldSaveCodebase mCodePathOption transcriptFiles
Launch isHeadless codebaseServerOpts downloadBase -> do
(closeCodebase, theCodebase) <- getCodebaseOrExit mCodePathOption
runtime <- RTI.startRuntime
Server.startServer codebaseServerOpts runtime theCodebase $ \baseUrl -> do
PT.putPrettyLn $ P.lines
["The Unison Codebase UI is running at", P.string $ Server.urlFor Server.UI baseUrl]
case isHeadless of
Headless -> do
PT.putPrettyLn $ P.lines
["I've started the codebase API server at" , P.string $ Server.urlFor Server.Api baseUrl]
PT.putPrettyLn $
P.lines
[ "I've started the Codebase API server at",
P.string $ Server.urlFor Server.Api baseUrl,
"and the Codebase UI at",
P.string $ Server.urlFor Server.UI baseUrl
]
PT.putPrettyLn $ P.string "Running the codebase manager headless with "
<> P.shown GHC.Conc.numCapabilities
<> " "
@ -124,19 +145,20 @@ main = do
mvar <- newEmptyMVar
takeMVar mvar
WithCLI -> do
PT.putPrettyLn $ P.string "Now starting the Unison Codebase Manager..."
launch currentDir config runtime theCodebase [] (Just baseUrl)
PT.putPrettyLn $ P.string "Now starting the Unison Codebase Manager (UCM)..."
launch currentDir config runtime theCodebase [] (Just baseUrl) downloadBase
closeCodebase
prepareTranscriptDir :: ShouldForkCodebase -> Maybe FilePath -> IO FilePath
prepareTranscriptDir shouldFork mcodepath = do
prepareTranscriptDir :: ShouldForkCodebase -> Maybe CodebasePathOption -> IO FilePath
prepareTranscriptDir shouldFork mCodePathOption = do
tmp <- Temp.getCanonicalTemporaryDirectory >>= (`Temp.createTempDirectory` "transcript")
let cbInit = SC.init
case shouldFork of
UseFork -> do
getCodebaseOrExit mcodepath
path <- Codebase.getCodebaseDir mcodepath
PT.putPrettyLn $ P.lines [
-- A forked codebase does not need to Create a codebase, because it already exists
getCodebaseOrExit mCodePathOption
path <- Codebase.getCodebaseDir (fmap codebasePathOptionToPath mCodePathOption)
PT.putPrettyLn $ P.lines [
P.wrap "Transcript will be run on a copy of the codebase at: ", "",
P.indentN 2 (P.string path)
]
@ -164,7 +186,8 @@ runTranscripts' mcodepath transcriptDir args = do
P.indentN 2 $ P.string err])
Right stanzas -> do
configFilePath <- getConfigFilePath mcodepath
(closeCodebase, theCodebase) <- getCodebaseOrExit $ Just transcriptDir
-- We don't need to create a codebase through `getCodebaseOrExit` as we've already done so previously.
(closeCodebase, theCodebase) <- getCodebaseOrExit (Just (DontCreateCodebaseWhenMissing transcriptDir))
mdOut <- TR.run transcriptDir configFilePath stanzas theCodebase
closeCodebase
let out = currentDir FP.</>
@ -187,12 +210,12 @@ runTranscripts
:: UsageRenderer
-> ShouldForkCodebase
-> ShouldSaveCodebase
-> Maybe FilePath
-> Maybe CodebasePathOption
-> NonEmpty String
-> IO ()
runTranscripts renderUsageInfo shouldFork shouldSaveTempCodebase mcodepath args = do
runTranscripts renderUsageInfo shouldFork shouldSaveTempCodebase mCodePathOption args = do
progName <- getProgName
transcriptDir <- prepareTranscriptDir shouldFork mcodepath
transcriptDir <- prepareTranscriptDir shouldFork mCodePathOption
completed <-
runTranscripts' (Just transcriptDir) transcriptDir args
case shouldSaveTempCodebase of
@ -222,18 +245,25 @@ launch
-> Codebase.Codebase IO Symbol Ann
-> [Either Input.Event Input.Input]
-> Maybe Server.BaseUrl
-> ShouldDownloadBase
-> IO ()
launch dir config runtime codebase inputs serverBaseUrl =
CommandLine.main
dir
defaultBaseLib
initialPath
config
inputs
runtime
codebase
Version.gitDescribe
serverBaseUrl
launch dir config runtime codebase inputs serverBaseUrl shouldDownloadBase =
let
downloadBase = case defaultBaseLib of
Just remoteNS | shouldDownloadBase == ShouldDownloadBase -> Welcome.DownloadBase remoteNS
_ -> Welcome.DontDownloadBase
welcome = Welcome.Welcome downloadBase dir Version.gitDescribe
in
CommandLine.main
dir
welcome
initialPath
config
inputs
runtime
codebase
serverBaseUrl
isMarkdown :: String -> Bool
isMarkdown md = case FP.takeExtension md of
@ -256,13 +286,10 @@ defaultBaseLib :: Maybe ReadRemoteNamespace
defaultBaseLib = rightMay $
runParser VP.defaultBaseLib "version" (Text.pack Version.gitDescribe)
getCodebaseOrExit :: Maybe Codebase.CodebasePath -> IO (IO (), Codebase.Codebase IO Symbol Ann)
getCodebaseOrExit maybeSpecifiedDir = do
-- Likely we should only change codebase format 2? Or both?
-- Notes for selves: create a function 'openOrCreateCodebase' which handles v1/v2 codebase provided / no codebase specified
-- encode error messages as types. Our spike / idea is below:
codebaseDir <- CodebaseInit.homeOrSpecifiedDir maybeSpecifiedDir
CodebaseInit.openOrCreateCodebase SC.init "main" codebaseDir >>= \case
getCodebaseOrExit :: Maybe CodebasePathOption -> IO (IO (), Codebase.Codebase IO Symbol Ann)
getCodebaseOrExit codebasePathOption = do
initOptions <- argsToCodebaseInitOptions codebasePathOption
CodebaseInit.openOrCreateCodebase SC.init "main" initOptions >>= \case
Error dir error ->
let
message = do
@ -271,10 +298,9 @@ getCodebaseOrExit maybeSpecifiedDir = do
case error of
NoCodebaseFoundAtSpecifiedDir ->
-- TODO: Perhaps prompt the user to create a codebase in that directory right away?
pure (P.lines
[ "No codebase exists in " <> pDir <> ".",
"Run `" <> executableName <> " --codebase " <> P.string dir <> " init` to create one, then try again!"
"Run `" <> executableName <> " --codebase-create " <> P.string dir <> " to create one, then try again!"
])
FoundV1Codebase ->
@ -293,7 +319,7 @@ getCodebaseOrExit maybeSpecifiedDir = do
CreatedCodebase dir cb -> do
pDir <- prettyDir dir
PT.putPrettyLn' ""
PT.putPrettyLn' . P.indentN 2 . P.wrap $ "I created a new codebase for you at" <> pDir
PT.putPrettyLn' . P.indentN 2 . P.wrap $ "I created a new codebase for you at" <> P.blue pDir
pure cb
OpenedCodebase _ cb ->
@ -301,3 +327,16 @@ getCodebaseOrExit maybeSpecifiedDir = do
where
prettyDir dir = P.string <$> canonicalizePath dir
argsToCodebaseInitOptions :: Maybe CodebasePathOption -> IO CodebaseInit.CodebaseInitOptions
argsToCodebaseInitOptions pathOption =
case pathOption of
Just (CreateCodebaseWhenMissing path) -> pure $ Specified (CreateWhenMissing path)
Just (DontCreateCodebaseWhenMissing path) -> pure $ Specified (DontCreateWhenMissing path)
Nothing -> do Home <$> getHomeDirectory
codebasePathOptionToPath :: CodebasePathOption -> FilePath
codebasePathOptionToPath codebasePathOption =
case codebasePathOption of
CreateCodebaseWhenMissing p -> p
DontCreateCodebaseWhenMissing p -> p

View File

@ -22,7 +22,7 @@ packages:
- codebase2/util-term
#compiler-check: match-exact
resolver: lts-18.6
resolver: lts-18.9
extra-deps:
- github: unisonweb/configurator
@ -35,18 +35,8 @@ extra-deps:
- prelude-extras-0.4.0.3@sha256:1c10b0123ea13a6423d74a8fcbaeb2d5249b472588abde418a36b47b7c4f48c8,1163
- sandi-0.5@sha256:b278d072ca717706ea38f9bd646e023f7f2576a778fb43565b434f93638849aa,3010
- strings-1.1@sha256:0285dec4c8ab262359342b3e5ef1eb567074669461b9b38404f1cb870c881c5c,1617
- random-1.2.0
# remove these when stackage upgrades containers
# (these = containers 0.6.4, text-1.2.4, binary-0.8.8, parsec-3.1.14, Cabal-3.2.1.0)
# see https://github.com/unisonweb/unison/pull/1807#issuecomment-777069869
- containers-0.6.4.1
- text-1.2.4.1
- binary-0.8.8.0
- parsec-3.1.14.0
- Cabal-3.2.1.0
- fuzzyfind-3.0.0
- monad-validate-1.2.0.0@sha256:9850f408431098b28806dd464b6825a88a0b56c84f380d7fe0454c1df9d6f881,3505
- optparse-applicative-0.16.1.0 # We need some features from the most recent revision
ghc-options:
# All packages

View File

@ -669,6 +669,9 @@ cleanup :: Var v => Type v a -> Type v a
cleanup t | not Settings.cleanupTypes = t
cleanup t = cleanupVars1 . cleanupAbilityLists $ t
builtinAbilities :: Set Reference
builtinAbilities = Set.fromList [builtinIORef, stmRef]
instance Show a => Show (F a) where
showsPrec = go where
go _ (Ref r) = shows r

View File

@ -79,3 +79,94 @@ f x = let
.> load scratch.u
```
## Parens around infix patterns
Regression test for https://github.com/unisonweb/unison/issues/2224
```unison:hide
f : [a] -> a
f xs = match xs with
x +: (x' +: rest) -> x
g : [a] -> a
g xs = match xs with
(rest :+ x') :+ x -> x
h : [[a]] -> a
h xs = match xs with
(rest :+ (rest' :+ x)) -> x
```
```ucm
.> add
.> edit f g
.> reflog
.> reset-root 2
```
``` ucm
.> load scratch.u
```
## Type application inserts necessary parens
Regression test for https://github.com/unisonweb/unison/issues/2392
```unison:hide
unique ability Zonk where zonk : Nat
unique type Foo x y =
foo : Nat -> Foo ('{Zonk} a) ('{Zonk} b) -> Nat
foo n _ = n
```
```ucm
.> add
.> edit foo Zonk Foo
.> reflog
.> reset-root 2
```
``` ucm
.> load scratch.u
```
## Long lines with repeated operators
Regression test for https://github.com/unisonweb/unison/issues/1035
```unison:hide
foo : Text
foo =
"aaaaaaaaaaaaaaaaaaaaaa" ++ "bbbbbbbbbbbbbbbbbbbbbb" ++ "cccccccccccccccccccccc" ++ "dddddddddddddddddddddd"
```
```ucm
.> add
.> edit foo
.> reflog
.> reset-root 2
```
``` ucm
.> load scratch.u
```
## Emphasis in docs inserts the right number of underscores
Regression test for https://github.com/unisonweb/unison/issues/2408
```unison:hide
myDoc = {{ **my text** __my text__ **MY_TEXT** ___MY__TEXT___ ~~MY~TEXT~~ **MY*TEXT** }}
```
```ucm
.> add
.> edit myDoc
.> undo
```
``` ucm
.> load scratch.u
```

View File

@ -34,15 +34,15 @@ x = 1 + 1
most recent, along with the command that got us there. Try:
`fork 2 .old`
`fork #pqvd5behc2 .old` to make an old namespace
`fork #bt17giel42 .old` to make an old namespace
accessible again,
`reset-root #pqvd5behc2` to reset the root namespace and
`reset-root #bt17giel42` to reset the root namespace and
its history to that of the
specified namespace.
1. #8rn1an5gj8 : add
2. #pqvd5behc2 : builtins.mergeio
1. #agadr8gg6g : add
2. #bt17giel42 : builtins.mergeio
3. #sjg2v58vn2 : (initial reflogged namespace)
.> reset-root 2
@ -116,17 +116,17 @@ Without the above stanza, the `edit` will send the definition to the most recent
most recent, along with the command that got us there. Try:
`fork 2 .old`
`fork #pqvd5behc2 .old` to make an old namespace
`fork #bt17giel42 .old` to make an old namespace
accessible again,
`reset-root #pqvd5behc2` to reset the root namespace and
`reset-root #bt17giel42` to reset the root namespace and
its history to that of the
specified namespace.
1. #dbvse9969b : add
2. #pqvd5behc2 : reset-root #pqvd5behc2
3. #8rn1an5gj8 : add
4. #pqvd5behc2 : builtins.mergeio
1. #rhf1s808fb : add
2. #bt17giel42 : reset-root #bt17giel42
3. #agadr8gg6g : add
4. #bt17giel42 : builtins.mergeio
5. #sjg2v58vn2 : (initial reflogged namespace)
.> reset-root 2
@ -157,7 +157,6 @@ unique type Blah = Blah Boolean Boolean
f : Blah -> Boolean
f x = let
0
(Blah.Blah a b) = x
a
```
@ -181,11 +180,7 @@ f x = let
= Blah Boolean Boolean
f : Blah -> Boolean
f x =
0
let
(Blah a b) = x
a
f = cases Blah a b -> a
You can edit them there, then do `update` to replace the
definitions currently in this namespace.
@ -196,19 +191,19 @@ f x = let
most recent, along with the command that got us there. Try:
`fork 2 .old`
`fork #pqvd5behc2 .old` to make an old namespace
`fork #bt17giel42 .old` to make an old namespace
accessible again,
`reset-root #pqvd5behc2` to reset the root namespace and
`reset-root #bt17giel42` to reset the root namespace and
its history to that of the
specified namespace.
1. #53gruvtk78 : add
2. #pqvd5behc2 : reset-root #pqvd5behc2
3. #dbvse9969b : add
4. #pqvd5behc2 : reset-root #pqvd5behc2
5. #8rn1an5gj8 : add
6. #pqvd5behc2 : builtins.mergeio
1. #gj5agagj7s : add
2. #bt17giel42 : reset-root #bt17giel42
3. #rhf1s808fb : add
4. #bt17giel42 : reset-root #bt17giel42
5. #agadr8gg6g : add
6. #bt17giel42 : builtins.mergeio
7. #sjg2v58vn2 : (initial reflogged namespace)
.> reset-root 2
@ -229,3 +224,302 @@ f x = let
f : Blah -> Boolean
```
## Parens around infix patterns
Regression test for https://github.com/unisonweb/unison/issues/2224
```unison
f : [a] -> a
f xs = match xs with
x +: (x' +: rest) -> x
g : [a] -> a
g xs = match xs with
(rest :+ x') :+ x -> x
h : [[a]] -> a
h xs = match xs with
(rest :+ (rest' :+ x)) -> x
```
```ucm
.> add
⍟ I've added these definitions:
f : [a] -> a
g : [a] -> a
h : [[a]] -> a
.> edit f g
☝️
I added these definitions to the top of
/Users/runar/work/unison/scratch.u
f : [a] -> a
f = cases x +: (x' +: rest) -> x
g : [a] -> a
g = cases rest :+ x' :+ x -> x
You can edit them there, then do `update` to replace the
definitions currently in this namespace.
.> reflog
Here is a log of the root namespace hashes, starting with the
most recent, along with the command that got us there. Try:
`fork 2 .old`
`fork #bt17giel42 .old` to make an old namespace
accessible again,
`reset-root #bt17giel42` to reset the root namespace and
its history to that of the
specified namespace.
1. #3igmh2it4p : add
2. #bt17giel42 : reset-root #bt17giel42
3. #gj5agagj7s : add
4. #bt17giel42 : reset-root #bt17giel42
5. #rhf1s808fb : add
6. #bt17giel42 : reset-root #bt17giel42
7. #agadr8gg6g : add
8. #bt17giel42 : builtins.mergeio
9. #sjg2v58vn2 : (initial reflogged namespace)
.> reset-root 2
Done.
```
```ucm
.> load 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`:
f : [a] -> a
g : [a] -> a
```
## Type application inserts necessary parens
Regression test for https://github.com/unisonweb/unison/issues/2392
```unison
unique ability Zonk where zonk : Nat
unique type Foo x y =
foo : Nat -> Foo ('{Zonk} a) ('{Zonk} b) -> Nat
foo n _ = n
```
```ucm
.> add
⍟ I've added these definitions:
unique type Foo x y
unique ability Zonk
foo : Nat -> Foo ('{Zonk} a) ('{Zonk} b) -> Nat
.> edit foo Zonk Foo
☝️
I added these definitions to the top of
/Users/runar/work/unison/scratch.u
unique type Foo x y
=
unique ability Zonk where zonk : {Zonk} Nat
foo : Nat -> Foo ('{Zonk} a) ('{Zonk} b) -> Nat
foo n _ = n
You can edit them there, then do `update` to replace the
definitions currently in this namespace.
.> reflog
Here is a log of the root namespace hashes, starting with the
most recent, along with the command that got us there. Try:
`fork 2 .old`
`fork #bt17giel42 .old` to make an old namespace
accessible again,
`reset-root #bt17giel42` to reset the root namespace and
its history to that of the
specified namespace.
1. #jsnoueu9le : add
2. #bt17giel42 : reset-root #bt17giel42
3. #3igmh2it4p : add
4. #bt17giel42 : reset-root #bt17giel42
5. #gj5agagj7s : add
6. #bt17giel42 : reset-root #bt17giel42
7. #rhf1s808fb : add
8. #bt17giel42 : reset-root #bt17giel42
9. #agadr8gg6g : add
10. #bt17giel42 : builtins.mergeio
11. #sjg2v58vn2 : (initial reflogged namespace)
.> reset-root 2
Done.
```
```ucm
.> load 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`:
unique type Foo x y
unique ability Zonk
foo : Nat -> Foo ('{Zonk} a) ('{Zonk} b) -> Nat
```
## Long lines with repeated operators
Regression test for https://github.com/unisonweb/unison/issues/1035
```unison
foo : Text
foo =
"aaaaaaaaaaaaaaaaaaaaaa" ++ "bbbbbbbbbbbbbbbbbbbbbb" ++ "cccccccccccccccccccccc" ++ "dddddddddddddddddddddd"
```
```ucm
.> add
⍟ I've added these definitions:
foo : Text
.> edit foo
☝️
I added these definitions to the top of
/Users/runar/work/unison/scratch.u
foo : Text
foo =
use Text ++
"aaaaaaaaaaaaaaaaaaaaaa"
++ "bbbbbbbbbbbbbbbbbbbbbb"
++ "cccccccccccccccccccccc"
++ "dddddddddddddddddddddd"
You can edit them there, then do `update` to replace the
definitions currently in this namespace.
.> reflog
Here is a log of the root namespace hashes, starting with the
most recent, along with the command that got us there. Try:
`fork 2 .old`
`fork #bt17giel42 .old` to make an old namespace
accessible again,
`reset-root #bt17giel42` to reset the root namespace and
its history to that of the
specified namespace.
1. #vbmanbqtlh : add
2. #bt17giel42 : reset-root #bt17giel42
3. #jsnoueu9le : add
4. #bt17giel42 : reset-root #bt17giel42
5. #3igmh2it4p : add
6. #bt17giel42 : reset-root #bt17giel42
7. #gj5agagj7s : add
8. #bt17giel42 : reset-root #bt17giel42
9. #rhf1s808fb : add
10. #bt17giel42 : reset-root #bt17giel42
11. #agadr8gg6g : add
12. #bt17giel42 : builtins.mergeio
13. #sjg2v58vn2 : (initial reflogged namespace)
.> reset-root 2
Done.
```
```ucm
.> load 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 : Text
```
## Emphasis in docs inserts the right number of underscores
Regression test for https://github.com/unisonweb/unison/issues/2408
```unison
myDoc = {{ **my text** __my text__ **MY_TEXT** ___MY__TEXT___ ~~MY~TEXT~~ **MY*TEXT** }}
```
```ucm
.> add
⍟ I've added these definitions:
myDoc : Doc2
.> edit myDoc
☝️
I added these definitions to the top of
/Users/runar/work/unison/scratch.u
myDoc : Doc2
myDoc =
{{
**my text** __my text__ **MY_TEXT** ___MY__TEXT___
~~MY~TEXT~~ **MY*TEXT**
}}
You can edit them there, then do `update` to replace the
definitions currently in this namespace.
.> undo
Here are the changes I undid
Added definitions:
1. myDoc : Doc2
```
```ucm
.> load 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`:
myDoc : Doc2
```

View File

@ -166,3 +166,34 @@ to actual show that the serialization works.
.> io.test tests
.> io.test badLoad
```
```unison
validateTest : Link.Term ->{IO} Result
validateTest l = match Code.lookup l with
None -> Fail "Couldn't look up link"
Some co -> match Code.validate [(l, co)] with
Some f -> Fail "invalid code pre"
None -> match Code.deserialize (Code.serialize co) with
Left _ -> Fail "code failed deserialization"
Right co -> match Code.validate [(l, co)] with
Some f -> Fail "invalid code post"
None -> Ok "validated"
vtests : '{IO} [Result]
vtests _ =
List.map validateTest
[ termLink fib10
, termLink compose
, termLink List.all
, termLink hex
, termLink isDirectory
, termLink delay
, termLink printLine
, termLink isNone
]
```
```ucm
.> add
.> io.test vtests
```

View File

@ -281,3 +281,67 @@ to actual show that the serialization works.
Tip: Use view badLoad to view the source of a test.
```
```unison
validateTest : Link.Term ->{IO} Result
validateTest l = match Code.lookup l with
None -> Fail "Couldn't look up link"
Some co -> match Code.validate [(l, co)] with
Some f -> Fail "invalid code pre"
None -> match Code.deserialize (Code.serialize co) with
Left _ -> Fail "code failed deserialization"
Right co -> match Code.validate [(l, co)] with
Some f -> Fail "invalid code post"
None -> Ok "validated"
vtests : '{IO} [Result]
vtests _ =
List.map validateTest
[ termLink fib10
, termLink compose
, termLink List.all
, termLink hex
, termLink isDirectory
, termLink delay
, termLink printLine
, termLink isNone
]
```
```ucm
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`:
validateTest : Link.Term ->{IO} Result
vtests : '{IO} [Result]
```
```ucm
.> add
⍟ I've added these definitions:
validateTest : Link.Term ->{IO} Result
vtests : '{IO} [Result]
.> io.test vtests
New test results:
◉ vtests validated
◉ vtests validated
◉ vtests validated
◉ vtests validated
◉ vtests validated
◉ vtests validated
◉ vtests validated
◉ vtests validated
✅ 8 test(s) passing
Tip: Use view vtests to view the source of a test.
```

View File

@ -5,7 +5,7 @@ basicFormatting = {{
Paragraphs are separated by one or more blanklines. Sections
have a title and 0 or more paragraphs or other section elements.
Text can be __bold__, *italicized*, ~~strikethrough~~, or
Text can be **bold**, __italicized__, ~~strikethrough~~, or
''monospaced''.
You can link to Unison terms, types, and external URLs:
@ -20,7 +20,7 @@ basicFormatting = {{
This is useful for creating documents programmatically
or just including other documents.
*Next up:* {lists}
__Next up:__ {lists}
}}
lists = {{
@ -168,7 +168,7 @@ This is an aside. {{ docAside {{ Some extra detail that doesn't belong in main t
docBlockquote {{
"And what is the use of a book," thought Alice, "without pictures or conversation?"
*Lewis Carroll, Alice's Adventures in Wonderland* }}
_Lewis Carroll, Alice's Adventures in Wonderland_ }}
}}
{{ docTooltip {{Hover over me}} {{Extra detail}} }}

View File

@ -113,8 +113,8 @@ and the rendered output using `display`:
Sections have a title and 0 or more paragraphs or other
section elements.
Text can be __bold__, *italicized*, ~~strikethrough~~, or
''monospaced''.
Text can be **bold**, __italicized__, ~~strikethrough~~,
or ''monospaced''.
You can link to Unison terms, types, and external URLs:
@ -129,7 +129,7 @@ and the rendered output using `display`:
useful for creating documents programmatically or just
including other documents.
*Next up:* {lists}
__Next up:__ {lists}
}}
.> display basicFormatting
@ -469,7 +469,7 @@ and the rendered output using `display`:
"And what is the use of a book," thought Alice, "without
pictures or conversation?"
*Lewis Carroll, Alice's Adventures in Wonderland*
__Lewis Carroll, Alice's Adventures in Wonderland__
}} }}
{{ docTooltip {{ Hover over me }} {{ Extra detail }} }}

View File

@ -20,442 +20,446 @@ Let's try it!
1. builtin type Any
2. Any.Any : a -> Any
3. builtin type Boolean
4. Boolean.not : Boolean -> Boolean
5. bug : a -> b
6. builtin type Bytes
7. Bytes.++ : Bytes -> Bytes -> Bytes
8. Bytes.at : Nat -> Bytes -> Optional Nat
9. Bytes.decodeNat16be : Bytes -> Optional (Nat, Bytes)
10. Bytes.decodeNat16le : Bytes -> Optional (Nat, Bytes)
11. Bytes.decodeNat32be : Bytes -> Optional (Nat, Bytes)
12. Bytes.decodeNat32le : Bytes -> Optional (Nat, Bytes)
13. Bytes.decodeNat64be : Bytes -> Optional (Nat, Bytes)
14. Bytes.decodeNat64le : Bytes -> Optional (Nat, Bytes)
15. Bytes.drop : Nat -> Bytes -> Bytes
16. Bytes.empty : Bytes
17. Bytes.encodeNat16be : Nat -> Bytes
18. Bytes.encodeNat16le : Nat -> Bytes
19. Bytes.encodeNat32be : Nat -> Bytes
20. Bytes.encodeNat32le : Nat -> Bytes
21. Bytes.encodeNat64be : Nat -> Bytes
22. Bytes.encodeNat64le : Nat -> Bytes
23. Bytes.flatten : Bytes -> Bytes
24. Bytes.fromBase16 : Bytes -> Either Text Bytes
25. Bytes.fromBase32 : Bytes -> Either Text Bytes
26. Bytes.fromBase64 : Bytes -> Either Text Bytes
27. Bytes.fromBase64UrlUnpadded : Bytes -> Either Text Bytes
28. Bytes.fromList : [Nat] -> Bytes
29. Bytes.size : Bytes -> Nat
30. Bytes.take : Nat -> Bytes -> Bytes
31. Bytes.toBase16 : Bytes -> Bytes
32. Bytes.toBase32 : Bytes -> Bytes
33. Bytes.toBase64 : Bytes -> Bytes
34. Bytes.toBase64UrlUnpadded : Bytes -> Bytes
35. Bytes.toList : Bytes -> [Nat]
36. builtin type Char
37. Char.fromNat : Nat -> Char
38. Char.toNat : Char -> Nat
39. Char.toText : Char -> Text
40. builtin type Code
41. Code.cache_ : [(Term, Code)] ->{IO} [Term]
42. Code.dependencies : Code -> [Term]
43. Code.deserialize : Bytes -> Either Text Code
44. Code.isMissing : Term ->{IO} Boolean
45. Code.lookup : Term ->{IO} Optional Code
46. Code.serialize : Code -> Bytes
47. crypto.hash : HashAlgorithm -> a -> Bytes
48. builtin type crypto.HashAlgorithm
49. crypto.HashAlgorithm.Blake2b_256 : HashAlgorithm
50. crypto.HashAlgorithm.Blake2b_512 : HashAlgorithm
51. crypto.HashAlgorithm.Blake2s_256 : HashAlgorithm
52. crypto.HashAlgorithm.Sha2_256 : HashAlgorithm
53. crypto.HashAlgorithm.Sha2_512 : HashAlgorithm
54. crypto.HashAlgorithm.Sha3_256 : HashAlgorithm
55. crypto.HashAlgorithm.Sha3_512 : HashAlgorithm
56. crypto.hashBytes : HashAlgorithm -> Bytes -> Bytes
57. crypto.hmac : HashAlgorithm -> Bytes -> a -> Bytes
58. crypto.hmacBytes : HashAlgorithm
3. Any.unsafeExtract : Any -> a
4. builtin type Boolean
5. Boolean.not : Boolean -> Boolean
6. bug : a -> b
7. builtin type Bytes
8. Bytes.++ : Bytes -> Bytes -> Bytes
9. Bytes.at : Nat -> Bytes -> Optional Nat
10. Bytes.decodeNat16be : Bytes -> Optional (Nat, Bytes)
11. Bytes.decodeNat16le : Bytes -> Optional (Nat, Bytes)
12. Bytes.decodeNat32be : Bytes -> Optional (Nat, Bytes)
13. Bytes.decodeNat32le : Bytes -> Optional (Nat, Bytes)
14. Bytes.decodeNat64be : Bytes -> Optional (Nat, Bytes)
15. Bytes.decodeNat64le : Bytes -> Optional (Nat, Bytes)
16. Bytes.drop : Nat -> Bytes -> Bytes
17. Bytes.empty : Bytes
18. Bytes.encodeNat16be : Nat -> Bytes
19. Bytes.encodeNat16le : Nat -> Bytes
20. Bytes.encodeNat32be : Nat -> Bytes
21. Bytes.encodeNat32le : Nat -> Bytes
22. Bytes.encodeNat64be : Nat -> Bytes
23. Bytes.encodeNat64le : Nat -> Bytes
24. Bytes.flatten : Bytes -> Bytes
25. Bytes.fromBase16 : Bytes -> Either Text Bytes
26. Bytes.fromBase32 : Bytes -> Either Text Bytes
27. Bytes.fromBase64 : Bytes -> Either Text Bytes
28. Bytes.fromBase64UrlUnpadded : Bytes -> Either Text Bytes
29. Bytes.fromList : [Nat] -> Bytes
30. Bytes.size : Bytes -> Nat
31. Bytes.take : Nat -> Bytes -> Bytes
32. Bytes.toBase16 : Bytes -> Bytes
33. Bytes.toBase32 : Bytes -> Bytes
34. Bytes.toBase64 : Bytes -> Bytes
35. Bytes.toBase64UrlUnpadded : Bytes -> Bytes
36. Bytes.toList : Bytes -> [Nat]
37. builtin type Char
38. Char.fromNat : Nat -> Char
39. Char.toNat : Char -> Nat
40. Char.toText : Char -> Text
41. builtin type Code
42. Code.cache_ : [(Term, Code)] ->{IO} [Term]
43. Code.dependencies : Code -> [Term]
44. Code.deserialize : Bytes -> Either Text Code
45. Code.display : Text -> Code -> Text
46. Code.isMissing : Term ->{IO} Boolean
47. Code.lookup : Term ->{IO} Optional Code
48. Code.serialize : Code -> Bytes
49. Code.validate : [(Term, Code)] ->{IO} Optional Failure
50. crypto.hash : HashAlgorithm -> a -> Bytes
51. builtin type crypto.HashAlgorithm
52. crypto.HashAlgorithm.Blake2b_256 : HashAlgorithm
53. crypto.HashAlgorithm.Blake2b_512 : HashAlgorithm
54. crypto.HashAlgorithm.Blake2s_256 : HashAlgorithm
55. crypto.HashAlgorithm.Sha2_256 : HashAlgorithm
56. crypto.HashAlgorithm.Sha2_512 : HashAlgorithm
57. crypto.HashAlgorithm.Sha3_256 : HashAlgorithm
58. crypto.HashAlgorithm.Sha3_512 : HashAlgorithm
59. crypto.hashBytes : HashAlgorithm -> Bytes -> Bytes
60. crypto.hmac : HashAlgorithm -> Bytes -> a -> Bytes
61. crypto.hmacBytes : HashAlgorithm
-> Bytes
-> Bytes
-> Bytes
59. Debug.watch : Text -> a -> a
60. unique type Doc
61. Doc.Blob : Text -> Doc
62. Doc.Evaluate : Term -> Doc
63. Doc.Join : [Doc] -> Doc
64. Doc.Link : Link -> Doc
65. Doc.Signature : Term -> Doc
66. Doc.Source : Link -> Doc
67. structural type Either a b
68. Either.Left : a -> Either a b
69. Either.Right : b -> Either a b
70. structural ability Exception
71. Exception.raise : Failure ->{Exception} x
72. builtin type Float
73. Float.* : Float -> Float -> Float
74. Float.+ : Float -> Float -> Float
75. Float.- : Float -> Float -> Float
76. Float./ : Float -> Float -> Float
77. Float.abs : Float -> Float
78. Float.acos : Float -> Float
79. Float.acosh : Float -> Float
80. Float.asin : Float -> Float
81. Float.asinh : Float -> Float
82. Float.atan : Float -> Float
83. Float.atan2 : Float -> Float -> Float
84. Float.atanh : Float -> Float
85. Float.ceiling : Float -> Int
86. Float.cos : Float -> Float
87. Float.cosh : Float -> Float
88. Float.eq : Float -> Float -> Boolean
89. Float.exp : Float -> Float
90. Float.floor : Float -> Int
91. Float.fromRepresentation : Nat -> Float
92. Float.fromText : Text -> Optional Float
93. Float.gt : Float -> Float -> Boolean
94. Float.gteq : Float -> Float -> Boolean
95. Float.log : Float -> Float
96. Float.logBase : Float -> Float -> Float
97. Float.lt : Float -> Float -> Boolean
98. Float.lteq : Float -> Float -> Boolean
99. Float.max : Float -> Float -> Float
100. Float.min : Float -> Float -> Float
101. Float.pow : Float -> Float -> Float
102. Float.round : Float -> Int
103. Float.sin : Float -> Float
104. Float.sinh : Float -> Float
105. Float.sqrt : Float -> Float
106. Float.tan : Float -> Float
107. Float.tanh : Float -> Float
108. Float.toRepresentation : Float -> Nat
109. Float.toText : Float -> Text
110. Float.truncate : Float -> Int
111. builtin type Int
112. Int.* : Int -> Int -> Int
113. Int.+ : Int -> Int -> Int
114. Int.- : Int -> Int -> Int
115. Int./ : Int -> Int -> Int
116. Int.and : Int -> Int -> Int
117. Int.complement : Int -> Int
118. Int.eq : Int -> Int -> Boolean
119. Int.fromRepresentation : Nat -> Int
120. Int.fromText : Text -> Optional Int
121. Int.gt : Int -> Int -> Boolean
122. Int.gteq : Int -> Int -> Boolean
123. Int.increment : Int -> Int
124. Int.isEven : Int -> Boolean
125. Int.isOdd : Int -> Boolean
126. Int.leadingZeros : Int -> Nat
127. Int.lt : Int -> Int -> Boolean
128. Int.lteq : Int -> Int -> Boolean
129. Int.mod : Int -> Int -> Int
130. Int.negate : Int -> Int
131. Int.or : Int -> Int -> Int
132. Int.popCount : Int -> Nat
133. Int.pow : Int -> Nat -> Int
134. Int.shiftLeft : Int -> Nat -> Int
135. Int.shiftRight : Int -> Nat -> Int
136. Int.signum : Int -> Int
137. Int.toFloat : Int -> Float
138. Int.toRepresentation : Int -> Nat
139. Int.toText : Int -> Text
140. Int.trailingZeros : Int -> Nat
141. Int.truncate0 : Int -> Nat
142. Int.xor : Int -> Int -> Int
143. unique type io2.BufferMode
144. io2.BufferMode.BlockBuffering : BufferMode
145. io2.BufferMode.LineBuffering : BufferMode
146. io2.BufferMode.NoBuffering : BufferMode
147. io2.BufferMode.SizedBlockBuffering : Nat -> BufferMode
148. unique type io2.Failure
149. io2.Failure.Failure : Type -> Text -> Any -> Failure
150. unique type io2.FileMode
151. io2.FileMode.Append : FileMode
152. io2.FileMode.Read : FileMode
153. io2.FileMode.ReadWrite : FileMode
154. io2.FileMode.Write : FileMode
155. builtin type io2.Handle
156. builtin type io2.IO
157. io2.IO.clientSocket.impl : Text
62. Debug.watch : Text -> a -> a
63. unique type Doc
64. Doc.Blob : Text -> Doc
65. Doc.Evaluate : Term -> Doc
66. Doc.Join : [Doc] -> Doc
67. Doc.Link : Link -> Doc
68. Doc.Signature : Term -> Doc
69. Doc.Source : Link -> Doc
70. structural type Either a b
71. Either.Left : a -> Either a b
72. Either.Right : b -> Either a b
73. structural ability Exception
74. Exception.raise : Failure ->{Exception} x
75. builtin type Float
76. Float.* : Float -> Float -> Float
77. Float.+ : Float -> Float -> Float
78. Float.- : Float -> Float -> Float
79. Float./ : Float -> Float -> Float
80. Float.abs : Float -> Float
81. Float.acos : Float -> Float
82. Float.acosh : Float -> Float
83. Float.asin : Float -> Float
84. Float.asinh : Float -> Float
85. Float.atan : Float -> Float
86. Float.atan2 : Float -> Float -> Float
87. Float.atanh : Float -> Float
88. Float.ceiling : Float -> Int
89. Float.cos : Float -> Float
90. Float.cosh : Float -> Float
91. Float.eq : Float -> Float -> Boolean
92. Float.exp : Float -> Float
93. Float.floor : Float -> Int
94. Float.fromRepresentation : Nat -> Float
95. Float.fromText : Text -> Optional Float
96. Float.gt : Float -> Float -> Boolean
97. Float.gteq : Float -> Float -> Boolean
98. Float.log : Float -> Float
99. Float.logBase : Float -> Float -> Float
100. Float.lt : Float -> Float -> Boolean
101. Float.lteq : Float -> Float -> Boolean
102. Float.max : Float -> Float -> Float
103. Float.min : Float -> Float -> Float
104. Float.pow : Float -> Float -> Float
105. Float.round : Float -> Int
106. Float.sin : Float -> Float
107. Float.sinh : Float -> Float
108. Float.sqrt : Float -> Float
109. Float.tan : Float -> Float
110. Float.tanh : Float -> Float
111. Float.toRepresentation : Float -> Nat
112. Float.toText : Float -> Text
113. Float.truncate : Float -> Int
114. builtin type Int
115. Int.* : Int -> Int -> Int
116. Int.+ : Int -> Int -> Int
117. Int.- : Int -> Int -> Int
118. Int./ : Int -> Int -> Int
119. Int.and : Int -> Int -> Int
120. Int.complement : Int -> Int
121. Int.eq : Int -> Int -> Boolean
122. Int.fromRepresentation : Nat -> Int
123. Int.fromText : Text -> Optional Int
124. Int.gt : Int -> Int -> Boolean
125. Int.gteq : Int -> Int -> Boolean
126. Int.increment : Int -> Int
127. Int.isEven : Int -> Boolean
128. Int.isOdd : Int -> Boolean
129. Int.leadingZeros : Int -> Nat
130. Int.lt : Int -> Int -> Boolean
131. Int.lteq : Int -> Int -> Boolean
132. Int.mod : Int -> Int -> Int
133. Int.negate : Int -> Int
134. Int.or : Int -> Int -> Int
135. Int.popCount : Int -> Nat
136. Int.pow : Int -> Nat -> Int
137. Int.shiftLeft : Int -> Nat -> Int
138. Int.shiftRight : Int -> Nat -> Int
139. Int.signum : Int -> Int
140. Int.toFloat : Int -> Float
141. Int.toRepresentation : Int -> Nat
142. Int.toText : Int -> Text
143. Int.trailingZeros : Int -> Nat
144. Int.truncate0 : Int -> Nat
145. Int.xor : Int -> Int -> Int
146. unique type io2.BufferMode
147. io2.BufferMode.BlockBuffering : BufferMode
148. io2.BufferMode.LineBuffering : BufferMode
149. io2.BufferMode.NoBuffering : BufferMode
150. io2.BufferMode.SizedBlockBuffering : Nat -> BufferMode
151. unique type io2.Failure
152. io2.Failure.Failure : Type -> Text -> Any -> Failure
153. unique type io2.FileMode
154. io2.FileMode.Append : FileMode
155. io2.FileMode.Read : FileMode
156. io2.FileMode.ReadWrite : FileMode
157. io2.FileMode.Write : FileMode
158. builtin type io2.Handle
159. builtin type io2.IO
160. io2.IO.clientSocket.impl : Text
-> Text
->{IO} Either Failure Socket
158. io2.IO.closeFile.impl : Handle ->{IO} Either Failure ()
159. io2.IO.closeSocket.impl : Socket ->{IO} Either Failure ()
160. io2.IO.createDirectory.impl : Text
161. io2.IO.closeFile.impl : Handle ->{IO} Either Failure ()
162. io2.IO.closeSocket.impl : Socket ->{IO} Either Failure ()
163. io2.IO.createDirectory.impl : Text
->{IO} Either Failure ()
161. io2.IO.createTempDirectory.impl : Text
164. io2.IO.createTempDirectory.impl : Text
->{IO} Either
Failure Text
162. io2.IO.delay.impl : Nat ->{IO} Either Failure ()
163. io2.IO.directoryContents.impl : Text
165. io2.IO.delay.impl : Nat ->{IO} Either Failure ()
166. io2.IO.directoryContents.impl : Text
->{IO} Either
Failure [Text]
164. io2.IO.fileExists.impl : Text
167. io2.IO.fileExists.impl : Text
->{IO} Either Failure Boolean
165. io2.IO.forkComp : '{IO} a ->{IO} ThreadId
166. io2.IO.getBuffering.impl : Handle
168. io2.IO.forkComp : '{IO} a ->{IO} ThreadId
169. io2.IO.getBuffering.impl : Handle
->{IO} Either
Failure BufferMode
167. io2.IO.getBytes.impl : Handle
170. io2.IO.getBytes.impl : Handle
-> Nat
->{IO} Either Failure Bytes
168. io2.IO.getCurrentDirectory.impl : '{IO} Either
171. io2.IO.getCurrentDirectory.impl : '{IO} Either
Failure Text
169. io2.IO.getEnv.impl : Text ->{IO} Either Failure Text
170. io2.IO.getFileSize.impl : Text ->{IO} Either Failure Nat
171. io2.IO.getFileTimestamp.impl : Text
172. io2.IO.getEnv.impl : Text ->{IO} Either Failure Text
173. io2.IO.getFileSize.impl : Text ->{IO} Either Failure Nat
174. io2.IO.getFileTimestamp.impl : Text
->{IO} Either Failure Nat
172. io2.IO.getLine.impl : Handle ->{IO} Either Failure Text
173. io2.IO.getTempDirectory.impl : '{IO} Either Failure Text
174. io2.IO.handlePosition.impl : Handle
175. io2.IO.getLine.impl : Handle ->{IO} Either Failure Text
176. io2.IO.getTempDirectory.impl : '{IO} Either Failure Text
177. io2.IO.handlePosition.impl : Handle
->{IO} Either Failure Nat
175. io2.IO.isDirectory.impl : Text
178. io2.IO.isDirectory.impl : Text
->{IO} Either Failure Boolean
176. io2.IO.isFileEOF.impl : Handle
179. io2.IO.isFileEOF.impl : Handle
->{IO} Either Failure Boolean
177. io2.IO.isFileOpen.impl : Handle
180. io2.IO.isFileOpen.impl : Handle
->{IO} Either Failure Boolean
178. io2.IO.isSeekable.impl : Handle
181. io2.IO.isSeekable.impl : Handle
->{IO} Either Failure Boolean
179. io2.IO.kill.impl : ThreadId ->{IO} Either Failure ()
180. io2.IO.listen.impl : Socket ->{IO} Either Failure ()
181. io2.IO.openFile.impl : Text
182. io2.IO.kill.impl : ThreadId ->{IO} Either Failure ()
183. io2.IO.listen.impl : Socket ->{IO} Either Failure ()
184. io2.IO.openFile.impl : Text
-> FileMode
->{IO} Either Failure Handle
182. io2.IO.putBytes.impl : Handle
185. io2.IO.putBytes.impl : Handle
-> Bytes
->{IO} Either Failure ()
183. io2.IO.ref : a ->{IO} Ref {IO} a
184. io2.IO.removeDirectory.impl : Text
186. io2.IO.ref : a ->{IO} Ref {IO} a
187. io2.IO.removeDirectory.impl : Text
->{IO} Either Failure ()
185. io2.IO.removeFile.impl : Text ->{IO} Either Failure ()
186. io2.IO.renameDirectory.impl : Text
188. io2.IO.removeFile.impl : Text ->{IO} Either Failure ()
189. io2.IO.renameDirectory.impl : Text
-> Text
->{IO} Either Failure ()
187. io2.IO.renameFile.impl : Text
190. io2.IO.renameFile.impl : Text
-> Text
->{IO} Either Failure ()
188. io2.IO.seekHandle.impl : Handle
191. io2.IO.seekHandle.impl : Handle
-> SeekMode
-> Int
->{IO} Either Failure ()
189. io2.IO.serverSocket.impl : Optional Text
192. io2.IO.serverSocket.impl : Optional Text
-> Text
->{IO} Either Failure Socket
190. io2.IO.setBuffering.impl : Handle
193. io2.IO.setBuffering.impl : Handle
-> BufferMode
->{IO} Either Failure ()
191. io2.IO.setCurrentDirectory.impl : Text
194. io2.IO.setCurrentDirectory.impl : Text
->{IO} Either
Failure ()
192. io2.IO.socketAccept.impl : Socket
195. io2.IO.socketAccept.impl : Socket
->{IO} Either Failure Socket
193. io2.IO.socketPort.impl : Socket ->{IO} Either Failure Nat
194. io2.IO.socketReceive.impl : Socket
196. io2.IO.socketPort.impl : Socket ->{IO} Either Failure Nat
197. io2.IO.socketReceive.impl : Socket
-> Nat
->{IO} Either Failure Bytes
195. io2.IO.socketSend.impl : Socket
198. io2.IO.socketSend.impl : Socket
-> Bytes
->{IO} Either Failure ()
196. io2.IO.stdHandle : StdHandle -> Handle
197. io2.IO.systemTime.impl : '{IO} Either Failure Nat
198. unique type io2.IOError
199. io2.IOError.AlreadyExists : IOError
200. io2.IOError.EOF : IOError
201. io2.IOError.IllegalOperation : IOError
202. io2.IOError.NoSuchThing : IOError
203. io2.IOError.PermissionDenied : IOError
204. io2.IOError.ResourceBusy : IOError
205. io2.IOError.ResourceExhausted : IOError
206. io2.IOError.UserError : IOError
207. unique type io2.IOFailure
208. builtin type io2.MVar
209. io2.MVar.isEmpty : MVar a ->{IO} Boolean
210. io2.MVar.new : a ->{IO} MVar a
211. io2.MVar.newEmpty : '{IO} MVar a
212. io2.MVar.put.impl : MVar a -> a ->{IO} Either Failure ()
213. io2.MVar.read.impl : MVar a ->{IO} Either Failure a
214. io2.MVar.swap.impl : MVar a -> a ->{IO} Either Failure a
215. io2.MVar.take.impl : MVar a ->{IO} Either Failure a
216. io2.MVar.tryPut.impl : MVar a
199. io2.IO.stdHandle : StdHandle -> Handle
200. io2.IO.systemTime.impl : '{IO} Either Failure Nat
201. unique type io2.IOError
202. io2.IOError.AlreadyExists : IOError
203. io2.IOError.EOF : IOError
204. io2.IOError.IllegalOperation : IOError
205. io2.IOError.NoSuchThing : IOError
206. io2.IOError.PermissionDenied : IOError
207. io2.IOError.ResourceBusy : IOError
208. io2.IOError.ResourceExhausted : IOError
209. io2.IOError.UserError : IOError
210. unique type io2.IOFailure
211. builtin type io2.MVar
212. io2.MVar.isEmpty : MVar a ->{IO} Boolean
213. io2.MVar.new : a ->{IO} MVar a
214. io2.MVar.newEmpty : '{IO} MVar a
215. io2.MVar.put.impl : MVar a -> a ->{IO} Either Failure ()
216. io2.MVar.read.impl : MVar a ->{IO} Either Failure a
217. io2.MVar.swap.impl : MVar a -> a ->{IO} Either Failure a
218. io2.MVar.take.impl : MVar a ->{IO} Either Failure a
219. io2.MVar.tryPut.impl : MVar a
-> a
->{IO} Either Failure Boolean
217. io2.MVar.tryRead.impl : MVar a
220. io2.MVar.tryRead.impl : MVar a
->{IO} Either
Failure (Optional a)
218. io2.MVar.tryTake : MVar a ->{IO} Optional a
219. unique type io2.SeekMode
220. io2.SeekMode.AbsoluteSeek : SeekMode
221. io2.SeekMode.RelativeSeek : SeekMode
222. io2.SeekMode.SeekFromEnd : SeekMode
223. builtin type io2.Socket
224. unique type io2.StdHandle
225. io2.StdHandle.StdErr : StdHandle
226. io2.StdHandle.StdIn : StdHandle
227. io2.StdHandle.StdOut : StdHandle
228. builtin type io2.STM
229. io2.STM.atomically : '{STM} a ->{IO} a
230. io2.STM.retry : '{STM} a
231. builtin type io2.ThreadId
232. builtin type io2.Tls
233. builtin type io2.Tls.Cipher
234. builtin type io2.Tls.ClientConfig
235. io2.Tls.ClientConfig.certificates.set : [SignedCert]
221. io2.MVar.tryTake : MVar a ->{IO} Optional a
222. unique type io2.SeekMode
223. io2.SeekMode.AbsoluteSeek : SeekMode
224. io2.SeekMode.RelativeSeek : SeekMode
225. io2.SeekMode.SeekFromEnd : SeekMode
226. builtin type io2.Socket
227. unique type io2.StdHandle
228. io2.StdHandle.StdErr : StdHandle
229. io2.StdHandle.StdIn : StdHandle
230. io2.StdHandle.StdOut : StdHandle
231. builtin type io2.STM
232. io2.STM.atomically : '{STM} a ->{IO} a
233. io2.STM.retry : '{STM} a
234. builtin type io2.ThreadId
235. builtin type io2.Tls
236. builtin type io2.Tls.Cipher
237. builtin type io2.Tls.ClientConfig
238. io2.Tls.ClientConfig.certificates.set : [SignedCert]
-> ClientConfig
-> ClientConfig
236. io2.TLS.ClientConfig.ciphers.set : [Cipher]
239. io2.TLS.ClientConfig.ciphers.set : [Cipher]
-> ClientConfig
-> ClientConfig
237. io2.Tls.ClientConfig.default : Text
240. io2.Tls.ClientConfig.default : Text
-> Bytes
-> ClientConfig
238. io2.Tls.ClientConfig.versions.set : [Version]
241. io2.Tls.ClientConfig.versions.set : [Version]
-> ClientConfig
-> ClientConfig
239. io2.Tls.decodeCert.impl : Bytes
242. io2.Tls.decodeCert.impl : Bytes
-> Either Failure SignedCert
240. io2.Tls.decodePrivateKey : Bytes -> [PrivateKey]
241. io2.Tls.encodeCert : SignedCert -> Bytes
242. io2.Tls.encodePrivateKey : PrivateKey -> Bytes
243. io2.Tls.handshake.impl : Tls ->{IO} Either Failure ()
244. io2.Tls.newClient.impl : ClientConfig
243. io2.Tls.decodePrivateKey : Bytes -> [PrivateKey]
244. io2.Tls.encodeCert : SignedCert -> Bytes
245. io2.Tls.encodePrivateKey : PrivateKey -> Bytes
246. io2.Tls.handshake.impl : Tls ->{IO} Either Failure ()
247. io2.Tls.newClient.impl : ClientConfig
-> Socket
->{IO} Either Failure Tls
245. io2.Tls.newServer.impl : ServerConfig
248. io2.Tls.newServer.impl : ServerConfig
-> Socket
->{IO} Either Failure Tls
246. builtin type io2.Tls.PrivateKey
247. io2.Tls.receive.impl : Tls ->{IO} Either Failure Bytes
248. io2.Tls.send.impl : Tls -> Bytes ->{IO} Either Failure ()
249. builtin type io2.Tls.ServerConfig
250. io2.Tls.ServerConfig.certificates.set : [SignedCert]
249. builtin type io2.Tls.PrivateKey
250. io2.Tls.receive.impl : Tls ->{IO} Either Failure Bytes
251. io2.Tls.send.impl : Tls -> Bytes ->{IO} Either Failure ()
252. builtin type io2.Tls.ServerConfig
253. io2.Tls.ServerConfig.certificates.set : [SignedCert]
-> ServerConfig
-> ServerConfig
251. io2.Tls.ServerConfig.ciphers.set : [Cipher]
254. io2.Tls.ServerConfig.ciphers.set : [Cipher]
-> ServerConfig
-> ServerConfig
252. io2.Tls.ServerConfig.default : [SignedCert]
255. io2.Tls.ServerConfig.default : [SignedCert]
-> PrivateKey
-> ServerConfig
253. io2.Tls.ServerConfig.versions.set : [Version]
256. io2.Tls.ServerConfig.versions.set : [Version]
-> ServerConfig
-> ServerConfig
254. builtin type io2.Tls.SignedCert
255. io2.Tls.terminate.impl : Tls ->{IO} Either Failure ()
256. builtin type io2.Tls.Version
257. unique type io2.TlsFailure
258. builtin type io2.TVar
259. io2.TVar.new : a ->{STM} TVar a
260. io2.TVar.newIO : a ->{IO} TVar a
261. io2.TVar.read : TVar a ->{STM} a
262. io2.TVar.readIO : TVar a ->{IO} a
263. io2.TVar.swap : TVar a -> a ->{STM} a
264. io2.TVar.write : TVar a -> a ->{STM} ()
265. unique type IsPropagated
266. IsPropagated.IsPropagated : IsPropagated
267. unique type IsTest
268. IsTest.IsTest : IsTest
269. unique type Link
270. builtin type Link.Term
271. Link.Term : Term -> Link
272. builtin type Link.Type
273. Link.Type : Type -> Link
274. builtin type List
275. List.++ : [a] -> [a] -> [a]
276. List.+: : a -> [a] -> [a]
277. List.:+ : [a] -> a -> [a]
278. List.at : Nat -> [a] -> Optional a
279. List.cons : a -> [a] -> [a]
280. List.drop : Nat -> [a] -> [a]
281. List.empty : [a]
282. List.size : [a] -> Nat
283. List.snoc : [a] -> a -> [a]
284. List.take : Nat -> [a] -> [a]
285. metadata.isPropagated : IsPropagated
286. metadata.isTest : IsTest
287. builtin type Nat
288. Nat.* : Nat -> Nat -> Nat
289. Nat.+ : Nat -> Nat -> Nat
290. Nat./ : Nat -> Nat -> Nat
291. Nat.and : Nat -> Nat -> Nat
292. Nat.complement : Nat -> Nat
293. Nat.drop : Nat -> Nat -> Nat
294. Nat.eq : Nat -> Nat -> Boolean
295. Nat.fromText : Text -> Optional Nat
296. Nat.gt : Nat -> Nat -> Boolean
297. Nat.gteq : Nat -> Nat -> Boolean
298. Nat.increment : Nat -> Nat
299. Nat.isEven : Nat -> Boolean
300. Nat.isOdd : Nat -> Boolean
301. Nat.leadingZeros : Nat -> Nat
302. Nat.lt : Nat -> Nat -> Boolean
303. Nat.lteq : Nat -> Nat -> Boolean
304. Nat.mod : Nat -> Nat -> Nat
305. Nat.or : Nat -> Nat -> Nat
306. Nat.popCount : Nat -> Nat
307. Nat.pow : Nat -> Nat -> Nat
308. Nat.shiftLeft : Nat -> Nat -> Nat
309. Nat.shiftRight : Nat -> Nat -> Nat
310. Nat.sub : Nat -> Nat -> Int
311. Nat.toFloat : Nat -> Float
312. Nat.toInt : Nat -> Int
313. Nat.toText : Nat -> Text
314. Nat.trailingZeros : Nat -> Nat
315. Nat.xor : Nat -> Nat -> Nat
316. structural type Optional a
317. Optional.None : Optional a
318. Optional.Some : a -> Optional a
319. builtin type Ref
320. Ref.read : Ref g a ->{g} a
321. Ref.write : Ref g a -> a ->{g} ()
322. builtin type Request
323. builtin type Scope
324. Scope.ref : a ->{Scope s} Ref {Scope s} a
325. Scope.run : (∀ s. '{g, Scope s} r) ->{g} r
326. structural type SeqView a b
327. SeqView.VElem : a -> b -> SeqView a b
328. SeqView.VEmpty : SeqView a b
329. unique type Test.Result
330. Test.Result.Fail : Text -> Result
331. Test.Result.Ok : Text -> Result
332. builtin type Text
333. Text.!= : Text -> Text -> Boolean
334. Text.++ : Text -> Text -> Text
335. Text.drop : Nat -> Text -> Text
336. Text.empty : Text
337. Text.eq : Text -> Text -> Boolean
338. Text.fromCharList : [Char] -> Text
339. Text.fromUtf8.impl : Bytes -> Either Failure Text
340. Text.gt : Text -> Text -> Boolean
341. Text.gteq : Text -> Text -> Boolean
342. Text.lt : Text -> Text -> Boolean
343. Text.lteq : Text -> Text -> Boolean
344. Text.repeat : Nat -> Text -> Text
345. Text.size : Text -> Nat
346. Text.take : Nat -> Text -> Text
347. Text.toCharList : Text -> [Char]
348. Text.toUtf8 : Text -> Bytes
349. Text.uncons : Text -> Optional (Char, Text)
350. Text.unsnoc : Text -> Optional (Text, Char)
351. todo : a -> b
352. structural type Tuple a b
353. Tuple.Cons : a -> b -> Tuple a b
354. structural type Unit
355. Unit.Unit : ()
356. Universal.< : a -> a -> Boolean
357. Universal.<= : a -> a -> Boolean
358. Universal.== : a -> a -> Boolean
359. Universal.> : a -> a -> Boolean
360. Universal.>= : a -> a -> Boolean
361. Universal.compare : a -> a -> Int
362. unsafe.coerceAbilities : (a ->{e1} b) -> a ->{e2} b
363. builtin type Value
364. Value.dependencies : Value -> [Term]
365. Value.deserialize : Bytes -> Either Text Value
366. Value.load : Value ->{IO} Either [Term] a
367. Value.serialize : Value -> Bytes
368. Value.value : a -> Value
257. builtin type io2.Tls.SignedCert
258. io2.Tls.terminate.impl : Tls ->{IO} Either Failure ()
259. builtin type io2.Tls.Version
260. unique type io2.TlsFailure
261. builtin type io2.TVar
262. io2.TVar.new : a ->{STM} TVar a
263. io2.TVar.newIO : a ->{IO} TVar a
264. io2.TVar.read : TVar a ->{STM} a
265. io2.TVar.readIO : TVar a ->{IO} a
266. io2.TVar.swap : TVar a -> a ->{STM} a
267. io2.TVar.write : TVar a -> a ->{STM} ()
268. unique type IsPropagated
269. IsPropagated.IsPropagated : IsPropagated
270. unique type IsTest
271. IsTest.IsTest : IsTest
272. unique type Link
273. builtin type Link.Term
274. Link.Term : Term -> Link
275. Link.Term.toText : Term -> Text
276. builtin type Link.Type
277. Link.Type : Type -> Link
278. builtin type List
279. List.++ : [a] -> [a] -> [a]
280. List.+: : a -> [a] -> [a]
281. List.:+ : [a] -> a -> [a]
282. List.at : Nat -> [a] -> Optional a
283. List.cons : a -> [a] -> [a]
284. List.drop : Nat -> [a] -> [a]
285. List.empty : [a]
286. List.size : [a] -> Nat
287. List.snoc : [a] -> a -> [a]
288. List.take : Nat -> [a] -> [a]
289. metadata.isPropagated : IsPropagated
290. metadata.isTest : IsTest
291. builtin type Nat
292. Nat.* : Nat -> Nat -> Nat
293. Nat.+ : Nat -> Nat -> Nat
294. Nat./ : Nat -> Nat -> Nat
295. Nat.and : Nat -> Nat -> Nat
296. Nat.complement : Nat -> Nat
297. Nat.drop : Nat -> Nat -> Nat
298. Nat.eq : Nat -> Nat -> Boolean
299. Nat.fromText : Text -> Optional Nat
300. Nat.gt : Nat -> Nat -> Boolean
301. Nat.gteq : Nat -> Nat -> Boolean
302. Nat.increment : Nat -> Nat
303. Nat.isEven : Nat -> Boolean
304. Nat.isOdd : Nat -> Boolean
305. Nat.leadingZeros : Nat -> Nat
306. Nat.lt : Nat -> Nat -> Boolean
307. Nat.lteq : Nat -> Nat -> Boolean
308. Nat.mod : Nat -> Nat -> Nat
309. Nat.or : Nat -> Nat -> Nat
310. Nat.popCount : Nat -> Nat
311. Nat.pow : Nat -> Nat -> Nat
312. Nat.shiftLeft : Nat -> Nat -> Nat
313. Nat.shiftRight : Nat -> Nat -> Nat
314. Nat.sub : Nat -> Nat -> Int
315. Nat.toFloat : Nat -> Float
316. Nat.toInt : Nat -> Int
317. Nat.toText : Nat -> Text
318. Nat.trailingZeros : Nat -> Nat
319. Nat.xor : Nat -> Nat -> Nat
320. structural type Optional a
321. Optional.None : Optional a
322. Optional.Some : a -> Optional a
323. builtin type Ref
324. Ref.read : Ref g a ->{g} a
325. Ref.write : Ref g a -> a ->{g} ()
326. builtin type Request
327. builtin type Scope
328. Scope.ref : a ->{Scope s} Ref {Scope s} a
329. Scope.run : (∀ s. '{g, Scope s} r) ->{g} r
330. structural type SeqView a b
331. SeqView.VElem : a -> b -> SeqView a b
332. SeqView.VEmpty : SeqView a b
333. unique type Test.Result
334. Test.Result.Fail : Text -> Result
335. Test.Result.Ok : Text -> Result
336. builtin type Text
337. Text.!= : Text -> Text -> Boolean
338. Text.++ : Text -> Text -> Text
339. Text.drop : Nat -> Text -> Text
340. Text.empty : Text
341. Text.eq : Text -> Text -> Boolean
342. Text.fromCharList : [Char] -> Text
343. Text.fromUtf8.impl : Bytes -> Either Failure Text
344. Text.gt : Text -> Text -> Boolean
345. Text.gteq : Text -> Text -> Boolean
346. Text.lt : Text -> Text -> Boolean
347. Text.lteq : Text -> Text -> Boolean
348. Text.repeat : Nat -> Text -> Text
349. Text.size : Text -> Nat
350. Text.take : Nat -> Text -> Text
351. Text.toCharList : Text -> [Char]
352. Text.toUtf8 : Text -> Bytes
353. Text.uncons : Text -> Optional (Char, Text)
354. Text.unsnoc : Text -> Optional (Text, Char)
355. todo : a -> b
356. structural type Tuple a b
357. Tuple.Cons : a -> b -> Tuple a b
358. structural type Unit
359. Unit.Unit : ()
360. Universal.< : a -> a -> Boolean
361. Universal.<= : a -> a -> Boolean
362. Universal.== : a -> a -> Boolean
363. Universal.> : a -> a -> Boolean
364. Universal.>= : a -> a -> Boolean
365. Universal.compare : a -> a -> Int
366. unsafe.coerceAbilities : (a ->{e1} b) -> a ->{e2} b
367. builtin type Value
368. Value.dependencies : Value -> [Term]
369. Value.deserialize : Bytes -> Either Text Value
370. Value.load : Value ->{IO} Either [Term] a
371. Value.serialize : Value -> Bytes
372. Value.value : a -> Value
.builtin> alias.many 94-104 .mylib
@ -464,17 +468,17 @@ Let's try it!
Added definitions:
1. Float.gteq : Float -> Float -> Boolean
2. Float.log : Float -> Float
3. Float.logBase : Float -> Float -> Float
4. Float.lt : Float -> Float -> Boolean
5. Float.lteq : Float -> Float -> Boolean
6. Float.max : Float -> Float -> Float
7. Float.min : Float -> Float -> Float
8. Float.pow : Float -> Float -> Float
9. Float.round : Float -> Int
10. Float.sin : Float -> Float
11. Float.sinh : Float -> Float
1. Float.fromRepresentation : Nat -> Float
2. Float.fromText : Text -> Optional Float
3. Float.gt : Float -> Float -> Boolean
4. Float.gteq : Float -> Float -> Boolean
5. Float.log : Float -> Float
6. Float.logBase : Float -> Float -> Float
7. Float.lt : Float -> Float -> Boolean
8. Float.lteq : Float -> Float -> Boolean
9. Float.max : Float -> Float -> Float
10. Float.min : Float -> Float -> Float
11. Float.pow : Float -> Float -> Float
Tip: You can use `undo` or `reflog` to undo this change.
@ -534,17 +538,17 @@ I want to incorporate a few more from another namespace:
.mylib> find
1. Float.gteq : Float -> Float -> Boolean
2. Float.log : Float -> Float
3. Float.logBase : Float -> Float -> Float
4. Float.lt : Float -> Float -> Boolean
5. Float.lteq : Float -> Float -> Boolean
6. Float.max : Float -> Float -> Float
7. Float.min : Float -> Float -> Float
8. Float.pow : Float -> Float -> Float
9. Float.round : Float -> Int
10. Float.sin : Float -> Float
11. Float.sinh : Float -> Float
1. Float.fromRepresentation : Nat -> Float
2. Float.fromText : Text -> Optional Float
3. Float.gt : Float -> Float -> Boolean
4. Float.gteq : Float -> Float -> Boolean
5. Float.log : Float -> Float
6. Float.logBase : Float -> Float -> Float
7. Float.lt : Float -> Float -> Boolean
8. Float.lteq : Float -> Float -> Boolean
9. Float.max : Float -> Float -> Float
10. Float.min : Float -> Float -> Float
11. Float.pow : Float -> Float -> Float
12. List.adjacentPairs : [a] -> [(a, a)]
13. List.all : (a ->{g} Boolean) -> [a] ->{g} Boolean
14. List.any : (a ->{g} Boolean) -> [a] ->{g} Boolean

View File

@ -0,0 +1,25 @@
# Unit tests for Any.unsafeExtract
```ucm:hide
.> builtins.merge
.> cd builtin
.> load unison-src/transcripts-using-base/base.u
.> add
```
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
test> Any.unsafeExtract.works =
use Nat !=
checks [1 == Any.unsafeExtract (Any 1),
not (1 == Any.unsafeExtract (Any 2)),
(Some 1) == Any.unsafeExtract (Any (Some 1))
]
```
```ucm
.> add
```

View File

@ -0,0 +1,39 @@
# Unit tests for Any.unsafeExtract
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
test> Any.unsafeExtract.works =
use Nat !=
checks [1 == Any.unsafeExtract (Any 1),
not (1 == Any.unsafeExtract (Any 2)),
(Some 1) == Any.unsafeExtract (Any (Some 1))
]
```
```ucm
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`:
Any.unsafeExtract.works : [Result]
Now evaluating any watch expressions (lines starting with
`>`)... Ctrl+C cancels.
3 | checks [1 == Any.unsafeExtract (Any 1),
✅ Passed Passed
```
```ucm
.> add
⍟ I've added these definitions:
Any.unsafeExtract.works : [Result]
```

View File

@ -2077,10 +2077,9 @@ rendered = Pretty.get (docFormatConsole doc.guide)
(Term.Term
(Any
'(f x ->
f
x
Nat.+ sqr
1))))),
f x
Nat.+ sqr
1))))),
!Lit
(Right
(Plain "-")),

View File

@ -10,7 +10,7 @@ The `builtins.merge` command adds the known builtins to a `builtin` subnamespace
.tmp> ls builtin
1. Any (builtin type)
2. Any/ (1 definition)
2. Any/ (2 definitions)
3. Boolean (builtin type)
4. Boolean/ (1 definition)
5. Bytes (builtin type)
@ -18,7 +18,7 @@ The `builtins.merge` command adds the known builtins to a `builtin` subnamespace
7. Char (builtin type)
8. Char/ (3 definitions)
9. Code (builtin type)
10. Code/ (6 definitions)
10. Code/ (8 definitions)
11. Debug/ (1 definition)
12. Doc (type)
13. Doc/ (6 definitions)
@ -35,7 +35,7 @@ The `builtins.merge` command adds the known builtins to a `builtin` subnamespace
24. IsTest (type)
25. IsTest/ (1 definition)
26. Link (type)
27. Link/ (4 definitions)
27. Link/ (5 definitions)
28. List (builtin type)
29. List/ (10 definitions)
30. Nat (builtin type)

View File

@ -23,7 +23,7 @@ Technically, the definitions all exist, but they have no names. `builtins.merge`
.foo> ls
1. builtin/ (368 definitions)
1. builtin/ (372 definitions)
```
And for a limited time, you can get even more builtin goodies:
@ -35,7 +35,7 @@ And for a limited time, you can get even more builtin goodies:
.foo> ls
1. builtin/ (536 definitions)
1. builtin/ (540 definitions)
```
More typically, you'd start out by pulling `base.

View File

@ -0,0 +1,66 @@
Tests that `if` statements can appear as list and tuple elements.
```ucm:hide
.> builtins.merge
```
```unison:hide
> [ if true then 1 else 0 ]
> [ if true then 1 else 0, 1]
> [1, if true then 1 else 0]
> (if true then 1 else 0, 0)
> (0, if true then 1 else 0)
> (1)
> (1,2)
> (1,2,3)
> [1,2,3]
> []
> [1]
> [1,2]
> [1,2,3]
> [
1,
2,
3
]
> [
1,
2,
3,]
> (1,2,3,)
> (1,
2,)
structural ability Zoot where zoot : ()
Zoot.handler : Request {Zoot} a -> a
Zoot.handler = cases
{ a } -> a
{ zoot -> k } -> handle !k with Zoot.handler
fst = cases (x,_) -> x
> List.size
[ if true then (x y -> y)
else handle (x y -> x) with fst (Zoot.handler, 42),
cases a, b -> a Nat.+ b, -- multi-arg cases lambda
cases x, y -> x Nat.+ y
]
```

View File

@ -0,0 +1,62 @@
Tests that `if` statements can appear as list and tuple elements.
```unison
> [ if true then 1 else 0 ]
> [ if true then 1 else 0, 1]
> [1, if true then 1 else 0]
> (if true then 1 else 0, 0)
> (0, if true then 1 else 0)
> (1)
> (1,2)
> (1,2,3)
> [1,2,3]
> []
> [1]
> [1,2]
> [1,2,3]
> [
1,
2,
3
]
> [
1,
2,
3,]
> (1,2,3,)
> (1,
2,)
structural ability Zoot where zoot : ()
Zoot.handler : Request {Zoot} a -> a
Zoot.handler = cases
{ a } -> a
{ zoot -> k } -> handle !k with Zoot.handler
fst = cases (x,_) -> x
> List.size
[ if true then (x y -> y)
else handle (x y -> x) with fst (Zoot.handler, 42),
cases a, b -> a Nat.+ b, -- multi-arg cases lambda
cases x, y -> x Nat.+ y
]
```

View File

@ -112,13 +112,13 @@ We can also delete the fork if we're done with it. (Don't worry, it's still in t
Note: The most recent namespace hash is immediately below this
message.
#nl3sdb3eid
#8bi2fepmci
- Deletes:
feature1.y
#nt4hpgmam9
#0toe0ni06d
+ Adds / updates:
@ -129,26 +129,26 @@ We can also delete the fork if we're done with it. (Don't worry, it's still in t
Original name New name(s)
feature1.y master.y
#hjtrj2kgl4
#8hp71hs6bk
+ Adds / updates:
feature1.y
#04vktkvglu
#lujhuhd7it
> Moves:
Original name New name
x master.x
#0g638hmb59
#hl2puv6t7v
+ Adds / updates:
x
#2f9h2uhlk9 (start of history)
#rmafm3f1ih (start of history)
```
To resurrect an old version of a namespace, you can learn its hash via the `history` command, then use `fork #namespacehash .newname`.

View File

@ -0,0 +1,70 @@
Ensure that Records keep their syntax after being added to the codebase
```ucm:hide
.> builtins.mergeio
.> load unison-src/transcripts-using-base/base.u
```
## Record with 1 field
```unison:hide
unique type Record1 = { a : Text }
```
```ucm:hide
.> add
```
```ucm
.> view Record1
```
## Record with 2 fields
```unison:hide
unique type Record2 = { a : Text, b : Int }
```
```ucm:hide
.> add
```
```ucm
.> view Record2
```
## Record with 3 fields
```unison:hide
unique type Record3 = { a : Text, b : Int, c : Nat }
```
```ucm:hide
.> add
```
```ucm
.> view Record3
```
## Record with many fields
```unison:hide
unique type Record4 =
{ a : Text
, b : Int
, c : Nat
, d : Bytes
, e : Text
, f : Nat
, g : [Nat]
}
```
```ucm:hide
.> add
```
```ucm
.> view Record4
```

View File

@ -0,0 +1,65 @@
Ensure that Records keep their syntax after being added to the codebase
## Record with 1 field
```unison
unique type Record1 = { a : Text }
```
```ucm
.> view Record1
unique type Record1 = { a : Text }
```
## Record with 2 fields
```unison
unique type Record2 = { a : Text, b : Int }
```
```ucm
.> view Record2
unique type Record2 = { a : Text, b : Int }
```
## Record with 3 fields
```unison
unique type Record3 = { a : Text, b : Int, c : Nat }
```
```ucm
.> view Record3
unique type Record3 = { a : Text, b : Int, c : Nat }
```
## Record with many fields
```unison
unique type Record4 =
{ a : Text
, b : Int
, c : Nat
, d : Bytes
, e : Text
, f : Nat
, g : [Nat]
}
```
```ucm
.> view Record4
unique type Record4
= { a : Text,
b : Int,
c : Nat,
d : Bytes,
e : Text,
f : Nat,
g : [Nat] }
```

View File

@ -59,16 +59,16 @@ y = 2
most recent, along with the command that got us there. Try:
`fork 2 .old`
`fork #3n9h2vkhe3 .old` to make an old namespace
`fork #12c7nag7oi .old` to make an old namespace
accessible again,
`reset-root #3n9h2vkhe3` to reset the root namespace and
`reset-root #12c7nag7oi` to reset the root namespace and
its history to that of the
specified namespace.
1. #vfl0sjr6kg : add
2. #3n9h2vkhe3 : add
3. #2f9h2uhlk9 : builtins.merge
1. #sjer10g2l4 : add
2. #12c7nag7oi : add
3. #rmafm3f1ih : builtins.merge
4. #sjg2v58vn2 : (initial reflogged namespace)
```

View File

@ -13,7 +13,7 @@ Let's look at some examples. We'll start with a namespace with just the builtins
#fhun4m3q9g (start of history)
#7ogvf7kc1m (start of history)
.> fork builtin builtin2
@ -42,21 +42,21 @@ Now suppose we `fork` a copy of builtin, then rename `Nat.+` to `frobnicate`, th
Note: The most recent namespace hash is immediately below this
message.
#565pe56252
#b4nitt6goc
> Moves:
Original name New name
Nat.frobnicate Nat.+
#oavs87p39a
#s92i00andp
> Moves:
Original name New name
Nat.+ Nat.frobnicate
#fhun4m3q9g (start of history)
#7ogvf7kc1m (start of history)
```
If we merge that back into `builtin`, we get that same chain of history:
@ -71,21 +71,21 @@ If we merge that back into `builtin`, we get that same chain of history:
Note: The most recent namespace hash is immediately below this
message.
#565pe56252
#b4nitt6goc
> Moves:
Original name New name
Nat.frobnicate Nat.+
#oavs87p39a
#s92i00andp
> Moves:
Original name New name
Nat.+ Nat.frobnicate
#fhun4m3q9g (start of history)
#7ogvf7kc1m (start of history)
```
Let's try again, but using a `merge.squash` (or just `squash`) instead. The history will be unchanged:
@ -106,7 +106,7 @@ Let's try again, but using a `merge.squash` (or just `squash`) instead. The hist
#fhun4m3q9g (start of history)
#7ogvf7kc1m (start of history)
```
The churn that happened in `mybuiltin` namespace ended up back in the same spot, so the squash merge of that namespace with our original namespace had no effect.
@ -485,13 +485,13 @@ This checks to see that squashing correctly preserves deletions:
Note: The most recent namespace hash is immediately below this
message.
#jqps95msh5
#ct8sk813ij
- Deletes:
Nat.* Nat.+
#fhun4m3q9g (start of history)
#7ogvf7kc1m (start of history)
```
Notice that `Nat.+` and `Nat.*` are deleted by the squash, and we see them deleted in one atomic step in the history.