Merge branch 'trunk' into kylegoetz-udp

# Conflicts:
#	unison-src/transcripts-using-base/all-base-hashes.output.md
#	unison-src/transcripts/builtins-merge.output.md
#	unison-src/transcripts/emptyCodebase.output.md
#	unison-src/transcripts/merges.output.md
#	unison-src/transcripts/move-all.output.md
#	unison-src/transcripts/move-namespace.output.md
#	unison-src/transcripts/reflog.output.md
#	unison-src/transcripts/reset.output.md
#	unison-src/transcripts/squash.output.md
#	unison-src/transcripts/upgrade-happy-path.output.md
This commit is contained in:
Arya Irani 2024-04-02 00:19:42 -06:00
commit 1be5cf2d1d
37 changed files with 996 additions and 521 deletions

View File

@ -1,99 +0,0 @@
name: build optimized ucm
on:
workflow_call:
inputs:
ref:
description: Git ref to check out for this build, e.g. `trunk` or `release/0.5.19`
type: string
required: true
stack-cache-prefix:
description: The Stack cache prefix to use for builds
type: string
default: release
defaults:
run:
shell: bash
jobs:
build-ucm:
name: bundle ucm+ui ${{matrix.os}}
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, macos-12, windows-2019]
steps:
- uses: actions/checkout@v4
with:
ref: ${{inputs.ref}}
- name: restore stack caches
uses: unisonweb/actions/stack/cache/restore@main
with:
cache-prefix: release
- name: install stack
uses: unisonweb/actions/stack/install@main
- name: build
run: |
# unison-cli embeds version numbers using TH
# so it needs to be forced to rebuild to ensure those are updated.
stack clean unison-cli-main
# Windows will crash on build intermittently because the filesystem
# sucks at managing concurrent file access;
# Just keep retrying on these failures.
tries=5
for (( i = 0; i < $tries; i++ )); do
stack build unison-cli-main \
--flag unison-parser-typechecker:optimized \
&& break;
done
- name: save stack caches
uses: unisonweb/actions/stack/cache/save@main
with:
cache-prefix: release
- name: set up environment
run: |
if [[ ${{runner.os}} = 'Windows' ]]; then
artifact_os="windows"
elif [[ ${{runner.os}} = 'macOS' ]]; then
artifact_os="osx"
elif [[ ${{runner.os}} = 'Linux' ]]; then
artifact_os="linux"
else
echo "Unexpected OS: ${{runner.os}}"
exit 1
fi
echo "artifact_os=$artifact_os" >> $GITHUB_ENV
- name: fetch latest Unison Local UI and package with ucm
run: |
mkdir /tmp/ucm
cp -v $(stack exec -- which unison) /tmp/ucm/ucm
curl -L -o /tmp/unisonLocal.zip \
https://github.com/unisonweb/unison-local-ui/releases/download/latest/unisonLocal.zip
mkdir /tmp/ucm/ui
unzip -d /tmp/ucm/ui /tmp/unisonLocal.zip
if [[ ${{runner.os}} = 'Windows' ]]; then
artifact_archive=ucm-${{env.artifact_os}}.zip
7z a -r -tzip ${artifact_archive} /tmp/ucm/*
else
artifact_archive=ucm-${{env.artifact_os}}.tar.gz
tar -c -z -f ${artifact_archive} -C /tmp/ucm .
fi
echo "artifact_archive=${artifact_archive}" >> $GITHUB_ENV
- name: upload artifact
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: build-${{env.artifact_os}}
path: ${{env.artifact_archive}}

261
.github/workflows/bundle-ucm.yaml vendored Normal file
View File

@ -0,0 +1,261 @@
name: bundle ucm
# build optimized ucm
# package racket lib
# build/dist unison-runtime
on:
workflow_call:
inputs:
ref:
description: Git ref to check out for this build, e.g. `trunk` or `release/0.5.19`
type: string
required: true
env:
racket_version: "8.7"
defaults:
run:
shell: bash
jobs:
build-ucm:
name: build ucm
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, macos-12, windows-2019]
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
with:
ref: ${{inputs.ref}}
- name: restore stack caches
uses: unisonweb/actions/stack/cache/restore@main
with:
cache-prefix: release
- name: install stack
uses: unisonweb/actions/stack/install@main
- name: build
run: |
# unison-cli-main embeds version numbers using TH
# so it needs to be forced to rebuild to ensure those are updated.
stack clean unison-cli-main
mkdir ucm-bin
# Windows will crash on build intermittently because the filesystem
# sucks at managing concurrent file access;
# Just keep retrying on these failures.
tries=5
for (( i = 0; i < $tries; i++ )); do
stack build :unison \
--flag unison-parser-typechecker:optimized \
--local-bin-path ucm-bin \
--copy-bins \
&& break;
done
if [[ ${{runner.os}} = 'Windows' ]]; then
ucm=$(stack exec where unison)
else
ucm=$(stack exec which unison)
fi
echo ucm="$ucm" >> $GITHUB_ENV
ls -l $ucm
- name: save stack caches
uses: unisonweb/actions/stack/cache/save@main
with:
cache-prefix: release
- name: upload ucm
uses: actions/upload-artifact@v4
with:
name: unison-${{matrix.os}}
path: ${{ env.ucm }}
if-no-files-found: error
package-racket-lib:
strategy:
matrix:
os: [ubuntu-20.04]
needs: build-ucm
name: package racket lib
runs-on: ${{matrix.os}}
steps:
- name: set up environment
run: echo "ucm=${{ runner.temp }}/unison" >> $GITHUB_ENV
- name: download racket `unison` source
uses: actions/checkout@v4
with:
ref: ${{inputs.ref}}
- name: download ucm artifact
uses: actions/download-artifact@v4
with:
name: unison-${{matrix.os}}
path: ${{ runner.temp }}
- name: generate source
run: |
chmod +x ${{ env.ucm }}
${{ env.ucm }} transcript unison-src/transcripts-manual/gen-racket-libs.md
- uses: Bogdanp/setup-racket@v1.11
with:
architecture: "x64"
distribution: "full"
variant: "CS"
version: ${{env.racket_version}}
- name: create racket lib
run: |
raco pkg create scheme-libs/racket/unison
ls -l scheme-libs/racket/unison.zip{,.CHECKSUM}
- name: upload racket lib
uses: actions/upload-artifact@v4
with:
name: racket-lib
path: |
scheme-libs/racket/unison.zip
scheme-libs/racket/unison.zip.CHECKSUM
if-no-files-found: error
build-dist-unison-runtime:
needs: package-racket-lib
name: build unison-runtime
strategy:
fail-fast: false
matrix:
os:
- ubuntu-20.04
- macos-12
- windows-2019
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
with:
ref: ${{inputs.ref}}
- name: download racket lib
uses: actions/download-artifact@v4
with:
name: racket-lib
path: scheme-libs/racket/
- name: Cache Racket dependencies
id: cache-racket-deps
uses: actions/cache@v4
with:
path: |
~/.cache/racket
~/.local/share/racket
~/Library/Racket/${{env.racket_version}}
# This isn't right because unison.zip is going to include different dates each time.
# Maybe we can unpack it and hash the contents.
key: ${{ runner.os }}-racket-${{env.racket_version}}-${{hashFiles('scheme-libs/racket/unison.zip')}}
- uses: Bogdanp/setup-racket@v1.11
with:
architecture: "x64"
distribution: "full"
variant: "CS"
version: ${{env.racket_version}}
- uses: awalsh128/cache-apt-pkgs-action@latest
if: runner.os == 'Linux'
with:
packages: libb2-dev
version: 1.0 # cache key version afaik
- name: install unison racket lib
if: steps.cache-racket-deps.outputs.cache-hit != 'true'
run: raco pkg install --auto scheme-libs/racket/unison.zip
- name: build unison-runtime
run: |
raco exe --embed-dlls --orig-exe scheme-libs/racket/unison-runtime.rkt
mkdir runtime
if [[ ${{runner.os}} = 'Windows' ]]; then exe=".exe"; else exe=""; fi
raco distribute runtime scheme-libs/racket/unison-runtime$exe
ls -l runtime/
- name: upload unison-runtime
uses: actions/upload-artifact@v4
with:
name: unison-runtime-${{matrix.os}}
path: runtime/
if-no-files-found: error
bundle:
name: bundle ucm, jit, and ui
needs: [build-ucm, package-racket-lib, build-dist-unison-runtime]
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, macos-12, windows-2019]
steps:
- name: set up environment
run: |
staging_dir="${RUNNER_TEMP//\\//}/ucm-staging"
artifact_os="$(echo $RUNNER_OS | tr '[:upper:]' '[:lower:]')"
echo "staging_dir=$staging_dir" >> $GITHUB_ENV
echo "artifact_os=$artifact_os" >> $GITHUB_ENV
- name: download ucm
uses: actions/download-artifact@v4
with:
name: unison-${{matrix.os}}
path: ${{env.staging_dir}}/unison/
- name: restore permissions on ucm
run: chmod +x ${{env.staging_dir}}/unison/unison
- name: download racket lib
uses: actions/download-artifact@v4
with:
name: racket-lib
path: ${{env.staging_dir}}/racket/
- name: download unison-runtime
uses: actions/download-artifact@v4
with:
name: unison-runtime-${{matrix.os}}
path: ${{env.staging_dir}}/runtime
- name: restore permissions on unison-runtime
# here we have the `if:` not because of the missing .exe on Windows,
# nor the lack of need to chmod, but because /runtime/bin/ probably doesn't exist
# due to differences in `raco distribute` on Windows vs macOS and Linux.
if: runner.os != 'Windows'
run: chmod +x ${{env.staging_dir}}/runtime/bin/unison-runtime
- name: download latest unison-local-ui
run: |
curl -L -o /tmp/unisonLocal.zip \
https://github.com/unisonweb/unison-local-ui/releases/download/latest/unisonLocal.zip
unzip -d ${{env.staging_dir}}/ui /tmp/unisonLocal.zip
- name: create startup script (non-Windows)
if: runner.os != 'Windows'
uses: 1arp/create-a-file-action@0.4.4
with:
path: ${{env.staging_dir}}
file: ucm
content: |
#!/bin/bash
$(dirname "$0")/unison/unison --runtime-path $(dirname "$0")/runtime/bin/unison-runtime "$@"
- name: create startup script (Windows)
if: runner.os == 'Windows'
uses: 1arp/create-a-file-action@0.4.4
with:
path: ${{env.staging_dir}}
file: ucm.cmd
content: |
@echo off
"%~dp0unison\unison.exe" --runtime-path "%~dp0runtime\unison-runtime.exe" %*
- name: package everything together
run: |
if [[ ${{runner.os}} = 'Windows' ]]; then
artifact_archive=ucm-${{env.artifact_os}}.zip
7z a -r -tzip ${artifact_archive} ${{env.staging_dir}}/*
else
chmod +x ${{env.staging_dir}}/ucm
artifact_archive=ucm-${{env.artifact_os}}.tar.gz
tar -c -z -f ${artifact_archive} -C ${{env.staging_dir}} .
fi
echo "artifact_archive=${artifact_archive}" >> $GITHUB_ENV
- name: upload artifact
uses: actions/upload-artifact@v4
with:
name: bundle-${{env.artifact_os}}
path: ${{env.artifact_archive}}
if-no-files-found: error

View File

@ -1,20 +1,25 @@
name: pre-release
run-name: pre-release ${{github.ref_name}}
defaults:
run:
shell: bash
on:
# run on each merge to `trunk`
workflow_run:
workflows: ["CI"]
branches: [ trunk ]
branches: [trunk]
types:
- completed
# run manually
workflow_dispatch:
jobs:
build-ucm:
uses: ./.github/workflows/build-optimized-ucm.yaml
bundle-ucm:
name: build and bundle ucm
uses: ./.github/workflows/bundle-ucm.yaml
with:
ref: ${{ github.ref }}
@ -22,7 +27,7 @@ jobs:
name: create release
runs-on: ubuntu-20.04
needs:
- build-ucm
- bundle-ucm
steps:
- name: make download dir
@ -33,12 +38,15 @@ jobs:
with:
path: /tmp/ucm
- name: derive release tag
run: echo "ref_name=$(echo ${{ github.ref_name }} | awk -F'/' '{print $NF}')" >> $GITHUB_ENV
- uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "trunk-build"
automatic_release_tag: ${{ env.ref_name }}-build
prerelease: true
title: "Development Build"
title: Development Build (${{ env.ref_name }})
files: |
/tmp/ucm/**/*.tar.gz
/tmp/ucm/**/*.zip
/tmp/ucm/**/ucm-*.tar.gz
/tmp/ucm/**/ucm-*.zip

