mirror of
https://github.com/unisonweb/unison.git
synced 2024-10-05 06:07:21 +03:00
Merge branch 'cp/causal-name-lookup-index' into cp/remove-old-name-lookups
This commit is contained in:
commit
106af7fdd2
@ -42,6 +42,8 @@ If these instructions don't work for you or are incomplete, please file an issue
|
||||
|
||||
The build uses [Stack](http://docs.haskellstack.org/). If you don't already have it installed, [follow the install instructions](http://docs.haskellstack.org/en/stable/README.html#how-to-install) for your platform. (Hint: `brew update && brew install stack`)
|
||||
|
||||
If you have not set up the Haskell toolchain before and are trying to contribute to Unison on an M1 Mac, we have [some tips specifically for you](docs/m1-mac-setup-tips.markdown/new).
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/unisonweb/unison.git
|
||||
$ cd unison
|
||||
@ -49,7 +51,7 @@ $ stack --version # we'll want to know this version if you run into trouble
|
||||
$ stack build --fast --test && stack exec unison
|
||||
```
|
||||
|
||||
To run the Unison Local UI while building from source, you can use the `/dev-ui-install.sh` script. It will download the latest release of [unison-local-ui](https://github.com/unisonweb/unison-local-ui) and put it in the expected location for the unison executable created by `stack build`. When you start unison, you'll see a url where Unison Local UI is running.
|
||||
To run the Unison Local UI while building from source, you can use the `/dev-ui-install.sh` script. It will download the latest release of [unison-local-ui](https://github.com/unisonweb/unison-local-ui) and put it in the expected location for the unison executable created by `stack build`. When you start unison, you'll see a url where Unison Local UI is running.
|
||||
|
||||
See [`development.markdown`](development.markdown) for a list of build commands you'll likely use during development.
|
||||
|
||||
@ -61,7 +63,7 @@ View Language Server setup instructions [here](docs/language-server.markdown).
|
||||
Codebase Server
|
||||
---------------
|
||||
|
||||
When `ucm` starts it starts a Codebase web server that is used by the
|
||||
When `ucm` starts it starts a Codebase web server that is used by the
|
||||
[Unison Local UI](https://github.com/unisonweb/unison-local-ui). It selects a random
|
||||
port and a unique token that must be used when starting the UI to correctly
|
||||
connect to the server.
|
||||
|
@ -24,10 +24,11 @@ denoted by `$CUSTOM`, then the compiler commands will look in:
|
||||
for the `unison/` directory containing the library files.
|
||||
|
||||
The compiler commands also expect Chez Scheme to be installed
|
||||
separately, and for `scheme` to be callable on the user's path. For
|
||||
information on how to install, see:
|
||||
separately, and for `scheme` to be callable on the user's path. The
|
||||
continuation library now makes use of features in the Racket fork of
|
||||
Chez. For information on how to install, see:
|
||||
|
||||
https://github.com/cisco/ChezScheme/blob/main/BUILDING
|
||||
https://github.com/racket/ChezScheme/blob/master/BUILDING
|
||||
|
||||
For more information on Chez Scheme in general, see:
|
||||
|
||||
|
@ -1,47 +1,259 @@
|
||||
; This library is intended to contain the implementation of
|
||||
; delimited continuations used in the semantics of abilities.
|
||||
;
|
||||
; Currently, it is a somewhat naive implementation based on call/cc.
|
||||
; This has known issues that seem to still be in force even though a
|
||||
; tweak has been applied that should fix certain space leaks. So, in
|
||||
; the future it will likely need to be rewritten using some
|
||||
; implementation specific machinery (possibly making use of
|
||||
; continuation attachments as in the Racket implementation).
|
||||
;
|
||||
; Also, although the API includes prompts, they are currently ignored
|
||||
; in `control` and `prompt` always uses the same prompt (0). This
|
||||
; means that nesting handlers will not work in general, since requests
|
||||
; will not be able to jump over an inner handler of unrelated
|
||||
; abilities. It should be sufficient for testing simple examples in
|
||||
; the mean time, though.
|
||||
|
||||
(library (unison cont)
|
||||
(export prompt control)
|
||||
(export
|
||||
prompt
|
||||
control)
|
||||
|
||||
(import (chezscheme))
|
||||
(import (chezscheme)
|
||||
(unison core))
|
||||
|
||||
(define mk (lambda (x) (raise "fell off end")))
|
||||
; This implementation is based on the implementation of delimited
|
||||
; continuations used in racket, and makes use of primitives added in
|
||||
; the racket fork of chez scheme.
|
||||
;
|
||||
; The overall idea is to keep track of a meta-continuation that is
|
||||
; made up of a series of captured native continuations. The native
|
||||
; continuations make part of the frames of the meta-continuation,
|
||||
; and these frames can be labeled with prompts to support
|
||||
; multi-prompt delimited continuations. The native 'current
|
||||
; continuation' makes up the portion of the meta-continuation below
|
||||
; the nearest prompt.
|
||||
;
|
||||
; The specific racket-chez feature used is #%$call-in-continuation
|
||||
; which does not seem to be available in the upstream chez. This is
|
||||
; an important feature to have, because the mechanism for obtaining
|
||||
; the native continuation in chez is call/cc, which leaves the
|
||||
; native continuation in place. However, when we capture the native
|
||||
; continuation to push it onto a frame of the meta-continuation, it
|
||||
; may actually be completely eliminated from the implicit
|
||||
; continuation, because we will only ever return to it by popping
|
||||
; the corresponding frame of the meta=continuation.
|
||||
;
|
||||
; Failure to truncate the native continuation can lead to space
|
||||
; leaks due to growing unreachable portions of it. The racket-chez
|
||||
; feature allows us to instead repeatedly replace the implicit
|
||||
; continuation with #%$null-continuation, which avoids the leak.
|
||||
(define-virtual-register meta-continuation '())
|
||||
|
||||
; A record type representing continuation prompts.
|
||||
;
|
||||
; By comparing these records for pointer equality, we can make up
|
||||
; fresh prompts whenever needed, without having to keep track of
|
||||
; some sort of supply of prompts.
|
||||
(define-record-type continuation-prompt
|
||||
(fields (immutable name)))
|
||||
|
||||
; A frame of the meta-continuation consists of:
|
||||
; 1. A prompt delimiting the portion of the meta-continuation in
|
||||
; front of it.
|
||||
; 2. A native continuation to resume when re-entering the given
|
||||
; frame.
|
||||
(define-record-type meta-frame
|
||||
(fields
|
||||
(immutable prompt)
|
||||
(immutable resume-k)))
|
||||
|
||||
; A convenient abbreviation for grabbing the continuation.
|
||||
(define-syntax let/cc
|
||||
(syntax-rules ()
|
||||
[(let/cc k e ...)
|
||||
(identifier? #'k)
|
||||
(call/cc (lambda (k) e ...))]))
|
||||
|
||||
; A wrapper around primitive operations for truncating the implicit
|
||||
; continuation. `h` should be a nullary procedure that we want to
|
||||
; execute in an empty continuation.
|
||||
(define (call-in-empty-frame h)
|
||||
(($primitive $call-in-continuation)
|
||||
($primitive $null-continuation)
|
||||
'() ; marks
|
||||
h))
|
||||
|
||||
; Removes and returns the top frame of the meta-continuation.
|
||||
;
|
||||
; Note: this procedure assumes that the meta-continuation has
|
||||
; already been checked for emptiness, and does no checking of its
|
||||
; own.
|
||||
(define (pop-frame!)
|
||||
(let ([mf (car meta-continuation)])
|
||||
(set! meta-continuation (cdr meta-continuation))
|
||||
mf))
|
||||
|
||||
; Adds a frame to the top of the meta-continuation.
|
||||
(define (push-frame! fm)
|
||||
(set! meta-continuation (cons fm meta-continuation)))
|
||||
|
||||
; Handles returning values up the meta-continuation.
|
||||
;
|
||||
; Note: when we replace the native continuation with the null
|
||||
; continuation, for reasons mentioned above, it's important that the
|
||||
; things we run in that null continuation actually call this to
|
||||
; return up the meta-continuation. Otherwise we will _actually_
|
||||
; return to the null continuation, which causes a crash.
|
||||
(define (yield-to-meta-continuation results)
|
||||
(cond
|
||||
[(null? meta-continuation)
|
||||
(display "falling off end\n")
|
||||
results]
|
||||
[else
|
||||
(let ([mf (pop-frame!)])
|
||||
(($primitive $call-in-continuation)
|
||||
(meta-frame-resume-k mf)
|
||||
'()
|
||||
(lambda ()
|
||||
(if (and (pair? results) (null? (cdr results)))
|
||||
(car results)
|
||||
(apply values results)))))]))
|
||||
|
||||
; This operation corresponds roughly to `reset` in shift/reset
|
||||
; delimited control. It calls (h p) in a context delimited by
|
||||
; the prompt p.
|
||||
;
|
||||
; This is something of a helper function, as the actual `prompt`
|
||||
; implementation will involve making up a fresh `p`. However,
|
||||
; this common code is useful for test cases using only single
|
||||
; prompt continuations.
|
||||
;
|
||||
; Mechanically, what this does is capture the current native
|
||||
; continuation, push it on the meta-continuation with the specified
|
||||
; prompt attached, and call (h p) in an empty native continuation.
|
||||
(define (call-delimited-with-prompt p h)
|
||||
(let/cc k
|
||||
(call-in-empty-frame
|
||||
(lambda ()
|
||||
(let-values
|
||||
([results
|
||||
(let ([fm (make-meta-frame p k)])
|
||||
(push-frame! fm)
|
||||
(h p))])
|
||||
(yield-to-meta-continuation results))))))
|
||||
|
||||
; Implements prompt for our multi-prompt prompt/control calculus.
|
||||
;
|
||||
; `prompt` makes up a fresh prompt value, and runs its body
|
||||
; delimited with that value, e.g.:
|
||||
;
|
||||
; (prompt p ...)
|
||||
;
|
||||
; where `p` is a binding for the prompt value. The above is
|
||||
; syntactic sugar for something like:
|
||||
;
|
||||
; (prompt-impl (lambda (p) ...))
|
||||
(define (prompt-impl h)
|
||||
((call/cc
|
||||
(lambda (k)
|
||||
(let ([ok mk])
|
||||
(set! mk (lambda (x) (set! mk ok) (k x)))
|
||||
; (h 0) <-- prompt = 0
|
||||
(mk (let ([v (h 0)]) (lambda () v))))))))
|
||||
(let ([p (make-continuation-prompt 'prompt)])
|
||||
(call-delimited-with-prompt p h)))
|
||||
|
||||
; The nicer syntactic form for the above prompt implementation.
|
||||
(define-syntax prompt
|
||||
(syntax-rules ()
|
||||
[(prompt p e ...)
|
||||
(prompt-impl (lambda (p) e ...))]))
|
||||
|
||||
(define (control-impl h)
|
||||
(call/cc
|
||||
(lambda (k)
|
||||
(let* ([g (lambda () (prompt p (h k)))])
|
||||
(mk g)))))
|
||||
; Removes the prompt from the first frame of a meta-continuation.
|
||||
(define (strip-prompt mc)
|
||||
(let ([mf (car mc)])
|
||||
(cons (make-meta-frame #f (meta-frame-resume-k mf)) (cdr mc))))
|
||||
|
||||
; This funcion is used to reinstate a captured continuation. It
|
||||
; should be called with:
|
||||
;
|
||||
; k - a native continuation to be pushed before the captured
|
||||
; meta-continuation
|
||||
; cc - the captured meta-continuation segment
|
||||
; p - a prompt that should delimit cc
|
||||
;
|
||||
; `p` is used as the prompt value of the `k` frame, so shift/reset
|
||||
; can be implemented by passing the same `p` that was used when `cc`
|
||||
; was captured (as that means that any further `p` control effects
|
||||
; in `cc` do not escape their original scope).
|
||||
;
|
||||
; However, we will usually be calling with p = #f, since shallow
|
||||
; handlers correspond to control effects that are able to eliminate
|
||||
; prompts.
|
||||
;
|
||||
; Note: the captured continuation `cc` is assumed to be in reverse
|
||||
; order, so will be reversed back onto the meta-continuation.
|
||||
(define (push-to-meta-continuation k cc p)
|
||||
(push-frame! (make-meta-frame p k))
|
||||
(let rec ([cc cc])
|
||||
(cond
|
||||
[(null? cc) #f]
|
||||
[else
|
||||
(push-frame! (car cc))
|
||||
(rec (cdr cc))])))
|
||||
|
||||
; Wraps a captured continuation with a procedure that reinstates it
|
||||
; upon invocation. This should be called with:
|
||||
;
|
||||
; ok - the captured native continuation that was captured along
|
||||
; with...
|
||||
; cc - the split meta-continuation
|
||||
; p - a prompt associated with the captured continuation. This
|
||||
; will be installed as a delimiter when the captured
|
||||
; continuation is re-pushed. If no delimiting is desired,
|
||||
; simply use #f, or some dummy prompt that will not be
|
||||
; involved in actual control flow.
|
||||
;
|
||||
; Note: the captured continuation `cc` is assumed to be in reverse
|
||||
; order, so will be reversed back onto the meta-continuation.
|
||||
(define (make-callable-continuation ok cc p)
|
||||
(lambda vals
|
||||
(let/cc nk
|
||||
(($primitive $call-in-continuation)
|
||||
ok
|
||||
'()
|
||||
(lambda ()
|
||||
push-to-meta-continuation nk cc p
|
||||
(apply values vals))))))
|
||||
|
||||
; Captures the meta-continuation up to the specified prompt. The
|
||||
; continuation is wrapped in a function that reinstates it when
|
||||
; called. The supplied 'body' `h` is then evaluated with the
|
||||
; captured continuation.
|
||||
;
|
||||
; This implementation is designed to support shallow ability
|
||||
; handlers. This means that we actually implement what would be
|
||||
; called (in delimited continuation literature) control0. This means
|
||||
; that:
|
||||
;
|
||||
; 1. The control operator _removes_ the prompt from the
|
||||
; meta-continuation. So any control effects referring to the
|
||||
; same prompt will only be delimited further up the
|
||||
; continuation.
|
||||
; 2. The procedure reinstating the captured continuation does not
|
||||
; install a delimiter, so said captured continuation is itself
|
||||
; a procedure that can have control effects relevant to the
|
||||
; original prompt.
|
||||
;
|
||||
; The reason for this is that shallow handlers are one-shot in a
|
||||
; corresponding way. They only handle the first effect in their
|
||||
; 'body', and handling _all_ relevant effects requires an explicitly
|
||||
; recursive handler that re-installs a handling delimiter after each
|
||||
; effect request.
|
||||
(define (control-impl p h)
|
||||
(assert (continuation-prompt? p))
|
||||
(let/cc k
|
||||
(let rec ([cc '()] [mc meta-continuation])
|
||||
(cond
|
||||
[(or (null? mc)
|
||||
(eq? p (meta-frame-prompt (car mc))))
|
||||
(set! meta-continuation (strip-prompt mc))
|
||||
(let ([ck (make-callable-continuation k cc #f)])
|
||||
(call-in-empty-frame
|
||||
(lambda ()
|
||||
(let-values ([results (h ck)])
|
||||
(yield-to-meta-continuation results)))))]
|
||||
[else (rec (cons (car mc) cc) (cdr mc))]))))
|
||||
|
||||
; The nicer syntactic form for the control operator.
|
||||
(define-syntax control
|
||||
(syntax-rules ()
|
||||
[(control p k e ...)
|
||||
(control-impl (lambda (k) e ...))])))
|
||||
(control-impl (lambda (k) e ...))]))
|
||||
|
||||
; TODO: generate this as part of the main program.
|
||||
; (define-init-registers init-regs)
|
||||
; (init-regs)
|
||||
)
|
||||
|
109
chez-libs/unison/crypto.ss
Normal file
109
chez-libs/unison/crypto.ss
Normal file
@ -0,0 +1,109 @@
|
||||
|
||||
(library (unison crypto)
|
||||
(export
|
||||
unison-FOp-crypto.HashAlgorithm.Sha1
|
||||
unison-FOp-crypto.hashBytes)
|
||||
|
||||
(import (chezscheme)
|
||||
(unison core)
|
||||
(unison string)
|
||||
(unison bytevector))
|
||||
|
||||
(define (capture-output fn)
|
||||
(parameterize ((current-output-port (open-output-string)))
|
||||
(fn)
|
||||
(get-output-string (current-output-port))))
|
||||
|
||||
; if loading the dynamic library is successful, returns true
|
||||
; otherwise, returns a lambda that will throw the original error
|
||||
; with some helpful messaging.
|
||||
(define try-load-shared (lambda (name message)
|
||||
(guard (x [else (lambda ()
|
||||
(printf "\n🚨🚨🚨 (crypto.ss) Unable to load shared library ~s 🚨🚨🚨\n---> ~a\n\nOriginal exception:\n" name message)
|
||||
(raise x)
|
||||
)])
|
||||
(load-shared-object name)
|
||||
#t)))
|
||||
|
||||
(define libcrypto (try-load-shared "libcrypto.3.dylib" "Do you have openssl installed?"))
|
||||
(define libb2 (try-load-shared "libb2.dylib" "Do you have libb2 installed?"))
|
||||
|
||||
; if the "source" library was loaded, call (fn), otherwise returns a lambda
|
||||
; that will throw the original source-library-loading exception when called.
|
||||
(define (if-loaded source fn)
|
||||
(case source
|
||||
(#t (fn))
|
||||
(else (lambda args (source)))))
|
||||
|
||||
(define EVP_Digest
|
||||
(if-loaded libcrypto (lambda () (foreign-procedure "EVP_Digest"
|
||||
(
|
||||
u8* ; input buffer
|
||||
unsigned-int ; length of input
|
||||
u8* ; output buffer
|
||||
boolean ; note: not a boolean, we just need to be able to pass NULL (0)
|
||||
void* ; the EVP_MD* pointer, which holds the digest algorithm
|
||||
boolean ; note: not a boolean, we just need to be able to pass NULL (0)
|
||||
)
|
||||
; 1 if success, 0 or -1 for failure
|
||||
int))))
|
||||
|
||||
(define digest (lambda (text kind bits)
|
||||
(let ([buffer (make-bytevector (/ bits 8))])
|
||||
(if (= 1 (EVP_Digest text (bytevector-length text) buffer #f kind #f))
|
||||
buffer
|
||||
(error "crypto.ss digest" "libssl was unable to hash the data for some reason")))))
|
||||
|
||||
(define EVP_sha1 (if-loaded libcrypto (lambda () (foreign-procedure "EVP_sha1" () void*))))
|
||||
(define EVP_sha256 (if-loaded libcrypto (lambda () (foreign-procedure "EVP_sha256" () void*))))
|
||||
(define EVP_sha512 (if-loaded libcrypto (lambda () (foreign-procedure "EVP_sha512" () void*))))
|
||||
(define EVP_sha3_256 (if-loaded libcrypto (lambda () (foreign-procedure "EVP_sha3_256" () void*))))
|
||||
(define EVP_sha3_512 (if-loaded libcrypto (lambda () (foreign-procedure "EVP_sha3_512" () void*))))
|
||||
|
||||
(define sha1 (lambda (text) (digest text (EVP_sha1) 160)))
|
||||
(define sha256 (lambda (text) (digest text (EVP_sha256) 256)))
|
||||
(define sha512 (lambda (text) (digest text (EVP_sha512) 512)))
|
||||
(define sha3_256 (lambda (text) (digest text (EVP_sha3_256) 256)))
|
||||
(define sha3_512 (lambda (text) (digest text (EVP_sha3_512) 512)))
|
||||
|
||||
(define blake2b-raw
|
||||
(if-loaded libb2 (lambda () (foreign-procedure "blake2b"
|
||||
(
|
||||
u8* ; output buffer
|
||||
string ; input buffer
|
||||
u8* ; input key
|
||||
int ; output length
|
||||
int ; input length
|
||||
int ; key length
|
||||
) int
|
||||
))))
|
||||
|
||||
(define blake2s-raw
|
||||
(if-loaded libb2 (lambda () (foreign-procedure "blake2s"
|
||||
(
|
||||
u8* ; output buffer
|
||||
string ; input buffer
|
||||
u8* ; input key
|
||||
int ; output length
|
||||
int ; input length
|
||||
int ; key length
|
||||
) int
|
||||
))))
|
||||
|
||||
(define blake2s (lambda (text size)
|
||||
(let ([buffer (make-bytevector (/ size 8))])
|
||||
(if (= 0 (blake2s-raw buffer text #f (/ size 8) (string-length text) 0))
|
||||
buffer
|
||||
(error "crypto.ss blake2s" "libb2 was unable to hash the data for some reason")))))
|
||||
|
||||
(define blake2b (lambda (text size)
|
||||
(let ([buffer (make-bytevector (/ size 8))])
|
||||
(if (= 0 (blake2b-raw buffer text #f (/ size 8) (string-length text) 0))
|
||||
buffer
|
||||
(error "crypto.ss blake2b" "libb2 was unable to hash the data for some reason")))))
|
||||
|
||||
(define (unison-FOp-crypto.HashAlgorithm.Sha1) sha1)
|
||||
(define (unison-FOp-crypto.hashBytes algo text)
|
||||
(algo text))
|
||||
|
||||
)
|
@ -101,13 +101,35 @@
|
||||
unison-POp-VALU
|
||||
unison-POp-VWLS
|
||||
|
||||
unison-POp-UPKB
|
||||
unison-POp-ADDI
|
||||
unison-POp-DIVI
|
||||
unison-POp-EQLI
|
||||
unison-POp-MODI
|
||||
unison-POp-LEQI
|
||||
unison-POp-POWN
|
||||
unison-POp-VWRS
|
||||
|
||||
unison-FOp-crypto.HashAlgorithm.Sha1
|
||||
unison-FOp-crypto.hashBytes
|
||||
)
|
||||
|
||||
(import (chezscheme)
|
||||
(unison core)
|
||||
(unison string)
|
||||
(unison crypto)
|
||||
(unison bytevector))
|
||||
|
||||
(define unison-POp-UPKB bytevector->u8-list)
|
||||
(define unison-POp-ADDI +)
|
||||
(define unison-POp-DIVI /)
|
||||
(define (unison-POp-EQLI a b)
|
||||
(if (= a b) 1 0)
|
||||
)
|
||||
(define unison-POp-MODI mod)
|
||||
(define unison-POp-LEQI <=)
|
||||
(define unison-POp-POWN expt)
|
||||
|
||||
(define (reify-exn thunk)
|
||||
(call/1cc
|
||||
(lambda (k)
|
||||
@ -145,11 +167,8 @@
|
||||
(define (unison-POp-FTOT f) (number->istring f))
|
||||
(define (unison-POp-IDXB n bs) (bytevector-u8-ref bs n))
|
||||
(define (unison-POp-IDXS n l)
|
||||
(call/1cc
|
||||
(lambda (k)
|
||||
(with-exception-handler
|
||||
(lambda (e) (list 0))
|
||||
(lambda () (list-ref l n))))))
|
||||
(guard (x [else (list 0)])
|
||||
(list 1 (list-ref l n))))
|
||||
(define (unison-POp-IORN m n) (fxlogior m n))
|
||||
(define (unison-POp-ITOT i) (signed-number->istring i))
|
||||
(define (unison-POp-LEQN m n) (if (fx<= m n) 1 0))
|
||||
@ -182,6 +201,12 @@
|
||||
(if (null? l)
|
||||
(list 0)
|
||||
(list 1 (car l) (cdr l))))
|
||||
(define (unison-POp-VWRS l)
|
||||
(if (null? l)
|
||||
(list 0)
|
||||
(let ([r (reverse l)])
|
||||
(list 1 (reverse (cdr l)) (car l)))))
|
||||
|
||||
(define (unison-POp-XORN m n) (fxxor m n))
|
||||
(define (unison-POp-VALU c) (decode-value c))
|
||||
|
||||
|
164
docs/m1-mac-setup-tips.markdown
Normal file
164
docs/m1-mac-setup-tips.markdown
Normal file
@ -0,0 +1,164 @@
|
||||
|
||||
# M1 Mac Haskell toolchain setup
|
||||
|
||||
If you are a newcomer to the Haskell ecosystem trying to set up your dev environment on a Mac M1 computer, welcome, you can do this! The tips in this document provide one way to get a working development setup, but are not the only path forward. If you haven't downloaded the Haskell toolchain before, our recommendation is to use GHCup. We've found that issues can arise if you mix ARM native binaries with x86 binaries to be run with Rosetta. If you're a veteran Haskell developer, much of this won't apply to you as it's likely you already have a working development environment.
|
||||
|
||||
Here is a working set of versions you can use to build the Unison executable:
|
||||
|
||||
GHC version: 8.10.7
|
||||
Stack version: 2.7.5
|
||||
Cabal version 3.6.2.0
|
||||
Haskell language server version: 1.7.0.0
|
||||
|
||||
The GHC version for the project can be confirmed by looking at the `resolver` key in this project's `stack.yaml`.
|
||||
|
||||
## Newcomer setup tips
|
||||
|
||||
[Install GHCup using the instructions on their website.](https://www.haskell.org/ghcup/) Once it's installed make sure `ghcup` is on your path.
|
||||
|
||||
```
|
||||
export PATH="$HOME/.ghcup/bin:$PATH"
|
||||
```
|
||||
|
||||
GHCup has a nice ui for setting Haskell toolchain versions for the project. Enter `ghcup tui` to open it up and follow the instructions for installing and setting the versions there. GHCup will try to download M1 native binaries for the versions given.
|
||||
|
||||
Check your clang version. For [hand-wavey reasons](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/301) we recommend you use llvm version 12. See troubleshooting note below about changing your LLVM if your version is different.
|
||||
|
||||
```shell
|
||||
$ clang --version
|
||||
Homebrew clang version 12.0.1
|
||||
Target: arm64-apple-darwin20.2.0
|
||||
Thread model: posix
|
||||
InstalledDir: /opt/homebrew/opt/llvm@12/bin
|
||||
```
|
||||
|
||||
At the end of the process you should see something like the following for executable locations and versions.
|
||||
|
||||
```shell
|
||||
$ which ghcup
|
||||
~/.ghcup/bin/ghcup
|
||||
$ ghcup --version
|
||||
The GHCup Haskell installer, version 0.1.19.0
|
||||
```
|
||||
|
||||
```bash
|
||||
$ which stack
|
||||
~/.ghcup/bin/stack
|
||||
$ stack --version
|
||||
Version 2.7.5, Git revision 717ec96c15520748f3fcee00f72504ddccaa30b5 (dirty) (163 commits) aarch64
|
||||
```
|
||||
|
||||
```shell
|
||||
$ which ghc
|
||||
~/.ghcup/bin/ghc
|
||||
$ ghc --version
|
||||
The Glorious Glasgow Haskell Compilation System, version 8.10.7
|
||||
```
|
||||
|
||||
Check which GHC version Stack thinks it's using too, for good measure:
|
||||
|
||||
```shell
|
||||
$ stack ghc -- --version
|
||||
The Glorious Glasgow Haskell Compilation System, version 8.10.7
|
||||
$ stack exec -- which ghc
|
||||
~/.ghcup/ghc/8.10.7/bin/ghc
|
||||
```
|
||||
|
||||
```shell
|
||||
$ which haskell-language-server-wrapper
|
||||
~/.ghcup/bin/haskell-language-server-wrapper
|
||||
$ haskell-language-server-wrapper
|
||||
|
||||
Found "...unison/hie.yaml" for "...unison/a"
|
||||
Run entered for haskell-language-server-wrapper(haskell-language-server-wrapper) Version 1.7.0.0 aarch64 ghc-9.2.2
|
||||
Current directory: ...unison
|
||||
Operating system: darwin
|
||||
Arguments: []
|
||||
Cradle directory: ...unison
|
||||
Cradle type: Stack
|
||||
|
||||
Tool versions found on the $PATH
|
||||
cabal: 3.6.2.0
|
||||
stack: 2.7.5
|
||||
ghc: 8.10.7
|
||||
```
|
||||
|
||||
If you're a VS Code user, you can download the Haskell extension for IDE support. You may need to configure it in `settings.json`.
|
||||
|
||||
```json
|
||||
"haskell.manageHLS": "GHCup",
|
||||
"haskell.toolchain": {
|
||||
"stack": "2.7.5",
|
||||
"ghc": "8.10.7",
|
||||
"cabal": "recommended",
|
||||
"hls": "1.7.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
These setting blocks say that the VS Code extension will use GHCup for your Haskell language server distribution, and sets the versions for elements in the toolchain.
|
||||
|
||||
## Troubleshooting:
|
||||
|
||||
The VS Code extension has compiled a helpful list of troubleshooting steps here: https://github.com/haskell/vscode-haskell#troubleshooting
|
||||
|
||||
### "Couldn't figure out LLVM version" or "failed to compile a sanity check" errors
|
||||
|
||||
```
|
||||
<no location info>: error:
|
||||
Warning: Couldn't figure out LLVM version!
|
||||
Make sure you have installed LLVM between [9 and 13)
|
||||
ghc: could not execute: opt
|
||||
```
|
||||
|
||||
Or
|
||||
|
||||
```
|
||||
ld: symbol(s) not found for architecture x86_64
|
||||
clang: error: linker command failed with exit code 1 (use -v to see invocation)
|
||||
`gcc' failed in phase `Linker'. (Exit code: 1)
|
||||
```
|
||||
|
||||
Try installing llvm version 12
|
||||
`brew install llvm@12`
|
||||
|
||||
and prepend it to your path
|
||||
```
|
||||
export PATH="$(brew --prefix)/opt/llvm@12/bin:$PATH"
|
||||
```
|
||||
|
||||
(The GHC version 8.10.7 mentions it supports LLVM versions up to 12. https://www.haskell.org/ghc/download_ghc_8_10_7.html)
|
||||
|
||||
### "GHC ABIs don't match!"
|
||||
|
||||
Follow the steps here:
|
||||
|
||||
https://github.com/haskell/vscode-haskell#ghc-abis-dont-match
|
||||
|
||||
We found some success telling Stack to use the system's GHC instead of managing its own version of GHC. You can try this by setting the following two configuration flags in ~/.stack/config.yaml
|
||||
|
||||
```
|
||||
system-ghc: true
|
||||
install-ghc: false
|
||||
```
|
||||
|
||||
This is telling Stack to use the GHC executable that it finds on your $PATH. Make sure the ghc being provided is the proper version, 8.10.7, from ghcup.
|
||||
|
||||
Note that you may need to clean the cache for the project after this failure with `stack clean --full` if you have previously built things with a different stack distribution.
|
||||
|
||||
### "stack" commands like "stack build" cause a segfault:
|
||||
|
||||
1. Make sure your stack state is clean. `stack clean --full` removes the project's stack work directories (things in .stack-work).
|
||||
2. [Wait for this bug to be fixed (or help fix this bug!)](https://github.com/commercialhaskell/stack/issues/5607)
|
||||
3. Or subshell out your stack commands `$(stack commandHere)`
|
||||
4. Or use bash instead of zsh
|
||||
|
||||
### Help! Everything is broken and I want to start over
|
||||
|
||||
Warning, the following will remove ghcup, configuration files, cached packages, and versions of the toolchain.
|
||||
|
||||
```
|
||||
ghcup nuke
|
||||
rm -rf ~/.ghcup
|
||||
rm -rf ~/.stack
|
||||
rm -rf ~/.cabal
|
||||
```
|
43
flake.lock
Normal file
43
flake.lock
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1667395993,
|
||||
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1674781052,
|
||||
"narHash": "sha256-nseKFXRvmZ+BDAeWQtsiad+5MnvI/M2Ak9iAWzooWBw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "cc4bb87f5457ba06af9ae57ee4328a49ce674b1b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-22.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
105
flake.nix
Normal file
105
flake.nix
Normal file
@ -0,0 +1,105 @@
|
||||
{
|
||||
description = "A common environment for unison development";
|
||||
|
||||
inputs = {
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11";
|
||||
};
|
||||
|
||||
outputs = { self, flake-utils, nixpkgs }:
|
||||
let
|
||||
systemAttrs = flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages."${system}".extend self.overlay;
|
||||
|
||||
mystack = pkgs.symlinkJoin {
|
||||
name = "stack";
|
||||
paths = [ pkgs.stack ];
|
||||
buildInputs = [ pkgs.makeWrapper ];
|
||||
postBuild = let
|
||||
flags = [ "--no-nix" "--system-ghc" "--no-install-ghc" ];
|
||||
add-flags =
|
||||
"--add-flags '${pkgs.lib.concatStringsSep " " flags}'";
|
||||
in ''
|
||||
wrapProgram "$out/bin/stack" ${add-flags}
|
||||
'';
|
||||
};
|
||||
ghc-version = "8107";
|
||||
ghc = pkgs.haskell.packages."ghc${ghc-version}";
|
||||
make-ormolu = p:
|
||||
p.callHackageDirect {
|
||||
pkg = "ormolu";
|
||||
ver = "0.4.0.0";
|
||||
sha256 = "0r8jb8lpaxx7wxnvxiynx2dkrfibfl8nxnjl5n4vwy0az166bbnd";
|
||||
} {
|
||||
ghc-lib-parser =
|
||||
pkgs.haskellPackages.ghc-lib-parser_9_2_5_20221107;
|
||||
Cabal = pkgs.haskellPackages.Cabal_3_6_3_0;
|
||||
};
|
||||
myhls = let
|
||||
hp = pkgs.haskellPackages.extend hp-override;
|
||||
hp-override = final: prev: {
|
||||
hls-floskell-plugin =
|
||||
pkgs.haskell.lib.dontCheck prev.hls-floskell-plugin;
|
||||
hls-rename-plugin =
|
||||
pkgs.haskell.lib.dontCheck prev.hls-rename-plugin;
|
||||
haskell-language-server =
|
||||
pkgs.haskell.lib.overrideCabal prev.haskell-language-server
|
||||
(drv: {
|
||||
configureFlags = drv.configureFlags ++ [
|
||||
"-f-brittany"
|
||||
"-f-fourmolu"
|
||||
"-f-floskell"
|
||||
"-f-stylishhaskell"
|
||||
"-f-hlint"
|
||||
];
|
||||
});
|
||||
ormolu = make-ormolu final;
|
||||
};
|
||||
in pkgs.haskell-language-server.override {
|
||||
haskellPackages = hp;
|
||||
dynamic = true;
|
||||
supportedGhcVersions = [ ghc-version ];
|
||||
};
|
||||
myormolu = make-ormolu pkgs.haskellPackages;
|
||||
nativePackages = pkgs.lib.optionals pkgs.stdenv.isDarwin (with pkgs.darwin.apple_sdk.frameworks; [ Cocoa ]);
|
||||
|
||||
unison-env = pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
mystack
|
||||
(haskell.compiler."ghc${ghc-version}".override {
|
||||
useLLVM = pkgs.stdenv.isAarch64;
|
||||
})
|
||||
myormolu
|
||||
myhls
|
||||
pkg-config
|
||||
zlib
|
||||
] ++ nativePackages;
|
||||
# workaround for https://gitlab.haskell.org/ghc/ghc/-/issues/11042
|
||||
shellHook = ''
|
||||
export LD_LIBRARY_PATH=${pkgs.zlib}/lib:$LD_LIBRARY_PATH
|
||||
'';
|
||||
};
|
||||
in {
|
||||
|
||||
apps.repl = flake-utils.lib.mkApp {
|
||||
drv =
|
||||
nixpkgs.legacyPackages."${system}".writeShellScriptBin "repl" ''
|
||||
confnix=$(mktemp)
|
||||
echo "builtins.getFlake (toString $(git rev-parse --show-toplevel))" >$confnix
|
||||
trap "rm $confnix" EXIT
|
||||
nix repl $confnix
|
||||
'';
|
||||
};
|
||||
|
||||
pkgs = pkgs;
|
||||
|
||||
devShell = unison-env;
|
||||
|
||||
packages = { };
|
||||
|
||||
defaultPackage = self.packages."${system}".unison-env;
|
||||
});
|
||||
topLevelAttrs = { overlay = final: prev: { }; };
|
||||
in systemAttrs // topLevelAttrs;
|
||||
}
|
@ -204,6 +204,8 @@ builtinTypesSrc =
|
||||
Rename' "IO" "io2.IO",
|
||||
B' "Handle" CT.Data,
|
||||
Rename' "Handle" "io2.Handle",
|
||||
B' "ProcessHandle" CT.Data,
|
||||
Rename' "ProcessHandle" "io2.ProcessHandle",
|
||||
B' "Socket" CT.Data,
|
||||
Rename' "Socket" "io2.Socket",
|
||||
B' "ThreadId" CT.Data,
|
||||
@ -760,6 +762,13 @@ ioBuiltins =
|
||||
forall1 "a" $ \a ->
|
||||
a --> io (reft iot a)
|
||||
),
|
||||
( "IO.process.call", text --> list text --> io nat),
|
||||
( "IO.process.start",
|
||||
text --> list text -->
|
||||
io (tuple [handle, handle, handle, phandle])),
|
||||
( "IO.process.kill", phandle --> io unit),
|
||||
( "IO.process.wait", phandle --> io nat),
|
||||
( "IO.process.exitCode", phandle --> io (optionalt nat)),
|
||||
( "validateSandboxed",
|
||||
forall1 "a" $ \a -> list termLink --> a --> boolean
|
||||
),
|
||||
@ -955,10 +964,11 @@ iarrayt a = Type.iarrayType () `app` a
|
||||
marrayt :: Type -> Type -> Type
|
||||
marrayt g a = Type.marrayType () `app` g `app` a
|
||||
|
||||
socket, threadId, handle, unit :: Type
|
||||
socket, threadId, handle, phandle, unit :: Type
|
||||
socket = Type.socket ()
|
||||
threadId = Type.threadId ()
|
||||
handle = Type.fileHandle ()
|
||||
phandle = Type.processHandle ()
|
||||
unit = DD.unitType ()
|
||||
|
||||
tls, tlsClientConfig, tlsServerConfig, tlsSignedCert, tlsPrivateKey, tlsVersion, tlsCipher :: Type
|
||||
|
@ -13,8 +13,6 @@ module Unison.Codebase.BranchUtil
|
||||
|
||||
-- * Branch modifications
|
||||
makeSetBranch,
|
||||
makeDeleteBranch,
|
||||
makeObliterateBranch,
|
||||
makeAddTypeName,
|
||||
makeDeleteTypeName,
|
||||
makeAddTermName,
|
||||
@ -24,7 +22,6 @@ module Unison.Codebase.BranchUtil
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Lens
|
||||
import qualified Data.Map as Map
|
||||
import qualified Data.Set as Set
|
||||
import Unison.Codebase.Branch (Branch, Branch0)
|
||||
@ -137,18 +134,3 @@ makeDeleteTypeName (p, name) r = (p, Branch.deleteTypeName r name)
|
||||
makeSetBranch ::
|
||||
Path.Split -> Branch m -> (Path, Branch0 m -> Branch0 m)
|
||||
makeSetBranch (p, name) b = (p, Branch.setChildBranch name b)
|
||||
|
||||
-- | "delete"s a branch by cons'ing an empty Branch0 onto the history at that location.
|
||||
-- See also 'makeObliterateBranch'.
|
||||
makeDeleteBranch ::
|
||||
Applicative m =>
|
||||
Path.Split ->
|
||||
(Path, Branch0 m -> Branch0 m)
|
||||
makeDeleteBranch (p, name) = (p, Branch.children . ix name %~ Branch.cons Branch.empty0)
|
||||
|
||||
-- | Erase a branch and its history
|
||||
-- See also 'makeDeleteBranch'.
|
||||
-- Note that this requires a AllowRewritingHistory update strategy to behave correctly.
|
||||
makeObliterateBranch ::
|
||||
Path.Split -> (Path, Branch0 m -> Branch0 m)
|
||||
makeObliterateBranch p = makeSetBranch p Branch.empty
|
||||
|
@ -101,6 +101,7 @@ import System.Environment as SYS
|
||||
( getArgs,
|
||||
getEnv,
|
||||
)
|
||||
import System.Exit as SYS (ExitCode(..))
|
||||
import System.FilePath (isPathSeparator)
|
||||
import System.IO (Handle)
|
||||
import System.IO as SYS
|
||||
@ -123,6 +124,14 @@ import System.IO as SYS
|
||||
stdout,
|
||||
)
|
||||
import System.IO.Temp (createTempDirectory)
|
||||
import System.Process as SYS
|
||||
( getProcessExitCode,
|
||||
proc,
|
||||
runInteractiveProcess,
|
||||
terminateProcess,
|
||||
waitForProcess,
|
||||
withCreateProcess
|
||||
)
|
||||
import qualified System.X509 as X
|
||||
import Unison.ABT.Normalized hiding (TTm)
|
||||
import qualified Unison.Builtin as Ty (builtinTypes)
|
||||
@ -1014,6 +1023,19 @@ infixr 0 -->
|
||||
(-->) :: a -> b -> (a, b)
|
||||
x --> y = (x, y)
|
||||
|
||||
start'process :: ForeignOp
|
||||
start'process instr =
|
||||
([BX, BX],)
|
||||
. TAbss [exe, args]
|
||||
. TLets Direct [hin,hout,herr,hproc] [BX,BX,BX,BX] (TFOp instr [exe, args])
|
||||
. TLetD un BX (TCon Ty.unitRef 0 [])
|
||||
. TLetD p3 BX (TCon Ty.pairRef 0 [hproc, un])
|
||||
. TLetD p2 BX (TCon Ty.pairRef 0 [herr, p3])
|
||||
. TLetD p1 BX (TCon Ty.pairRef 0 [hout, p2])
|
||||
$ TCon Ty.pairRef 0 [hin, p1]
|
||||
where
|
||||
(exe,args,hin,hout,herr,hproc,un,p3,p2,p1) = fresh
|
||||
|
||||
set'buffering :: ForeignOp
|
||||
set'buffering instr =
|
||||
([BX, BX],)
|
||||
@ -1236,6 +1258,16 @@ outMaybe maybe result =
|
||||
(1, ([BX], TAbs maybe $ some maybe))
|
||||
]
|
||||
|
||||
outMaybeNat :: Var v => v -> v -> v -> ANormal v
|
||||
outMaybeNat tag result n =
|
||||
TMatch tag . MatchSum $
|
||||
mapFromList
|
||||
[ (0, ([], none)),
|
||||
(1, ([UN],
|
||||
TAbs result .
|
||||
TLetD n BX (TCon Ty.natRef 0 [n]) $ some n))
|
||||
]
|
||||
|
||||
outMaybeNTup :: forall v. Var v => v -> v -> v -> v -> v -> v -> v -> ANormal v
|
||||
outMaybeNTup a b n u bp p result =
|
||||
TMatch result . MatchSum $
|
||||
@ -1495,6 +1527,16 @@ boxBoxTo0 instr =
|
||||
where
|
||||
(arg1, arg2) = fresh
|
||||
|
||||
-- a -> b ->{E} Nat
|
||||
boxBoxToNat :: ForeignOp
|
||||
boxBoxToNat instr =
|
||||
([BX, BX],)
|
||||
. TAbss [arg1, arg2]
|
||||
. TLetD result UN (TFOp instr [arg1, arg2])
|
||||
$ TCon Ty.natRef 0 [result]
|
||||
where
|
||||
(arg1, arg2, result) = fresh
|
||||
|
||||
-- a -> b -> Option c
|
||||
|
||||
-- a -> Bool
|
||||
@ -1616,6 +1658,12 @@ boxToMaybeBox =
|
||||
where
|
||||
(arg, maybe, result) = fresh
|
||||
|
||||
-- a -> Maybe Nat
|
||||
boxToMaybeNat :: ForeignOp
|
||||
boxToMaybeNat = inBx arg tag $ outMaybeNat tag result n
|
||||
where
|
||||
(arg, tag, result, n) = fresh
|
||||
|
||||
-- a -> Maybe (Nat, b)
|
||||
boxToMaybeNTup :: ForeignOp
|
||||
boxToMaybeNTup =
|
||||
@ -2272,6 +2320,27 @@ declareForeigns = do
|
||||
2 -> pure (Just SYS.stderr)
|
||||
_ -> pure Nothing
|
||||
|
||||
let exitDecode ExitSuccess = 0
|
||||
exitDecode (ExitFailure n) = n
|
||||
|
||||
declareForeign Tracked "IO.process.call" boxBoxToNat . mkForeign $
|
||||
\(exe, map Util.Text.unpack -> args) ->
|
||||
withCreateProcess (proc exe args) $ \_ _ _ p ->
|
||||
exitDecode <$> waitForProcess p
|
||||
|
||||
declareForeign Tracked "IO.process.start" start'process . mkForeign $
|
||||
\(exe, map Util.Text.unpack -> args) ->
|
||||
runInteractiveProcess exe args Nothing Nothing
|
||||
|
||||
declareForeign Tracked "IO.process.kill" boxTo0 . mkForeign $
|
||||
terminateProcess
|
||||
|
||||
declareForeign Tracked "IO.process.wait" boxToNat . mkForeign $
|
||||
\ph -> exitDecode <$> waitForProcess ph
|
||||
|
||||
declareForeign Tracked "IO.process.exitCode" boxToMaybeNat . mkForeign $
|
||||
fmap (fmap exitDecode) . getProcessExitCode
|
||||
|
||||
declareForeign Tracked "MVar.new" boxDirect
|
||||
. mkForeign
|
||||
$ \(c :: Closure) -> newMVar c
|
||||
|
@ -27,6 +27,7 @@ import qualified Data.X509 as X509
|
||||
import Network.Socket (Socket)
|
||||
import qualified Network.TLS as TLS (ClientParams, Context, ServerParams)
|
||||
import System.Clock (TimeSpec)
|
||||
import System.Process (ProcessHandle)
|
||||
import System.IO (Handle)
|
||||
import Unison.Reference (Reference)
|
||||
import Unison.Referent (Referent)
|
||||
@ -191,6 +192,8 @@ instance BuiltinForeign Bytes where foreignRef = Tagged Ty.bytesRef
|
||||
|
||||
instance BuiltinForeign Handle where foreignRef = Tagged Ty.fileHandleRef
|
||||
|
||||
instance BuiltinForeign ProcessHandle where foreignRef = Tagged Ty.processHandleRef
|
||||
|
||||
instance BuiltinForeign Socket where foreignRef = Tagged Ty.socketRef
|
||||
|
||||
instance BuiltinForeign ThreadId where foreignRef = Tagged Ty.threadIdRef
|
||||
|
@ -354,6 +354,27 @@ instance
|
||||
(ustk, bstk) <- writeForeign ustk bstk b
|
||||
writeForeign ustk bstk a
|
||||
|
||||
instance
|
||||
( ForeignConvention a,
|
||||
ForeignConvention b,
|
||||
ForeignConvention c,
|
||||
ForeignConvention d
|
||||
) =>
|
||||
ForeignConvention (a, b, c, d)
|
||||
where
|
||||
readForeign us bs ustk bstk = do
|
||||
(us, bs, a) <- readForeign us bs ustk bstk
|
||||
(us, bs, b) <- readForeign us bs ustk bstk
|
||||
(us, bs, c) <- readForeign us bs ustk bstk
|
||||
(us, bs, d) <- readForeign us bs ustk bstk
|
||||
pure (us, bs, (a, b, c, d))
|
||||
|
||||
writeForeign ustk bstk (a, b, c, d) = do
|
||||
(ustk, bstk) <- writeForeign ustk bstk d
|
||||
(ustk, bstk) <- writeForeign ustk bstk c
|
||||
(ustk, bstk) <- writeForeign ustk bstk b
|
||||
writeForeign ustk bstk a
|
||||
|
||||
instance
|
||||
( ForeignConvention a,
|
||||
ForeignConvention b,
|
||||
|
@ -1366,29 +1366,33 @@ bprim1 !ustk !bstk UCNS i =
|
||||
pure (ustk, bstk)
|
||||
bprim1 !ustk !bstk TTOI i =
|
||||
peekOffBi bstk i >>= \t -> case readm $ Util.Text.unpack t of
|
||||
Nothing -> do
|
||||
Just n
|
||||
| fromIntegral (minBound :: Int) <= n,
|
||||
n <= fromIntegral (maxBound :: Int) -> do
|
||||
ustk <- bumpn ustk 2
|
||||
poke ustk 1
|
||||
pokeOff ustk 1 (fromInteger n)
|
||||
pure (ustk, bstk)
|
||||
_ -> do
|
||||
ustk <- bump ustk
|
||||
poke ustk 0
|
||||
pure (ustk, bstk)
|
||||
Just n -> do
|
||||
ustk <- bumpn ustk 2
|
||||
poke ustk 1
|
||||
pokeOff ustk 1 n
|
||||
pure (ustk, bstk)
|
||||
where
|
||||
readm ('+' : s) = readMaybe s
|
||||
readm s = readMaybe s
|
||||
bprim1 !ustk !bstk TTON i =
|
||||
peekOffBi bstk i >>= \t -> case readMaybe $ Util.Text.unpack t of
|
||||
Nothing -> do
|
||||
Just n
|
||||
| 0 <= n,
|
||||
n <= fromIntegral (maxBound :: Word) -> do
|
||||
ustk <- bumpn ustk 2
|
||||
poke ustk 1
|
||||
pokeOffN ustk 1 (fromInteger n)
|
||||
pure (ustk, bstk)
|
||||
_ -> do
|
||||
ustk <- bump ustk
|
||||
poke ustk 0
|
||||
pure (ustk, bstk)
|
||||
Just n -> do
|
||||
ustk <- bumpn ustk 2
|
||||
poke ustk 1
|
||||
pokeOffN ustk 1 n
|
||||
pure (ustk, bstk)
|
||||
bprim1 !ustk !bstk TTOF i =
|
||||
peekOffBi bstk i >>= \t -> case readMaybe $ Util.Text.unpack t of
|
||||
Nothing -> do
|
||||
|
@ -984,13 +984,13 @@ destructuringBind = do
|
||||
-- Some 42
|
||||
-- vs
|
||||
-- Some 42 = List.head elems
|
||||
(p, boundVars, guard) <- P.try $ do
|
||||
(p, boundVars) <- P.try $ do
|
||||
(p, boundVars) <- parsePattern
|
||||
let boundVars' = snd <$> boundVars
|
||||
guard <- optional $ reserved "|" *> infixAppOrBooleanOp
|
||||
P.lookAhead (openBlockWith "=")
|
||||
pure (p, boundVars', guard)
|
||||
pure (p, boundVars')
|
||||
scrute <- block "=" -- Dwight K. Scrute ("The People's Scrutinee")
|
||||
let guard = Nothing
|
||||
let absChain vs t = foldr (\v t -> ABT.abs' (ann t) v t) t vs
|
||||
thecase t = Term.MatchCase p (fmap (absChain boundVars) guard) $ absChain boundVars t
|
||||
pure $
|
||||
|
@ -884,12 +884,10 @@ loop e = do
|
||||
if hasConfirmed || insistence == Force
|
||||
then do
|
||||
description <- inputDescription input
|
||||
Cli.stepAt
|
||||
description
|
||||
(Path.empty, const Branch.empty0)
|
||||
Cli.updateRoot Branch.empty description
|
||||
Cli.respond DeletedEverything
|
||||
else Cli.respond DeleteEverythingConfirmation
|
||||
DeleteTarget'Branch insistence (Just p) -> do
|
||||
DeleteTarget'Branch insistence (Just p@(parentPath, childName)) -> do
|
||||
branch <- Cli.expectBranchAtPath' (Path.unsplit' p)
|
||||
description <- inputDescription input
|
||||
absPath <- Cli.resolveSplit' p
|
||||
@ -911,8 +909,12 @@ loop e = do
|
||||
ppeDecl <- currentPrettyPrintEnvDecl Backend.Within
|
||||
Cli.respondNumbered $ CantDeleteNamespace ppeDecl endangerments
|
||||
Cli.returnEarlyWithoutOutput
|
||||
Cli.stepAt description $
|
||||
BranchUtil.makeDeleteBranch (Path.convert absPath)
|
||||
parentPathAbs <- Cli.resolvePath' parentPath
|
||||
-- We have to modify the parent in order to also wipe out the history at the
|
||||
-- child.
|
||||
Cli.updateAt description parentPathAbs \parentBranch ->
|
||||
parentBranch
|
||||
& Branch.modifyAt (Path.singleton childName) \_ -> Branch.empty
|
||||
afterDelete
|
||||
DisplayI outputLoc names' -> do
|
||||
currentBranch0 <- Cli.getCurrentBranch0
|
||||
@ -2796,7 +2798,7 @@ buildScheme main file = do
|
||||
++ lns gd gen
|
||||
++ [surround file]
|
||||
|
||||
doRunAsScheme :: HQ.HashQualified Name -> [String] -> Cli ()
|
||||
doRunAsScheme :: HQ.HashQualified Name -> [String] -> Cli ()
|
||||
doRunAsScheme main args = do
|
||||
fullpath <- generateSchemeFile True (HQ.toString main) main
|
||||
runScheme fullpath args
|
||||
|
@ -71,23 +71,27 @@ authLogin host = do
|
||||
-- and it all works out fine.
|
||||
redirectURIVar <- liftIO newEmptyMVar
|
||||
(verifier, challenge, state) <- generateParams
|
||||
let codeHandler code mayNextURI = do
|
||||
let codeHandler :: (Code -> Maybe URI -> (Response -> IO ResponseReceived) -> IO ResponseReceived)
|
||||
codeHandler code mayNextURI respond = do
|
||||
redirectURI <- readMVar redirectURIVar
|
||||
result <- exchangeCode httpClient tokenEndpoint code verifier redirectURI
|
||||
putMVar authResultVar result
|
||||
case result of
|
||||
respReceived <- case result of
|
||||
Left err -> do
|
||||
Debug.debugM Debug.Auth "Auth Error" err
|
||||
pure $ Wai.responseLBS internalServerError500 [] "Something went wrong, please try again."
|
||||
respond $ Wai.responseLBS internalServerError500 [] "Something went wrong, please try again."
|
||||
Right _ ->
|
||||
case mayNextURI of
|
||||
Nothing -> pure $ Wai.responseLBS found302 [] "Authorization successful. You may close this page and return to UCM."
|
||||
Nothing -> respond $ Wai.responseLBS found302 [] "Authorization successful. You may close this page and return to UCM."
|
||||
Just nextURI ->
|
||||
pure $
|
||||
respond $
|
||||
Wai.responseLBS
|
||||
found302
|
||||
[("LOCATION", BSC.pack $ show @URI nextURI)]
|
||||
"Authorization successful. You may close this page and return to UCM."
|
||||
-- Wait until we've responded to the browser before putting the result,
|
||||
-- otherwise the server will shut down prematurely.
|
||||
putMVar authResultVar result
|
||||
pure respReceived
|
||||
tokens <-
|
||||
Cli.with (Warp.withApplication (pure $ authTransferServer codeHandler)) \port -> do
|
||||
let redirectURI = "http://localhost:" <> show port <> "/redirect"
|
||||
@ -105,11 +109,11 @@ authLogin host = do
|
||||
-- | A server in the format expected for a Wai Application
|
||||
-- This is a temporary server which is spun up only until we get a code back from the
|
||||
-- auth server.
|
||||
authTransferServer :: (Code -> Maybe URI -> IO Response) -> Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived
|
||||
authTransferServer :: (Code -> Maybe URI -> (Response -> IO ResponseReceived) -> IO ResponseReceived) -> Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived
|
||||
authTransferServer callback req respond =
|
||||
case (requestMethod req, pathInfo req, getQueryParams req) of
|
||||
("GET", ["redirect"], (Just code, maybeNextURI)) -> do
|
||||
callback code maybeNextURI >>= respond
|
||||
callback code maybeNextURI respond
|
||||
_ -> respond (responseLBS status404 [] "Not Found")
|
||||
where
|
||||
getQueryParams req = do
|
||||
|
@ -259,6 +259,9 @@ filePathRef = Reference.Builtin "FilePath"
|
||||
threadIdRef = Reference.Builtin "ThreadId"
|
||||
socketRef = Reference.Builtin "Socket"
|
||||
|
||||
processHandleRef :: Reference
|
||||
processHandleRef = Reference.Builtin "ProcessHandle"
|
||||
|
||||
scopeRef, refRef :: Reference
|
||||
scopeRef = Reference.Builtin "Scope"
|
||||
refRef = Reference.Builtin "Ref"
|
||||
@ -348,6 +351,9 @@ char a = ref a charRef
|
||||
fileHandle :: Ord v => a -> Type v a
|
||||
fileHandle a = ref a fileHandleRef
|
||||
|
||||
processHandle :: Ord v => a -> Type v a
|
||||
processHandle a = ref a processHandleRef
|
||||
|
||||
threadId :: Ord v => a -> Type v a
|
||||
threadId a = ref a threadIdRef
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -297,363 +297,375 @@ Let's try it!
|
||||
222. io2.IO.openFile.impl : Text
|
||||
-> FileMode
|
||||
->{IO} Either Failure Handle
|
||||
223. io2.IO.putBytes.impl : Handle
|
||||
223. io2.IO.process.call : Text -> [Text] ->{IO} Nat
|
||||
224. io2.IO.process.exitCode : ProcessHandle
|
||||
->{IO} Optional Nat
|
||||
225. io2.IO.process.kill : ProcessHandle ->{IO} ()
|
||||
226. io2.IO.process.start : Text
|
||||
-> [Text]
|
||||
->{IO} ( Handle,
|
||||
Handle,
|
||||
Handle,
|
||||
ProcessHandle)
|
||||
227. io2.IO.process.wait : ProcessHandle ->{IO} Nat
|
||||
228. io2.IO.putBytes.impl : Handle
|
||||
-> Bytes
|
||||
->{IO} Either Failure ()
|
||||
224. io2.IO.ready.impl : Handle ->{IO} Either Failure Boolean
|
||||
225. io2.IO.ref : a ->{IO} Ref {IO} a
|
||||
226. io2.IO.removeDirectory.impl : Text
|
||||
229. io2.IO.ready.impl : Handle ->{IO} Either Failure Boolean
|
||||
230. io2.IO.ref : a ->{IO} Ref {IO} a
|
||||
231. io2.IO.removeDirectory.impl : Text
|
||||
->{IO} Either Failure ()
|
||||
227. io2.IO.removeFile.impl : Text ->{IO} Either Failure ()
|
||||
228. io2.IO.renameDirectory.impl : Text
|
||||
232. io2.IO.removeFile.impl : Text ->{IO} Either Failure ()
|
||||
233. io2.IO.renameDirectory.impl : Text
|
||||
-> Text
|
||||
->{IO} Either Failure ()
|
||||
229. io2.IO.renameFile.impl : Text
|
||||
234. io2.IO.renameFile.impl : Text
|
||||
-> Text
|
||||
->{IO} Either Failure ()
|
||||
230. io2.IO.seekHandle.impl : Handle
|
||||
235. io2.IO.seekHandle.impl : Handle
|
||||
-> SeekMode
|
||||
-> Int
|
||||
->{IO} Either Failure ()
|
||||
231. io2.IO.serverSocket.impl : Optional Text
|
||||
236. io2.IO.serverSocket.impl : Optional Text
|
||||
-> Text
|
||||
->{IO} Either Failure Socket
|
||||
232. io2.IO.setBuffering.impl : Handle
|
||||
237. io2.IO.setBuffering.impl : Handle
|
||||
-> BufferMode
|
||||
->{IO} Either Failure ()
|
||||
233. io2.IO.setCurrentDirectory.impl : Text
|
||||
238. io2.IO.setCurrentDirectory.impl : Text
|
||||
->{IO} Either
|
||||
Failure ()
|
||||
234. io2.IO.setEcho.impl : Handle
|
||||
239. io2.IO.setEcho.impl : Handle
|
||||
-> Boolean
|
||||
->{IO} Either Failure ()
|
||||
235. io2.IO.socketAccept.impl : Socket
|
||||
240. io2.IO.socketAccept.impl : Socket
|
||||
->{IO} Either Failure Socket
|
||||
236. io2.IO.socketPort.impl : Socket ->{IO} Either Failure Nat
|
||||
237. io2.IO.socketReceive.impl : Socket
|
||||
241. io2.IO.socketPort.impl : Socket ->{IO} Either Failure Nat
|
||||
242. io2.IO.socketReceive.impl : Socket
|
||||
-> Nat
|
||||
->{IO} Either Failure Bytes
|
||||
238. io2.IO.socketSend.impl : Socket
|
||||
243. io2.IO.socketSend.impl : Socket
|
||||
-> Bytes
|
||||
->{IO} Either Failure ()
|
||||
239. io2.IO.stdHandle : StdHandle -> Handle
|
||||
240. io2.IO.systemTime.impl : '{IO} Either Failure Nat
|
||||
241. io2.IO.systemTimeMicroseconds : '{IO} Int
|
||||
242. io2.IO.tryEval : '{IO} a ->{IO, Exception} a
|
||||
243. unique type io2.IOError
|
||||
244. io2.IOError.AlreadyExists : IOError
|
||||
245. io2.IOError.EOF : IOError
|
||||
246. io2.IOError.IllegalOperation : IOError
|
||||
247. io2.IOError.NoSuchThing : IOError
|
||||
248. io2.IOError.PermissionDenied : IOError
|
||||
249. io2.IOError.ResourceBusy : IOError
|
||||
250. io2.IOError.ResourceExhausted : IOError
|
||||
251. io2.IOError.UserError : IOError
|
||||
252. unique type io2.IOFailure
|
||||
253. unique type io2.MiscFailure
|
||||
254. builtin type io2.MVar
|
||||
255. io2.MVar.isEmpty : MVar a ->{IO} Boolean
|
||||
256. io2.MVar.new : a ->{IO} MVar a
|
||||
257. io2.MVar.newEmpty : '{IO} MVar a
|
||||
258. io2.MVar.put.impl : MVar a -> a ->{IO} Either Failure ()
|
||||
259. io2.MVar.read.impl : MVar a ->{IO} Either Failure a
|
||||
260. io2.MVar.swap.impl : MVar a -> a ->{IO} Either Failure a
|
||||
261. io2.MVar.take.impl : MVar a ->{IO} Either Failure a
|
||||
262. io2.MVar.tryPut.impl : MVar a
|
||||
244. io2.IO.stdHandle : StdHandle -> Handle
|
||||
245. io2.IO.systemTime.impl : '{IO} Either Failure Nat
|
||||
246. io2.IO.systemTimeMicroseconds : '{IO} Int
|
||||
247. io2.IO.tryEval : '{IO} a ->{IO, Exception} a
|
||||
248. unique type io2.IOError
|
||||
249. io2.IOError.AlreadyExists : IOError
|
||||
250. io2.IOError.EOF : IOError
|
||||
251. io2.IOError.IllegalOperation : IOError
|
||||
252. io2.IOError.NoSuchThing : IOError
|
||||
253. io2.IOError.PermissionDenied : IOError
|
||||
254. io2.IOError.ResourceBusy : IOError
|
||||
255. io2.IOError.ResourceExhausted : IOError
|
||||
256. io2.IOError.UserError : IOError
|
||||
257. unique type io2.IOFailure
|
||||
258. unique type io2.MiscFailure
|
||||
259. builtin type io2.MVar
|
||||
260. io2.MVar.isEmpty : MVar a ->{IO} Boolean
|
||||
261. io2.MVar.new : a ->{IO} MVar a
|
||||
262. io2.MVar.newEmpty : '{IO} MVar a
|
||||
263. io2.MVar.put.impl : MVar a -> a ->{IO} Either Failure ()
|
||||
264. io2.MVar.read.impl : MVar a ->{IO} Either Failure a
|
||||
265. io2.MVar.swap.impl : MVar a -> a ->{IO} Either Failure a
|
||||
266. io2.MVar.take.impl : MVar a ->{IO} Either Failure a
|
||||
267. io2.MVar.tryPut.impl : MVar a
|
||||
-> a
|
||||
->{IO} Either Failure Boolean
|
||||
263. io2.MVar.tryRead.impl : MVar a
|
||||
268. io2.MVar.tryRead.impl : MVar a
|
||||
->{IO} Either
|
||||
Failure (Optional a)
|
||||
264. io2.MVar.tryTake : MVar a ->{IO} Optional a
|
||||
265. builtin type io2.Promise
|
||||
266. io2.Promise.new : '{IO} Promise a
|
||||
267. io2.Promise.read : Promise a ->{IO} a
|
||||
268. io2.Promise.tryRead : Promise a ->{IO} Optional a
|
||||
269. io2.Promise.write : Promise a -> a ->{IO} Boolean
|
||||
270. io2.Ref.cas : Ref {IO} a -> Ticket a -> a ->{IO} Boolean
|
||||
271. io2.Ref.readForCas : Ref {IO} a ->{IO} Ticket a
|
||||
272. builtin type io2.Ref.Ticket
|
||||
273. io2.Ref.Ticket.read : Ticket a -> a
|
||||
274. unique type io2.RuntimeFailure
|
||||
275. unique type io2.SeekMode
|
||||
276. io2.SeekMode.AbsoluteSeek : SeekMode
|
||||
277. io2.SeekMode.RelativeSeek : SeekMode
|
||||
278. io2.SeekMode.SeekFromEnd : SeekMode
|
||||
279. builtin type io2.Socket
|
||||
280. unique type io2.StdHandle
|
||||
281. io2.StdHandle.StdErr : StdHandle
|
||||
282. io2.StdHandle.StdIn : StdHandle
|
||||
283. io2.StdHandle.StdOut : StdHandle
|
||||
284. builtin type io2.STM
|
||||
285. io2.STM.atomically : '{STM} a ->{IO} a
|
||||
286. io2.STM.retry : '{STM} a
|
||||
287. unique type io2.STMFailure
|
||||
288. builtin type io2.ThreadId
|
||||
289. builtin type io2.Tls
|
||||
290. builtin type io2.Tls.Cipher
|
||||
291. builtin type io2.Tls.ClientConfig
|
||||
292. io2.Tls.ClientConfig.certificates.set : [SignedCert]
|
||||
269. io2.MVar.tryTake : MVar a ->{IO} Optional a
|
||||
270. builtin type io2.ProcessHandle
|
||||
271. builtin type io2.Promise
|
||||
272. io2.Promise.new : '{IO} Promise a
|
||||
273. io2.Promise.read : Promise a ->{IO} a
|
||||
274. io2.Promise.tryRead : Promise a ->{IO} Optional a
|
||||
275. io2.Promise.write : Promise a -> a ->{IO} Boolean
|
||||
276. io2.Ref.cas : Ref {IO} a -> Ticket a -> a ->{IO} Boolean
|
||||
277. io2.Ref.readForCas : Ref {IO} a ->{IO} Ticket a
|
||||
278. builtin type io2.Ref.Ticket
|
||||
279. io2.Ref.Ticket.read : Ticket a -> a
|
||||
280. unique type io2.RuntimeFailure
|
||||
281. unique type io2.SeekMode
|
||||
282. io2.SeekMode.AbsoluteSeek : SeekMode
|
||||
283. io2.SeekMode.RelativeSeek : SeekMode
|
||||
284. io2.SeekMode.SeekFromEnd : SeekMode
|
||||
285. builtin type io2.Socket
|
||||
286. unique type io2.StdHandle
|
||||
287. io2.StdHandle.StdErr : StdHandle
|
||||
288. io2.StdHandle.StdIn : StdHandle
|
||||
289. io2.StdHandle.StdOut : StdHandle
|
||||
290. builtin type io2.STM
|
||||
291. io2.STM.atomically : '{STM} a ->{IO} a
|
||||
292. io2.STM.retry : '{STM} a
|
||||
293. unique type io2.STMFailure
|
||||
294. builtin type io2.ThreadId
|
||||
295. builtin type io2.Tls
|
||||
296. builtin type io2.Tls.Cipher
|
||||
297. builtin type io2.Tls.ClientConfig
|
||||
298. io2.Tls.ClientConfig.certificates.set : [SignedCert]
|
||||
-> ClientConfig
|
||||
-> ClientConfig
|
||||
293. io2.TLS.ClientConfig.ciphers.set : [Cipher]
|
||||
299. io2.TLS.ClientConfig.ciphers.set : [Cipher]
|
||||
-> ClientConfig
|
||||
-> ClientConfig
|
||||
294. io2.Tls.ClientConfig.default : Text
|
||||
300. io2.Tls.ClientConfig.default : Text
|
||||
-> Bytes
|
||||
-> ClientConfig
|
||||
295. io2.Tls.ClientConfig.versions.set : [Version]
|
||||
301. io2.Tls.ClientConfig.versions.set : [Version]
|
||||
-> ClientConfig
|
||||
-> ClientConfig
|
||||
296. io2.Tls.decodeCert.impl : Bytes
|
||||
302. io2.Tls.decodeCert.impl : Bytes
|
||||
-> Either Failure SignedCert
|
||||
297. io2.Tls.decodePrivateKey : Bytes -> [PrivateKey]
|
||||
298. io2.Tls.encodeCert : SignedCert -> Bytes
|
||||
299. io2.Tls.encodePrivateKey : PrivateKey -> Bytes
|
||||
300. io2.Tls.handshake.impl : Tls ->{IO} Either Failure ()
|
||||
301. io2.Tls.newClient.impl : ClientConfig
|
||||
303. io2.Tls.decodePrivateKey : Bytes -> [PrivateKey]
|
||||
304. io2.Tls.encodeCert : SignedCert -> Bytes
|
||||
305. io2.Tls.encodePrivateKey : PrivateKey -> Bytes
|
||||
306. io2.Tls.handshake.impl : Tls ->{IO} Either Failure ()
|
||||
307. io2.Tls.newClient.impl : ClientConfig
|
||||
-> Socket
|
||||
->{IO} Either Failure Tls
|
||||
302. io2.Tls.newServer.impl : ServerConfig
|
||||
308. io2.Tls.newServer.impl : ServerConfig
|
||||
-> Socket
|
||||
->{IO} Either Failure Tls
|
||||
303. builtin type io2.Tls.PrivateKey
|
||||
304. io2.Tls.receive.impl : Tls ->{IO} Either Failure Bytes
|
||||
305. io2.Tls.send.impl : Tls -> Bytes ->{IO} Either Failure ()
|
||||
306. builtin type io2.Tls.ServerConfig
|
||||
307. io2.Tls.ServerConfig.certificates.set : [SignedCert]
|
||||
309. builtin type io2.Tls.PrivateKey
|
||||
310. io2.Tls.receive.impl : Tls ->{IO} Either Failure Bytes
|
||||
311. io2.Tls.send.impl : Tls -> Bytes ->{IO} Either Failure ()
|
||||
312. builtin type io2.Tls.ServerConfig
|
||||
313. io2.Tls.ServerConfig.certificates.set : [SignedCert]
|
||||
-> ServerConfig
|
||||
-> ServerConfig
|
||||
308. io2.Tls.ServerConfig.ciphers.set : [Cipher]
|
||||
314. io2.Tls.ServerConfig.ciphers.set : [Cipher]
|
||||
-> ServerConfig
|
||||
-> ServerConfig
|
||||
309. io2.Tls.ServerConfig.default : [SignedCert]
|
||||
315. io2.Tls.ServerConfig.default : [SignedCert]
|
||||
-> PrivateKey
|
||||
-> ServerConfig
|
||||
310. io2.Tls.ServerConfig.versions.set : [Version]
|
||||
316. io2.Tls.ServerConfig.versions.set : [Version]
|
||||
-> ServerConfig
|
||||
-> ServerConfig
|
||||
311. builtin type io2.Tls.SignedCert
|
||||
312. io2.Tls.terminate.impl : Tls ->{IO} Either Failure ()
|
||||
313. builtin type io2.Tls.Version
|
||||
314. unique type io2.TlsFailure
|
||||
315. builtin type io2.TVar
|
||||
316. io2.TVar.new : a ->{STM} TVar a
|
||||
317. io2.TVar.newIO : a ->{IO} TVar a
|
||||
318. io2.TVar.read : TVar a ->{STM} a
|
||||
319. io2.TVar.readIO : TVar a ->{IO} a
|
||||
320. io2.TVar.swap : TVar a -> a ->{STM} a
|
||||
321. io2.TVar.write : TVar a -> a ->{STM} ()
|
||||
322. io2.validateSandboxed : [Term] -> a -> Boolean
|
||||
323. unique type IsPropagated
|
||||
324. IsPropagated.IsPropagated : IsPropagated
|
||||
325. unique type IsTest
|
||||
326. IsTest.IsTest : IsTest
|
||||
327. unique type Link
|
||||
328. builtin type Link.Term
|
||||
329. Link.Term : Term -> Link
|
||||
330. Link.Term.toText : Term -> Text
|
||||
331. builtin type Link.Type
|
||||
332. Link.Type : Type -> Link
|
||||
333. builtin type List
|
||||
334. List.++ : [a] -> [a] -> [a]
|
||||
335. List.+: : a -> [a] -> [a]
|
||||
336. List.:+ : [a] -> a -> [a]
|
||||
337. List.at : Nat -> [a] -> Optional a
|
||||
338. List.cons : a -> [a] -> [a]
|
||||
339. List.drop : Nat -> [a] -> [a]
|
||||
340. List.empty : [a]
|
||||
341. List.size : [a] -> Nat
|
||||
342. List.snoc : [a] -> a -> [a]
|
||||
343. List.take : Nat -> [a] -> [a]
|
||||
344. metadata.isPropagated : IsPropagated
|
||||
345. metadata.isTest : IsTest
|
||||
346. builtin type MutableArray
|
||||
347. MutableArray.copyTo! : MutableArray g a
|
||||
317. builtin type io2.Tls.SignedCert
|
||||
318. io2.Tls.terminate.impl : Tls ->{IO} Either Failure ()
|
||||
319. builtin type io2.Tls.Version
|
||||
320. unique type io2.TlsFailure
|
||||
321. builtin type io2.TVar
|
||||
322. io2.TVar.new : a ->{STM} TVar a
|
||||
323. io2.TVar.newIO : a ->{IO} TVar a
|
||||
324. io2.TVar.read : TVar a ->{STM} a
|
||||
325. io2.TVar.readIO : TVar a ->{IO} a
|
||||
326. io2.TVar.swap : TVar a -> a ->{STM} a
|
||||
327. io2.TVar.write : TVar a -> a ->{STM} ()
|
||||
328. io2.validateSandboxed : [Term] -> a -> Boolean
|
||||
329. unique type IsPropagated
|
||||
330. IsPropagated.IsPropagated : IsPropagated
|
||||
331. unique type IsTest
|
||||
332. IsTest.IsTest : IsTest
|
||||
333. unique type Link
|
||||
334. builtin type Link.Term
|
||||
335. Link.Term : Term -> Link
|
||||
336. Link.Term.toText : Term -> Text
|
||||
337. builtin type Link.Type
|
||||
338. Link.Type : Type -> Link
|
||||
339. builtin type List
|
||||
340. List.++ : [a] -> [a] -> [a]
|
||||
341. List.+: : a -> [a] -> [a]
|
||||
342. List.:+ : [a] -> a -> [a]
|
||||
343. List.at : Nat -> [a] -> Optional a
|
||||
344. List.cons : a -> [a] -> [a]
|
||||
345. List.drop : Nat -> [a] -> [a]
|
||||
346. List.empty : [a]
|
||||
347. List.size : [a] -> Nat
|
||||
348. List.snoc : [a] -> a -> [a]
|
||||
349. List.take : Nat -> [a] -> [a]
|
||||
350. metadata.isPropagated : IsPropagated
|
||||
351. metadata.isTest : IsTest
|
||||
352. builtin type MutableArray
|
||||
353. MutableArray.copyTo! : MutableArray g a
|
||||
-> Nat
|
||||
-> MutableArray g a
|
||||
-> Nat
|
||||
-> Nat
|
||||
->{g, Exception} ()
|
||||
348. MutableArray.freeze : MutableArray g a
|
||||
354. MutableArray.freeze : MutableArray g a
|
||||
-> Nat
|
||||
-> Nat
|
||||
->{g} ImmutableArray a
|
||||
349. MutableArray.freeze! : MutableArray g a
|
||||
355. MutableArray.freeze! : MutableArray g a
|
||||
->{g} ImmutableArray a
|
||||
350. MutableArray.read : MutableArray g a
|
||||
356. MutableArray.read : MutableArray g a
|
||||
-> Nat
|
||||
->{g, Exception} a
|
||||
351. MutableArray.size : MutableArray g a -> Nat
|
||||
352. MutableArray.write : MutableArray g a
|
||||
357. MutableArray.size : MutableArray g a -> Nat
|
||||
358. MutableArray.write : MutableArray g a
|
||||
-> Nat
|
||||
-> a
|
||||
->{g, Exception} ()
|
||||
353. builtin type MutableByteArray
|
||||
354. MutableByteArray.copyTo! : MutableByteArray g
|
||||
359. builtin type MutableByteArray
|
||||
360. MutableByteArray.copyTo! : MutableByteArray g
|
||||
-> Nat
|
||||
-> MutableByteArray g
|
||||
-> Nat
|
||||
-> Nat
|
||||
->{g, Exception} ()
|
||||
355. MutableByteArray.freeze : MutableByteArray g
|
||||
361. MutableByteArray.freeze : MutableByteArray g
|
||||
-> Nat
|
||||
-> Nat
|
||||
->{g} ImmutableByteArray
|
||||
356. MutableByteArray.freeze! : MutableByteArray g
|
||||
362. MutableByteArray.freeze! : MutableByteArray g
|
||||
->{g} ImmutableByteArray
|
||||
357. MutableByteArray.read16be : MutableByteArray g
|
||||
363. MutableByteArray.read16be : MutableByteArray g
|
||||
-> Nat
|
||||
->{g, Exception} Nat
|
||||
358. MutableByteArray.read24be : MutableByteArray g
|
||||
364. MutableByteArray.read24be : MutableByteArray g
|
||||
-> Nat
|
||||
->{g, Exception} Nat
|
||||
359. MutableByteArray.read32be : MutableByteArray g
|
||||
365. MutableByteArray.read32be : MutableByteArray g
|
||||
-> Nat
|
||||
->{g, Exception} Nat
|
||||
360. MutableByteArray.read40be : MutableByteArray g
|
||||
366. MutableByteArray.read40be : MutableByteArray g
|
||||
-> Nat
|
||||
->{g, Exception} Nat
|
||||
361. MutableByteArray.read64be : MutableByteArray g
|
||||
367. MutableByteArray.read64be : MutableByteArray g
|
||||
-> Nat
|
||||
->{g, Exception} Nat
|
||||
362. MutableByteArray.read8 : MutableByteArray g
|
||||
368. MutableByteArray.read8 : MutableByteArray g
|
||||
-> Nat
|
||||
->{g, Exception} Nat
|
||||
363. MutableByteArray.size : MutableByteArray g -> Nat
|
||||
364. MutableByteArray.write16be : MutableByteArray g
|
||||
369. MutableByteArray.size : MutableByteArray g -> Nat
|
||||
370. MutableByteArray.write16be : MutableByteArray g
|
||||
-> Nat
|
||||
-> Nat
|
||||
->{g, Exception} ()
|
||||
365. MutableByteArray.write32be : MutableByteArray g
|
||||
371. MutableByteArray.write32be : MutableByteArray g
|
||||
-> Nat
|
||||
-> Nat
|
||||
->{g, Exception} ()
|
||||
366. MutableByteArray.write64be : MutableByteArray g
|
||||
372. MutableByteArray.write64be : MutableByteArray g
|
||||
-> Nat
|
||||
-> Nat
|
||||
->{g, Exception} ()
|
||||
367. MutableByteArray.write8 : MutableByteArray g
|
||||
373. MutableByteArray.write8 : MutableByteArray g
|
||||
-> Nat
|
||||
-> Nat
|
||||
->{g, Exception} ()
|
||||
368. builtin type Nat
|
||||
369. Nat.* : Nat -> Nat -> Nat
|
||||
370. Nat.+ : Nat -> Nat -> Nat
|
||||
371. Nat./ : Nat -> Nat -> Nat
|
||||
372. Nat.and : Nat -> Nat -> Nat
|
||||
373. Nat.complement : Nat -> Nat
|
||||
374. Nat.drop : Nat -> Nat -> Nat
|
||||
375. Nat.eq : Nat -> Nat -> Boolean
|
||||
376. Nat.fromText : Text -> Optional Nat
|
||||
377. Nat.gt : Nat -> Nat -> Boolean
|
||||
378. Nat.gteq : Nat -> Nat -> Boolean
|
||||
379. Nat.increment : Nat -> Nat
|
||||
380. Nat.isEven : Nat -> Boolean
|
||||
381. Nat.isOdd : Nat -> Boolean
|
||||
382. Nat.leadingZeros : Nat -> Nat
|
||||
383. Nat.lt : Nat -> Nat -> Boolean
|
||||
384. Nat.lteq : Nat -> Nat -> Boolean
|
||||
385. Nat.mod : Nat -> Nat -> Nat
|
||||
386. Nat.or : Nat -> Nat -> Nat
|
||||
387. Nat.popCount : Nat -> Nat
|
||||
388. Nat.pow : Nat -> Nat -> Nat
|
||||
389. Nat.shiftLeft : Nat -> Nat -> Nat
|
||||
390. Nat.shiftRight : Nat -> Nat -> Nat
|
||||
391. Nat.sub : Nat -> Nat -> Int
|
||||
392. Nat.toFloat : Nat -> Float
|
||||
393. Nat.toInt : Nat -> Int
|
||||
394. Nat.toText : Nat -> Text
|
||||
395. Nat.trailingZeros : Nat -> Nat
|
||||
396. Nat.xor : Nat -> Nat -> Nat
|
||||
397. structural type Optional a
|
||||
398. Optional.None : Optional a
|
||||
399. Optional.Some : a -> Optional a
|
||||
400. builtin type Pattern
|
||||
401. Pattern.capture : Pattern a -> Pattern a
|
||||
402. Pattern.isMatch : Pattern a -> a -> Boolean
|
||||
403. Pattern.join : [Pattern a] -> Pattern a
|
||||
404. Pattern.many : Pattern a -> Pattern a
|
||||
405. Pattern.or : Pattern a -> Pattern a -> Pattern a
|
||||
406. Pattern.replicate : Nat -> Nat -> Pattern a -> Pattern a
|
||||
407. Pattern.run : Pattern a -> a -> Optional ([a], a)
|
||||
408. builtin type Ref
|
||||
409. Ref.read : Ref g a ->{g} a
|
||||
410. Ref.write : Ref g a -> a ->{g} ()
|
||||
411. builtin type Request
|
||||
412. builtin type Scope
|
||||
413. Scope.array : Nat ->{Scope s} MutableArray (Scope s) a
|
||||
414. Scope.arrayOf : a
|
||||
374. builtin type Nat
|
||||
375. Nat.* : Nat -> Nat -> Nat
|
||||
376. Nat.+ : Nat -> Nat -> Nat
|
||||
377. Nat./ : Nat -> Nat -> Nat
|
||||
378. Nat.and : Nat -> Nat -> Nat
|
||||
379. Nat.complement : Nat -> Nat
|
||||
380. Nat.drop : Nat -> Nat -> Nat
|
||||
381. Nat.eq : Nat -> Nat -> Boolean
|
||||
382. Nat.fromText : Text -> Optional Nat
|
||||
383. Nat.gt : Nat -> Nat -> Boolean
|
||||
384. Nat.gteq : Nat -> Nat -> Boolean
|
||||
385. Nat.increment : Nat -> Nat
|
||||
386. Nat.isEven : Nat -> Boolean
|
||||
387. Nat.isOdd : Nat -> Boolean
|
||||
388. Nat.leadingZeros : Nat -> Nat
|
||||
389. Nat.lt : Nat -> Nat -> Boolean
|
||||
390. Nat.lteq : Nat -> Nat -> Boolean
|
||||
391. Nat.mod : Nat -> Nat -> Nat
|
||||
392. Nat.or : Nat -> Nat -> Nat
|
||||
393. Nat.popCount : Nat -> Nat
|
||||
394. Nat.pow : Nat -> Nat -> Nat
|
||||
395. Nat.shiftLeft : Nat -> Nat -> Nat
|
||||
396. Nat.shiftRight : Nat -> Nat -> Nat
|
||||
397. Nat.sub : Nat -> Nat -> Int
|
||||
398. Nat.toFloat : Nat -> Float
|
||||
399. Nat.toInt : Nat -> Int
|
||||
400. Nat.toText : Nat -> Text
|
||||
401. Nat.trailingZeros : Nat -> Nat
|
||||
402. Nat.xor : Nat -> Nat -> Nat
|
||||
403. structural type Optional a
|
||||
404. Optional.None : Optional a
|
||||
405. Optional.Some : a -> Optional a
|
||||
406. builtin type Pattern
|
||||
407. Pattern.capture : Pattern a -> Pattern a
|
||||
408. Pattern.isMatch : Pattern a -> a -> Boolean
|
||||
409. Pattern.join : [Pattern a] -> Pattern a
|
||||
410. Pattern.many : Pattern a -> Pattern a
|
||||
411. Pattern.or : Pattern a -> Pattern a -> Pattern a
|
||||
412. Pattern.replicate : Nat -> Nat -> Pattern a -> Pattern a
|
||||
413. Pattern.run : Pattern a -> a -> Optional ([a], a)
|
||||
414. builtin type Ref
|
||||
415. Ref.read : Ref g a ->{g} a
|
||||
416. Ref.write : Ref g a -> a ->{g} ()
|
||||
417. builtin type Request
|
||||
418. builtin type Scope
|
||||
419. Scope.array : Nat ->{Scope s} MutableArray (Scope s) a
|
||||
420. Scope.arrayOf : a
|
||||
-> Nat
|
||||
->{Scope s} MutableArray (Scope s) a
|
||||
415. Scope.bytearray : Nat
|
||||
421. Scope.bytearray : Nat
|
||||
->{Scope s} MutableByteArray (Scope s)
|
||||
416. Scope.bytearrayOf : Nat
|
||||
422. Scope.bytearrayOf : Nat
|
||||
-> Nat
|
||||
->{Scope s} MutableByteArray
|
||||
(Scope s)
|
||||
417. Scope.ref : a ->{Scope s} Ref {Scope s} a
|
||||
418. Scope.run : (∀ s. '{g, Scope s} r) ->{g} r
|
||||
419. structural type SeqView a b
|
||||
420. SeqView.VElem : a -> b -> SeqView a b
|
||||
421. SeqView.VEmpty : SeqView a b
|
||||
422. Socket.toText : Socket -> Text
|
||||
423. unique type Test.Result
|
||||
424. Test.Result.Fail : Text -> Result
|
||||
425. Test.Result.Ok : Text -> Result
|
||||
426. builtin type Text
|
||||
427. Text.!= : Text -> Text -> Boolean
|
||||
428. Text.++ : Text -> Text -> Text
|
||||
429. Text.drop : Nat -> Text -> Text
|
||||
430. Text.empty : Text
|
||||
431. Text.eq : Text -> Text -> Boolean
|
||||
432. Text.fromCharList : [Char] -> Text
|
||||
433. Text.fromUtf8.impl : Bytes -> Either Failure Text
|
||||
434. Text.gt : Text -> Text -> Boolean
|
||||
435. Text.gteq : Text -> Text -> Boolean
|
||||
436. Text.lt : Text -> Text -> Boolean
|
||||
437. Text.lteq : Text -> Text -> Boolean
|
||||
438. Text.patterns.anyChar : Pattern Text
|
||||
439. Text.patterns.charIn : [Char] -> Pattern Text
|
||||
440. Text.patterns.charRange : Char -> Char -> Pattern Text
|
||||
441. Text.patterns.digit : Pattern Text
|
||||
442. Text.patterns.eof : Pattern Text
|
||||
443. Text.patterns.letter : Pattern Text
|
||||
444. Text.patterns.literal : Text -> Pattern Text
|
||||
445. Text.patterns.notCharIn : [Char] -> Pattern Text
|
||||
446. Text.patterns.notCharRange : Char -> Char -> Pattern Text
|
||||
447. Text.patterns.punctuation : Pattern Text
|
||||
448. Text.patterns.space : Pattern Text
|
||||
449. Text.repeat : Nat -> Text -> Text
|
||||
450. Text.reverse : Text -> Text
|
||||
451. Text.size : Text -> Nat
|
||||
452. Text.take : Nat -> Text -> Text
|
||||
453. Text.toCharList : Text -> [Char]
|
||||
454. Text.toLowercase : Text -> Text
|
||||
455. Text.toUppercase : Text -> Text
|
||||
456. Text.toUtf8 : Text -> Bytes
|
||||
457. Text.uncons : Text -> Optional (Char, Text)
|
||||
458. Text.unsnoc : Text -> Optional (Text, Char)
|
||||
459. ThreadId.toText : ThreadId -> Text
|
||||
460. todo : a -> b
|
||||
461. structural type Tuple a b
|
||||
462. Tuple.Cons : a -> b -> Tuple a b
|
||||
463. structural type Unit
|
||||
464. Unit.Unit : ()
|
||||
465. Universal.< : a -> a -> Boolean
|
||||
466. Universal.<= : a -> a -> Boolean
|
||||
467. Universal.== : a -> a -> Boolean
|
||||
468. Universal.> : a -> a -> Boolean
|
||||
469. Universal.>= : a -> a -> Boolean
|
||||
470. Universal.compare : a -> a -> Int
|
||||
471. Universal.murmurHash : a -> Nat
|
||||
472. unsafe.coerceAbilities : (a ->{e1} b) -> a ->{e2} b
|
||||
473. builtin type Value
|
||||
474. Value.dependencies : Value -> [Term]
|
||||
475. Value.deserialize : Bytes -> Either Text Value
|
||||
476. Value.load : Value ->{IO} Either [Term] a
|
||||
477. Value.serialize : Value -> Bytes
|
||||
478. Value.value : a -> Value
|
||||
423. Scope.ref : a ->{Scope s} Ref {Scope s} a
|
||||
424. Scope.run : (∀ s. '{g, Scope s} r) ->{g} r
|
||||
425. structural type SeqView a b
|
||||
426. SeqView.VElem : a -> b -> SeqView a b
|
||||
427. SeqView.VEmpty : SeqView a b
|
||||
428. Socket.toText : Socket -> Text
|
||||
429. unique type Test.Result
|
||||
430. Test.Result.Fail : Text -> Result
|
||||
431. Test.Result.Ok : Text -> Result
|
||||
432. builtin type Text
|
||||
433. Text.!= : Text -> Text -> Boolean
|
||||
434. Text.++ : Text -> Text -> Text
|
||||
435. Text.drop : Nat -> Text -> Text
|
||||
436. Text.empty : Text
|
||||
437. Text.eq : Text -> Text -> Boolean
|
||||
438. Text.fromCharList : [Char] -> Text
|
||||
439. Text.fromUtf8.impl : Bytes -> Either Failure Text
|
||||
440. Text.gt : Text -> Text -> Boolean
|
||||
441. Text.gteq : Text -> Text -> Boolean
|
||||
442. Text.lt : Text -> Text -> Boolean
|
||||
443. Text.lteq : Text -> Text -> Boolean
|
||||
444. Text.patterns.anyChar : Pattern Text
|
||||
445. Text.patterns.charIn : [Char] -> Pattern Text
|
||||
446. Text.patterns.charRange : Char -> Char -> Pattern Text
|
||||
447. Text.patterns.digit : Pattern Text
|
||||
448. Text.patterns.eof : Pattern Text
|
||||
449. Text.patterns.letter : Pattern Text
|
||||
450. Text.patterns.literal : Text -> Pattern Text
|
||||
451. Text.patterns.notCharIn : [Char] -> Pattern Text
|
||||
452. Text.patterns.notCharRange : Char -> Char -> Pattern Text
|
||||
453. Text.patterns.punctuation : Pattern Text
|
||||
454. Text.patterns.space : Pattern Text
|
||||
455. Text.repeat : Nat -> Text -> Text
|
||||
456. Text.reverse : Text -> Text
|
||||
457. Text.size : Text -> Nat
|
||||
458. Text.take : Nat -> Text -> Text
|
||||
459. Text.toCharList : Text -> [Char]
|
||||
460. Text.toLowercase : Text -> Text
|
||||
461. Text.toUppercase : Text -> Text
|
||||
462. Text.toUtf8 : Text -> Bytes
|
||||
463. Text.uncons : Text -> Optional (Char, Text)
|
||||
464. Text.unsnoc : Text -> Optional (Text, Char)
|
||||
465. ThreadId.toText : ThreadId -> Text
|
||||
466. todo : a -> b
|
||||
467. structural type Tuple a b
|
||||
468. Tuple.Cons : a -> b -> Tuple a b
|
||||
469. structural type Unit
|
||||
470. Unit.Unit : ()
|
||||
471. Universal.< : a -> a -> Boolean
|
||||
472. Universal.<= : a -> a -> Boolean
|
||||
473. Universal.== : a -> a -> Boolean
|
||||
474. Universal.> : a -> a -> Boolean
|
||||
475. Universal.>= : a -> a -> Boolean
|
||||
476. Universal.compare : a -> a -> Int
|
||||
477. Universal.murmurHash : a -> Nat
|
||||
478. unsafe.coerceAbilities : (a ->{e1} b) -> a ->{e2} b
|
||||
479. builtin type Value
|
||||
480. Value.dependencies : Value -> [Term]
|
||||
481. Value.deserialize : Bytes -> Either Text Value
|
||||
482. Value.load : Value ->{IO} Either [Term] a
|
||||
483. Value.serialize : Value -> Bytes
|
||||
484. Value.value : a -> Value
|
||||
|
||||
|
||||
.builtin> alias.many 94-104 .mylib
|
||||
|
@ -74,7 +74,7 @@ The `builtins.merge` command adds the known builtins to a `builtin` subnamespace
|
||||
63. Value/ (5 terms)
|
||||
64. bug (a -> b)
|
||||
65. crypto/ (12 terms, 1 type)
|
||||
66. io2/ (126 terms, 30 types)
|
||||
66. io2/ (131 terms, 31 types)
|
||||
67. metadata/ (2 terms)
|
||||
68. todo (a -> b)
|
||||
69. unsafe/ (1 term)
|
||||
|
@ -81,6 +81,8 @@ test> Int.tests.conversions =
|
||||
fromText "+0" == Some +0,
|
||||
fromText "a8f9djasdlfkj" == None,
|
||||
fromText "3940" == Some +3940,
|
||||
fromText "1000000000000000000000000000" == None,
|
||||
fromText "-1000000000000000000000000000" == None,
|
||||
toFloat +9394 == 9394.0,
|
||||
toFloat -20349 == -20349.0
|
||||
]
|
||||
@ -150,6 +152,8 @@ test> Nat.tests.conversions =
|
||||
toText 10 == "10",
|
||||
fromText "ooga" == None,
|
||||
fromText "90" == Some 90,
|
||||
fromText "-1" == None,
|
||||
fromText "100000000000000000000000000" == None,
|
||||
unsnoc "abc" == Some ("ab", ?c),
|
||||
uncons "abc" == Some (?a, "bc"),
|
||||
unsnoc "" == None,
|
||||
|
@ -74,6 +74,8 @@ test> Int.tests.conversions =
|
||||
fromText "+0" == Some +0,
|
||||
fromText "a8f9djasdlfkj" == None,
|
||||
fromText "3940" == Some +3940,
|
||||
fromText "1000000000000000000000000000" == None,
|
||||
fromText "-1000000000000000000000000000" == None,
|
||||
toFloat +9394 == 9394.0,
|
||||
toFloat -20349 == -20349.0
|
||||
]
|
||||
@ -139,6 +141,8 @@ test> Nat.tests.conversions =
|
||||
toText 10 == "10",
|
||||
fromText "ooga" == None,
|
||||
fromText "90" == Some 90,
|
||||
fromText "-1" == None,
|
||||
fromText "100000000000000000000000000" == None,
|
||||
unsnoc "abc" == Some ("ab", ?c),
|
||||
uncons "abc" == Some (?a, "bc"),
|
||||
unsnoc "" == None,
|
||||
|
@ -47,11 +47,15 @@ Deleting the root namespace should require confirmation if not forced.
|
||||
```ucm
|
||||
.> delete.namespace .
|
||||
.> delete.namespace .
|
||||
-- Should have an empty history
|
||||
.> history .
|
||||
```
|
||||
|
||||
Deleting the root namespace shouldn't require confirmation if forced.
|
||||
|
||||
```ucm
|
||||
.> delete.namespace.force .
|
||||
-- Should have an empty history
|
||||
.> history .
|
||||
```
|
||||
|
||||
|
@ -86,6 +86,11 @@ Deleting the root namespace should require confirmation if not forced.
|
||||
undo, or `builtins.merge` to restore the absolute basics to
|
||||
the current path.
|
||||
|
||||
-- Should have an empty history
|
||||
.> history .
|
||||
|
||||
☝️ The namespace . is empty.
|
||||
|
||||
```
|
||||
Deleting the root namespace shouldn't require confirmation if forced.
|
||||
|
||||
@ -96,4 +101,9 @@ Deleting the root namespace shouldn't require confirmation if forced.
|
||||
undo, or `builtins.merge` to restore the absolute basics to
|
||||
the current path.
|
||||
|
||||
-- Should have an empty history
|
||||
.> history .
|
||||
|
||||
☝️ The namespace . is empty.
|
||||
|
||||
```
|
||||
|
@ -33,14 +33,6 @@ ex2 tup = match tup with
|
||||
(a, b, (c,d)) -> c + d
|
||||
```
|
||||
|
||||
Syntactically, the left-hand side of the bind can be any pattern and can even include guards, for instance, see below. Because a destructuring bind desugars to a regular pattern match, pattern match coverage will eventually cause this to not typecheck:
|
||||
|
||||
```unison:hide
|
||||
ex3 =
|
||||
Some x | x > 10 = Some 19
|
||||
x + 1
|
||||
```
|
||||
|
||||
## Corner cases
|
||||
|
||||
Destructuring binds can't be recursive: the left-hand side bound variables aren't available on the right hand side. For instance, this doesn't typecheck:
|
||||
|
@ -71,14 +71,6 @@ ex2 tup = match tup with
|
||||
(also named ex1)
|
||||
|
||||
```
|
||||
Syntactically, the left-hand side of the bind can be any pattern and can even include guards, for instance, see below. Because a destructuring bind desugars to a regular pattern match, pattern match coverage will eventually cause this to not typecheck:
|
||||
|
||||
```unison
|
||||
ex3 =
|
||||
Some x | x > 10 = Some 19
|
||||
x + 1
|
||||
```
|
||||
|
||||
## Corner cases
|
||||
|
||||
Destructuring binds can't be recursive: the left-hand side bound variables aren't available on the right hand side. For instance, this doesn't typecheck:
|
||||
|
@ -22,15 +22,15 @@ The deleted namespace shouldn't appear in `ls` output.
|
||||
|
||||
## history
|
||||
|
||||
The history of the namespace should still exist if requested explicitly.
|
||||
The history of the namespace should be empty.
|
||||
|
||||
```ucm
|
||||
.> history mynamespace
|
||||
```
|
||||
|
||||
Merging an empty namespace should still copy its history if it has some.
|
||||
Merging an empty namespace should be a no-op
|
||||
|
||||
```ucm
|
||||
```ucm:error
|
||||
.empty> history
|
||||
.empty> merge .mynamespace
|
||||
.empty> history
|
||||
|
@ -47,24 +47,15 @@ The deleted namespace shouldn't appear in `ls` output.
|
||||
```
|
||||
## history
|
||||
|
||||
The history of the namespace should still exist if requested explicitly.
|
||||
The history of the namespace should be empty.
|
||||
|
||||
```ucm
|
||||
.> history mynamespace
|
||||
|
||||
Note: The most recent namespace hash is immediately below this
|
||||
message.
|
||||
|
||||
⊙ 1. #nvh8d4j0fm
|
||||
|
||||
- Deletes:
|
||||
|
||||
x
|
||||
|
||||
□ 2. #i52j9fd57b (start of history)
|
||||
☝️ The namespace .mynamespace is empty.
|
||||
|
||||
```
|
||||
Merging an empty namespace should still copy its history if it has some.
|
||||
Merging an empty namespace should be a no-op
|
||||
|
||||
```ucm
|
||||
☝️ The namespace .empty is empty.
|
||||
@ -75,20 +66,13 @@ Merging an empty namespace should still copy its history if it has some.
|
||||
|
||||
.empty> merge .mynamespace
|
||||
|
||||
Nothing changed as a result of the merge.
|
||||
⚠️
|
||||
|
||||
The namespace .mynamespace doesn't exist.
|
||||
|
||||
.empty> history
|
||||
|
||||
Note: The most recent namespace hash is immediately below this
|
||||
message.
|
||||
|
||||
⊙ 1. #nvh8d4j0fm
|
||||
|
||||
- Deletes:
|
||||
|
||||
x
|
||||
|
||||
□ 2. #i52j9fd57b (start of history)
|
||||
☝️ The namespace .empty is empty.
|
||||
|
||||
```
|
||||
Add and then delete a term to add some history to a deleted namespace.
|
||||
|
@ -23,7 +23,7 @@ Technically, the definitions all exist, but they have no names. `builtins.merge`
|
||||
|
||||
.foo> ls
|
||||
|
||||
1. builtin/ (415 terms, 63 types)
|
||||
1. builtin/ (420 terms, 64 types)
|
||||
|
||||
```
|
||||
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/ (587 terms, 81 types)
|
||||
1. builtin/ (592 terms, 82 types)
|
||||
|
||||
```
|
||||
More typically, you'd start out by pulling `base.
|
||||
|
@ -49,7 +49,8 @@ y = "hello"
|
||||
|
||||
Notice that `master` now has the definition of `y` we wrote.
|
||||
|
||||
We can also delete the fork if we're done with it. (Don't worry, it's still in the `history` and can be resurrected at any time.)
|
||||
We can also delete the fork if we're done with it. (Don't worry, even though the history at that path is now empty,
|
||||
it's still in the `history` of the parent namespace and can be resurrected at any time.)
|
||||
|
||||
```ucm
|
||||
.> delete.namespace .feature1
|
||||
|
@ -96,7 +96,8 @@ y = "hello"
|
||||
|
||||
Notice that `master` now has the definition of `y` we wrote.
|
||||
|
||||
We can also delete the fork if we're done with it. (Don't worry, it's still in the `history` and can be resurrected at any time.)
|
||||
We can also delete the fork if we're done with it. (Don't worry, even though the history at that path is now empty,
|
||||
it's still in the `history` of the parent namespace and can be resurrected at any time.)
|
||||
|
||||
```ucm
|
||||
.> delete.namespace .feature1
|
||||
@ -105,29 +106,20 @@ We can also delete the fork if we're done with it. (Don't worry, it's still in t
|
||||
|
||||
.> history .feature1
|
||||
|
||||
Note: The most recent namespace hash is immediately below this
|
||||
message.
|
||||
|
||||
⊙ 1. #hsbtlt2og6
|
||||
|
||||
- Deletes:
|
||||
|
||||
y
|
||||
|
||||
□ 2. #q95r47tc4l (start of history)
|
||||
☝️ The namespace .feature1 is empty.
|
||||
|
||||
.> history
|
||||
|
||||
Note: The most recent namespace hash is immediately below this
|
||||
message.
|
||||
|
||||
⊙ 1. #ut7mk2guld
|
||||
⊙ 1. #492bge1qkb
|
||||
|
||||
- Deletes:
|
||||
|
||||
feature1.y
|
||||
|
||||
⊙ 2. #oaneanmrn8
|
||||
⊙ 2. #qdsgea37fc
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
@ -138,26 +130,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
|
||||
|
||||
⊙ 3. #m6o57p1elr
|
||||
⊙ 3. #ppkkh269f7
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
feature1.y
|
||||
|
||||
⊙ 4. #ep8ckbhnqt
|
||||
⊙ 4. #u8aiheqfug
|
||||
|
||||
> Moves:
|
||||
|
||||
Original name New name
|
||||
x master.x
|
||||
|
||||
⊙ 5. #t7aklphn43
|
||||
⊙ 5. #es9cmc7kok
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
x
|
||||
|
||||
□ 6. #l6lcr63iti (start of history)
|
||||
□ 6. #jo7t8m4dft (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`.
|
||||
|
@ -58,7 +58,9 @@ b.termInB = 11
|
||||
.history> update
|
||||
```
|
||||
|
||||
Now, if we soft-delete a namespace, but move another over it we expect the history to be replaced, and we expect the history from the source to be wiped out.
|
||||
Deleting a namespace should not leave behind any history,
|
||||
if we move another to that location we expect the history to simply be the history
|
||||
of the moved namespace.
|
||||
|
||||
```ucm
|
||||
.history> delete.namespace b
|
||||
|
@ -150,7 +150,9 @@ b.termInB = 11
|
||||
b.termInB : Nat
|
||||
|
||||
```
|
||||
Now, if we soft-delete a namespace, but move another over it we expect the history to be replaced, and we expect the history from the source to be wiped out.
|
||||
Deleting a namespace should not leave behind any history,
|
||||
if we move another to that location we expect the history to simply be the history
|
||||
of the moved namespace.
|
||||
|
||||
```ucm
|
||||
.history> delete.namespace b
|
||||
@ -267,7 +269,7 @@ I should be able to move the root into a sub-namespace
|
||||
|
||||
.> ls
|
||||
|
||||
1. root/ (592 terms, 82 types)
|
||||
1. root/ (597 terms, 83 types)
|
||||
|
||||
.> history
|
||||
|
||||
@ -276,13 +278,13 @@ I should be able to move the root into a sub-namespace
|
||||
|
||||
|
||||
|
||||
□ 1. #o2vkdh7ltv (start of history)
|
||||
□ 1. #bn675bbtpm (start of history)
|
||||
|
||||
```
|
||||
```ucm
|
||||
.> ls .root.at.path
|
||||
|
||||
1. builtin/ (587 terms, 81 types)
|
||||
1. builtin/ (592 terms, 82 types)
|
||||
2. existing/ (1 term)
|
||||
3. happy/ (3 terms, 1 type)
|
||||
4. history/ (1 term)
|
||||
@ -292,7 +294,7 @@ I should be able to move the root into a sub-namespace
|
||||
Note: The most recent namespace hash is immediately below this
|
||||
message.
|
||||
|
||||
⊙ 1. #i0lk1c81v7
|
||||
⊙ 1. #vor04lbt72
|
||||
|
||||
- Deletes:
|
||||
|
||||
@ -303,7 +305,7 @@ I should be able to move the root into a sub-namespace
|
||||
Original name New name
|
||||
existing.a.termInA existing.b.termInA
|
||||
|
||||
⊙ 2. #64lmvl3fbe
|
||||
⊙ 2. #tk3qtdeoov
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
@ -315,26 +317,26 @@ I should be able to move the root into a sub-namespace
|
||||
happy.b.termInA existing.a.termInA
|
||||
history.b.termInA existing.a.termInA
|
||||
|
||||
⊙ 3. #1upc23ts8h
|
||||
⊙ 3. #r971i7m95i
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
existing.a.termInA existing.b.termInB
|
||||
|
||||
⊙ 4. #hp3nttbbeu
|
||||
⊙ 4. #6qh988adub
|
||||
|
||||
> Moves:
|
||||
|
||||
Original name New name
|
||||
history.a.termInA history.b.termInA
|
||||
|
||||
⊙ 5. #3vt487avqa
|
||||
⊙ 5. #g19mlrid0i
|
||||
|
||||
- Deletes:
|
||||
|
||||
history.b.termInB
|
||||
|
||||
⊙ 6. #cng5456u5h
|
||||
⊙ 6. #n0a5seofan
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
@ -345,13 +347,13 @@ I should be able to move the root into a sub-namespace
|
||||
Original name New name(s)
|
||||
happy.b.termInA history.a.termInA
|
||||
|
||||
⊙ 7. #6s6rta6dft
|
||||
⊙ 7. #i3nsbtl7kc
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
history.a.termInA history.b.termInB
|
||||
|
||||
⊙ 8. #ri5k67h719
|
||||
⊙ 8. #a2u0kep087
|
||||
|
||||
> Moves:
|
||||
|
||||
@ -361,7 +363,7 @@ I should be able to move the root into a sub-namespace
|
||||
happy.a.T.T2 happy.b.T.T2
|
||||
happy.a.termInA happy.b.termInA
|
||||
|
||||
⊙ 9. #5lhn2nqa5u
|
||||
⊙ 9. #g18uf760mb
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
@ -371,7 +373,7 @@ I should be able to move the root into a sub-namespace
|
||||
|
||||
happy.a.T.T
|
||||
|
||||
⊙ 10. #2oljit38kd
|
||||
⊙ 10. #2edl4803r1
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
@ -383,7 +385,7 @@ I should be able to move the root into a sub-namespace
|
||||
|
||||
⠇
|
||||
|
||||
⊙ 11. #95soup1m3q
|
||||
⊙ 11. #qcd5obbuv8
|
||||
|
||||
|
||||
```
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -59,17 +59,17 @@ y = 2
|
||||
most recent, along with the command that got us there. Try:
|
||||
|
||||
`fork 2 .old`
|
||||
`fork #c50ilio6t7 .old` to make an old namespace
|
||||
`fork #2b8npf0tu2 .old` to make an old namespace
|
||||
accessible again,
|
||||
|
||||
`reset-root #c50ilio6t7` to reset the root namespace and
|
||||
`reset-root #2b8npf0tu2` to reset the root namespace and
|
||||
its history to that of the
|
||||
specified namespace.
|
||||
|
||||
When Root Hash Action
|
||||
1. now #r1ojo66sp7 add
|
||||
2. now #c50ilio6t7 add
|
||||
3. now #k0vh8qed2b builtins.merge
|
||||
1. now #j967usn5hk add
|
||||
2. now #2b8npf0tu2 add
|
||||
3. now #lv9og66mct builtins.merge
|
||||
4. #sg60bvjo91 history starts here
|
||||
|
||||
Tip: Use `diff.namespace 1 7` to compare namespaces between
|
||||
|
@ -13,7 +13,7 @@ Let's look at some examples. We'll start with a namespace with just the builtins
|
||||
|
||||
|
||||
|
||||
□ 1. #61h5m6vr8d (start of history)
|
||||
□ 1. #a2uij441jg (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.
|
||||
|
||||
⊙ 1. #h3t1td6j70
|
||||
⊙ 1. #2orc0vqqcv
|
||||
|
||||
> Moves:
|
||||
|
||||
Original name New name
|
||||
Nat.frobnicate Nat.+
|
||||
|
||||
⊙ 2. #hof2b14ggf
|
||||
⊙ 2. #fk0nmiqqgk
|
||||
|
||||
> Moves:
|
||||
|
||||
Original name New name
|
||||
Nat.+ Nat.frobnicate
|
||||
|
||||
□ 3. #61h5m6vr8d (start of history)
|
||||
□ 3. #a2uij441jg (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.
|
||||
|
||||
⊙ 1. #h3t1td6j70
|
||||
⊙ 1. #2orc0vqqcv
|
||||
|
||||
> Moves:
|
||||
|
||||
Original name New name
|
||||
Nat.frobnicate Nat.+
|
||||
|
||||
⊙ 2. #hof2b14ggf
|
||||
⊙ 2. #fk0nmiqqgk
|
||||
|
||||
> Moves:
|
||||
|
||||
Original name New name
|
||||
Nat.+ Nat.frobnicate
|
||||
|
||||
□ 3. #61h5m6vr8d (start of history)
|
||||
□ 3. #a2uij441jg (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
|
||||
|
||||
|
||||
|
||||
□ 1. #61h5m6vr8d (start of history)
|
||||
□ 1. #a2uij441jg (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.
|
||||
|
||||
⊙ 1. #v3tbgssvfo
|
||||
⊙ 1. #9ijnd9ip7o
|
||||
|
||||
- Deletes:
|
||||
|
||||
Nat.* Nat.+
|
||||
|
||||
□ 2. #61h5m6vr8d (start of history)
|
||||
□ 2. #a2uij441jg (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.
|
||||
|
Loading…
Reference in New Issue
Block a user