diff --git a/lib/unison-prelude/src/Unison/Util/Map.hs b/lib/unison-prelude/src/Unison/Util/Map.hs index d667e5300..fe54b14a7 100644 --- a/lib/unison-prelude/src/Unison/Util/Map.hs +++ b/lib/unison-prelude/src/Unison/Util/Map.hs @@ -2,6 +2,7 @@ module Unison.Util.Map ( bimap, bitraverse, + deleteLookup, foldMapM, unionWithM, ) @@ -20,6 +21,11 @@ bimap fa fb = Map.fromList . map (B.bimap fa fb) . Map.toList bitraverse :: (Applicative f, Ord a') => (a -> f a') -> (b -> f b') -> Map a b -> f (Map a' b') bitraverse fa fb = fmap Map.fromList . traverse (B.bitraverse fa fb) . Map.toList +-- | Like 'Map.delete', but returns the value as well. +deleteLookup :: Ord k => k -> Map k v -> (Maybe v, Map k v) +deleteLookup = + Map.alterF (,Nothing) + -- | Construct a map from a foldable container by mapping each element to monadic action that returns a key and a value. -- -- The map is constructed from the left: if two elements map to the same key, the second will overwrite the first. diff --git a/lib/unison-sqlite/package.yaml b/lib/unison-sqlite/package.yaml index 53631e186..cfd4f2e5a 100644 --- a/lib/unison-sqlite/package.yaml +++ b/lib/unison-sqlite/package.yaml @@ -45,6 +45,7 @@ default-extensions: - NamedFieldPuns - NumericUnderscores - OverloadedStrings + - PatternSynonyms - ScopedTypeVariables - TupleSections - TypeApplications diff --git a/lib/unison-sqlite/src/Unison/Sqlite/Exception.hs b/lib/unison-sqlite/src/Unison/Sqlite/Exception.hs index 598fcd495..9d7106094 100644 --- a/lib/unison-sqlite/src/Unison/Sqlite/Exception.hs +++ b/lib/unison-sqlite/src/Unison/Sqlite/Exception.hs @@ -9,6 +9,8 @@ module Unison.Sqlite.Exception -- ** @SqliteQueryException@ SqliteQueryException (..), + pattern SqliteBusyException, + isSqliteBusyException, SqliteQueryExceptionInfo (..), throwSqliteQueryException, SomeSqliteExceptionReason (..), @@ -74,7 +76,7 @@ rethrowAsSqliteConnectException name file exception = do ------------------------------------------------------------------------------------------------------------------------ -- SomeSqliteException --- └── SqliteConnectException +-- └── SqliteQueryException -- | A @SqliteQueryException@ represents an exception thrown during processing a query, paired with some context that -- resulted in the exception. @@ -101,6 +103,15 @@ instance Exception SqliteQueryException where toException = toException . SomeSqliteException fromException = fromException >=> \(SomeSqliteException e) -> cast e +pattern SqliteBusyException :: SqliteQueryException +pattern SqliteBusyException <- (isSqliteBusyException -> True) + +isSqliteBusyException :: SqliteQueryException -> Bool +isSqliteBusyException SqliteQueryException {exception = SomeSqliteExceptionReason reason} = + case cast reason of + Just (Sqlite.SQLError Sqlite.ErrorBusy _ _) -> True + _ -> False + data SqliteQueryExceptionInfo params connection = SqliteQueryExceptionInfo { connection :: connection, sql :: Sql, diff --git a/lib/unison-sqlite/src/Unison/Sqlite/JournalMode.hs b/lib/unison-sqlite/src/Unison/Sqlite/JournalMode.hs index 5d5a9c769..cc0e6aeed 100644 --- a/lib/unison-sqlite/src/Unison/Sqlite/JournalMode.hs +++ b/lib/unison-sqlite/src/Unison/Sqlite/JournalMode.hs @@ -24,12 +24,12 @@ data JournalMode journalModeFromText :: Text -> Maybe JournalMode journalModeFromText = \case - "DELETE" -> Just JournalMode'DELETE - "TRUNCATE" -> Just JournalMode'TRUNCATE - "PERSIST" -> Just JournalMode'PERSIST - "MEMORY" -> Just JournalMode'MEMORY - "WAL" -> Just JournalMode'WAL - "OFF" -> Just JournalMode'OFF + "delete" -> Just JournalMode'DELETE + "truncate" -> Just JournalMode'TRUNCATE + "persist" -> Just JournalMode'PERSIST + "memory" -> Just JournalMode'MEMORY + "wal" -> Just JournalMode'WAL + "off" -> Just JournalMode'OFF _ -> Nothing unsafeJournalModeFromText :: HasCallStack => Text -> JournalMode @@ -38,12 +38,12 @@ unsafeJournalModeFromText s = journalModeToText :: JournalMode -> Text journalModeToText = \case - JournalMode'DELETE -> "DELETE" - JournalMode'TRUNCATE -> "TRUNCATE" - JournalMode'PERSIST -> "PERSIST" - JournalMode'MEMORY -> "MEMORY" - JournalMode'WAL -> "WAL" - JournalMode'OFF -> "OFF" + JournalMode'DELETE -> "delete" + JournalMode'TRUNCATE -> "truncate" + JournalMode'PERSIST -> "persist" + JournalMode'MEMORY -> "memory" + JournalMode'WAL -> "wal" + JournalMode'OFF -> "off" trySetJournalMode :: JournalMode -> Transaction () trySetJournalMode mode0 = do diff --git a/lib/unison-sqlite/src/Unison/Sqlite/Transaction.hs b/lib/unison-sqlite/src/Unison/Sqlite/Transaction.hs index af8123599..66a47cb66 100644 --- a/lib/unison-sqlite/src/Unison/Sqlite/Transaction.hs +++ b/lib/unison-sqlite/src/Unison/Sqlite/Transaction.hs @@ -50,14 +50,17 @@ module Unison.Sqlite.Transaction ) where +import Control.Concurrent (threadDelay) +import Control.Exception (Exception (fromException), onException, throwIO) import Control.Monad.Trans.Reader (ReaderT (..)) import qualified Database.SQLite.Simple as Sqlite import qualified Database.SQLite.Simple.FromField as Sqlite -import Unison.Prelude +import Unison.Prelude hiding (try) import Unison.Sqlite.Connection (Connection (..)) import qualified Unison.Sqlite.Connection as Connection -import Unison.Sqlite.Exception (SqliteExceptionReason) +import Unison.Sqlite.Exception (SqliteExceptionReason, SqliteQueryException, pattern SqliteBusyException) import Unison.Sqlite.Sql +import UnliftIO.Exception (catchAny, try, trySyncOrAsync, uninterruptibleMask) newtype Transaction a = Transaction (Connection -> IO a) @@ -67,13 +70,35 @@ newtype Transaction a -- | Run a transaction on the given connection. runTransaction :: MonadIO m => Connection -> Transaction a -> m a -runTransaction conn@(Connection _ _ conn0) (Transaction f) = - -- TODO some sensible retry logic - liftIO do - Sqlite.execute_ conn0 "BEGIN" - result <- f conn - Sqlite.execute_ conn0 "COMMIT" +runTransaction conn (Transaction f) = liftIO do + uninterruptibleMask \restore -> do + Connection.execute_ conn "BEGIN" + result <- + -- Catch all exceptions (sync or async), because we want to ROLLBACK the BEGIN no matter what. + trySyncOrAsync @_ @SomeException (restore (f conn)) >>= \case + Left exception -> do + ignoringExceptions rollback + case fromException exception of + Just SqliteBusyException -> + let loop microseconds = do + restore (threadDelay microseconds) + try @_ @SqliteQueryException (Connection.execute_ conn "BEGIN IMMEDIATE") >>= \case + Left SqliteBusyException -> loop (microseconds * 2) + Left exception -> throwIO exception + Right () -> restore (f conn) `onException` ignoringExceptions rollback + in loop 100_000 + _ -> throwIO exception + Right result -> pure result + Connection.execute_ conn "COMMIT" pure result + where + rollback :: IO () + rollback = + Connection.execute_ conn "ROLLBACK" + + ignoringExceptions :: IO () -> IO () + ignoringExceptions action = + action `catchAny` \_ -> pure () -- Without results, with parameters diff --git a/lib/unison-sqlite/unison-sqlite.cabal b/lib/unison-sqlite/unison-sqlite.cabal index 723bd4864..159ea91d8 100644 --- a/lib/unison-sqlite/unison-sqlite.cabal +++ b/lib/unison-sqlite/unison-sqlite.cabal @@ -47,6 +47,7 @@ library NamedFieldPuns NumericUnderscores OverloadedStrings + PatternSynonyms ScopedTypeVariables TupleSections TypeApplications diff --git a/lib/unison-util-relation/benchmarks/relation/Main.hs b/lib/unison-util-relation/benchmarks/relation/Main.hs index 80406124a..8aa7e709d 100644 --- a/lib/unison-util-relation/benchmarks/relation/Main.hs +++ b/lib/unison-util-relation/benchmarks/relation/Main.hs @@ -18,6 +18,12 @@ main = bench "intersection" $ nf (uncurry R.intersection) rs, bench "union" $ nf (uncurry R.union) rs ], + env (pure (R.fromList ((,) <$> [(1 :: Int) .. 1000] <*> [(1 :: Int) .. 1000]))) \r -> + bgroup + "replaceDom" + [ bench "old implementation" (nf (oldReplaceDom 1 2) r), + bench "new implementation" (nf (R.replaceDom 2 2) r) + ], env (genRelation @Char @Char 10000 2) \r -> env (genSet @Char 100) \s -> bgroup @@ -30,6 +36,10 @@ main = ] ] +oldReplaceDom :: (Ord a, Ord b) => a -> a -> Relation a b -> Relation a b +oldReplaceDom a a' r = + foldl' (\r b -> R.insert a' b $ R.delete a b r) r (R.lookupDom a r) + oldSubtractDom :: (Ord a, Ord b) => Set a -> Relation a b -> Relation a b oldSubtractDom s r = R.fromList [(a, b) | (a, b) <- R.toList r, not (a `Set.member` s)] diff --git a/lib/unison-util-relation/src/Unison/Util/Relation.hs b/lib/unison-util-relation/src/Unison/Util/Relation.hs index 18f005c0a..eb0ec20c5 100644 --- a/lib/unison-util-relation/src/Unison/Util/Relation.hs +++ b/lib/unison-util-relation/src/Unison/Util/Relation.hs @@ -114,7 +114,9 @@ import qualified Data.Map as Map import qualified Data.Map.Internal as Map import Data.Ord (comparing) import qualified Data.Set as S +import qualified Data.Set as Set import Unison.Prelude hiding (empty, toList) +import qualified Unison.Util.Map as Map import qualified Unison.Util.Set as Set import Prelude hiding (filter, map, null) @@ -602,13 +604,31 @@ searchDom f r = go (domain r) searchRan :: (Ord a, Ord b) => (b -> Ordering) -> Relation a b -> Set a searchRan f r = searchDom f (swap r) +-- | @replaceDom x y r@ replaces all @(x, _)@ with @(y, _)@ in @r@. replaceDom :: (Ord a, Ord b) => a -> a -> Relation a b -> Relation a b replaceDom a a' r = - foldl' (\r b -> insert a' b $ delete a b r) r (lookupDom a r) + if a == a' + then r + else case Map.deleteLookup a (domain r) of + (Nothing, _) -> r + (Just bs, domain') -> + Relation + { domain = Map.insertWith Set.union a' bs domain', + range = foldl' (\acc b -> Map.adjust (Set.insert a' . Set.delete a) b acc) (range r) bs + } +-- | @replaceRan x y r@ replaces all @(_, x)@ with @(_, y)@ in @r@. replaceRan :: (Ord a, Ord b) => b -> b -> Relation a b -> Relation a b replaceRan b b' r = - foldl' (\r a -> insert a b' $ delete a b r) r (lookupRan b r) + if b == b' + then r + else case Map.deleteLookup b (range r) of + (Nothing, _) -> r + (Just as, range') -> + Relation + { domain = foldl' (\acc a -> Map.adjust (Set.insert b' . Set.delete b) a acc) (domain r) as, + range = Map.insertWith Set.union b' as range' + } updateDom :: (Ord a, Ord b) => (a -> a) -> b -> Relation a b -> Relation a b updateDom f b r = diff --git a/lib/unison-util-relation/src/Unison/Util/Relation3.hs b/lib/unison-util-relation/src/Unison/Util/Relation3.hs index 711709173..13528bdc4 100644 --- a/lib/unison-util-relation/src/Unison/Util/Relation3.hs +++ b/lib/unison-util-relation/src/Unison/Util/Relation3.hs @@ -128,6 +128,9 @@ fromList xs = insertAll xs empty empty :: (Ord a, Ord b, Ord c) => Relation3 a b c empty = mempty +null :: Relation3 a b c -> Bool +null r = Map.null $ d1 r + insert, delete :: (Ord a, Ord b, Ord c) => a -> b -> c -> Relation3 a b c -> Relation3 a b c diff --git a/lib/unison-util-relation/src/Unison/Util/Relation4.hs b/lib/unison-util-relation/src/Unison/Util/Relation4.hs index b664361b0..70c657a9f 100644 --- a/lib/unison-util-relation/src/Unison/Util/Relation4.hs +++ b/lib/unison-util-relation/src/Unison/Util/Relation4.hs @@ -47,6 +47,9 @@ toList = fmap (\(a,(b,(c,d))) -> (a,b,c,d)) . toNestedList empty :: (Ord a, Ord b, Ord c, Ord d) => Relation4 a b c d empty = mempty +null :: Relation4 a b c d -> Bool +null r = Map.null $ d1 r + fromList :: (Ord a, Ord b, Ord c, Ord d) => [(a,b,c,d)] -> Relation4 a b c d fromList xs = insertAll xs empty diff --git a/parser-typechecker/src/Unison/Builtin.hs b/parser-typechecker/src/Unison/Builtin.hs index df469064f..e6d8e2f77 100644 --- a/parser-typechecker/src/Unison/Builtin.hs +++ b/parser-typechecker/src/Unison/Builtin.hs @@ -476,6 +476,7 @@ builtinsSrc = , B "ThreadId.toText" $ threadId --> text , B "Debug.watch" $ forall1 "a" (\a -> text --> a --> a) + , B "Debug.trace" $ forall1 "a" (\a -> text --> a --> unit) , B "unsafe.coerceAbilities" $ forall4 "a" "b" "e1" "e2" $ \a b e1 e2 -> (a --> Type.effect1 () e1 b) --> (a --> Type.effect1 () e2 b) diff --git a/parser-typechecker/src/Unison/Codebase/Branch.hs b/parser-typechecker/src/Unison/Codebase/Branch.hs index ed1cc9a92..090fbdd41 100644 --- a/parser-typechecker/src/Unison/Codebase/Branch.hs +++ b/parser-typechecker/src/Unison/Codebase/Branch.hs @@ -39,6 +39,7 @@ module Unison.Codebase.Branch , head , headHash , children + , nonEmptyChildren , deepEdits' , toList0 -- * step @@ -118,6 +119,7 @@ import qualified Unison.Util.Star3 as Star3 import qualified Unison.Util.List as List import qualified Data.Semialign as Align import Data.These (These(..)) +import qualified Unison.Util.Relation as Relation -- | A node in the Unison namespace hierarchy -- along with its history. @@ -228,6 +230,12 @@ types = children :: Lens' (Branch0 m) (Map NameSegment (Branch m)) children = lens _children (\Branch0{..} x -> branch0 _terms _types x _edits) +nonEmptyChildren :: Branch0 m -> Map NameSegment (Branch m) +nonEmptyChildren b = + b + & _children + & Map.filter (not . isEmpty0 . head) + -- creates a Branch0 from the primary fields and derives the others. branch0 :: forall m. @@ -260,7 +268,7 @@ branch0 terms types children edits = -- | Derive the 'deepTerms' field of a branch. deriveDeepTerms :: Branch0 m -> Branch0 m deriveDeepTerms branch = - branch {deepTerms = makeDeepTerms (_terms branch) (_children branch)} + branch {deepTerms = makeDeepTerms (_terms branch) (nonEmptyChildren branch)} where makeDeepTerms :: Metadata.Star Referent NameSegment -> Map NameSegment (Branch m) -> Relation Referent Name makeDeepTerms terms children = @@ -273,7 +281,7 @@ deriveDeepTerms branch = -- | Derive the 'deepTypes' field of a branch. deriveDeepTypes :: Branch0 m -> Branch0 m deriveDeepTypes branch = - branch {deepTypes = makeDeepTypes (_types branch) (_children branch)} + branch {deepTypes = makeDeepTypes (_types branch) (nonEmptyChildren branch)} where makeDeepTypes :: Metadata.Star TypeReference NameSegment -> Map NameSegment (Branch m) -> Relation TypeReference Name makeDeepTypes types children = @@ -286,7 +294,7 @@ deriveDeepTypes branch = -- | Derive the 'deepTermMetadata' field of a branch. deriveDeepTermMetadata :: Branch0 m -> Branch0 m deriveDeepTermMetadata branch = - branch {deepTermMetadata = makeDeepTermMetadata (_terms branch) (_children branch)} + branch {deepTermMetadata = makeDeepTermMetadata (_terms branch) (nonEmptyChildren branch)} where makeDeepTermMetadata :: Metadata.Star Referent NameSegment -> Map NameSegment (Branch m) -> Metadata.R4 Referent Name makeDeepTermMetadata terms children = @@ -299,7 +307,7 @@ deriveDeepTermMetadata branch = -- | Derive the 'deepTypeMetadata' field of a branch. deriveDeepTypeMetadata :: Branch0 m -> Branch0 m deriveDeepTypeMetadata branch = - branch {deepTypeMetadata = makeDeepTypeMetadata (_types branch) (_children branch)} + branch {deepTypeMetadata = makeDeepTypeMetadata (_types branch) (nonEmptyChildren branch)} where makeDeepTypeMetadata :: Metadata.Star TypeReference NameSegment -> Map NameSegment (Branch m) -> Metadata.R4 TypeReference Name makeDeepTypeMetadata types children = @@ -312,7 +320,7 @@ deriveDeepTypeMetadata branch = -- | Derive the 'deepPaths' field of a branch. deriveDeepPaths :: Branch0 m -> Branch0 m deriveDeepPaths branch = - branch {deepPaths = makeDeepPaths (_children branch)} + branch {deepPaths = makeDeepPaths (nonEmptyChildren branch)} where makeDeepPaths :: Map NameSegment (Branch m) -> Set Path makeDeepPaths children = @@ -325,7 +333,7 @@ deriveDeepPaths branch = -- | Derive the 'deepEdits' field of a branch. deriveDeepEdits :: Branch0 m -> Branch0 m deriveDeepEdits branch = - branch {deepEdits = makeDeepEdits (_edits branch) (_children branch)} + branch {deepEdits = makeDeepEdits (_edits branch) (nonEmptyChildren branch)} where makeDeepEdits :: Map NameSegment (EditHash, m Patch) -> Map NameSegment (Branch m) -> Map Name EditHash makeDeepEdits edits children = @@ -500,9 +508,15 @@ empty0 :: Branch0 m empty0 = Branch0 mempty mempty mempty mempty mempty mempty mempty mempty mempty mempty --- | Checks whether a Branch0 is empty. +-- | Checks whether a Branch0 is empty, which means that the branch contains no terms or +-- types, and that the heads of all children are empty by the same definition. +-- This is not as easy as checking whether the branch is equal to the `empty0` branch +-- because child branches may be empty, but still have history. isEmpty0 :: Branch0 m -> Bool -isEmpty0 = (== empty0) +isEmpty0 (Branch0 _terms _types _children _edits deepTerms deepTypes _deepTermMetadata _deepTypeMetadata _deepPaths deepEdits) = + Relation.null deepTerms + && Relation.null deepTypes + && Map.null deepEdits -- | Checks whether a branch is empty AND has no history. isEmpty :: Branch m -> Bool @@ -784,10 +798,13 @@ consBranch :: -- If the target branch is empty we just replace it. consBranch Empty headBranch = discardHistory headBranch consBranch baseBranch headBranch = - Branch $ - Causal.consDistinct - (head headBranch & children .~ combinedChildren) - (_history baseBranch) + if baseBranch == headBranch + then baseBranch + else + Branch $ + Causal.consDistinct + (head headBranch & children .~ combinedChildren) + (_history baseBranch) where combineChildren :: These (Branch m) (Branch m) -> Branch m combineChildren = \case diff --git a/parser-typechecker/src/Unison/Codebase/SqliteCodebase.hs b/parser-typechecker/src/Unison/Codebase/SqliteCodebase.hs index 7c49a014b..5a6c7fa04 100644 --- a/parser-typechecker/src/Unison/Codebase/SqliteCodebase.hs +++ b/parser-typechecker/src/Unison/Codebase/SqliteCodebase.hs @@ -14,7 +14,7 @@ where import qualified Control.Concurrent import Control.Monad (filterM, unless, when, (>=>)) -import Control.Monad.Except (ExceptT, MonadError (throwError), runExceptT, withExceptT) +import Control.Monad.Except (ExceptT (ExceptT), runExceptT, withExceptT) import qualified Control.Monad.Except as Except import Control.Monad.Extra (ifM, unlessM) import qualified Control.Monad.Extra as Monad @@ -110,7 +110,6 @@ import qualified UnliftIO import UnliftIO.Directory (canonicalizePath, createDirectoryIfMissing, doesDirectoryExist, doesFileExist) import UnliftIO.STM import UnliftIO.Exception (catch, bracket) -import Control.Monad.Trans.Except (mapExceptT) debug, debugProcessBranches, debugCommitFailedTransaction :: Bool debug = False @@ -174,16 +173,17 @@ createCodebaseOrError' debugName path action = do fmap (Either.mapLeft CreateCodebaseUnknownSchemaVersion) (sqliteCodebase debugName path action) -openOrCreateCodebaseConnection :: - MonadIO m => +withOpenOrCreateCodebaseConnection :: + (MonadUnliftIO m) => Codebase.DebugName -> FilePath -> - m (IO (), Connection) -openOrCreateCodebaseConnection debugName path = do + (Connection -> m r) -> + m r +withOpenOrCreateCodebaseConnection debugName path action = do unlessM (doesFileExist $ path codebasePath) (initSchemaIfNotExist path) - unsafeGetConnection debugName path + withConnection debugName path action -- get the codebase in dir getCodebaseOrError :: @@ -1113,13 +1113,12 @@ pushGitBranch srcConn branch repo (PushGitBranchOpts setRoot _syncMode) = runExc -- set up the cache dir remotePath <- time "Git fetch" $ withExceptT C.GitProtocolError $ pullBranch (writeToRead repo) - (closeDestConn, destConn) <- openOrCreateCodebaseConnection "push.dest" remotePath - mapExceptT (`finally` liftIO closeDestConn) $ do + ExceptT . withOpenOrCreateCodebaseConnection "push.dest" remotePath $ \destConn -> do flip runReaderT destConn $ Q.savepoint "push" - lift . flip State.execStateT emptySyncProgressState $ + flip State.execStateT emptySyncProgressState $ syncInternal syncProgress srcConn destConn (Branch.transform lift branch) flip runReaderT destConn do - if setRoot + result <- if setRoot then do let newRootHash = Branch.headHash branch -- the call to runDB "handles" the possible DB error by bombing @@ -1127,6 +1126,7 @@ pushGitBranch srcConn branch repo (PushGitBranchOpts setRoot _syncMode) = runExc Nothing -> do setRepoRoot newRootHash Q.release "push" + pure $ Right () Just oldRootHash -> do before oldRootHash newRootHash >>= \case Nothing -> @@ -1139,13 +1139,17 @@ pushGitBranch srcConn branch repo (PushGitBranchOpts setRoot _syncMode) = runExc ++ "." Just False -> do Q.rollbackRelease "push" - throwError . C.GitProtocolError $ GitError.PushDestinationHasNewStuff repo + pure . Left . C.GitProtocolError $ GitError.PushDestinationHasNewStuff repo Just True -> do setRepoRoot newRootHash Q.release "push" - else Q.release "push" + pure $ Right () + else do + Q.release "push" + pure $ Right () Q.setJournalMode JournalMode.DELETE + pure result liftIO do void $ push remotePath repo where diff --git a/parser-typechecker/src/Unison/Runtime/ANF.hs b/parser-typechecker/src/Unison/Runtime/ANF.hs index a997be9bb..3a94b361b 100644 --- a/parser-typechecker/src/Unison/Runtime/ANF.hs +++ b/parser-typechecker/src/Unison/Runtime/ANF.hs @@ -762,7 +762,7 @@ data POp | CVLD -- validate | VALU | TLTT -- value, Term.Link.toText -- Debug - | PRNT | INFO + | PRNT | INFO | TRCE -- STM | ATOM deriving (Show,Eq,Ord) diff --git a/parser-typechecker/src/Unison/Runtime/Builtin.hs b/parser-typechecker/src/Unison/Runtime/Builtin.hs index efc6050af..95493f340 100644 --- a/parser-typechecker/src/Unison/Runtime/Builtin.hs +++ b/parser-typechecker/src/Unison/Runtime/Builtin.hs @@ -736,6 +736,12 @@ raise where i = fromIntegral $ builtinTypeNumbering Map.! Ty.exceptionRef +gen'trace :: Var v => SuperNormal v +gen'trace + = binop0 0 $ \[t,v] + -> TLets Direct [] [] (TPrm TRCE [t,v]) + $ TCon Ty.unitRef 0 [] + code'missing :: Var v => SuperNormal v code'missing = unop0 1 $ \[link,b] @@ -1457,6 +1463,7 @@ builtinLookup , ("bug", bug "builtin.bug") , ("todo", bug "builtin.todo") , ("Debug.watch", watch) + , ("Debug.trace", gen'trace) , ("unsafe.coerceAbilities", poly'coerce) , ("Char.toNat", cast Ty.charRef Ty.natRef) diff --git a/parser-typechecker/src/Unison/Runtime/Interface.hs b/parser-typechecker/src/Unison/Runtime/Interface.hs index 4aea066ab..e21f1aca0 100644 --- a/parser-typechecker/src/Unison/Runtime/Interface.hs +++ b/parser-typechecker/src/Unison/Runtime/Interface.hs @@ -53,6 +53,7 @@ import qualified Unison.LabeledDependency as RF import Unison.Reference (Reference) import qualified Unison.Referent as RF (pattern Ref) import qualified Unison.Reference as RF +import qualified Unison.Util.Text as UT import Unison.Util.EnumContainers as EC @@ -332,11 +333,22 @@ evalInContext ppe ctx w = do crs <- readTVarIO (combRefs $ ccache ctx) let hook = watchHook r decom = decompile (backReferenceTm crs (decompTm ctx)) + prettyError (PE _ p) = p prettyError (BU nm c) = either id (bugMsg ppe nm) $ decom c + + tr tx c = case decom c of + Right dv -> do + putStrLn $ "trace: " ++ UT.unpack tx + putStrLn . toANSI 50 $ pretty ppe dv + Left _ -> do + putStrLn $ "trace: " ++ UT.unpack tx + putStrLn "Couldn't decompile value." + print c + result <- traverse (const $ readIORef r) . first prettyError - <=< try $ apply0 (Just hook) (ccache ctx) w + <=< try $ apply0 (Just hook) ((ccache ctx) { tracer = tr }) w pure $ decom =<< result executeMainComb @@ -483,7 +495,7 @@ getStoredCache = SCache restoreCache :: StoredCache -> IO CCache restoreCache (SCache cs crs trs ftm fty int rtm rty) - = CCache builtinForeigns + = CCache builtinForeigns uglyTrace <$> newTVarIO (cs <> combs) <*> newTVarIO (crs <> builtinTermBackref) <*> newTVarIO (trs <> builtinTypeBackref) @@ -493,6 +505,9 @@ restoreCache (SCache cs crs trs ftm fty int rtm rty) <*> newTVarIO (rtm <> builtinTermNumbering) <*> newTVarIO (rty <> builtinTypeNumbering) where + uglyTrace tx c = do + putStrLn $ "trace: " ++ UT.unpack tx + print c rns = emptyRNs { dnum = refLookup "ty" builtinTypeNumbering } combs = mapWithKey diff --git a/parser-typechecker/src/Unison/Runtime/MCode.hs b/parser-typechecker/src/Unison/Runtime/MCode.hs index 9f373a327..85ea1536d 100644 --- a/parser-typechecker/src/Unison/Runtime/MCode.hs +++ b/parser-typechecker/src/Unison/Runtime/MCode.hs @@ -352,7 +352,7 @@ data BPrim2 -- bytes | TAKB | DRPB | IDXB | CATB -- take,drop,index,append -- general - | THRO -- throw + | THRO | TRCE -- throw deriving (Show, Eq, Ord) data MLit @@ -1074,6 +1074,7 @@ emitPOp ANF.VALU = emitBP1 VALU -- error call emitPOp ANF.EROR = emitBP2 THRO +emitPOp ANF.TRCE = emitBP2 TRCE -- non-prim translations emitPOp ANF.BLDS = Seq diff --git a/parser-typechecker/src/Unison/Runtime/Machine.hs b/parser-typechecker/src/Unison/Runtime/Machine.hs index 0e811eda0..9cbbbc8d3 100644 --- a/parser-typechecker/src/Unison/Runtime/Machine.hs +++ b/parser-typechecker/src/Unison/Runtime/Machine.hs @@ -59,7 +59,10 @@ import Unison.Runtime.Foreign.Function import Unison.Runtime.Stack import Unison.Runtime.MCode +import Unison.Util.Text (Text) + import qualified Unison.Type as Rf +import qualified Unison.Builtin.Decls as Rf import qualified Unison.Util.Bytes as By import Unison.Util.Pretty (toPlainUnbroken) @@ -74,6 +77,7 @@ type DEnv = EnumMap Word64 Closure data CCache = CCache { foreignFuncs :: EnumMap Word64 ForeignFunc + , tracer :: Text -> Closure -> IO () , combs :: TVar (EnumMap Word64 Combs) , combRefs :: TVar (EnumMap Word64 Reference) , tagRefs :: TVar (EnumMap Word64 Reference) @@ -105,7 +109,7 @@ refNumTy' cc r = M.lookup r <$> refNumsTy cc baseCCache :: IO CCache baseCCache - = CCache builtinForeigns + = CCache builtinForeigns noTrace <$> newTVarIO combs <*> newTVarIO builtinTermBackref <*> newTVarIO builtinTypeBackref @@ -115,6 +119,7 @@ baseCCache <*> newTVarIO builtinTermNumbering <*> newTVarIO builtinTypeNumbering where + noTrace _ _ = pure () ftm = 1 + maximum builtinTermNumbering fty = 1 + maximum builtinTypeNumbering @@ -184,6 +189,23 @@ apply1 callback env clo = do where k0 = CB $ Hook callback +-- Entry point for evaluating a saved continuation. +-- +-- The continuation must be from an evaluation context expecting a +-- unit value. +jump0 + :: (Stack 'UN -> Stack 'BX -> IO ()) + -> CCache -> Closure -> IO () +jump0 !callback !env !clo = do + ustk <- alloc + bstk <- alloc + (denv, kf) <- + topDEnv <$> readTVarIO (refTy env) <*> readTVarIO (refTm env) + bstk <- bump bstk + poke bstk (Enum Rf.unitRef unitTag) + jump env denv ustk bstk (kf k0) (BArg1 0) clo + where + k0 = CB (Hook callback) lookupDenv :: Word64 -> DEnv -> Closure lookupDenv p denv = fromMaybe BlackHole $ EC.lookup p denv @@ -300,6 +322,11 @@ exec !_ !denv !ustk !bstk !k (BPrim2 CMPU i j) = do ustk <- bump ustk poke ustk . fromEnum $ universalCompare compare x y pure (denv, ustk, bstk, k) +exec !env !denv !ustk !bstk !k (BPrim2 TRCE i j) = do + tx <- peekOffBi bstk i + clo <- peekOff bstk j + tracer env tx clo + pure (denv, ustk, bstk, k) exec !_ !denv !ustk !bstk !k (BPrim2 op i j) = do (ustk,bstk) <- bprim2 ustk bstk op i j pure (denv, ustk, bstk, k) @@ -1373,6 +1400,7 @@ bprim2 !_ !bstk THRO i j = do name <- peekOffBi @Util.Text.Text bstk i x <- peekOff bstk j throwIO (BU (Util.Text.toText name) x) +bprim2 !ustk !bstk TRCE _ _ = pure (ustk, bstk) -- impossible bprim2 !ustk !bstk CMPU _ _ = pure (ustk, bstk) -- impossible {-# inline bprim2 #-} @@ -1772,6 +1800,13 @@ charTag = packTags rt 0 | otherwise = error "internal error: charTag" +unitTag :: Word64 +unitTag + | Just n <- M.lookup Rf.unitRef builtinTypeNumbering + , rt <- toEnum (fromIntegral n) + = packTags rt 0 + | otherwise = error "internal error: unitTag" + universalCompare :: (Foreign -> Foreign -> Ordering) -> Closure diff --git a/parser-typechecker/src/Unison/Runtime/Serialize.hs b/parser-typechecker/src/Unison/Runtime/Serialize.hs index dd4d1efc9..b49a87936 100644 --- a/parser-typechecker/src/Unison/Runtime/Serialize.hs +++ b/parser-typechecker/src/Unison/Runtime/Serialize.hs @@ -428,6 +428,7 @@ instance Tag BPrim2 where tag2word IDXB = 18 tag2word CATB = 19 tag2word THRO = 20 + tag2word TRCE = 21 word2tag 0 = pure EQLU word2tag 1 = pure CMPU @@ -450,4 +451,5 @@ instance Tag BPrim2 where word2tag 18 = pure IDXB word2tag 19 = pure CATB word2tag 20 = pure THRO + word2tag 21 = pure TRCE word2tag n = unknownTag "BPrim2" n diff --git a/parser-typechecker/src/Unison/Server/Backend.hs b/parser-typechecker/src/Unison/Server/Backend.hs index 9f98de7fd..22478835b 100644 --- a/parser-typechecker/src/Unison/Server/Backend.hs +++ b/parser-typechecker/src/Unison/Server/Backend.hs @@ -431,7 +431,7 @@ findShallowInBranch codebase b = do [ ShallowBranchEntry ns (SBH.fullFromHash $ Branch.headHash b) (defnCount b) - | (ns, b) <- Map.toList $ Branch._children b0 + | (ns, b) <- Map.toList $ Branch.nonEmptyChildren b0 ] patchEntries = [ ShallowPatchEntry ns diff --git a/unison-cli/src/Unison/Codebase/Editor/HandleInput.hs b/unison-cli/src/Unison/Codebase/Editor/HandleInput.hs index 85bc5d1ed..5b2696c53 100644 --- a/unison-cli/src/Unison/Codebase/Editor/HandleInput.hs +++ b/unison-cli/src/Unison/Codebase/Editor/HandleInput.hs @@ -660,7 +660,7 @@ loop = do let dest = resolveToAbsolute dest0 -- if dest isn't empty: leave dest unchanged, and complain. destb <- getAt dest - if Branch.isEmpty destb + if Branch.isEmpty0 (Branch.head destb) then do ok <- updateAtM dest (const $ pure srcb) if ok then success else respond $ BranchEmpty src0 @@ -848,7 +848,7 @@ loop = do let path = resolveToAbsolute path' LoopState.currentPathStack %= Nel.cons path branch' <- getAt path - when (Branch.isEmpty branch') (respond $ CreatedNewBranch path) + when (Branch.isEmpty0 $ Branch.head branch') (respond $ CreatedNewBranch path) UpI -> use LoopState.currentPath >>= \p -> case Path.unsnoc (Path.unabsolute p) of Nothing -> pure () @@ -1903,8 +1903,8 @@ doPushRemoteBranch repo localPath syncMode remoteTarget = do shouldPushTo :: PushBehavior -> Branch m -> Bool shouldPushTo pushBehavior remoteBranch = case pushBehavior of - PushBehavior.RequireEmpty -> Branch.isEmpty remoteBranch - PushBehavior.RequireNonEmpty -> not (Branch.isEmpty remoteBranch) + PushBehavior.RequireEmpty -> Branch.isEmpty0 (Branch.head remoteBranch) + PushBehavior.RequireNonEmpty -> not (Branch.isEmpty0 (Branch.head remoteBranch)) -- | Handle a @ShowDefinitionI@ input command, i.e. `view` or `edit`. handleShowDefinition :: diff --git a/unison-cli/src/Unison/CommandLine/InputPatterns.hs b/unison-cli/src/Unison/CommandLine/InputPatterns.hs index 5a1e0c9b2..7b058355a 100644 --- a/unison-cli/src/Unison/CommandLine/InputPatterns.hs +++ b/unison-cli/src/Unison/CommandLine/InputPatterns.hs @@ -2057,7 +2057,7 @@ bothCompletors c1 c2 q code b currentPath = do . nubOrdOn Completion.display $ suggestions1 ++ suggestions2 --- | +-- | A completer for namespace paths. pathCompletor :: Applicative f => -- | Turns a query and list of possible completions into a 'Completion'. @@ -2092,7 +2092,7 @@ namespaceArg = -- | Recursively collects all names of namespaces which are children of the branch. allSubNamespaces :: Branch.Branch0 m -> [Text] allSubNamespaces b = - flip Map.foldMapWithKey (Branch._children b) $ + flip Map.foldMapWithKey (Branch.nonEmptyChildren b) $ \(NameSegment k) (Branch.head -> b') -> (k : fmap (\sn -> k <> "." <> sn) (allSubNamespaces b')) diff --git a/unison-cli/tests/Unison/Test/GitSync.hs b/unison-cli/tests/Unison/Test/GitSync.hs index 6f66719a0..f64db190b 100644 --- a/unison-cli/tests/Unison/Test/GitSync.hs +++ b/unison-cli/tests/Unison/Test/GitSync.hs @@ -40,6 +40,53 @@ test = scope "gitsync22" . tests $ destroyedRemote : flip map [(Ucm.CodebaseFormat2, "sc")] \(fmt, name) -> scope name $ tests [ + pushPullTest "pull-over-deleted-namespace" fmt + (\repo -> [i| + ```unison:hide + x = 1 + ``` + ```ucm:hide + .> add + .> push.create ${repo} + ``` + |]) + (\repo -> [i| + ```unison:hide + child.y = 2 + ``` + + Should be able to pull a branch from the repo over top of our deleted local branch. + ```ucm + .> add + .> delete.namespace child + .> pull ${repo} child + ``` + |]) + , + pushPullTest "push-over-deleted-namespace" fmt + (\repo -> [i| + ```unison:hide + child.x = 1 + y = 2 + ``` + ```ucm:hide + .> add + .> delete.namespace child + .> push.create ${repo} + ``` + |]) + (\repo -> [i| + ```unison:hide + child.z = 3 + ``` + + Should be able to push a branch over top of a deleted remote branch. + ```ucm + .> add + .> push.create ${repo}:.child child + ``` + |]) + , pushPullTest "typeAlias" fmt (\repo -> [i| ```ucm diff --git a/unison-src/transcripts/alias-many.output.md b/unison-src/transcripts/alias-many.output.md index 920a7abae..f1381241d 100644 --- a/unison-src/transcripts/alias-many.output.md +++ b/unison-src/transcripts/alias-many.output.md @@ -86,389 +86,390 @@ Let's try it! -> Bytes -> Bytes -> Bytes - 66. Debug.watch : Text -> a -> a - 67. unique type Doc - 68. Doc.Blob : Text -> Doc - 69. Doc.Evaluate : Term -> Doc - 70. Doc.Join : [Doc] -> Doc - 71. Doc.Link : Link -> Doc - 72. Doc.Signature : Term -> Doc - 73. Doc.Source : Link -> Doc - 74. structural type Either a b - 75. Either.Left : a -> Either a b - 76. Either.Right : b -> Either a b - 77. structural ability Exception - 78. Exception.raise : Failure ->{Exception} x - 79. builtin type Float - 80. Float.* : Float -> Float -> Float - 81. Float.+ : Float -> Float -> Float - 82. Float.- : Float -> Float -> Float - 83. Float./ : Float -> Float -> Float - 84. Float.abs : Float -> Float - 85. Float.acos : Float -> Float - 86. Float.acosh : Float -> Float - 87. Float.asin : Float -> Float - 88. Float.asinh : Float -> Float - 89. Float.atan : Float -> Float - 90. Float.atan2 : Float -> Float -> Float - 91. Float.atanh : Float -> Float - 92. Float.ceiling : Float -> Int - 93. Float.cos : Float -> Float - 94. Float.cosh : Float -> Float - 95. Float.eq : Float -> Float -> Boolean - 96. Float.exp : Float -> Float - 97. Float.floor : Float -> Int - 98. Float.fromRepresentation : Nat -> Float - 99. Float.fromText : Text -> Optional Float - 100. Float.gt : Float -> Float -> Boolean - 101. Float.gteq : Float -> Float -> Boolean - 102. Float.log : Float -> Float - 103. Float.logBase : Float -> Float -> Float - 104. Float.lt : Float -> Float -> Boolean - 105. Float.lteq : Float -> Float -> Boolean - 106. Float.max : Float -> Float -> Float - 107. Float.min : Float -> Float -> Float - 108. Float.pow : Float -> Float -> Float - 109. Float.round : Float -> Int - 110. Float.sin : Float -> Float - 111. Float.sinh : Float -> Float - 112. Float.sqrt : Float -> Float - 113. Float.tan : Float -> Float - 114. Float.tanh : Float -> Float - 115. Float.toRepresentation : Float -> Nat - 116. Float.toText : Float -> Text - 117. Float.truncate : Float -> Int - 118. Handle.toText : Handle -> Text - 119. builtin type Int - 120. Int.* : Int -> Int -> Int - 121. Int.+ : Int -> Int -> Int - 122. Int.- : Int -> Int -> Int - 123. Int./ : Int -> Int -> Int - 124. Int.and : Int -> Int -> Int - 125. Int.complement : Int -> Int - 126. Int.eq : Int -> Int -> Boolean - 127. Int.fromRepresentation : Nat -> Int - 128. Int.fromText : Text -> Optional Int - 129. Int.gt : Int -> Int -> Boolean - 130. Int.gteq : Int -> Int -> Boolean - 131. Int.increment : Int -> Int - 132. Int.isEven : Int -> Boolean - 133. Int.isOdd : Int -> Boolean - 134. Int.leadingZeros : Int -> Nat - 135. Int.lt : Int -> Int -> Boolean - 136. Int.lteq : Int -> Int -> Boolean - 137. Int.mod : Int -> Int -> Int - 138. Int.negate : Int -> Int - 139. Int.or : Int -> Int -> Int - 140. Int.popCount : Int -> Nat - 141. Int.pow : Int -> Nat -> Int - 142. Int.shiftLeft : Int -> Nat -> Int - 143. Int.shiftRight : Int -> Nat -> Int - 144. Int.signum : Int -> Int - 145. Int.toFloat : Int -> Float - 146. Int.toRepresentation : Int -> Nat - 147. Int.toText : Int -> Text - 148. Int.trailingZeros : Int -> Nat - 149. Int.truncate0 : Int -> Nat - 150. Int.xor : Int -> Int -> Int - 151. unique type io2.BufferMode - 152. io2.BufferMode.BlockBuffering : BufferMode - 153. io2.BufferMode.LineBuffering : BufferMode - 154. io2.BufferMode.NoBuffering : BufferMode - 155. io2.BufferMode.SizedBlockBuffering : Nat -> BufferMode - 156. unique type io2.Failure - 157. io2.Failure.Failure : Type -> Text -> Any -> Failure - 158. unique type io2.FileMode - 159. io2.FileMode.Append : FileMode - 160. io2.FileMode.Read : FileMode - 161. io2.FileMode.ReadWrite : FileMode - 162. io2.FileMode.Write : FileMode - 163. builtin type io2.Handle - 164. builtin type io2.IO - 165. io2.IO.clientSocket.impl : Text + 66. Debug.trace : Text -> a -> () + 67. Debug.watch : Text -> a -> a + 68. unique type Doc + 69. Doc.Blob : Text -> Doc + 70. Doc.Evaluate : Term -> Doc + 71. Doc.Join : [Doc] -> Doc + 72. Doc.Link : Link -> Doc + 73. Doc.Signature : Term -> Doc + 74. Doc.Source : Link -> Doc + 75. structural type Either a b + 76. Either.Left : a -> Either a b + 77. Either.Right : b -> Either a b + 78. structural ability Exception + 79. Exception.raise : Failure ->{Exception} x + 80. builtin type Float + 81. Float.* : Float -> Float -> Float + 82. Float.+ : Float -> Float -> Float + 83. Float.- : Float -> Float -> Float + 84. Float./ : Float -> Float -> Float + 85. Float.abs : Float -> Float + 86. Float.acos : Float -> Float + 87. Float.acosh : Float -> Float + 88. Float.asin : Float -> Float + 89. Float.asinh : Float -> Float + 90. Float.atan : Float -> Float + 91. Float.atan2 : Float -> Float -> Float + 92. Float.atanh : Float -> Float + 93. Float.ceiling : Float -> Int + 94. Float.cos : Float -> Float + 95. Float.cosh : Float -> Float + 96. Float.eq : Float -> Float -> Boolean + 97. Float.exp : Float -> Float + 98. Float.floor : Float -> Int + 99. Float.fromRepresentation : Nat -> Float + 100. Float.fromText : Text -> Optional Float + 101. Float.gt : Float -> Float -> Boolean + 102. Float.gteq : Float -> Float -> Boolean + 103. Float.log : Float -> Float + 104. Float.logBase : Float -> Float -> Float + 105. Float.lt : Float -> Float -> Boolean + 106. Float.lteq : Float -> Float -> Boolean + 107. Float.max : Float -> Float -> Float + 108. Float.min : Float -> Float -> Float + 109. Float.pow : Float -> Float -> Float + 110. Float.round : Float -> Int + 111. Float.sin : Float -> Float + 112. Float.sinh : Float -> Float + 113. Float.sqrt : Float -> Float + 114. Float.tan : Float -> Float + 115. Float.tanh : Float -> Float + 116. Float.toRepresentation : Float -> Nat + 117. Float.toText : Float -> Text + 118. Float.truncate : Float -> Int + 119. Handle.toText : Handle -> Text + 120. builtin type Int + 121. Int.* : Int -> Int -> Int + 122. Int.+ : Int -> Int -> Int + 123. Int.- : Int -> Int -> Int + 124. Int./ : Int -> Int -> Int + 125. Int.and : Int -> Int -> Int + 126. Int.complement : Int -> Int + 127. Int.eq : Int -> Int -> Boolean + 128. Int.fromRepresentation : Nat -> Int + 129. Int.fromText : Text -> Optional Int + 130. Int.gt : Int -> Int -> Boolean + 131. Int.gteq : Int -> Int -> Boolean + 132. Int.increment : Int -> Int + 133. Int.isEven : Int -> Boolean + 134. Int.isOdd : Int -> Boolean + 135. Int.leadingZeros : Int -> Nat + 136. Int.lt : Int -> Int -> Boolean + 137. Int.lteq : Int -> Int -> Boolean + 138. Int.mod : Int -> Int -> Int + 139. Int.negate : Int -> Int + 140. Int.or : Int -> Int -> Int + 141. Int.popCount : Int -> Nat + 142. Int.pow : Int -> Nat -> Int + 143. Int.shiftLeft : Int -> Nat -> Int + 144. Int.shiftRight : Int -> Nat -> Int + 145. Int.signum : Int -> Int + 146. Int.toFloat : Int -> Float + 147. Int.toRepresentation : Int -> Nat + 148. Int.toText : Int -> Text + 149. Int.trailingZeros : Int -> Nat + 150. Int.truncate0 : Int -> Nat + 151. Int.xor : Int -> Int -> Int + 152. unique type io2.BufferMode + 153. io2.BufferMode.BlockBuffering : BufferMode + 154. io2.BufferMode.LineBuffering : BufferMode + 155. io2.BufferMode.NoBuffering : BufferMode + 156. io2.BufferMode.SizedBlockBuffering : Nat -> BufferMode + 157. unique type io2.Failure + 158. io2.Failure.Failure : Type -> Text -> Any -> Failure + 159. unique type io2.FileMode + 160. io2.FileMode.Append : FileMode + 161. io2.FileMode.Read : FileMode + 162. io2.FileMode.ReadWrite : FileMode + 163. io2.FileMode.Write : FileMode + 164. builtin type io2.Handle + 165. builtin type io2.IO + 166. io2.IO.clientSocket.impl : Text -> Text ->{IO} Either Failure Socket - 166. io2.IO.closeFile.impl : Handle ->{IO} Either Failure () - 167. io2.IO.closeSocket.impl : Socket ->{IO} Either Failure () - 168. io2.IO.createDirectory.impl : Text + 167. io2.IO.closeFile.impl : Handle ->{IO} Either Failure () + 168. io2.IO.closeSocket.impl : Socket ->{IO} Either Failure () + 169. io2.IO.createDirectory.impl : Text ->{IO} Either Failure () - 169. io2.IO.createTempDirectory.impl : Text + 170. io2.IO.createTempDirectory.impl : Text ->{IO} Either Failure Text - 170. io2.IO.delay.impl : Nat ->{IO} Either Failure () - 171. io2.IO.directoryContents.impl : Text + 171. io2.IO.delay.impl : Nat ->{IO} Either Failure () + 172. io2.IO.directoryContents.impl : Text ->{IO} Either Failure [Text] - 172. io2.IO.fileExists.impl : Text + 173. io2.IO.fileExists.impl : Text ->{IO} Either Failure Boolean - 173. io2.IO.forkComp : '{IO} a ->{IO} ThreadId - 174. io2.IO.getArgs.impl : '{IO} Either Failure [Text] - 175. io2.IO.getBuffering.impl : Handle + 174. io2.IO.forkComp : '{IO} a ->{IO} ThreadId + 175. io2.IO.getArgs.impl : '{IO} Either Failure [Text] + 176. io2.IO.getBuffering.impl : Handle ->{IO} Either Failure BufferMode - 176. io2.IO.getBytes.impl : Handle + 177. io2.IO.getBytes.impl : Handle -> Nat ->{IO} Either Failure Bytes - 177. io2.IO.getCurrentDirectory.impl : '{IO} Either + 178. io2.IO.getCurrentDirectory.impl : '{IO} Either Failure Text - 178. io2.IO.getEnv.impl : Text ->{IO} Either Failure Text - 179. io2.IO.getFileSize.impl : Text ->{IO} Either Failure Nat - 180. io2.IO.getFileTimestamp.impl : Text + 179. io2.IO.getEnv.impl : Text ->{IO} Either Failure Text + 180. io2.IO.getFileSize.impl : Text ->{IO} Either Failure Nat + 181. io2.IO.getFileTimestamp.impl : Text ->{IO} Either Failure Nat - 181. io2.IO.getLine.impl : Handle ->{IO} Either Failure Text - 182. io2.IO.getTempDirectory.impl : '{IO} Either Failure Text - 183. io2.IO.handlePosition.impl : Handle + 182. io2.IO.getLine.impl : Handle ->{IO} Either Failure Text + 183. io2.IO.getTempDirectory.impl : '{IO} Either Failure Text + 184. io2.IO.handlePosition.impl : Handle ->{IO} Either Failure Nat - 184. io2.IO.isDirectory.impl : Text + 185. io2.IO.isDirectory.impl : Text ->{IO} Either Failure Boolean - 185. io2.IO.isFileEOF.impl : Handle + 186. io2.IO.isFileEOF.impl : Handle ->{IO} Either Failure Boolean - 186. io2.IO.isFileOpen.impl : Handle + 187. io2.IO.isFileOpen.impl : Handle ->{IO} Either Failure Boolean - 187. io2.IO.isSeekable.impl : Handle + 188. io2.IO.isSeekable.impl : Handle ->{IO} Either Failure Boolean - 188. io2.IO.kill.impl : ThreadId ->{IO} Either Failure () - 189. io2.IO.listen.impl : Socket ->{IO} Either Failure () - 190. io2.IO.openFile.impl : Text + 189. io2.IO.kill.impl : ThreadId ->{IO} Either Failure () + 190. io2.IO.listen.impl : Socket ->{IO} Either Failure () + 191. io2.IO.openFile.impl : Text -> FileMode ->{IO} Either Failure Handle - 191. io2.IO.putBytes.impl : Handle + 192. io2.IO.putBytes.impl : Handle -> Bytes ->{IO} Either Failure () - 192. io2.IO.ref : a ->{IO} Ref {IO} a - 193. io2.IO.removeDirectory.impl : Text + 193. io2.IO.ref : a ->{IO} Ref {IO} a + 194. io2.IO.removeDirectory.impl : Text ->{IO} Either Failure () - 194. io2.IO.removeFile.impl : Text ->{IO} Either Failure () - 195. io2.IO.renameDirectory.impl : Text + 195. io2.IO.removeFile.impl : Text ->{IO} Either Failure () + 196. io2.IO.renameDirectory.impl : Text -> Text ->{IO} Either Failure () - 196. io2.IO.renameFile.impl : Text + 197. io2.IO.renameFile.impl : Text -> Text ->{IO} Either Failure () - 197. io2.IO.seekHandle.impl : Handle + 198. io2.IO.seekHandle.impl : Handle -> SeekMode -> Int ->{IO} Either Failure () - 198. io2.IO.serverSocket.impl : Optional Text + 199. io2.IO.serverSocket.impl : Optional Text -> Text ->{IO} Either Failure Socket - 199. io2.IO.setBuffering.impl : Handle + 200. io2.IO.setBuffering.impl : Handle -> BufferMode ->{IO} Either Failure () - 200. io2.IO.setCurrentDirectory.impl : Text + 201. io2.IO.setCurrentDirectory.impl : Text ->{IO} Either Failure () - 201. io2.IO.socketAccept.impl : Socket + 202. io2.IO.socketAccept.impl : Socket ->{IO} Either Failure Socket - 202. io2.IO.socketPort.impl : Socket ->{IO} Either Failure Nat - 203. io2.IO.socketReceive.impl : Socket + 203. io2.IO.socketPort.impl : Socket ->{IO} Either Failure Nat + 204. io2.IO.socketReceive.impl : Socket -> Nat ->{IO} Either Failure Bytes - 204. io2.IO.socketSend.impl : Socket + 205. io2.IO.socketSend.impl : Socket -> Bytes ->{IO} Either Failure () - 205. io2.IO.stdHandle : StdHandle -> Handle - 206. io2.IO.systemTime.impl : '{IO} Either Failure Nat - 207. io2.IO.systemTimeMicroseconds : '{IO} Int - 208. unique type io2.IOError - 209. io2.IOError.AlreadyExists : IOError - 210. io2.IOError.EOF : IOError - 211. io2.IOError.IllegalOperation : IOError - 212. io2.IOError.NoSuchThing : IOError - 213. io2.IOError.PermissionDenied : IOError - 214. io2.IOError.ResourceBusy : IOError - 215. io2.IOError.ResourceExhausted : IOError - 216. io2.IOError.UserError : IOError - 217. unique type io2.IOFailure - 218. builtin type io2.MVar - 219. io2.MVar.isEmpty : MVar a ->{IO} Boolean - 220. io2.MVar.new : a ->{IO} MVar a - 221. io2.MVar.newEmpty : '{IO} MVar a - 222. io2.MVar.put.impl : MVar a -> a ->{IO} Either Failure () - 223. io2.MVar.read.impl : MVar a ->{IO} Either Failure a - 224. io2.MVar.swap.impl : MVar a -> a ->{IO} Either Failure a - 225. io2.MVar.take.impl : MVar a ->{IO} Either Failure a - 226. io2.MVar.tryPut.impl : MVar a + 206. io2.IO.stdHandle : StdHandle -> Handle + 207. io2.IO.systemTime.impl : '{IO} Either Failure Nat + 208. io2.IO.systemTimeMicroseconds : '{IO} Int + 209. unique type io2.IOError + 210. io2.IOError.AlreadyExists : IOError + 211. io2.IOError.EOF : IOError + 212. io2.IOError.IllegalOperation : IOError + 213. io2.IOError.NoSuchThing : IOError + 214. io2.IOError.PermissionDenied : IOError + 215. io2.IOError.ResourceBusy : IOError + 216. io2.IOError.ResourceExhausted : IOError + 217. io2.IOError.UserError : IOError + 218. unique type io2.IOFailure + 219. builtin type io2.MVar + 220. io2.MVar.isEmpty : MVar a ->{IO} Boolean + 221. io2.MVar.new : a ->{IO} MVar a + 222. io2.MVar.newEmpty : '{IO} MVar a + 223. io2.MVar.put.impl : MVar a -> a ->{IO} Either Failure () + 224. io2.MVar.read.impl : MVar a ->{IO} Either Failure a + 225. io2.MVar.swap.impl : MVar a -> a ->{IO} Either Failure a + 226. io2.MVar.take.impl : MVar a ->{IO} Either Failure a + 227. io2.MVar.tryPut.impl : MVar a -> a ->{IO} Either Failure Boolean - 227. io2.MVar.tryRead.impl : MVar a + 228. io2.MVar.tryRead.impl : MVar a ->{IO} Either Failure (Optional a) - 228. io2.MVar.tryTake : MVar a ->{IO} Optional a - 229. unique type io2.SeekMode - 230. io2.SeekMode.AbsoluteSeek : SeekMode - 231. io2.SeekMode.RelativeSeek : SeekMode - 232. io2.SeekMode.SeekFromEnd : SeekMode - 233. builtin type io2.Socket - 234. unique type io2.StdHandle - 235. io2.StdHandle.StdErr : StdHandle - 236. io2.StdHandle.StdIn : StdHandle - 237. io2.StdHandle.StdOut : StdHandle - 238. builtin type io2.STM - 239. io2.STM.atomically : '{STM} a ->{IO} a - 240. io2.STM.retry : '{STM} a - 241. builtin type io2.ThreadId - 242. builtin type io2.Tls - 243. builtin type io2.Tls.Cipher - 244. builtin type io2.Tls.ClientConfig - 245. io2.Tls.ClientConfig.certificates.set : [SignedCert] + 229. io2.MVar.tryTake : MVar a ->{IO} Optional a + 230. unique type io2.SeekMode + 231. io2.SeekMode.AbsoluteSeek : SeekMode + 232. io2.SeekMode.RelativeSeek : SeekMode + 233. io2.SeekMode.SeekFromEnd : SeekMode + 234. builtin type io2.Socket + 235. unique type io2.StdHandle + 236. io2.StdHandle.StdErr : StdHandle + 237. io2.StdHandle.StdIn : StdHandle + 238. io2.StdHandle.StdOut : StdHandle + 239. builtin type io2.STM + 240. io2.STM.atomically : '{STM} a ->{IO} a + 241. io2.STM.retry : '{STM} a + 242. builtin type io2.ThreadId + 243. builtin type io2.Tls + 244. builtin type io2.Tls.Cipher + 245. builtin type io2.Tls.ClientConfig + 246. io2.Tls.ClientConfig.certificates.set : [SignedCert] -> ClientConfig -> ClientConfig - 246. io2.TLS.ClientConfig.ciphers.set : [Cipher] + 247. io2.TLS.ClientConfig.ciphers.set : [Cipher] -> ClientConfig -> ClientConfig - 247. io2.Tls.ClientConfig.default : Text + 248. io2.Tls.ClientConfig.default : Text -> Bytes -> ClientConfig - 248. io2.Tls.ClientConfig.versions.set : [Version] + 249. io2.Tls.ClientConfig.versions.set : [Version] -> ClientConfig -> ClientConfig - 249. io2.Tls.decodeCert.impl : Bytes + 250. io2.Tls.decodeCert.impl : Bytes -> Either Failure SignedCert - 250. io2.Tls.decodePrivateKey : Bytes -> [PrivateKey] - 251. io2.Tls.encodeCert : SignedCert -> Bytes - 252. io2.Tls.encodePrivateKey : PrivateKey -> Bytes - 253. io2.Tls.handshake.impl : Tls ->{IO} Either Failure () - 254. io2.Tls.newClient.impl : ClientConfig + 251. io2.Tls.decodePrivateKey : Bytes -> [PrivateKey] + 252. io2.Tls.encodeCert : SignedCert -> Bytes + 253. io2.Tls.encodePrivateKey : PrivateKey -> Bytes + 254. io2.Tls.handshake.impl : Tls ->{IO} Either Failure () + 255. io2.Tls.newClient.impl : ClientConfig -> Socket ->{IO} Either Failure Tls - 255. io2.Tls.newServer.impl : ServerConfig + 256. io2.Tls.newServer.impl : ServerConfig -> Socket ->{IO} Either Failure Tls - 256. builtin type io2.Tls.PrivateKey - 257. io2.Tls.receive.impl : Tls ->{IO} Either Failure Bytes - 258. io2.Tls.send.impl : Tls -> Bytes ->{IO} Either Failure () - 259. builtin type io2.Tls.ServerConfig - 260. io2.Tls.ServerConfig.certificates.set : [SignedCert] + 257. builtin type io2.Tls.PrivateKey + 258. io2.Tls.receive.impl : Tls ->{IO} Either Failure Bytes + 259. io2.Tls.send.impl : Tls -> Bytes ->{IO} Either Failure () + 260. builtin type io2.Tls.ServerConfig + 261. io2.Tls.ServerConfig.certificates.set : [SignedCert] -> ServerConfig -> ServerConfig - 261. io2.Tls.ServerConfig.ciphers.set : [Cipher] + 262. io2.Tls.ServerConfig.ciphers.set : [Cipher] -> ServerConfig -> ServerConfig - 262. io2.Tls.ServerConfig.default : [SignedCert] + 263. io2.Tls.ServerConfig.default : [SignedCert] -> PrivateKey -> ServerConfig - 263. io2.Tls.ServerConfig.versions.set : [Version] + 264. io2.Tls.ServerConfig.versions.set : [Version] -> ServerConfig -> ServerConfig - 264. builtin type io2.Tls.SignedCert - 265. io2.Tls.terminate.impl : Tls ->{IO} Either Failure () - 266. builtin type io2.Tls.Version - 267. unique type io2.TlsFailure - 268. builtin type io2.TVar - 269. io2.TVar.new : a ->{STM} TVar a - 270. io2.TVar.newIO : a ->{IO} TVar a - 271. io2.TVar.read : TVar a ->{STM} a - 272. io2.TVar.readIO : TVar a ->{IO} a - 273. io2.TVar.swap : TVar a -> a ->{STM} a - 274. io2.TVar.write : TVar a -> a ->{STM} () - 275. unique type IsPropagated - 276. IsPropagated.IsPropagated : IsPropagated - 277. unique type IsTest - 278. IsTest.IsTest : IsTest - 279. unique type Link - 280. builtin type Link.Term - 281. Link.Term : Term -> Link - 282. Link.Term.toText : Term -> Text - 283. builtin type Link.Type - 284. Link.Type : Type -> Link - 285. builtin type List - 286. List.++ : [a] -> [a] -> [a] - 287. List.+: : a -> [a] -> [a] - 288. List.:+ : [a] -> a -> [a] - 289. List.at : Nat -> [a] -> Optional a - 290. List.cons : a -> [a] -> [a] - 291. List.drop : Nat -> [a] -> [a] - 292. List.empty : [a] - 293. List.size : [a] -> Nat - 294. List.snoc : [a] -> a -> [a] - 295. List.take : Nat -> [a] -> [a] - 296. metadata.isPropagated : IsPropagated - 297. metadata.isTest : IsTest - 298. builtin type Nat - 299. Nat.* : Nat -> Nat -> Nat - 300. Nat.+ : Nat -> Nat -> Nat - 301. Nat./ : Nat -> Nat -> Nat - 302. Nat.and : Nat -> Nat -> Nat - 303. Nat.complement : Nat -> Nat - 304. Nat.drop : Nat -> Nat -> Nat - 305. Nat.eq : Nat -> Nat -> Boolean - 306. Nat.fromText : Text -> Optional Nat - 307. Nat.gt : Nat -> Nat -> Boolean - 308. Nat.gteq : Nat -> Nat -> Boolean - 309. Nat.increment : Nat -> Nat - 310. Nat.isEven : Nat -> Boolean - 311. Nat.isOdd : Nat -> Boolean - 312. Nat.leadingZeros : Nat -> Nat - 313. Nat.lt : Nat -> Nat -> Boolean - 314. Nat.lteq : Nat -> Nat -> Boolean - 315. Nat.mod : Nat -> Nat -> Nat - 316. Nat.or : Nat -> Nat -> Nat - 317. Nat.popCount : Nat -> Nat - 318. Nat.pow : Nat -> Nat -> Nat - 319. Nat.shiftLeft : Nat -> Nat -> Nat - 320. Nat.shiftRight : Nat -> Nat -> Nat - 321. Nat.sub : Nat -> Nat -> Int - 322. Nat.toFloat : Nat -> Float - 323. Nat.toInt : Nat -> Int - 324. Nat.toText : Nat -> Text - 325. Nat.trailingZeros : Nat -> Nat - 326. Nat.xor : Nat -> Nat -> Nat - 327. structural type Optional a - 328. Optional.None : Optional a - 329. Optional.Some : a -> Optional a - 330. builtin type Ref - 331. Ref.read : Ref g a ->{g} a - 332. Ref.write : Ref g a -> a ->{g} () - 333. builtin type Request - 334. builtin type Scope - 335. Scope.ref : a ->{Scope s} Ref {Scope s} a - 336. Scope.run : (∀ s. '{g, Scope s} r) ->{g} r - 337. structural type SeqView a b - 338. SeqView.VElem : a -> b -> SeqView a b - 339. SeqView.VEmpty : SeqView a b - 340. Socket.toText : Socket -> Text - 341. unique type Test.Result - 342. Test.Result.Fail : Text -> Result - 343. Test.Result.Ok : Text -> Result - 344. builtin type Text - 345. Text.!= : Text -> Text -> Boolean - 346. Text.++ : Text -> Text -> Text - 347. Text.drop : Nat -> Text -> Text - 348. Text.empty : Text - 349. Text.eq : Text -> Text -> Boolean - 350. Text.fromCharList : [Char] -> Text - 351. Text.fromUtf8.impl : Bytes -> Either Failure Text - 352. Text.gt : Text -> Text -> Boolean - 353. Text.gteq : Text -> Text -> Boolean - 354. Text.lt : Text -> Text -> Boolean - 355. Text.lteq : Text -> Text -> Boolean - 356. Text.repeat : Nat -> Text -> Text - 357. Text.size : Text -> Nat - 358. Text.take : Nat -> Text -> Text - 359. Text.toCharList : Text -> [Char] - 360. Text.toUtf8 : Text -> Bytes - 361. Text.uncons : Text -> Optional (Char, Text) - 362. Text.unsnoc : Text -> Optional (Text, Char) - 363. ThreadId.toText : ThreadId -> Text - 364. todo : a -> b - 365. structural type Tuple a b - 366. Tuple.Cons : a -> b -> Tuple a b - 367. structural type Unit - 368. Unit.Unit : () - 369. Universal.< : a -> a -> Boolean - 370. Universal.<= : a -> a -> Boolean - 371. Universal.== : a -> a -> Boolean - 372. Universal.> : a -> a -> Boolean - 373. Universal.>= : a -> a -> Boolean - 374. Universal.compare : a -> a -> Int - 375. unsafe.coerceAbilities : (a ->{e1} b) -> a ->{e2} b - 376. builtin type Value - 377. Value.dependencies : Value -> [Term] - 378. Value.deserialize : Bytes -> Either Text Value - 379. Value.load : Value ->{IO} Either [Term] a - 380. Value.serialize : Value -> Bytes - 381. Value.value : a -> Value + 265. builtin type io2.Tls.SignedCert + 266. io2.Tls.terminate.impl : Tls ->{IO} Either Failure () + 267. builtin type io2.Tls.Version + 268. unique type io2.TlsFailure + 269. builtin type io2.TVar + 270. io2.TVar.new : a ->{STM} TVar a + 271. io2.TVar.newIO : a ->{IO} TVar a + 272. io2.TVar.read : TVar a ->{STM} a + 273. io2.TVar.readIO : TVar a ->{IO} a + 274. io2.TVar.swap : TVar a -> a ->{STM} a + 275. io2.TVar.write : TVar a -> a ->{STM} () + 276. unique type IsPropagated + 277. IsPropagated.IsPropagated : IsPropagated + 278. unique type IsTest + 279. IsTest.IsTest : IsTest + 280. unique type Link + 281. builtin type Link.Term + 282. Link.Term : Term -> Link + 283. Link.Term.toText : Term -> Text + 284. builtin type Link.Type + 285. Link.Type : Type -> Link + 286. builtin type List + 287. List.++ : [a] -> [a] -> [a] + 288. List.+: : a -> [a] -> [a] + 289. List.:+ : [a] -> a -> [a] + 290. List.at : Nat -> [a] -> Optional a + 291. List.cons : a -> [a] -> [a] + 292. List.drop : Nat -> [a] -> [a] + 293. List.empty : [a] + 294. List.size : [a] -> Nat + 295. List.snoc : [a] -> a -> [a] + 296. List.take : Nat -> [a] -> [a] + 297. metadata.isPropagated : IsPropagated + 298. metadata.isTest : IsTest + 299. builtin type Nat + 300. Nat.* : Nat -> Nat -> Nat + 301. Nat.+ : Nat -> Nat -> Nat + 302. Nat./ : Nat -> Nat -> Nat + 303. Nat.and : Nat -> Nat -> Nat + 304. Nat.complement : Nat -> Nat + 305. Nat.drop : Nat -> Nat -> Nat + 306. Nat.eq : Nat -> Nat -> Boolean + 307. Nat.fromText : Text -> Optional Nat + 308. Nat.gt : Nat -> Nat -> Boolean + 309. Nat.gteq : Nat -> Nat -> Boolean + 310. Nat.increment : Nat -> Nat + 311. Nat.isEven : Nat -> Boolean + 312. Nat.isOdd : Nat -> Boolean + 313. Nat.leadingZeros : Nat -> Nat + 314. Nat.lt : Nat -> Nat -> Boolean + 315. Nat.lteq : Nat -> Nat -> Boolean + 316. Nat.mod : Nat -> Nat -> Nat + 317. Nat.or : Nat -> Nat -> Nat + 318. Nat.popCount : Nat -> Nat + 319. Nat.pow : Nat -> Nat -> Nat + 320. Nat.shiftLeft : Nat -> Nat -> Nat + 321. Nat.shiftRight : Nat -> Nat -> Nat + 322. Nat.sub : Nat -> Nat -> Int + 323. Nat.toFloat : Nat -> Float + 324. Nat.toInt : Nat -> Int + 325. Nat.toText : Nat -> Text + 326. Nat.trailingZeros : Nat -> Nat + 327. Nat.xor : Nat -> Nat -> Nat + 328. structural type Optional a + 329. Optional.None : Optional a + 330. Optional.Some : a -> Optional a + 331. builtin type Ref + 332. Ref.read : Ref g a ->{g} a + 333. Ref.write : Ref g a -> a ->{g} () + 334. builtin type Request + 335. builtin type Scope + 336. Scope.ref : a ->{Scope s} Ref {Scope s} a + 337. Scope.run : (∀ s. '{g, Scope s} r) ->{g} r + 338. structural type SeqView a b + 339. SeqView.VElem : a -> b -> SeqView a b + 340. SeqView.VEmpty : SeqView a b + 341. Socket.toText : Socket -> Text + 342. unique type Test.Result + 343. Test.Result.Fail : Text -> Result + 344. Test.Result.Ok : Text -> Result + 345. builtin type Text + 346. Text.!= : Text -> Text -> Boolean + 347. Text.++ : Text -> Text -> Text + 348. Text.drop : Nat -> Text -> Text + 349. Text.empty : Text + 350. Text.eq : Text -> Text -> Boolean + 351. Text.fromCharList : [Char] -> Text + 352. Text.fromUtf8.impl : Bytes -> Either Failure Text + 353. Text.gt : Text -> Text -> Boolean + 354. Text.gteq : Text -> Text -> Boolean + 355. Text.lt : Text -> Text -> Boolean + 356. Text.lteq : Text -> Text -> Boolean + 357. Text.repeat : Nat -> Text -> Text + 358. Text.size : Text -> Nat + 359. Text.take : Nat -> Text -> Text + 360. Text.toCharList : Text -> [Char] + 361. Text.toUtf8 : Text -> Bytes + 362. Text.uncons : Text -> Optional (Char, Text) + 363. Text.unsnoc : Text -> Optional (Text, Char) + 364. ThreadId.toText : ThreadId -> Text + 365. todo : a -> b + 366. structural type Tuple a b + 367. Tuple.Cons : a -> b -> Tuple a b + 368. structural type Unit + 369. Unit.Unit : () + 370. Universal.< : a -> a -> Boolean + 371. Universal.<= : a -> a -> Boolean + 372. Universal.== : a -> a -> Boolean + 373. Universal.> : a -> a -> Boolean + 374. Universal.>= : a -> a -> Boolean + 375. Universal.compare : a -> a -> Int + 376. unsafe.coerceAbilities : (a ->{e1} b) -> a ->{e2} b + 377. builtin type Value + 378. Value.dependencies : Value -> [Term] + 379. Value.deserialize : Bytes -> Either Text Value + 380. Value.load : Value ->{IO} Either [Term] a + 381. Value.serialize : Value -> Bytes + 382. Value.value : a -> Value .builtin> alias.many 94-104 .mylib @@ -477,17 +478,17 @@ Let's try it! Added definitions: - 1. Float.cosh : Float -> Float - 2. Float.eq : Float -> Float -> Boolean - 3. Float.exp : Float -> Float - 4. Float.floor : Float -> Int - 5. Float.fromRepresentation : Nat -> Float - 6. Float.fromText : Text -> Optional Float - 7. Float.gt : Float -> Float -> Boolean - 8. Float.gteq : Float -> Float -> Boolean - 9. Float.log : Float -> Float - 10. Float.logBase : Float -> Float -> Float - 11. Float.lt : Float -> Float -> Boolean + 1. Float.cos : Float -> Float + 2. Float.cosh : Float -> Float + 3. Float.eq : Float -> Float -> Boolean + 4. Float.exp : Float -> Float + 5. Float.floor : Float -> Int + 6. Float.fromRepresentation : Nat -> Float + 7. Float.fromText : Text -> Optional Float + 8. Float.gt : Float -> Float -> Boolean + 9. Float.gteq : Float -> Float -> Boolean + 10. Float.log : Float -> Float + 11. Float.logBase : Float -> Float -> Float Tip: You can use `undo` or `reflog` to undo this change. @@ -547,17 +548,17 @@ I want to incorporate a few more from another namespace: .mylib> find - 1. Float.cosh : Float -> Float - 2. Float.eq : Float -> Float -> Boolean - 3. Float.exp : Float -> Float - 4. Float.floor : Float -> Int - 5. Float.fromRepresentation : Nat -> Float - 6. Float.fromText : Text -> Optional Float - 7. Float.gt : Float -> Float -> Boolean - 8. Float.gteq : Float -> Float -> Boolean - 9. Float.log : Float -> Float - 10. Float.logBase : Float -> Float -> Float - 11. Float.lt : Float -> Float -> Boolean + 1. Float.cos : Float -> Float + 2. Float.cosh : Float -> Float + 3. Float.eq : Float -> Float -> Boolean + 4. Float.exp : Float -> Float + 5. Float.floor : Float -> Int + 6. Float.fromRepresentation : Nat -> Float + 7. Float.fromText : Text -> Optional Float + 8. Float.gt : Float -> Float -> Boolean + 9. Float.gteq : Float -> Float -> Boolean + 10. Float.log : Float -> Float + 11. Float.logBase : 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 diff --git a/unison-src/transcripts/builtins-merge.output.md b/unison-src/transcripts/builtins-merge.output.md index b6aeb9aab..f11216193 100644 --- a/unison-src/transcripts/builtins-merge.output.md +++ b/unison-src/transcripts/builtins-merge.output.md @@ -19,7 +19,7 @@ The `builtins.merge` command adds the known builtins to a `builtin` subnamespace 8. Char/ (3 definitions) 9. Code (builtin type) 10. Code/ (8 definitions) - 11. Debug/ (1 definition) + 11. Debug/ (2 definitions) 12. Doc (type) 13. Doc/ (6 definitions) 14. Either (type) diff --git a/unison-src/transcripts/empty-namespaces.md b/unison-src/transcripts/empty-namespaces.md new file mode 100644 index 000000000..2d9f901dc --- /dev/null +++ b/unison-src/transcripts/empty-namespaces.md @@ -0,0 +1,62 @@ +# Empty namespace behaviours + +```unison:hide +mynamespace.x = 1 +``` + +```ucm:hide +.> add +.> delete.namespace mynamespace +``` + +The deleted namespace shouldn't appear in `ls` output. +```ucm:error +.> ls +``` +```ucm:error +.> ls.verbose +``` +```ucm:error +.> find mynamespace +``` + +## history + +The history of the namespace should still exist if requested explicitly. + +```ucm +.> history mynamespace +``` + +Merging an empty namespace should still copy its history if it has some. + +```ucm +.empty> history +.empty> merge .mynamespace +.empty> history +``` + +Add and then delete a term to add some history to a deleted namespace. + +```unison:hide +deleted.x = 1 +stuff.thing = 2 +``` + +```ucm:hide +.> add +.> delete.namespace .deleted +``` + +I should be allowed to fork over a deleted namespace + +```ucm +.> fork stuff deleted +``` + +The history from the `deleted` namespace should have been overwritten by the history from `stuff`. + +```ucm +.> history stuff +.> history deleted +``` diff --git a/unison-src/transcripts/empty-namespaces.output.md b/unison-src/transcripts/empty-namespaces.output.md new file mode 100644 index 000000000..68accf1a2 --- /dev/null +++ b/unison-src/transcripts/empty-namespaces.output.md @@ -0,0 +1,114 @@ +# Empty namespace behaviours + +```unison +mynamespace.x = 1 +``` + +The deleted namespace shouldn't appear in `ls` output. +```ucm +.> ls + + nothing to show + +``` +```ucm +.> ls.verbose + + 😶 + + No results. Check your spelling, or try using tab completion + to supply command arguments. + +``` +```ucm +.> find mynamespace + + 😶 + + No results. Check your spelling, or try using tab completion + to supply command arguments. + +``` +## history + +The history of the namespace should still exist if requested explicitly. + +```ucm +.> history mynamespace + + Note: The most recent namespace hash is immediately below this + message. + + ⊙ #qjc20aua9h + + - Deletes: + + x + + □ #hkrqt3tm05 (start of history) + +``` +Merging an empty namespace should still copy its history if it has some. + +```ucm + ☝️ The namespace .empty is empty. + +.empty> history + + ☝️ The namespace .empty is empty. + +.empty> merge .mynamespace + + Nothing changed as a result of the merge. + +.empty> history + + Note: The most recent namespace hash is immediately below this + message. + + ⊙ #qjc20aua9h + + - Deletes: + + x + + □ #hkrqt3tm05 (start of history) + +``` +Add and then delete a term to add some history to a deleted namespace. + +```unison +deleted.x = 1 +stuff.thing = 2 +``` + +I should be allowed to fork over a deleted namespace + +```ucm +.> fork stuff deleted + + Done. + +``` +The history from the `deleted` namespace should have been overwritten by the history from `stuff`. + +```ucm +.> history stuff + + Note: The most recent namespace hash is immediately below this + message. + + + + □ #3bm1524lb7 (start of history) + +.> history deleted + + Note: The most recent namespace hash is immediately below this + message. + + + + □ #3bm1524lb7 (start of history) + +``` diff --git a/unison-src/transcripts/emptyCodebase.output.md b/unison-src/transcripts/emptyCodebase.output.md index 3cf0d18ff..9ea833644 100644 --- a/unison-src/transcripts/emptyCodebase.output.md +++ b/unison-src/transcripts/emptyCodebase.output.md @@ -23,7 +23,7 @@ Technically, the definitions all exist, but they have no names. `builtins.merge` .foo> ls - 1. builtin/ (381 definitions) + 1. builtin/ (382 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/ (549 definitions) + 1. builtin/ (550 definitions) ``` More typically, you'd start out by pulling `base. diff --git a/unison-src/transcripts/merges.output.md b/unison-src/transcripts/merges.output.md index b293ff68b..f3cbd6b66 100644 --- a/unison-src/transcripts/merges.output.md +++ b/unison-src/transcripts/merges.output.md @@ -125,13 +125,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. - ⊙ #7gjmqmlj0v + ⊙ #5aa4qmhvur - Deletes: feature1.y - ⊙ #7qqt9t3qr5 + ⊙ #g1jho38v97 + Adds / updates: @@ -142,26 +142,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 - ⊙ #u86vero990 + ⊙ #dkcip47417 + Adds / updates: feature1.y - ⊙ #el4liebh4m + ⊙ #at9qnsl83m > Moves: Original name New name x master.x - ⊙ #pne2sthbc8 + ⊙ #g271dghaje + Adds / updates: x - □ #qnkdl1f20n (start of history) + □ #aooso6apun (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`. diff --git a/unison-src/transcripts/reflog.output.md b/unison-src/transcripts/reflog.output.md index 380c9ea4b..7829d29cb 100644 --- a/unison-src/transcripts/reflog.output.md +++ b/unison-src/transcripts/reflog.output.md @@ -59,16 +59,16 @@ y = 2 most recent, along with the command that got us there. Try: `fork 2 .old` - `fork #7m7gaa64si .old` to make an old namespace + `fork #ttu893rclh .old` to make an old namespace accessible again, - `reset-root #7m7gaa64si` to reset the root namespace and + `reset-root #ttu893rclh` to reset the root namespace and its history to that of the specified namespace. - 1. #k8o73d0cc0 : add - 2. #7m7gaa64si : add - 3. #qnkdl1f20n : builtins.merge + 1. #opcc5n8q9a : add + 2. #ttu893rclh : add + 3. #aooso6apun : builtins.merge 4. #sjg2v58vn2 : (initial reflogged namespace) ``` diff --git a/unison-src/transcripts/squash.output.md b/unison-src/transcripts/squash.output.md index b969d1e00..f8e5a8be4 100644 --- a/unison-src/transcripts/squash.output.md +++ b/unison-src/transcripts/squash.output.md @@ -13,7 +13,7 @@ Let's look at some examples. We'll start with a namespace with just the builtins - □ #tfjjgvaq9l (start of history) + □ #afd37h0nli (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. - ⊙ #uiahjr3nvu + ⊙ #k528t27n2n > Moves: Original name New name Nat.frobnicate Nat.+ - ⊙ #ov2s5dsaba + ⊙ #3a5rbkh4bd > Moves: Original name New name Nat.+ Nat.frobnicate - □ #tfjjgvaq9l (start of history) + □ #afd37h0nli (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. - ⊙ #uiahjr3nvu + ⊙ #k528t27n2n > Moves: Original name New name Nat.frobnicate Nat.+ - ⊙ #ov2s5dsaba + ⊙ #3a5rbkh4bd > Moves: Original name New name Nat.+ Nat.frobnicate - □ #tfjjgvaq9l (start of history) + □ #afd37h0nli (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 - □ #tfjjgvaq9l (start of history) + □ #afd37h0nli (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. - ⊙ #dp0rpp67if + ⊙ #jma01uqhdr - Deletes: Nat.* Nat.+ - □ #tfjjgvaq9l (start of history) + □ #afd37h0nli (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.