View File

@ -1,6 +1,6 @@
name: "release"
name: release
run-name: "release ${{inputs.version}}"
run-name: release ${{inputs.version}}
defaults:
run:
@ -13,30 +13,26 @@ on:
description: Release version; e.g. `0.5.19`. We'll create tag `release/${version}`.
required: true
type: string
target:
description: Git ref to use for this release; defaults to `trunk`.
required: true
default: trunk
type: string
jobs:
build-ucm:
uses: ./.github/workflows/build-optimized-ucm.yaml
bundle-ucm:
name: build and bundle ucm
uses: ./.github/workflows/bundle-ucm.yaml
with:
ref: release/${{inputs.version}}
ref: ${{github.ref}}
release:
name: create release
runs-on: ubuntu-20.04
needs:
- build-ucm
- bundle-ucm
steps:
- name: make download dir
run: mkdir /tmp/ucm
- name: "download artifacts"
uses: actions/download-artifact@v2
uses: actions/download-artifact@v4
with:
path: /tmp/ucm
@ -44,8 +40,6 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
version="${{inputs.version}}"
target="${{inputs.target}}"
prev_tag="$( \
gh release view \
--repo unisonweb/unison \
@ -54,13 +48,12 @@ jobs:
if [ -z "$prev_tag" ]; then echo "No previous release found"; exit 1; fi
echo "Creating a release from these artifacts:"
ls -R /tmp/ucm
ls -R /tmp/ucm/**/ucm-*.{zip,tar.gz}
gh release create "release/${version}" \
gh release create "release/${{inputs.version}}" \
--repo unisonweb/unison \
--target "${target}" \
--target "${{github.ref}}" \
--generate-notes \
--notes-start-tag "${prev_tag}" \
\
/tmp/ucm/**/*.{zip,tar.gz}
/tmp/ucm/**/ucm-*.{zip,tar.gz}

