diff --git a/parser-typechecker/src/Unison/Runtime/Decompile.hs b/parser-typechecker/src/Unison/Runtime/Decompile.hs index 264aa2b188..9da8d47ca8 100644 --- a/parser-typechecker/src/Unison/Runtime/Decompile.hs +++ b/parser-typechecker/src/Unison/Runtime/Decompile.hs @@ -5,13 +5,14 @@ {-# LANGUAGE ViewPatterns #-} module Unison.Runtime.Decompile - ( decompile - , DecompError (..) - , renderDecompError - ) where + ( decompile, + DecompResult, + DecompError (..), + renderDecompError, + ) +where import Data.Set (singleton) -import Prelude hiding (lines) import Unison.ABT (substs) import Unison.Codebase.Runtime (Error) import Unison.ConstructorReference (GConstructorReference (..)) @@ -64,10 +65,11 @@ import Unison.Type typeLinkRef, ) import Unison.Util.Bytes qualified as By -import Unison.Util.Pretty (lit, indentN, lines, wrap, syntaxToColor) +import Unison.Util.Pretty (indentN, lines, lit, syntaxToColor, wrap) import Unison.Util.Text qualified as Text import Unison.Var (Var) import Unsafe.Coerce -- for Int -> Double +import Prelude hiding (lines) con :: (Var v) => Reference -> Word64 -> Term v () con rf ct = constructor () (ConstructorReference rf $ fromIntegral ct) diff --git a/parser-typechecker/src/Unison/Runtime/Interface.hs b/parser-typechecker/src/Unison/Runtime/Interface.hs index 9b0e9f0586..538381a423 100644 --- a/parser-typechecker/src/Unison/Runtime/Interface.hs +++ b/parser-typechecker/src/Unison/Runtime/Interface.hs @@ -10,6 +10,7 @@ module Unison.Runtime.Interface ( startRuntime, withRuntime, + startNativeRuntime, standalone, runStandalone, StoredCache, @@ -23,13 +24,16 @@ import Control.Concurrent.STM as STM import Control.Monad import Data.Binary.Get (runGetOrFail) -- import Data.Bits (shiftL) +import Data.ByteString qualified as BS import Data.ByteString.Lazy qualified as BL import Data.Bytes.Get (MonadGet) -import Data.Bytes.Put (MonadPut, runPutL) +import Data.Bytes.Put (MonadPut, putWord32be, runPutL, runPutS) import Data.Bytes.Serial import Data.Foldable import Data.IORef +import Data.List qualified as L import Data.Map.Strict qualified as Map +import Data.Sequence qualified as Seq (fromList) import Data.Set as Set ( filter, fromList, @@ -40,6 +44,13 @@ import Data.Set as Set ) import Data.Set qualified as Set import Data.Text (isPrefixOf, unpack) +import System.Process + ( CreateProcess (..), + StdStream (..), + proc, + waitForProcess, + withCreateProcess, + ) import Unison.Builtin.Decls qualified as RF import Unison.Codebase.CodeLookup (CodeLookup (..)) import Unison.Codebase.MainTerm (builtinIOTestTypes, builtinMain) @@ -56,9 +67,13 @@ import Unison.PrettyPrintEnv qualified as PPE import Unison.Reference (Reference) import Unison.Reference qualified as RF import Unison.Referent qualified as RF (pattern Ref) -import Unison.Runtime.ANF -import Unison.Runtime.ANF.Rehash (rehashGroups) -import Unison.Runtime.ANF.Serialize (getGroup, putGroup) +import Unison.Runtime.ANF as ANF +import Unison.Runtime.ANF.Rehash as ANF (rehashGroups) +import Unison.Runtime.ANF.Serialize as ANF + ( getGroup, + putGroup, + serializeValue, + ) import Unison.Runtime.Builtin import Unison.Runtime.Decompile import Unison.Runtime.Exception @@ -88,6 +103,7 @@ import Unison.Runtime.Machine refNumTm, refNumsTm, refNumsTy, + reifyValue, ) import Unison.Runtime.Pattern import Unison.Runtime.Serialize as SER @@ -218,6 +234,37 @@ recursiveRefDeps seen cl (RF.DerivedId i) = Nothing -> pure mempty recursiveRefDeps _ _ _ = pure mempty +recursiveIRefDeps :: + Map.Map Reference (SuperGroup Symbol) -> + Set Reference -> + [Reference] -> + Set Reference +recursiveIRefDeps cl seen0 rfs = srfs <> foldMap f rfs + where + seen = seen0 <> srfs + srfs = Set.fromList rfs + f = foldMap (recursiveGroupDeps cl seen) . flip Map.lookup cl + +recursiveGroupDeps :: + Map.Map Reference (SuperGroup Symbol) -> + Set Reference -> + SuperGroup Symbol -> + Set Reference +recursiveGroupDeps cl seen0 grp = deps <> recursiveIRefDeps cl seen depl + where + depl = Prelude.filter (`Set.notMember` seen0) $ groupTermLinks grp + deps = Set.fromList depl + seen = seen0 <> deps + +recursiveIntermedDeps :: + Map.Map Reference (SuperGroup Symbol) -> + [Reference] -> + [(Reference, SuperGroup Symbol)] +recursiveIntermedDeps cl rfs = mapMaybe f $ Set.toList ds + where + ds = recursiveIRefDeps cl mempty rfs + f rf = fmap (rf,) (Map.lookup rf cl) + collectDeps :: CodeLookup Symbol IO () -> Term Symbol -> @@ -312,22 +359,14 @@ performRehash rgrp0 ctx = Left (msg, refs) -> error $ unpack msg ++ ": " ++ show refs Right p -> p -loadDeps :: +loadCode :: CodeLookup Symbol IO () -> PrettyPrintEnv -> EvalCtx -> - [(Reference, Either [Int] [Int])] -> [Reference] -> - IO EvalCtx -loadDeps cl ppe ctx tyrs tmrs = do - let cc = ccache ctx - sand <- readTVarIO (sandbox cc) - p <- - refNumsTy cc <&> \m (r, _) -> case r of - RF.DerivedId {} -> - r `Map.notMember` dspec ctx - || r `Map.notMember` m - _ -> False + IO (EvalCtx, [(Reference, SuperGroup Symbol)]) +loadCode cl ppe ctx tmrs = do + igs <- readTVarIO (intermed $ ccache ctx) q <- refNumsTm (ccache ctx) <&> \m r -> case r of RF.DerivedId {} @@ -335,24 +374,132 @@ loadDeps cl ppe ctx tyrs tmrs = do | Just r <- floatToIntermed ctx r -> r `Map.notMember` m | otherwise -> True _ -> False - ctx <- foldM (uncurry . allocType) ctx $ Prelude.filter p tyrs + let (new, old) = L.partition q tmrs + odeps = recursiveIntermedDeps igs $ toIntermed ctx <$> old itms <- - traverse (\r -> (RF.unsafeId r,) <$> resolveTermRef cl r) $ - Prelude.filter q tmrs + traverse (\r -> (RF.unsafeId r,) <$> resolveTermRef cl r) new let im = Tm.unhashComponent (Map.fromList itms) (subvs, rgrp0, rbkr) = intermediateTerms ppe ctx im lubvs r = case Map.lookup r subvs of Just r -> r - Nothing -> error "loadDeps: variable missing for float refs" + Nothing -> error "loadCode: variable missing for float refs" vm = Map.mapKeys RF.DerivedId . Map.map (lubvs . fst) $ im int b r = if b then r else toIntermed ctx r (ctx', _, rgrp) = performRehash (fmap (overGroupLinks int) rgrp0) (floatRemapAdd vm ctx) - tyAdd = Set.fromList $ fst <$> tyrs - backrefAdd rbkr ctx' - <$ cacheAdd0 tyAdd rgrp (expandSandbox sand rgrp) cc + return (backrefAdd rbkr ctx', rgrp ++ odeps) + +loadDeps :: + CodeLookup Symbol IO () -> + PrettyPrintEnv -> + EvalCtx -> + [(Reference, Either [Int] [Int])] -> + [Reference] -> + IO (EvalCtx, [(Reference, SuperGroup Symbol)]) +loadDeps cl ppe ctx tyrs tmrs = do + let cc = ccache ctx + sand <- readTVarIO (sandbox cc) + p <- + refNumsTy cc <&> \m (r, _) -> case r of + RF.DerivedId {} -> + r `Map.notMember` dspec ctx + || r `Map.notMember` m + _ -> False + ctx <- foldM (uncurry . allocType) ctx $ Prelude.filter p tyrs + let tyAdd = Set.fromList $ fst <$> tyrs + out@(_, rgrp) <- loadCode cl ppe ctx tmrs + out <$ cacheAdd0 tyAdd rgrp (expandSandbox sand rgrp) cc + +compileValue :: Reference -> [(Reference, SuperGroup Symbol)] -> Value +compileValue base = + flip pair (rf base) . ANF.BLit . List . Seq.fromList . fmap cpair + where + rf = ANF.BLit . TmLink . RF.Ref + cons x y = Data RF.pairRef 0 [] [x, y] + tt = Data RF.unitRef 0 [] [] + code sg = ANF.BLit (Code sg) + pair x y = cons x (cons y tt) + cpair (r, sg) = pair (rf r) (code sg) + +decompileCtx :: + EnumMap Word64 Reference -> EvalCtx -> Closure -> DecompResult Symbol +decompileCtx crs ctx = decompile ib $ backReferenceTm crs fr ir dt + where + ib = intermedToBase ctx + fr = floatRemap ctx + ir = intermedRemap ctx + dt = decompTm ctx + +nativeEval :: + IORef EvalCtx -> + CodeLookup Symbol IO () -> + PrettyPrintEnv -> + Term Symbol -> + IO (Either Error ([Error], Term Symbol)) +nativeEval ctxVar cl ppe tm = catchInternalErrors $ do + ctx <- readIORef ctxVar + (tyrs, tmrs) <- collectDeps cl tm + (ctx, codes) <- loadDeps cl ppe ctx tyrs tmrs + (ctx, tcodes, base) <- prepareEvaluation ppe tm ctx + writeIORef ctxVar ctx + nativeEvalInContext ppe ctx (codes ++ tcodes) base + +interpEval :: + ActiveThreads -> + IO () -> + IORef EvalCtx -> + CodeLookup Symbol IO () -> + PrettyPrintEnv -> + Term Symbol -> + IO (Either Error ([Error], Term Symbol)) +interpEval activeThreads cleanupThreads ctxVar cl ppe tm = + catchInternalErrors $ do + ctx <- readIORef ctxVar + (tyrs, tmrs) <- collectDeps cl tm + (ctx, _) <- loadDeps cl ppe ctx tyrs tmrs + (ctx, _, init) <- prepareEvaluation ppe tm ctx + initw <- refNumTm (ccache ctx) init + writeIORef ctxVar ctx + evalInContext ppe ctx activeThreads initw + `UnliftIO.finally` cleanupThreads + +nativeCompile :: + Text -> + IORef EvalCtx -> + CodeLookup Symbol IO () -> + PrettyPrintEnv -> + Reference -> + FilePath -> + IO (Maybe Error) +nativeCompile _version ctxVar cl ppe base path = tryM $ do + ctx <- readIORef ctxVar + (tyrs, tmrs) <- collectRefDeps cl base + (_, codes) <- loadDeps cl ppe ctx tyrs tmrs + nativeCompileCodes codes base path + +interpCompile :: + Text -> + IORef EvalCtx -> + CodeLookup Symbol IO () -> + PrettyPrintEnv -> + Reference -> + FilePath -> + IO (Maybe Error) +interpCompile version ctxVar cl ppe rf path = tryM $ do + ctx <- readIORef ctxVar + (tyrs, tmrs) <- collectRefDeps cl rf + (ctx, _) <- loadDeps cl ppe ctx tyrs tmrs + let cc = ccache ctx + lk m = flip Map.lookup m =<< baseToIntermed ctx rf + Just w <- lk <$> readTVarIO (refTm cc) + sto <- standalone cc w + BL.writeFile path . runPutL $ do + serialize $ version + serialize $ RF.showShort 8 rf + putNat w + putStoredCache sto backrefLifted :: Reference -> @@ -461,13 +608,13 @@ prepareEvaluation :: PrettyPrintEnv -> Term Symbol -> EvalCtx -> - IO (EvalCtx, Word64) + IO (EvalCtx, [(Reference, SuperGroup Symbol)], Reference) prepareEvaluation ppe tm ctx = do missing <- cacheAdd rgrp (ccache ctx') when (not . null $ missing) . fail $ reportBug "E029347" $ "Error in prepareEvaluation, cache is missing: " <> show missing - (,) (backrefAdd rbkr ctx') <$> refNumTm (ccache ctx') rmn + pure (backrefAdd rbkr ctx', rgrp, rmn) where (rmn0, frem, rgrp0, rbkr) = intermediateTerm ppe ctx tm int b r = if b then r else toIntermed ctx r @@ -500,6 +647,73 @@ backReferenceTm ws frs irs dcm c i = do bs <- Map.lookup r dcm Map.lookup i bs +schemeProc :: [String] -> CreateProcess +schemeProc args = + (proc "native-compiler/bin/runner" args) + { std_in = CreatePipe, + std_out = Inherit, + std_err = Inherit + } + +-- Note: this currently does not support yielding values; instead it +-- just produces a result appropriate for unitary `run` commands. The +-- reason is that the executed code can cause output to occur, which +-- would interfere with using stdout to communicate the final value +-- back from the subprocess. We need a side channel to support both +-- output effects and result communication. +-- +-- Strictly speaking, this also holds for input. Input effects will +-- just get EOF in this scheme, because the code communication has +-- taken over the input. This could probably be without a side +-- channel, but a side channel is probably better. +nativeEvalInContext :: + PrettyPrintEnv -> + EvalCtx -> + [(Reference, SuperGroup Symbol)] -> + Reference -> + IO (Either Error ([Error], Term Symbol)) +nativeEvalInContext _ ctx codes base = do + let cc = ccache ctx + crs <- readTVarIO $ combRefs cc + let bytes = serializeValue . compileValue base $ codes + + decodeResult (Left msg) = pure . Left $ fromString msg + decodeResult (Right val) = + reifyValue cc val >>= \case + Left _ -> pure . Left $ "missing references from result" + Right cl -> case decompileCtx crs ctx cl of + (errs, dv) -> pure $ Right (listErrors errs, dv) + + callout (Just pin) _ _ ph = do + BS.hPut pin . runPutS . putWord32be . fromIntegral $ BS.length bytes + BS.hPut pin bytes + UnliftIO.hClose pin + let unit = Data RF.unitRef 0 [] [] + sunit = Data RF.pairRef 0 [] [unit, unit] + waitForProcess ph + decodeResult $ Right sunit + -- TODO: actualy receive output from subprocess + -- decodeResult . deserializeValue =<< BS.hGetContents pout + callout _ _ _ _ = + pure . Left $ "withCreateProcess didn't provide handles" + withCreateProcess (schemeProc []) callout + +nativeCompileCodes :: + [(Reference, SuperGroup Symbol)] -> + Reference -> + FilePath -> + IO () +nativeCompileCodes codes base path = do + let bytes = serializeValue . compileValue base $ codes + callout (Just pin) _ _ ph = do + BS.hPut pin . runPutS . putWord32be . fromIntegral $ BS.length bytes + BS.hPut pin bytes + UnliftIO.hClose pin + waitForProcess ph + pure () + callout _ _ _ _ = fail "withCreateProcess didn't provide handles" + withCreateProcess (schemeProc ["-o", path]) callout + evalInContext :: PrettyPrintEnv -> EvalCtx -> @@ -510,16 +724,7 @@ evalInContext ppe ctx activeThreads w = do r <- newIORef BlackHole crs <- readTVarIO (combRefs $ ccache ctx) let hook = watchHook r - decom = - decompile - (intermedToBase ctx) - ( backReferenceTm - crs - (floatRemap ctx) - (intermedRemap ctx) - (decompTm ctx) - ) - + decom = decompileCtx crs ctx finish = fmap (first listErrors . decom) prettyError (PE _ p) = p @@ -706,26 +911,20 @@ startRuntime sandboxed runtimeHost version = do pure $ Runtime { terminate = pure (), - evaluate = \cl ppe tm -> catchInternalErrors $ do - ctx <- readIORef ctxVar - (tyrs, tmrs) <- collectDeps cl tm - ctx <- loadDeps cl ppe ctx tyrs tmrs - (ctx, init) <- prepareEvaluation ppe tm ctx - writeIORef ctxVar ctx - evalInContext ppe ctx activeThreads init `UnliftIO.finally` cleanupThreads, - compileTo = \cl ppe rf path -> tryM $ do - ctx <- readIORef ctxVar - (tyrs, tmrs) <- collectRefDeps cl rf - ctx <- loadDeps cl ppe ctx tyrs tmrs - let cc = ccache ctx - lk m = flip Map.lookup m =<< baseToIntermed ctx rf - Just w <- lk <$> readTVarIO (refTm cc) - sto <- standalone cc w - BL.writeFile path . runPutL $ do - serialize $ version - serialize $ RF.showShort 8 rf - putNat w - putStoredCache sto, + evaluate = interpEval activeThreads cleanupThreads ctxVar, + compileTo = interpCompile version ctxVar, + mainType = builtinMain External, + ioTestType = builtinTest External + } + +startNativeRuntime :: Text -> IO (Runtime Symbol) +startNativeRuntime version = do + ctxVar <- newIORef =<< baseContext False + pure $ + Runtime + { terminate = pure (), + evaluate = nativeEval ctxVar, + compileTo = nativeCompile version ctxVar, mainType = builtinMain External, ioTestTypes = builtinIOTestTypes External } diff --git a/scheme-libs/racket/runner.rkt b/scheme-libs/racket/runner.rkt new file mode 100644 index 0000000000..37406b55ba --- /dev/null +++ b/scheme-libs/racket/runner.rkt @@ -0,0 +1,88 @@ +#!racket/base + +(require + (except-in racket false true unit any) + compiler/embed + unison/boot + unison/data + unison/data-info + unison/chunked-seq + unison/primops + unison/primops-generated + unison/builtin-generated) + +(define (grab-bytes) + (let* ([size-bytes (read-bytes 4)] + [size (integer-bytes->integer size-bytes #f #t 0 4)]) + (read-bytes size))) + +(define (decode-input) + (let ([bs (grab-bytes)]) + (match (builtin-Value.deserialize (bytes->chunked-bytes bs)) + [(unison-data _ t (list q)) + (= t unison-either-right:tag) + (apply + values + (unison-tuple->list (reify-value (unison-quote-val q))))] + [else + (raise "unexpected input")]))) + +(define (build-main-module main-def) + `(module unison-main racket/base + (require + unison/boot) + + (provide main) + + (define (main) + (handle ['ref-4n0fgs00] top-exn-handler + (,(termlink->name main-def)))))) + +(define (do-evaluate) + (let-values ([(code main-ref) (decode-input)]) + (add-runtime-code 'unison-main code) + (handle ['ref-4n0fgs00] top-exn-handler + ((termlink->proc main-ref)) + (data 'unit 0)))) + +; stub implementation +(define (do-compile output) (void)) + ; (let-values ([(code main-ref) (decode-input)]) + ; (create-embedding-executable + ; output + ; #:modules '((#f unison-main)) + ; #:literal-expression '(begin (require unison-main) (main))))) + +(define runtime-namespace + (let ([ns (variable-reference->namespace (#%variable-reference))]) + (namespace-require ''#%kernel ns) + ns)) + +(define (chunked-list->list cl) + (vector->list (chunked-list->vector cl))) + +(define (list->chunked-list l) + (vector->chunked-list (list->vector l))) + +(define (join ls) + (cond + [(null? ls) '()] + [else (append (car ls) (join (cdr ls)))])) + +(define compile (make-parameter #f)) + +(define (handle-command-line) + (command-line + #:program "runner" + #:once-any + [("-o" "--output") + file + "compile to " + (compile file)] + #:args () + (compile))) + +(let ([out (handle-command-line)]) + (if out + (do-compile out) + (do-evaluate))) diff --git a/scheme-libs/racket/unison/boot.ss b/scheme-libs/racket/unison/boot.ss index 4938ac8510..febd27901c 100644 --- a/scheme-libs/racket/unison/boot.ss +++ b/scheme-libs/racket/unison/boot.ss @@ -48,6 +48,8 @@ describe-value decode-value + top-exn-handler + reference->termlink reference->typelink referent->termlink @@ -567,3 +569,25 @@ (define (unison-seq . l) (vector->chunked-list (list->vector l))) + +; Top level exception handler, moved from being generated in unison. +; The in-unison definition was effectively just literal scheme code +; represented as a unison data type, with some names generated from +; codebase data. +; +; Note: the ref-4n0fgs00 stuff is probably not ultimately correct, but +; is how things work for now. +(define (top-exn-handler rq) + (request-case rq + [pure (x) + (match x + [(unison-data r 0 (list)) + (eq? r unison-unit:link) + (display "")] + [else + (display (describe-value x))])] + [ref-4n0fgs00 + [0 (f) + (control 'ref-4n0fgs00 k + (let ([disp (describe-value f)]) + (raise (make-exn:bug "builtin.bug" disp))))]])) diff --git a/scheme-libs/racket/unison/primops-generated.rkt b/scheme-libs/racket/unison/primops-generated.rkt index 4cb4ab633d..03f49e776d 100644 --- a/scheme-libs/racket/unison/primops-generated.rkt +++ b/scheme-libs/racket/unison/primops-generated.rkt @@ -41,7 +41,16 @@ unison-POp-CACH unison-POp-LOAD - unison-POp-LKUP) + unison-POp-LKUP + + ; some exports of internal machinery for use elsewhere + gen-code + reify-value + termlink->name + + add-runtime-code + build-runtime-module + termlink->proc) (define-builtin-link Value.value) (define-builtin-link Value.reflect) @@ -65,6 +74,11 @@ (define (list->chunked-list l) (vector->chunked-list (list->vector l))) +(define (assemble-cases hd sc cs) + (cond + [(equal? hd 'cond) `(cond ,@cs)] + [else `(,hd ,sc ,@cs)])) + (define (decode-term tm) (match tm [(unison-data _ t (list tms)) @@ -80,9 +94,10 @@ ,@(map decode-term (chunked-list->list tms)))] [(unison-data _ t (list hd sc cs)) #:when (= t unison-schemeterm-cases:tag) - `(,(text->ident hd) - ,(decode-term sc) - ,@(map decode-term (chunked-list->list cs)))] + (assemble-cases + (text->ident hd) + (decode-term sc) + (map decode-term (chunked-list->list cs)))] [(unison-data _ t (list hd bs bd)) #:when (= t unison-schemeterm-binds:tag) `(,(text->ident hd) @@ -126,10 +141,23 @@ [else (raise (format "decode-syntax: unimplemented case: ~a" dfn))])) +(define (string->char st) + (cond + [(< (string-length st) 3) #f] + [(> (string-length st) 3) #f] + [(equal? (substring st 0 2) "#\\") (string-ref st 2)] + [else #f])) + (define (text->ident tx) (let* ([st (chunked-string->string tx)] - [n (string->number st)]) - (if n n (string->symbol st)))) + [n (string->number st)] + [c (string->char st)]) + (cond + [(equal? st "#f") #f] + [(equal? st "#t") #t] + [c c] + [n n] + [else (string->symbol st)]))) (define (decode-ref rf) (match rf @@ -433,6 +461,13 @@ [0 (snd nil) (values fst snd)])])) +(define (gen-typelinks code) + (map decode-syntax + (chunked-list->list + (gen-typelink-defns + (list->chunked-list + (map unison-code-rep code)))))) + (define (gen-code args) (let-values ([(tl co) (splat-upair args)]) (match tl @@ -500,6 +535,17 @@ 'unison/simple-wrappers nm)))) +(define (termlink->proc tl) + (match tl + [(unison-termlink-derived bs i) + (let ([mname (hash-ref runtime-module-map bs)]) + (parameterize ([current-namespace runtime-namespace]) + (dynamic-require `(quote ,mname) (termlink->name tl))))] + [(unison-termlink-builtin name) + (let ([mname (string->symbol (string-append "builtin-" name))]) + (parameterize ([current-namespace runtime-namespace]) + (resolve-builtin mname)))])) + (define (resolve-proc gr) (sum-case (decode-ref (group-reference gr)) [0 (tx) @@ -512,50 +558,65 @@ (parameterize ([current-namespace runtime-namespace]) (dynamic-require `(quote ,mname) sym)))])) -(define (add-runtime-module mname links defs) - (let ([names (map termlink->name links)]) - (eval - `(module ,mname racket/base - (require unison/boot) - (require unison/primops) - (require unison/primops-generated) - (require unison/builtin-generated) - (require unison/simple-wrappers) - (provide ,@names) - ,@defs) - runtime-namespace))) +(define (build-runtime-module mname tylinks tmlinks defs) + (let ([names (map termlink->name tmlinks)]) + `(module ,mname racket/base + (require unison/boot + unison/data-info + unison/primops + unison/primops-generated + unison/builtin-generated + unison/simple-wrappers + unison/compound-wrappers) + + (provide ,@names) + + ,@tylinks + + ,@defs))) + +(define (add-runtime-module mname tylinks tmlinks defs) + (eval (build-runtime-module mname tylinks tmlinks defs) + runtime-namespace)) (define (code-dependencies co) (chunked-list->list (group-term-dependencies (unison-code-rep co)))) -(define (unison-POp-CACH dfns0) +(define (add-runtime-code mname0 dfns0) (define (map-links dss) (map (lambda (ds) (map reference->termlink ds)) dss)) (let ([udefs (chunked-list->list dfns0)]) (cond [(not (null? udefs)) - (let* ([links (map ufst udefs)] - [refs (map termlink->reference links)] - [depss (map (compose code-dependencies usnd) udefs)] + (let* ([tmlinks (map ufst udefs)] + [codes (map usnd udefs)] + [refs (map termlink->reference tmlinks)] + [depss (map code-dependencies codes)] + [tylinks (gen-typelinks codes)] [deps (flatten depss)] [fdeps (filter need-dependency? deps)] [rdeps (remove* refs fdeps)]) (cond - [(null? fdeps) (sum 0 '())] + [(null? fdeps) #f] [(null? rdeps) - (let ([sdefs (flatten (map gen-code udefs))] - [mname (generate-module-name links)]) - (expand-sandbox links (map-links depss)) + (let ([ndefs (map gen-code udefs)] [sdefs (flatten (map gen-code udefs))] + [mname (or mname0 (generate-module-name tmlinks))]) + (expand-sandbox tmlinks (map-links depss)) (register-code udefs) - (add-module-associations links mname) - (add-runtime-module mname links sdefs) - (sum 0 '()))] - [else - (sum 1 (list->chunked-list rdeps))]))] - [else (sum 0 '())]))) + (add-module-associations tmlinks mname) + (add-runtime-module mname tylinks tmlinks sdefs) + #f)] + [else (list->chunked-list rdeps)]))] + [else #f]))) + +(define (unison-POp-CACH dfns0) + (let ([result (add-runtime-code #f dfns0)]) + (if result + (sum 1 result) + (sum 0 '())))) (define (unison-POp-LOAD v0) (let* ([val (unison-quote-val v0)] diff --git a/unison-cli/src/Unison/Cli/Monad.hs b/unison-cli/src/Unison/Cli/Monad.hs index 3a61e6407a..404bdf45b0 100644 --- a/unison-cli/src/Unison/Cli/Monad.hs +++ b/unison-cli/src/Unison/Cli/Monad.hs @@ -164,6 +164,7 @@ data Env = Env notifyNumbered :: NumberedOutput -> IO NumberedArgs, runtime :: Runtime Symbol, sandboxedRuntime :: Runtime Symbol, + nativeRuntime :: Runtime Symbol, serverBaseUrl :: Maybe Server.BaseUrl, ucmVersion :: UCMVersion } diff --git a/unison-cli/src/Unison/Codebase/Editor/HandleInput.hs b/unison-cli/src/Unison/Codebase/Editor/HandleInput.hs index 724e31725a..5d8228d046 100644 --- a/unison-cli/src/Unison/Codebase/Editor/HandleInput.hs +++ b/unison-cli/src/Unison/Codebase/Editor/HandleInput.hs @@ -1092,34 +1092,12 @@ loop e = do scopePath <- Cli.resolvePath' scopePath' updated <- propagatePatch description patch scopePath when (not updated) (Cli.respond $ NothingToPatch patchPath scopePath') - ExecuteI main args -> do - (unisonFile, mainResType) <- do - (sym, term, typ, otyp) <- getTerm main - uf <- createWatcherFile sym term typ - pure (uf, otyp) - ppe <- executePPE unisonFile - (_, xs) <- evalUnisonFile False ppe unisonFile args - mainRes :: Term Symbol () <- - let bonk (_, (_ann, watchKind, _id, _term0, term1, _isCacheHit)) = (watchKind, term1) - in case lookup magicMainWatcherString (map bonk (Map.toList xs)) of - Nothing -> - error - ( "impossible: we manually added the watcher " - <> show magicMainWatcherString - <> " with 'createWatcherFile', but it isn't here." - ) - Just x -> pure (stripUnisonFileReferences unisonFile x) - #lastRunResult .= Just (Term.amap (\() -> External) mainRes, mainResType, unisonFile) - Cli.respond (RunResult ppe mainRes) - MakeStandaloneI output main -> do - Cli.Env {codebase, runtime} <- ask - (ref, ppe) <- resolveMainRef main - let codeLookup = () <$ Codebase.toCodeLookup codebase - whenJustM (liftIO (Runtime.compileTo runtime codeLookup ppe ref (output <> ".uc"))) \err -> - Cli.returnEarly (EvaluationFailure err) + ExecuteI main args -> doExecute False main args + MakeStandaloneI output main -> doCompile False output main CompileSchemeI output main -> doCompileScheme output main ExecuteSchemeI main args -> doRunAsScheme main args - GenSchemeLibsI -> doGenerateSchemeBoot True Nothing + GenSchemeLibsI mdir -> + doGenerateSchemeBoot True Nothing mdir FetchSchemeCompilerI name branch -> doFetchCompiler name branch IOTestI main -> Tests.handleIOTest main @@ -1313,7 +1291,7 @@ loadUnisonFile sourceName text = do pped <- prettyPrintEnvDecl names let ppe = PPE.suffixifiedPPE pped Cli.respond $ Typechecked sourceName ppe sr unisonFile - (bindings, e) <- evalUnisonFile False ppe unisonFile [] + (bindings, e) <- evalUnisonFile Permissive ppe unisonFile [] let e' = Map.map go e go (ann, kind, _hash, _uneval, eval, isHit) = (ann, kind, eval, isHit) when (not (null e')) do @@ -1514,13 +1492,11 @@ inputDescription input = MergeIOBuiltinsI -> pure "builtins.mergeio" MakeStandaloneI out nm -> pure ("compile " <> Text.pack out <> " " <> HQ.toText nm) ExecuteSchemeI nm args -> - pure $ - "run.native " - <> HQ.toText nm - <> " " - <> Text.unwords (fmap Text.pack args) + pure $ "run.native " <> Text.unwords (fmap Text.pack (nm : args)) CompileSchemeI fi nm -> pure ("compile.native " <> HQ.toText nm <> " " <> Text.pack fi) - GenSchemeLibsI -> pure "compile.native.genlibs" + GenSchemeLibsI mdir -> + pure $ + "compile.native.genlibs" <> Text.pack (maybe "" (" " ++) mdir) FetchSchemeCompilerI name branch -> pure ("compile.native.fetch" <> Text.pack name <> " " <> Text.pack branch) CreateAuthorI (NameSegment id) name -> pure ("create.author " <> id <> " " <> name) @@ -2318,10 +2294,11 @@ getSchemeStaticLibDir = liftIO $ getXdgDirectory XdgData ("unisonlanguage" "scheme-libs") -doGenerateSchemeBoot :: Bool -> Maybe PPE.PrettyPrintEnv -> Cli () -doGenerateSchemeBoot force mppe = do +doGenerateSchemeBoot :: + Bool -> Maybe PPE.PrettyPrintEnv -> Maybe String -> Cli () +doGenerateSchemeBoot force mppe mdir = do ppe <- maybe basicPPE pure mppe - dir <- getSchemeGenLibDir + dir <- maybe getSchemeGenLibDir pure mdir let bootf = dir "unison" "boot-generated.ss" swrapf = dir "unison" "simple-wrappers.ss" binf = dir "unison" "builtin-generated.ss" @@ -2437,10 +2414,53 @@ buildRacket genDir statDir main file = (True <$ callProcess "racket" opts) (\(_ :: IOException) -> pure False) -doRunAsScheme :: HQ.HashQualified Name -> [String] -> Cli () -doRunAsScheme main args = do - fullpath <- generateSchemeFile True (HQ.toString main) main - runScheme fullpath args +doExecute :: Bool -> String -> [String] -> Cli () +doExecute native main args = do + (unisonFile, mainResType) <- do + (sym, term, typ, otyp) <- getTerm main + uf <- createWatcherFile sym term typ + pure (uf, otyp) + ppe <- executePPE unisonFile + let mode | native = Native | otherwise = Permissive + (_, xs) <- evalUnisonFile mode ppe unisonFile args + mainRes :: Term Symbol () <- + case lookup magicMainWatcherString (map bonk (Map.toList xs)) of + Nothing -> + error + ( "impossible: we manually added the watcher " + <> show magicMainWatcherString + <> " with 'createWatcherFile', but it isn't here." + ) + Just x -> pure (stripUnisonFileReferences unisonFile x) + #lastRunResult .= Just (Term.amap (\() -> External) mainRes, mainResType, unisonFile) + Cli.respond (RunResult ppe mainRes) + where + bonk (_, (_ann, watchKind, _id, _term0, term1, _isCacheHit)) = + (watchKind, term1) + +doCompile :: Bool -> String -> HQ.HashQualified Name -> Cli () +doCompile native output main = do + Cli.Env {codebase, runtime, nativeRuntime} <- ask + let theRuntime + | native = nativeRuntime + | otherwise = runtime + (ref, ppe) <- resolveMainRef main + let codeLookup = () <$ Codebase.toCodeLookup codebase + outf + | native = output + | otherwise = output <> ".uc" + whenJustM + ( liftIO $ + Runtime.compileTo theRuntime codeLookup ppe ref outf + ) + (Cli.returnEarly . EvaluationFailure) + +doRunAsScheme :: String -> [String] -> Cli () +doRunAsScheme main0 args = case HQ.fromString main0 of + Just main -> do + fullpath <- generateSchemeFile True main0 main + runScheme fullpath args + Nothing -> Cli.respond $ BadName main0 doCompileScheme :: String -> HQ.HashQualified Name -> Cli () doCompileScheme out main = @@ -2450,7 +2470,7 @@ generateSchemeFile :: Bool -> String -> HQ.HashQualified Name -> Cli String generateSchemeFile exec out main = do (comp, ppe) <- resolveMainRef main ensureCompilerExists - doGenerateSchemeBoot False $ Just ppe + doGenerateSchemeBoot False (Just ppe) Nothing cacheDir <- getCacheDir liftIO $ createDirectoryIfMissing True (cacheDir "scheme-tmp") let scratch = out ++ ".scm" @@ -2627,7 +2647,7 @@ displayI prettyPrintNames outputLoc hq = do doDisplay outputLoc parseNames (Term.unannotate tm) Just (toDisplay, unisonFile) -> do ppe <- PPE.biasTo bias <$> executePPE unisonFile - (_, watches) <- evalUnisonFile True ppe unisonFile [] + (_, watches) <- evalUnisonFile Sandboxed ppe unisonFile [] (_, _, _, _, tm, _) <- Map.lookup toDisplay watches & onNothing (error $ "Evaluation dropped a watch expression: " <> HQ.toString hq) ns <- displayNames unisonFile @@ -2976,6 +2996,8 @@ synthesizeForce typeOfFunc = do ) Identity (Just typ, _) -> typ +data EvalMode = Sandboxed | Permissive | Native + -- | Evaluate all watched expressions in a UnisonFile and return -- their results, keyed by the name of the watch variable. The tuple returned -- has the form: @@ -2993,7 +3015,7 @@ synthesizeForce typeOfFunc = do -- `(hash, evaluatedTerm)` mapping to a cache to make future evaluations -- of the same watches instantaneous. evalUnisonFile :: - Bool -> + EvalMode -> PPE.PrettyPrintEnv -> TypecheckedUnisonFile Symbol Ann -> [String] -> @@ -3001,9 +3023,12 @@ evalUnisonFile :: ( [(Symbol, Term Symbol ())], Map Symbol (Ann, WK.WatchKind, Reference.Id, Term Symbol (), Term Symbol (), Bool) ) -evalUnisonFile sandbox ppe unisonFile args = do - Cli.Env {codebase, runtime, sandboxedRuntime} <- ask - let theRuntime = if sandbox then sandboxedRuntime else runtime +evalUnisonFile mode ppe unisonFile args = do + Cli.Env {codebase, runtime, sandboxedRuntime, nativeRuntime} <- ask + let theRuntime = case mode of + Sandboxed -> sandboxedRuntime + Permissive -> runtime + Native -> nativeRuntime let watchCache :: Reference.Id -> IO (Maybe (Term Symbol ())) watchCache ref = do diff --git a/unison-cli/src/Unison/Codebase/Editor/Input.hs b/unison-cli/src/Unison/Codebase/Editor/Input.hs index 071e780bf4..f3e9666a9c 100644 --- a/unison-cli/src/Unison/Codebase/Editor/Input.hs +++ b/unison-cli/src/Unison/Codebase/Editor/Input.hs @@ -177,11 +177,11 @@ data Input | -- make a standalone binary file MakeStandaloneI String (HQ.HashQualified Name) | -- execute an IO thunk using scheme - ExecuteSchemeI (HQ.HashQualified Name) [String] + ExecuteSchemeI String [String] | -- compile to a scheme file CompileSchemeI String (HQ.HashQualified Name) - | -- generate scheme libraries - GenSchemeLibsI + | -- generate scheme libraries, optional target directory + GenSchemeLibsI (Maybe String) | -- fetch scheme compiler from a given username and branch FetchSchemeCompilerI String String | TestI TestInput diff --git a/unison-cli/src/Unison/Codebase/TranscriptParser.hs b/unison-cli/src/Unison/Codebase/TranscriptParser.hs index b03c8f80d2..e33934d1e4 100644 --- a/unison-cli/src/Unison/Codebase/TranscriptParser.hs +++ b/unison-cli/src/Unison/Codebase/TranscriptParser.hs @@ -201,19 +201,21 @@ withTranscriptRunner :: (TranscriptRunner -> m r) -> m r withTranscriptRunner verbosity ucmVersion configFile action = do - withRuntimes \runtime sbRuntime -> withConfig \config -> do + withRuntimes \runtime sbRuntime nRuntime -> withConfig \config -> do action \transcriptName transcriptSrc (codebaseDir, codebase) -> do Server.startServer (Backend.BackendEnv {Backend.useNamesIndex = False}) Server.defaultCodebaseServerOpts runtime codebase \baseUrl -> do let parsed = parse transcriptName transcriptSrc result <- for parsed \stanzas -> do - liftIO $ run verbosity codebaseDir stanzas codebase runtime sbRuntime config ucmVersion (tShow baseUrl) + liftIO $ run verbosity codebaseDir stanzas codebase runtime sbRuntime nRuntime config ucmVersion (tShow baseUrl) pure $ join @(Either TranscriptError) result where - withRuntimes :: ((Runtime.Runtime Symbol -> Runtime.Runtime Symbol -> m a) -> m a) + withRuntimes :: + (Runtime.Runtime Symbol -> Runtime.Runtime Symbol -> Runtime.Runtime Symbol -> m a) -> m a withRuntimes action = RTI.withRuntime False RTI.Persistent ucmVersion \runtime -> do RTI.withRuntime True RTI.Persistent ucmVersion \sbRuntime -> do action runtime sbRuntime + =<< liftIO (RTI.startNativeRuntime ucmVersion) withConfig :: forall a. ((Maybe Config -> m a) -> m a) withConfig action = do case configFile of @@ -235,11 +237,12 @@ run :: Codebase IO Symbol Ann -> Runtime.Runtime Symbol -> Runtime.Runtime Symbol -> + Runtime.Runtime Symbol -> Maybe Config -> UCMVersion -> Text -> IO (Either TranscriptError Text) -run verbosity dir stanzas codebase runtime sbRuntime config ucmVersion baseURL = UnliftIO.try $ Ki.scoped \scope -> do +run verbosity dir stanzas codebase runtime sbRuntime nRuntime config ucmVersion baseURL = UnliftIO.try $ Ki.scoped \scope -> do httpManager <- HTTP.newManager HTTP.defaultManagerSettings let initialPath = Path.absoluteEmpty unless (isSilent verbosity) . putPrettyLn $ @@ -502,6 +505,7 @@ run verbosity dir stanzas codebase runtime sbRuntime config ucmVersion baseURL = notifyNumbered = printNumbered, runtime, sandboxedRuntime = sbRuntime, + nativeRuntime = nRuntime, serverBaseUrl = Nothing, ucmVersion } diff --git a/unison-cli/src/Unison/CommandLine/InputPatterns.hs b/unison-cli/src/Unison/CommandLine/InputPatterns.hs index 71e1737036..cc63fa2ce1 100644 --- a/unison-cli/src/Unison/CommandLine/InputPatterns.hs +++ b/unison-cli/src/Unison/CommandLine/InputPatterns.hs @@ -2412,8 +2412,7 @@ runScheme = ] ) ( \case - (main : args) -> - flip Input.ExecuteSchemeI args <$> parseHashQualifiedName main + (main : args) -> Right $ Input.ExecuteSchemeI main args _ -> Left $ showPatternHelp runScheme ) @@ -2444,9 +2443,9 @@ schemeLibgen = "compile.native.genlibs" [] I.Visible - [] + [(Optional, noCompletionsArg)] ( P.wrapColumn2 - [ ( makeExample schemeLibgen [], + [ ( makeExample schemeLibgen ["[targetDir]"], "Generates libraries necessary for scheme compilation.\n\n\ \There is no need to run this before" <> P.group (makeExample compileScheme []) @@ -2460,7 +2459,8 @@ schemeLibgen = ] ) ( \case - [] -> pure Input.GenSchemeLibsI + [] -> pure $ Input.GenSchemeLibsI Nothing + [dir] -> pure . Input.GenSchemeLibsI $ Just dir _ -> Left $ showPatternHelp schemeLibgen ) diff --git a/unison-cli/src/Unison/CommandLine/Main.hs b/unison-cli/src/Unison/CommandLine/Main.hs index 4d51f11091..4453ab5add 100644 --- a/unison-cli/src/Unison/CommandLine/Main.hs +++ b/unison-cli/src/Unison/CommandLine/Main.hs @@ -119,6 +119,7 @@ main :: [Either Event Input] -> Runtime.Runtime Symbol -> Runtime.Runtime Symbol -> + Runtime.Runtime Symbol -> Codebase IO Symbol Ann -> Maybe Server.BaseUrl -> UCMVersion -> @@ -126,7 +127,7 @@ main :: (Path.Absolute -> STM ()) -> ShouldWatchFiles -> IO () -main dir welcome initialPath config initialInputs runtime sbRuntime codebase serverBaseUrl ucmVersion notifyBranchChange notifyPathChange shouldWatchFiles = Ki.scoped \scope -> do +main dir welcome initialPath config initialInputs runtime sbRuntime nRuntime codebase serverBaseUrl ucmVersion notifyBranchChange notifyPathChange shouldWatchFiles = Ki.scoped \scope -> do rootVar <- newEmptyTMVarIO initialRootCausalHash <- Codebase.runTransaction codebase Operations.expectRootCausalHash _ <- Ki.fork scope $ do @@ -232,6 +233,7 @@ main dir welcome initialPath config initialInputs runtime sbRuntime codebase ser in putPrettyNonempty p $> args, runtime, sandboxedRuntime = sbRuntime, + nativeRuntime = nRuntime, serverBaseUrl, ucmVersion } diff --git a/unison-cli/src/Unison/JitInfo.hs b/unison-cli/src/Unison/JitInfo.hs index dfa7a52cd4..a0e429c333 100644 --- a/unison-cli/src/Unison/JitInfo.hs +++ b/unison-cli/src/Unison/JitInfo.hs @@ -1,4 +1,4 @@ module Unison.JitInfo (currentRelease) where currentRelease :: String -currentRelease = "releases/0.0.9" +currentRelease = "releases/0.0.10" diff --git a/unison-cli/unison/Main.hs b/unison-cli/unison/Main.hs index d439e256f6..0eac4d13d5 100644 --- a/unison-cli/unison/Main.hs +++ b/unison-cli/unison/Main.hs @@ -85,6 +85,9 @@ import UnliftIO qualified import UnliftIO.Directory (getHomeDirectory) import Version qualified +type Runtimes = + (RTI.Runtime Symbol, RTI.Runtime Symbol, RTI.Runtime Symbol) + main :: IO () main = withCP65001 . runInUnboundThread . Ki.scoped $ \scope -> do -- Replace the default exception handler with one that pretty-prints. @@ -128,7 +131,7 @@ main = withCP65001 . runInUnboundThread . Ki.scoped $ \scope -> do Left _ -> exitError "I couldn't find that file or it is for some reason unreadable." Right contents -> do getCodebaseOrExit mCodePathOption (SC.MigrateAutomatically SC.Backup SC.Vacuum) \(initRes, _, theCodebase) -> do - withRuntimes RTI.OneOff \(rt, sbrt) -> do + withRuntimes RTI.OneOff \(rt, sbrt, nrt) -> do let fileEvent = Input.UnisonFileChanged (Text.pack file) contents let noOpRootNotifier _ = pure () let noOpPathNotifier _ = pure () @@ -139,6 +142,7 @@ main = withCP65001 . runInUnboundThread . Ki.scoped $ \scope -> do config rt sbrt + nrt theCodebase [Left fileEvent, Right $ Input.ExecuteI mainName args, Right Input.QuitI] serverUrl @@ -153,7 +157,7 @@ main = withCP65001 . runInUnboundThread . Ki.scoped $ \scope -> do Left _ -> exitError "I had trouble reading this input." Right contents -> do getCodebaseOrExit mCodePathOption (SC.MigrateAutomatically SC.Backup SC.Vacuum) \(initRes, _, theCodebase) -> do - withRuntimes RTI.OneOff \(rt, sbrt) -> do + withRuntimes RTI.OneOff \(rt, sbrt, nrt) -> do let fileEvent = Input.UnisonFileChanged (Text.pack "") contents let noOpRootNotifier _ = pure () let noOpPathNotifier _ = pure () @@ -164,6 +168,7 @@ main = withCP65001 . runInUnboundThread . Ki.scoped $ \scope -> do config rt sbrt + nrt theCodebase [Left fileEvent, Right $ Input.ExecuteI mainName args, Right Input.QuitI] serverUrl @@ -243,7 +248,7 @@ main = withCP65001 . runInUnboundThread . Ki.scoped $ \scope -> do Just fp -> recordRtsStats fp action Launch isHeadless codebaseServerOpts mayStartingPath shouldWatchFiles -> do getCodebaseOrExit mCodePathOption (SC.MigrateAfterPrompt SC.Backup SC.Vacuum) \(initRes, _, theCodebase) -> do - withRuntimes RTI.Persistent \(runtime, sbRuntime) -> do + withRuntimes RTI.Persistent \(runtime, sbRuntime, nRuntime) -> do startingPath <- case isHeadless of WithCLI -> do -- If the user didn't provide a starting path on the command line, put them in the most recent @@ -298,6 +303,7 @@ main = withCP65001 . runInUnboundThread . Ki.scoped $ \scope -> do config runtime sbRuntime + nRuntime theCodebase [] (Just baseUrl) @@ -309,11 +315,12 @@ main = withCP65001 . runInUnboundThread . Ki.scoped $ \scope -> do Exit -> do Exit.exitSuccess where -- (runtime, sandboxed runtime) - withRuntimes :: RTI.RuntimeHost -> ((RTI.Runtime Symbol, RTI.Runtime Symbol) -> IO a) -> IO a + withRuntimes :: RTI.RuntimeHost -> (Runtimes -> IO a) -> IO a withRuntimes mode action = RTI.withRuntime False mode Version.gitDescribeWithDate \runtime -> do - RTI.withRuntime True mode Version.gitDescribeWithDate \sbRuntime -> do - action (runtime, sbRuntime) + RTI.withRuntime True mode Version.gitDescribeWithDate \sbRuntime -> + action . (runtime, sbRuntime,) + =<< RTI.startNativeRuntime Version.gitDescribeWithDate withConfig :: Maybe CodebasePathOption -> (Config -> IO a) -> IO a withConfig mCodePathOption action = do UnliftIO.bracket @@ -469,6 +476,7 @@ launch :: Config -> Rt.Runtime Symbol -> Rt.Runtime Symbol -> + Rt.Runtime Symbol -> Codebase.Codebase IO Symbol Ann -> [Either Input.Event Input.Input] -> Maybe Server.BaseUrl -> @@ -478,7 +486,7 @@ launch :: (Path.Absolute -> STM ()) -> CommandLine.ShouldWatchFiles -> IO () -launch dir config runtime sbRuntime codebase inputs serverBaseUrl mayStartingPath initResult notifyRootChange notifyPathChange shouldWatchFiles = do +launch dir config runtime sbRuntime nRuntime codebase inputs serverBaseUrl mayStartingPath initResult notifyRootChange notifyPathChange shouldWatchFiles = do showWelcomeHint <- Codebase.runTransaction codebase Queries.doProjectsExist let isNewCodebase = case initResult of CreatedCodebase -> NewlyCreatedCodebase @@ -493,6 +501,7 @@ launch dir config runtime sbRuntime codebase inputs serverBaseUrl mayStartingPat inputs runtime sbRuntime + nRuntime codebase serverBaseUrl ucmVersion diff --git a/unison-src/builtin-tests/sandbox-tests.u b/unison-src/builtin-tests/sandbox-tests.u index 97b83a9b42..94983a0df7 100644 --- a/unison-src/builtin-tests/sandbox-tests.u +++ b/unison-src/builtin-tests/sandbox-tests.u @@ -26,7 +26,7 @@ sandbox.directory = sandbox.file = FilePath (directory ++ "case-04.v4.ser") sandbox.open1 = do - _ = FilePath.open + _ = FilePath.open (FilePath "hello") () sandbox.open2 = do