View File

@ -29,13 +29,13 @@ jobs:
git config --global user.name "GitHub Actions"
git config --global user.email "actions@github.com"
- name: build
run: stack --no-terminal build --fast --no-run-tests --test
run: stack build --fast --no-run-tests --test
- name: round-trip-tests
run: |
stack --no-terminal exec unison transcript unison-src/transcripts-round-trip/main.md
stack --no-terminal exec unison transcript unison-src/transcripts-manual/rewrites.md
stack exec unison transcript unison-src/transcripts-round-trip/main.md
stack exec unison transcript unison-src/transcripts-manual/rewrites.md
- name: transcripts
run: stack --no-terminal exec transcripts
run: stack exec transcripts
- name: save transcript changes
uses: stefanzweifel/git-auto-commit-action@v5
with:

View File

@ -1,9 +1,15 @@
## Some things I wish I'd known about Github Actions
You can't have an `env:` key defined in terms of another `env` key, but
You can't have an `env:` key defined in terms of another `env` key, but you can use `$GITHUB_ENV` to get around this.
You can't define a `matrix` at the top level, it has to be defined within a `job`'s `strategy`.
`runs-on:` doesn't allow `env` for some reason.
Strings don't need quotes, unless you need to force something to be a string.
A `@ref` is always needed on a remote action.
Windows doesn't seem to honor the `default: run: shell:` setting, so you need to set the `shell:` on `run:` manually?
Don't hesitate to do a lot with `run:` blocks aka bash scripts — at least bash is mature and well documented.
@ -20,6 +26,20 @@ e.g.
It's not clear to me when to use `$GITHUB_OUTPUT` vs `$GITHUB_ENV`, but I have been favoring `$GITHUB_ENV` because it requires fewer characters to access.
However, it seems a little wrong.
### `if:`
Although the type rules don't totally make sense in Github Actions, `if:` takes a Boolean.
Therefore, I think the String interpolation in `if: ${{runner.os}} != 'Windows'` causes the whole expression to become a String, which is coerced to `true`, when you definitely didn't mean `if: true`. So don't use `${{}}` here.
### Job names
Job names will automatically get `(${{matrix.os}})` if you don't use `${{matrix.os}}` somewhere in the name.
### Windows
The whole thing with `.exe` is a mess. Unix commands typically drop and add `.exe` correctly as needed, but Github Actions (e.g. `actions/upload-artifact`?) don't.
### Cache
When using the `cache` action, getting a cache hit on the primary key means you won't update the cache with any changes.
@ -29,6 +49,15 @@ Similarly, `save-always: true` only if a key hit means there will be nothing new
Backup restore keys: "Is there a prior run that would be worth starting out from? With the caveat that any irrelevant garbage it includes will be saved into this run too."
### Upload Artifact
I suspect on Windows it can't support paths that select a drive in a Unix-y way,
like `/c/asdf` or `/d/asdf`. It's got to be `C:/asdf` or `C:\asdf` etc.
Upload will complain if any
Upload and Download plugin versions have to match.
### Reusability
Github supports splitting off "reusable workflows" (`jobs` that can be imported into another workflow), and "composite actions" (multi-step `steps` that can be imported into another `job`).
@ -37,6 +66,10 @@ Github supports splitting off "reusable workflows" (`jobs` that can be imported
Needs to have `shell:` specified on every `run:`
#### Reusable workflows
These have to be in `.github/workflows`, you can't organize them deeper, or elsewhere.
### Reference
Default Environment Variables:

View File

@ -111,11 +111,11 @@ cradle:
- path: "unison-cli/tests"
component: "unison-cli:test:cli-tests"
- path: "unison-cli-main/integration-tests/Suite.hs"
component: "unison-cli-main:exe:cli-integration-tests"
- path: "unison-cli-integration/integration-tests/Suite.hs"
component: "unison-cli-integration:exe:cli-integration-tests"
- path: "unison-cli-main/integration-tests/IntegrationTests/ArgumentParsing.hs"
component: "unison-cli-main:exe:cli-integration-tests"
- path: "unison-cli-integration/integration-tests/IntegrationTests/ArgumentParsing.hs"
component: "unison-cli-integration:exe:cli-integration-tests"
- path: "unison-cli-main/unison/Main.hs"
component: "unison-cli-main:exe:unison"

View File

@ -509,6 +509,7 @@ builtinsSrc =
B "Text.patterns.notCharIn" $ list char --> pat text,
-- Pattern.many : Pattern a -> Pattern a
B "Pattern.many" $ forall1 "a" (\a -> pat a --> pat a),
B "Pattern.many.corrected" $ forall1 "a" (\a -> pat a --> pat a),
B "Pattern.replicate" $ forall1 "a" (\a -> nat --> nat --> pat a --> pat a),
B "Pattern.capture" $ forall1 "a" (\a -> pat a --> pat a),
B "Pattern.captureAs" $ forall1 "a" (\a -> a --> pat a --> pat a),

View File

@ -3217,7 +3217,9 @@ declareForeigns = do
_ -> die "Text.patterns.notCharIn: non-character closure"
evaluate . TPat.cpattern . TPat.Char . TPat.Not $ TPat.CharSet cs
declareForeign Untracked "Pattern.many" boxDirect . mkForeign $
\(TPat.CP p _) -> evaluate . TPat.cpattern $ TPat.Many p
\(TPat.CP p _) -> evaluate . TPat.cpattern $ TPat.Many False p
declareForeign Untracked "Pattern.many.corrected" boxDirect . mkForeign $
\(TPat.CP p _) -> evaluate . TPat.cpattern $ TPat.Many True p
declareForeign Untracked "Pattern.capture" boxDirect . mkForeign $
\(TPat.CP p _) -> evaluate . TPat.cpattern $ TPat.Capture p
declareForeign Untracked "Pattern.captureAs" boxBoxDirect . mkForeign $

View File

@ -363,6 +363,7 @@ performRehash rgrp0 ctx =
irs = remap $ intermedRemap ctx
f b r
| not b,
r `Map.notMember` rgrp0,
r <- Map.findWithDefault r r frs,
Just r <- Map.lookup r irs =
r
@ -757,7 +758,9 @@ prepareEvaluation ppe tm ctx = do
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
int b r
| b || Map.member r rgrp0 = r
| otherwise = toIntermed ctx r
(ctx', rrefs, rgrp) =
performRehash
((fmap . overGroupLinks) int rgrp0)

View File

@ -12,7 +12,7 @@ data Pattern
| Or Pattern Pattern -- left-biased choice: tries second pattern only if first fails
| Capture Pattern -- capture all the text consumed by the inner pattern, discarding its subcaptures
| CaptureAs Text Pattern -- capture the given text, discarding its subcaptures, and name the capture
| Many Pattern -- zero or more repetitions (at least 1 can be written: Join [p, Many p])
| Many Bool Pattern -- zero or more repetitions (at least 1 can be written: Join [p, Many p]); boolean determines whether it's the correct version (True) or the original (False).
| Replicate Int Int Pattern -- m to n occurrences of a pattern, optional = 0-1
| Eof -- succeed if given the empty text, fail otherwise
| Literal Text -- succeed if input starts with the given text, advance by that text
@ -128,7 +128,7 @@ compile (CaptureAs t p) !err !success = go
success' _ rem acc0 _ = success (pushCapture t acc0) rem
compiled = compile p err' success'
go acc t = compiled acc t acc t
compile (Capture (Many (Char Any))) !_ !success = \acc t -> success (pushCapture t acc) Text.empty
compile (Capture (Many _ (Char Any))) !_ !success = \acc t -> success (pushCapture t acc) Text.empty
compile (Capture c) !err !success = go
where
err' _ _ acc0 t0 = err acc0 t0
@ -152,12 +152,13 @@ compile (Char cp) !err !success = go
go acc t = case Text.uncons t of
Just (ch, rem) | ok ch -> success acc rem
_ -> err acc t
compile (Many p) !_ !success = case p of
compile (Many correct p) !_ !success = case p of
Char Any -> (\acc _ -> success acc Text.empty)
Char cp -> walker (charPatternPred cp)
p -> go
where
go = try "Many" (compile p) success success'
go | correct = try "Many" (compile p) success success'
| otherwise = compile p success success'
success' acc rem
| Text.size rem == 0 = success acc rem
| otherwise = go acc rem

View File

@ -114,12 +114,12 @@ test =
expect' (P.run (P.Char (P.CharSet "0123")) "3ab" == Just ([], "ab"))
expect' (P.run (P.Char (P.Not (P.CharSet "0123"))) "a3b" == Just ([], "3b"))
expect' (P.run (P.Capture (P.Char (P.Not (P.CharSet "0123")))) "a3b" == Just (["a"], "3b"))
expect' (P.run (P.Many (P.Char (P.CharSet "abcd"))) "babbababac123" == Just ([], "123"))
expect' (P.run (P.Capture (P.Many (P.Char (P.CharSet "abcd")))) "babbababac123" == Just (["babbababac"], "123"))
expect' (P.run (P.Capture (P.Many (P.Char (P.CharClass P.Number)))) "012345abc" == Just (["012345"], "abc"))
expect' (P.run (P.Join [P.Capture (P.Many (P.Char (P.CharClass P.Number))), P.Literal ",", P.Capture (P.Many (P.Char P.Any))]) "012345,abc" == Just (["012345", "abc"], ""))
expect' (P.run (P.Many True (P.Char (P.CharSet "abcd"))) "babbababac123" == Just ([], "123"))
expect' (P.run (P.Capture (P.Many True (P.Char (P.CharSet "abcd")))) "babbababac123" == Just (["babbababac"], "123"))
expect' (P.run (P.Capture (P.Many True (P.Char (P.CharClass P.Number)))) "012345abc" == Just (["012345"], "abc"))
expect' (P.run (P.Join [P.Capture (P.Many True (P.Char (P.CharClass P.Number))), P.Literal ",", P.Capture (P.Many True (P.Char P.Any))]) "012345,abc" == Just (["012345", "abc"], ""))
expect'
( P.run (P.Many (P.Join [P.Capture (P.Many (P.Char (P.CharClass P.Number))), P.Many (P.Char (P.CharClass P.Whitespace))])) "01 10 20 1123 292 110 10"
( P.run (P.Many True (P.Join [P.Capture (P.Many True (P.Char (P.CharClass P.Number))), P.Many True (P.Char (P.CharClass P.Whitespace))])) "01 10 20 1123 292 110 10"
== Just (["01", "10", "20", "1123", "292", "110", "10"], "")
)
expect' $

View File

@ -545,11 +545,6 @@
[(unison-termlink-con tyl i)
(ref-referent-con (typelink->reference tyl) i)]))
(define (list->unison-tuple l)
(foldr ref-tuple-pair ref-unit-unit l))
(define (unison-tuple . l) (list->unison-tuple l))
(define (unison-seq . l)
(vector->chunked-list (list->vector l)))

View File

@ -106,7 +106,6 @@
(or (exn:fail:contract:divide-by-zero? e)
(exn:fail:contract:non-fixnum-result? e)))
;; TODO Replace strings with proper type links once we have them
(define (try-eval thunk)
(with-handlers
([exn:break?

View File

@ -30,6 +30,9 @@
chunked-string-foldMap-chunks
unison-tuple
list->unison-tuple
freeze-bytevector!
freeze-vector!
freeze-subvector
@ -69,6 +72,7 @@
build-path
path->string
match
match*
for/fold)
(string-copy! racket-string-copy!)
(bytes-append bytevector-append)
@ -184,12 +188,43 @@
[sfx (if (<= l 10) "" "...")])
(string-append "32x" (substring s 0 10) sfx)))
(define (describe-tuple x)
(define (format-tuple l)
(for/fold
([sep ")"]
[bits '()]
#:result (apply string-append (cons "(" bits)))
([e l])
(values ", " (list* (describe-value e) sep bits))))
(define (format-non-tuple l)
(for/fold
([result #f])
([e l])
(let ([de (describe-value e)])
(if (not result) de
(string-append "Cons (" de ") (" result ")")))))
(let rec ([acc '()] [tup x])
(match tup
[(unison-data r t (list x y))
#:when (eq? r ref-tuple:typelink)
(rec (cons x acc) y)]
[(unison-data r t (list))
#:when (eq? r ref-unit:typelink)
(format-tuple acc)]
[else
(format-non-tuple (cons tup acc))])))
(define (describe-value x)
(match x
[(unison-sum t fs)
(let ([tt (number->string t)]
[vs (describe-list-br fs)])
(string-append "Sum " tt " " vs))]
[(unison-data r t fs)
#:when (eq? r ref-tuple:typelink)
(describe-tuple x)]
[(unison-data r t fs)
(let ([tt (number->string t)]
[rt (describe-ref r)]
@ -258,62 +293,158 @@
[else sc]))]))
; universal-compares two lists of values lexicographically
(define (lexico-compare ls rs)
(define (lexico-compare ls rs cmp-ty)
(let rec ([cls ls] [crs rs])
(cond
[(and (null? cls) (null? crs)) '=]
[else
(comparisons
(universal-compare (car cls) (car crs))
(universal-compare (car cls) (car crs) cmp-ty)
(rec (cdr cls) (cdr crs)))])))
(define (cmp-num l r)
(define ((comparison e? l?) l r)
(cond
[(= l r) '=]
[(< l r) '<]
[(e? l r) '=]
[(l? l r) '<]
[else '>]))
(define (compare-char a b)
(cond
[(char=? a b) '=]
[(char<? a b) '<]
[else '>]))
(define compare-num (comparison = <))
(define compare-char (comparison char=? char<?))
(define compare-byte (comparison = <))
(define compare-bytes (comparison bytes=? bytes<?))
(define compare-string (comparison string=? string<?))
(define (compare-byte a b)
(cond
[(= a b) '=]
[(< a b) '<]
[else '>]))
(define (compare-typelink ll rl)
(match ll
[(unison-typelink-builtin lnm)
(match rl
[(unison-typelink-builtin rnm) (compare-string lnm rnm)]
[(? unison-typelink-derived?) '<])]
[(unison-typelink-derived lh i)
(match rl
[(unison-typelink-derived rh j)
(comparisons
(compare-bytes lh rh)
(compare-num i j))]
[(? unison-typelink-builtin?) '>])]))
(define (universal-compare l r)
(define (compare-termlink ll rl)
(match ll
[(unison-termlink-builtin lnm)
(match rl
[(unison-termlink-builtin rnm)
(compare-string lnm rnm)]
[else '<])]
[(unison-termlink-derived lh i)
(match rl
[(unison-termlink-derived rh j)
(comparisons
(compare-bytes lh rh)
(compare-num i j))]
[(? unison-termlink-builtin?) '>]
[else '<])]
[(unison-termlink-con lr t)
(match rl
[(unison-termlink-con rr u)
(comparisons
(compare-typelink lr rr)
(compare-num t u))]
[else '>])]))
(define (value->category v)
(cond
[(equal? l r) '=]
[(and (number? l) (number? r)) (if (< l r) '< '>)]
[(and (char? l) (char? r)) (if (char<? l r) '< '>)]
[(procedure? v) 0]
[(unison-closure? v) 0]
[(number? v) 1]
[(char? v) 1]
[(boolean? v) 1]
[(unison-data? v) 1]
[(chunked-list? v) 3]
[(chunked-string? v) 3]
[(chunked-bytes? v) 3]
[(unison-termlink? v) 3]
[(unison-typelink? v) 3]
[(bytes? v) 5]))
(define (compare-data l r cmp-ty)
(match* (l r)
[((unison-data lr lt lfs) (unison-data rr rt rfs))
(compare-data-stuff lr lt lfs rr rt rfs cmp-ty)]))
(define (compare-data-stuff lr lt lfs rr rt rfs cmp-ty)
(define new-cmp-ty (or cmp-ty (eq? lr builtin-any:typelink)))
(comparisons
(if cmp-ty (compare-typelink lr rr) '=)
(compare-num lt rt)
(compare-num (length lfs) (length rfs))
(lexico-compare lfs rfs new-cmp-ty)))
; gives links to compare values as pseudo- or actual data types.
; This is how the interpreter works, so this is an attempt to obtain
; the same ordering.
(define (pseudo-data-link v)
(cond
[(boolean? v) builtin-boolean:typelink]
[(char? v) builtin-char:typelink]
[(flonum? v) builtin-float:typelink]
[(and (number? v) (negative? v)) builtin-int:typelink]
[(number? v) builtin-nat:typelink]
[(unison-data? v) (unison-data-ref v)]))
(define (compare-proc l r cmp-ty)
(define (unpack v)
(if (procedure? v)
(values (lookup-function-link v) '())
(values
(lookup-function-link (unison-closure-code v))
(unison-closure-env v))))
(define-values (lnl envl) (unpack l))
(define-values (lnr envr) (unpack r))
(comparisons
(compare-termlink lnl lnr)
(lexico-compare envl envr cmp-ty)))
(define (universal-compare l r [cmp-ty #f])
(define (u-proc? v)
(or (procedure? v) (unison-closure? v)))
(cond
[(eq? l r) '=] ; optimistic equality case
[(and (boolean? l) (boolean? r)) (if r '< '>)]
[(and (chunked-list? l) (chunked-list? r)) (chunked-list-compare/recur l r universal-compare)]
[(and (char? l) (char? r)) (if (char<? l r) '< '>)]
[(and (number? l) (number? r)) (compare-num l r)]
[(and (chunked-list? l) (chunked-list? r))
(chunked-list-compare/recur l r universal-compare)]
[(and (chunked-string? l) (chunked-string? r))
(chunked-string-compare/recur l r compare-char)]
[(and (chunked-bytes? l) (chunked-bytes? r))
(chunked-bytes-compare/recur l r compare-byte)]
[(and (bytes? l) (bytes? r))
(cond
[(bytes=? l r) '=]
[(bytes<? l r) '<]
[else '>])]
[(and (unison-data? l) (unison-data? r))
(let ([fls (unison-data-fields l)] [frs (unison-data-fields r)])
(comparisons
(cmp-num (unison-data-tag l) (unison-data-tag r))
(cmp-num (length fls) (length frs))
(lexico-compare fls frs)))]
[(and (unison-data? l) (unison-data? r)) (compare-data l r cmp-ty)]
[(and (bytes? r) (bytes? r)) (compare-bytes l r)]
[(and (u-proc? l) (u-proc? r)) (compare-proc l r)]
[(and (unison-termlink? l) (unison-termlink? r))
(compare-termlink l r)]
[(and (unison-typelink? l) (unison-typelink? r))
(compare-typelink l r)]
[(= 3 (value->category l) (value->category r))
(compare-typelink (pseudo-data-link l) (pseudo-data-link r))]
[(= (value->category l) (value->category r))
(raise
(make-exn:bug
"unsupported universal comparison of values"
(unison-tuple l r)))]
[else
(let ([dl (describe-value l)]
[dr (describe-value r)])
(raise
(format
"universal-compare: unimplemented\n~a\n\n~a"
dl dr)))]))
(compare-num (value->category l) (value->category r))]))
(define (list->unison-tuple l)
(foldr ref-tuple-pair ref-unit-unit l))
(define (unison-tuple . l) (list->unison-tuple l))
(define (chunked-string<? l r) (chunked-string=?/recur l r char<?))
@ -380,11 +511,29 @@
(vector-set! dst i (vector-ref src (+ off i)))
(next (fx1- i)))))))
; TODO needs better pretty printing for when it isn't caught
(struct exn:bug (msg a)
#:constructor-name make-exn:bug)
(define (write-exn:bug ex port mode)
(when mode
(write-string "<exn:bug " port))
(let ([recur (case mode
[(#t) write]
[(#f) display]
[else (lambda (v port) (print v port mode))])])
(recur (chunked-string->string (exn:bug-msg ex)) port)
(if mode (write-string " " port) (newline port))
(write-string (describe-value (exn:bug-val ex)) port))
(when mode
(write-string ">")))
(struct exn:bug (msg val)
#:constructor-name make-exn:bug
#:methods gen:custom-write
[(define write-proc write-exn:bug)])
(define (exn:bug->exception b)
(exception
ref-runtimefailure:typelink
(exn:bug-msg b)
(exn:bug-a b)))
(exn:bug-val b)))

View File

@ -248,6 +248,8 @@
builtin-Char.Class.is:termlink
builtin-Pattern.captureAs
builtin-Pattern.captureAs:termlink
builtin-Pattern.many.corrected
builtin-Pattern.many.corrected:termlink
builtin-Pattern.isMatch
builtin-Pattern.isMatch:termlink
builtin-IO.fileExists.impl.v3
@ -740,6 +742,7 @@
(define-builtin-link Universal.compare)
(define-builtin-link Universal.murmurHash)
(define-builtin-link Pattern.captureAs)
(define-builtin-link Pattern.many.corrected)
(define-builtin-link Pattern.isMatch)
(define-builtin-link Char.Class.is)
(define-builtin-link Scope.bytearrayOf)
@ -862,6 +865,8 @@
(define-unison (builtin-Pattern.captureAs c p)
(capture-as c p))
(define-unison (builtin-Pattern.many.corrected p) (many p))
(define-unison (builtin-Pattern.isMatch p s)
(pattern-match? p s))
@ -909,7 +914,7 @@
(define (unison-POp-EQLT s t) (bool (equal? s t)))
(define (unison-POp-LEQT s t) (bool (chunked-string<? s t)))
(define (unison-POp-EQLU x y) (bool (universal=? x y)))
(define (unison-POp-EROR fnm x) ;; TODO raise the correct failure, use display
(define (unison-POp-EROR fnm x)
(let-values ([(p g) (open-string-output-port)])
(put-string p (chunked-string->string fnm))
(put-string p ": ")
@ -1457,5 +1462,6 @@
(declare-builtin-link builtin-Pattern.isMatch)
(declare-builtin-link builtin-Scope.bytearrayOf)
(declare-builtin-link builtin-Char.Class.is)
(declare-builtin-link builtin-Pattern.many.corrected)
(declare-builtin-link builtin-unsafe.coerceAbilities)
)

View File

@ -113,8 +113,6 @@
(define (ClientConfig.certificates.set certs config) ; list tlsSignedCert tlsClientConfig -> tlsClientConfig
(client-config (client-config-host config) certs))
; TODO: have someone familiar with TLS verify these exception
; classifications
(define (handle-errors fn)
(with-handlers
[[exn:fail:network?

View File

@ -13,10 +13,10 @@ usage() {
prev_version="${prev_tag#release/}"
prefix="${prev_version%.*}"
next_version="${prefix}.$(( ${prev_version##*.} + 1 ))"
echo "usage: $0 <version> [target]"
echo "usage: $0 <version> [ref]"
echo ""
echo "version: The new version number"
echo "target: The Git revision to make the release from, defaults to 'origin/trunk'"
echo "ref: The Git revision to make the release from, defaults to 'origin/trunk'"
echo ""
echo "Try: $0 $next_version"
}
@ -53,8 +53,8 @@ git fetch origin trunk
git tag "${tag}" "${target}"
git push origin "${tag}"
gh workflow run release --repo unisonweb/unison \
--field "version=${version}" \
--field "target=${target}"
--ref "${tag}" \
--field "version=${version}"
echo "Kicking off Homebrew update task"
gh workflow run release --repo unisonweb/homebrew-unison --field "version=${version}"

View File

@ -2507,7 +2507,7 @@ runScheme =
InputPattern
"run.native"
[]
I.Visible
I.Hidden
[("definition to run", Required, exactDefinitionTermQueryArg), ("arguments", ZeroPlus, noCompletionsArg)]
( P.wrapColumn2
[ ( makeExample runScheme ["main", "args"],
@ -2524,7 +2524,7 @@ compileScheme =
InputPattern
"compile.native"
[]
I.Visible
I.Hidden
[("definition to compile", Required, exactDefinitionTermQueryArg), ("output file", Required, filePathArg)]
( P.wrapColumn2
[ ( makeExample compileScheme ["main", "file"],

View File

@ -277,7 +277,7 @@ data TermEntry v a = TermEntry
deriving (Eq, Ord, Show, Generic)
termEntryLabeledDependencies :: Ord v => TermEntry v a -> Set LD.LabeledDependency
termEntryLabeledDependencies TermEntry {termEntryType, termEntryReferent, termEntryTag} =
termEntryLabeledDependencies TermEntry {termEntryType, termEntryReferent, termEntryTag, termEntryName} =
foldMap Type.labeledDependencies termEntryType
<> Set.singleton (LD.TermReferent (Cv.referent2to1UsingCT ct termEntryReferent))
where
@ -285,7 +285,8 @@ termEntryLabeledDependencies TermEntry {termEntryType, termEntryReferent, termEn
ct = case termEntryTag of
ServerTypes.Constructor ServerTypes.Ability -> V2Referent.EffectConstructor
ServerTypes.Constructor ServerTypes.Data -> V2Referent.DataConstructor
_ -> error "termEntryLabeledDependencies: not a constructor, but one was required"
ServerTypes.Doc -> V2Referent.DataConstructor
_ -> error $ "termEntryLabeledDependencies: Term is not a constructor, but the referent was a constructor. Tag: " <> show termEntryTag <> " Name: " <> show termEntryName <> " Referent: " <> show termEntryReferent
termEntryDisplayName :: TermEntry v a -> Text
termEntryDisplayName = HQ'.toTextWith Name.toText . termEntryHQName

View File

@ -21,6 +21,11 @@ to `Tests.check` and `Tests.checkEqual`).
.> add
```
```ucm:hide
.> load unison-src/builtin-tests/link-tests.u
.> add
```
```ucm:hide
.> load unison-src/builtin-tests/math-tests.u
.> add

View File

@ -21,6 +21,11 @@ to `Tests.check` and `Tests.checkEqual`).
.> add
```
```ucm:hide
.> load unison-src/builtin-tests/link-tests.u
.> add
```
```ucm:hide
.> load unison-src/builtin-tests/math-tests.u
.> add
@ -98,3 +103,17 @@ to `Tests.check` and `Tests.checkEqual`).
```ucm
.> run.native tests.jit.only
```
```unison
foo = do
go : Nat ->{Exception} ()
go = cases
0 -> ()
n -> go (decrement n)
go 1000
```
```ucm
.> run.native foo
.> run.native foo
```

View File

@ -17,3 +17,35 @@ to `Tests.check` and `Tests.checkEqual`).
()
```
```unison
foo = do
go : Nat ->{Exception} ()
go = cases
0 -> ()
n -> go (decrement n)
go 1000
```
```ucm
Loading changes detected in scratch.u.
I found and typechecked these definitions in scratch.u. If you
do an `add` or `update`, here's how your codebase would
change:
⍟ These new definitions are ok to `add`:
foo : '{Exception} ()
```
```ucm
.> run.native foo
()
.> run.native foo
()
```

View File

@ -0,0 +1,58 @@
linkstuff.termlinks =
[ termLink data.Map.adjust
, termLink data.Map.alter
, termLink data.Map.contains
, termLink data.Map.delete
, termLink data.Map.difference
, termLink data.List.any
, termLink data.List.apply
, termLink data.List.compare
, termLink data.List.contains
, termLink data.List.count
, termLink data.List.diagonal
, termLink data.List.distinct
, termLink data.NatSet.alter
, termLink data.NatSet.any
, termLink data.NatSet.empty
, termLink data.NatSet.filter
, termLink data.Tuple.at1
, termLink data.Tuple.at2
, termLink data.Tuple.at3
, termLink data.Tuple.bimap
, termLink data.Tuple.mapLeft
, termLink data.graph.SCC.map
]
linkstuff.typelinks =
[ typeLink data.Map
, typeLink Nat
, typeLink Char
, typeLink data.List
, typeLink data.NatSet
, typeLink data.Tuple
]
linkstuff.tmlpairs =
flatMap (l -> map (r -> (l,r)) termlinks) termlinks
linkstuff.tylpairs =
flatMap (l -> map (r -> (l,r)) typelinks) typelinks
linkstuff.tests : '{Tests,IO} ()
linkstuff.tests = do
use Universal gteq
if all (cases (l,r) -> (l === r) || (l !== r)) tmlpairs
then pass "term link equality"
else fail "term link equality" ""
if all (cases (l,r) -> (l === r) || (l !== r)) tylpairs
then pass "type link equality"
else fail "type link equality" ""
if all (cases (l,r) -> gteq l r || gteq r l) tmlpairs
then pass "term link comparison"
else fail "term link comparison" ""
if all (cases (l,r) -> gteq l r || gteq r l) tylpairs
then pass "type link comparison"
else fail "type link comparison" ""

View File

@ -18,6 +18,7 @@ tests = Tests.main do
!array.tests
!codelookup.tests
!sandbox.tests
!linkstuff.tests
murmur.hash.tests = do
targets =

File diff suppressed because it is too large Load Diff

View File

@ -54,7 +54,7 @@ The `builtins.merge` command adds the known builtins to a `builtin` subnamespace
43. Optional (type)
44. Optional/ (2 terms)
45. Pattern (builtin type)
46. Pattern/ (8 terms)
46. Pattern/ (9 terms)
47. Ref (builtin type)
48. Ref/ (2 terms)
49. Request (builtin type)

View File

@ -23,7 +23,7 @@ Technically, the definitions all exist, but they have no names. `builtins.merge`
.foo> ls
1. builtin/ (468 terms, 74 types)
1. builtin/ (469 terms, 74 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/ (640 terms, 92 types)
1. builtin/ (641 terms, 92 types)
```
More typically, you'd start out by pulling `base.

View File

@ -119,13 +119,13 @@ it's still in the `history` of the parent namespace and can be resurrected at an
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #pspa3vq2ua
⊙ 1. #bu1i0n9dc8
- Deletes:
feature1.y
⊙ 2. #b5dm426u7b
⊙ 2. #5tcb95h81s
+ Adds / updates:
@ -136,26 +136,26 @@ it's still in the `history` of the parent namespace and can be resurrected at an
Original name New name(s)
feature1.y master.y
⊙ 3. #do0jngnhtf
⊙ 3. #mnckoq3rit
+ Adds / updates:
feature1.y
⊙ 4. #tf4a4vpcr4
⊙ 4. #p4tlcg4hum
> Moves:
Original name New name
x master.x
⊙ 5. #aq3rvje4v5
⊙ 5. #annk1i1aiq
+ Adds / updates:
x
□ 6. #h4s6dfeqgs (start of history)
□ 6. #g1cc8nnehi (start of history)
```
To resurrect an old version of a namespace, you can learn its hash via the `history` command, then use `fork #namespacehash .newname`.

View File

@ -80,7 +80,7 @@ Should be able to move the term, type, and namespace, including its types, terms
1. Bar (Nat)
2. Bar (type)
3. Bar/ (4 terms, 1 type)
4. builtin/ (640 terms, 92 types)
4. builtin/ (641 terms, 92 types)
.> ls Bar
@ -145,7 +145,7 @@ bonk = 5
.z> ls
1. builtin/ (468 terms, 74 types)
1. builtin/ (469 terms, 74 types)
2. zonk (Nat)
```
@ -188,7 +188,7 @@ bonk.zonk = 5
.a> ls
1. builtin/ (468 terms, 74 types)
1. builtin/ (469 terms, 74 types)
2. zonk/ (1 term)
.a> view zonk.zonk

View File

@ -277,7 +277,7 @@ I should be able to move the root into a sub-namespace
.> ls
1. root/ (1409 terms, 223 types)
1. root/ (1412 terms, 223 types)
.> history
@ -286,22 +286,22 @@ I should be able to move the root into a sub-namespace
□ 1. #a82udhdkkm (start of history)
□ 1. #a8po34tuor (start of history)
```
```ucm
.> ls .root.at.path
1. existing/ (469 terms, 74 types)
2. happy/ (471 terms, 75 types)
3. history/ (469 terms, 74 types)
1. existing/ (470 terms, 74 types)
2. happy/ (472 terms, 75 types)
3. history/ (470 terms, 74 types)
.> history .root.at.path
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #j740r84t45
⊙ 1. #pic2513iu5
- Deletes:
@ -312,7 +312,7 @@ I should be able to move the root into a sub-namespace
Original name New name
existing.a.termInA existing.b.termInA
⊙ 2. #t2qb2srrfq
⊙ 2. #dpkar0l7eh
+ Adds / updates:
@ -324,26 +324,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. #m0cm2kfj3j
⊙ 3. #ed8rah4ani
+ Adds / updates:
existing.a.termInA existing.b.termInB
⊙ 4. #m1gruau69b
⊙ 4. #8esastt942
> Moves:
Original name New name
history.a.termInA history.b.termInA
⊙ 5. #3lgjqfeklh
⊙ 5. #u50bign98h
- Deletes:
history.b.termInB
⊙ 6. #224buskj1c
⊙ 6. #eunua4ftsk
+ Adds / updates:
@ -354,13 +354,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. #4opi5ic0s8
⊙ 7. #9v1fp5smbj
+ Adds / updates:
history.a.termInA history.b.termInB
⊙ 8. #cea3fkkpr9
⊙ 8. #j6i6o027uo
> Moves:
@ -370,7 +370,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. #92t382h305
⊙ 9. #g0773g7caj
+ Adds / updates:
@ -380,7 +380,7 @@ I should be able to move the root into a sub-namespace
happy.a.T.T
⊙ 10. #1bipgm96rn
⊙ 10. #3ak6nm4g2v
+ Adds / updates:
@ -392,7 +392,7 @@ I should be able to move the root into a sub-namespace
⊙ 11. #vjq331o3fk
⊙ 11. #4p3p54fdb5
```
@ -414,26 +414,26 @@ I should be able to move a sub namespace _over_ the root.
.> ls
1. b/ (3 terms, 1 type)
2. builtin/ (468 terms, 74 types)
2. builtin/ (469 terms, 74 types)
.> history
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #mq7u2mestj
⊙ 1. #dd6g9ldnd6
+ Adds / updates:
b.T b.T.T1 b.T.T2 b.termInA
⊙ 2. #d6c7njuurg
⊙ 2. #ripe11pmqo
- Deletes:
a.T a.T.T1 a.T.T2 a.termInA
⊙ 3. #peh53098rj
⊙ 3. #1stj775onu
+ Adds / updates:
@ -443,13 +443,13 @@ I should be able to move a sub namespace _over_ the root.
a.T.T
⊙ 4. #f1q7d2411o
⊙ 4. #0sor1jkilb
+ Adds / updates:
a.T a.T.T a.termInA
□ 5. #i38nt50r1v (start of history)
□ 5. #htl7ctb3ei (start of history)
```
```ucm

View File

@ -8,4 +8,5 @@ Some tests of pattern behavior.
p1 = join [literal "blue", literal "frog"]
> Pattern.run (many p1) "bluefrogbluegoat"
> Pattern.run (many.corrected p1) "bluefrogbluegoat"
```

View File

@ -4,6 +4,7 @@ Some tests of pattern behavior.
p1 = join [literal "blue", literal "frog"]
> Pattern.run (many p1) "bluefrogbluegoat"
> Pattern.run (many.corrected p1) "bluefrogbluegoat"
```
```ucm
@ -22,6 +23,10 @@ p1 = join [literal "blue", literal "frog"]
`>`)... Ctrl+C cancels.
3 | > Pattern.run (many p1) "bluefrogbluegoat"
Some ([], "goat")
4 | > Pattern.run (many.corrected p1) "bluefrogbluegoat"
Some ([], "bluegoat")

View File

@ -63,17 +63,17 @@ y = 2
most recent, along with the command that got us there. Try:
`fork 2 .old`
`fork #jpjvuobccr .old` to make an old namespace
`fork #gpvnq2mlbn .old` to make an old namespace
accessible again,
`reset-root #jpjvuobccr` to reset the root namespace and
`reset-root #gpvnq2mlbn` to reset the root namespace and
its history to that of the
specified namespace.
When Root Hash Action
1. now #civ82mf97k add
2. now #jpjvuobccr add
3. now #i38nt50r1v builtins.merge
1. now #919gfih828 add
2. now #gpvnq2mlbn add
3. now #htl7ctb3ei builtins.merge
4. #sg60bvjo91 history starts here
Tip: Use `diff.namespace 1 7` to compare namespaces between

View File

@ -28,13 +28,13 @@ a = 5
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #84ho0ifat5
⊙ 1. #matjo6b9c2
+ Adds / updates:
a
□ 2. #i38nt50r1v (start of history)
□ 2. #htl7ctb3ei (start of history)
.> reset 2
@ -47,7 +47,7 @@ a = 5
□ 1. #i38nt50r1v (start of history)
□ 1. #htl7ctb3ei (start of history)
```
```unison
@ -83,13 +83,13 @@ foo.a = 5
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #v4j1mnirpd
⊙ 1. #okc86j6fft
+ Adds / updates:
foo.a
□ 2. #i38nt50r1v (start of history)
□ 2. #htl7ctb3ei (start of history)
.> reset 1 foo

View File

@ -13,7 +13,7 @@ Let's look at some examples. We'll start with a namespace with just the builtins
□ 1. #5ablb8f4a3 (start of history)
□ 1. #thnqh4ngaa (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. #33ueli4s7t
⊙ 1. #3fc4t9cl7b
> Moves:
Original name New name
Nat.frobnicate Nat.+
⊙ 2. #26f2828s84
⊙ 2. #s9orh4o9om
> Moves:
Original name New name
Nat.+ Nat.frobnicate
□ 3. #5ablb8f4a3 (start of history)
□ 3. #thnqh4ngaa (start of history)
```
If we merge that back into `builtin`, we get that same chain of history:
@ -73,21 +73,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. #33ueli4s7t
⊙ 1. #3fc4t9cl7b
> Moves:
Original name New name
Nat.frobnicate Nat.+
⊙ 2. #26f2828s84
⊙ 2. #s9orh4o9om
> Moves:
Original name New name
Nat.+ Nat.frobnicate
□ 3. #5ablb8f4a3 (start of history)
□ 3. #thnqh4ngaa (start of history)
```
Let's try again, but using a `merge.squash` (or just `squash`) instead. The history will be unchanged:
@ -108,7 +108,7 @@ Let's try again, but using a `merge.squash` (or just `squash`) instead. The hist
□ 1. #5ablb8f4a3 (start of history)
□ 1. #thnqh4ngaa (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.
@ -493,13 +493,13 @@ This checks to see that squashing correctly preserves deletions:
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #mmg0dcd1dg
⊙ 1. #u5k1lfopsu
- Deletes:
Nat.* Nat.+
□ 2. #5ablb8f4a3 (start of history)
□ 2. #thnqh4ngaa (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.

View File

@ -57,7 +57,7 @@ proj/main> upgrade old new
proj/main> ls lib
1. builtin/ (468 terms, 74 types)
1. builtin/ (469 terms, 74 types)
2. new/ (1 term)
proj/main> view thingy